summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorailurux <ailuruxx@gmail.com>2024-07-22 14:37:05 +1000
committerailurux <ailuruxx@gmail.com>2024-07-22 14:37:05 +1000
commit514540d89cb99725aa38455c52340f2cd4115896 (patch)
treec85b2ab77aa0cc0a57654391d8553e0c692211a9 /src
parent69cd2847577f88a2f4148bca91df5670ce714a94 (diff)
downloadtangara-fw-514540d89cb99725aa38455c52340f2cd4115896.tar.gz
Queue now keeps file offsets in memory to speed up search
Diffstat (limited to 'src')
-rw-r--r--src/tangara/audio/playlist.cpp68
-rw-r--r--src/tangara/audio/playlist.hpp9
2 files changed, 69 insertions, 8 deletions
diff --git a/src/tangara/audio/playlist.cpp b/src/tangara/audio/playlist.cpp
index 850b7335..f34be9c9 100644
--- a/src/tangara/audio/playlist.cpp
+++ b/src/tangara/audio/playlist.cpp
@@ -16,7 +16,12 @@ namespace audio {
[[maybe_unused]] static constexpr char kTag[] = "playlist";
Playlist::Playlist(std::string playlistFilepath)
- : filepath_(playlistFilepath), mutex_(), total_size_(0), pos_(0) {}
+ : filepath_(playlistFilepath),
+ mutex_(),
+ total_size_(0),
+ pos_(-1),
+ offset_cache_(&memory::kSpiRamResource),
+ sample_size_(50) {}
auto Playlist::open() -> bool {
FRESULT res =
@@ -47,8 +52,10 @@ auto Playlist::size() const -> size_t {
auto Playlist::append(Item i) -> void {
std::unique_lock<std::mutex> lock(mutex_);
auto offset = f_tell(&file_);
+ bool first_entry = current_value_.empty();
// Seek to end and append
- auto res = f_lseek(&file_, f_size(&file_));
+ auto end = f_size(&file_);
+ auto res = f_lseek(&file_, end);
if (res != FR_OK) {
ESP_LOGE(kTag, "Seek to end of file failed? Error %d", res);
return;
@@ -58,16 +65,19 @@ auto Playlist::append(Item i) -> void {
if (std::holds_alternative<std::string>(i)) {
path = std::get<std::string>(i);
f_printf(&file_, "%s\n", path.c_str());
- total_size_++;
- if (current_value_.empty()) {
+ if (total_size_ % sample_size_ == 0) {
+ offset_cache_.push_back(end);
+ }
+ if (first_entry) {
current_value_ = path;
}
+ total_size_++;
}
// Restore position
res = f_lseek(&file_, offset);
- if (res != FR_OK) {
- ESP_LOGE(kTag, "Failed to restore file position after append?");
- return;
+ if (res != FR_OK) {
+ ESP_LOGE(kTag, "Failed to restore file position after append?");
+ return;
}
res = f_sync(&file_);
if (res != FR_OK) {
@@ -77,8 +87,25 @@ auto Playlist::append(Item i) -> void {
}
auto Playlist::skipTo(size_t position) -> void {
+ std::unique_lock<std::mutex> lock(mutex_);
+ // Check our cache and go to nearest entry
pos_ = position;
- consumeAndCount(position);
+ auto remainder = position % sample_size_;
+ auto quotient = (position - remainder) / sample_size_;
+ if (offset_cache_.size() < quotient) {
+ // Fall back case
+ ESP_LOGW(kTag, "File offset cache failed, falling back...");
+ f_rewind(&file_);
+ advanceBy(pos_);
+ }
+ auto entry = offset_cache_.at(quotient);
+ // Go to byte offset
+ auto res = f_lseek(&file_, entry);
+ if (res != FR_OK) {
+ ESP_LOGW(kTag, "Error going to byte offset %llu for playlist entry index %d", entry, pos_);
+ }
+ // Count ahead entries
+ advanceBy(remainder+1);
}
auto Playlist::next() -> void {
@@ -99,6 +126,7 @@ auto Playlist::value() const -> std::string {
}
auto Playlist::clear() -> bool {
+ std::unique_lock<std::mutex> lock(mutex_);
auto res = f_close(&file_);
if (res != FR_OK) {
return false;
@@ -110,6 +138,7 @@ auto Playlist::clear() -> bool {
}
total_size_ = 0;
current_value_.clear();
+ offset_cache_.clear();
pos_ = 0;
return true;
}
@@ -128,6 +157,7 @@ auto Playlist::consumeAndCount(ssize_t upto) -> bool {
size_t count = 0;
f_rewind(&file_);
while (!f_eof(&file_)) {
+ auto offset = f_tell(&file_);
// TODO: Correctly handle lines longer than this
// TODO: Also correctly handle the case where the last entry doesn't end in
// \n
@@ -136,6 +166,9 @@ auto Playlist::consumeAndCount(ssize_t upto) -> bool {
ESP_LOGW(kTag, "Error consuming playlist file at line %d", count);
return false;
}
+ if (count % sample_size_ == 0) {
+ offset_cache_.push_back(offset);
+ }
count++;
if (upto >= 0 && count > upto) {
@@ -151,4 +184,23 @@ auto Playlist::consumeAndCount(ssize_t upto) -> bool {
return true;
}
+auto Playlist::advanceBy(ssize_t amt) -> bool {
+ TCHAR buff[512];
+ size_t count = 0;
+ while (!f_eof(&file_)) {
+ auto res = f_gets(buff, 512, &file_);
+ if (res == NULL) {
+ ESP_LOGW(kTag, "Error consuming playlist file at line %d", count);
+ return false;
+ }
+ count++;
+ if (count >= amt) {
+ size_t len = strlen(buff);
+ current_value_.assign(buff, len - 1);
+ break;
+ }
+ }
+ return true;
+}
+
} // namespace audio \ No newline at end of file
diff --git a/src/tangara/audio/playlist.hpp b/src/tangara/audio/playlist.hpp
index b278d8a6..3d914663 100644
--- a/src/tangara/audio/playlist.hpp
+++ b/src/tangara/audio/playlist.hpp
@@ -50,7 +50,16 @@ class Playlist {
FIL file_;
std::string current_value_;
+
+ std::pmr::vector<FSIZE_t> offset_cache_; // List of offsets determined by sample size;
+ /*
+ * How many tracks per offset saved (ie, a value of 100 means every 100 tracks the file offset is saved)
+ * This speeds up searches, especially in the case of shuffling a lot of tracks.
+ */
+ const uint32_t sample_size_;
+
auto consumeAndCount(ssize_t upto) -> bool;
+ auto advanceBy(ssize_t amt) -> bool;
};
} // namespace audio \ No newline at end of file