summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio/CMakeLists.txt4
-rw-r--r--src/audio/audio_decoder.cpp8
-rw-r--r--src/audio/audio_task.cpp36
-rw-r--r--src/audio/chunk.cpp44
-rw-r--r--src/audio/fatfs_audio_input.cpp40
-rw-r--r--src/audio/include/audio_decoder.hpp7
-rw-r--r--src/audio/include/audio_element.hpp15
-rw-r--r--src/audio/include/fatfs_audio_input.hpp7
-rw-r--r--src/audio/include/stream_info.hpp15
-rw-r--r--src/audio/include/stream_message.hpp49
-rw-r--r--src/audio/stream_info.cpp92
-rw-r--r--src/audio/stream_message.cpp26
-rw-r--r--src/cbor_wrapper/CMakeLists.txt6
-rw-r--r--src/cbor_wrapper/cbor_decoder.cpp112
-rw-r--r--src/cbor_wrapper/cbor_encoder.cpp63
-rw-r--r--src/cbor_wrapper/include/cbor_decoder.hpp113
-rw-r--r--src/cbor_wrapper/include/cbor_encoder.hpp52
17 files changed, 218 insertions, 471 deletions
diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt
index 32ca1a56..d5564f13 100644
--- a/src/audio/CMakeLists.txt
+++ b/src/audio/CMakeLists.txt
@@ -1,7 +1,7 @@
idf_component_register(
SRCS "audio_decoder.cpp" "audio_task.cpp" "chunk.cpp" "fatfs_audio_input.cpp"
- "stream_info.cpp"
+ "stream_info.cpp" "stream_message.cpp"
INCLUDE_DIRS "include"
- REQUIRES "codecs" "drivers" "cbor_wrapper" "result" "tasks")
+ REQUIRES "codecs" "drivers" "cbor" "result" "tasks")
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})
diff --git a/src/audio/audio_decoder.cpp b/src/audio/audio_decoder.cpp
index a19fd5bf..48637f08 100644
--- a/src/audio/audio_decoder.cpp
+++ b/src/audio/audio_decoder.cpp
@@ -39,8 +39,8 @@ auto AudioDecoder::SetOutputBuffer(MessageBufferHandle_t* buffer) -> void {
output_buffer_ = buffer;
}
-auto AudioDecoder::ProcessStreamInfo(StreamInfo&& info)
- -> cpp::result<void, StreamError> {
+auto AudioDecoder::ProcessStreamInfo(StreamInfo& info)
+ -> cpp::result<void, AudioProcessingError> {
stream_info_ = info;
// Reuse the existing codec if we can. This will help with gapless playback,
@@ -62,7 +62,7 @@ auto AudioDecoder::ProcessStreamInfo(StreamInfo&& info)
}
auto AudioDecoder::ProcessChunk(uint8_t* data, std::size_t length)
- -> cpp::result<size_t, StreamError> {
+ -> cpp::result<size_t, AudioProcessingError> {
if (current_codec_ == nullptr) {
// Should never happen, but fail explicitly anyway.
return cpp::fail(UNSUPPORTED_STREAM);
@@ -111,7 +111,7 @@ auto AudioDecoder::ProcessChunk(uint8_t* data, std::size_t length)
return current_codec_->GetInputPosition();
}
-auto AudioDecoder::ProcessIdle() -> cpp::result<void, StreamError> {
+auto AudioDecoder::ProcessIdle() -> cpp::result<void, AudioProcessingError> {
// Not used; we delay forever when waiting on IO.
return {};
}
diff --git a/src/audio/audio_task.cpp b/src/audio/audio_task.cpp
index f3362897..9ffcab74 100644
--- a/src/audio/audio_task.cpp
+++ b/src/audio/audio_task.cpp
@@ -4,9 +4,7 @@
#include <cstdint>
-#include "cbor_decoder.hpp"
-#include "chunk.hpp"
-#include "esp-idf/components/cbor/tinycbor/src/cbor.h"
+#include "cbor.h"
#include "esp_heap_caps.h"
#include "freertos/portmacro.h"
#include "freertos/queue.h"
@@ -14,6 +12,7 @@
#include "audio_element.hpp"
#include "chunk.hpp"
+#include "stream_info.hpp"
#include "stream_message.hpp"
#include "tasks.hpp"
@@ -39,7 +38,7 @@ void AudioTaskMain(void* args) {
ChunkReader chunk_reader = ChunkReader(element->InputBuffer());
while (1) {
- cpp::result<size_t, StreamError> process_res;
+ cpp::result<size_t, AudioProcessingError> process_res;
// If this element has an input stream, then our top priority is
// processing any chunks from it. Try doing this first, then fall back to
@@ -67,26 +66,15 @@ void AudioTaskMain(void* args) {
if (has_received_message) {
auto [buffer, length] = chunk_reader.GetLastMessage();
- auto decoder_res = cbor::ArrayDecoder::Create(buffer, length);
- if (decoder_res.has_error()) {
- // TODO.
- break;
- }
- auto decoder = std::move(decoder_res.value());
- // TODO: this can be more elegant i think
- cpp::result<uint64_t, CborError> message_type =
- decoder->NextValue<uint64_t>();
- if (message_type.has_error()) {
- break; // TODO.
- } else if (message_type.value() == TYPE_STREAM_INFO) {
- auto info_decoder = cbor::MapDecoder::Create(decoder->Iterator());
- if (info_decoder.has_value()) {
- auto process_error = element->ProcessStreamInfo(
- StreamInfo(info_decoder.value().get()));
- if (process_error.has_error()) {
- break; // TODO.
- }
- } else {
+ MessageType msg = ReadMessageType(buffer, length);
+ if (msg == TYPE_STREAM_INFO) {
+ auto parse_res =
+ ReadMessage<StreamInfo>(&StreamInfo::Parse, buffer, length);
+ if (parse_res.has_error()) {
+ break; // TODO.
+ }
+ auto info_res = element->ProcessStreamInfo(parse_res.value());
+ if (info_res.has_error()) {
break; // TODO.
}
}
diff --git a/src/audio/chunk.cpp b/src/audio/chunk.cpp
index 718b2649..94618ab1 100644
--- a/src/audio/chunk.cpp
+++ b/src/audio/chunk.cpp
@@ -1,14 +1,12 @@
#include "chunk.hpp"
-#include <string.h>
-
#include <cstddef>
#include <cstdint>
+#include <cstring>
+#include <optional>
#include "cbor.h"
-#include "cbor_decoder.hpp"
-#include "cbor_encoder.hpp"
#include "stream_message.hpp"
namespace audio {
@@ -25,7 +23,7 @@ static const std::size_t kWorkingBufferSize = kMaxChunkSize * 1.5;
* space for future headers more compactly.
*/
// TODO: measure how big headers tend to be to pick a better value.
-static const size_t kInitialHeaderSize = 32;
+static const std::size_t kInitialHeaderSize = 32;
auto WriteChunksToStream(MessageBufferHandle_t* stream,
uint8_t* working_buffer,
@@ -44,14 +42,20 @@ auto WriteChunksToStream(MessageBufferHandle_t* stream,
}
// Put together a header.
- cbor::Encoder encoder(cbor::CONTAINER_ARRAY, 3, working_buffer,
- working_buffer_length);
- encoder.WriteValue(TYPE_CHUNK_HEADER);
- encoder.WriteValue(header_size);
- encoder.WriteValue(chunk_size);
+ cpp::result<size_t, CborError> encoder_res;
+ CborEncoder arr;
+ WriteMessage(
+ TYPE_CHUNK_HEADER,
+ [&](CborEncoder& container) {
+ cbor_encoder_create_array(&container, &arr, 2);
+ cbor_encode_uint(&arr, header_size);
+ cbor_encode_uint(&arr, chunk_size);
+ cbor_encoder_close_container(&container, &arr);
+ return std::nullopt;
+ },
+ working_buffer, working_buffer_length);
size_t new_header_size = header_size;
- cpp::result<size_t, CborError> encoder_res = encoder.Finish();
if (encoder_res.has_error()) {
return CHUNK_ENCODING_ERROR;
} else {
@@ -108,15 +112,9 @@ auto ChunkReader::ReadChunkFromStream(
return CHUNK_READ_TIMEOUT;
}
- auto decoder = cbor::ArrayDecoder::Create(working_buffer_ + leftover_bytes_,
- last_message_size_);
- if (decoder.has_error()) {
- // Weird; this implies someone is shoving invalid data into the buffer.
- return CHUNK_DECODING_ERROR;
- }
+ MessageType type =
+ ReadMessageType(working_buffer_ + leftover_bytes_, last_message_size_);
- MessageType type = static_cast<MessageType>(
- decoder.value()->NextValue<uint64_t>().value_or(TYPE_UNKNOWN));
if (type != TYPE_CHUNK_HEADER) {
// This message wasn't for us, so let the caller handle it.
Reset();
@@ -124,11 +122,9 @@ auto ChunkReader::ReadChunkFromStream(
}
// Work the size and position of the chunk.
- size_t header_length = decoder.value()->NextValue<uint64_t>().value_or(0);
- size_t chunk_length = decoder.value()->NextValue<uint64_t>().value_or(0);
- if (decoder.value()->Failed()) {
- return CHUNK_DECODING_ERROR;
- }
+ size_t header_length = 0, chunk_length = 0;
+
+ // TODO: chunker header type to encapsulate this?
// Now we need to stick the end of the last chunk (if it exists) onto the
// front of the new chunk. Do it this way around bc we assume the old chunk
diff --git a/src/audio/fatfs_audio_input.cpp b/src/audio/fatfs_audio_input.cpp
index dee090d0..d4cbf6db 100644
--- a/src/audio/fatfs_audio_input.cpp
+++ b/src/audio/fatfs_audio_input.cpp
@@ -10,6 +10,9 @@
#include "audio_element.hpp"
#include "chunk.hpp"
+#include "stream_message.hpp"
+
+static const char* kTag = "SRC";
namespace audio {
@@ -43,14 +46,17 @@ FatfsAudioInput::~FatfsAudioInput() {
free(output_buffer_);
}
-auto FatfsAudioInput::ProcessStreamInfo(StreamInfo&& info)
- -> cpp::result<void, StreamError> {
+auto FatfsAudioInput::ProcessStreamInfo(StreamInfo& info)
+ -> cpp::result<void, AudioProcessingError> {
if (is_file_open_) {
f_close(&current_file_);
is_file_open_ = false;
}
- std::string path = info.Path().value_or("");
+ if (!info.Path()) {
+ return cpp::fail(UNSUPPORTED_STREAM);
+ }
+ std::string path = info.Path().value();
FRESULT res = f_open(&current_file_, path.c_str(), FA_READ);
if (res != FR_OK) {
return cpp::fail(IO_ERROR);
@@ -58,15 +64,24 @@ auto FatfsAudioInput::ProcessStreamInfo(StreamInfo&& info)
is_file_open_ = true;
- // TODO: pass on stream info.
+ auto write_res =
+ WriteMessage(TYPE_STREAM_INFO,
+ std::bind(&StreamInfo::Encode, info, std::placeholders::_1),
+ chunk_buffer_, kMaxChunkSize);
+
+ if (write_res.has_error()) {
+ return cpp::fail(IO_ERROR);
+ } else {
+ xMessageBufferSend(output_buffer_, chunk_buffer_, write_res.value(),
+ portMAX_DELAY);
+ }
return {};
}
auto FatfsAudioInput::ProcessChunk(uint8_t* data, std::size_t length)
- -> cpp::result<size_t, StreamError> {
- // TODO.
- return 0;
+ -> cpp::result<size_t, AudioProcessingError> {
+ return cpp::fail(UNSUPPORTED_STREAM);
}
auto FatfsAudioInput::GetRingBufferDistance() -> size_t {
@@ -83,7 +98,7 @@ auto FatfsAudioInput::GetRingBufferDistance() -> size_t {
+ (file_buffer_write_pos_ - file_buffer_);
}
-auto FatfsAudioInput::ProcessIdle() -> cpp::result<void, StreamError> {
+auto FatfsAudioInput::ProcessIdle() -> cpp::result<void, AudioProcessingError> {
// First, see if we're able to fill up the input buffer with any more of the
// file's contents.
if (is_file_open_) {
@@ -102,7 +117,8 @@ auto FatfsAudioInput::ProcessIdle() -> cpp::result<void, StreamError> {
FRESULT result = f_read(&current_file_, file_buffer_write_pos_, read_size,
&bytes_read);
if (result != FR_OK) {
- return cpp::fail(IO_ERROR); // TODO;
+ ESP_LOGE(kTag, "file I/O error %d", result);
+ return cpp::fail(IO_ERROR);
}
if (f_eof(&current_file_)) {
@@ -128,9 +144,11 @@ auto FatfsAudioInput::ProcessIdle() -> cpp::result<void, StreamError> {
switch (result) {
case CHUNK_WRITE_TIMEOUT:
case CHUNK_OUT_OF_DATA:
- return {}; // TODO.
+ // Both of these are fine; SendChunk keeps track of where it's up to
+ // internally, so we will pick back up where we left off.
+ return {};
default:
- return {}; // TODO.
+ return cpp::fail(IO_ERROR);
}
}
diff --git a/src/audio/include/audio_decoder.hpp b/src/audio/include/audio_decoder.hpp
index a4508c3e..4d2fd5f3 100644
--- a/src/audio/include/audio_decoder.hpp
+++ b/src/audio/include/audio_decoder.hpp
@@ -21,10 +21,11 @@ class AudioDecoder : public IAudioElement {
auto SetInputBuffer(MessageBufferHandle_t*) -> void;
auto SetOutputBuffer(MessageBufferHandle_t*) -> void;
- auto ProcessStreamInfo(StreamInfo&& info) -> cpp::result<void, StreamError>;
+ auto ProcessStreamInfo(StreamInfo& info)
+ -> cpp::result<void, AudioProcessingError>;
auto ProcessChunk(uint8_t* data, std::size_t length)
- -> cpp::result<size_t, StreamError>;
- auto ProcessIdle() -> cpp::result<void, StreamError>;
+ -> cpp::result<size_t, AudioProcessingError>;
+ auto ProcessIdle() -> cpp::result<void, AudioProcessingError>;
AudioDecoder(const AudioDecoder&) = delete;
AudioDecoder& operator=(const AudioDecoder&) = delete;
diff --git a/src/audio/include/audio_element.hpp b/src/audio/include/audio_element.hpp
index 13a48590..5b697784 100644
--- a/src/audio/include/audio_element.hpp
+++ b/src/audio/include/audio_element.hpp
@@ -15,8 +15,11 @@
namespace audio {
-/* Errors that may be returned by any of the Process* methods. */
-enum StreamError {
+/*
+ * Errors that may be returned by any of the Process* methods of an audio
+ * element.
+ */
+enum AudioProcessingError {
// Indicates that this element is unable to handle the upcoming chunks.
UNSUPPORTED_STREAM,
// Indicates an error with reading or writing stream data.
@@ -65,8 +68,8 @@ class IAudioElement {
* Called when a StreamInfo message is received. Used to configure this
* element in preperation for incoming chunks.
*/
- virtual auto ProcessStreamInfo(StreamInfo&& info)
- -> cpp::result<void, StreamError> = 0;
+ virtual auto ProcessStreamInfo(StreamInfo& info)
+ -> cpp::result<void, AudioProcessingError> = 0;
/*
* Called when a ChunkHeader message is received. Includes the data associated
@@ -75,14 +78,14 @@ class IAudioElement {
* prepended to the next call.
*/
virtual auto ProcessChunk(uint8_t* data, std::size_t length)
- -> cpp::result<size_t, StreamError> = 0;
+ -> cpp::result<size_t, AudioProcessingError> = 0;
/*
* Called when there has been no data received over the input buffer for some
* time. This could be used to synthesize output, or to save memory by
* releasing unused resources.
*/
- virtual auto ProcessIdle() -> cpp::result<void, StreamError> = 0;
+ virtual auto ProcessIdle() -> cpp::result<void, AudioProcessingError> = 0;
protected:
MessageBufferHandle_t* input_buffer_;
diff --git a/src/audio/include/fatfs_audio_input.hpp b/src/audio/include/fatfs_audio_input.hpp
index 6fe178ab..c54b32bd 100644
--- a/src/audio/include/fatfs_audio_input.hpp
+++ b/src/audio/include/fatfs_audio_input.hpp
@@ -19,10 +19,11 @@ class FatfsAudioInput : public IAudioElement {
FatfsAudioInput(std::shared_ptr<drivers::SdStorage> storage);
~FatfsAudioInput();
- auto ProcessStreamInfo(StreamInfo&& info) -> cpp::result<void, StreamError>;
+ auto ProcessStreamInfo(StreamInfo& info)
+ -> cpp::result<void, AudioProcessingError>;
auto ProcessChunk(uint8_t* data, std::size_t length)
- -> cpp::result<size_t, StreamError>;
- auto ProcessIdle() -> cpp::result<void, StreamError>;
+ -> cpp::result<size_t, AudioProcessingError>;
+ auto ProcessIdle() -> cpp::result<void, AudioProcessingError>;
auto SendChunk(uint8_t* buffer, size_t size) -> size_t;
diff --git a/src/audio/include/stream_info.hpp b/src/audio/include/stream_info.hpp
index ca28dd4e..47bcaa45 100644
--- a/src/audio/include/stream_info.hpp
+++ b/src/audio/include/stream_info.hpp
@@ -7,22 +7,11 @@
#include "cbor.h"
#include "result.hpp"
-#include "cbor_decoder.hpp"
-#include "cbor_encoder.hpp"
-
namespace audio {
class StreamInfo {
public:
- enum ParseError {
- WRONG_TYPE,
- MISSING_MAP,
- CBOR_ERROR,
- };
-
- static auto Create(const uint8_t* buffer, size_t length)
- -> cpp::result<StreamInfo, ParseError>;
- StreamInfo(cbor::MapDecoder*);
+ static auto Parse(CborValue& container) -> cpp::result<StreamInfo, CborError>;
StreamInfo() = default;
StreamInfo(const StreamInfo&) = default;
@@ -38,7 +27,7 @@ class StreamInfo {
return sample_rate_;
}
- auto WriteToMap(cbor::Encoder& encoder) -> cpp::result<size_t, CborError>;
+ auto Encode(CborEncoder& enc) -> std::optional<CborError>;
private:
std::optional<std::string> path_;
diff --git a/src/audio/include/stream_message.hpp b/src/audio/include/stream_message.hpp
index 2791dcd8..cbd7c733 100644
--- a/src/audio/include/stream_message.hpp
+++ b/src/audio/include/stream_message.hpp
@@ -1,11 +1,60 @@
#pragma once
+#include <stdint.h>
+
+#include <functional>
+#include <optional>
+
+#include "cbor.h"
+#include "result.hpp"
+
namespace audio {
+extern const int kEncoderFlags;
+extern const int kDecoderFlags;
+
enum MessageType {
TYPE_UNKNOWN,
TYPE_CHUNK_HEADER,
TYPE_STREAM_INFO,
};
+template <typename Writer>
+auto WriteMessage(MessageType type,
+ Writer&& writer,
+ uint8_t* buffer,
+ size_t length) -> cpp::result<size_t, CborError> {
+ CborEncoder root;
+ CborEncoder container;
+
+ cbor_encoder_init(&root, buffer, length, kEncoderFlags);
+ cbor_encoder_create_array(&root, &container, 2);
+ cbor_encode_uint(&container, type);
+
+ std::optional<CborError> inner_err = std::invoke(writer, container);
+ if (inner_err) {
+ return cpp::fail(inner_err.value());
+ }
+
+ cbor_encoder_close_container(&root, &container);
+ return cbor_encoder_get_buffer_size(&root, buffer);
+}
+
+template <typename Result, typename Reader>
+auto ReadMessage(Reader&& reader, uint8_t* buffer, size_t length)
+ -> cpp::result<Result, CborError> {
+ CborParser parser;
+ CborValue root;
+ CborValue container;
+
+ cbor_parser_init(buffer, length, kDecoderFlags, &parser, &root);
+ cbor_value_enter_container(&root, &container);
+ // Skip the type header
+ cbor_value_advance_fixed(&container);
+
+ return std::invoke(reader, container);
+}
+
+auto ReadMessageType(uint8_t* buffer, size_t length) -> MessageType;
+
} // namespace audio
diff --git a/src/audio/stream_info.cpp b/src/audio/stream_info.cpp
index a5f7bebf..8f217b79 100644
--- a/src/audio/stream_info.cpp
+++ b/src/audio/stream_info.cpp
@@ -5,8 +5,6 @@
#include "cbor.h"
-#include "cbor_decoder.hpp"
-#include "cbor_encoder.hpp"
#include "stream_message.hpp"
namespace audio {
@@ -16,48 +14,72 @@ static const std::string kKeyChannels = "c";
static const std::string kKeyBitsPerSample = "b";
static const std::string kKeySampleRate = "r";
-auto StreamInfo::Create(const uint8_t* buffer, size_t length)
- -> cpp::result<StreamInfo, ParseError> {
- CborParser parser;
- CborValue value;
+auto StreamInfo::Parse(CborValue& container)
+ -> cpp::result<StreamInfo, CborError> {
+ CborValue map;
+ cbor_value_enter_container(&container, &map);
- cbor_parser_init(buffer, length, 0, &parser, &value);
+ CborValue entry;
+ StreamInfo ret;
- int type = 0;
- if (!cbor_value_is_integer(&value) || !cbor_value_get_int(&value, &type) ||
- type != TYPE_STREAM_INFO) {
- return cpp::fail(WRONG_TYPE);
+ cbor_value_map_find_value(&map, kKeyPath.c_str(), &entry);
+ if (cbor_value_get_type(&entry) != CborInvalidType) {
+ char* val;
+ size_t len;
+ cbor_value_dup_text_string(&entry, &val, &len, NULL);
+ ret.path_ = std::string(val, len);
+ free(val);
+ }
+ cbor_value_map_find_value(&map, kKeyChannels.c_str(), &entry);
+ if (cbor_value_get_type(&entry) != CborInvalidType) {
+ uint64_t val;
+ cbor_value_get_uint64(&entry, &val);
+ ret.channels_ = val;
+ }
+ cbor_value_map_find_value(&map, kKeyBitsPerSample.c_str(), &entry);
+ if (cbor_value_get_type(&entry) != CborInvalidType) {
+ uint64_t val;
+ cbor_value_get_uint64(&entry, &val);
+ ret.bits_per_sample_ = val;
+ }
+ cbor_value_map_find_value(&map, kKeySampleRate.c_str(), &entry);
+ if (cbor_value_get_type(&entry) != CborInvalidType) {
+ uint64_t val;
+ cbor_value_get_uint64(&entry, &val);
+ ret.sample_rate_ = val;
}
- cbor_value_advance_fixed(&value);
+ return ret;
+}
- if (!cbor_value_is_map(&value)) {
- return cpp::fail(MISSING_MAP);
- }
+auto StreamInfo::Encode(CborEncoder& enc) -> std::optional<CborError> {
+ CborEncoder map;
+ size_t num_items = 0 + channels_.has_value() + bits_per_sample_.has_value() +
+ sample_rate_.has_value() + path_.has_value();
+ cbor_encoder_create_map(&enc, &map, num_items);
- auto map_decoder = cbor::MapDecoder::Create(value);
- if (map_decoder.has_value()) {
- return StreamInfo(map_decoder.value().get());
+ if (channels_) {
+ cbor_encode_text_string(&map, kKeyChannels.c_str(), kKeyChannels.size());
+ cbor_encode_uint(&map, channels_.value());
+ }
+ if (bits_per_sample_) {
+ cbor_encode_text_string(&map, kKeyBitsPerSample.c_str(),
+ kKeyBitsPerSample.size());
+ cbor_encode_uint(&map, bits_per_sample_.value());
+ }
+ if (sample_rate_) {
+ cbor_encode_text_string(&map, kKeySampleRate.c_str(),
+ kKeySampleRate.size());
+ cbor_encode_uint(&map, sample_rate_.value());
+ }
+ if (path_) {
+ cbor_encode_text_string(&map, kKeyPath.c_str(), kKeyPath.size());
+ cbor_encode_text_string(&map, path_.value().c_str(), path_.value().size());
}
- return cpp::fail(CBOR_ERROR);
-}
-StreamInfo::StreamInfo(cbor::MapDecoder* decoder) {
- // TODO: this method is n^2, which seems less than ideal. But you don't do it
- // that frequently, so maybe it's okay? Needs investigation.
- channels_ = decoder->FindValue<uint64_t>(kKeyChannels);
- bits_per_sample_ = decoder->FindValue<uint64_t>(kKeyBitsPerSample);
- sample_rate_ = decoder->FindValue<uint64_t>(kKeySampleRate);
- path_ = decoder->FindValue<std::string>(kKeyPath);
-}
+ cbor_encoder_close_container(&enc, &map);
-auto StreamInfo::WriteToMap(cbor::Encoder& map_encoder)
- -> cpp::result<size_t, CborError> {
- map_encoder.WriteKeyValue<uint64_t>(kKeyChannels, channels_);
- map_encoder.WriteKeyValue<uint64_t>(kKeyBitsPerSample, bits_per_sample_);
- map_encoder.WriteKeyValue<uint64_t>(kKeySampleRate, sample_rate_);
- map_encoder.WriteKeyValue<std::string>(kKeyPath, path_);
- return map_encoder.Finish();
+ return std::nullopt;
}
} // namespace audio
diff --git a/src/audio/stream_message.cpp b/src/audio/stream_message.cpp
new file mode 100644
index 00000000..58868ce8
--- /dev/null
+++ b/src/audio/stream_message.cpp
@@ -0,0 +1,26 @@
+#include "stream_message.hpp"
+
+#include <cstdint>
+
+#include "cbor.h"
+
+namespace audio {
+
+const int kEncoderFlags = 0;
+const int kDecoderFlags = 0;
+
+auto ReadMessageType(uint8_t* buffer, size_t length) -> MessageType {
+ CborParser parser;
+ CborValue root;
+ CborValue container;
+
+ cbor_parser_init(buffer, length, kDecoderFlags, &parser, &root);
+ cbor_value_enter_container(&root, &container);
+
+ uint64_t header = 0;
+ cbor_value_get_uint64(&container, &header);
+
+ return static_cast<MessageType>(header);
+}
+
+} // namespace audio
diff --git a/src/cbor_wrapper/CMakeLists.txt b/src/cbor_wrapper/CMakeLists.txt
deleted file mode 100644
index cd5186e0..00000000
--- a/src/cbor_wrapper/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-idf_component_register(
- SRCS "cbor_decoder.cpp" "cbor_encoder.cpp"
- INCLUDE_DIRS "include"
- REQUIRES "cbor" "result")
-
-target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})
diff --git a/src/cbor_wrapper/cbor_decoder.cpp b/src/cbor_wrapper/cbor_decoder.cpp
deleted file mode 100644
index a99cca02..00000000
--- a/src/cbor_wrapper/cbor_decoder.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-#include "cbor_decoder.hpp"
-
-#include <cstdint>
-#include <string>
-
-#include "cbor.h"
-#include "result.hpp"
-
-static const int kDecoderFlags = 0;
-
-namespace cbor {
-
-auto parse_stdstring(const CborValue* val, std::string* out) -> CborError {
- char* buf;
- size_t len;
- CborError err = cbor_value_dup_text_string(val, &buf, &len, NULL);
- if (err != CborNoError) {
- return err;
- }
- *out = std::string(buf, len);
- free(buf);
- return err;
-}
-
-auto ArrayDecoder::Create(uint8_t* buffer, size_t buffer_len)
- -> cpp::result<std::unique_ptr<ArrayDecoder>, CborError> {
- auto decoder = std::make_unique<ArrayDecoder>();
- cbor_parser_init(buffer, buffer_len, kDecoderFlags, &decoder->parser_,
- &decoder->root_);
- if (!cbor_value_is_array(&decoder->root_)) {
- return cpp::fail(CborErrorIllegalType);
- }
- CborError err = cbor_value_enter_container(&decoder->root_, &decoder->it_);
- if (err != CborNoError) {
- return cpp::fail(err);
- }
- return std::move(decoder);
-}
-
-auto ArrayDecoder::Create(CborValue& root)
- -> cpp::result<std::unique_ptr<ArrayDecoder>, CborError> {
- auto decoder = std::make_unique<ArrayDecoder>();
- decoder->root_ = root;
- if (!cbor_value_is_array(&decoder->root_)) {
- return cpp::fail(CborErrorIllegalType);
- }
-
- CborError err = cbor_value_enter_container(&decoder->root_, &decoder->it_);
- if (err != CborNoError) {
- return cpp::fail(err);
- }
- return std::move(decoder);
-}
-
-template <>
-auto ArrayDecoder::NextValue() -> cpp::result<int64_t, CborError> {
- return NextValue(&cbor_value_is_integer, &cbor_value_get_int);
-}
-template <>
-auto ArrayDecoder::NextValue() -> cpp::result<uint64_t, CborError> {
- return NextValue(&cbor_value_is_unsigned_integer, &cbor_value_get_uint64);
-}
-template <>
-auto ArrayDecoder::NextValue() -> cpp::result<std::string, CborError> {
- return NextValue(&cbor_value_is_byte_string, &parse_stdstring);
-}
-
-auto MapDecoder::Create(uint8_t* buffer, size_t buffer_len)
- -> cpp::result<std::unique_ptr<MapDecoder>, CborError> {
- auto decoder = std::make_unique<MapDecoder>();
- cbor_parser_init(buffer, buffer_len, kDecoderFlags, &decoder->parser_,
- &decoder->root_);
- if (!cbor_value_is_map(&decoder->root_)) {
- return cpp::fail(CborErrorIllegalType);
- }
- CborError err = cbor_value_enter_container(&decoder->root_, &decoder->it_);
- if (err != CborNoError) {
- return cpp::fail(err);
- }
- return std::move(decoder);
-}
-
-auto MapDecoder::Create(CborValue& root)
- -> cpp::result<std::unique_ptr<MapDecoder>, CborError> {
- auto decoder = std::make_unique<MapDecoder>();
- decoder->root_ = root;
- if (!cbor_value_is_map(&decoder->root_)) {
- return cpp::fail(CborErrorIllegalType);
- }
- CborError err = cbor_value_enter_container(&decoder->root_, &decoder->it_);
- if (err != CborNoError) {
- return cpp::fail(err);
- }
- return std::move(decoder);
-}
-
-template <>
-auto MapDecoder::FindValue(const std::string& key) -> std::optional<int64_t> {
- return FindValue(key, &cbor_value_is_integer, &cbor_value_get_int);
-}
-template <>
-auto MapDecoder::FindValue(const std::string& key) -> std::optional<uint64_t> {
- return FindValue(key, &cbor_value_is_unsigned_integer,
- &cbor_value_get_uint64);
-}
-template <>
-auto MapDecoder::FindValue(const std::string& key)
- -> std::optional<std::string> {
- return FindValue(key, &cbor_value_is_byte_string, &parse_stdstring);
-}
-
-} // namespace cbor
diff --git a/src/cbor_wrapper/cbor_encoder.cpp b/src/cbor_wrapper/cbor_encoder.cpp
deleted file mode 100644
index e4e8ee84..00000000
--- a/src/cbor_wrapper/cbor_encoder.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#include "cbor_encoder.hpp"
-
-#include <cstdint>
-#include <string>
-
-#include "cbor.h"
-#include "cbor_decoder.hpp"
-#include "result.hpp"
-
-namespace cbor {
-
-static const int kEncoderFlags = 0;
-
-Encoder::Encoder(ContainerType type,
- uint32_t container_len,
- uint8_t* buffer,
- size_t buffer_len) {
- cbor_encoder_init(&root_encoder_, buffer, buffer_len, kEncoderFlags);
- switch (type) {
- case CONTAINER_ARRAY:
- error_ = cbor_encoder_create_array(&root_encoder_, &container_encoder_,
- container_len);
- break;
- case CONTAINER_MAP:
- error_ = cbor_encoder_create_map(&root_encoder_, &container_encoder_,
- container_len);
- break;
- }
-}
-
-auto Encoder::WriteValue(const std::string& val) -> void {
- if (error_ != CborNoError) {
- return;
- }
- error_ =
- cbor_encode_text_string(&container_encoder_, val.c_str(), val.size());
-}
-
-auto Encoder::WriteValue(uint32_t val) -> void {
- if (error_ != CborNoError) {
- return;
- }
- error_ = cbor_encode_uint(&container_encoder_, val);
-}
-
-auto Encoder::WriteValue(int32_t val) -> void {
- if (error_ != CborNoError) {
- return;
- }
- error_ = cbor_encode_int(&container_encoder_, val);
-}
-
-auto Encoder::Finish() -> cpp::result<size_t, CborError> {
- if (error_ == CborNoError) {
- error_ = cbor_encoder_close_container(&root_encoder_, &container_encoder_);
- }
- if (error_ != CborNoError) {
- return cpp::fail(error_);
- }
- return cbor_encoder_get_buffer_size(&root_encoder_, buffer_);
-}
-
-} // namespace cbor
diff --git a/src/cbor_wrapper/include/cbor_decoder.hpp b/src/cbor_wrapper/include/cbor_decoder.hpp
deleted file mode 100644
index 193e7843..00000000
--- a/src/cbor_wrapper/include/cbor_decoder.hpp
+++ /dev/null
@@ -1,113 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-
-#include <cstdint>
-#include <string>
-
-#include "cbor.h"
-#include "result.hpp"
-
-namespace cbor {
-
-class ArrayDecoder {
- public:
- static auto Create(uint8_t* buffer, size_t buffer_len)
- -> cpp::result<std::unique_ptr<ArrayDecoder>, CborError>;
-
- static auto Create(CborValue& root)
- -> cpp::result<std::unique_ptr<ArrayDecoder>, CborError>;
-
- ArrayDecoder() {}
-
- template <typename T>
- auto NextValue() -> cpp::result<T, CborError>;
-
- template <typename T>
- auto NextValue(bool (*is_valid)(const CborValue*),
- CborError (*parse)(const CborValue*, T*))
- -> cpp::result<T, CborError> {
- if (error_ != CborNoError) {
- return cpp::fail(error_);
- }
- if (!is_valid(&it_)) {
- error_ = CborErrorIllegalType;
- return cpp::fail(error_);
- }
- T ret;
- error_ = parse(&it_, &ret);
- if (error_ != CborNoError) {
- return cpp::fail(error_);
- }
- error_ = cbor_value_advance(&it_);
- if (error_ != CborNoError) {
- return cpp::fail(error_);
- }
- return ret;
- }
-
- auto Failed() -> CborError { return error_; }
-
- auto Iterator() -> CborValue& { return it_; }
-
- ArrayDecoder(const ArrayDecoder&) = delete;
- ArrayDecoder& operator=(const ArrayDecoder&) = delete;
-
- private:
- CborParser parser_;
- CborValue root_;
-
- CborValue it_;
- CborError error_ = CborNoError;
-};
-
-class MapDecoder {
- public:
- static auto Create(uint8_t* buffer, size_t buffer_len)
- -> cpp::result<std::unique_ptr<MapDecoder>, CborError>;
-
- static auto Create(CborValue& root)
- -> cpp::result<std::unique_ptr<MapDecoder>, CborError>;
-
- MapDecoder() {}
-
- template <typename T>
- auto FindValue(const std::string& key) -> std::optional<T>;
-
- template <typename T>
- auto FindValue(const std::string& key,
- bool (*is_valid)(const CborValue*),
- CborError (*parse)(const CborValue*, T*)) -> std::optional<T> {
- if (error_ != CborNoError) {
- return {};
- }
- CborValue val;
- if (cbor_value_map_find_value(&it_, key.c_str(), &val) != CborNoError) {
- return {};
- }
- if (!is_valid(&val)) {
- error_ = CborErrorIllegalType;
- return {};
- }
- T ret;
- error_ = parse(&val, &ret);
- if (error_ != CborNoError) {
- return {};
- }
- return ret;
- }
-
- auto Failed() -> CborError { return error_; }
-
- MapDecoder(const MapDecoder&) = delete;
- MapDecoder& operator=(const MapDecoder&) = delete;
-
- private:
- CborParser parser_;
- CborValue root_;
-
- CborValue it_;
- CborError error_ = CborNoError;
-};
-
-} // namespace cbor
diff --git a/src/cbor_wrapper/include/cbor_encoder.hpp b/src/cbor_wrapper/include/cbor_encoder.hpp
deleted file mode 100644
index cc57e8a4..00000000
--- a/src/cbor_wrapper/include/cbor_encoder.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include <cstdint>
-#include <optional>
-#include <string>
-
-#include "cbor.h"
-#include "result.hpp"
-
-namespace cbor {
-
-enum ContainerType { CONTAINER_ARRAY, CONTAINER_MAP };
-
-class Encoder {
- public:
- Encoder(ContainerType type,
- uint32_t container_len,
- uint8_t* buffer,
- size_t buffer_len);
-
- auto WriteValue(const std::string& val) -> void;
- auto WriteValue(uint32_t val) -> void;
- auto WriteValue(int32_t val) -> void;
-
- template <typename T>
- auto WriteKeyValue(const std::string& key, const T&& val) -> void {
- WriteValue(key);
- WriteValue(val);
- }
-
- template <typename T>
- auto WriteKeyValue(const std::string& key, const std::optional<T>& val)
- -> void {
- if (val) {
- WriteKeyValue<T>(key, val.value());
- }
- }
-
- auto Finish() -> cpp::result<size_t, CborError>;
-
- Encoder(const Encoder&) = delete;
- Encoder& operator=(const Encoder&) = delete;
-
- private:
- uint8_t* buffer_;
- CborEncoder root_encoder_;
- CborEncoder container_encoder_;
-
- CborError error_ = CborNoError;
-};
-
-} // namespace cbor