output/Interface: pass std::span to Play()
This commit is contained in:
parent
f5d104e7af
commit
45071607aa
@ -173,10 +173,10 @@ FilteredAudioOutput::SendTag(const Tag &tag)
|
|||||||
output->SendTag(tag);
|
output->SendTag(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
FilteredAudioOutput::Play(const void *data, size_t size)
|
FilteredAudioOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
return output->Play(data, size);
|
return output->Play(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -23,10 +23,11 @@
|
|||||||
#include "pcm/AudioFormat.hxx"
|
#include "pcm/AudioFormat.hxx"
|
||||||
#include "filter/Observer.hxx"
|
#include "filter/Observer.hxx"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <span>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class FilterFactory;
|
class FilterFactory;
|
||||||
class PreparedFilter;
|
class PreparedFilter;
|
||||||
@ -224,7 +225,7 @@ public:
|
|||||||
|
|
||||||
void SendTag(const Tag &tag);
|
void SendTag(const Tag &tag);
|
||||||
|
|
||||||
size_t Play(const void *data, size_t size);
|
std::size_t Play(std::span<const std::byte> src);
|
||||||
|
|
||||||
void Drain();
|
void Drain();
|
||||||
void Cancel() noexcept;
|
void Cancel() noexcept;
|
||||||
|
@ -21,8 +21,9 @@
|
|||||||
#define MPD_AUDIO_OUTPUT_INTERFACE_HXX
|
#define MPD_AUDIO_OUTPUT_INTERFACE_HXX
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <span>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
struct AudioFormat;
|
struct AudioFormat;
|
||||||
struct Tag;
|
struct Tag;
|
||||||
@ -180,7 +181,7 @@ public:
|
|||||||
* @return the number of bytes played (must be a multiple of
|
* @return the number of bytes played (must be a multiple of
|
||||||
* the frame size)
|
* the frame size)
|
||||||
*/
|
*/
|
||||||
virtual size_t Play(const void *chunk, size_t size) = 0;
|
virtual std::size_t Play(std::span<const std::byte> src) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait until the device has finished playing.
|
* Wait until the device has finished playing.
|
||||||
|
@ -265,7 +265,7 @@ AudioOutputControl::PlayChunk(std::unique_lock<Mutex> &lock) noexcept
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const ScopeUnlock unlock(mutex);
|
const ScopeUnlock unlock(mutex);
|
||||||
nbytes = output->Play(data.data(), data.size());
|
nbytes = output->Play(data);
|
||||||
assert(nbytes > 0);
|
assert(nbytes > 0);
|
||||||
assert(nbytes <= data.size());
|
assert(nbytes <= data.size());
|
||||||
} catch (AudioOutputInterrupted) {
|
} catch (AudioOutputInterrupted) {
|
||||||
@ -380,7 +380,7 @@ static void
|
|||||||
PlayFull(FilteredAudioOutput &output, std::span<const std::byte> buffer)
|
PlayFull(FilteredAudioOutput &output, std::span<const std::byte> buffer)
|
||||||
{
|
{
|
||||||
while (!buffer.empty()) {
|
while (!buffer.empty()) {
|
||||||
size_t nbytes = output.Play(buffer.data(), buffer.size());
|
size_t nbytes = output.Play(buffer);
|
||||||
assert(nbytes > 0);
|
assert(nbytes > 0);
|
||||||
|
|
||||||
buffer = buffer.subspan(nbytes);
|
buffer = buffer.subspan(nbytes);
|
||||||
|
@ -283,7 +283,7 @@ private:
|
|||||||
|
|
||||||
void Interrupt() noexcept override;
|
void Interrupt() noexcept override;
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
void Drain() override;
|
void Drain() override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
bool Pause() noexcept override;
|
bool Pause() noexcept override;
|
||||||
@ -1219,26 +1219,26 @@ AlsaOutput::LockWaitWriteAvailable()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
AlsaOutput::Play(const void *chunk, size_t size)
|
AlsaOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
assert(size > 0);
|
assert(!src.empty());
|
||||||
assert(size % in_frame_size == 0);
|
assert(src.size() % in_frame_size == 0);
|
||||||
|
|
||||||
const size_t max_frames = LockWaitWriteAvailable();
|
const size_t max_frames = LockWaitWriteAvailable();
|
||||||
const size_t max_size = max_frames * in_frame_size;
|
const size_t max_size = max_frames * in_frame_size;
|
||||||
if (size > max_size)
|
if (src.size() > max_size)
|
||||||
size = max_size;
|
src = src.first(max_size);
|
||||||
|
|
||||||
const auto e = pcm_export->Export({(const std::byte *)chunk, size});
|
const auto e = pcm_export->Export(src);
|
||||||
if (e.empty())
|
if (e.empty())
|
||||||
return size;
|
return src.size();
|
||||||
|
|
||||||
size_t bytes_written = ring_buffer->push(e.data(), e.size());
|
size_t bytes_written = ring_buffer->push(e.data(), e.size());
|
||||||
assert(bytes_written == e.size());
|
assert(bytes_written == e.size());
|
||||||
(void)bytes_written;
|
(void)bytes_written;
|
||||||
|
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::Duration
|
Event::Duration
|
||||||
|
@ -74,7 +74,7 @@ public:
|
|||||||
void Open(AudioFormat &audio_format) override;
|
void Open(AudioFormat &audio_format) override;
|
||||||
void Close() noexcept override;
|
void Close() noexcept override;
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Domain ao_output_domain("ao_output");
|
static constexpr Domain ao_output_domain("ao_output");
|
||||||
@ -195,23 +195,24 @@ AoOutput::Close() noexcept
|
|||||||
ao_close(device);
|
ao_close(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
AoOutput::Play(const void *chunk, size_t size)
|
AoOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
assert(size % frame_size == 0);
|
assert(src.size() % frame_size == 0);
|
||||||
|
|
||||||
if (size > max_size)
|
if (src.size() > max_size)
|
||||||
size = max_size;
|
/* round down to a multiple of the frame size */
|
||||||
|
src = src.first(max_size);
|
||||||
|
|
||||||
/* For whatever reason, libao wants a non-const pointer.
|
/* For whatever reason, libao wants a non-const pointer.
|
||||||
Let's hope it does not write to the buffer, and use the
|
Let's hope it does not write to the buffer, and use the
|
||||||
union deconst hack to * work around this API misdesign. */
|
union deconst hack to * work around this API misdesign. */
|
||||||
char *data = const_cast<char *>((const char *)chunk);
|
char *data = const_cast<char *>((const char *)src.data());
|
||||||
|
|
||||||
if (ao_play(device, data, size) == 0)
|
if (ao_play(device, data, src.size()) == 0)
|
||||||
throw MakeAoError();
|
throw MakeAoError();
|
||||||
|
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct AudioOutputPlugin ao_output_plugin = {
|
const struct AudioOutputPlugin ao_output_plugin = {
|
||||||
|
@ -69,7 +69,7 @@ private:
|
|||||||
void Close() noexcept override;
|
void Close() noexcept override;
|
||||||
|
|
||||||
[[nodiscard]] std::chrono::steady_clock::duration Delay() const noexcept override;
|
[[nodiscard]] std::chrono::steady_clock::duration Delay() const noexcept override;
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -208,17 +208,17 @@ FifoOutput::Delay() const noexcept
|
|||||||
: std::chrono::steady_clock::duration::zero();
|
: std::chrono::steady_clock::duration::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
FifoOutput::Play(const void *chunk, size_t size)
|
FifoOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
if (!timer->IsStarted())
|
if (!timer->IsStarted())
|
||||||
timer->Start();
|
timer->Start();
|
||||||
timer->Add(size);
|
timer->Add(src.size());
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
ssize_t bytes = write(output, chunk, size);
|
ssize_t bytes = write(output, src.data(), src.size());
|
||||||
if (bytes > 0)
|
if (bytes > 0)
|
||||||
return (size_t)bytes;
|
return (std::size_t)bytes;
|
||||||
|
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
switch (errno) {
|
switch (errno) {
|
||||||
|
@ -75,7 +75,7 @@ private:
|
|||||||
void Open(AudioFormat &audio_format) override;
|
void Open(AudioFormat &audio_format) override;
|
||||||
void Close() noexcept override;
|
void Close() noexcept override;
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
|
|
||||||
std::chrono::steady_clock::duration Delay() const noexcept override;
|
std::chrono::steady_clock::duration Delay() const noexcept override;
|
||||||
|
|
||||||
@ -256,17 +256,17 @@ HaikuOutput::Open(AudioFormat &audio_format)
|
|||||||
sound_player->SetHasData(false);
|
sound_player->SetHasData(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
HaikuOutput::Play(const void *chunk, size_t size)
|
HaikuOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
BSoundPlayer* const soundPlayer = sound_player;
|
BSoundPlayer* const soundPlayer = sound_player;
|
||||||
const uint8 *data = (const uint8 *)chunk;
|
const uint8 *data = (const uint8 *)src.data();
|
||||||
|
|
||||||
if (!soundPlayer->HasData())
|
if (!soundPlayer->HasData())
|
||||||
soundPlayer->SetHasData(true);
|
soundPlayer->SetHasData(true);
|
||||||
acquire_sem(new_buffer);
|
acquire_sem(new_buffer);
|
||||||
|
|
||||||
size_t bytesLeft = size;
|
size_t bytesLeft = src.size();
|
||||||
while (bytesLeft > 0) {
|
while (bytesLeft > 0) {
|
||||||
if (buffer_filled == buffer_size) {
|
if (buffer_filled == buffer_size) {
|
||||||
// Request another buffer from BSoundPlayer
|
// Request another buffer from BSoundPlayer
|
||||||
@ -293,7 +293,7 @@ HaikuOutput::Play(const void *chunk, size_t size)
|
|||||||
//soundPlayer->SetHasData(false);
|
//soundPlayer->SetHasData(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::chrono::steady_clock::duration
|
inline std::chrono::steady_clock::duration
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "util/ScopeExit.hxx"
|
#include "util/ScopeExit.hxx"
|
||||||
#include "util/IterableSplitString.hxx"
|
#include "util/IterableSplitString.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
|
#include "util/SpanCast.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
@ -178,7 +179,7 @@ public:
|
|||||||
: std::chrono::steady_clock::duration::zero();
|
: std::chrono::steady_clock::duration::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
|
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
bool Pause() override;
|
bool Pause() override;
|
||||||
@ -689,14 +690,17 @@ JackOutput::WriteSamples(const float *src, size_t n_frames)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t
|
std::size_t
|
||||||
JackOutput::Play(const void *chunk, size_t size)
|
JackOutput::Play(std::span<const std::byte> _src)
|
||||||
{
|
{
|
||||||
|
const auto src = FromBytesStrict<const float>(_src);
|
||||||
|
|
||||||
pause = false;
|
pause = false;
|
||||||
|
|
||||||
const size_t frame_size = audio_format.GetFrameSize();
|
const size_t frame_size = audio_format.GetFrameSize();
|
||||||
assert(size % frame_size == 0);
|
assert(src.size() % frame_size == 0);
|
||||||
size /= frame_size;
|
|
||||||
|
const std::size_t n_frames = src.size() / audio_format.channels;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
{
|
{
|
||||||
@ -709,7 +713,7 @@ JackOutput::Play(const void *chunk, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t frames_written =
|
size_t frames_written =
|
||||||
WriteSamples((const float *)chunk, size);
|
WriteSamples(src.data(), n_frames);
|
||||||
if (frames_written > 0)
|
if (frames_written > 0)
|
||||||
return frames_written * frame_size;
|
return frames_written * frame_size;
|
||||||
|
|
||||||
|
@ -53,14 +53,14 @@ private:
|
|||||||
: std::chrono::steady_clock::duration::zero();
|
: std::chrono::steady_clock::duration::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Play([[maybe_unused]] const void *chunk, size_t size) override {
|
size_t Play(std::span<const std::byte> src) override {
|
||||||
if (sync) {
|
if (sync) {
|
||||||
if (!timer->IsStarted())
|
if (!timer->IsStarted())
|
||||||
timer->Start();
|
timer->Start();
|
||||||
timer->Add(size);
|
timer->Add(src.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cancel() noexcept override {
|
void Cancel() noexcept override {
|
||||||
|
@ -112,7 +112,7 @@ private:
|
|||||||
void Close() noexcept override;
|
void Close() noexcept override;
|
||||||
|
|
||||||
std::chrono::steady_clock::duration Delay() const noexcept override;
|
std::chrono::steady_clock::duration Delay() const noexcept override;
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
bool Pause() override;
|
bool Pause() override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
};
|
};
|
||||||
@ -770,15 +770,13 @@ OSXOutput::Open(AudioFormat &audio_format)
|
|||||||
started = false;
|
started = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
OSXOutput::Play(const void *chunk, size_t size)
|
OSXOutput::Play(std::span<const std::byte> input)
|
||||||
{
|
{
|
||||||
assert(size > 0);
|
assert(size > 0);
|
||||||
|
|
||||||
pause = false;
|
pause = false;
|
||||||
|
|
||||||
std::span<const std::byte> input((const std::byte *)chunk, size);
|
|
||||||
|
|
||||||
#ifdef ENABLE_DSD
|
#ifdef ENABLE_DSD
|
||||||
if (dop_enabled) {
|
if (dop_enabled) {
|
||||||
input = pcm_export->Export(input);
|
input = pcm_export->Export(input);
|
||||||
|
@ -69,7 +69,7 @@ private:
|
|||||||
: std::chrono::milliseconds(50);
|
: std::chrono::milliseconds(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
|
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
|
|
||||||
@ -180,8 +180,8 @@ OpenALOutput::Close() noexcept
|
|||||||
alcCloseDevice(device);
|
alcCloseDevice(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
OpenALOutput::Play(const void *chunk, size_t size)
|
OpenALOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
if (alcGetCurrentContext() != context)
|
if (alcGetCurrentContext() != context)
|
||||||
alcMakeContextCurrent(context);
|
alcMakeContextCurrent(context);
|
||||||
@ -199,13 +199,13 @@ OpenALOutput::Play(const void *chunk, size_t size)
|
|||||||
alSourceUnqueueBuffers(source, 1, &buffer);
|
alSourceUnqueueBuffers(source, 1, &buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
alBufferData(buffer, format, chunk, size, frequency);
|
alBufferData(buffer, format, src.data(), src.size(), frequency);
|
||||||
alSourceQueueBuffers(source, 1, &buffer);
|
alSourceQueueBuffers(source, 1, &buffer);
|
||||||
|
|
||||||
if (!IsPlaying())
|
if (!IsPlaying())
|
||||||
alSourcePlay(source);
|
alSourcePlay(source);
|
||||||
|
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -114,7 +114,7 @@ public:
|
|||||||
DoClose();
|
DoClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -679,26 +679,21 @@ OssOutput::Cancel() noexcept
|
|||||||
pcm_export->Reset();
|
pcm_export->Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
OssOutput::Play(const void *chunk, size_t size)
|
OssOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
assert(!src.empty());
|
||||||
|
|
||||||
assert(size > 0);
|
|
||||||
|
|
||||||
/* reopen the device since it was closed by dropBufferedAudio */
|
/* reopen the device since it was closed by dropBufferedAudio */
|
||||||
if (!fd.IsDefined())
|
if (!fd.IsDefined())
|
||||||
Reopen();
|
Reopen();
|
||||||
|
|
||||||
const auto e = pcm_export->Export({(const std::byte *)chunk, size});
|
const auto e = pcm_export->Export(src);
|
||||||
if (e.empty())
|
if (e.empty())
|
||||||
return size;
|
return src.size();
|
||||||
|
|
||||||
chunk = e.data();
|
|
||||||
size = e.size();
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
ret = fd.Write(chunk, size);
|
const ssize_t ret = fd.Write(e.data(), e.size());
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
return pcm_export->CalcInputSize(ret);
|
return pcm_export->CalcInputSize(ret);
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ private:
|
|||||||
pclose(fh);
|
pclose(fh);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
PipeOutput::PipeOutput(const ConfigBlock &block)
|
PipeOutput::PipeOutput(const ConfigBlock &block)
|
||||||
@ -64,10 +64,10 @@ PipeOutput::Open([[maybe_unused]] AudioFormat &audio_format)
|
|||||||
throw FormatErrno("Error opening pipe \"%s\"", cmd.c_str());
|
throw FormatErrno("Error opening pipe \"%s\"", cmd.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t
|
std::size_t
|
||||||
PipeOutput::Play(const void *chunk, size_t size)
|
PipeOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
size_t nbytes = fwrite(chunk, 1, size, fh);
|
size_t nbytes = fwrite(src.data(), 1, src.size(), fh);
|
||||||
if (nbytes == 0)
|
if (nbytes == 0)
|
||||||
throw MakeErrno("Write error on pipe");
|
throw MakeErrno("Write error on pipe");
|
||||||
|
|
||||||
|
@ -290,7 +290,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::chrono::steady_clock::duration Delay() const noexcept override;
|
[[nodiscard]] std::chrono::steady_clock::duration Delay() const noexcept override;
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
|
|
||||||
void Drain() override;
|
void Drain() override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
@ -828,8 +828,8 @@ PipeWireOutput::Delay() const noexcept
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
PipeWireOutput::Play(const void *chunk, size_t size)
|
PipeWireOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
const PipeWire::ThreadLoopLock lock(thread_loop);
|
const PipeWire::ThreadLoopLock lock(thread_loop);
|
||||||
|
|
||||||
@ -839,7 +839,7 @@ PipeWireOutput::Play(const void *chunk, size_t size)
|
|||||||
CheckThrowError();
|
CheckThrowError();
|
||||||
|
|
||||||
std::size_t bytes_written =
|
std::size_t bytes_written =
|
||||||
ring_buffer->push((const std::byte *)chunk, size);
|
ring_buffer->push(src.data(), src.size());
|
||||||
if (bytes_written > 0) {
|
if (bytes_written > 0) {
|
||||||
drained = false;
|
drained = false;
|
||||||
return bytes_written;
|
return bytes_written;
|
||||||
|
@ -110,7 +110,7 @@ public:
|
|||||||
void Interrupt() noexcept override;
|
void Interrupt() noexcept override;
|
||||||
|
|
||||||
[[nodiscard]] std::chrono::steady_clock::duration Delay() const noexcept override;
|
[[nodiscard]] std::chrono::steady_clock::duration Delay() const noexcept override;
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
void Drain() override;
|
void Drain() override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
bool Pause() override;
|
bool Pause() override;
|
||||||
@ -775,8 +775,8 @@ PulseOutput::Delay() const noexcept
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
PulseOutput::Play(const void *chunk, size_t size)
|
PulseOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
assert(mainloop != nullptr);
|
assert(mainloop != nullptr);
|
||||||
assert(stream != nullptr);
|
assert(stream != nullptr);
|
||||||
@ -811,18 +811,18 @@ PulseOutput::Play(const void *chunk, size_t size)
|
|||||||
|
|
||||||
/* now write */
|
/* now write */
|
||||||
|
|
||||||
if (size > writable)
|
if (src.size() > writable)
|
||||||
/* don't send more than possible */
|
/* don't send more than possible */
|
||||||
size = writable;
|
src = src.first(writable);
|
||||||
|
|
||||||
writable -= size;
|
writable -= src.size();
|
||||||
|
|
||||||
int result = pa_stream_write(stream, chunk, size, nullptr,
|
int result = pa_stream_write(stream, src.data(), src.size(), nullptr,
|
||||||
0, PA_SEEK_RELATIVE);
|
0, PA_SEEK_RELATIVE);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
throw MakePulseError(context, "pa_stream_write() failed");
|
throw MakePulseError(context, "pa_stream_write() failed");
|
||||||
|
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -86,7 +86,7 @@ private:
|
|||||||
|
|
||||||
void SendTag(const Tag &tag) override;
|
void SendTag(const Tag &tag) override;
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
|
|
||||||
[[nodiscard]] gcc_pure
|
[[nodiscard]] gcc_pure
|
||||||
bool HasDynamicPath() const noexcept {
|
bool HasDynamicPath() const noexcept {
|
||||||
@ -322,22 +322,22 @@ RecorderOutput::SendTag(const Tag &tag)
|
|||||||
encoder->SendTag(tag);
|
encoder->SendTag(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
RecorderOutput::Play(const void *chunk, size_t size)
|
RecorderOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
if (file == nullptr) {
|
if (file == nullptr) {
|
||||||
/* not currently encoding to a file; discard incoming
|
/* not currently encoding to a file; discard incoming
|
||||||
data */
|
data */
|
||||||
assert(HasDynamicPath());
|
assert(HasDynamicPath());
|
||||||
assert(path.IsNull());
|
assert(path.IsNull());
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
encoder->Write({(const std::byte *)chunk, size});
|
encoder->Write(src);
|
||||||
|
|
||||||
EncoderToFile();
|
EncoderToFile();
|
||||||
|
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct AudioOutputPlugin recorder_output_plugin = {
|
const struct AudioOutputPlugin recorder_output_plugin = {
|
||||||
|
@ -88,7 +88,7 @@ struct ShoutOutput final : AudioOutput {
|
|||||||
|
|
||||||
[[nodiscard]] std::chrono::steady_clock::duration Delay() const noexcept override;
|
[[nodiscard]] std::chrono::steady_clock::duration Delay() const noexcept override;
|
||||||
void SendTag(const Tag &tag) override;
|
void SendTag(const Tag &tag) override;
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
bool Pause() override;
|
bool Pause() override;
|
||||||
|
|
||||||
@ -413,12 +413,12 @@ ShoutOutput::Delay() const noexcept
|
|||||||
return std::chrono::milliseconds(delay);
|
return std::chrono::milliseconds(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
ShoutOutput::Play(const void *chunk, size_t size)
|
ShoutOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
encoder->Write({(const std::byte *)chunk, size});
|
encoder->Write(src);
|
||||||
WritePage();
|
WritePage();
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -144,11 +144,9 @@ SndioOutput::Close() noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
SndioOutput::Play(const void *chunk, size_t size)
|
SndioOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
size_t n;
|
const std::size_t n = sio_write(hdl, src.data(), src.size());
|
||||||
|
|
||||||
n = sio_write(hdl, chunk, size);
|
|
||||||
if (n == 0 && sio_eof(hdl) != 0)
|
if (n == 0 && sio_eof(hdl) != 0)
|
||||||
throw std::runtime_error("sndio write failed");
|
throw std::runtime_error("sndio write failed");
|
||||||
return n;
|
return n;
|
||||||
|
@ -49,7 +49,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void Open(AudioFormat &audio_format) override;
|
void Open(AudioFormat &audio_format) override;
|
||||||
void Close() noexcept override;
|
void Close() noexcept override;
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
size_t Play(std::span<const std::byte> src) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -76,7 +76,7 @@ private:
|
|||||||
void Open(AudioFormat &audio_format) override;
|
void Open(AudioFormat &audio_format) override;
|
||||||
void Close() noexcept override;
|
void Close() noexcept override;
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -139,10 +139,10 @@ SolarisOutput::Close() noexcept
|
|||||||
fd.Close();
|
fd.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
SolarisOutput::Play(const void *chunk, size_t size)
|
SolarisOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
ssize_t nbytes = fd.Write(chunk, size);
|
ssize_t nbytes = fd.Write(src.data(), src.size());
|
||||||
if (nbytes <= 0)
|
if (nbytes <= 0)
|
||||||
throw MakeErrno("Write failed");
|
throw MakeErrno("Write failed");
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ private:
|
|||||||
void Open(AudioFormat &audio_format) override;
|
void Open(AudioFormat &audio_format) override;
|
||||||
void Close() noexcept override;
|
void Close() noexcept override;
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
void Drain() override;
|
void Drain() override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
|
|
||||||
@ -256,13 +256,13 @@ WinmmOutput::DrainBuffer(WinmmBuffer &buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
WinmmOutput::Play(const void *chunk, size_t size)
|
WinmmOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
/* get the next buffer from the ring and prepare it */
|
/* get the next buffer from the ring and prepare it */
|
||||||
WinmmBuffer *buffer = &buffers[next_buffer];
|
WinmmBuffer *buffer = &buffers[next_buffer];
|
||||||
DrainBuffer(*buffer);
|
DrainBuffer(*buffer);
|
||||||
winmm_set_buffer(handle, buffer, chunk, size);
|
winmm_set_buffer(handle, buffer, src.data(), src.size());
|
||||||
|
|
||||||
/* enqueue the buffer */
|
/* enqueue the buffer */
|
||||||
MMRESULT result = waveOutWrite(handle, &buffer->hdr,
|
MMRESULT result = waveOutWrite(handle, &buffer->hdr,
|
||||||
@ -276,7 +276,7 @@ WinmmOutput::Play(const void *chunk, size_t size)
|
|||||||
/* mark our buffer as "used" */
|
/* mark our buffer as "used" */
|
||||||
next_buffer = (next_buffer + 1) % buffers.size();
|
next_buffer = (next_buffer + 1) % buffers.size();
|
||||||
|
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -254,7 +254,7 @@ public:
|
|||||||
|
|
||||||
void SendTag(const Tag &tag) override;
|
void SendTag(const Tag &tag) override;
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mutext must not be locked.
|
* Mutext must not be locked.
|
||||||
|
@ -309,19 +309,19 @@ HttpdOutput::EncodeAndPlay(std::span<const std::byte> src)
|
|||||||
BroadcastFromEncoder();
|
BroadcastFromEncoder();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
HttpdOutput::Play(const void *chunk, size_t size)
|
HttpdOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
pause = false;
|
pause = false;
|
||||||
|
|
||||||
if (LockHasClients())
|
if (LockHasClients())
|
||||||
EncodeAndPlay({(const std::byte *)chunk, size});
|
EncodeAndPlay(src);
|
||||||
|
|
||||||
if (!timer->IsStarted())
|
if (!timer->IsStarted())
|
||||||
timer->Start();
|
timer->Start();
|
||||||
timer->Add(size);
|
timer->Add(src.size());
|
||||||
|
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -330,8 +330,8 @@ HttpdOutput::Pause()
|
|||||||
pause = true;
|
pause = true;
|
||||||
|
|
||||||
if (LockHasClients()) {
|
if (LockHasClients()) {
|
||||||
static const char silence[1020] = { 0 };
|
static constexpr std::byte silence[1020]{};
|
||||||
Play(silence, sizeof(silence));
|
Play(std::span{silence});
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -99,7 +99,7 @@ private:
|
|||||||
: std::chrono::steady_clock::duration::zero();
|
: std::chrono::steady_clock::duration::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
|
|
||||||
void Drain() override;
|
void Drain() override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
@ -333,8 +333,8 @@ SlesOutput::Close() noexcept
|
|||||||
engine_object.Destroy();
|
engine_object.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
SlesOutput::Play(const void *chunk, size_t size)
|
SlesOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
cancel = false;
|
cancel = false;
|
||||||
|
|
||||||
@ -356,8 +356,8 @@ SlesOutput::Play(const void *chunk, size_t size)
|
|||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
|
|
||||||
size_t nbytes = std::min(BUFFER_SIZE - filled, size);
|
size_t nbytes = std::min(BUFFER_SIZE - filled, src.size());
|
||||||
memcpy(buffers[next] + filled, chunk, nbytes);
|
memcpy(buffers[next] + filled, src.data(), nbytes);
|
||||||
filled += nbytes;
|
filled += nbytes;
|
||||||
if (filled < BUFFER_SIZE)
|
if (filled < BUFFER_SIZE)
|
||||||
return nbytes;
|
return nbytes;
|
||||||
|
@ -183,7 +183,7 @@ public:
|
|||||||
|
|
||||||
void SendTag(const Tag &tag) override;
|
void SendTag(const Tag &tag) override;
|
||||||
|
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
|
|
||||||
void Drain() override;
|
void Drain() override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
|
@ -297,8 +297,8 @@ SnapcastOutput::SendTag(const Tag &tag)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
SnapcastOutput::Play(const void *chunk, size_t size)
|
SnapcastOutput::Play(std::span<const std::byte> src)
|
||||||
{
|
{
|
||||||
pause = false;
|
pause = false;
|
||||||
|
|
||||||
@ -306,13 +306,13 @@ SnapcastOutput::Play(const void *chunk, size_t size)
|
|||||||
|
|
||||||
if (!timer->IsStarted())
|
if (!timer->IsStarted())
|
||||||
timer->Start();
|
timer->Start();
|
||||||
timer->Add(size);
|
timer->Add(src.size());
|
||||||
|
|
||||||
if (!LockHasClients())
|
if (!LockHasClients())
|
||||||
return size;
|
return src.size();
|
||||||
|
|
||||||
encoder->Write({(const std::byte *)chunk, size});
|
encoder->Write(src);
|
||||||
unflushed_input += size;
|
unflushed_input += src.size();
|
||||||
|
|
||||||
if (unflushed_input >= 65536) {
|
if (unflushed_input >= 65536) {
|
||||||
/* we have fed a lot of input into the encoder, but it
|
/* we have fed a lot of input into the encoder, but it
|
||||||
@ -343,7 +343,7 @@ SnapcastOutput::Play(const void *chunk, size_t size)
|
|||||||
chunks.push(std::make_shared<SnapcastChunk>(now, AllocatedArray{payload}));
|
chunks.push(std::make_shared<SnapcastChunk>(now, AllocatedArray{payload}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return src.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -357,7 +357,7 @@ public:
|
|||||||
}
|
}
|
||||||
void Close() noexcept override;
|
void Close() noexcept override;
|
||||||
std::chrono::steady_clock::duration Delay() const noexcept override;
|
std::chrono::steady_clock::duration Delay() const noexcept override;
|
||||||
size_t Play(const void *chunk, size_t size) override;
|
std::size_t Play(std::span<const std::byte> src) override;
|
||||||
void Drain() override;
|
void Drain() override;
|
||||||
void Cancel() noexcept override;
|
void Cancel() noexcept override;
|
||||||
bool Pause() override;
|
bool Pause() override;
|
||||||
@ -707,8 +707,8 @@ WasapiOutput::Delay() const noexcept
|
|||||||
return std::chrono::steady_clock::duration::zero();
|
return std::chrono::steady_clock::duration::zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
WasapiOutput::Play(const void *chunk, size_t size)
|
WasapiOutput::Play(std::span<const std::byte> input)
|
||||||
{
|
{
|
||||||
assert(thread);
|
assert(thread);
|
||||||
|
|
||||||
@ -716,12 +716,11 @@ WasapiOutput::Play(const void *chunk, size_t size)
|
|||||||
|
|
||||||
not_interrupted.test_and_set();
|
not_interrupted.test_and_set();
|
||||||
|
|
||||||
std::span<const std::byte> input{(const std::byte*)chunk, size};
|
|
||||||
if (pcm_export) {
|
if (pcm_export) {
|
||||||
input = pcm_export->Export(input);
|
input = pcm_export->Export(input);
|
||||||
}
|
}
|
||||||
if (input.empty())
|
if (input.empty())
|
||||||
return size;
|
return input.size();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
const size_t consumed_size = thread->Push(input);
|
const size_t consumed_size = thread->Push(input);
|
||||||
|
@ -155,7 +155,7 @@ RunOutput(AudioOutput &ao, AudioFormat audio_format,
|
|||||||
if (src.empty())
|
if (src.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
size_t consumed = ao.Play(src.data(), src.size());
|
size_t consumed = ao.Play(src);
|
||||||
|
|
||||||
assert(consumed <= src.size());
|
assert(consumed <= src.size());
|
||||||
assert(consumed % in_frame_size == 0);
|
assert(consumed % in_frame_size == 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user