From 4b9d581b50f53a97007b9e90388ac078aa628d47 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Wed, 28 Mar 2012 21:51:17 +0200
Subject: fifo_buffer

---
 src/output/osx_plugin.c | 93 ++++++++++++++++++++-----------------------------
 1 file 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 = {
-- 
cgit v1.2.3