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:
parent
bde64a13e2
commit
17b0ac75ca
2
NEWS
2
NEWS
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue