diff options
Diffstat (limited to 'audio/out/ao.c')
-rw-r--r-- | audio/out/ao.c | 63 |
1 files changed, 46 insertions, 17 deletions
diff --git a/audio/out/ao.c b/audio/out/ao.c index 7c347cb138..ee20b736a3 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -40,7 +40,10 @@ extern const struct ao_driver audio_out_audiotrack; extern const struct ao_driver audio_out_audiounit; extern const struct ao_driver audio_out_coreaudio; extern const struct ao_driver audio_out_coreaudio_exclusive; +extern const struct ao_driver audio_out_avfoundation; extern const struct ao_driver audio_out_rsound; +extern const struct ao_driver audio_out_pipewire; +extern const struct ao_driver audio_out_sndio; extern const struct ao_driver audio_out_pulse; extern const struct ao_driver audio_out_jack; extern const struct ao_driver audio_out_openal; @@ -63,6 +66,12 @@ static const struct ao_driver * const audio_out_drivers[] = { #if HAVE_COREAUDIO &audio_out_coreaudio, #endif +#if HAVE_AVFOUNDATION + &audio_out_avfoundation, +#endif +#if HAVE_PIPEWIRE + &audio_out_pipewire, +#endif #if HAVE_PULSE &audio_out_pulse, #endif @@ -88,18 +97,20 @@ static const struct ao_driver * const audio_out_drivers[] = { #if HAVE_SDL2_AUDIO &audio_out_sdl, #endif +#if HAVE_SNDIO + &audio_out_sndio, +#endif &audio_out_null, #if HAVE_COREAUDIO &audio_out_coreaudio_exclusive, #endif &audio_out_pcm, &audio_out_lavc, - NULL }; static bool get_desc(struct m_obj_desc *dst, int index) { - if (index >= MP_ARRAY_SIZE(audio_out_drivers) - 1) + if (index >= MP_ARRAY_SIZE(audio_out_drivers)) return false; const struct ao_driver *ao = audio_out_drivers[index]; *dst = (struct m_obj_desc) { @@ -120,7 +131,6 @@ static bool get_desc(struct m_obj_desc *dst, int index) static const struct m_obj_list ao_obj_list = { .get_desc = get_desc, .description = "audio outputs", - .allow_unknown_entries = true, .allow_trailer = true, .disallow_positional_parameters = true, .use_global_options = true, @@ -231,7 +241,7 @@ static struct ao *ao_init(bool probing, struct mpv_global *global, } else { ao->sstride *= ao->channels.num; } - ao->bps = ao->samplerate * ao->sstride; + ao->bps = (int64_t)ao->samplerate * ao->sstride; if (ao->device_buffer <= 0 && ao->driver->write) { MP_ERR(ao, "Device buffer size not set.\n"); @@ -306,7 +316,7 @@ struct ao *ao_init_best(struct mpv_global *global, } if (autoprobe) { - for (int n = 0; audio_out_drivers[n]; n++) { + for (int n = 0; n < MP_ARRAY_SIZE(audio_out_drivers); n++) { const struct ao_driver *driver = audio_out_drivers[n]; if (driver == &audio_out_null) break; @@ -446,8 +456,9 @@ struct ao_hotplug { void *wakeup_ctx; // A single AO instance is used to listen to hotplug events. It wouldn't // make much sense to allow multiple AO drivers; all sane platforms have - // a single such audio API. - // This is _not_ the same AO instance as used for playing audio. + // a single audio API providing all events. + // This is _not_ necessarily the same AO instance as used for playing + // audio. struct ao *ao; // cached struct ao_device_list *list; @@ -487,7 +498,8 @@ bool ao_hotplug_check_update(struct ao_hotplug *hp) } // The return value is valid until the next call to this API. -struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp) +struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp, + struct ao *playback_ao) { if (hp->list && !hp->needs_update) return hp->list; @@ -499,7 +511,20 @@ struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp) MP_TARRAY_APPEND(list, list->devices, list->num_devices, (struct ao_device_desc){"auto", "Autoselect device"}); - for (int n = 0; audio_out_drivers[n]; n++) { + // Try to use the same AO for hotplug handling as for playback. + // Different AOs may not agree and the playback one is the only one the + // user knows about and may even have configured explicitly. + if (!hp->ao && playback_ao && playback_ao->driver->hotplug_init) { + struct ao *ao = ao_alloc(true, hp->global, hp->wakeup_cb, hp->wakeup_ctx, + (char *)playback_ao->driver->name); + if (playback_ao->driver->hotplug_init(ao) >= 0) { + hp->ao = ao; + } else { + talloc_free(ao); + } + } + + for (int n = 0; n < MP_ARRAY_SIZE(audio_out_drivers); n++) { const struct ao_driver *d = audio_out_drivers[n]; if (d == &audio_out_null) break; // don't add unsafe/special entries @@ -510,10 +535,13 @@ struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp) continue; if (ao->driver->hotplug_init) { - if (!hp->ao && ao->driver->hotplug_init(ao) >= 0) - hp->ao = ao; // keep this one - if (hp->ao && hp->ao->driver == d) - get_devices(hp->ao, list); + if (ao->driver->hotplug_init(ao) >= 0) { + get_devices(ao, list); + if (hp->ao) + ao->driver->hotplug_uninit(ao); + else + hp->ao = ao; // keep this one + } } else { get_devices(ao, list); } @@ -562,10 +590,11 @@ static void dummy_wakeup(void *ctx) { } -void ao_print_devices(struct mpv_global *global, struct mp_log *log) +void ao_print_devices(struct mpv_global *global, struct mp_log *log, + struct ao *playback_ao) { struct ao_hotplug *hp = ao_hotplug_create(global, dummy_wakeup, NULL); - struct ao_device_list *list = ao_hotplug_get_device_list(hp); + struct ao_device_list *list = ao_hotplug_get_device_list(hp, playback_ao); mp_info(log, "List of detected audio devices:\n"); for (int n = 0; n < list->num_devices; n++) { struct ao_device_desc *desc = &list->devices[n]; @@ -587,7 +616,7 @@ void ao_set_gain(struct ao *ao, float gain) #define MUL_GAIN_f(d, num_samples, gain) \ for (int n = 0; n < (num_samples); n++) \ - (d)[n] = MPCLAMP(((d)[n]) * (gain), -1.0, 1.0) + (d)[n] = (d)[n] * (gain) static void process_plane(struct ao *ao, void *data, int num_samples) { @@ -676,7 +705,7 @@ static void convert_plane(int type, void *data, int num_samples) break; } default: - abort(); + MP_ASSERT_UNREACHABLE(); } } |