From edad4fc29b6da0202d6be4daf63dbcf825d85212 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 10 Oct 2014 18:27:21 +0200 Subject: audio: change internal device listing API Now we run ao_driver->list_devs on a dummy AO instance, which will probably confuse everyone. This is done for the sake of PulseAudio. --- audio/out/ao.c | 54 ++++++++++++++++++++++++++++++++++------------------ audio/out/ao.h | 8 ++++---- audio/out/ao_alsa.c | 4 ++-- audio/out/internal.h | 14 ++++++++++++-- 4 files changed, 53 insertions(+), 27 deletions(-) (limited to 'audio/out') diff --git a/audio/out/ao.c b/audio/out/ao.c index 4da77c6356..5f85f516f5 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -152,11 +152,8 @@ static bool match_ao_driver(const char *ao_name, char *opt, char **out_device) return true; } -static struct ao *ao_create(bool probing, struct mpv_global *global, - struct input_ctx *input_ctx, - struct encode_lavc_context *encode_lavc_ctx, - int samplerate, int format, struct mp_chmap channels, - char *name, char **args) +static struct ao *ao_alloc(bool probing, struct mpv_global *global, + struct input_ctx *input_ctx, char *name, char **args) { struct MPOpts *opts = global->opts; struct mp_log *log = mp_log_new(NULL, global->log, "ao"); @@ -171,22 +168,36 @@ static struct ao *ao_create(bool probing, struct mpv_global *global, *ao = (struct ao) { .driver = desc.p, .probing = probing, - .encode_lavc_ctx = encode_lavc_ctx, .input_ctx = input_ctx, - .samplerate = samplerate, - .channels = channels, - .format = format, .log = mp_log_new(ao, log, name), .def_buffer = opts->audio_buffer, }; - if (ao->driver->encode != !!ao->encode_lavc_ctx) - goto error; struct m_config *config = m_config_from_obj_desc(ao, ao->log, &desc); if (m_config_apply_defaults(config, name, opts->ao_defs) < 0) goto error; if (m_config_set_obj_params(config, args) < 0) goto error; ao->priv = config->optstruct; + return ao; +error: + talloc_free(ao); + return NULL; +} + +static struct ao *ao_create(bool probing, struct mpv_global *global, + struct input_ctx *input_ctx, + struct encode_lavc_context *encode_lavc_ctx, + int samplerate, int format, struct mp_chmap channels, + char *name, char **args) +{ + struct MPOpts *opts = global->opts; + struct ao *ao = ao_alloc(probing, global, input_ctx, name, args); + ao->samplerate = samplerate; + ao->channels = channels; + ao->format = format; + ao->encode_lavc_ctx = encode_lavc_ctx; + if (ao->driver->encode != !!ao->encode_lavc_ctx) + goto error; match_ao_driver(ao->driver->name, opts->audio_device, &ao->device); ao->device = talloc_strdup(ao, ao->device); @@ -388,34 +399,39 @@ bool ao_untimed(struct ao *ao) return ao->untimed; } -struct ao_device_list *ao_get_device_list(void) +struct ao_device_list *ao_get_device_list(struct mpv_global *global) { struct ao_device_list *list = talloc_zero(NULL, struct ao_device_list); for (int n = 0; audio_out_drivers[n]; n++) { const struct ao_driver *d = audio_out_drivers[n]; + struct ao *ao = ao_alloc(true, global, NULL, (char *)d->name, NULL); + if (!ao) + continue; int num = list->num_devices; if (d->list_devs) - d->list_devs(d, list); + d->list_devs(ao, list); // Add at least a default entry if (list->num_devices == num) - ao_device_list_add(list, d, &(struct ao_device_desc){"", ""}); + ao_device_list_add(list, ao, &(struct ao_device_desc){"", ""}); + talloc_free(ao); } return list; } -void ao_device_list_add(struct ao_device_list *list, const struct ao_driver *d, +void ao_device_list_add(struct ao_device_list *list, struct ao *ao, struct ao_device_desc *e) { struct ao_device_desc c = *e; - c.name = c.name[0] ? talloc_asprintf(list, "%s/%s", d->name, c.name) - : talloc_strdup(list, d->name); + const char *dname = ao->driver->name; + c.name = c.name[0] ? talloc_asprintf(list, "%s/%s", dname, c.name) + : talloc_strdup(list, dname); c.desc = talloc_strdup(list, c.desc); MP_TARRAY_APPEND(list, list->devices, list->num_devices, c); } -void ao_print_devices(struct mp_log *log) +void ao_print_devices(struct mpv_global *global, struct mp_log *log) { - struct ao_device_list *list = ao_get_device_list(); + struct ao_device_list *list = ao_get_device_list(global); 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]; diff --git a/audio/out/ao.h b/audio/out/ao.h index 32b6611afc..3d811fe8d3 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -52,8 +52,8 @@ typedef struct ao_control_vol { } ao_control_vol_t; struct ao_device_desc { - char *name; // symbolic name; will be set on ao->device - char *desc; // verbose human readable name + const char *name; // symbolic name; will be set on ao->device + const char *desc; // verbose human readable name }; struct ao_device_list { @@ -86,7 +86,7 @@ void ao_resume(struct ao *ao); void ao_drain(struct ao *ao); bool ao_eof_reached(struct ao *ao); -struct ao_device_list *ao_get_device_list(void); -void ao_print_devices(struct mp_log *log); +struct ao_device_list *ao_get_device_list(struct mpv_global *global); +void ao_print_devices(struct mpv_global *global, struct mp_log *log); #endif /* MPLAYER_AUDIO_OUT_H */ diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index 1b0703cea6..fb3cef75d4 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -733,7 +733,7 @@ alsa_error: return -1; } -static void list_devs(const struct ao_driver *d, struct ao_device_list *list) +static void list_devs(struct ao *ao, struct ao_device_list *list) { void **hints; if (snd_device_name_hint(-1, "pcm", &hints) < 0) @@ -751,7 +751,7 @@ static void list_devs(const struct ao_driver *d, struct ao_device_list *list) if (desc2[i] == '\n') desc2[i] = '/'; } - ao_device_list_add(list, d, &(struct ao_device_desc){name, desc2}); + ao_device_list_add(list, ao, &(struct ao_device_desc){name, desc2}); } snd_device_name_free_hint(hints); diff --git a/audio/out/internal.h b/audio/out/internal.h index 4532ff2c0c..18120fb1d3 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -149,7 +149,16 @@ struct ao_driver { // Return the list of devices currently available in the system. Use // ao_device_list_add() to add entries. The selected device will be set as // ao->device (using ao_device_desc.name). - void (*list_devs)(const struct ao_driver *d, struct ao_device_list *list); + // Warning: the ao struct passed doesn't necessarily have ao_driver->init() + // called on it - in this case, ->uninit() won't be called either + // after this function. The idea is that list_devs can be called + // both when no audio or when audio is active. the latter can + // happen if the audio config change at runtime, and in this case + // we don't want to force a new connection to the audio server + // just to update the device list. For runtime updates, ->init() + // will have been called. In both cases, ao->priv is properly + // allocated. (Runtime updates are not used/supported yet.) + void (*list_devs)(struct ao *ao, struct ao_device_list *list); // For option parsing (see vo.h) int priv_size; @@ -172,7 +181,8 @@ bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s, struct mp_chmap *map, int num); // Add a deep copy of e to the list. -void ao_device_list_add(struct ao_device_list *list, const struct ao_driver *d, +// Call from ao_driver->list_devs callback only. +void ao_device_list_add(struct ao_device_list *list, struct ao *ao, struct ao_device_desc *e); #endif -- cgit v1.2.3