output/pipewire: DSD support
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1297
This commit is contained in:
parent
78257408b4
commit
32851d1bc7
1
NEWS
1
NEWS
@ -3,6 +3,7 @@ ver 0.23.2 (not yet released)
|
|||||||
- nfs: fix playback bug
|
- nfs: fix playback bug
|
||||||
* output
|
* output
|
||||||
- pipewire: send artist and title to PipeWire
|
- pipewire: send artist and title to PipeWire
|
||||||
|
- pipewire: DSD support
|
||||||
* neighbor
|
* neighbor
|
||||||
- mention failed plugin name in error message
|
- mention failed plugin name in error message
|
||||||
* fix crash with libfmt versions older than 7
|
* fix crash with libfmt versions older than 7
|
||||||
|
@ -1094,6 +1094,8 @@ Connect to a `PipeWire <https://pipewire.org/>`_ server. Requires
|
|||||||
* - **remote NAME**
|
* - **remote NAME**
|
||||||
- The name of the remote to connect to. The default is
|
- The name of the remote to connect to. The default is
|
||||||
``pipewire-0``.
|
``pipewire-0``.
|
||||||
|
* - **dsd yes|no**
|
||||||
|
- Enable DSD playback. This requires PipeWire 0.38.
|
||||||
|
|
||||||
.. _pulse_plugin:
|
.. _pulse_plugin:
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "util/WritableBuffer.hxx"
|
#include "util/WritableBuffer.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "tag/Format.hxx"
|
#include "tag/Format.hxx"
|
||||||
|
#include "config.h" // for ENABLE_DSD
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
@ -91,6 +92,10 @@ class PipeWireOutput final : AudioOutput {
|
|||||||
*/
|
*/
|
||||||
SampleFormat sample_format;
|
SampleFormat sample_format;
|
||||||
|
|
||||||
|
#if defined(ENABLE_DSD) && defined(SPA_AUDIO_DSD_FLAG_NONE)
|
||||||
|
const bool enable_dsd;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool disconnected;
|
bool disconnected;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -262,6 +267,9 @@ PipeWireOutput::PipeWireOutput(const ConfigBlock &block)
|
|||||||
name(block.GetBlockValue("name", "pipewire")),
|
name(block.GetBlockValue("name", "pipewire")),
|
||||||
remote(block.GetBlockValue("remote", nullptr)),
|
remote(block.GetBlockValue("remote", nullptr)),
|
||||||
target(block.GetBlockValue("target", 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 (target != nullptr) {
|
||||||
if (StringIsEmpty(target))
|
if (StringIsEmpty(target))
|
||||||
@ -477,6 +485,13 @@ PipeWireOutput::Open(AudioFormat &audio_format)
|
|||||||
if (stream == nullptr)
|
if (stream == nullptr)
|
||||||
throw MakeErrno("pw_stream_new_simple() failed");
|
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);
|
auto raw = ToPipeWireAudioFormat(audio_format);
|
||||||
|
|
||||||
frame_size = audio_format.GetFrameSize();
|
frame_size = audio_format.GetFrameSize();
|
||||||
@ -494,8 +509,28 @@ PipeWireOutput::Open(AudioFormat &audio_format)
|
|||||||
pod_builder = {};
|
pod_builder = {};
|
||||||
pod_builder.data = buffer;
|
pod_builder.data = buffer;
|
||||||
pod_builder.size = sizeof(buffer);
|
pod_builder.size = sizeof(buffer);
|
||||||
|
|
||||||
|
#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,
|
params[0] = spa_format_audio_raw_build(&pod_builder,
|
||||||
SPA_PARAM_EnumFormat, &raw);
|
SPA_PARAM_EnumFormat,
|
||||||
|
&raw);
|
||||||
|
|
||||||
int error =
|
int error =
|
||||||
pw_stream_connect(stream,
|
pw_stream_connect(stream,
|
||||||
|
Loading…
Reference in New Issue
Block a user