changeset 1637:5261e37b4d55 trunk

[svn] - fully working CoreAudio plugin, based on the OSS plugin and an incomplete xmms coreaudio plugin (fink)
author nenolod
date Thu, 07 Sep 2006 11:32:59 -0700
parents 09905c29250d
children 9937a2512823
files ChangeLog Plugins/Output/CoreAudio/Makefile Plugins/Output/CoreAudio/about.c Plugins/Output/CoreAudio/audio.c Plugins/Output/CoreAudio/configure.c Plugins/Output/CoreAudio/convert.c Plugins/Output/CoreAudio/coreaudio.c Plugins/Output/CoreAudio/coreaudio.h Plugins/Output/CoreAudio/dbaudiolib.h Plugins/Output/CoreAudio/dbconvert.c Plugins/Output/CoreAudio/init.c Plugins/Output/CoreAudio/mixer.c
diffstat 12 files changed, 2342 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Sep 07 11:06:40 2006 -0700
+++ b/ChangeLog	Thu Sep 07 11:32:59 2006 -0700
@@ -1,3 +1,11 @@
+2006-09-07 18:06:40 +0000  William Pitcock <nenolod@nenolod.net>
+  revision [2203]
+  - remove CoreAudio plugin, and try again :P
+  
+
+  Changes:        Modified:
+
+
 2006-09-07 16:11:46 +0000  William Pitcock <nenolod@nenolod.net>
   revision [2201]
   - fork the OSS plugin for CoreAudio work
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Output/CoreAudio/Makefile	Thu Sep 07 11:32:59 2006 -0700
@@ -0,0 +1,17 @@
+include ../../../mk/rules.mk
+include ../../../mk/init.mk
+
+OBJECTIVE_LIBS = libcoreaudio$(SHARED_SUFFIX)
+
+noinst_HEADERS = coreaudio.h
+
+LIBDIR = $(plugindir)/$(OUTPUT_PLUGIN_DIR)
+
+LIBADD = $(GTK_LIBS) -Wl,-framework,CoreAudio
+SOURCES = coreaudio.c mixer.c about.c configure.c audio.c init.c convert.c dbconvert.c
+
+OBJECTS = ${SOURCES:.c=.o}
+
+CFLAGS += $(PICFLAGS) $(GTK_CFLAGS) -I../../../intl -I../../..
+
+include ../../../mk/objective.mk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Output/CoreAudio/about.c	Thu Sep 07 11:32:59 2006 -0700
@@ -0,0 +1,48 @@
+/*  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "coreaudio.h"
+#include "libaudacious/util.h"
+
+void osx_about(void)
+{
+	static GtkWidget *dialog;
+
+	if (dialog != NULL)
+		return;
+	
+	dialog = xmms_show_message(
+							   "About CoreAudio Plugin",
+							   "Audacious CoreAudio Plugin\n\n "
+							   "This program is free software; you can redistribute it and/or modify\n"
+							   "it under the terms of the GNU General Public License as published by\n"
+							   "the Free Software Foundation; either version 2 of the License, or\n"
+							   "(at your option) any later version.\n"
+							   "\n"
+							   "This program is distributed in the hope that it will be useful,\n"
+							   "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+							   "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+							   "GNU General Public License for more details.\n"
+							   "\n"
+							   "You should have received a copy of the GNU General Public License\n"
+							   "along with this program; if not, write to the Free Software\n"
+							   "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,\n"
+							   "USA.","Ok", FALSE, NULL, NULL);
+	gtk_signal_connect(GTK_OBJECT(dialog), "destroy",
+					   GTK_SIGNAL_FUNC(gtk_widget_destroyed),
+					   &dialog);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Output/CoreAudio/audio.c	Thu Sep 07 11:32:59 2006 -0700
@@ -0,0 +1,612 @@
+/*  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2001  Peter Alm, Mikael Alm, Olle Hallnas,
+ *                           Thomas Nilsson and 4Front Technologies
+ *  Copyright (C) 1999-2001  Haavard Kvaalen
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "coreaudio.h"
+#include "libaudacious/util.h"
+#include <errno.h>
+#include <CoreAudio/CoreAudio.h>
+
+AudioDeviceID device_id;
+AudioStreamBasicDescription device_format;
+AudioStreamBasicDescription streamDesc;
+
+//static gint fd = 0;
+static float *buffer;
+gboolean playing_flag;
+static gboolean prebuffer, unpause, do_pause, remove_prebuffer;
+static gint device_buffer_size;
+static gint buffer_size, prebuffer_size;//, blk_size;
+static gint buffer_index = 0;
+static gint output_time_offset = 0;
+static guint64 written = 0, output_total = 0;
+static gint flush;
+static gchar *device_name;
+
+gint sample_multiplier, sample_size;
+
+gboolean paused;
+
+
+float left_volume, right_volume;
+float base_pitch = 0.0;
+float user_pitch = 0.0;
+int   output_buf_length; // length of data in output buffer
+short output_buf[OUTPUT_BUFSIZE];  /* buffer used to hold main output to dbfsd */
+short cue_buf[OUTPUT_BUFSIZE];     /* buffer used to hold cue output to dbfsd */
+short conv_buf[OUTPUT_BUFSIZE];    /* buffer used to hold format converted input */
+
+/*
+ * The format of the data from the input plugin
+ * This will never change during a song. 
+ */
+struct format_info input;
+
+
+/*
+ * The format we get from the effect plugin.
+ * This will be different from input if the effect plugin does
+ * some kind of format conversion.
+ */
+struct format_info effect;
+
+
+/*
+ * The format of the data we actually send to the soundcard.
+ * This might be different from effect if we need to resample or do
+ * some other format conversion.
+ */
+struct format_info output;
+
+
+static int osx_calc_bitrate(int osx_fmt, int rate, int channels)
+{
+	int bitrate = rate * channels;
+
+	// for now we know output is stereo
+	// fix this later
+
+	if (osx_fmt == FMT_U16_BE || osx_fmt == FMT_U16_LE ||
+	    osx_fmt == FMT_S16_BE || osx_fmt == FMT_S16_LE)
+	{
+		bitrate *= 2;
+	}
+
+	//printf("osx_calc_bitrate(): %d\n",bitrate);
+
+	return bitrate;
+}
+
+
+static int osx_get_format(AFormat fmt)
+{
+	int format = 0;
+
+	switch (fmt)
+	{
+		case FMT_U16_NE:
+#ifdef WORDS_BIGENDIAN
+			format = FMT_U16_BE;
+#else
+			format = FMT_U16_LE;
+#endif
+			break;
+		case FMT_S16_NE:
+#ifdef WORDS_BIGENDIAN
+			format = FMT_S16_BE;
+#else
+			format = FMT_S16_LE;
+#endif
+			break;
+		default:
+			format = fmt;
+			break;
+	}
+
+	return format;
+}
+
+
+OSStatus play_callback(AudioDeviceID inDevice, const AudioTimeStamp * inNow, const AudioBufferList * inInputData, const AudioTimeStamp * inInputTime, AudioBufferList * outOutputData, const AudioTimeStamp * inOutputTime, void * inClientData)
+{
+	int i;
+	long m, n, o;
+	float * dest, tempfloat;
+	float * src;
+	int     src_size_bytes;
+	int     src_size_float;
+	int     num_output_samples;
+	int     used_samples;
+
+	src_size_bytes = outOutputData->mBuffers[0].mDataByteSize;
+	src_size_float = src_size_bytes / sizeof(float);
+
+	num_output_samples = MIN(buffer_index,src_size_float);
+
+	//printf("play_callback(): num_output_samples %d, index %d\n",num_output_samples,buffer_index);
+
+	// if we are prebuffering, zero the buffer
+	if (prebuffer && (buffer_index < prebuffer_size))
+	{
+		//printf("prebuffering... %d samples left\n",prebuffer_size-buffer_index);
+		num_output_samples = 0;
+	}
+	else
+	{
+		prebuffer = FALSE;
+	}
+
+	src = buffer;
+	dest = outOutputData->mBuffers[0].mData;
+
+	// copy available data to buffer and apply volume to each channel
+	for (i = 0; i < num_output_samples/2; i++)
+	{
+		//tempfloat = *src;
+		*dest = (*src) * left_volume;
+		src++;
+		dest++;
+
+		*dest = (*src) * right_volume;
+		src++;
+		dest++;
+	}
+
+	// if less than a buffer's worth of data is ready, zero remainder of output buffer
+	if (num_output_samples != src_size_float)
+	{
+		//printf("zeroing %d samples",(src_size_float - num_output_samples));
+
+		dest = (float*)outOutputData->mBuffers[0].mData + num_output_samples;
+
+		memset(dest,0,(src_size_float - num_output_samples) * sizeof(float));
+	}
+	
+	// move unwritten data to beginning of buffer
+	{
+		dest = buffer;
+
+		for (i = num_output_samples; i < buffer_index; i++)
+		{
+			*dest = *src;
+			dest++;
+			src++;
+		}
+
+		output_total += num_output_samples;
+		buffer_index -= num_output_samples;
+	}
+
+
+	if (flush != -1)
+	{
+		osx_set_audio_params();
+		output_time_offset = flush;
+		written = ((guint64)flush * input.bps) / (1000 * sample_size);
+		buffer_index = 0;
+		output_total = 0;
+
+		flush = -1;
+		prebuffer = TRUE;
+	}
+
+	//printf("\n");
+
+	return 0;
+}
+
+
+static void osx_setup_format(AFormat fmt, int rate, int nch)
+{
+	//printf("osx_setup_format(): fmt %d, rate %d, nch %d\n",fmt,rate,nch);
+
+	effect.format.xmms = osx_get_format(fmt);
+	effect.frequency = rate;
+	effect.channels = nch;
+	effect.bps = osx_calc_bitrate(fmt, rate, nch);
+
+	output.format.osx = osx_get_format(fmt);
+	output.frequency = rate;
+	output.channels = nch;
+
+	osx_set_audio_params();
+
+	output.bps = osx_calc_bitrate(output.format.osx, output.frequency,output.channels);
+}
+
+
+gint osx_get_written_time(void)
+{
+	gint  retval;
+
+	if (!playing_flag)
+	{
+		retval = 0;
+	}
+	else
+	{
+		retval = (written * sample_size * 1000) / effect.bps;
+		retval = (int)((float)retval / user_pitch);
+	}
+
+	//printf("osx_get_written_time(): written time is %d\n",retval);
+
+	return retval;
+}
+
+
+gint osx_get_output_time(void)
+{
+	gint retval;
+
+	retval = output_time_offset + ((output_total * sample_size * 1000) / output.bps);
+	retval = (int)((float)retval / user_pitch);
+	
+	//printf("osx_get_output_time(): time is %d\n",retval);
+
+	return retval;
+}
+
+
+gint osx_playing(void)
+{
+	gint retval;
+
+	retval = 0;
+
+	if (!playing_flag)
+	{
+		retval = 0;
+	}
+	else
+	{
+		if (buffer_index == 0)
+		{
+			retval = FALSE;
+		}
+		else
+		{
+			retval = TRUE;
+		}
+	}
+
+	//printf("osx_playing(): playing is now %d\n",playing_flag);
+
+	return retval;
+}
+
+
+gint osx_free(void)
+{
+	gint bytes_free;
+
+	if (remove_prebuffer && prebuffer)
+	{
+		prebuffer = FALSE;
+		remove_prebuffer = FALSE;
+	}
+
+	if (prebuffer)
+	{
+		remove_prebuffer = TRUE;
+	}
+
+	// get number of free samples
+	bytes_free = buffer_size - buffer_index;
+	
+	// adjust for mono
+	if (input.channels == 1)
+	{
+		bytes_free /= 2;
+	}
+
+	// adjust by pitch conversion;
+	bytes_free = (int)((float)bytes_free * base_pitch * user_pitch);
+
+	// convert from number of samples to number of bytes
+	bytes_free *= sample_size;
+
+	return bytes_free;
+}
+
+
+void osx_write(gpointer ptr, int length)
+{
+	int count, offset = 0;
+	int error;
+	float tempfloat;
+	float * dest;
+	short * src, * tempbuf;
+	int i;
+	int num_samples;
+
+	//printf("oss_write(): lenght: %d \n",length);
+
+	remove_prebuffer = FALSE;
+
+	//	//printf("written is now %d\n",(gint)written);
+
+	// get number of samples
+	num_samples = length / sample_size;
+
+	// update amount of samples received
+	written += num_samples;
+
+	// step through audio 
+	while (num_samples > 0)
+	{
+		// get # of samples to write to the buffer
+		count = MIN(num_samples, osx_free()/sample_size);
+		
+		src = ptr+offset;
+
+		if (dbconvert((char*)src,count * sample_size) == -1)
+		{
+			//printf("dbconvert error %d\n",errno);
+		}
+		else
+		{
+			src = output_buf;
+			dest = (float*)(buffer + buffer_index);
+			
+			//printf("output_buf_length is %d\n",output_buf_length);
+
+			for (i = 0; i < output_buf_length; i++)
+			{
+				tempfloat = ((float)*src)/32768.0;
+				*dest = tempfloat;
+				dest++;
+				src++;
+			}
+
+			buffer_index += output_buf_length;
+		}
+
+		if (buffer_index > buffer_size)
+		{
+			//printf("BUFFER_INDEX > BUFFER_SIZE!!!!\n");
+			exit(0);
+		}
+
+		num_samples -= count;
+		offset += count;
+	}
+
+	//printf("buffer_index is now %d\n\n",buffer_index);
+}
+
+
+void osx_close(void)
+{
+	//printf("osx_close(): playing_flag is %d\n",playing_flag);
+
+	if (!playing_flag)
+	{
+		return;
+	}
+
+	playing_flag = 0;
+
+	// close audio device
+	AudioDeviceStop(device_id, play_callback); 
+	AudioDeviceRemoveIOProc(device_id, play_callback);
+
+	g_free(device_name);
+
+	//printf("osx_close(): playing_flag is now %d\n",playing_flag);
+}
+
+
+void osx_flush(gint time)
+{
+	//printf("osx_flush(): %d\n",time);
+
+	flush = time;
+
+	while (flush != -1)
+	{
+		xmms_usleep(10000);
+	}
+}
+
+
+void osx_pause(short p)
+{
+	//printf("osx_pause(): %d\n",p);
+
+	if (p == TRUE)
+	{
+		if (AudioDeviceStop(device_id, play_callback))
+		{
+			//printf("failed to stop audio device.\n");
+		}
+
+		//printf("PAUSED!\n");
+	}
+	else
+	{
+		if (AudioDeviceStart(device_id, play_callback))
+		{
+			//printf("failed to start audio device.\n");
+		}
+
+		//printf("UNPAUSED!\n");
+	}
+
+	paused = p;
+}
+
+
+void osx_set_audio_params(void)
+{
+	int stereo_multiplier, format_multiplier;
+	int frag, stereo, ret;
+	struct timeval tv;
+	fd_set set;
+
+	//printf("osx_set_audio_params(): fmt %d, freq %d, nch %d\n",output.format.osx,output.frequency,output.channels);
+
+	// set audio format 
+
+	// set num channels
+
+	switch (input.channels)
+	{
+		case 1:  stereo_multiplier = 2; break;
+		case 2:  stereo_multiplier = 1; break;
+		default: stereo_multiplier = 1; break;
+	}
+	
+	switch (input.format.xmms)
+	{
+		case FMT_U8:    
+		case FMT_S8:
+			format_multiplier = 2;
+			sample_size = 1;
+			break;
+		case FMT_S16_LE:
+		case FMT_S16_BE:
+		case FMT_S16_NE:
+			format_multiplier = 1;
+			sample_size = 2;
+			break;
+		default: format_multiplier = 1; break;
+	}
+
+	sample_multiplier = stereo_multiplier * format_multiplier;
+
+	base_pitch = input.frequency / device_format.mSampleRate;
+
+	//printf("sample multiplier is now %d, base pitch %.2f\n",sample_multiplier,base_pitch);
+}
+
+
+gint osx_open(AFormat fmt, gint rate, gint nch)
+{
+	char s[32];
+	long m;
+	long size;
+	char device_name[128];
+
+	//printf("\nosx_open(): fmt %d, rate %d, nch %d\n",fmt,rate,nch);
+
+	// init conversion variables
+	base_pitch = 1.0;
+	user_pitch = 1.0;
+
+	// open audio device
+
+	size = sizeof(device_id);
+
+	if (AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &size, &device_id))
+	{
+		//printf("failed to open default audio device");
+		return -1;
+	}
+
+	//printf("opened audio device\n");
+
+	size = 128;
+
+	if (AudioDeviceGetProperty(device_id,1,0,kAudioDevicePropertyDeviceName,&size,device_name))
+	{
+		//printf("could not get device name\n");
+		return -1;
+	}
+
+	//printf("device name is: \"%s\"\n",device_name);
+
+	size = sizeof(device_format);
+
+	if (AudioDeviceGetProperty(device_id, 0, 0, kAudioDevicePropertyStreamFormat, &size, &device_format))
+	{
+		//printf("failed to get audio format!\n");
+		return -1;
+	}
+
+	//fprintf(stderr, "got format:  sample rate %f, %ld channels and %ld-bit sample\n",
+	//		device_format.mSampleRate,device_format.mChannelsPerFrame,device_format.mBitsPerChannel);
+
+	if (device_format.mFormatID != kAudioFormatLinearPCM)
+	{
+		//printf("audio format isn't PCM\n");
+		return -1;
+	}
+
+	//printf("format is PCM\n");
+
+	input.format.xmms = fmt;
+	input.frequency = rate;
+	input.channels = nch;
+	input.bps = osx_calc_bitrate(osx_get_format(fmt),rate,nch);
+
+	osx_setup_format(osx_get_format(fmt),device_format.mSampleRate,device_format.mChannelsPerFrame);
+
+	//set audio buffer size
+	{
+		device_buffer_size = 4096 * sizeof(float);
+		size = sizeof(gint);
+
+		if (AudioDeviceSetProperty(device_id,0,0,0,kAudioDevicePropertyBufferSize,size,&device_buffer_size))
+		{
+			//printf("failed to set device buffer size\n");
+		}
+
+		//printf("buffer size set to %d\n",device_buffer_size);
+	}
+
+	buffer_size = 11 * 4096;
+	prebuffer_size = 4096;
+
+	buffer = (float *) g_malloc0(buffer_size*sizeof(float));
+
+	//printf("created buffer of size %d, prebuffer is %d\n",buffer_size,prebuffer_size);
+
+	flush = -1;
+	prebuffer = TRUE;
+
+	buffer_index = output_time_offset = written = output_total = 0;
+
+	paused = FALSE;
+
+	do_pause = FALSE;
+	unpause = FALSE;
+	remove_prebuffer = FALSE;
+
+	playing_flag = 1;
+
+	if (AudioDeviceAddIOProc(device_id, play_callback, NULL))
+	{
+		//printf("failed to add IO Proc callback\n");
+		osx_close();
+		return -1;
+	}
+
+	//printf("added callback\n");
+
+	if (AudioDeviceStart(device_id,play_callback))
+	{
+		osx_close();
+		//printf("failed to start audio device.\n");
+		exit(0);
+	}
+
+	//printf("started audio device\n");
+
+	return 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Output/CoreAudio/configure.c	Thu Sep 07 11:32:59 2006 -0700
@@ -0,0 +1,296 @@
+/*  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2001  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
+ *  Copyright (C) 1999-2001  Håvard Kvålen
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+//#include <glib/gi18n.h>
+#include "coreaudio.h"
+#include "libaudacious/configdb.h"
+#include <CoreAudio/CoreAudio.h>
+
+static GtkWidget *configure_win = NULL;
+static GtkWidget *mixer_usemaster_check, *buffer_size_spin, *buffer_pre_spin;
+static GtkWidget *adevice_use_alt_check, *audio_alt_device_entry;
+static GtkWidget *mdevice_use_alt_check, *mixer_alt_device_entry;
+static gint audio_device, mixer_device;
+
+static void configure_win_ok_cb(GtkWidget * w, gpointer data)
+{
+	ConfigDb *cfgfile;
+
+	osx_cfg.audio_device = audio_device;
+	osx_cfg.mixer_device = mixer_device;
+	osx_cfg.buffer_size =
+		gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buffer_size_spin));
+	osx_cfg.prebuffer =
+		gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buffer_pre_spin));
+	osx_cfg.use_master =
+		gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(mixer_usemaster_check));
+	osx_cfg.use_alt_audio_device =
+		gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(adevice_use_alt_check));
+	osx_cfg.use_alt_mixer_device =
+		gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(mdevice_use_alt_check));
+	g_free(osx_cfg.alt_audio_device);
+	osx_cfg.alt_audio_device =
+		gtk_editable_get_chars(GTK_EDITABLE(audio_alt_device_entry), 0, -1);
+	g_strstrip(osx_cfg.alt_audio_device);
+	g_free(osx_cfg.alt_mixer_device);
+	osx_cfg.alt_mixer_device =
+		gtk_editable_get_chars(GTK_EDITABLE(mixer_alt_device_entry), 0, -1);
+	g_strstrip(osx_cfg.alt_mixer_device);
+
+	if (osx_cfg.use_alt_audio_device)
+		/* do a minimum of sanity checking */
+		if (osx_cfg.alt_audio_device[0] != '/') 
+			osx_cfg.use_alt_audio_device = FALSE;
+	if (osx_cfg.use_alt_mixer_device)
+		if (osx_cfg.alt_mixer_device[0] != '/') 
+			osx_cfg.use_alt_mixer_device = FALSE;
+	
+	cfgfile = bmp_cfg_db_open();
+
+	bmp_cfg_db_set_int(cfgfile, "OSX", "audio_device", osx_cfg.audio_device);
+	bmp_cfg_db_set_int(cfgfile, "OSX", "mixer_device", osx_cfg.mixer_device);
+	bmp_cfg_db_set_int(cfgfile, "OSX", "buffer_size", osx_cfg.buffer_size);
+	bmp_cfg_db_set_int(cfgfile, "OSX", "prebuffer", osx_cfg.prebuffer);
+	bmp_cfg_db_set_bool(cfgfile,"OSX","use_master",osx_cfg.use_master);
+	bmp_cfg_db_set_bool(cfgfile, "OSX", "use_alt_audio_device", osx_cfg.use_alt_audio_device);
+	bmp_cfg_db_set_string(cfgfile, "OSX", "alt_audio_device", osx_cfg.alt_audio_device);
+	bmp_cfg_db_set_bool(cfgfile, "OSX", "use_alt_mixer_device", osx_cfg.use_alt_mixer_device);
+	bmp_cfg_db_set_string(cfgfile, "OSX", "alt_mixer_device", osx_cfg.alt_mixer_device);
+	bmp_cfg_db_close(cfgfile);
+
+	gtk_widget_destroy(configure_win);
+}
+
+static void configure_win_audio_dev_cb(GtkWidget * widget, gint device)
+{
+	audio_device = device;
+}
+
+static void configure_win_mixer_dev_cb(GtkWidget * widget, gint device)
+{
+	mixer_device = device;
+}
+
+static void audio_device_toggled(GtkToggleButton * widget, gpointer data)
+{
+	gboolean use_alt_audio_device = gtk_toggle_button_get_active(widget);
+	gtk_widget_set_sensitive(GTK_WIDGET(data), !use_alt_audio_device);
+	gtk_widget_set_sensitive(audio_alt_device_entry, use_alt_audio_device);
+}
+
+static void mixer_device_toggled(GtkToggleButton * widget, gpointer data)
+{
+	gboolean use_alt_device = gtk_toggle_button_get_active(widget);
+	gtk_widget_set_sensitive(GTK_WIDGET(data), !use_alt_device);
+	gtk_widget_set_sensitive(mixer_alt_device_entry, use_alt_device);
+}
+
+static void scan_devices(gchar * type, GtkWidget * option_menu, GtkSignalFunc sigfunc)
+{
+	GtkWidget *menu, *item;
+	FILE *file;
+	UInt32 size,len,i;
+	AudioDeviceID * devicelist;
+	char device_name[128];
+
+	menu = gtk_menu_new();
+
+	if (AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,&size,NULL))
+	{
+		item = gtk_menu_item_new_with_label("Default");
+		gtk_signal_connect(GTK_OBJECT(item), "activate", sigfunc, (gpointer) 0);
+		gtk_widget_show(item);
+		gtk_menu_append(GTK_MENU(menu), item);
+	}
+	else
+	{
+		printf("there are %d devices\n",size/sizeof(AudioDeviceID));
+		
+		devicelist = (AudioDeviceID*) malloc(size);
+		
+		if (AudioHardwareGetProperty(kAudioHardwarePropertyDevices,&size,devicelist))
+		{
+			printf("failed to get device list");
+		}
+		
+		for (i = 0; i < size/sizeof(AudioDeviceID); i++)
+		{
+			len = 128;
+			AudioDeviceGetProperty(devicelist[i],1,0,kAudioDevicePropertyDeviceName,&len,device_name);
+			
+			item = gtk_menu_item_new_with_label(device_name);
+			gtk_signal_connect(GTK_OBJECT(item), "activate", sigfunc, (gpointer) 0);
+			gtk_widget_show(item);
+			gtk_menu_append(GTK_MENU(menu), item);
+			
+		}
+	}
+
+	gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
+}
+
+void osx_configure(void)
+{
+	GtkWidget *vbox, *notebook;
+	GtkWidget *dev_vbox, *adevice_frame, *adevice_box, *adevice;
+	GtkWidget *mdevice_frame, *mdevice_box, *mdevice;
+	GtkWidget *buffer_frame, *buffer_vbox, *buffer_table;
+	GtkWidget *buffer_size_box, *buffer_size_label;
+	GtkObject *buffer_size_adj, *buffer_pre_adj;
+	GtkWidget *buffer_pre_box, *buffer_pre_label;
+	GtkWidget *audio_alt_box, *mixer_alt_box;
+	GtkWidget *bbox, *ok, *cancel;
+	GtkWidget *mixer_table, *mixer_frame;
+	
+	if (configure_win)
+	{
+		gdk_window_raise(configure_win->window);
+		return;
+	}
+
+	configure_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+	gtk_signal_connect(GTK_OBJECT(configure_win), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &configure_win);
+	gtk_window_set_title(GTK_WINDOW(configure_win), "CoreAudio Plugin Configuration");
+	gtk_window_set_policy(GTK_WINDOW(configure_win), FALSE, FALSE, FALSE);
+	gtk_window_set_position(GTK_WINDOW(configure_win), GTK_WIN_POS_MOUSE);
+	gtk_container_border_width(GTK_CONTAINER(configure_win), 10);
+	
+
+	vbox = gtk_vbox_new(FALSE, 10);
+	gtk_container_add(GTK_CONTAINER(configure_win), vbox);
+	
+	notebook = gtk_notebook_new();
+	gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
+	
+	dev_vbox = gtk_vbox_new(FALSE, 5);
+	gtk_container_set_border_width(GTK_CONTAINER(dev_vbox), 5);
+
+	adevice_frame = gtk_frame_new("Audio device:");
+	gtk_box_pack_start(GTK_BOX(dev_vbox), adevice_frame, FALSE, FALSE, 0);
+	
+	adevice_box = gtk_vbox_new(FALSE, 5);
+	gtk_container_set_border_width(GTK_CONTAINER(adevice_box), 5);
+	gtk_container_add(GTK_CONTAINER(adevice_frame), adevice_box);
+
+	adevice = gtk_option_menu_new();
+	gtk_box_pack_start(GTK_BOX(adevice_box), adevice, TRUE, TRUE, 0);
+
+	scan_devices("Audio devices:", adevice, configure_win_audio_dev_cb);
+
+	audio_device = osx_cfg.audio_device;
+	gtk_option_menu_set_history(GTK_OPTION_MENU(adevice), osx_cfg.audio_device);
+
+	/*
+	  audio_alt_box = gtk_hbox_new(FALSE, 0);
+		gtk_box_pack_start_defaults(GTK_BOX(adevice_box), audio_alt_box);
+		adevice_use_alt_check = gtk_check_button_new_with_label("Use alternate device:");
+		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(adevice_use_alt_check), osx_cfg.use_alt_audio_device);
+		gtk_signal_connect(GTK_OBJECT(adevice_use_alt_check), "toggled", audio_device_toggled, adevice);
+   
+		gtk_box_pack_start(GTK_BOX(audio_alt_box), adevice_use_alt_check, FALSE, FALSE, 0);
+		audio_alt_device_entry = gtk_entry_new();
+
+	gtk_box_pack_start_defaults(GTK_BOX(audio_alt_box), audio_alt_device_entry);
+	*/
+
+	gtk_box_pack_start(GTK_BOX(dev_vbox), mdevice_frame, FALSE, FALSE, 0);
+	
+	mdevice_box = gtk_vbox_new(FALSE, 0);
+	gtk_container_set_border_width(GTK_CONTAINER(mdevice_box), 5);
+	gtk_container_add(GTK_CONTAINER(mdevice_frame), mdevice_box);
+
+	mdevice = gtk_option_menu_new();
+	gtk_box_pack_start(GTK_BOX(mdevice_box), mdevice, TRUE, TRUE, 0);
+
+	scan_devices("Mixers:", mdevice, configure_win_mixer_dev_cb);
+
+	mixer_device = osx_cfg.mixer_device;
+	gtk_option_menu_set_history(GTK_OPTION_MENU(mdevice), osx_cfg.mixer_device);
+	mixer_alt_box = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start_defaults(GTK_BOX(mdevice_box), mixer_alt_box);
+	mdevice_use_alt_check = gtk_check_button_new_with_label("Use alternate device:");
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mdevice_use_alt_check), osx_cfg.use_alt_mixer_device);
+	gtk_signal_connect(GTK_OBJECT(mdevice_use_alt_check), "toggled", mixer_device_toggled, mdevice);
+	gtk_box_pack_start(GTK_BOX(mixer_alt_box), mdevice_use_alt_check, FALSE, FALSE, 0);
+	mixer_alt_device_entry = gtk_entry_new();
+
+	if (osx_cfg.alt_mixer_device != NULL)
+		gtk_entry_set_text(GTK_ENTRY(mixer_alt_device_entry), osx_cfg.alt_mixer_device);
+	else
+		gtk_entry_set_text(GTK_ENTRY(mixer_alt_device_entry), "/dev/mixer");
+
+	gtk_box_pack_start_defaults(GTK_BOX(mixer_alt_box), mixer_alt_device_entry);
+
+	if (osx_cfg.use_alt_mixer_device)
+		gtk_widget_set_sensitive(mdevice, FALSE);
+	else
+		gtk_widget_set_sensitive(mixer_alt_device_entry, FALSE);
+
+	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dev_vbox, gtk_label_new("Devices"));
+
+
+	buffer_frame = gtk_frame_new("Buffering:");
+	gtk_container_set_border_width(GTK_CONTAINER(buffer_frame), 5);
+
+	buffer_vbox = gtk_vbox_new(FALSE, 0);
+	gtk_container_add(GTK_CONTAINER(buffer_frame), buffer_vbox);
+
+	buffer_table = gtk_table_new(2, 1, TRUE);
+	gtk_container_set_border_width(GTK_CONTAINER(buffer_table), 5);
+	gtk_box_pack_start(GTK_BOX(buffer_vbox), buffer_table, FALSE, FALSE, 0);
+
+	buffer_size_box = gtk_hbox_new(FALSE, 5);
+	gtk_table_attach_defaults(GTK_TABLE(buffer_table), buffer_size_box, 0, 1, 0, 1);
+	buffer_size_label = gtk_label_new("Buffer size (ms):");
+	gtk_box_pack_start(GTK_BOX(buffer_size_box), buffer_size_label, FALSE, FALSE, 0);
+	buffer_size_adj = gtk_adjustment_new(osx_cfg.buffer_size, 200, 10000, 100, 100, 100);
+	buffer_size_spin = gtk_spin_button_new(GTK_ADJUSTMENT(buffer_size_adj), 8, 0);
+	gtk_widget_set_usize(buffer_size_spin, 60, -1);
+	gtk_box_pack_start(GTK_BOX(buffer_size_box), buffer_size_spin, FALSE, FALSE, 0);
+
+	buffer_pre_box = gtk_hbox_new(FALSE, 5);
+	gtk_table_attach_defaults(GTK_TABLE(buffer_table), buffer_pre_box, 1, 2, 0, 1);
+	buffer_pre_label = gtk_label_new("Pre-buffer (percent):");
+	gtk_box_pack_start(GTK_BOX(buffer_pre_box), buffer_pre_label, FALSE, FALSE, 0);
+	buffer_pre_adj = gtk_adjustment_new(osx_cfg.prebuffer, 0, 90, 1, 1, 1);
+	buffer_pre_spin = gtk_spin_button_new(GTK_ADJUSTMENT(buffer_pre_adj), 1, 0);
+	gtk_widget_set_usize(buffer_pre_spin, 60, -1);
+	gtk_box_pack_start(GTK_BOX(buffer_pre_box), buffer_pre_spin, FALSE, FALSE, 0);
+
+	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), buffer_frame, gtk_label_new("Buffering"));
+
+
+	bbox = gtk_hbutton_box_new();
+	gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+	gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
+	gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
+
+	ok = gtk_button_new_with_label("Ok");
+	gtk_signal_connect(GTK_OBJECT(ok), "clicked", GTK_SIGNAL_FUNC(configure_win_ok_cb), NULL);
+	GTK_WIDGET_SET_FLAGS(ok, GTK_CAN_DEFAULT);
+	gtk_box_pack_start(GTK_BOX(bbox), ok, TRUE, TRUE, 0);
+	gtk_widget_grab_default(ok);
+
+	cancel = gtk_button_new_with_label("Cancel");
+	gtk_signal_connect_object(GTK_OBJECT(cancel), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(configure_win));
+	GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT);
+	gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0);
+
+	gtk_widget_show_all(configure_win);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Output/CoreAudio/convert.c	Thu Sep 07 11:32:59 2006 -0700
@@ -0,0 +1,313 @@
+/*
+ *  Copyright (C) 2001  Haavard Kvaalen
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "coreaudio.h"
+
+void* osx_get_convert_buffer(size_t size)
+{
+	static size_t length;
+	static void *buffer;
+
+	if (size > 0 && size <= length)
+		return buffer;
+
+	length = size;
+	buffer = g_realloc(buffer, size);
+	return buffer;
+}
+
+static int convert_swap_endian(void **data, int length)
+{
+	guint16 *ptr = *data;
+	int i;
+	for (i = 0; i < length; i += 2, ptr++)
+		*ptr = GUINT16_SWAP_LE_BE(*ptr);
+
+	return i;
+}
+
+static int convert_swap_sign_and_endian_to_native(void **data, int length)
+{
+	guint16 *ptr = *data;
+	int i;
+	for (i = 0; i < length; i += 2, ptr++)
+		*ptr = GUINT16_SWAP_LE_BE(*ptr) ^ 1 << 15;
+
+	return i;
+}
+
+static int convert_swap_sign_and_endian_to_alien(void **data, int length)
+{
+	guint16 *ptr = *data;
+	int i;
+	for (i = 0; i < length; i += 2, ptr++)
+		*ptr = GUINT16_SWAP_LE_BE(*ptr ^ 1 << 15);
+
+	return i;
+}
+
+static int convert_swap_sign16(void **data, int length)
+{
+	gint16 *ptr = *data;
+	int i;
+	for (i = 0; i < length; i += 2, ptr++)
+		*ptr ^= 1 << 15;
+
+	return i;
+}
+
+static int convert_swap_sign8(void **data, int length)
+{
+	gint8 *ptr = *data;
+	int i;
+	for (i = 0; i < length; i++)
+		*ptr++ ^= 1 << 7;
+
+	return i;
+}
+
+static int convert_to_8_native_endian(void **data, int length)
+{
+	gint8 *output = *data;
+	gint16 *input = *data;
+	int i;
+	for (i = 0; i < length / 2; i++)
+		*output++ = *input++ >> 8;
+
+	return i;
+}
+
+static int convert_to_8_native_endian_swap_sign(void **data, int length)
+{
+	gint8 *output = *data;
+	gint16 *input = *data;
+	int i;
+	for (i = 0; i < length / 2; i++)
+		*output++ = (*input++ >> 8) ^ (1 << 7);
+
+	return i;
+}
+
+
+static int convert_to_8_alien_endian(void **data, int length)
+{
+	gint8 *output = *data;
+	gint16 *input = *data;
+	int i;
+	for (i = 0; i < length / 2; i++)
+		*output++ = *input++ & 0xff;
+
+	return i;
+}
+
+static int convert_to_8_alien_endian_swap_sign(void **data, int length)
+{
+	gint8 *output = *data;
+	gint16 *input = *data;
+	int i;
+	for (i = 0; i < length / 2; i++)
+		*output++ = (*input++ & 0xff) ^ (1 << 7);
+
+	return i;
+}
+
+static int convert_to_16_native_endian(void **data, int length)
+{
+	guint8 *input = *data;
+	guint16 *output;
+	int i;
+	*data = osx_get_convert_buffer(length * 2);
+	output = *data;
+	for (i = 0; i < length; i++)
+		*output++ = *input++ << 8;
+
+	return i * 2;
+}
+
+static int convert_to_16_native_endian_swap_sign(void **data, int length)
+{
+	guint8 *input = *data;
+	guint16 *output;
+	int i;
+	*data = osx_get_convert_buffer(length * 2);
+	output = *data;
+	for (i = 0; i < length; i++)
+		*output++ = (*input++ << 8) ^ (1 << 15);
+
+	return i * 2;
+}
+
+
+static int convert_to_16_alien_endian(void **data, int length)
+{
+	guint8 *input = *data;
+	guint16 *output;
+	int i;
+	*data = osx_get_convert_buffer(length * 2);
+	output = *data;
+	for (i = 0; i < length; i++)
+		*output++ = *input++;
+
+	return i * 2;
+}
+
+static int convert_to_16_alien_endian_swap_sign(void **data, int length)
+{
+	guint8 *input = *data;
+	guint16 *output;
+	int i;
+	*data = osx_get_convert_buffer(length * 2);
+	output = *data;
+	for (i = 0; i < length; i++)
+		*output++ = *input++ ^ (1 << 7);
+
+	return i * 2;
+}
+
+int (*osx_get_convert_func(int output, int input))(void **, int)
+{
+	if (output == input)
+		return NULL;
+
+	printf("1\n");
+
+	if ((output == FMT_U16_BE && input == FMT_U16_LE) ||
+	    (output == FMT_U16_LE && input == FMT_U16_BE) ||
+	    (output == FMT_S16_BE && input == FMT_S16_LE) ||
+	    (output == FMT_S16_LE && input == FMT_S16_BE))
+		return convert_swap_endian;
+
+	printf("2\n");
+
+	if ((output == FMT_U16_BE && input == FMT_S16_BE) ||
+	    (output == FMT_U16_LE && input == FMT_S16_LE) ||
+	    (output == FMT_S16_BE && input == FMT_U16_BE) ||
+	    (output == FMT_S16_LE && input == FMT_U16_LE))
+		return convert_swap_sign16;
+
+	printf("3\n");
+
+
+	if ((IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_BE && input == FMT_S16_LE) ||
+	      (output == FMT_S16_BE && input == FMT_U16_LE))) ||
+	    (!IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_LE && input == FMT_S16_BE) ||
+	      (output == FMT_S16_LE && input == FMT_U16_BE))))
+		return convert_swap_sign_and_endian_to_native;
+
+	printf("4\n");
+		
+	if ((!IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_BE && input == FMT_S16_LE) ||
+	      (output == FMT_S16_BE && input == FMT_U16_LE))) ||
+	    (IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_LE && input == FMT_S16_BE) ||
+	      (output == FMT_S16_LE && input == FMT_U16_BE))))
+		return convert_swap_sign_and_endian_to_alien;
+
+	printf("5\n");
+
+	if ((IS_BIG_ENDIAN &&
+	     ((output == FMT_U8 && input == FMT_U16_BE) ||
+	      (output == FMT_S8 && input == FMT_S16_BE))) ||
+	    (!IS_BIG_ENDIAN &&
+	     ((output == FMT_U8 && input == FMT_U16_LE) ||
+	      (output == FMT_S8 && input == FMT_S16_LE))))
+		return convert_to_8_native_endian;
+
+	printf("6\n");
+
+	if ((IS_BIG_ENDIAN &&
+	     ((output == FMT_U8 && input == FMT_S16_BE) ||
+	      (output == FMT_S8 && input == FMT_U16_BE))) ||
+	    (!IS_BIG_ENDIAN &&
+	     ((output == FMT_U8 && input == FMT_S16_LE) ||
+	      (output == FMT_S8 && input == FMT_U16_LE))))
+		return convert_to_8_native_endian_swap_sign;
+
+	printf("7\n");
+
+	if ((!IS_BIG_ENDIAN &&
+	     ((output == FMT_U8 && input == FMT_U16_BE) ||
+	      (output == FMT_S8 && input == FMT_S16_BE))) ||
+	    (IS_BIG_ENDIAN &&
+	     ((output == FMT_U8 && input == FMT_U16_LE) ||
+	      (output == FMT_S8 && input == FMT_S16_LE))))
+		return convert_to_8_alien_endian;
+
+	printf("8\n");
+
+	if ((!IS_BIG_ENDIAN &&
+	     ((output == FMT_U8 && input == FMT_S16_BE) ||
+	      (output == FMT_S8 && input == FMT_U16_BE))) ||
+	    (IS_BIG_ENDIAN &&
+	     ((output == FMT_U8 && input == FMT_S16_LE) ||
+	      (output == FMT_S8 && input == FMT_U16_LE))))
+		return convert_to_8_alien_endian_swap_sign;
+
+	printf("9\n");
+
+	if ((output == FMT_U8 && input == FMT_S8) ||
+	    (output == FMT_S8 && input == FMT_U8))
+		return convert_swap_sign8;
+
+	printf("10\n");
+
+	if ((IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_BE && input == FMT_U8) ||
+	      (output == FMT_S16_BE && input == FMT_S8))) ||
+	    (!IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_LE && input == FMT_U8) ||
+	      (output == FMT_S16_LE && input == FMT_S8))))
+		return convert_to_16_native_endian;
+
+	printf("11\n");
+
+	if ((IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_BE && input == FMT_S8) ||
+	      (output == FMT_S16_BE && input == FMT_U8))) ||
+	    (!IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_LE && input == FMT_S8) ||
+	      (output == FMT_S16_LE && input == FMT_U8))))
+		return convert_to_16_native_endian_swap_sign;
+
+	printf("12\n");
+
+	if ((!IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_BE && input == FMT_U8) ||
+	      (output == FMT_S16_BE && input == FMT_S8))) ||
+	    (IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_LE && input == FMT_U8) ||
+	      (output == FMT_S16_LE && input == FMT_S8))))
+		return convert_to_16_alien_endian;
+
+	printf("14\n");
+
+	if ((!IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_BE && input == FMT_S8) ||
+	      (output == FMT_S16_BE && input == FMT_U8))) ||
+	    (IS_BIG_ENDIAN &&
+	     ((output == FMT_U16_LE && input == FMT_S8) ||
+	      (output == FMT_S16_LE && input == FMT_U8))))
+		return convert_to_16_alien_endian_swap_sign;
+
+	g_warning("Translation needed, but not available.\n"
+			  "Input: %d; Output %d.", input, output);
+	return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Output/CoreAudio/coreaudio.c	Thu Sep 07 11:32:59 2006 -0700
@@ -0,0 +1,51 @@
+/*  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "coreaudio.h"
+
+#include "audacious/plugin.h"
+
+OutputPlugin osx_op =
+	{
+		NULL,
+		NULL,
+		NULL, /* Description */
+		osx_init,
+		NULL,
+		osx_about,
+		osx_configure,
+		osx_get_volume,
+		osx_set_volume,
+		osx_open,
+		osx_write,
+		osx_close,
+		osx_flush,
+		osx_pause,
+		osx_free,
+		osx_playing,
+		osx_get_output_time,
+		osx_get_written_time,
+	};
+
+OutputPlugin *get_oplugin_info(void)
+{
+	osx_op.description = g_strdup(_("CoreAudio Output Plugin"));
+	return &osx_op;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Output/CoreAudio/coreaudio.h	Thu Sep 07 11:32:59 2006 -0700
@@ -0,0 +1,106 @@
+/*  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef OSX_H
+#define OSX_H
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_SOUNDCARD_H
+#include <sys/soundcard.h>
+#elif defined(HAVE_MACHINE_SOUNDCARD_H)
+#include <machine/soundcard.h>
+#endif
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "audacious/plugin.h"
+
+#ifdef WORDS_BIGENDIAN
+# define IS_BIG_ENDIAN TRUE
+#else
+# define IS_BIG_ENDIAN FALSE
+#endif
+
+#define OUTPUT_BUFSIZE (4096 * 8)
+
+extern OutputPlugin op;
+
+
+struct format_info 
+{
+	union 
+	{
+		AFormat xmms;
+		int osx;
+	} format;
+
+
+	int frequency;
+	int channels;
+	int bps;
+};
+
+
+typedef struct
+{
+	gint audio_device;
+	gint mixer_device;
+	gint buffer_size;
+	gint prebuffer;
+	gboolean use_master;
+	gboolean use_alt_audio_device, use_alt_mixer_device;
+	gchar *alt_audio_device, *alt_mixer_device;
+}
+OSXConfig;
+
+extern OSXConfig osx_cfg;
+
+void osx_init(void);
+void osx_about(void);
+void osx_configure(void);
+
+void osx_get_volume(int *l, int *r);
+void osx_set_volume(int l, int r);
+
+int osx_playing(void);
+int osx_free(void);
+void osx_write(void *ptr, int length);
+void osx_close(void);
+void osx_flush(int time);
+void osx_pause(short p);
+int osx_open(AFormat fmt, int rate, int nch);
+int osx_get_output_time(void);
+int osx_get_written_time(void);
+void osx_set_audio_params(void);
+
+void* osx_get_convert_buffer(size_t size);
+int (*osx_get_convert_func(int output, int input))(void **, int);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Output/CoreAudio/dbaudiolib.h	Thu Sep 07 11:32:59 2006 -0700
@@ -0,0 +1,231 @@
+/*
+
+  Definitions for dbaudiolib.c
+
+  Author:  Bob Dean
+  Copyright (c) 1999
+
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public Licensse as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#ifndef __DB_AUDIOLIB_H_
+#define __DB_AUDIOLIB_H_
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+	
+#include <glib.h>
+/* #include <dbchannel.h> */
+	
+#define  DBAUDIOLIB_VERSION "0.9.8";
+	
+	
+	/* DBAudioLib Error Codes */
+	/* when possible the actual system error code is left in errno, since it
+	   more specifically describes the error */
+
+	enum {
+		ERROR_BASE = 50000,
+		ERROR_NOT_IMPLEMENTED,    /* user tried to access functionality that has not yet been implemented. */
+		ERROR_BAD_CHANNEL,        /* unknown channel type */
+		ERROR_BAD_PARAM,          /* function recieved a bad parameter*/
+		ERROR_NO_FREE_CHANNELS,   /* all channels are in use */
+		ERROR_TOO_MUCH_DATA,      /* the client gave too muxh data to dbaudiolib, conversion would overrun the internal buffers */
+		ERROR_BAD_SAMPLERATE,     /* the samplerate provided is not supported */
+		ERROR_BAD_CHANNELTYPE,    /* the channeltype provided is not supported */
+		ERROR_BAD_NUMCH,          /* the number of audio channels (stereo or mono) is not supported */
+		ERROR_BAD_FORMAT,         /* the input audio format is not supported */
+		ERROR_CHANNEL_IN_USE,     /* the requested channel index passed to DBAudio_Init is already in use */
+		ERROR_BAD_CHANNEL_ID,     /* the requested channel index passed to DBAudio_Init is out of range */
+		ERROR_TOO_LITTLE_DATA,    /* the client gave too little data to dbaudiolib - depreciated */
+		ERROR_NOT_INITIALIZED,    /* attempted to use dbaudiolib without a call to DBAudio_Init first */
+		ERROR_INIT_FAILURE        /* some part of the init process not related to dbmix failed */
+	};
+
+
+	/* enumeration of sampler state */
+	enum sampler_state_e {SAMPLER_OFF,
+						  SAMPLER_RECORD,
+						  SAMPLER_PLAY_SINGLE,
+						  SAMPLER_PLAY_LOOP,
+						  SAMPLER_READY};
+	
+	typedef enum sampler_state_e sampler_state;
+
+#define DBAUDIO_MAX_VOLUME             100
+#define DBAUDIO_INTERNAL_MAX_VOLUME    128
+#define DBAUDIO_MIN_VOLUME             0
+
+#define DBMIX_COPYRIGHT "Copyright (c) 2002 by Robert Michael S Dean"
+#define DBMIX_VERSION   "v0.9.8"
+
+#define SUCCESS                     0
+#define FAILURE                    -1
+
+#ifndef TRUE
+#define TRUE                        1
+#endif
+
+#ifndef FALSE
+#define FALSE                       0
+#endif
+
+#define MONO                        1
+#define STEREO                      2
+
+
+	/*
+	 * Message structure used to communicate within dbmix channels
+	 */
+
+#define DBMSG_NONE         0x00000000
+#define DBMSG_ALL          (0xFFFFFFFF & ~DBMSG_SAMPLERLOAD & ~DBMSG_SAMPLERSAVE)
+#define DBMSG_PAUSE        0x00000001
+#define DBMSG_UNPAUSE      0x00000002
+#define DBMSG_PLAY         0x00000004
+#define DBMSG_STOP         0x00000008
+#define DBMSG_EJECT        0x00000010
+#define DBMSG_REWIND       0x00000020
+#define DBMSG_FFORWARD     0x00000040
+#define DBMSG_NEXT         0x00000080
+#define DBMSG_PREV         0x00000100
+#define DBMSG_MUTE         0x00000200
+#define DBMSG_UNMUTE       0x00000400
+#define DBMSG_SAMPLERSIZE  0x00000800
+#define DBMSG_SAMPLERSAVE  0x00001000
+#define DBMSG_SAMPLERLOAD  0x00002000
+#define DBMSG_SAMPLERREC   0x00004000
+#define DBMSG_SAMPLERSTOP  0x00008000
+#define DBMSG_SAMPLERLOOP  0x00010000
+#define DBMSG_SAMPLERONCE  0x00020000
+
+	typedef struct dbfsd_msg_s
+	{
+		long int   msg_type;
+		float      data;
+		char *     datastr;
+	} dbfsd_msg;
+
+	/* enumeration of the different channels types */
+	enum channel_type_e {PIPE_CHANNEL, SOCKET_CHANNEL};
+
+	/* DBAudioLib Prototypes for statically linked libraries */
+	int    DBAudio_Init(char * name, int fmt, int rte, int numch,
+						enum channel_type_e type, int chindex);
+	int    DBAudio_Ready();
+	int    DBAudio_Write(char* buf, int len);
+	int    DBAudio_Read(char * buf, int count);
+	int    DBAudio_Close();
+	int    DBAudio_Set_Volume(int left, int right);
+	int    DBAudio_Get_Volume(int *left, int *right);
+	int    DBAudio_Pause(int value);
+	char * DBAudio_Get_Version();
+	char * DBAudio_Get_Channel_Name(char * name);
+	int    DBAudio_Set_Channel_Name(char * name);
+	enum channel_type_e DBAudio_Get_Channel_Type();
+	int    DBAudio_Set_Channel_Type(enum channel_type_e type);
+	int    DBAudio_Cue_Enabled();
+	int    DBAudio_Set_Cue(int flag);
+	int    DBAudio_Get_Cue();
+	int    DBAudio_Set_Rate(int rte);
+	int    DBAudio_Get_Rate();
+	int    DBAudio_Set_Channels(int numch);
+	int    DBAudio_Get_Channels();
+	int    DBAudio_Set_Format(int fmt);
+	int    DBAudio_Get_Format();
+	int    DBAudio_Get_Bufsize(int input_bufsize);
+	void   DBAudio_perror(char *str);
+	int    DBAudio_Set_Message_Handler(void(*message_handler)(dbfsd_msg msg), int msg_flags);
+	int    DBAudio_Handle_Message_Queue();
+	int    DBAudio_Set_Channel_Flag(unsigned int flag);
+	int    DBAudio_Clear_Channel_Flag(unsigned int flag);
+	unsigned int DBAudio_Get_Channel_Flags();
+	int    DBAudio_Set_Mute(int value);
+	int    DBAudio_Get_Mute();
+	int    DBAudio_Sampler_Record();
+	int    DBAudio_Sampler_Stop();
+	int    DBAudio_Sampler_Loop();
+	int    DBAudio_Sampler_Single();
+	int    DBAudio_Sampler_Get_Offsets(int * start_offset, int * end_offset);
+	int    DBAudio_Sampler_Set_Offsets(int start_offset, int end_offset);
+	int    DBAudio_Sampler_Get_Size(int * size);
+	int    DBAudio_Sampler_Save(char * filename);
+	int    DBAudio_Sampler_Load(char * filename);
+	sampler_state DBAudio_Sampler_Get_State();
+
+/* structure to hold audiolib functions plugin style for dynamically linked
+    libraries... 
+	As functions are added, they are placed at the end of the struct so as
+    not to break clients using older versions of the library
+*/
+	typedef struct
+	{ 
+		int    (*DBAudio_Init)(char * name, int fmt, int rte, int numch,
+							   enum channel_type_e type, int chindex);
+		int    (*DBAudio_Ready)();
+		int    (*DBAudio_Write)(char* buf, int len);
+		int    (*DBAudio_Read)(char * buf, int count);
+		int    (*DBAudio_Close)();
+		int    (*DBAudio_Set_Volume)(int left, int right);
+		int    (*DBAudio_Get_Volume)(int *left, int *right);
+		int    (*DBAudio_Pause)(int value);
+		char * (*DBAudio_Get_Version)();
+		char * (*DBAudio_Get_Channel_Name)(char * name);
+		int    (*DBAudio_Set_Channel_Name)(char * name);
+		enum channel_type_e (*DBAudio_Get_Channel_Type)();
+		int    (*DBAudio_Set_Channel_Type)(enum channel_type_e type);
+		int    (*DBAudio_Cue_Enabled)();
+		int    (*DBAudio_Set_Rate)(int rte);
+		int    (*DBAudio_Get_Rate)();
+		int    (*DBAudio_Set_Channels)(int numch);
+		int    (*DBAudio_Get_Channels)();
+		int    (*DBAudio_Set_Format)(int fmt);
+		int    (*DBAudio_Get_Format)();
+		int    (*DBAudio_Set_Cue)(int flag);
+		int    (*DBAudio_Get_Cue)();
+		int    (*DBAudio_Get_Bufsize)(int input_bufsize);	
+		void   (*DBAudio_perror)(char *str);
+		int    (*DBAudio_Set_Message_Handler)(void(*message_handler)(dbfsd_msg msg),int msg_flags);
+		int    (*DBAudio_Handle_Message_Queue)();
+		int    (*DBAudio_Set_Channel_Flag)(unsigned int flag);
+		int    (*DBAudio_Clear_Channel_Flag)(unsigned int flag);
+		unsigned int (* DBAudio_Get_Channel_Flags)();
+		int    (*DBAudio_Set_Mute)(int value);
+		int    (*DBAudio_Get_Mute)();
+		int    (*DBAudio_Sampler_Record)();
+		int    (*DBAudio_Sampler_Stop)();
+		int    (*DBAudio_Sampler_Loop)();
+		int    (*DBAudio_Sampler_Single)();
+		int    (*DBAudio_Sampler_Get_Offsets)(int * start_offset, int * end_offset);
+		int    (*DBAudio_Sampler_Set_Offsets)(int start_offset, int end_offset);
+		int    (*DBAudio_Sampler_Get_Size)(int * size);
+		int    (*DBAudio_Sampler_Save)(char * filename);
+		int    (*DBAudio_Sampler_Load)(char * filename);
+		sampler_state (*DBAudio_Sampler_Get_State)();
+	} DBAudioLibFunctions;
+	
+	DBAudioLibFunctions * DBAudio_Get_Functions();
+	
+	
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DB_AUDIOLIB_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Output/CoreAudio/dbconvert.c	Thu Sep 07 11:32:59 2006 -0700
@@ -0,0 +1,524 @@
+/*
+
+  Author:  Bob Dean
+  Copyright (c) 1999 - 2004
+
+  The functionality in this file is modified from DBAudio_Write.c. 
+  part of the DBMix project which is also released under the GPL.
+  It is used here both as licensed under the GPL and additionally 
+  by permission of the original author (which is me).
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public Licensse as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+ 
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <sys/shm.h>
+#include <glib.h>
+#include <math.h>
+#include <string.h>
+	
+#include "coreaudio.h"
+#include "dbaudiolib.h"
+
+	extern int errno;
+	
+	extern gboolean paused;
+	extern float left_volume, right_volume;
+
+	extern float base_pitch;
+	extern float user_pitch;
+	
+
+	float local_pitch;
+	float sample1, sample2;
+	float float_index;
+	
+	extern signed short output_buf[];  /* buffer used to hold main output to dbfsd */
+	extern signed short cue_buf[];     /* buffer used to hold cue output to dbfsd */
+	extern signed short conv_buf[];    /* buffer used to hold format converted input */
+	extern int output_buf_length;
+	
+	int outlen;
+	int sampleindex;
+	int num_channels;
+	int format;
+
+
+	extern struct format_info input;
+
+	
+	/*
+	  dbconvert - given a buf of length len, write the data to the
+	  channel associated with this instance.
+
+	  On success, the number of bytes written is returned. Otherwise
+	  -1, or FAILURE, is returned, and errno is set accordingly.
+
+	  Hopefully this function returns values in the same fashion
+	  as other basic I/O functions such as read() and write()
+
+	  Variables: 
+	  count is the number of bytes written during a loop iteration
+	  totalcount is the total number of bytes written
+	  left_gain and right_gain are percentages used to adjust the 
+	  output signal volume
+	  tempbuf is a temporary pointer used in the volume operation
+	  temp_chbuf is a pointer to the buffer to be written to during
+	  shared memory mode.
+	*/
+
+	int dbconvert(char* buf, int len)
+	{
+		int left_gain,right_gain;
+		int left_cue_gain, right_cue_gain;
+		signed short * tempbuf, *tempbuf2, * tempoutbuf;
+		char * tempcharbuf;
+		int incr_flag, count;
+		int intindex;
+		float buflen, gain1, gain2;
+		int   index1,index2, output_sample;
+		int i;
+		int stereo_multiplier,format_multiplier;
+		int tempsize;
+		int sampler_flag;
+		//enum sampler_state_e local_sampler_state;
+
+		/* check parameters */
+		if (buf == NULL) {errno = ERROR_BAD_PARAM; return FAILURE;}
+		//if (ch == NULL)  {errno = ERROR_NOT_INITIALIZED; return FAILURE;}
+		if (len < 0)     {errno = ERROR_BAD_PARAM; return FAILURE;}
+	
+		//DBAudio_Handle_Message_Queue();
+		
+		/* remember sampler state as it may change during
+		   the course of the function */
+#ifdef COMPILE_SAMPLER
+		local_sampler_state = ch->sampler_state;
+#endif
+
+		if (paused)
+		{
+			//printf("convert: pauseed\n");
+			return 0;
+		}
+
+		/* get pitch */
+		local_pitch = base_pitch * user_pitch;
+
+		//printf("convert: local pitch is %.2f, base %.2f user %.2f\n",local_pitch,base_pitch,user_pitch);
+		buflen = len / 2.0;
+	
+		//printf("convert: buflen %.2f len is %d\n",buflen,len);
+
+		/* calculate buffer space needed to convert the data to 
+		   44.1kHz 16bit stereo*/
+		switch (input.channels)
+		{
+			case 1:  stereo_multiplier = 2; break;
+			case 2:  stereo_multiplier = 1; break;
+			default: errno = ERROR_BAD_NUMCH; return FAILURE;
+		}
+		
+		//printf("convert: format %d, %d %d %d %d\n",input.format.xmms,FMT_U8,FMT_S8,FMT_S16_LE,FMT_S16_BE);
+
+		switch (input.format.xmms)
+		{
+			case FMT_U8:     format_multiplier = 2; break;
+			case FMT_S8:     format_multiplier = 2; break;
+			case FMT_S16_LE: format_multiplier = 1; break;
+			case FMT_S16_BE: format_multiplier = 1; break;
+			case FMT_S16_NE: format_multiplier = 1; break;
+			default: errno = ERROR_BAD_FORMAT; return FAILURE;
+		}
+		
+		/* return error if the needed output space is greater than the
+		   output buffer */
+		if (ceil((buflen * (float)stereo_multiplier * 
+				  (float)format_multiplier) / local_pitch) > (float)(OUTPUT_BUFSIZE))
+		{
+			errno = ERROR_TOO_MUCH_DATA; 
+			return FAILURE;
+		}
+		
+		/* init local variables */
+		intindex = 0;
+		incr_flag = 0;
+		sampleindex = 0;
+		gain1 = gain2 = 0.0;
+		sample1 = sample2 = 0.0;
+		sampler_flag = 0;
+
+		left_gain = (int)(128.0 * left_volume);
+		right_gain = (int)(128.0 * right_volume);
+
+	
+#ifdef COMPILE_CUE
+		left_cue_gain = ch->cue_left_gain;
+		right_cue_gain = ch->cue_right_gain;
+
+		/* calculate gain percentages */
+		if (ch->mute == TRUE)
+		{
+			left_gain = right_gain = 0;
+		}
+		else
+		{
+			left_gain = ch->left_gain * sysdata->left_balance;
+			right_gain = ch->right_gain * sysdata->right_balance;
+	
+			/* cut volume if mic is being used */
+			if (sysdata->talkover_enabled && !(MIC_ENABLED))
+			{
+				left_gain = left_gain >> DB_TALKOVER_DIVISOR_POWER;
+				right_gain = right_gain >> DB_TALKOVER_DIVISOR_POWER;
+			}
+		}
+#endif
+
+#ifdef COMPILE_SAMPLER
+		switch (local_sampler_state)
+		{
+			case SAMPLER_PLAY_SINGLE:
+			case SAMPLER_PLAY_LOOP:				
+
+				if (ch->sampler_size == 0)
+				{
+					ch->sampler_state = SAMPLER_OFF;
+					len = 0;
+					goto done;
+				}
+				
+				/* tempsize - amount of data available in buffer to read */
+				tempsize = (ch->sampler_endoffset - ch->sampler_readoffset);
+
+				sampler_flag = 1;
+
+				/* if we are in loop mode and loop over end of buffer, 
+                   get data from start of buffer */
+				if ((tempsize < len) && (local_sampler_state == SAMPLER_PLAY_LOOP))
+				{
+					/* copy portion at end of buffer */
+					memcpy(conv_buf,(ch->sampler_buf + ch->sampler_readoffset),tempsize);
+					/* copy portion at beginning of buffer */
+					memcpy(conv_buf+tempsize,ch->sampler_buf+ch->sampler_startoffset,(len - tempsize));
+					/* update variables */
+					/* read offset is now amount to write, minus the overflow, plus the startoffset */
+					ch->sampler_readoffset = len - tempsize + ch->sampler_startoffset;
+					tempsize = len;
+				}
+				else
+				{
+					/* if we are in simgle play mode and out of data, reset state
+                       and exit */
+					if ((tempsize <= 0) && (local_sampler_state == SAMPLER_PLAY_SINGLE))
+					{
+						ch->sampler_state = SAMPLER_READY;
+						goto done;
+					}
+
+					/* get full buffers worth of data from somewhere in middle of 
+                       sampler buffer  */
+					if (tempsize > len) tempsize = len;
+
+					memcpy(conv_buf,(ch->sampler_buf + ch->sampler_readoffset),tempsize);
+
+					ch->sampler_readoffset += tempsize;
+				}
+
+
+				/* update function state variables */
+				buflen = (tempsize / 2);
+				tempbuf = conv_buf;
+
+				break;
+			default:
+#endif
+				{
+					/* convert input data into 44.1 KHz 16 bit stereo */
+					tempbuf = (signed short *) buf;
+					
+					/* convert mono input to stereo */
+					if (input.channels == 1)
+					{
+						//printf("convert: data is mono\n");
+
+						tempbuf2 = conv_buf;
+						
+						if ((input.format.xmms == FMT_U8) || (input.format.xmms == FMT_S8))
+						{
+							tempcharbuf = buf;
+							
+							for (i = 0; i < buflen*2.0; i++)
+							{
+								*tempbuf2 = *tempcharbuf; tempbuf2++;
+								*tempbuf2 = *tempcharbuf; tempbuf2++; tempcharbuf++;
+							}
+						} 
+						else 
+						{
+							for (i = 0; i < buflen; i++)
+							{
+								*tempbuf2 = *tempbuf; tempbuf2++;
+								*tempbuf2 = *tempbuf; tempbuf2++; tempbuf++;
+							}
+						}
+						
+						buflen *=2.0;
+						tempbuf = conv_buf;
+					}
+					else
+					{
+						//printf("convet: data is stereo\n");
+					}
+					
+		//printf("convert: buflen %.2f\n",buflen);
+
+
+					/* convert 8 bit input to 16 bit input */
+					if ((input.format.xmms != FMT_S16_LE) && (input.format.xmms != FMT_S16_BE) 
+						&& (input.format.xmms != FMT_S16_NE))
+					{
+						switch (input.format.xmms)
+						{
+							case FMT_U8:
+							{
+								//printf("convert: converting unsigned 8 bit\n");
+								
+								tempbuf2 = conv_buf;
+								buflen *= 2.0;
+								
+								/* if data was mono, then it is already in conv_buf */
+								if (input.channels == 1)
+								{
+									for (i = 0; i < buflen; i++)
+									{
+										*tempbuf = (*tempbuf2 - 127) << 8;
+										tempbuf++; tempbuf2++;
+									}
+								}
+								else
+								{   /* data is 8 bit stereo, and is in buf not conv_buf*/
+									tempcharbuf = buf;
+									for (i = 0; i < len; i++)
+									{
+										*tempbuf = (*tempcharbuf - 127) << 8;
+										tempbuf++; tempcharbuf++;
+									}			
+								}
+								
+								tempbuf = conv_buf;
+								break;
+							}
+							case FMT_S8:
+							{
+								//printf("convert: converting signed 8 bit\n");
+
+								tempbuf2 = conv_buf;
+								buflen *= 2.0;
+								
+								/* if data was mono, then it is already in conv_buf */
+								if (input.channels == 1)
+								{
+									for (i = 0; i < buflen; i++)
+									{
+										*tempbuf = *tempbuf2 << 8;
+										tempbuf++; tempbuf2++;
+									}
+								}
+								else
+								{   /* data is 8 bit stereo, and is in buf not conv_buf*/
+									tempcharbuf = buf;
+									for (i = 0; i < len; i++)
+									{
+										*tempbuf = *tempcharbuf << 8;
+										tempbuf++; tempcharbuf++;
+									}			
+								}
+								
+								tempbuf = conv_buf;
+								break;
+							}
+							default: 
+							{
+								errno = ERROR_BAD_FORMAT; 
+								//ch->writing = 0;
+								return FAILURE;
+							}
+						}
+					}	
+				} /* end default case*/
+
+		//printf("convert: buflen %.2f\n",buflen);
+
+
+
+#ifdef COMPILE_SAMPLER
+		} /* end switch sampler_state */
+
+		/* copy buffer to sample buffer if sampler state is record */
+		if (local_sampler_state == SAMPLER_RECORD)
+		{
+			tempsize = 0;
+
+			/* get amount of data to copy */
+			if ((ch->sampler_size + (buflen * 2)) > ch->sampler_bufsize)
+			{
+				tempsize = ch->sampler_bufsize - ch->sampler_size;
+			}
+			else
+			{
+				tempsize = (buflen * 2);
+			}
+
+			/* change state if buffer is full */
+			if (tempsize == 0)
+			{
+				ch->sampler_state = SAMPLER_READY;
+			}
+			
+			/* copy data */
+			memcpy(((ch->sampler_buf) + (ch->sampler_size)),tempbuf,tempsize);
+
+			/* update sampler state variables */
+			ch->sampler_size += tempsize;
+			ch->sampler_endoffset = ch->sampler_size;
+		}
+#endif
+
+		if (local_pitch == 1.0)
+		{
+			//printf("convert: pitch optimization buflen %.2f *2 %.2f\n",buflen,buflen*2);
+			//printf("tempbuf is 0x%x, output_buf is 0x%x\n",tempbuf,output_buf);
+			memcpy(output_buf,tempbuf,buflen*2);
+			
+			outlen = buflen*2;
+			tempbuf = output_buf;
+			output_buf_length = buflen;
+			
+			goto done;
+		}
+
+		/* calculate pitch shifted signal using basic linear interpolation
+		   the theory is this:
+		   you have two known samples, and want to calculate the value of a new sample
+		   in between them.  The new sample will contain a percentage of the first sample
+		   and a percentage of the second sample.  These percentages are porportional
+		   to the distance between the new sample and each of the knwon samples.
+		   The "position" of the new sample is determined by the float index */
+
+		tempoutbuf = output_buf;
+
+		while (intindex < buflen)
+		{
+			/* calculate sample percentages (amplitude) */
+			intindex = floor(float_index);
+			gain2 = float_index - intindex;
+			gain1 = 1.0 - gain2;
+
+			/* get index of first sample pair */
+			intindex = intindex << 1;
+			
+			/* check incr_flag to see if we should be operatiing 
+			   on the left or right channel sample */
+			if (incr_flag) 
+			{ 
+				float_index += local_pitch; 
+				incr_flag = 0; 
+				intindex++;
+			}
+			else
+			{
+				incr_flag = 1;
+			}
+			
+			index1 = intindex;
+			
+			/* get the first "known" sample*/
+			sample1 = tempbuf[index1];
+			index2 = index1 + 2; 
+			
+			/* get the second "known" sample */
+			if (index2 < (buflen))
+			{
+				sample2 = tempbuf[index2];
+			}
+			else
+				/* if index2 is beyond the length of the input buffer,
+                   then cheat to prevent audio pops/snaps/etc */
+			{
+				*tempoutbuf = sample1;
+				sampleindex++;
+				break;
+			}
+			
+			/* create the new sample */
+			output_sample = (((float)sample1 * gain1) + ((float)sample2 * gain2));
+			
+			if (output_sample > 32767)  {output_sample = 32767;}
+			if (output_sample < -32767)	{output_sample = -32767;}
+			
+			*tempoutbuf = output_sample;
+			tempoutbuf++;
+			
+			sampleindex++;
+		}
+
+		/* update global variables */
+		outlen = (sampleindex-1) << 1;
+		
+		float_index = float_index - floor(float_index);
+		
+		tempbuf = output_buf;
+
+		output_buf_length = sampleindex - 1;
+		
+		/* 	if (outlen < PIPE_BUF)
+			{errno = ERROR_TOO_LITTLE_DATA; return FAILURE;} */
+
+	apply_gain:
+
+	
+	done:
+
+		//ch->writing = 0;
+
+		if (sampler_flag)
+		{
+			return 0;
+		}
+		else
+		{
+			return len;
+		}
+	}
+
+#ifdef __cplusplus
+}
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Output/CoreAudio/init.c	Thu Sep 07 11:32:59 2006 -0700
@@ -0,0 +1,55 @@
+/*  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "coreaudio.h"
+#include "libaudacious/configdb.h"
+
+OSXConfig osx_cfg;
+
+extern float left_volume, right_volume;
+
+void osx_init(void)
+{
+	ConfigDb *cfgfile;
+
+	left_volume = 1.0;
+	right_volume = 1.0;
+
+	memset(&osx_cfg, 0, sizeof (OSXConfig));
+
+	osx_cfg.audio_device = 0;
+	osx_cfg.mixer_device = 0;
+	osx_cfg.buffer_size = 3000;
+	osx_cfg.prebuffer = 25;
+	osx_cfg.use_alt_audio_device = FALSE;
+	osx_cfg.alt_audio_device = NULL;
+	osx_cfg.use_master=0;
+	
+	if ((cfgfile = bmp_cfg_db_open()))
+	{
+		bmp_cfg_db_get_int(cfgfile, "OSX", "audio_device", &osx_cfg.audio_device);
+		bmp_cfg_db_get_int(cfgfile, "OSX", "mixer_device", &osx_cfg.mixer_device);
+		bmp_cfg_db_get_int(cfgfile, "OSX", "buffer_size", &osx_cfg.buffer_size);
+		bmp_cfg_db_get_int(cfgfile, "OSX", "prebuffer", &osx_cfg.prebuffer);
+		bmp_cfg_db_get_bool(cfgfile, "OSX", "use_master", &osx_cfg.use_master);
+		bmp_cfg_db_get_bool(cfgfile, "OSX", "use_alt_audio_device", &osx_cfg.use_alt_audio_device);
+		bmp_cfg_db_get_string(cfgfile, "OSX", "alt_audio_device", &osx_cfg.alt_audio_device);
+		bmp_cfg_db_get_bool(cfgfile, "OSX", "use_alt_mixer_device", &osx_cfg.use_alt_mixer_device);
+		bmp_cfg_db_get_string(cfgfile, "OSX", "alt_mixer_device", &osx_cfg.alt_mixer_device);
+		bmp_cfg_db_close(cfgfile);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Output/CoreAudio/mixer.c	Thu Sep 07 11:32:59 2006 -0700
@@ -0,0 +1,81 @@
+/*  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "coreaudio.h"
+#include <errno.h>
+#include <CoreAudio/CoreAudio.h>
+
+extern AudioDeviceID device_id;
+extern gboolean playing_flag;
+extern float left_volume, right_volume;
+
+void osx_get_volume(int *l, int *r)
+{
+	*l = left_volume * 100;
+	*r = right_volume * 100;
+
+#if 0
+	float  volume;
+	UInt32 size;
+	AudioDeviceID temp_device_id;
+
+	size = sizeof(float);
+
+	AudioDeviceGetProperty(device_id,1,0,kAudioDevicePropertyVolumeScalar,&size,&volume);
+
+	volume = volume * 100;
+
+	*r = volume;
+	*l = volume;
+#endif
+}
+
+
+void osx_set_volume(int l, int r)
+{
+	left_volume = (float)l / 100.0;
+	right_volume = (float) r / 100.0;
+
+
+#if 0
+	int fd, v, cmd, devs;
+	gchar *devname;
+
+	Boolean writeable_flag; 
+
+	if (AudioDeviceGetPropertyInfo(device_id,1,false,kAudioDevicePropertyVolumeScalar,NULL,&writeable_flag))
+	{
+		printf("could not get property info for volume write\n");
+	}
+	else 
+	{
+		if (writeable_flag)
+		{
+			float  volume;
+
+			volume = l / 100.0;
+			AudioDeviceSetProperty(device_id,NULL,1,0,kAudioDevicePropertyVolumeScalar,sizeof(float),&volume);
+		}
+		else
+		{
+			printf("volume property is not writeable\n");
+		}
+	}
+#endif
+}
+
+