summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-10-03 15:19:55 +1000
committerjacqueline <me@jacqueline.id.au>2024-10-03 15:19:55 +1000
commit6318b272842f5447c90d55123a60fdde2202993d (patch)
treee95c3291e25400e2ab9fd098bac506f3786a3e7a /src
parentea71fa5d2b76a4de6e67a46b0853dc1dc5272d39 (diff)
downloadtangara-fw-6318b272842f5447c90d55123a60fdde2202993d.tar.gz
Use cppbor for encoding playlist toc
Also fix a locking issue with opening+clearing Co-authored-by: ailurux <ailuruxx@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/tangara/audio/playlist.cpp93
-rw-r--r--src/tangara/audio/playlist.hpp7
2 files changed, 40 insertions, 60 deletions
diff --git a/src/tangara/audio/playlist.cpp b/src/tangara/audio/playlist.cpp
index 630b0097..805b0953 100644
--- a/src/tangara/audio/playlist.cpp
+++ b/src/tangara/audio/playlist.cpp
@@ -4,9 +4,12 @@
* SPDX-License-Identifier: GPL-3.0-only
*/
#include "playlist.hpp"
+#include <stdint.h>
#include <string>
+#include "cppbor.h"
+#include "cppbor_parse.h"
#include "esp_log.h"
#include "ff.h"
@@ -121,48 +124,25 @@ auto Playlist::serialiseCache() -> bool {
return false;
}
- uint8_t header[12];
+ cppbor::Array data;
+ // First item = file size of queue file (for checking this file matches)
+ data.add(f_size(&file_));
+ // Next item = number of tracks in this queue
+ data.add(total_size_);
- // First 8 bytes = file size of queue file (for checking this file matches)
- uint64_t q_file_size = f_size(&file_);
- header[0] = q_file_size >> 56;
- header[1] = q_file_size >> 48;
- header[2] = q_file_size >> 40;
- header[3] = q_file_size >> 32;
- header[4] = q_file_size >> 24;
- header[5] = q_file_size >> 16;
- header[6] = q_file_size >> 8;
- header[7] = q_file_size;
+ // Next, write out every cached offset
+ for (uint64_t offset : offset_cache_) {
+ data.add(offset);
+ }
- // Next 4 bytes = number of tracks in this queue
- header[8] = total_size_ >> 24;
- header[9] = total_size_ >> 16;
- header[10] = total_size_ >> 8;
- header[11] = total_size_;
+ auto encoded = data.encode();
UINT bytes_written = 0;
- f_write(&file, header, 12, &bytes_written);
- if (bytes_written < 12) {
+ f_write(&file, encoded.data(), encoded.size(), &bytes_written);
+ if (bytes_written != encoded.size()) {
return false;
}
- // Next, write out every cached offset
- for (uint64_t offset : offset_cache_) {
- uint8_t bytes_out[8];
- bytes_out[0] = offset >> 56;
- bytes_out[1] = offset >> 48;
- bytes_out[2] = offset >> 40;
- bytes_out[3] = offset >> 32;
- bytes_out[4] = offset >> 24;
- bytes_out[5] = offset >> 16;
- bytes_out[6] = offset >> 8;
- bytes_out[7] = offset;
- f_write(&file, bytes_out, 8, &bytes_written);
- if (bytes_written < 8) {
- return false;
- }
- }
-
f_close(&file);
return true;
}
@@ -183,36 +163,31 @@ auto Playlist::deserialiseCache() -> bool {
return false;
}
- uint8_t header[8];
+ std::vector<uint8_t> encoded;
+ encoded.resize(f_size(&file));
+
UINT bytes_read;
- f_read(&file, header, 12, &bytes_read);
- if (bytes_read != 12) {
+ f_read(&file, encoded.data(), encoded.size(), &bytes_read);
+ if (bytes_read != encoded.size()) {
+ return false;
+ }
+
+ auto [data, unused, err] = cppbor::parse(encoded);
+ if (!data || data->type() != cppbor::ARRAY) {
return false;
}
- uint64_t file_size_check =
- header[0] << 56 | header[1] << 48 | header[2] << 40 | header[3] << 32 |
- header[4] << 24 | header[5] << 16 | header[6] << 8 | header[7];
+ auto entries = data->asArray();
- if (file_size_check != f_size(&file_)) {
+ // Double check the expected file size matches.
+ if (entries->get(0)->asUint()->unsignedValue() != f_size(&file_)) {
return false;
}
- uint32_t size =
- header[8] << 24 | header[9] << 16 | header[10] << 8 | header[11];
- total_size_ = size;
+ total_size_ = entries->get(1)->asUint()->unsignedValue();
// Read in the cache
- uint8_t buf[8];
- size_t idx = 0;
- while (true) {
- f_read(&file, buf, 8, &bytes_read);
- if (bytes_read == 0) {
- break;
- }
- uint64_t offset = buf[0] << 56 | buf[1] << 48 | buf[2] << 40 |
- buf[3] << 32 | buf[4] << 24 | buf[5] << 16 | buf[6] << 8 |
- buf[7];
- offset_cache_.push_back(offset);
+ for (size_t i = 2; i < entries->size(); i++) {
+ offset_cache_.push_back(entries->get(i)->asUint()->unsignedValue());
}
f_close(&file);
@@ -350,7 +325,7 @@ auto MutablePlaylist::open() -> bool {
// If there's no cache (or deserialising failed) and the queue is
// sufficiently large, abort and clear the queue
if (queue_filesize > 50000) {
- clear();
+ clearLocked();
} else {
// Otherwise, read in the existing entries
countItems();
@@ -360,12 +335,14 @@ auto MutablePlaylist::open() -> bool {
}
return !file_error_;
- return false;
}
auto MutablePlaylist::clear() -> bool {
std::unique_lock<std::mutex> lock(mutex_);
+ return clearLocked();
+}
+auto MutablePlaylist::clearLocked() -> bool {
// Try to recover from any IO errors.
if (file_error_ && file_open_) {
file_error_ = false;
diff --git a/src/tangara/audio/playlist.hpp b/src/tangara/audio/playlist.hpp
index 7cf99953..b794e444 100644
--- a/src/tangara/audio/playlist.hpp
+++ b/src/tangara/audio/playlist.hpp
@@ -33,7 +33,7 @@ class Playlist {
virtual ~Playlist();
using Item =
std::variant<database::TrackId, database::TrackIterator, std::string>;
- auto open() -> bool;
+ virtual auto open() -> bool;
auto filepath() const -> std::string;
auto currentPosition() const -> size_t;
@@ -82,10 +82,13 @@ class Playlist {
class MutablePlaylist : public Playlist {
public:
MutablePlaylist(const std::string& playlistFilepath);
- auto open() -> bool;
+ auto open() -> bool override;
auto clear() -> bool;
auto append(Item i) -> void;
+
+ private:
+ auto clearLocked() -> bool;
};
} // namespace audio