diff --git a/client/controller.hpp b/client/controller.hpp index 59327730..c43da761 100644 --- a/client/controller.hpp +++ b/client/controller.hpp @@ -44,7 +44,7 @@ class Controller { public: /// c'tor - Controller(boost::asio::io_context& io_context, const ClientSettings& settings); //, std::unique_ptr meta); + Controller(boost::asio::io_context& io_context, const ClientSettings& settings); /// Start thw work void start(); // void stop(); @@ -74,7 +74,6 @@ private: std::shared_ptr stream_; std::unique_ptr decoder_; std::unique_ptr player_; - // std::unique_ptr meta_; std::unique_ptr serverSettings_; std::unique_ptr headerChunk_; }; diff --git a/client/metadata.hpp b/client/metadata.hpp deleted file mode 100644 index cdc18512..00000000 --- a/client/metadata.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/*** - This file is part of snapcast - Copyright (C) 2014-2024 Johannes Pohl - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -***/ - -#pragma once - -// local headers -#include "common/json.hpp" - -// standard headers -#include - - -// Prefix used in output -#define METADATA std::string("metadata") - -/* - * Implement a generic metadata output handler - */ -using json = nlohmann::json; - -/* - * Base class, prints to stdout - */ -class MetadataAdapter -{ -public: - MetadataAdapter() - { - reset(); - } - - virtual ~MetadataAdapter() = default; - - void reset() - { - msg_ = json{}; - } - - std::string serialize() - { - return METADATA + ":" + msg_.dump(); - } - - void tag(const std::string& name, const std::string& value) - { - msg_[name] = value; - } - - std::string operator[](const std::string& key) - { - try - { - return msg_[key]; - } - catch (std::domain_error&) - { - return std::string(); - } - } - - virtual int push() - { - std::cout << serialize() << "\n"; - return 0; - } - - int push(const json& jtag) - { - msg_ = jtag; - return push(); - } - -protected: - json msg_; -}; - -/* - * Send metadata to stderr as json - */ -class MetaStderrAdapter : public MetadataAdapter -{ -public: - using MetadataAdapter::push; - - int push() override - { - std::cerr << serialize() << "\n"; - return 0; - } -}; diff --git a/common/queue.hpp b/common/queue.hpp index 6648aeca..15df986d 100644 --- a/common/queue.hpp +++ b/common/queue.hpp @@ -1,6 +1,6 @@ /*** This file is part of snapcast - Copyright (C) 2014-2024 Johannes Pohl + Copyright (C) 2014-2025 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ #include +/// Queue with "wait for new element" functionality template class Queue { @@ -32,8 +33,7 @@ public: T pop() { std::unique_lock mlock(mutex_); - while (queue_.empty()) - cond_.wait(mlock); + cond_.wait(mlock, [this]() { return queue_.empty(); }); // std::lock_guard lock(mutex_); auto val = queue_.front(); @@ -54,7 +54,7 @@ public: { std::unique_lock mlock(mutex_); abort_ = false; - if (!cond_.wait_for(mlock, timeout, [this] { return (!queue_.empty() || abort_); })) + if (!cond_.wait_for(mlock, timeout, [this]() { return (!queue_.empty() || abort_); })) return false; return !queue_.empty() && !abort_; @@ -66,7 +66,7 @@ public: abort_ = false; if (timeout.count() > 0) { - if (!cond_.wait_for(mlock, timeout, [this] { return (!queue_.empty() || abort_); })) + if (!cond_.wait_for(mlock, timeout, [this]() { return (!queue_.empty() || abort_); })) return false; } diff --git a/common/resampler.hpp b/common/resampler.hpp index 3e191024..7f1ab878 100644 --- a/common/resampler.hpp +++ b/common/resampler.hpp @@ -1,6 +1,6 @@ /*** This file is part of snapcast - Copyright (C) 2014-2024 Johannes Pohl + Copyright (C) 2014-2025 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,20 +32,24 @@ #include +/// Resampler class Resampler { public: + /// c'tor to resample from @p in_format to @p out_format Resampler(const SampleFormat& in_format, const SampleFormat& out_format); + /// d'tor virtual ~Resampler(); - // std::shared_ptr resample(std::shared_ptr chunk, chronos::usec duration); + /// @return resampled @p chunk std::shared_ptr resample(std::shared_ptr chunk); + /// @return resampled @p chunk std::shared_ptr resample(const msg::PcmChunk& chunk); + /// @return if resampling is needed (in_format != out_format) bool resamplingNeeded() const; private: std::vector resample_buffer_; - // std::unique_ptr resampled_chunk_; SampleFormat in_format_; SampleFormat out_format_; #ifdef HAS_SOXR diff --git a/server/streamreader/metadata.hpp b/server/streamreader/metadata.hpp index 85299a68..86fb767b 100644 --- a/server/streamreader/metadata.hpp +++ b/server/streamreader/metadata.hpp @@ -1,6 +1,6 @@ /*** This file is part of snapcast - Copyright (C) 2014-2024 Johannes Pohl + Copyright (C) 2014-2025 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,27 +29,35 @@ using json = nlohmann::json; +/// Meta data of a single track class Metadata { public: + /// Cover art struct ArtData { + /// base64 encoded art data std::string data; + /// type of the data (e.g. jpg) std::string extension; + /// compare for equality bool operator==(const ArtData& other) const { return ((other.data == data) && (other.extension == extension)); } + /// compare for un-equality bool operator!=(const ArtData& other) const { return !(other == *this); } }; + /// c'tor Metadata() = default; - Metadata(const json& j); + /// c'tor taking json serialized meta data + explicit Metadata(const json& j); /// https://www.musicpd.org/doc/html/protocol.html#tags /// the duration of the song @@ -142,7 +150,10 @@ public: /// Spotify track id std::optional spotify_track_id; + /// serialize to json json toJson() const; + /// deserialize from json void fromJson(const json& j); + /// compare for equality bool operator==(const Metadata& other) const; }; diff --git a/server/streamreader/pcm_stream.cpp b/server/streamreader/pcm_stream.cpp index 810aa80c..d6794b1f 100644 --- a/server/streamreader/pcm_stream.cpp +++ b/server/streamreader/pcm_stream.cpp @@ -29,6 +29,7 @@ #include "control_error.hpp" #include "encoder/encoder_factory.hpp" #include "image_cache.hpp" +#include "streamreader/properties.hpp" // 3rd party headers #include @@ -152,7 +153,7 @@ void PcmStream::pollProperties() { LOG(INFO, LOG_TAG) << "Response for Plugin.Stream.Player.GetProperties: " << response.to_json() << "\n"; if (response.error().code() == 0) - setProperties(response.result()); + setProperties(Properties(response.result())); }); pollProperties(); } @@ -168,7 +169,7 @@ void PcmStream::onControlNotification(const jsonrpcpp::Notification& notificatio if (notification.method() == "Plugin.Stream.Player.Properties") { LOG(DEBUG, LOG_TAG) << "Received properties notification\n"; - setProperties(notification.params().to_json()); + setProperties(Properties(notification.params().to_json())); } else if (notification.method() == "Plugin.Stream.Ready") { @@ -177,7 +178,7 @@ void PcmStream::onControlNotification(const jsonrpcpp::Notification& notificatio { LOG(INFO, LOG_TAG) << "Response for Plugin.Stream.Player.GetProperties: " << response.to_json() << "\n"; if (response.error().code() == 0) - setProperties(response.result()); + setProperties(Properties(response.result())); }); // TODO: Add capabilities or settings? diff --git a/server/streamreader/properties.hpp b/server/streamreader/properties.hpp index aa8f4415..49b697ce 100644 --- a/server/streamreader/properties.hpp +++ b/server/streamreader/properties.hpp @@ -1,6 +1,6 @@ /*** This file is part of snapcast - Copyright (C) 2014-2024 Johannes Pohl + Copyright (C) 2014-2025 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -143,12 +143,14 @@ static std::istream& operator>>(std::istream& is, LoopStatus& loop_status) return is; } - +/// Properties of the stream (volume, shuffle, mute, position, can_play, can_pause, ...) class Properties { public: + /// c'tor Properties() = default; - Properties(const json& j); + /// c'tor taking json serialized properties + explicit Properties(const json& j); /// Meta data std::optional metadata; @@ -185,7 +187,10 @@ public: /// Whether the media player may be controlled over this interface bool can_control = false; + /// serialize to json json toJson() const; + /// deserialize from json void fromJson(const json& j); + /// compare for equality bool operator==(const Properties& other) const; };