output/oss: always enable PcmExport for alsa_channel_order

We need this even when AFMT_S24_PACKED is not available, for the
correct channel order in multi-channel files.  Internally, MPD uses
FLAC channel order, but OSS uses the same channel order as ALSA.
This commit is contained in:
Max Kellermann 2021-08-05 15:07:27 +02:00
parent bde64a13e2
commit 17b0ac75ca
2 changed files with 17 additions and 50 deletions

2
NEWS
View File

@ -8,6 +8,8 @@ ver 0.22.10 (not yet released)
- tidal: remove defunct unmaintained plugin - tidal: remove defunct unmaintained plugin
* tags * tags
- fix crash caused by bug in TagBuilder and a few potential reference leaks - fix crash caused by bug in TagBuilder and a few potential reference leaks
* output
- oss: fix channel order of multi-channel files
ver 0.22.9 (2021/06/23) ver 0.22.9 (2021/06/23)
* database * database

View File

@ -20,11 +20,13 @@
#include "OssOutputPlugin.hxx" #include "OssOutputPlugin.hxx"
#include "../OutputAPI.hxx" #include "../OutputAPI.hxx"
#include "mixer/MixerList.hxx" #include "mixer/MixerList.hxx"
#include "pcm/Export.hxx"
#include "io/UniqueFileDescriptor.hxx" #include "io/UniqueFileDescriptor.hxx"
#include "system/Error.hxx" #include "system/Error.hxx"
#include "util/ConstBuffer.hxx" #include "util/ConstBuffer.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "util/ByteOrder.hxx" #include "util/ByteOrder.hxx"
#include "util/Manual.hxx"
#include "Log.hxx" #include "Log.hxx"
#include <cassert> #include <cassert>
@ -53,15 +55,8 @@
#undef AFMT_S24_NE #undef AFMT_S24_NE
#endif #endif
#ifdef AFMT_S24_PACKED
#include "pcm/Export.hxx"
#include "util/Manual.hxx"
#endif
class OssOutput final : AudioOutput { class OssOutput final : AudioOutput {
#ifdef AFMT_S24_PACKED
Manual<PcmExport> pcm_export; Manual<PcmExport> pcm_export;
#endif
FileDescriptor fd = FileDescriptor::Undefined(); FileDescriptor fd = FileDescriptor::Undefined();
const char *device; const char *device;
@ -78,11 +73,7 @@ class OssOutput final : AudioOutput {
*/ */
int oss_format; int oss_format;
#ifdef AFMT_S24_PACKED
static constexpr unsigned oss_flags = FLAG_ENABLE_DISABLE; static constexpr unsigned oss_flags = FLAG_ENABLE_DISABLE;
#else
static constexpr unsigned oss_flags = 0;
#endif
public: public:
explicit OssOutput(const char *_device=nullptr) explicit OssOutput(const char *_device=nullptr)
@ -92,7 +83,6 @@ public:
static AudioOutput *Create(EventLoop &event_loop, static AudioOutput *Create(EventLoop &event_loop,
const ConfigBlock &block); const ConfigBlock &block);
#ifdef AFMT_S24_PACKED
void Enable() override { void Enable() override {
pcm_export.Construct(); pcm_export.Construct();
} }
@ -100,7 +90,6 @@ public:
void Disable() noexcept override { void Disable() noexcept override {
pcm_export.Destruct(); pcm_export.Destruct();
} }
#endif
void Open(AudioFormat &audio_format) override; void Open(AudioFormat &audio_format) override;
@ -428,11 +417,8 @@ sample_format_from_oss(int format) noexcept
static bool static bool
oss_probe_sample_format(FileDescriptor fd, SampleFormat sample_format, oss_probe_sample_format(FileDescriptor fd, SampleFormat sample_format,
SampleFormat *sample_format_r, SampleFormat *sample_format_r,
int *oss_format_r int *oss_format_r,
#ifdef AFMT_S24_PACKED PcmExport &pcm_export)
, PcmExport &pcm_export
#endif
)
{ {
int oss_format = sample_format_to_oss(sample_format); int oss_format = sample_format_to_oss(sample_format);
if (oss_format == AFMT_QUERY) if (oss_format == AFMT_QUERY)
@ -464,15 +450,15 @@ oss_probe_sample_format(FileDescriptor fd, SampleFormat sample_format,
*sample_format_r = sample_format; *sample_format_r = sample_format;
*oss_format_r = oss_format; *oss_format_r = oss_format;
#ifdef AFMT_S24_PACKED
PcmExport::Params params; PcmExport::Params params;
params.alsa_channel_order = true; params.alsa_channel_order = true;
#ifdef AFMT_S24_PACKED
params.pack24 = oss_format == AFMT_S24_PACKED; params.pack24 = oss_format == AFMT_S24_PACKED;
params.reverse_endian = oss_format == AFMT_S24_PACKED && params.reverse_endian = oss_format == AFMT_S24_PACKED &&
!IsLittleEndian(); !IsLittleEndian();
#endif
pcm_export.Open(sample_format, 0, params); pcm_export.Open(sample_format, 0, params);
#endif
return true; return true;
} }
@ -483,19 +469,13 @@ oss_probe_sample_format(FileDescriptor fd, SampleFormat sample_format,
*/ */
static void static void
oss_setup_sample_format(FileDescriptor fd, AudioFormat &audio_format, oss_setup_sample_format(FileDescriptor fd, AudioFormat &audio_format,
int *oss_format_r int *oss_format_r,
#ifdef AFMT_S24_PACKED PcmExport &pcm_export)
, PcmExport &pcm_export
#endif
)
{ {
SampleFormat mpd_format; SampleFormat mpd_format;
if (oss_probe_sample_format(fd, audio_format.format, if (oss_probe_sample_format(fd, audio_format.format,
&mpd_format, oss_format_r &mpd_format, oss_format_r,
#ifdef AFMT_S24_PACKED pcm_export)) {
, pcm_export
#endif
)) {
audio_format.format = mpd_format; audio_format.format = mpd_format;
return; return;
} }
@ -518,11 +498,8 @@ oss_setup_sample_format(FileDescriptor fd, AudioFormat &audio_format,
continue; continue;
if (oss_probe_sample_format(fd, mpd_format, if (oss_probe_sample_format(fd, mpd_format,
&mpd_format, oss_format_r &mpd_format, oss_format_r,
#ifdef AFMT_S24_PACKED pcm_export)) {
, pcm_export
#endif
)) {
audio_format.format = mpd_format; audio_format.format = mpd_format;
return; return;
} }
@ -536,11 +513,7 @@ OssOutput::Setup(AudioFormat &_audio_format)
{ {
oss_setup_channels(fd, _audio_format); oss_setup_channels(fd, _audio_format);
oss_setup_sample_rate(fd, _audio_format); oss_setup_sample_rate(fd, _audio_format);
oss_setup_sample_format(fd, _audio_format, &oss_format oss_setup_sample_format(fd, _audio_format, &oss_format, pcm_export);
#ifdef AFMT_S24_PACKED
, pcm_export
#endif
);
} }
/** /**
@ -595,9 +568,7 @@ OssOutput::Cancel() noexcept
DoClose(); DoClose();
} }
#ifdef AFMT_S24_PACKED
pcm_export->Reset(); pcm_export->Reset();
#endif
} }
size_t size_t
@ -611,23 +582,17 @@ OssOutput::Play(const void *chunk, size_t size)
if (!fd.IsDefined()) if (!fd.IsDefined())
Reopen(); Reopen();
#ifdef AFMT_S24_PACKED
const auto e = pcm_export->Export({chunk, size}); const auto e = pcm_export->Export({chunk, size});
if (e.empty()) if (e.empty())
return size; return size;
chunk = e.data; chunk = e.data;
size = e.size; size = e.size;
#endif
while (true) { while (true) {
ret = fd.Write(chunk, size); ret = fd.Write(chunk, size);
if (ret > 0) { if (ret > 0)
#ifdef AFMT_S24_PACKED return pcm_export->CalcInputSize(ret);
ret = pcm_export->CalcInputSize(ret);
#endif
return ret;
}
if (ret < 0 && errno != EINTR) if (ret < 0 && errno != EINTR)
throw FormatErrno("Write error on %s", device); throw FormatErrno("Write error on %s", device);