From 1b6888ae8e30331033bf197b862742d9bda21843 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 4 Jun 2013 01:42:57 +0200 Subject: ao_openal: switch to new AO API --- audio/out/ao_openal.c | 118 ++++++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 52 deletions(-) (limited to 'audio') diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c index c693674984..5dc95a4dd9 100644 --- a/audio/out/ao_openal.c +++ b/audio/out/ao_openal.c @@ -38,21 +38,10 @@ #include "core/mp_msg.h" #include "ao.h" -#include "audio_out_internal.h" #include "audio/format.h" #include "osdep/timer.h" #include "core/subopt-helper.h" -static const ao_info_t info = -{ - "OpenAL audio output", - "openal", - "Reimar Döffinger ", - "" -}; - -LIBAO_EXTERN(openal) - #define MAX_CHANS MP_NUM_CHANNELS #define NUM_BUF 128 #define CHUNK_SIZE 512 @@ -63,8 +52,11 @@ static int cur_buf[MAX_CHANS]; static int unqueue_buf[MAX_CHANS]; static int16_t *tmpbuf; +static struct ao *ao_data; + +static void reset(struct ao *ao); -static int control(int cmd, void *arg) +static int control(struct ao *ao, enum aocontrol cmd, void *arg) { switch (cmd) { case AOCONTROL_GET_VOLUME: @@ -130,25 +122,29 @@ static const struct speaker speaker_pos[] = { {-1}, }; -static int init(int rate, const struct mp_chmap *channels, int format, - int flags) +static int init(struct ao *ao, char *params) { float position[3] = {0, 0, 0}; float direction[6] = {0, 0, 1, 0, -1, 0}; ALCdevice *dev = NULL; ALCcontext *ctx = NULL; ALCint freq = 0; - ALCint attribs[] = {ALC_FREQUENCY, rate, 0, 0}; + ALCint attribs[] = {ALC_FREQUENCY, ao->samplerate, 0, 0}; int i; char *device = NULL; const opt_t subopts[] = { {"device", OPT_ARG_MSTRZ, &device, NULL}, {NULL} }; - global_ao->no_persistent_volume = true; - if (subopt_parse(ao_subdevice, subopts) != 0) { + if (ao_data) { + mp_msg(MSGT_AO, MSGL_FATAL, "[OpenAL] Not reentrant!\n"); + return -1; + } + ao_data = ao; + ao->no_persistent_volume = true; + if (subopt_parse(params, subopts) != 0) { print_help(); - return 0; + return -1; } if (device && strcmp(device, "help") == 0) { list_devices(); @@ -157,13 +153,13 @@ static int init(int rate, const struct mp_chmap *channels, int format, struct mp_chmap_sel sel = {0}; for (i = 0; speaker_pos[i].id != -1; i++) mp_chmap_sel_add_speaker(&sel, speaker_pos[i].id); - if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels)) + if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) goto err_out; struct speaker speakers[MAX_CHANS]; - for (i = 0; i < ao_data.channels.num; i++) { + for (i = 0; i < ao->channels.num; i++) { speakers[i].id = -1; for (int n = 0; speaker_pos[n].id >= 0; n++) { - if (speaker_pos[n].id == ao_data.channels.speaker[i]) + if (speaker_pos[n].id == ao->channels.speaker[i]) speakers[i] = speaker_pos[n]; } if (speakers[i].id < 0) { @@ -180,8 +176,8 @@ static int init(int rate, const struct mp_chmap *channels, int format, alcMakeContextCurrent(ctx); alListenerfv(AL_POSITION, position); alListenerfv(AL_ORIENTATION, direction); - alGenSources(ao_data.channels.num, sources); - for (i = 0; i < ao_data.channels.num; i++) { + alGenSources(ao->channels.num, sources); + for (i = 0; i < ao->channels.num; i++) { cur_buf[i] = 0; unqueue_buf[i] = 0; alGenBuffers(NUM_BUF, buffers[i]); @@ -190,23 +186,22 @@ static int init(int rate, const struct mp_chmap *channels, int format, } alcGetIntegerv(dev, ALC_FREQUENCY, 1, &freq); if (alcGetError(dev) == ALC_NO_ERROR && freq) - rate = freq; - ao_data.samplerate = rate; - ao_data.format = AF_FORMAT_S16_NE; - ao_data.bps = ao_data.channels.num * rate * 2; - ao_data.buffersize = CHUNK_SIZE * NUM_BUF; - ao_data.outburst = ao_data.channels.num * CHUNK_SIZE; + ao->samplerate = freq; + ao->format = AF_FORMAT_S16_NE; + ao->bps = ao->channels.num * ao->samplerate * 2; + ao->buffersize = CHUNK_SIZE * NUM_BUF; + ao->outburst = ao->channels.num * CHUNK_SIZE; tmpbuf = malloc(CHUNK_SIZE); free(device); - return 1; + return 0; err_out: free(device); - return 0; + return -1; } // close audio device -static void uninit(int immed) +static void uninit(struct ao *ao, bool immed) { ALCcontext *ctx = alcGetCurrentContext(); ALCdevice *dev = alcGetContextsDevice(ctx); @@ -219,17 +214,18 @@ static void uninit(int immed) alGetSourcei(sources[0], AL_SOURCE_STATE, &state); } } - reset(); + reset(ao); alcMakeContextCurrent(NULL); alcDestroyContext(ctx); alcCloseDevice(dev); + ao_data = NULL; } static void unqueue_buffers(void) { ALint p; int s; - for (s = 0; s < ao_data.channels.num; s++) { + for (s = 0; s < ao_data->channels.num; s++) { int till_wrap = NUM_BUF - unqueue_buf[s]; alGetSourcei(sources[s], AL_BUFFERS_PROCESSED, &p); if (p >= till_wrap) { @@ -248,29 +244,29 @@ static void unqueue_buffers(void) /** * \brief stop playing and empty buffers (for seeking/pause) */ -static void reset(void) +static void reset(struct ao *ao) { - alSourceStopv(ao_data.channels.num, sources); + alSourceStopv(ao->channels.num, sources); unqueue_buffers(); } /** * \brief stop playing, keep buffers (for pause) */ -static void audio_pause(void) +static void audio_pause(struct ao *ao) { - alSourcePausev(ao_data.channels.num, sources); + alSourcePausev(ao->channels.num, sources); } /** * \brief resume playing, after audio_pause() */ -static void audio_resume(void) +static void audio_resume(struct ao *ao) { - alSourcePlayv(ao_data.channels.num, sources); + alSourcePlayv(ao->channels.num, sources); } -static int get_space(void) +static int get_space(struct ao *ao) { ALint queued; unqueue_buffers(); @@ -278,40 +274,58 @@ static int get_space(void) queued = NUM_BUF - queued - 3; if (queued < 0) return 0; - return queued * CHUNK_SIZE * ao_data.channels.num; + return queued * CHUNK_SIZE * ao->channels.num; } /** * \brief write data into buffer and reset underrun flag */ -static int play(void *data, int len, int flags) +static int play(struct ao *ao, void *data, int len, int flags) { ALint state; int i, j, k; int ch; int16_t *d = data; - len /= ao_data.channels.num * CHUNK_SIZE; + len /= ao->channels.num * CHUNK_SIZE; for (i = 0; i < len; i++) { - for (ch = 0; ch < ao_data.channels.num; ch++) { - for (j = 0, k = ch; j < CHUNK_SIZE / 2; j++, k += ao_data.channels.num) + for (ch = 0; ch < ao->channels.num; ch++) { + for (j = 0, k = ch; j < CHUNK_SIZE / 2; j++, k += ao->channels.num) tmpbuf[j] = d[k]; alBufferData(buffers[ch][cur_buf[ch]], AL_FORMAT_MONO16, tmpbuf, - CHUNK_SIZE, ao_data.samplerate); + CHUNK_SIZE, ao->samplerate); alSourceQueueBuffers(sources[ch], 1, &buffers[ch][cur_buf[ch]]); cur_buf[ch] = (cur_buf[ch] + 1) % NUM_BUF; } - d += ao_data.channels.num * CHUNK_SIZE / 2; + d += ao->channels.num * CHUNK_SIZE / 2; } alGetSourcei(sources[0], AL_SOURCE_STATE, &state); if (state != AL_PLAYING) // checked here in case of an underrun - alSourcePlayv(ao_data.channels.num, sources); - return len * ao_data.channels.num * CHUNK_SIZE; + alSourcePlayv(ao->channels.num, sources); + return len * ao->channels.num * CHUNK_SIZE; } -static float get_delay(void) +static float get_delay(struct ao *ao) { ALint queued; unqueue_buffers(); alGetSourcei(sources[0], AL_BUFFERS_QUEUED, &queued); - return queued * CHUNK_SIZE / 2 / (float)ao_data.samplerate; + return queued * CHUNK_SIZE / 2 / (float)ao->samplerate; } + +const struct ao_driver audio_out_openal = { + .info = &(const struct ao_info) { + "OpenAL audio output", + "openal", + "Reimar Döffinger ", + "" + }, + .init = init, + .uninit = uninit, + .control = control, + .get_space = get_space, + .play = play, + .get_delay = get_delay, + .pause = audio_pause, + .resume = audio_resume, + .reset = reset, +}; -- cgit v1.2.3