Mercurial > audlegacy
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 +} + +