summaryrefslogtreecommitdiff
path: root/src/audio/fatfs_source.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio/fatfs_source.cpp')
-rw-r--r--src/audio/fatfs_source.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/audio/fatfs_source.cpp b/src/audio/fatfs_source.cpp
new file mode 100644
index 00000000..6a9aea47
--- /dev/null
+++ b/src/audio/fatfs_source.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2023 jacqueline <me@jacqueline.id.au>
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#include "fatfs_source.hpp"
+#include <sys/_stdint.h>
+
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+
+#include "esp_log.h"
+#include "ff.h"
+
+#include "audio_source.hpp"
+#include "codec.hpp"
+#include "types.hpp"
+
+namespace audio {
+
+static constexpr char kTag[] = "fatfs_src";
+
+FatfsSource::FatfsSource(codecs::StreamType t, std::unique_ptr<FIL> file)
+ : IStream(t), file_(std::move(file)) {}
+
+FatfsSource::~FatfsSource() {
+ f_close(file_.get());
+}
+
+auto FatfsSource::Read(cpp::span<std::byte> dest) -> ssize_t {
+ if (f_eof(file_.get())) {
+ ESP_LOGI(kTag, "read from empty file");
+ return 0;
+ }
+ UINT bytes_read = 0;
+ FRESULT res = f_read(file_.get(), dest.data(), dest.size(), &bytes_read);
+ if (res != FR_OK) {
+ ESP_LOGE(kTag, "error reading from file");
+ return -1;
+ }
+ ESP_LOGI(kTag, "read %u bytes into %p (%u)", bytes_read, dest.data(),
+ dest.size_bytes());
+ return bytes_read;
+}
+
+auto FatfsSource::CanSeek() -> bool {
+ return true;
+}
+
+auto FatfsSource::SeekTo(int64_t destination, SeekFrom from) -> void {
+ ESP_LOGI(kTag, "seeking to %llu", destination);
+ switch (from) {
+ case SeekFrom::kStartOfStream:
+ f_lseek(file_.get(), destination);
+ break;
+ case SeekFrom::kEndOfStream:
+ f_lseek(file_.get(), f_size(file_.get()) + destination);
+ break;
+ case SeekFrom::kCurrentPosition:
+ f_lseek(file_.get(), f_tell(file_.get()) + destination);
+ break;
+ }
+}
+
+auto FatfsSource::CurrentPosition() -> int64_t {
+ return f_tell(file_.get());
+}
+} // namespace audio