diff --git a/audio/out/buffer.c b/audio/out/buffer.c index 4ab3e405bc..a5520f3a21 100644 --- a/audio/out/buffer.c +++ b/audio/out/buffer.c @@ -170,21 +170,12 @@ static int read_buffer(struct ao *ao, void **data, int samples, bool *eof) return pos; } -// Read the given amount of samples in the user-provided data buffer. Returns -// the number of samples copied. If there is not enough data (buffer underrun -// or EOF), return the number of samples that could be copied, and fill the -// rest of the user-provided buffer with silence. -// This basically assumes that the audio device doesn't care about underruns. -// If this is called in paused mode, it will always return 0. -// The caller should set out_time_ns to the expected delay until the last sample -// reaches the speakers, in nanoseconds, using mp_time_ns() as reference. -int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns) +static int ao_read_data_unlocked(struct ao *ao, void **data, int samples, + int64_t out_time_ns) { struct buffer_state *p = ao->buffer_state; assert(!ao->driver->write); - mp_mutex_lock(&p->lock); - int pos = read_buffer(ao, data, samples, &(bool){0}); if (pos > 0) @@ -197,6 +188,41 @@ int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns) mp_cond_broadcast(&p->wakeup); } + return pos; +} + +// Read the given amount of samples in the user-provided data buffer. Returns +// the number of samples copied. If there is not enough data (buffer underrun +// or EOF), return the number of samples that could be copied, and fill the +// rest of the user-provided buffer with silence. +// This basically assumes that the audio device doesn't care about underruns. +// If this is called in paused mode, it will always return 0. +// The caller should set out_time_ns to the expected delay until the last sample +// reaches the speakers, in nanoseconds, using mp_time_ns() as reference. +int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns) +{ + struct buffer_state *p = ao->buffer_state; + + mp_mutex_lock(&p->lock); + + int pos = ao_read_data_unlocked(ao, data, samples, out_time_ns); + + mp_mutex_unlock(&p->lock); + + return pos; +} + +// Like ao_read_data() but does not block and also may return partial data. +// Callers have to check the return value. +int ao_read_data_nonblocking(struct ao *ao, void **data, int samples, int64_t out_time_ns) +{ + struct buffer_state *p = ao->buffer_state; + + if (mp_mutex_trylock(&p->lock)) + return 0; + + int pos = ao_read_data_unlocked(ao, data, samples, out_time_ns); + mp_mutex_unlock(&p->lock); return pos; diff --git a/audio/out/internal.h b/audio/out/internal.h index 1ae92a8b92..7951b3861e 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -200,6 +200,8 @@ struct ao_driver { // These functions can be called by AOs. int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_ns); +MP_WARN_UNUSED_RESULT +int ao_read_data_nonblocking(struct ao *ao, void **data, int samples, int64_t out_time_ns); bool ao_chmap_sel_adjust(struct ao *ao, const struct mp_chmap_sel *s, struct mp_chmap *map); diff --git a/osdep/compiler.h b/osdep/compiler.h index 2908f6e0f2..f5658979e3 100644 --- a/osdep/compiler.h +++ b/osdep/compiler.h @@ -7,10 +7,12 @@ #define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format(printf, a1, a2))) #define MP_NORETURN __attribute__((noreturn)) #define MP_FALLTHROUGH __attribute__((fallthrough)) +#define MP_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #else #define PRINTF_ATTRIBUTE(a1, a2) #define MP_NORETURN #define MP_FALLTHROUGH do {} while (0) +#define MP_WARN_UNUSED_RESULT #endif // Broken crap with __USE_MINGW_ANSI_STDIO