output/pipewire: DSD support

Closes https://github.com/MusicPlayerDaemon/MPD/issues/1297
This commit is contained in:
Max Kellermann 2021-10-20 09:54:05 +02:00
parent 78257408b4
commit 32851d1bc7
3 changed files with 40 additions and 2 deletions

1
NEWS
View File

@ -3,6 +3,7 @@ ver 0.23.2 (not yet released)
- nfs: fix playback bug
* output
- pipewire: send artist and title to PipeWire
- pipewire: DSD support
* neighbor
- mention failed plugin name in error message
* fix crash with libfmt versions older than 7

View File

@ -1094,6 +1094,8 @@ Connect to a `PipeWire <https://pipewire.org/>`_ server. Requires
* - **remote NAME**
- The name of the remote to connect to. The default is
``pipewire-0``.
* - **dsd yes|no**
- Enable DSD playback. This requires PipeWire 0.38.
.. _pulse_plugin:

View File

@ -31,6 +31,7 @@
#include "util/WritableBuffer.hxx"
#include "Log.hxx"
#include "tag/Format.hxx"
#include "config.h" // for ENABLE_DSD
#ifdef __GNUC__
#pragma GCC diagnostic push
@ -91,6 +92,10 @@ class PipeWireOutput final : AudioOutput {
*/
SampleFormat sample_format;
#if defined(ENABLE_DSD) && defined(SPA_AUDIO_DSD_FLAG_NONE)
const bool enable_dsd;
#endif
bool disconnected;
/**
@ -262,6 +267,9 @@ PipeWireOutput::PipeWireOutput(const ConfigBlock &block)
name(block.GetBlockValue("name", "pipewire")),
remote(block.GetBlockValue("remote", nullptr)),
target(block.GetBlockValue("target", nullptr))
#if defined(ENABLE_DSD) && defined(SPA_AUDIO_DSD_FLAG_NONE)
, enable_dsd(block.GetBlockValue("dsd", false))
#endif
{
if (target != nullptr) {
if (StringIsEmpty(target))
@ -477,6 +485,13 @@ PipeWireOutput::Open(AudioFormat &audio_format)
if (stream == nullptr)
throw MakeErrno("pw_stream_new_simple() failed");
#if defined(ENABLE_DSD) && defined(SPA_AUDIO_DSD_FLAG_NONE)
/* this needs to be determined before ToPipeWireAudioFormat()
switches DSD to S16 */
const bool use_dsd = enable_dsd &&
audio_format.format == SampleFormat::DSD;
#endif
auto raw = ToPipeWireAudioFormat(audio_format);
frame_size = audio_format.GetFrameSize();
@ -494,8 +509,28 @@ PipeWireOutput::Open(AudioFormat &audio_format)
pod_builder = {};
pod_builder.data = buffer;
pod_builder.size = sizeof(buffer);
params[0] = spa_format_audio_raw_build(&pod_builder,
SPA_PARAM_EnumFormat, &raw);
#if defined(ENABLE_DSD) && defined(SPA_AUDIO_DSD_FLAG_NONE)
struct spa_audio_info_dsd dsd;
if (use_dsd) {
dsd = {};
/* copy all relevant settings from the
ToPipeWireAudioFormat() return value */
dsd.flags = raw.flags;
dsd.rate = raw.rate;
dsd.channels = raw.channels;
if ((dsd.flags & SPA_AUDIO_FLAG_UNPOSITIONED) == 0)
std::copy_n(raw.position, dsd.channels, dsd.position);
params[0] = spa_format_audio_dsd_build(&pod_builder,
SPA_PARAM_EnumFormat,
&dsd);
} else
#endif
params[0] = spa_format_audio_raw_build(&pod_builder,
SPA_PARAM_EnumFormat,
&raw);
int error =
pw_stream_connect(stream,