summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libao2/audio_out.c166
-rw-r--r--libao2/audio_out.h35
-rw-r--r--libao2/audio_out_internal.h37
3 files changed, 169 insertions, 69 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();
}
diff --git a/libao2/audio_out.h b/libao2/audio_out.h
index dddcb55a6a..c60819e545 100644
--- a/libao2/audio_out.h
+++ b/libao2/audio_out.h
@@ -33,8 +33,7 @@ typedef struct ao_info {
} ao_info_t;
/* interface towards mplayer and */
-typedef struct ao_functions {
- const ao_info_t *info;
+typedef struct ao_old_functions {
int (*control)(int cmd, void *arg);
int (*init)(int rate, int channels, int format, int flags);
void (*uninit)(int immed);
@@ -46,6 +45,23 @@ typedef struct ao_functions {
void (*resume)(void);
} ao_functions_t;
+struct ao;
+
+struct ao_driver {
+ bool is_new;
+ const struct ao_info *info;
+ const struct ao_old_functions *old_functions;
+ int (*control)(struct ao *ao, int cmd, void *arg);
+ int (*init)(struct ao *ao, char *params);
+ void (*uninit)(struct ao *ao, bool cut_audio);
+ void (*reset)(struct ao*ao);
+ int (*get_space)(struct ao *ao);
+ int (*play)(struct ao *ao, void *data, int len, int flags);
+ float (*get_delay)(struct ao *ao);
+ void (*pause)(struct ao *ao);
+ void (*resume)(struct ao *ao);
+};
+
/* global data used by mplayer and plugins */
struct ao {
int samplerate;
@@ -56,7 +72,8 @@ struct ao {
int buffersize;
int pts;
bool initialized;
- const struct ao_functions *driver;
+ const struct ao_driver *driver;
+ void *priv;
};
extern char *ao_subdevice;
@@ -87,7 +104,7 @@ typedef struct ao_control_vol {
struct ao *ao_create(void);
void ao_init(struct ao *ao, char **ao_list);
-void ao_uninit(struct ao *ao, bool drain_audio);
+void ao_uninit(struct ao *ao, bool cut_audio);
int ao_play(struct ao *ao, void *data, int len, int flags);
int ao_control(struct ao *ao, int cmd, void *arg);
double ao_get_delay(struct ao *ao);
@@ -96,4 +113,14 @@ void ao_reset(struct ao *ao);
void ao_pause(struct ao *ao);
void ao_resume(struct ao *ao);
+int old_ao_control(struct ao *ao, int cmd, void *arg);
+int old_ao_init(struct ao *ao, char *params);
+void old_ao_uninit(struct ao *ao, bool cut_audio);
+void old_ao_reset(struct ao*ao);
+int old_ao_get_space(struct ao *ao);
+int old_ao_play(struct ao *ao, void *data, int len, int flags);
+float old_ao_get_delay(struct ao *ao);
+void old_ao_pause(struct ao *ao);
+void old_ao_resume(struct ao *ao);
+
#endif /* MPLAYER_AUDIO_OUT_H */
diff --git a/libao2/audio_out_internal.h b/libao2/audio_out_internal.h
index c093be6989..67bcfa953d 100644
--- a/libao2/audio_out_internal.h
+++ b/libao2/audio_out_internal.h
@@ -31,20 +31,31 @@ static float get_delay(void);
static void audio_pause(void);
static void audio_resume(void);
-extern struct ao ao_data;
+extern struct ao *global_ao;
+#define ao_data (*global_ao)
-#define LIBAO_EXTERN(x) const ao_functions_t audio_out_##x =\
-{\
- &info,\
- control,\
- init,\
- uninit,\
- reset,\
- get_space,\
- play,\
- get_delay,\
- audio_pause,\
- audio_resume\
+#define LIBAO_EXTERN(x) const struct ao_driver audio_out_##x = { \
+ .info = &info, \
+ .control = old_ao_control, \
+ .init = old_ao_init, \
+ .uninit = old_ao_uninit, \
+ .reset = old_ao_reset, \
+ .get_space = old_ao_get_space, \
+ .play = old_ao_play, \
+ .get_delay = old_ao_get_delay, \
+ .pause = old_ao_pause, \
+ .resume = old_ao_resume, \
+ .old_functions = &(const struct ao_old_functions) { \
+ .control = control, \
+ .init = init, \
+ .uninit = uninit, \
+ .reset = reset, \
+ .get_space = get_space, \
+ .play = play, \
+ .get_delay = get_delay, \
+ .pause = audio_pause, \
+ .resume = audio_resume, \
+ }, \
};
#endif /* MPLAYER_AUDIO_OUT_INTERNAL_H */