summaryrefslogtreecommitdiff
path: root/src/audio/stream_info.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2022-11-22 17:05:02 +1100
committerjacqueline <me@jacqueline.id.au>2022-11-22 17:05:02 +1100
commit9176ef187227ffb56c249c5f321cd1bf50d4cfcc (patch)
treea846c8fc4e5788e97d6fca43c2807c4bf0ae0214 /src/audio/stream_info.cpp
parent9f8cfaa7a8abd885785830e03d7c417e856b8a22 (diff)
downloadtangara-fw-9176ef187227ffb56c249c5f321cd1bf50d4cfcc.tar.gz
Add cbor wrapper, and chunk streaming util
Diffstat (limited to 'src/audio/stream_info.cpp')
-rw-r--r--src/audio/stream_info.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/audio/stream_info.cpp b/src/audio/stream_info.cpp
new file mode 100644
index 00000000..bb9b1fa2
--- /dev/null
+++ b/src/audio/stream_info.cpp
@@ -0,0 +1,90 @@
+#include "stream_info.hpp"
+#include "stream_message.hpp"
+#include <cstdint>
+#include "esp-idf/components/cbor/tinycbor/src/cbor.h"
+
+namespace audio {
+
+ static const char* kKeyPath = "p";
+ static const char* kKeyChannels = "c";
+ static const char* kKeyBitsPerSample = "b";
+ static const char* kKeySampleRate = "r";
+
+ static auto find_uint64(CborValue &map, char *key) -> cpp::optional<uint64_t> {
+ CborValue val;
+ cbor_value_map_find_value(&map, key, &val);
+ if (cbor_value_is_unsigned_integer(&val)) {
+ uint64_t raw_val;
+ cbor_value_get_uint64(&val, &raw_val);
+ return raw_val;
+ }
+ return {};
+ }
+
+
+ static auto write_uint64(CborEncoder &map, const char *key, const optional<uint64_t> &val) -> cpp::result<void, StreamInfo::EncodeError> {
+ if (val) {
+ cbor_encode_byte_string(&map, key, 1);
+ cbor_encode_uint(&map, *val);
+ }
+ return {};
+ }
+
+static auto StreamInfo::Create(const uint8_t *buffer, size_t length) -> cpp::result<StreamInfo, ParseError> {
+ CborParser parser;
+ CborValue value;
+
+ cbor_parser_init(buffer, len, 0, &parser, &value);
+
+ uint8_t type = 0;
+ if (!cbor_value_is_integer(&value)
+ || !cbor_value_get_integer(&value, &type)
+ || type != STREAM_INFO) {
+ return cpp::fail(WRONG_TYPE);
+ }
+
+ cbor_value_advance_fixed(&value);
+
+ if (!cbor_value_is_map(&value)) {
+ return cpp::fail(MISSING_MAP);
+ }
+
+ return StreamInfo(value);
+}
+
+StreamInfo::StreamInfo(CborValue& map) {
+ // 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_ = find_uint64(map, kKeyChannels);
+ bits_per_sample_ = find_uint64(map, kKeyBitsPerSample);
+ sample_rate_ = find_uint64(map, kKeySampleRate);
+
+ CborValue val;
+ cbor_value_map_find_value(&map, kKeyPath, &val);
+ if (cbor_value_is_text_string(&val)) {
+ size_t len;
+ char *str;
+ cbor_value_dup_text_string(&val, &str, &len, &val);
+ path_ = std::string(str, len);
+ free(str);
+ }
+}
+
+auto StreamInfo::WriteToStream(CborEncoder encoder) -> cpp::result<void, EncodeError> {
+ cbor_encode_int(&encoder, STREAM_INFO);
+
+ CborEncoder map;
+ cbor_encoder_create_map(&encoder, &map, length);
+
+ write_uint64(&map, kKeyChannels, channels_);
+ write_uint64(&map, kKeyBitsPerSample, bits_per_sample_);
+ write_uint64(&map, kKeySampleRate, sample_rate_);
+
+ if (path_) {
+ cbor_encode_text_string(&map, path_->c_str(), path_->size());
+ }
+
+ cbor_encoder_close_container(&encoder, &map);
+}
+
+} // namespace audio