output/Interface: pass std::span to Play()

This commit is contained in:
Max Kellermann 2022-07-12 12:31:35 +02:00
parent f5d104e7af
commit 45071607aa
29 changed files with 138 additions and 141 deletions

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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 = {

View File

@ -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) {

View File

@ -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

View File

@ -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;

View File

@ -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 {

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -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

View File

@ -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 = {

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);