summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/chmap.h2
-rw-r--r--audio/out/ao_alsa.c53
-rw-r--r--audio/out/ao_coreaudio.c11
-rw-r--r--audio/out/ao_dsound.c18
-rw-r--r--audio/out/ao_jack.c16
-rw-r--r--audio/out/ao_lavc.c4
-rw-r--r--audio/out/ao_null.c6
-rw-r--r--audio/out/ao_openal.c10
-rw-r--r--audio/out/ao_oss.c8
-rw-r--r--audio/out/ao_pcm.c5
-rw-r--r--audio/out/ao_portaudio.c6
-rw-r--r--audio/out/ao_pulse.c21
-rw-r--r--audio/out/ao_rsound.c8
-rw-r--r--audio/out/ao_sdl.c14
14 files changed, 114 insertions, 68 deletions
diff --git a/audio/chmap.h b/audio/chmap.h
index 929283dfd5..1848c86efd 100644
--- a/audio/chmap.h
+++ b/audio/chmap.h
@@ -129,6 +129,4 @@ void mp_chmap_print_help(int msgt, int msgl);
#define mp_chmap_is_waveext mp_chmap_is_lavc
#define mp_chmap_reorder_to_waveext mp_chmap_reorder_to_lavc
-#define mp_chmap_reorder_to_alsa(x) mp_chmap_from_channels_alsa((x), (x)->num)
-
#endif
diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c
index 477caa51de..bb7a5cbb15 100644
--- a/audio/out/ao_alsa.c
+++ b/audio/out/ao_alsa.c
@@ -330,22 +330,35 @@ static const char *device_channel_layouts[][2] = {
{"surround41", "fl-fr-bl-br-lfe"},
{"surround51", "fl-fr-bl-br-fc-lfe"},
{"surround71", "fl-fr-bl-br-fc-lfe-sl-sr"},
- {0}
};
-// Find a device that contains exactly all the requested speakers.
-// Set *request to the required channel order.
-static const char *find_device(struct mp_chmap *request)
+#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
+
+#define NUM_ALSA_CHMAPS ARRAY_LEN(device_channel_layouts)
+
+static const char *select_chmap(struct ao *ao)
{
- for (int n = 0; device_channel_layouts[n][0]; n++) {
- struct mp_chmap map = {0};
- mp_chmap_from_str(&map, bstr0(device_channel_layouts[n][1]));
- if (mp_chmap_equals_reordered(&map, request)) {
- *request = map;
+ struct mp_chmap_sel sel = {0};
+ struct mp_chmap maps[NUM_ALSA_CHMAPS];
+ for (int n = 0; n < NUM_ALSA_CHMAPS; n++) {
+ mp_chmap_from_str(&maps[n], bstr0(device_channel_layouts[n][1]));
+ mp_chmap_sel_add_map(&sel, &maps[n]);
+ };
+
+ if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
+ return NULL;
+
+ for (int n = 0; n < NUM_ALSA_CHMAPS; n++) {
+ if (mp_chmap_equals(&ao->channels, &maps[n]))
return device_channel_layouts[n][0];
- }
}
- return NULL;
+
+ char *name = mp_chmap_to_str(&ao->channels);
+ mp_tmsg(MSGT_AO, MSGL_ERR,
+ "[AO_ALSA] channel layout %s (%d ch) not supported.\n",
+ name, ao->channels.num);
+ talloc_free(name);
+ return "default";
}
static int try_open_device(struct ao *ao, const char *device, int open_mode,
@@ -449,16 +462,7 @@ static int init(struct ao *ao, char *params)
"alsa-spdif-init: playing AC3/iec61937/iec958, %i channels\n",
ao->channels.num);
} else {
- device.str = find_device(&ao->channels);
- if (!device.str) {
- char *name = mp_chmap_to_str(&ao->channels);
- device.str = "default";
- mp_chmap_from_channels(&ao->channels, ao->channels.num);
- mp_tmsg(MSGT_AO, MSGL_ERR,
- "[AO_ALSA] channel layout %s (%d ch) not supported.\n",
- name, ao->channels.num);
- talloc_free(name);
- }
+ device.str = select_chmap(ao);
if (strcmp(device.str, "default") != 0 && ao->format == AF_FORMAT_FLOAT_NE)
{
// hack - use the converter plugin (why the heck?)
@@ -535,8 +539,11 @@ static int init(struct ao *ao, char *params)
(p->alsa, alsa_hwparams, &num_channels);
CHECK_ALSA_ERROR("Unable to set channels");
- if (num_channels != ao->channels.num)
- mp_chmap_from_channels(&ao->channels, num_channels);
+ if (num_channels != ao->channels.num) {
+ mp_tmsg(MSGT_AO, MSGL_ERR,
+ "[AO_ALSA] Couldn't get requested number of channels.\n");
+ mp_chmap_from_channels_alsa(&ao->channels, num_channels);
+ }
/* workaround for buggy rate plugin (should be fixed in ALSA 1.0.11)
prefer our own resampler, since that allows users to choose the resampler,
diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c
index a3c6907ed4..6a15690074 100644
--- a/audio/out/ao_coreaudio.c
+++ b/audio/out/ao_coreaudio.c
@@ -499,6 +499,11 @@ int device_id, display_help = 0;
// Save selected device id
ao->i_selected_dev = devid_def;
+ struct mp_chmap_sel chmap_sel = {0};
+ mp_chmap_sel_add_waveext(&chmap_sel);
+ if (!ao_chmap_sel_adjust(&ao_data, &ao_data.channels, &chmap_sel))
+ goto err_out;
+
// Build Description for the input format
inDesc.mSampleRate=rate;
inDesc.mFormatID=ao->b_supports_digital ? kAudioFormat60958AC3 : kAudioFormatLinearPCM;
@@ -605,8 +610,8 @@ int device_id, display_help = 0;
ao->chunk_size = maxFrames;//*inDesc.mBytesPerFrame;
ao_data.samplerate = inDesc.mSampleRate;
- mp_chmap_from_channels(&ao_data.channels, inDesc.mChannelsPerFrame);
- mp_chmap_reorder_to_waveext(&ao_data.channels);
+ if (!ao_chmap_sel_get_def(&ao_data, &chmap_sel, &ao_data.channels, inDesc.mChannelsPerFrame))
+ goto err_out2;
ao_data.bps = ao_data.samplerate * inDesc.mBytesPerFrame;
ao_data.outburst = ao->chunk_size;
ao_data.buffersize = ao_data.bps;
@@ -838,7 +843,7 @@ static int OpenSPDIF(void)
ao->chunk_size = ao->stream_format.mBytesPerPacket;
ao_data.samplerate = ao->stream_format.mSampleRate;
- // Applies default ordering; ok becazse AC3 data is always in mpv internal channel order
+ // Applies default ordering; ok because AC3 data is always in mpv internal channel order
mp_chmap_from_channels(&ao_data.channels, ao->stream_format.mChannelsPerFrame);
ao_data.bps = ao_data.samplerate * (ao->stream_format.mBytesPerPacket/ao->stream_format.mFramesPerPacket);
ao_data.outburst = ao->chunk_size;
diff --git a/audio/out/ao_dsound.c b/audio/out/ao_dsound.c
index b096dd28db..967084d3ae 100644
--- a/audio/out/ao_dsound.c
+++ b/audio/out/ao_dsound.c
@@ -390,18 +390,14 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
DSBUFFERDESC dsbpridesc;
DSBUFFERDESC dsbdesc;
- //check if the channel count and format is supported in general
- if (ao_data.channels.num > 8) {
- // More than 8 channels might just work, but needs testing
- UninitDirectSound();
- mp_msg(MSGT_AO, MSGL_ERR, "ao_dsound: > 8 channel audio not yet supported\n");
- return 0;
- }
-
- if (AF_FORMAT_IS_AC3(format))
+ if (AF_FORMAT_IS_AC3(format)) {
format = AF_FORMAT_AC3_NE;
- else
- mp_chmap_reorder_to_waveext(&ao_data.channels);
+ } else {
+ struct mp_chmap_sel sel = {0};
+ mp_chmap_sel_add_waveext(&sel);
+ if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
+ return 0;
+ }
switch(format){
case AF_FORMAT_AC3_NE:
case AF_FORMAT_S24_LE:
diff --git a/audio/out/ao_jack.c b/audio/out/ao_jack.c
index aea64ee02c..0f8baeab86 100644
--- a/audio/out/ao_jack.c
+++ b/audio/out/ao_jack.c
@@ -50,7 +50,7 @@ static const ao_info_t info =
LIBAO_EXTERN(jack)
//! maximum number of channels supported, avoids lots of mallocs
-#define MAX_CHANS 8
+#define MAX_CHANS MP_NUM_CHANNELS
static jack_port_t *ports[MAX_CHANS];
static int num_ports; ///< Number of used ports == number of channels
static jack_client_t *client;
@@ -223,11 +223,12 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
print_help();
return 0;
}
- if (ao_data.channels.num > MAX_CHANS) {
- mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] Invalid number of channels: %i\n",
- ao_data.channels.num);
+
+ struct mp_chmap_sel sel = {0};
+ mp_chmap_sel_add_waveext(&sel);
+ if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
goto err_out;
- }
+
if (!client_name) {
client_name = malloc(40);
sprintf(client_name, "mpv [%d]", getpid());
@@ -283,8 +284,9 @@ static int init(int rate, const struct mp_chmap *channels, int format, int flags
/ (float)rate;
callback_interval = 0;
- mp_chmap_from_channels(&ao_data.channels, num_ports);
- mp_chmap_reorder_to_alsa(&ao_data.channels); // what order does hack use?
+ if (!ao_chmap_sel_get_def(&ao_data, &sel, &ao_data.channels, num_ports))
+ goto err_out;
+
ao_data.samplerate = rate;
ao_data.format = AF_FORMAT_FLOAT_NE;
ao_data.bps = ao_data.channels.num * rate * sizeof(float);
diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c
index ffe7d25415..0fda9a2b3a 100644
--- a/audio/out/ao_lavc.c
+++ b/audio/out/ao_lavc.c
@@ -102,6 +102,10 @@ static int init(struct ao *ao, char *params)
ac->stream->codec->sample_rate = ao->samplerate;
+ struct mp_chmap_sel sel = {0};
+ mp_chmap_sel_add_any(&sel);
+ if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
+ return -1;
mp_chmap_reorder_to_lavc(&ao->channels);
ac->stream->codec->channels = ao->channels.num;
ac->stream->codec->channel_layout = mp_chmap_to_lavc(&ao->channels);
diff --git a/audio/out/ao_null.c b/audio/out/ao_null.c
index c4288cffda..53ec2a9a83 100644
--- a/audio/out/ao_null.c
+++ b/audio/out/ao_null.c
@@ -48,6 +48,12 @@ static int init(struct ao *ao, char *params)
{
struct priv *priv = talloc_zero(ao, struct priv);
ao->priv = priv;
+
+ struct mp_chmap_sel sel = {0};
+ mp_chmap_sel_add_any(&sel);
+ if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
+ return -1;
+
int samplesize = af_fmt2bits(ao->format) / 8;
ao->outburst = 256 * ao->channels.num * samplesize;
// A "buffer" for about 0.2 seconds of audio
diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c
index 4c906802e1..08f8bc1978 100644
--- a/audio/out/ao_openal.c
+++ b/audio/out/ao_openal.c
@@ -53,7 +53,7 @@ static const ao_info_t info =
LIBAO_EXTERN(openal)
-#define MAX_CHANS 8
+#define MAX_CHANS MP_NUM_CHANNELS
#define NUM_BUF 128
#define CHUNK_SIZE 512
static ALuint buffers[MAX_CHANS][NUM_BUF];
@@ -151,11 +151,11 @@ static int init(int rate, const struct mp_chmap *channels, int format,
list_devices();
goto err_out;
}
- if (ao_data.channels.num > MAX_CHANS) {
- mp_msg(MSGT_AO, MSGL_FATAL, "[OpenAL] Invalid number of channels: %i\n",
- ao_data.channels.num);
+ struct mp_chmap_sel sel = {0};
+ for (i = 0; speaker_pos[i].id != -1; i++)
+ mp_chmap_sel_add_speaker(&sel, speaker_pos[i].id);
+ if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
goto err_out;
- }
struct speaker speakers[MAX_CHANS];
for (i = 0; i < ao_data.channels.num; i++) {
speakers[i].id = -1;
diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c
index 805a14cd8f..4ff97b30b6 100644
--- a/audio/out/ao_oss.c
+++ b/audio/out/ao_oss.c
@@ -340,7 +340,10 @@ ac3_retry:
af_fmt2str_short(ao_data.format), af_fmt2str_short(format));
if(!AF_FORMAT_IS_AC3(format)) {
- mp_chmap_reorder_to_alsa(&ao_data.channels);
+ struct mp_chmap_sel sel = {0};
+ mp_chmap_sel_add_alsa_def(&sel);
+ if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels))
+ return 0;
int reqchannels = ao_data.channels.num;
// We only use SNDCTL_DSP_CHANNELS for >2 channels, in case some drivers don't have it
if (reqchannels > 2) {
@@ -357,7 +360,8 @@ ac3_retry:
mp_tmsg(MSGT_AO,MSGL_ERR,"[AO OSS] audio_setup: Failed to set audio device to %d channels.\n", reqchannels);
return 0;
}
- mp_chmap_from_channels(&ao_data.channels, c + 1);
+ if (!ao_chmap_sel_get_def(&ao_data, &sel, &ao_data.channels, c + 1))
+ return 0;
}
mp_msg(MSGT_AO,MSGL_V,"audio_setup: using %d channels (requested: %d)\n", ao_data.channels.num, reqchannels);
// set rate
diff --git a/audio/out/ao_pcm.c b/audio/out/ao_pcm.c
index 1199ab5a90..903e89bc8b 100644
--- a/audio/out/ao_pcm.c
+++ b/audio/out/ao_pcm.c
@@ -146,7 +146,10 @@ static int init(struct ao *ao, char *params)
}
}
- mp_chmap_reorder_to_waveext(&ao->channels);
+ struct mp_chmap_sel sel = {0};
+ mp_chmap_sel_add_waveext(&sel);
+ if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
+ return -1;
ao->outburst = 65536;
ao->bps = ao->channels.num * ao->samplerate * (af_fmt2bits(ao->format) / 8);
diff --git a/audio/out/ao_portaudio.c b/audio/out/ao_portaudio.c
index 382523d08e..f84447bdb4 100644
--- a/audio/out/ao_portaudio.c
+++ b/audio/out/ao_portaudio.c
@@ -273,7 +273,11 @@ static int init(struct ao *ao, char *params)
if (pa_device == paNoDevice)
goto error_exit;
- mp_chmap_reorder_to_alsa(&ao->channels);
+ // The actual channel order probably depends on the platform.
+ struct mp_chmap_sel sel = {0};
+ mp_chmap_sel_add_waveext_def(&sel);
+ if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
+ goto error_exit;
PaStreamParameters sp = {
.device = pa_device,
diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c
index 9422fa319d..15a2b8b0a1 100644
--- a/audio/out/ao_pulse.c
+++ b/audio/out/ao_pulse.c
@@ -187,6 +187,15 @@ static bool chmap_pa_from_mp(pa_channel_map *dst, struct mp_chmap *src)
return true;
}
+static bool select_chmap(struct ao *ao, pa_channel_map *dst)
+{
+ struct mp_chmap_sel sel = {0};
+ for (int n = 0; speaker_map[n][1] != -1; n++)
+ mp_chmap_sel_add_speaker(&sel, speaker_map[n][1]);
+ return ao_chmap_sel_adjust(ao, &sel, &ao->channels) &&
+ chmap_pa_from_mp(dst, &ao->channels);
+}
+
static void uninit(struct ao *ao, bool cut_audio)
{
struct priv *priv = ao->priv;
@@ -301,16 +310,8 @@ static int init(struct ao *ao, char *params)
goto fail;
}
- if (!chmap_pa_from_mp(&map, &ao->channels)) {
- char *name = mp_chmap_to_str(&ao->channels);
- mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Can't map %s channel layout\n",
- name);
- talloc_free(name);
- // Not a really good fallback, since this doesn't trigger if the
- // channel map is valid, but unsupported by the output device.
- ao->channels = (struct mp_chmap) MP_CHMAP_INIT_STEREO;
- pa_channel_map_init_stereo(&map);
- }
+ if (!select_chmap(ao, &map))
+ goto fail;
ao->bps = pa_bytes_per_second(&ss);
diff --git a/audio/out/ao_rsound.c b/audio/out/ao_rsound.c
index 80dfa4dc2b..78ea2c63f5 100644
--- a/audio/out/ao_rsound.c
+++ b/audio/out/ao_rsound.c
@@ -121,7 +121,13 @@ static int init(struct ao *ao, char *params)
free(port);
}
- mp_chmap_reorder_to_alsa(&ao->channels);
+ // Actual channel layout unknown.
+ struct mp_chmap_sel sel = {0};
+ mp_chmap_sel_add_waveext_def(&sel);
+ if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) {
+ rsd_free(priv->rd);
+ return -1;
+ }
rsd_set_param(priv->rd, RSD_SAMPLERATE, &ao->samplerate);
rsd_set_param(priv->rd, RSD_CHANNELS, &ao->channels.num);
diff --git a/audio/out/ao_sdl.c b/audio/out/ao_sdl.c
index 4235a7c26c..6678cd3bd3 100644
--- a/audio/out/ao_sdl.c
+++ b/audio/out/ao_sdl.c
@@ -160,6 +160,13 @@ static int init(struct ao *ao, char *params)
return -1;
}
+ struct mp_chmap_sel sel = {0};
+ mp_chmap_sel_add_waveext_def(&sel);
+ if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) {
+ uninit(ao, true);
+ return -1;
+ }
+
SDL_AudioSpec desired, obtained;
int bytes = 0;
@@ -236,9 +243,12 @@ static int init(struct ao *ao, char *params)
return -1;
}
+ if (!ao_chmap_sel_get_def(ao, &sel, &ao->channels, obtained.channels)) {
+ uninit(ao, true);
+ return -1;
+ }
+
ao->samplerate = obtained.freq;
- mp_chmap_from_channels(&ao->channels, obtained.channels);
- mp_chmap_reorder_to_alsa(&ao->channels);
ao->bps = ao->channels.num * ao->samplerate * bytes;
ao->buffersize = obtained.size * bufcnt;
ao->outburst = obtained.size;