aboutsummaryrefslogtreecommitdiffstats
path: root/src/output
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2012-03-28 21:51:17 +0200
committerMax Kellermann <max@duempel.org>2012-03-28 21:51:17 +0200
commit8ff0197a4391a43ea932f7f4218e14d2e259c087 (patch)
treee6d0e155cb3394c6e1f7d45e918b94e2d4661736 /src/output
parentde0f46b947c6016bb72379527ea7af75190b5c4b (diff)
downloadmpd-8ff0197a4391a43ea932f7f4218e14d2e259c087.tar.gz
mpd-8ff0197a4391a43ea932f7f4218e14d2e259c087.tar.xz
mpd-8ff0197a4391a43ea932f7f4218e14d2e259c087.zip
output/osx: use the fifo_buffer library instead of rolling own
The existing buffer implementation has a major flaw: it is unable to re-fill the buffer until it has been consumed completely, leading to many occasions where the render callback needs to generate silence, just because the play() implementation was unable to append more data. The fifo_buffer library handles that well.
Diffstat (limited to 'src/output')
-rw-r--r--src/output/osx_plugin.c93
1 files changed, 37 insertions, 56 deletions
diff --git a/src/output/osx_plugin.c b/src/output/osx_plugin.c
index 5284afc29..501dcec10 100644
--- a/src/output/osx_plugin.c
+++ b/src/output/osx_plugin.c
@@ -19,6 +19,7 @@
#include "config.h"
#include "output_api.h"
+#include "fifo_buffer.h"
#include <glib.h>
#include <AudioUnit/AudioUnit.h>
@@ -31,10 +32,8 @@ struct osx_output {
AudioUnit au;
GMutex *mutex;
GCond *condition;
- char *buffer;
- size_t buffer_size;
- size_t pos;
- size_t len;
+
+ struct fifo_buffer *buffer;
};
/**
@@ -64,11 +63,6 @@ osx_output_init(G_GNUC_UNUSED const struct audio_format *audio_format,
oo->mutex = g_mutex_new();
oo->condition = g_cond_new();
- oo->pos = 0;
- oo->len = 0;
- oo->buffer = NULL;
- oo->buffer_size = 0;
-
return oo;
}
@@ -76,7 +70,6 @@ static void osx_output_finish(void *data)
{
struct osx_output *od = data;
- g_free(od->buffer);
g_mutex_free(od->mutex);
g_cond_free(od->condition);
g_free(od);
@@ -87,7 +80,7 @@ static void osx_output_cancel(void *data)
struct osx_output *od = data;
g_mutex_lock(od->mutex);
- od->len = 0;
+ fifo_buffer_clear(od->buffer);
g_mutex_unlock(od->mutex);
}
@@ -98,6 +91,8 @@ static void osx_output_close(void *data)
AudioOutputUnitStop(od->au);
AudioUnitUninitialize(od->au);
CloseComponent(od->au);
+
+ fifo_buffer_free(od->buffer);
}
static OSStatus
@@ -111,37 +106,29 @@ osx_render(void *vdata,
struct osx_output *od = (struct osx_output *) vdata;
AudioBuffer *buffer = &buffer_list->mBuffers[0];
size_t buffer_size = buffer->mDataByteSize;
- size_t bytes_to_copy;
- size_t trailer_length;
- size_t dest_pos = 0;
- g_mutex_lock(od->mutex);
+ assert(od->buffer != NULL);
- bytes_to_copy = MIN(od->len, buffer_size);
- od->len -= bytes_to_copy;
+ g_mutex_lock(od->mutex);
- trailer_length = od->buffer_size - od->pos;
- if (bytes_to_copy > trailer_length) {
- memcpy((unsigned char*)buffer->mData + dest_pos,
- od->buffer + od->pos, trailer_length);
- od->pos = 0;
- dest_pos += trailer_length;
- bytes_to_copy -= trailer_length;
- }
+ size_t nbytes;
+ const void *src = fifo_buffer_read(od->buffer, &nbytes);
- memcpy((unsigned char*)buffer->mData + dest_pos,
- od->buffer + od->pos, bytes_to_copy);
- od->pos += bytes_to_copy;
+ if (src != NULL) {
+ if (nbytes > buffer_size)
+ nbytes = buffer_size;
- if (od->pos >= od->buffer_size)
- od->pos = 0;
+ memcpy(buffer->mData, src, nbytes);
+ fifo_buffer_consume(od->buffer, nbytes);
+ } else
+ nbytes = 0;
g_cond_signal(od->condition);
g_mutex_unlock(od->mutex);
- if (bytes_to_copy < buffer_size)
- memset((unsigned char*)buffer->mData + bytes_to_copy, 0,
- buffer_size - bytes_to_copy);
+ if (nbytes < buffer_size)
+ memset((unsigned char*)buffer->mData + nbytes, 0,
+ buffer_size - nbytes);
return 0;
}
@@ -244,15 +231,12 @@ osx_output_open(void *data, struct audio_format *audio_format, GError **error)
}
/* create a buffer of 1s */
- od->buffer_size = (audio_format->sample_rate) *
- audio_format_frame_size(audio_format);
- od->buffer = g_realloc(od->buffer, od->buffer_size);
-
- od->pos = 0;
- od->len = 0;
+ od->buffer = fifo_buffer_new(audio_format->sample_rate *
+ audio_format_frame_size(audio_format));
status = AudioOutputUnitStart(od->au);
if (status != 0) {
+ fifo_buffer_free(od->buffer);
g_set_error(error, osx_output_quark(), 0,
"unable to start audio output: %s",
GetMacOSStatusCommentString(status));
@@ -267,33 +251,30 @@ osx_output_play(void *data, const void *chunk, size_t size,
G_GNUC_UNUSED GError **error)
{
struct osx_output *od = data;
- size_t start, nbytes;
g_mutex_lock(od->mutex);
- while (od->len >= od->buffer_size)
- /* wait for some free space in the buffer */
- g_cond_wait(od->condition, od->mutex);
-
- start = od->pos + od->len;
- if (start >= od->buffer_size)
- start -= od->buffer_size;
+ void *dest;
+ size_t max_length;
- nbytes = start < od->pos
- ? od->pos - start
- : od->buffer_size - start;
+ while (true) {
+ dest = fifo_buffer_write(od->buffer, &max_length);
+ if (dest != NULL)
+ break;
- assert(nbytes > 0);
+ /* wait for some free space in the buffer */
+ g_cond_wait(od->condition, od->mutex);
+ }
- if (nbytes > size)
- nbytes = size;
+ if (size > max_length)
+ size = max_length;
- memcpy(od->buffer + start, chunk, nbytes);
- od->len += nbytes;
+ memcpy(dest, chunk, size);
+ fifo_buffer_append(od->buffer, size);
g_mutex_unlock(od->mutex);
- return nbytes;
+ return size;
}
const struct audio_output_plugin osxPlugin = {