summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_pulse.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/out/ao_pulse.c')
-rw-r--r--audio/out/ao_pulse.c106
1 files changed, 80 insertions, 26 deletions
diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c
index 314ef778bd..15a2b8b0a1 100644
--- a/audio/out/ao_pulse.c
+++ b/audio/out/ao_pulse.c
@@ -143,6 +143,59 @@ static const struct format_map {
{AF_FORMAT_UNKNOWN, 0}
};
+static const int speaker_map[][2] = {
+ {PA_CHANNEL_POSITION_MONO, MP_SPEAKER_ID_FC},
+ {PA_CHANNEL_POSITION_FRONT_LEFT, MP_SPEAKER_ID_FL},
+ {PA_CHANNEL_POSITION_FRONT_RIGHT, MP_SPEAKER_ID_FR},
+ {PA_CHANNEL_POSITION_FRONT_CENTER, MP_SPEAKER_ID_FC},
+ {PA_CHANNEL_POSITION_REAR_CENTER, MP_SPEAKER_ID_BC},
+ {PA_CHANNEL_POSITION_REAR_LEFT, MP_SPEAKER_ID_BL},
+ {PA_CHANNEL_POSITION_REAR_RIGHT, MP_SPEAKER_ID_BR},
+ {PA_CHANNEL_POSITION_LFE, MP_SPEAKER_ID_LFE},
+ {PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, MP_SPEAKER_ID_FLC},
+ {PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, MP_SPEAKER_ID_FRC},
+ {PA_CHANNEL_POSITION_SIDE_LEFT, MP_SPEAKER_ID_SL},
+ {PA_CHANNEL_POSITION_SIDE_RIGHT, MP_SPEAKER_ID_SR},
+ {PA_CHANNEL_POSITION_TOP_CENTER, MP_SPEAKER_ID_TC},
+ {PA_CHANNEL_POSITION_TOP_FRONT_LEFT, MP_SPEAKER_ID_TFL},
+ {PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, MP_SPEAKER_ID_TFR},
+ {PA_CHANNEL_POSITION_TOP_FRONT_CENTER, MP_SPEAKER_ID_TFC},
+ {PA_CHANNEL_POSITION_TOP_REAR_LEFT, MP_SPEAKER_ID_TBL},
+ {PA_CHANNEL_POSITION_TOP_REAR_RIGHT, MP_SPEAKER_ID_TBR},
+ {PA_CHANNEL_POSITION_TOP_REAR_CENTER, MP_SPEAKER_ID_TBC},
+ {PA_CHANNEL_POSITION_INVALID, -1}
+};
+
+static bool chmap_pa_from_mp(pa_channel_map *dst, struct mp_chmap *src)
+{
+ if (src->num > PA_CHANNELS_MAX)
+ return false;
+ dst->channels = src->num;
+ for (int n = 0; n < src->num; n++) {
+ int mp_speaker = src->speaker[n];
+ int pa_speaker = PA_CHANNEL_POSITION_INVALID;
+ for (int i = 0; speaker_map[i][1] != -1; i++) {
+ if (speaker_map[i][1] == mp_speaker) {
+ pa_speaker = speaker_map[i][0];
+ break;
+ }
+ }
+ if (pa_speaker == PA_CHANNEL_POSITION_INVALID)
+ return false;
+ dst->map[n] = pa_speaker;
+ }
+ 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;
@@ -209,30 +262,6 @@ static int init(struct ao *ao, char *params)
priv->broken_pause = true;
}
- ss.channels = ao->channels;
- ss.rate = ao->samplerate;
-
- const struct format_map *fmt_map = format_maps;
- while (fmt_map->mp_format != ao->format) {
- if (fmt_map->mp_format == AF_FORMAT_UNKNOWN) {
- mp_msg(MSGT_AO, MSGL_V,
- "AO: [pulse] Unsupported format, using default\n");
- fmt_map = format_maps;
- break;
- }
- fmt_map++;
- }
- ao->format = fmt_map->mp_format;
- ss.format = fmt_map->pa_format;
-
- if (!pa_sample_spec_valid(&ss)) {
- mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Invalid sample spec\n");
- goto fail;
- }
-
- pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA);
- ao->bps = pa_bytes_per_second(&ss);
-
if (!(priv->mainloop = pa_threaded_mainloop_new())) {
mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to allocate main loop\n");
goto fail;
@@ -260,6 +289,32 @@ static int init(struct ao *ao, char *params)
if (pa_context_get_state(priv->context) != PA_CONTEXT_READY)
goto unlock_and_fail;
+ ss.channels = ao->channels.num;
+ ss.rate = ao->samplerate;
+
+ const struct format_map *fmt_map = format_maps;
+ while (fmt_map->mp_format != ao->format) {
+ if (fmt_map->mp_format == AF_FORMAT_UNKNOWN) {
+ mp_msg(MSGT_AO, MSGL_V,
+ "AO: [pulse] Unsupported format, using default\n");
+ fmt_map = format_maps;
+ break;
+ }
+ fmt_map++;
+ }
+ ao->format = fmt_map->mp_format;
+ ss.format = fmt_map->pa_format;
+
+ if (!pa_sample_spec_valid(&ss)) {
+ mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Invalid sample spec\n");
+ goto fail;
+ }
+
+ if (!select_chmap(ao, &map))
+ goto fail;
+
+ ao->bps = pa_bytes_per_second(&ss);
+
if (!(priv->stream = pa_stream_new(priv->context, "audio stream", &ss,
&map)))
goto unlock_and_fail;
@@ -495,7 +550,7 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
const ao_control_vol_t *vol = arg;
struct pa_cvolume volume;
- pa_cvolume_reset(&volume, ao->channels);
+ pa_cvolume_reset(&volume, ao->channels.num);
if (volume.channels != 2)
pa_cvolume_set(&volume, volume.channels, VOL_MP2PA(vol->left));
else {
@@ -533,7 +588,6 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
}
const struct ao_driver audio_out_pulse = {
- .is_new = true,
.info = &(const struct ao_info) {
"PulseAudio audio output",
"pulse",