diff --git a/Doxyfile b/Doxyfile index 5b10f778..a9f498e5 100644 --- a/Doxyfile +++ b/Doxyfile @@ -952,7 +952,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = README.md common/json.hpp server/etc +EXCLUDE = README.md common/json.hpp server/etc server/jsonrpcpp.hpp common/popl.hpp common/aixlog.hpp # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded diff --git a/client/decoder/decoder.hpp b/client/decoder/decoder.hpp index 679059b5..93ab4e2a 100644 --- a/client/decoder/decoder.hpp +++ b/client/decoder/decoder.hpp @@ -1,6 +1,6 @@ /*** This file is part of snapcast - Copyright (C) 2014-2023 Johannes Pohl + 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 @@ -27,22 +27,27 @@ // 3rd party headers // standard headers -#include namespace decoder { +/// Base class for an audio decoder class Decoder { public: - Decoder(){}; + /// c'tor + Decoder() = default; + /// d'tor virtual ~Decoder() = default; + /// decode encoded data stored in @p chunk, and write decoded data back into @p chunk + /// return true, if data could be decoded and written back into @p chunk virtual bool decode(msg::PcmChunk* chunk) = 0; - virtual SampleFormat setHeader(msg::CodecHeader* chunk) = 0; -protected: - std::mutex mutex_; + /// Set the codec header, stored in @p chunk. + /// The CodecHeader is sent to every newly connected streaming client as first audio message. + /// @return the sampleformat, decoded from the header + virtual SampleFormat setHeader(msg::CodecHeader* chunk) = 0; }; } // namespace decoder diff --git a/client/decoder/flac_decoder.hpp b/client/decoder/flac_decoder.hpp index a19a62b0..9b87e399 100644 --- a/client/decoder/flac_decoder.hpp +++ b/client/decoder/flac_decoder.hpp @@ -26,6 +26,7 @@ // standard headers #include +#include namespace decoder @@ -60,6 +61,9 @@ public: CacheInfo cacheInfo_; std::unique_ptr lastError_; + +private: + std::mutex mutex_; }; } // namespace decoder diff --git a/client/decoder/ogg_decoder.hpp b/client/decoder/ogg_decoder.hpp index 8a4f8c2d..9da91aac 100644 --- a/client/decoder/ogg_decoder.hpp +++ b/client/decoder/ogg_decoder.hpp @@ -29,6 +29,10 @@ #endif #include +// standard headers +#include + + namespace decoder { @@ -64,6 +68,7 @@ private: vorbis_block vb; /// local working space for packet->PCM decode SampleFormat sampleFormat_; + std::mutex mutex_; }; } // namespace decoder diff --git a/server/encoder/encoder.hpp b/server/encoder/encoder.hpp index a5bdf9c6..ad9e0b49 100644 --- a/server/encoder/encoder.hpp +++ b/server/encoder/encoder.hpp @@ -40,21 +40,24 @@ namespace encoder class Encoder { public: + /// Callback type to return encoded chunks, along with the encoder itself and the duration in ms of the chunk using OnEncodedCallback = std::function, double)>; - /// ctor. Codec options (E.g. compression level) are passed as string and are codec dependend + /// c'tor + /// Codec options (E.g. compression level) are passed as string and are codec dependend Encoder(const std::string& codecOptions = "") : headerChunk_(nullptr), codecOptions_(codecOptions) { } + /// d'tor virtual ~Encoder() = default; /// The listener will receive the encoded stream virtual void init(OnEncodedCallback callback, const SampleFormat& format) { - if (codecOptions_ == "") + if (codecOptions_.empty()) codecOptions_ = getDefaultOptions(); - encoded_callback_ = callback; + encoded_callback_ = std::move(callback); sampleFormat_ = format; initEncoder(); } @@ -62,13 +65,16 @@ public: /// Here the work is done. Encoded data is passed to the EncoderListener. virtual void encode(const msg::PcmChunk& chunk) = 0; + /// @return the name of the encoder virtual std::string name() const = 0; + /// @return configuration options of the encoder virtual std::string getAvailableOptions() const { return "No codec options supported"; } + /// @return default configuration option of the encoder virtual std::string getDefaultOptions() const { return ""; @@ -81,11 +87,16 @@ public: } protected: + /// Initialize the encoder virtual void initEncoder() = 0; + /// The sampleformat SampleFormat sampleFormat_; + /// The codec header, sent to each newly connected streaming client std::shared_ptr headerChunk_; + /// The configured codec options std::string codecOptions_; + /// Callback to return encoded chunks OnEncodedCallback encoded_callback_; }; diff --git a/server/stream_session.hpp b/server/stream_session.hpp index eeb464ac..33dbc137 100644 --- a/server/stream_session.hpp +++ b/server/stream_session.hpp @@ -106,6 +106,7 @@ private: }; +/// Write result callback function type using WriteHandler = std::function; /// Endpoint for a connected client. @@ -117,21 +118,27 @@ using WriteHandler = std::function { public: - /// ctor. Received message from the client are passed to StreamMessageReceiver + /// c'tor. Received message from the client are passed to StreamMessageReceiver StreamSession(const boost::asio::any_io_executor& executor, StreamMessageReceiver* receiver); + /// d'tor virtual ~StreamSession() = default; + /// @return the IP of the connected streaming client virtual std::string getIP() = 0; + /// Start the StreamSession, e.g. start reading and processing data virtual void start() = 0; + /// Stop the StreamSession virtual void stop() = 0; + /// Set the message receiver to @p receiver void setMessageReceiver(StreamMessageReceiver* receiver) { messageReceiver_ = receiver; } protected: + /// Send data @p buffer to the streaming client, result is returned in the callback @p handler virtual void sendAsync(const shared_const_buffer& buffer, const WriteHandler& handler) = 0; public: