summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_openal.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/out/ao_openal.c')
-rw-r--r--audio/out/ao_openal.c134
1 files changed, 49 insertions, 85 deletions
diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c
index 53fcaca05e..7172908e70 100644
--- a/audio/out/ao_openal.c
+++ b/audio/out/ao_openal.c
@@ -19,8 +19,6 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
@@ -58,24 +56,22 @@ struct priv {
ALenum al_format;
int num_buffers;
int num_samples;
- int direct_channels;
+ bool direct_channels;
};
-static void reset(struct ao *ao);
-
static int control(struct ao *ao, enum aocontrol cmd, void *arg)
{
switch (cmd) {
case AOCONTROL_GET_VOLUME:
case AOCONTROL_SET_VOLUME: {
ALfloat volume;
- ao_control_vol_t *vol = (ao_control_vol_t *)arg;
+ float *vol = arg;
if (cmd == AOCONTROL_SET_VOLUME) {
- volume = (vol->left + vol->right) / 200.0;
+ volume = *vol / 100.0;
alListenerf(AL_GAIN, volume);
}
alGetListenerf(AL_GAIN, &volume);
- vol->left = vol->right = volume * 100;
+ *vol = volume * 100;
return CONTROL_TRUE;
}
case AOCONTROL_GET_MUTE:
@@ -201,8 +197,14 @@ static int init(struct ao *ao)
alListenerfv(AL_ORIENTATION, direction);
alGenSources(1, &source);
- if (p->direct_channels && alGetEnumValue((ALchar*)"AL_DIRECT_CHANNELS_SOFT")) {
- alSourcei(source, alGetEnumValue((ALchar*)"AL_DIRECT_CHANNELS_SOFT"), AL_TRUE);
+ if (p->direct_channels) {
+ if (alIsExtensionPresent("AL_SOFT_direct_channels_remix")) {
+ alSourcei(source,
+ alGetEnumValue((ALchar*)"AL_DIRECT_CHANNELS_SOFT"),
+ alcGetEnumValue(dev, "AL_REMIX_UNMATCHED_SOFT"));
+ } else {
+ MP_WARN(ao, "Direct channels aren't supported by this version of OpenAL\n");
+ }
}
cur_buf = 0;
@@ -266,7 +268,7 @@ static int init(struct ao *ao)
goto err_out;
}
- ao->period_size = p->num_samples;
+ ao->device_buffer = p->num_buffers * p->num_samples;
return 0;
err_out:
@@ -274,16 +276,6 @@ err_out:
return -1;
}
-static void drain(struct ao *ao)
-{
- ALint state;
- alGetSourcei(source, AL_SOURCE_STATE, &state);
- while (state == AL_PLAYING) {
- mp_sleep_us(10000);
- alGetSourcei(source, AL_SOURCE_STATE, &state);
- }
-}
-
static void unqueue_buffers(struct ao *ao)
{
struct priv *q = ao->priv;
@@ -301,67 +293,32 @@ static void unqueue_buffers(struct ao *ao)
}
}
-/**
- * \brief stop playing and empty buffers (for seeking/pause)
- */
static void reset(struct ao *ao)
{
alSourceStop(source);
unqueue_buffers(ao);
}
-/**
- * \brief stop playing, keep buffers (for pause)
- */
-static void audio_pause(struct ao *ao)
+static bool audio_set_pause(struct ao *ao, bool pause)
{
- alSourcePause(source);
-}
-
-/**
- * \brief resume playing, after audio_pause()
- */
-static void audio_resume(struct ao *ao)
-{
- alSourcePlay(source);
-}
-
-static int get_space(struct ao *ao)
-{
- struct priv *p = ao->priv;
- ALint queued;
- unqueue_buffers(ao);
- alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
- queued = p->num_buffers - queued;
- if (queued < 0)
- return 0;
- return p->num_samples * queued;
+ if (pause) {
+ alSourcePause(source);
+ } else {
+ alSourcePlay(source);
+ }
+ return true;
}
-/**
- * \brief write data into buffer and reset underrun flag
- */
-static int play(struct ao *ao, void **data, int samples, int flags)
+static bool audio_write(struct ao *ao, void **data, int samples)
{
struct priv *p = ao->priv;
- int buffered_samples = 0;
- int num = 0;
- if (flags & AOPLAY_FINAL_CHUNK) {
- num = 1;
- buffered_samples = samples;
- } else {
- num = samples / p->num_samples;
- buffered_samples = num * p->num_samples;
- }
+ int num = (samples + p->num_samples - 1) / p->num_samples;
for (int i = 0; i < num; i++) {
char *d = *data;
- if (flags & AOPLAY_FINAL_CHUNK) {
- buffer_size[cur_buf] = samples;
- } else {
- buffer_size[cur_buf] = p->num_samples;
- }
+ buffer_size[cur_buf] =
+ MPMIN(samples - i * p->num_samples, p->num_samples);
d += i * buffer_size[cur_buf] * ao->sstride;
alBufferData(buffers[cur_buf], p->al_format, d,
buffer_size[cur_buf] * ao->sstride, ao->samplerate);
@@ -369,33 +326,34 @@ static int play(struct ao *ao, void **data, int samples, int flags)
cur_buf = (cur_buf + 1) % p->num_buffers;
}
- ALint state;
- alGetSourcei(source, AL_SOURCE_STATE, &state);
- if (state != AL_PLAYING) // checked here in case of an underrun
- alSourcePlay(source);
+ return true;
+}
- return buffered_samples;
+static void audio_start(struct ao *ao)
+{
+ alSourcePlay(source);
}
-static double get_delay(struct ao *ao)
+static void get_state(struct ao *ao, struct mp_pcm_state *state)
{
struct priv *p = ao->priv;
+
ALint queued;
unqueue_buffers(ao);
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
- double soft_source_latency = 0;
+ double source_offset = 0;
if(alIsExtensionPresent("AL_SOFT_source_latency")) {
ALdouble offsets[2];
LPALGETSOURCEDVSOFT alGetSourcedvSOFT = alGetProcAddress("alGetSourcedvSOFT");
alGetSourcedvSOFT(source, AL_SEC_OFFSET_LATENCY_SOFT, offsets);
// Additional latency to the play buffer, the remaining seconds to be
// played minus the offset (seconds already played)
- soft_source_latency = offsets[1] - offsets[0];
+ source_offset = offsets[1] - offsets[0];
} else {
float offset = 0;
alGetSourcef(source, AL_SEC_OFFSET, &offset);
- soft_source_latency = -offset;
+ source_offset = -offset;
}
int queued_samples = 0;
@@ -403,7 +361,15 @@ static double get_delay(struct ao *ao)
queued_samples += buffer_size[index];
index = (index + 1) % p->num_buffers;
}
- return (queued_samples / (double)ao->samplerate) + soft_source_latency;
+
+ state->delay = queued_samples / (double)ao->samplerate + source_offset;
+
+ state->queued_samples = queued_samples;
+ state->free_samples = MPMAX(p->num_buffers - queued, 0) * p->num_samples;
+
+ ALint source_state = 0;
+ alGetSourcei(source, AL_SOURCE_STATE, &source_state);
+ state->playing = source_state == AL_PLAYING;
}
#define OPT_BASE_STRUCT struct priv
@@ -414,23 +380,21 @@ const struct ao_driver audio_out_openal = {
.init = init,
.uninit = uninit,
.control = control,
- .get_space = get_space,
- .play = play,
- .get_delay = get_delay,
- .pause = audio_pause,
- .resume = audio_resume,
+ .get_state = get_state,
+ .write = audio_write,
+ .start = audio_start,
+ .set_pause = audio_set_pause,
.reset = reset,
- .drain = drain,
.priv_size = sizeof(struct priv),
.priv_defaults = &(const struct priv) {
.num_buffers = 4,
.num_samples = 8192,
- .direct_channels = 0,
+ .direct_channels = true,
},
.options = (const struct m_option[]) {
{"num-buffers", OPT_INT(num_buffers), M_RANGE(2, MAX_BUF)},
{"num-samples", OPT_INT(num_samples), M_RANGE(256, MAX_SAMPLES)},
- {"direct-channels", OPT_FLAG(direct_channels)},
+ {"direct-channels", OPT_BOOL(direct_channels)},
{0}
},
.options_prefix = "openal",