diff options
Diffstat (limited to 'libao2/audio_out.c')
-rw-r--r-- | libao2/audio_out.c | 166 |
1 files changed, 114 insertions, 52 deletions
diff --git a/libao2/audio_out.c b/libao2/audio_out.c index 3e37cfb70b..da471f0cc7 100644 --- a/libao2/audio_out.c +++ b/libao2/audio_out.c @@ -21,40 +21,42 @@ #include <string.h> #include <assert.h> +#include "talloc.h" + #include "config.h" #include "audio_out.h" #include "mp_msg.h" // there are some globals: -struct ao ao_data; +struct ao *global_ao; char *ao_subdevice = NULL; -extern const ao_functions_t audio_out_oss; -extern const ao_functions_t audio_out_coreaudio; -extern const ao_functions_t audio_out_arts; -extern const ao_functions_t audio_out_esd; -extern const ao_functions_t audio_out_pulse; -extern const ao_functions_t audio_out_jack; -extern const ao_functions_t audio_out_openal; -extern const ao_functions_t audio_out_null; -extern const ao_functions_t audio_out_alsa5; -extern const ao_functions_t audio_out_alsa; -extern const ao_functions_t audio_out_nas; -extern const ao_functions_t audio_out_sdl; -extern const ao_functions_t audio_out_sun; -extern const ao_functions_t audio_out_sgi; -extern const ao_functions_t audio_out_win32; -extern const ao_functions_t audio_out_dsound; -extern const ao_functions_t audio_out_kai; -extern const ao_functions_t audio_out_dart; -extern const ao_functions_t audio_out_ivtv; -extern const ao_functions_t audio_out_v4l2; -extern const ao_functions_t audio_out_mpegpes; -extern const ao_functions_t audio_out_pcm; -extern const ao_functions_t audio_out_pss; - -static const ao_functions_t *const audio_out_drivers[] = { +extern const struct ao_driver audio_out_oss; +extern const struct ao_driver audio_out_coreaudio; +extern const struct ao_driver audio_out_arts; +extern const struct ao_driver audio_out_esd; +extern const struct ao_driver audio_out_pulse; +extern const struct ao_driver audio_out_jack; +extern const struct ao_driver audio_out_openal; +extern const struct ao_driver audio_out_null; +extern const struct ao_driver audio_out_alsa5; +extern const struct ao_driver audio_out_alsa; +extern const struct ao_driver audio_out_nas; +extern const struct ao_driver audio_out_sdl; +extern const struct ao_driver audio_out_sun; +extern const struct ao_driver audio_out_sgi; +extern const struct ao_driver audio_out_win32; +extern const struct ao_driver audio_out_dsound; +extern const struct ao_driver audio_out_kai; +extern const struct ao_driver audio_out_dart; +extern const struct ao_driver audio_out_ivtv; +extern const struct ao_driver audio_out_v4l2; +extern const struct ao_driver audio_out_mpegpes; +extern const struct ao_driver audio_out_pcm; +extern const struct ao_driver audio_out_pss; + +static const struct ao_driver * const audio_out_drivers[] = { // native: #ifdef CONFIG_DIRECTX &audio_out_dsound, @@ -136,12 +138,17 @@ void list_audio_out(void) struct ao *ao_create(void) { - ao_data = (struct ao){.outburst = OUTBURST, .buffersize = -1}; - return &ao_data; + struct ao *r = talloc(NULL, struct ao); + *r = (struct ao){.outburst = OUTBURST, .buffersize = -1}; + return r; } void ao_init(struct ao *ao, char **ao_list) { + /* Caller adding child blocks is not supported as we may call + * talloc_free_children() to clean up after failed open attempts. + */ + assert(talloc_total_blocks(ao) == 1); struct ao backup = *ao; if (!ao_list) @@ -153,19 +160,18 @@ void ao_init(struct ao *ao, char **ao_list) if (!*ao_name) goto try_defaults; // empty entry means try defaults int ao_len; - assert(!ao_subdevice); - ao_subdevice = strchr(ao_name, ':'); - if (ao_subdevice) { - ao_len = ao_subdevice - ao_name; - ao_subdevice = strdup(ao_subdevice + 1); + char *params = strchr(ao_name, ':'); + if (params) { + ao_len = params - ao_name; + params++; } else ao_len = strlen(ao_name); mp_tmsg(MSGT_AO, MSGL_V, "Trying preferred audio driver '%.*s', options '%s'\n", - ao_len, ao_name, ao_subdevice ? ao_subdevice : "[none]"); + ao_len, ao_name, params ? params : "[none]"); - const ao_functions_t *audio_out = NULL; + const struct ao_driver *audio_out = NULL; for (int i = 0; audio_out_drivers[i]; i++) { audio_out = audio_out_drivers[i]; if (!strncmp(audio_out->info->short_name, ao_name, ao_len)) @@ -174,19 +180,19 @@ void ao_init(struct ao *ao, char **ao_list) } if (audio_out) { // name matches, try it - if (audio_out->init(ao->samplerate, ao->channels, ao->format, 0)) { + ao->driver = audio_out; + if (audio_out->init(ao, params) >= 0) { ao->driver = audio_out; ao->initialized = true; return; } mp_tmsg(MSGT_AO, MSGL_WARN, "Failed to initialize audio driver '%s'\n", ao_name); + talloc_free_children(ao); *ao = backup; } else mp_tmsg(MSGT_AO, MSGL_WARN, "No such audio driver '%.*s'\n", ao_len, ao_name); - free(ao_subdevice); - ao_subdevice = NULL; ++ao_list; } return; @@ -196,57 +202,113 @@ void ao_init(struct ao *ao, char **ao_list) // now try the rest... for (int i = 0; audio_out_drivers[i]; i++) { - const ao_functions_t *audio_out = audio_out_drivers[i]; - if (audio_out->init(ao->samplerate, ao->channels, ao->format, 0)) { + const struct ao_driver *audio_out = audio_out_drivers[i]; + ao->driver = audio_out; + if (audio_out->init(ao, NULL) >= 0) { ao->initialized = true; ao->driver = audio_out; return; } + talloc_free_children(ao); *ao = backup; } return; } -void ao_uninit(struct ao *ao, bool drain_audio) +void ao_uninit(struct ao *ao, bool cut_audio) { if (ao->initialized) - ao->driver->uninit(drain_audio); - ao->initialized = false; - free(ao_subdevice); - ao_subdevice = NULL; + ao->driver->uninit(ao, cut_audio); + talloc_free(ao); } int ao_play(struct ao *ao, void *data, int len, int flags) { - return ao->driver->play(data, len, flags); + return ao->driver->play(ao, data, len, flags); } int ao_control(struct ao *ao, int cmd, void *arg) { - return ao->driver->control(cmd, arg); + if (ao->driver->control) + return ao->driver->control(ao, cmd, arg); + return CONTROL_UNKNOWN; } double ao_get_delay(struct ao *ao) { - return ao->driver->get_delay(); + return ao->driver->get_delay(ao); } int ao_get_space(struct ao *ao) { - return ao->driver->get_space(); + return ao->driver->get_space(ao); } void ao_reset(struct ao *ao) { - ao->driver->reset(); + ao->driver->reset(ao); } void ao_pause(struct ao *ao) { - ao->driver->pause(); + ao->driver->pause(ao); } void ao_resume(struct ao *ao) { - ao->driver->resume(); + ao->driver->resume(ao); +} + + + +int old_ao_init(struct ao *ao, char *params) +{ + assert(!global_ao); + global_ao = ao; + ao_subdevice = params ? talloc_strdup(ao, params) : NULL; + if (ao->driver->old_functions->init(ao->samplerate, ao->channels, + ao->format, 0) == 0) + return -1; + return 0; +} + +void old_ao_uninit(struct ao *ao, bool cut_audio) +{ + ao->driver->old_functions->uninit(cut_audio); + global_ao = NULL; +} + +int old_ao_play(struct ao *ao, void *data, int len, int flags) +{ + return ao->driver->old_functions->play(data, len, flags); +} + +int old_ao_control(struct ao *ao, int cmd, void *arg) +{ + return ao->driver->old_functions->control(cmd, arg); +} + +float old_ao_get_delay(struct ao *ao) +{ + return ao->driver->old_functions->get_delay(); +} + +int old_ao_get_space(struct ao *ao) +{ + return ao->driver->old_functions->get_space(); +} + +void old_ao_reset(struct ao *ao) +{ + ao->driver->old_functions->reset(); +} + +void old_ao_pause(struct ao *ao) +{ + ao->driver->old_functions->pause(); +} + +void old_ao_resume(struct ao *ao) +{ + ao->driver->old_functions->resume(); } |