Add documentation

This commit is contained in:
badaix 2025-02-16 21:42:06 +01:00
parent a692cc8874
commit 1460a530d8
25 changed files with 140 additions and 80 deletions

View file

@ -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,34 +32,38 @@
namespace decoder
{
/// Cache internal decoder status
struct CacheInfo
{
CacheInfo() : sampleRate_(0)
{
reset();
}
/// Reset current cache info
void reset()
{
isCachedChunk_ = true;
cachedBlocks_ = 0;
}
bool isCachedChunk_;
size_t cachedBlocks_;
size_t sampleRate_;
bool isCachedChunk_{true}; ///< is the current block cached
size_t cachedBlocks_{0}; ///< number of cached blocks
size_t sampleRate_{0}; ///< sample rate of the block
};
/// Flac decoder
class FlacDecoder : public Decoder
{
public:
/// c'tor
FlacDecoder();
/// d'tor
~FlacDecoder() override;
bool decode(msg::PcmChunk* chunk) override;
SampleFormat setHeader(msg::CodecHeader* chunk) override;
/// Flac internal cache info
CacheInfo cacheInfo_;
/// Last decoder error
std::unique_ptr<FLAC__StreamDecoderErrorStatus> lastError_;
private:

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2023 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,10 +25,13 @@
namespace decoder
{
/// Dummy decoder, doing actually nothing
class NullDecoder : public Decoder
{
public:
/// c'tor
NullDecoder();
bool decode(msg::PcmChunk* chunk) override;
SampleFormat setHeader(msg::CodecHeader* chunk) override;
};

View file

@ -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
@ -36,11 +36,15 @@
namespace decoder
{
/// Ogg decoder
class OggDecoder : public Decoder
{
public:
/// c'tor
OggDecoder();
/// d'tor
~OggDecoder() override;
bool decode(msg::PcmChunk* chunk) override;
SampleFormat setHeader(msg::CodecHeader* chunk) override;
@ -57,15 +61,15 @@ private:
return static_cast<T>(value);
}
ogg_sync_state oy; /// sync and verify incoming physical bitstream
ogg_stream_state os; /// take physical pages, weld into a logical stream of packets
ogg_page og; /// one Ogg bitstream page. Vorbis packets are inside
ogg_packet op; /// one raw packet of data for decode
ogg_sync_state oy; ///< sync and verify incoming physical bitstream
ogg_stream_state os; ///< take physical pages, weld into a logical stream of packets
ogg_page og; ///< one Ogg bitstream page. Vorbis packets are inside
ogg_packet op; ///< one raw packet of data for decode
vorbis_info vi; /// struct that stores all the static vorbis bitstream settings
vorbis_comment vc; /// struct that stores all the bitstream user comments
vorbis_dsp_state vd; /// central working state for the packet->PCM decoder
vorbis_block vb; /// local working space for packet->PCM decode
vorbis_info vi; ///< struct that stores all the static vorbis bitstream settings
vorbis_comment vc; ///< struct that stores all the bitstream user comments
vorbis_dsp_state vd; ///< central working state for the packet->PCM decoder
vorbis_block vb; ///< local working space for packet->PCM decode
SampleFormat sampleFormat_;
std::mutex mutex_;

View file

@ -1,7 +1,7 @@
/***
This file is part of snapcast
Copyright (C) 2015 Hannes Ellinger
Copyright (C) 2016-2024 Johannes Pohl
Copyright (C) 2016-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
@ -36,11 +36,15 @@
namespace decoder
{
/// Opus decoder
class OpusDecoder : public Decoder
{
public:
/// c'tor
OpusDecoder();
~OpusDecoder();
/// c'tor
~OpusDecoder() override;
bool decode(msg::PcmChunk* chunk) override;
SampleFormat setHeader(msg::CodecHeader* chunk) override;

View file

@ -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,14 +32,18 @@ static constexpr auto ID_WAVE = 0x45564157;
static constexpr auto ID_FMT = 0x20746d66;
static constexpr auto ID_DATA = 0x61746164;
/// RIFF wave header
/// See https://en.wikipedia.org/wiki/WAV
struct riff_wave_header
{
uint32_t riff_id;
uint32_t riff_sz;
uint32_t wave_id;
uint32_t riff_id; ///< "RIFF"
uint32_t riff_sz; ///< file size - 8
uint32_t wave_id; ///< "WAVE"
};
/// Chunk header
/// See https://en.wikipedia.org/wiki/WAV
struct chunk_header
{
uint32_t id;
@ -47,9 +51,11 @@ struct chunk_header
};
/// Chunk format
/// See https://en.wikipedia.org/wiki/WAV
struct chunk_fmt
{
uint16_t audio_format;
uint16_t audio_format; ///<
uint16_t num_channels;
uint32_t sample_rate;
uint32_t byte_rate;

View file

@ -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,10 +25,13 @@
namespace decoder
{
/// PCM decoder
class PcmDecoder : public Decoder
{
public:
/// c'tor
PcmDecoder();
bool decode(msg::PcmChunk* chunk) override;
SampleFormat setHeader(msg::CodecHeader* chunk) override;
};

View file

@ -47,6 +47,7 @@ namespace player
static constexpr auto LOG_TAG = "WASAPI";
/// COMMemDeleter helper
template <typename T>
struct COMMemDeleter
{

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2022 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
@ -33,6 +33,7 @@
namespace player
{
/// Implementation of IAudioSessionEvents
class AudioSessionEventListener : public IAudioSessionEvents
{
LONG _cRef;
@ -108,6 +109,7 @@ public:
};
/// Implementation of IAudioEndpointVolumeCallback
class AudioEndpointVolumeCallback : public IAudioEndpointVolumeCallback
{
LONG _cRef;
@ -178,6 +180,7 @@ public:
static constexpr auto WASAPI = "wasapi";
/// WASAPI player
class WASAPIPlayer : public Player
{
public:

View file

@ -22,28 +22,33 @@
#include <exception>
#include <string>
// text_exception uses a dynamically-allocated internal c-string for what():
/// Snapcast specific exceptions
class SnapException : public std::exception
{
std::string text_;
int error_code_;
public:
/// c'tor
explicit SnapException(const char* text, int error_code = 0) : text_(text), error_code_(error_code)
{
}
/// c'tor
explicit SnapException(const std::string& text, int error_code = 0) : SnapException(text.c_str(), error_code)
{
}
/// d'tor
~SnapException() override = default;
/// @return error code
int code() const noexcept
{
return error_code_;
}
/// @return the exception text
const char* what() const noexcept override
{
return text_.c_str();

View file

@ -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
@ -45,7 +45,7 @@ public:
/// 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)
explicit Encoder(std::string codecOptions = "") : headerChunk_(nullptr), codecOptions_(std::move(codecOptions))
{
}

View file

@ -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
@ -40,9 +40,9 @@ using namespace std;
namespace encoder
{
std::unique_ptr<Encoder> EncoderFactory::createEncoder(const std::string& codecSettings) const
std::unique_ptr<Encoder> EncoderFactory::createEncoder(const std::string& codec_settings) const
{
std::string codec(codecSettings);
std::string codec(codec_settings);
std::string codecOptions;
if (codec.find(':') != std::string::npos)
{

View file

@ -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,11 +29,12 @@
namespace encoder
{
/// Factory to create an encoder from an URI
class EncoderFactory
{
public:
// EncoderFactory(const std::string& codecSettings);
std::unique_ptr<Encoder> createEncoder(const std::string& codecSettings) const;
/// @return Encoder from @p codec_settings
std::unique_ptr<Encoder> createEncoder(const std::string& codec_settings) const;
};
} // namespace encoder

View file

@ -40,7 +40,8 @@ namespace encoder
static constexpr auto LOG_TAG = "FlacEnc";
FlacEncoder::FlacEncoder(const std::string& codecOptions) : Encoder(codecOptions), encoder_(nullptr), pcmBufferSize_(0), encodedSamples_(0), flacChunk_(nullptr)
FlacEncoder::FlacEncoder(std::string codecOptions)
: Encoder(std::move(codecOptions)), encoder_(nullptr), pcmBufferSize_(0), encodedSamples_(0), flacChunk_(nullptr)
{
headerChunk_ = std::make_shared<msg::CodecHeader>("flac");
pcmBuffer_ = static_cast<FLAC__int32*>(malloc(pcmBufferSize_ * sizeof(FLAC__int32)));
@ -230,7 +231,7 @@ void FlacEncoder::initEncoder()
throw SnapException("out of memory or tag error");
metadata_[1]->length = 1234; // set the padding length
ok = FLAC__stream_encoder_set_metadata(encoder_, metadata_, 2);
ok = FLAC__stream_encoder_set_metadata(encoder_, metadata_.data(), 2);
if (ok == 0)
throw SnapException("error setting meta data");

View file

@ -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,24 +32,29 @@
namespace encoder
{
/// Flac encoder
class FlacEncoder : public Encoder
{
public:
explicit FlacEncoder(const std::string& codecOptions = "");
/// c'tor
explicit FlacEncoder(std::string codecOptions);
/// d'tor
~FlacEncoder() override;
void encode(const msg::PcmChunk& chunk) override;
std::string getAvailableOptions() const override;
std::string getDefaultOptions() const override;
std::string name() const override;
/// FLAC write callback
FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder* encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples,
unsigned current_frame);
protected:
private:
void initEncoder() override;
FLAC__StreamEncoder* encoder_;
FLAC__StreamMetadata* metadata_[2];
std::array<FLAC__StreamMetadata*, 2> metadata_;
FLAC__int32* pcmBuffer_;
int pcmBufferSize_;

View file

@ -31,7 +31,7 @@ namespace encoder
static constexpr auto LOG_TAG = "NullEnc";
NullEncoder::NullEncoder(const std::string& codecOptions) : Encoder(codecOptions)
NullEncoder::NullEncoder(std::string codecOptions) : Encoder(std::move(codecOptions))
{
headerChunk_ = std::make_shared<msg::CodecHeader>("null");
}

View file

@ -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
@ -37,11 +37,13 @@ namespace encoder
class NullEncoder : public Encoder
{
public:
NullEncoder(const std::string& codecOptions = "");
/// c'tor
explicit NullEncoder(std::string codecOptions);
void encode(const msg::PcmChunk& chunk) override;
std::string name() const override;
protected:
private:
void initEncoder() override;
};

View file

@ -38,7 +38,8 @@ namespace encoder
static constexpr auto LOG_TAG = "OggEnc";
OggEncoder::OggEncoder(const std::string& codecOptions) : Encoder(codecOptions), lastGranulepos_(0)
OggEncoder::OggEncoder(std::string codecOptions) : Encoder(std::move(codecOptions)), lastGranulepos_(0)
{
}

View file

@ -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,10 +29,13 @@
namespace encoder
{
/// Ogg encoder
class OggEncoder : public Encoder
{
public:
OggEncoder(const std::string& codecOptions = "");
/// c'tor
explicit OggEncoder(std::string codecOptions);
/// d'tor
~OggEncoder() override;
void encode(const msg::PcmChunk& chunk) override;
@ -40,19 +43,18 @@ public:
std::string getDefaultOptions() const override;
std::string name() const override;
protected:
private:
void initEncoder() override;
private:
ogg_stream_state os_; /// take physical pages, weld into a logical stream of packets
ogg_page og_; /// one Ogg bitstream page. Vorbis packets are inside
ogg_packet op_; /// one raw packet of data for decode
ogg_stream_state os_; ///< take physical pages, weld into a logical stream of packets
ogg_page og_; ///< one Ogg bitstream page. Vorbis packets are inside
ogg_packet op_; ///< one raw packet of data for decode
vorbis_info vi_; /// struct that stores all the static vorbis bitstream settings
vorbis_comment vc_; /// struct that stores all the user comments
vorbis_info vi_; ///< struct that stores all the static vorbis bitstream settings
vorbis_comment vc_; ///< struct that stores all the user comments
vorbis_dsp_state vd_; /// central working state for the packet->PCM decoder
vorbis_block vb_; /// local working space for packet->PCM decode
vorbis_dsp_state vd_; ///< central working state for the packet->PCM decoder
vorbis_block vb_; ///< local working space for packet->PCM decode
ogg_int64_t lastGranulepos_;
};

View file

@ -50,7 +50,7 @@ void assign(void* pointer, T val)
} // namespace
OpusEncoder::OpusEncoder(const std::string& codecOptions) : Encoder(codecOptions), enc_(nullptr), remainder_max_size_(0)
OpusEncoder::OpusEncoder(std::string codecOptions) : Encoder(std::move(codecOptions)), enc_(nullptr), remainder_max_size_(0)
{
headerChunk_ = make_unique<msg::CodecHeader>("opus");
}

View file

@ -1,7 +1,7 @@
/***
This file is part of snapcast
Copyright (C) 2015 Hannes Ellinger
Copyright (C) 2016-2024 Johannes Pohl
Copyright (C) 2016-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
@ -34,10 +34,13 @@
namespace encoder
{
/// Opuse encoder
class OpusEncoder : public Encoder
{
public:
OpusEncoder(const std::string& codecOptions = "");
/// c'tor
explicit OpusEncoder(std::string codecOptions);
/// d'tor
~OpusEncoder() override;
void encode(const msg::PcmChunk& chunk) override;
@ -45,7 +48,7 @@ public:
std::string getDefaultOptions() const override;
std::string name() const override;
protected:
private:
void encode(const SampleFormat& format, const char* data, size_t size);
void initEncoder() override;
::OpusEncoder* enc_;

View file

@ -48,7 +48,7 @@ void assign(void* pointer, T val)
} // namespace
PcmEncoder::PcmEncoder(const std::string& codecOptions) : Encoder(codecOptions)
PcmEncoder::PcmEncoder(std::string codecOptions) : Encoder(std::move(codecOptions))
{
headerChunk_ = std::make_shared<msg::CodecHeader>("pcm");
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2020 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,14 +25,17 @@
namespace encoder
{
/// PCM encoder
class PcmEncoder : public Encoder
{
public:
PcmEncoder(const std::string& codecOptions = "");
/// c'tor
explicit PcmEncoder(std::string codecOptions);
void encode(const msg::PcmChunk& chunk) override;
std::string name() const override;
protected:
private:
void initEncoder() override;
};

View file

@ -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,18 +32,14 @@
namespace streamreader
{
class TageEntry
/// Tage entry??
struct TageEntry
{
public:
TageEntry() : isBase64(false), length(0)
{
}
std::string code;
std::string type;
std::string data;
bool isBase64;
int length;
bool isBase64{false};
int length{0};
};
/// Starts shairport-sync and reads PCM data from stdout
@ -58,11 +54,12 @@ public:
class AirplayStream : public ProcessStream
{
public:
/// ctor. Encoded PCM data is passed to the PipeListener
/// c'tor. Encoded PCM data is passed to the PipeListener
AirplayStream(PcmStream::Listener* pcmListener, boost::asio::io_context& ioc, const ServerSettings& server_settings, const StreamUri& uri);
/// d'tor
~AirplayStream() override;
protected:
private:
#ifdef HAS_EXPAT
XML_Parser parser_;
std::unique_ptr<TageEntry> entry_;

View file

@ -37,21 +37,26 @@ namespace streamreader
using namespace std::chrono_literals;
/// Boost asio based stream class interface
template <typename ReadStream>
class AsioStream : public PcmStream
{
public:
/// ctor. Encoded PCM data is passed to the PipeListener
/// c'tor. Encoded PCM data is passed to the PipeListener
AsioStream(PcmStream::Listener* pcmListener, boost::asio::io_context& ioc, const ServerSettings& server_settings, const StreamUri& uri);
void start() override;
void stop() override;
protected:
/// connect to the stream
virtual void connect() = 0;
/// disconnect from the stream
virtual void disconnect();
/// resets first chunk timer and starts reader loop
virtual void on_connect();
/// read from asio stream
virtual void do_read();
/// Start a timer that will change the stream state to idle after \p duration
void check_state(const std::chrono::steady_clock::duration& duration);
@ -62,12 +67,18 @@ protected:
/// Cache last exception to avoid repeated error logging
std::string lastException_;
timeval tv_chunk_;
/// Marker: next chunk is the first chunk
bool first_;
/// next read = current chunk start + chunk duration
std::chrono::time_point<std::chrono::steady_clock> nextTick_;
/// chunk read buffer
uint32_t buffer_ms_;
/// read timer
boost::asio::steady_timer read_timer_;
/// state timer: set stream to idle/playing on timeout
boost::asio::steady_timer state_timer_;
/// the stream
std::unique_ptr<ReadStream> stream_;
/// duration of the current silence period

View file

@ -26,6 +26,7 @@ namespace snapcast::error::control
namespace detail
{
/// control error category
struct category : public std::error_category
{
public: