mirror of
https://github.com/badaix/snapcast.git
synced 2025-04-28 17:57:05 +02:00
Add documentation
This commit is contained in:
parent
a692cc8874
commit
1460a530d8
25 changed files with 140 additions and 80 deletions
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace player
|
|||
|
||||
static constexpr auto LOG_TAG = "WASAPI";
|
||||
|
||||
/// COMMemDeleter helper
|
||||
template <typename T>
|
||||
struct COMMemDeleter
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace snapcast::error::control
|
|||
namespace detail
|
||||
{
|
||||
|
||||
/// control error category
|
||||
struct category : public std::error_category
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Add table
Reference in a new issue