changeset 5684:b61520e71679

[gaim-migrate @ 6104] sound is now really core/ui split. committer: Tailor Script <tailor@pidgin.im>
author Nathan Walp <nwalp@pidgin.im>
date Tue, 03 Jun 2003 03:33:20 +0000
parents 9befba33f7c8
children 43ea75092684
files plugins/docklet/docklet.c src/Makefile.am src/gaimrc.c src/gtkdebug.c src/gtkprefs.c src/gtksound.c src/gtksound.h src/main.c src/prefs.c src/prefs.h src/sound.c src/sound.h
diffstat 12 files changed, 654 insertions(+), 493 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/docklet/docklet.c	Tue Jun 03 02:30:30 2003 +0000
+++ b/plugins/docklet/docklet.c	Tue Jun 03 03:33:20 2003 +0000
@@ -32,6 +32,7 @@
 #include "gtkaccount.h"
 #include "gaim.h"
 #include "sound.h"
+#include "gtksound.h"
 #include "prefs.h"
 #include "gtkblist.h"
 #include "eggtrayicon.h"
@@ -61,7 +62,7 @@
 static enum docklet_status icon;
 
 static void docklet_toggle_mute(GtkWidget *toggle, void *data) {
-	gaim_sound_set_mute(GTK_CHECK_MENU_ITEM(toggle)->active);
+	gaim_gtk_sound_set_mute(GTK_CHECK_MENU_ITEM(toggle)->active);
 }
 
 static void docklet_set_bool(GtkWidget *widget, const char *key) {
@@ -144,7 +145,7 @@
 	gaim_separator(menu);
 
 	entry = gtk_check_menu_item_new_with_label(_("Mute Sounds"));
-	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(entry), gaim_sound_get_mute());
+	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(entry), gaim_gtk_sound_get_mute());
 	g_signal_connect(G_OBJECT(entry), "toggled", G_CALLBACK(docklet_toggle_mute), NULL);
 	gtk_menu_shell_append(GTK_MENU_SHELL(menu), entry);
 
@@ -442,7 +443,7 @@
 	docklet = NULL;
 
 	/* do this while gaim has no other way to toggle the global mute */
-	gaim_sound_set_mute(FALSE);
+	gaim_gtk_sound_set_mute(FALSE);
 
 	gaim_debug(GAIM_DEBUG_INFO, "docklet", "Tray Icon: removed\n");
 
--- a/src/Makefile.am	Tue Jun 03 02:30:30 2003 +0000
+++ b/src/Makefile.am	Tue Jun 03 03:33:20 2003 +0000
@@ -83,6 +83,8 @@
 	gtkpounce.h \
 	gtkrequest.c \
 	gtkrequest.h \
+	gtksound.c \
+	gtksound.h \
 	gtkutils.c \
 	gtkutils.h \
 	html.c \
--- a/src/gaimrc.c	Tue Jun 03 02:30:30 2003 +0000
+++ b/src/gaimrc.c	Tue Jun 03 03:33:20 2003 +0000
@@ -40,6 +40,7 @@
 #include "prefs.h"
 #include "proxy.h"
 #include "sound.h"
+#include "gtksound.h"
 #include "pounce.h"
 #include "gtkpounce.h"
 #include "notify.h"
@@ -942,10 +943,8 @@
 
 		} else if (!strcmp(p->option, "sound_options")) {
 			sound_options = atoi(p->value[0]);
-			gaim_sound_change_output_method();
-			/* XXX: still need to convert these */
-			/* XXX: but first we need to figure out where the split is
-			 * for sounds */
+			/* XXX: figure out the mapping between the options
+			 * and the new sound method option */
 		} else if (!strcmp(p->option, "away_options")) {
 			away_options = atoi(p->value[0]);
 			gaim_prefs_set_bool("/core/conversations/away_back_on_send",
@@ -1065,7 +1064,7 @@
 	if (!(sound_options & (OPT_SOUND_BEEP | OPT_SOUND_NORMAL | OPT_SOUND_ESD
 					| OPT_SOUND_ARTS | OPT_SOUND_NAS | OPT_SOUND_CMD))) {
 		sound_options |= OPT_SOUND_NORMAL;
-		gaim_sound_change_output_method();
+		/* XXX: I don't think we need this anymore */
 	}
 
 	if (read_general) {
@@ -1112,11 +1111,16 @@
 	char buf[2048];
 	struct parse parse_buffer;
 	struct parse *p;
+	char *pref_name;
 
 	buf[0] = 0;
 
-	for(i=0; i<GAIM_NUM_SOUNDS; i++)
-		gaim_sound_set_event_file(i, NULL);
+	for(i=0; i<GAIM_NUM_SOUNDS; i++) {
+		pref_name = g_strdup_printf("/gaim/gtk/sound/file/%s",
+				gaim_gtk_sound_get_event_option(i));
+		gaim_prefs_set_string(pref_name, "");
+		g_free(pref_name);
+	}
 
 	while (buf[0] != '}') {
 		if (buf[0] == '#')
@@ -1128,14 +1132,15 @@
 		p = parse_line(buf, &parse_buffer);
 #ifndef _WIN32
 		if (!strcmp(p->option, "sound_cmd")) {
-			gaim_sound_set_command(p->value[0]);
+			gaim_prefs_set_string("/gaim/gtk/sound/command", p->value[0]);
 		} else
 #endif
 		if (!strncmp(p->option, "sound", strlen("sound"))) {
 			i = p->option[strlen("sound")] - 'A';
 
-			if (p->value[0][0])
-				gaim_sound_set_event_file(i, p->value[0]);
+			pref_name = g_strdup_printf("/gaim/gtk/sound/file/%s",
+					gaim_gtk_sound_get_event_option(i));
+			gaim_prefs_set_string(pref_name, p->value[0]);
 		}
 	}
 }
--- a/src/gtkdebug.c	Tue Jun 03 02:30:30 2003 +0000
+++ b/src/gtkdebug.c	Tue Jun 03 03:33:20 2003 +0000
@@ -196,8 +196,23 @@
 void
 gaim_gtk_debug_init(void)
 {
+	/* Debug window preferences. */
+	/*
+	 * NOTE: This must be set before prefs are loaded, and the callbacks
+	 *       set after they are loaded, since prefs sets the enabled
+	 *       preference here and that loads the window, which calls the
+	 *       configure event, which overrrides the width and height! :P
+	 */
+
+	gaim_prefs_add_none("/gaim/gtk/debug");
+	gaim_prefs_add_bool("/gaim/gtk/debug/enabled", FALSE);
+	gaim_prefs_add_bool("/gaim/gtk/debug/timestamps", FALSE);
+	gaim_prefs_add_bool("/gaim/gtk/debug/toolbar", TRUE);
+	gaim_prefs_add_int("/gaim/gtk/debug/width",  450);
+	gaim_prefs_add_int("/gaim/gtk/debug/height", 250);
+
 	gaim_prefs_connect_callback("/gaim/gtk/debug/enabled",
-								debug_enabled_cb, NULL);
+			debug_enabled_cb, NULL);
 }
 
 void
--- a/src/gtkprefs.c	Tue Jun 03 02:30:30 2003 +0000
+++ b/src/gtkprefs.c	Tue Jun 03 03:33:20 2003 +0000
@@ -47,6 +47,7 @@
 #include "prefs.h"
 #include "proxy.h"
 #include "sound.h"
+#include "gtksound.h"
 #include "notify.h"
 
 #ifdef _WIN32
@@ -1386,7 +1387,8 @@
 #ifndef _WIN32
 static gint sound_cmd_yeah(GtkEntry *entry, gpointer d)
 {
-	gaim_sound_set_command(gtk_entry_get_text(GTK_ENTRY(sndcmd)));
+	gaim_prefs_set_string("/gaim/gtk/sound/command",
+			gtk_entry_get_text(GTK_ENTRY(sndcmd)));
 	return TRUE;
 }
 #endif
@@ -1399,7 +1401,7 @@
 	GtkWidget *dd;
 	GtkWidget *hbox;
 	GtkWidget *label;
-	char *cmd;
+	const char *cmd;
 #endif
 
 	ret = gtk_vbox_new(FALSE, 18);
@@ -1411,12 +1413,12 @@
 	prefs_checkbox(_("_No sounds when you log in"),
 				   "/gaim/gtk/sound/silent_signon", vbox);
 	prefs_checkbox(_("_Sounds while away"),
-				   "/gaim/gtk/sound/while_away", vbox);
+				   "/core/sound/while_away", vbox);
 
 #ifndef _WIN32
 	vbox = gaim_gtk_make_frame (ret, _("Sound Method"));
 	dd = prefs_dropdown(vbox, _("_Method"), GAIM_PREF_STRING,
-						"/gaim/gtk/sound/sound_method",
+						"/gaim/gtk/sound/method",
 						_("Console beep"), "beep",
 #ifdef USE_AO
 						_("Automatic"), "automatic",
@@ -1426,7 +1428,7 @@
 #ifdef USE_NAS_AUDIO
 						"NAS", "nas",
 #endif
-						_("Command"), "custom_command",
+						_("Command"), "custom",
 						NULL);
 	gtk_size_group_add_widget(sg, dd);
 	gtk_misc_set_alignment(GTK_MISC(dd), 0, 0);
@@ -1445,13 +1447,13 @@
 	gtk_label_set_mnemonic_widget(GTK_LABEL(label), sndcmd);
 
 	gtk_editable_set_editable(GTK_EDITABLE(sndcmd), TRUE);
-	cmd = gaim_sound_get_command();
+	cmd = gaim_prefs_get_string("/gaim/gtk/sound/command");
 	if(cmd)
 		gtk_entry_set_text(GTK_ENTRY(sndcmd), cmd);
 	gtk_widget_set_size_request(sndcmd, 75, -1);
 
-	gtk_widget_set_sensitive(sndcmd, 
-			!strcmp(gaim_prefs_get_string("/gaim/gtk/sound/sound_method"),
+	gtk_widget_set_sensitive(sndcmd,
+			!strcmp(gaim_prefs_get_string("/gaim/gtk/sound/method"),
 					"command"));
 
 	gtk_box_pack_start(GTK_BOX(hbox), sndcmd, TRUE, TRUE, 5);
@@ -1854,7 +1856,7 @@
 						2, &pref,
 						-1);
 
-	gaim_prefs_set_bool(pref, gtk_cell_renderer_toggle_get_active(cell));
+	gaim_prefs_set_bool(pref, !gtk_cell_renderer_toggle_get_active(cell));
 
 	gtk_list_store_set(GTK_LIST_STORE (model), &iter,
 					   0, !gtk_cell_renderer_toggle_get_active(cell),
@@ -1866,10 +1868,11 @@
 static void
 test_sound(GtkWidget *button, gpointer i_am_NULL)
 {
-	const char *pref;
+	char *pref;
 	gboolean temp_value1, temp_value2;
 
-	pref = gaim_sound_get_event_option(sound_row_sel);
+	pref = g_strdup_printf("/gaim/gtk/sound/enabled/%s",
+			gaim_gtk_sound_get_event_option(sound_row_sel));
 
 	temp_value1 = gaim_prefs_get_bool("/gaim/gtk/sound/while_away");
 	temp_value2 = gaim_prefs_get_bool(pref);
@@ -1881,13 +1884,19 @@
 
 	if (!temp_value1) gaim_prefs_set_bool("/gaim/gtk/sound/while_away", FALSE);
 	if (!temp_value2) gaim_prefs_set_bool(pref, FALSE);
+
+	g_free(pref);
 }
 
 static void
 reset_sound(GtkWidget *button, gpointer i_am_also_NULL)
 {
+	char *pref = g_strdup_printf("/gaim/gtk/sound/file/%s",
+			gaim_gtk_sound_get_event_option(sound_row_sel));
+
 	/* This just resets a sound file back to default */
-	gaim_sound_set_event_file(sound_row_sel, NULL);
+	gaim_prefs_set_string(pref, "");
+	g_free(pref);
 
 	gtk_entry_set_text(GTK_ENTRY(sound_entry), "(default)");
 }
@@ -1910,6 +1919,7 @@
 void do_select_sound(GtkWidget *w, int snd)
 {
 	const char *file;
+	char *pref;
 
 	file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(sounddialog));
 
@@ -1918,7 +1928,10 @@
 		return;
 
 	/* Set it -- and forget it */
-	gaim_sound_set_event_file(snd, file);
+	pref = g_strdup_printf("/gaim/gtk/sound/file/%s",
+			gaim_gtk_sound_get_event_option(snd));
+	gaim_prefs_set_string(pref, file);
+	g_free(pref);
 
 	/* Set our text entry */
 	gtk_entry_set_text(GTK_ENTRY(sound_entry), file);
@@ -1965,13 +1978,18 @@
 static void prefs_sound_sel (GtkTreeSelection *sel, GtkTreeModel *model) {
 	GtkTreeIter  iter;
 	GValue val = { 0, };
-	char *file;
+	const char *file;
+	char *pref;
 
 	if (! gtk_tree_selection_get_selected (sel, &model, &iter))
 		return;
 	gtk_tree_model_get_value (model, &iter, 3, &val);
 	sound_row_sel = g_value_get_uint(&val);
-	file = gaim_sound_get_event_file(sound_row_sel);
+
+	pref = g_strdup_printf("/gaim/gtk/sound/file/%s",
+			gaim_gtk_sound_get_event_option(sound_row_sel));
+	file = gaim_prefs_get_string(pref);
+	g_free(pref);
 	if (sound_entry)
 		gtk_entry_set_text(GTK_ENTRY(sound_entry), file ? file : "(default)");
 	g_value_unset (&val);
@@ -1992,7 +2010,8 @@
 	GtkTreeSelection *sel;
 	GtkTreePath *path;
 	int j;
-	char *file;
+	const char *file;
+	char *pref;
 
 	ret = gtk_vbox_new(FALSE, 18);
 	gtk_container_set_border_width (GTK_CONTAINER (ret), 12);
@@ -2005,18 +2024,21 @@
 	event_store = gtk_list_store_new (4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT);
 
 	for (j=0; j < GAIM_NUM_SOUNDS; j++) {
-		const char *pref = gaim_sound_get_event_option(j);
-
-		if (pref == NULL)
+		char *pref = g_strdup_printf("/gaim/gtk/sound/enabled/%s",
+				gaim_gtk_sound_get_event_option(j));
+		const char *label = gaim_gtk_sound_get_event_label(j);
+
+		if (label == NULL)
 			continue;
 
 		gtk_list_store_append (event_store, &iter);
 		gtk_list_store_set(event_store, &iter,
 				   0, gaim_prefs_get_bool(pref),
-				   1, _(gaim_sound_get_event_label(j)),
+				   1, _(label),
 				   2, pref,
 				   3, j,
 				   -1);
+		g_free(pref);
 	}
 
 	event_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(event_store));
@@ -2050,7 +2072,10 @@
 	hbox = gtk_hbox_new(FALSE, 6);
 	gtk_box_pack_start(GTK_BOX(ret), hbox, FALSE, FALSE, 0);
 	sound_entry = gtk_entry_new();
-	file = gaim_sound_get_event_file(0);
+	pref = g_strdup_printf("/gaim/gtk/sound/file/%s",
+			gaim_gtk_sound_get_event_option(0));
+	file = gaim_prefs_get_string(pref);
+	g_free(pref);
 	gtk_entry_set_text(GTK_ENTRY(sound_entry), file ? file : "(default)");
 	gtk_editable_set_editable(GTK_EDITABLE(sound_entry), FALSE);
 	gtk_box_pack_start(GTK_BOX(hbox), sound_entry, FALSE, FALSE, 5);
@@ -2766,20 +2791,6 @@
 	gaim_prefs_add_int("/gaim/gtk/blist/width", 0);
 	gaim_prefs_add_int("/gaim/gtk/blist/height", 0);
 
-	/* Debug window preferences. */
-	/*
-	 * NOTE: This must be set before prefs are loaded, and the callbacks
-	 *       set after they are loaded, since prefs sets the enabled
-	 *       preference here and that loads the window, which calls the
-	 *       configure event, which overrrides the width and height! :P
-	 */
-	gaim_prefs_add_none("/gaim/gtk/debug");
-	gaim_prefs_add_bool("/gaim/gtk/debug/enabled", FALSE);
-	gaim_prefs_add_bool("/gaim/gtk/debug/timestamps", FALSE);
-	gaim_prefs_add_bool("/gaim/gtk/debug/toolbar", TRUE);
-	gaim_prefs_add_int("/gaim/gtk/debug/width",  450);
-	gaim_prefs_add_int("/gaim/gtk/debug/height", 250);
-
 	/* Idle */
 	gaim_prefs_add_none("/gaim/gtk/idle");
 	gaim_prefs_add_string("/gaim/gtk/idle/reporting_method", "system");
@@ -2799,21 +2810,5 @@
 	gaim_prefs_add_none("/gaim/gtk/smileys");
 	gaim_prefs_add_string("/gaim/gtk/smileys/theme", "");
 
-	/* Sound */
-	gaim_prefs_add_none("/gaim/gtk/sound");
-	gaim_prefs_add_bool("/gaim/gtk/sound/login", TRUE);
-	gaim_prefs_add_bool("/gaim/gtk/sound/logout", TRUE);
-	gaim_prefs_add_bool("/gaim/gtk/sound/im_recv", TRUE);
-	gaim_prefs_add_bool("/gaim/gtk/sound/first_im_recv", FALSE);
-	gaim_prefs_add_bool("/gaim/gtk/sound/send_im", TRUE);
-	gaim_prefs_add_bool("/gaim/gtk/sound/join_chat", FALSE);
-	gaim_prefs_add_bool("/gaim/gtk/sound/left_chat", FALSE);
-	gaim_prefs_add_bool("/gaim/gtk/sound/send_chat_msg", FALSE);
-	gaim_prefs_add_bool("/gaim/gtk/sound/chat_msg_recv", FALSE);
-	gaim_prefs_add_bool("/gaim/gtk/sound/nick_said", FALSE);
-	gaim_prefs_add_bool("/gaim/gtk/sound/silent_signon", TRUE);
-	gaim_prefs_add_bool("/gaim/gtk/sound/while_away", TRUE);
-	gaim_prefs_add_string("/gaim/gtk/sound/command", "");
-	gaim_prefs_add_string("/gaim/gtk/sound/sound_method", "automatic");
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gtksound.c	Tue Jun 03 03:33:20 2003 +0000
@@ -0,0 +1,413 @@
+/*
+ * gaim
+ *
+ * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
+ * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <windows.h>
+#include <mmsystem.h>
+#endif
+
+#ifdef USE_AO
+#include <ao/ao.h>
+#include <audiofile.h>
+#endif /* USE_AO */
+
+#ifdef USE_NAS_AUDIO
+#include <audio/audiolib.h>
+#include <audio/soundlib.h>
+#endif /* USE_NAS_AUDIO */
+
+#include "gaim.h" /* for gettext stuff */
+#include "sound.h"
+#include "gtksound.h"
+#include "prefs.h"
+
+#ifdef _WIN32
+#include "win32dep.h"
+#endif
+
+
+struct gaim_sound_event {
+	char *label;
+	char *pref;
+	char *def;
+};
+
+
+
+static gboolean mute_login_sounds = FALSE;
+static gboolean mute_sounds = FALSE;
+static char *sound_cmd = NULL;
+
+static struct gaim_sound_event sounds[GAIM_NUM_SOUNDS] = {
+	{N_("Buddy logs in"), "login", "arrive.wav"},
+	{N_("Buddy logs out"), "logout", "leave.wav"},
+	{N_("Message received"), "im_recv", "receive.wav"},
+	{N_("Message received begins conversation"), "first_im_recv", "receive.wav"},
+	{N_("Message sent"), "send_im", "send.wav"},
+	{N_("Person enters chat"), "join_chat", "arrive.wav"},
+	{N_("Person leaves chat"), "left_chat", "leave.wav"},
+	{N_("You talk in chat"), "send_chat_msg", "send.wav"},
+	{N_("Others talk in chat"), "chat_msg_recv", "receive.wav"},
+	/* this isn't a terminator, it's the buddy pounce default sound event ;-) */
+	{NULL, "pounce_default", "redalert.wav"},
+	{N_("Someone says your name in chat"), "nick_said", "redalert.wav"}
+};
+
+#ifdef USE_AO
+static int ao_driver = -1;
+#endif /* USE_AO */
+
+static void __pref_sound_method_changed(const char *name, GaimPrefType type,
+		gpointer val, gpointer data);
+
+static void gaim_gtk_sound_init(void)
+{
+	gaim_prefs_add_none("/gaim/gtk/sound");
+	gaim_prefs_add_none("/gaim/gtk/sound/enabled");
+	gaim_prefs_add_none("/gaim/gtk/sound/file");
+	gaim_prefs_add_bool("/gaim/gtk/sound/enabled/login", TRUE);
+	gaim_prefs_add_string("/gaim/gtk/sound/file/login", "");
+	gaim_prefs_add_bool("/gaim/gtk/sound/enabled/logout", TRUE);
+	gaim_prefs_add_string("/gaim/gtk/sound/file/logout", "");
+	gaim_prefs_add_bool("/gaim/gtk/sound/enabled/im_recv", TRUE);
+	gaim_prefs_add_string("/gaim/gtk/sound/file/im_recv", "");
+	gaim_prefs_add_bool("/gaim/gtk/sound/enabled/first_im_recv", FALSE);
+	gaim_prefs_add_string("/gaim/gtk/sound/file/first_im_recv", "");
+	gaim_prefs_add_bool("/gaim/gtk/sound/enabled/send_im", TRUE);
+	gaim_prefs_add_string("/gaim/gtk/sound/file/send_im", "");
+	gaim_prefs_add_bool("/gaim/gtk/sound/enabled/join_chat", FALSE);
+	gaim_prefs_add_string("/gaim/gtk/sound/file/join_chat", "");
+	gaim_prefs_add_bool("/gaim/gtk/sound/enabled/left_chat", FALSE);
+	gaim_prefs_add_string("/gaim/gtk/sound/file/left_chat", "");
+	gaim_prefs_add_bool("/gaim/gtk/sound/enabled/send_chat_msg", FALSE);
+	gaim_prefs_add_string("/gaim/gtk/sound/file/send_chat_msg", "");
+	gaim_prefs_add_bool("/gaim/gtk/sound/enabled/chat_msg_recv", FALSE);
+	gaim_prefs_add_string("/gaim/gtk/sound/file/chat_msg_recv", "");
+	gaim_prefs_add_bool("/gaim/gtk/sound/enabled/nick_said", FALSE);
+	gaim_prefs_add_string("/gaim/gtk/sound/file/nick_said", "");
+	gaim_prefs_add_bool("/gaim/gtk/sound/silent_signon", TRUE);
+	gaim_prefs_add_string("/gaim/gtk/sound/command", "");
+	gaim_prefs_add_string("/gaim/gtk/sound/method", "automatic");
+
+#ifdef USE_AO
+	gaim_debug(GAIM_DEBUG_INFO, "sound",
+			"Initializing sound output drivers.\n");
+	ao_initialize();
+#endif /* USE_AO */
+
+	gaim_prefs_connect_callback("/gaim/gtk/sound/method",
+			__pref_sound_method_changed, NULL);
+	gaim_prefs_trigger_callback("/gaim/gtk/sound/method");
+}
+
+
+static void gaim_gtk_sound_shutdown(void)
+{
+#ifdef USE_AO
+	ao_shutdown();
+#endif
+}
+
+static void gaim_gtk_sound_play_file(const char *filename)
+{
+	const char *method;
+#if defined(USE_NAS_AUDIO) || defined(USE_AO)
+	pid_t pid;
+#ifdef USE_AO
+	AFfilehandle file;
+#endif
+#endif
+
+	if (mute_sounds)
+		return;
+
+	method = gaim_prefs_get_string("/gaim/gtk/sound/method");
+
+	if (!strcmp(method, "beep")) {
+		gdk_beep();
+		return;
+	}
+
+	if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
+		char *tmp = g_strdup_printf(_("Unable to play sound because the chosen file (%s) does not exist."), filename);
+		gaim_notify_error(NULL, NULL, tmp, NULL);
+		g_free(tmp);
+		return;
+	}
+
+#ifndef _WIN32
+	if (!strcmp(method, "custom")) {
+		const char *sound_cmd;
+		char *command;
+		GError *error = NULL;
+
+		sound_cmd = gaim_prefs_get_string("/gaim/gtk/sound/command");
+
+		if (!sound_cmd || *sound_cmd == '\0') {
+			gaim_notify_error(NULL, NULL,
+							  _("Unable to play sound because the "
+								"'Command' sound method has been chosen, "
+								"but no command has been set."), NULL);
+			return;
+		}
+
+		command = g_strdup_printf(sound_cmd, filename);
+
+		if(!g_spawn_command_line_async(command, &error)) {
+			char *tmp = g_strdup_printf(_("Unable to play sound because the configured sound command could not be launched: %s"), error->message);
+			gaim_notify_error(NULL, NULL, tmp, NULL);
+			g_free(tmp);
+			g_error_free(error);
+		}
+
+		g_free(command);
+		return;
+	}
+#if defined(USE_NAS_AUDIO) || defined(USE_AO)
+	pid = fork();
+	if (pid < 0)
+		return;
+	else if (pid == 0) {
+#ifdef USE_NAS_AUDIO
+		if (!strcmp(method, "nas")) {
+			if (play_file_nas(filename))
+				_exit(0);
+		}
+#endif /* USE_NAS_AUDIO */
+
+#ifdef USE_AO
+		file = afOpenFile(filename, "rb", NULL);
+		if(file) {
+			ao_device *device;
+			ao_sample_format format;
+			int in_fmt;
+			int bytes_per_frame;
+
+			format.rate = afGetRate(file, AF_DEFAULT_TRACK);
+			format.channels = afGetChannels(file, AF_DEFAULT_TRACK);
+			afGetSampleFormat(file, AF_DEFAULT_TRACK, &in_fmt,
+					&format.bits);
+
+			/* XXX: libao doesn't seem to like 8-bit sounds, so we'll
+			 * let libaudiofile make them a bit better for us */
+			if(format.bits == 8)
+				format.bits = 16;
+
+			afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK,
+					AF_SAMPFMT_TWOSCOMP, format.bits);
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+			format.byte_format = AO_FMT_BIG;
+			afSetVirtualByteOrder(file, AF_DEFAULT_TRACK,
+					AF_BYTEORDER_BIGENDIAN);
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+			format.byte_format = AO_FMT_LITTLE;
+			afSetVirtualByteOrder(file, AF_DEFAULT_TRACK,
+					AF_BYTEORDER_LITTLEENDIAN);
+#endif
+
+			bytes_per_frame = format.bits * format.channels / 8;
+
+			device = ao_open_live(ao_driver, &format, NULL);
+
+			if(device) {
+				int frames_read;
+				char buf[4096];
+				int buf_frames = sizeof(buf) / bytes_per_frame;
+
+				while((frames_read = afReadFrames(file, AF_DEFAULT_TRACK,
+								buf, buf_frames))) {
+					if(!ao_play(device, buf, frames_read * bytes_per_frame))
+						break;
+				}
+				ao_close(device);
+			}
+			afCloseFile(file);
+		}
+		ao_shutdown();
+#endif /* USE_AO */
+		_exit(0);
+	}
+#else /* USE_NAS_AUDIO || USE_AO */
+	gdk_beep();
+	return;
+#endif /* USE_NAS_AUDIO || USE_AO */
+#else /* _WIN32 */
+	gaim_debug(GAIM_DEBUG_INFO, "sound", "Playing %s\n", filename);
+
+	if (!PlaySound(filename, 0, SND_ASYNC | SND_FILENAME))
+		gaim_debug(GAIM_DEBUG_ERROR, "sound", "Error playing sound.\n");
+#endif /* _WIN32 */
+}
+
+static void gaim_gtk_sound_play_event(GaimSoundEventID event)
+{
+	char *enable_pref;
+	char *file_pref;
+
+	if ((event == GAIM_SOUND_BUDDY_ARRIVE) && mute_login_sounds)
+		return;
+
+	if (event >= GAIM_NUM_SOUNDS) {
+		gaim_debug(GAIM_DEBUG_MISC, "sound",
+				   "got request for unknown sound: %d\n", event);
+		return;
+	}
+
+	enable_pref = g_strdup_printf("/gaim/gtk/sound/enabled/%s",
+			sounds[event].pref);
+	file_pref = g_strdup_printf("/gaim/gtk/sound/file/%s", sounds[event].pref);
+
+	/* check NULL for sounds that don't have an option, ie buddy pounce */
+	if (gaim_prefs_get_bool(enable_pref)) {
+		char *filename = g_strdup(gaim_prefs_get_string(file_pref));
+		if(!filename || !strlen(filename)) {
+			if(filename) g_free(filename);
+			filename = g_build_filename(DATADIR, "sounds", "gaim", sounds[event].def, NULL);
+		}
+
+		gaim_sound_play_file(filename);
+		g_free(filename);
+	}
+
+	g_free(enable_pref);
+	g_free(file_pref);
+}
+
+static GaimSoundUiOps sound_ui_ops =
+{
+	gaim_gtk_sound_init,
+	gaim_gtk_sound_shutdown,
+	gaim_gtk_sound_play_file,
+	gaim_gtk_sound_play_event
+};
+
+GaimSoundUiOps *gaim_get_gtk_sound_ui_ops(void)
+{
+	return &sound_ui_ops;
+}
+
+
+static void __pref_sound_method_changed(const char *name, GaimPrefType type,
+		gpointer val, gpointer data) {
+	if(type != GAIM_PREF_STRING || strcmp(name, "/gaim/gtk/sound/method"))
+		return;
+#ifdef USE_AO
+	ao_driver = -1;
+
+	if(!strcmp(val, "esd"))
+		ao_driver = ao_driver_id("esd");
+	else if(!strcmp(val, "arts"))
+		ao_driver = ao_driver_id("arts");
+	else if(!strcmp(val, "automatic"))
+		ao_driver = ao_default_driver_id();
+
+	if(ao_driver != -1) {
+		ao_info *info = ao_driver_info(ao_driver);
+		gaim_debug(GAIM_DEBUG_INFO, "sound",
+				   "Sound output driver loaded: %s\n", info->name);
+	}
+#endif /* USE_AO */
+#ifdef USE_NAS
+	if (!strcmp(val, "nas"))
+		gaim_debug(GAIM_DEBUG_INFO, "sound",
+				   "Sound output driver loaded: NAS output\n");
+#endif /* USE_NAS */
+}
+
+#ifdef USE_NAS_AUDIO
+static gboolean play_file_nas(const char *filename)
+{
+	AuServer *nas_serv;
+	gboolean ret = FALSE;
+
+	if((nas_serv = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL))) {
+		ret = AuSoundPlaySynchronousFromFile(nas_serv, filename, 100);
+		AuCloseServer(nas_serv);
+	}
+
+	return ret;
+}
+
+#endif /* USE_NAS_AUDIO */
+
+void gaim_gtk_sound_set_mute(gboolean mute)
+{
+	mute_sounds = mute;
+}
+
+gboolean gaim_gtk_sound_get_mute()
+{
+	return mute_sounds;
+}
+
+void gaim_gtk_sound_set_login_mute(gboolean mute)
+{
+	mute_login_sounds = mute;
+}
+
+const char *gaim_gtk_sound_get_event_option(GaimSoundEventID event)
+{
+	if(event >= GAIM_NUM_SOUNDS)
+		return 0;
+
+	return sounds[event].pref;
+}
+
+char *gaim_gtk_sound_get_event_label(GaimSoundEventID event)
+{
+	if(event >= GAIM_NUM_SOUNDS)
+		return NULL;
+
+	return sounds[event].label;
+}
+
+
+void gaim_sound_set_command(const char *cmd)
+{
+	if(sound_cmd)
+		g_free(sound_cmd);
+	if(strlen(cmd) > 0)
+		sound_cmd = g_strdup(cmd);
+	else
+		sound_cmd = NULL;
+}
+
+char *gaim_sound_get_command()
+{
+	return sound_cmd;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gtksound.h	Tue Jun 03 03:33:20 2003 +0000
@@ -0,0 +1,76 @@
+/**
+ * @file gtksound.h GTK+ Sound API
+ *
+ * gaim
+ *
+ * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ *
+ * 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 _GAIM_GTKSOUND_H_
+#define _GAIM_GTKSOUND_H_
+
+/**************************************************************************/
+/** @name GTK+ Sound API                                                  */
+/**************************************************************************/
+/*@{*/
+
+/**
+ * Gets GTK Sound UI opsA
+ *
+ * @return UI operations struct
+ */
+GaimSoundUiOps *gaim_get_gtk_sound_ui_ops(void);
+/**
+ * Mutes or un-mutes sounds.
+ *
+ * @param mute The mute state.
+ */
+void gaim_gtk_sound_set_mute(gboolean mute);
+
+/**
+ * Gets mute state for sounds.
+ *
+ * @return The mute state.
+ */
+gboolean gaim_gtk_sound_get_mute();
+
+/**
+ * Mutes or un-mutes login sounds.
+ *
+ * @param mute The mute state.
+ */
+void gaim_gtk_sound_set_login_mute(gboolean mute);
+
+/**
+ * Get the prefs option for an event.
+ *
+ * @param event The event.
+ * @return The option.
+ */
+const char *gaim_gtk_sound_get_event_option(GaimSoundEventID event);
+
+/**
+ * Get the label for an event.
+ *
+ * @param event The event.
+ * @return The label.
+ */
+char *gaim_gtk_sound_get_event_label(GaimSoundEventID event);
+
+/*@}*/
+
+#endif /* _GAIM_GTKSOUND_H_ */
--- a/src/main.c	Tue Jun 03 02:30:30 2003 +0000
+++ b/src/main.c	Tue Jun 03 03:33:20 2003 +0000
@@ -48,6 +48,7 @@
 #include <ctype.h>
 #include "prpl.h"
 #include "sound.h"
+#include "gtksound.h"
 #include "gaim.h"
 #include "gaim-socket.h"
 #include "account.h"
@@ -58,6 +59,7 @@
 #include "gtkdebug.h"
 #include "gtknotify.h"
 #include "gtkrequest.h"
+#include "gtksound.h"
 #if HAVE_SIGNAL_H
 #include <signal.h>
 #endif
@@ -150,7 +152,7 @@
 static guint snd_tmout = 0;
 static gboolean sound_timeout(gpointer data)
 {
-	gaim_sound_set_login_mute(FALSE);
+	gaim_gtk_sound_set_login_mute(FALSE);
 	snd_tmout = 0;
 	return FALSE;
 }
@@ -164,7 +166,7 @@
 		if(snd_tmout) {
 			g_source_remove(snd_tmout);
 		}
-		gaim_sound_set_login_mute(TRUE);
+		gaim_gtk_sound_set_login_mute(TRUE);
 		snd_tmout = g_timeout_add(10000, sound_timeout, NULL);
 	}
 }
@@ -876,18 +878,24 @@
 		return 0;
 	}
 
+	gaim_prefs_init();
+	gaim_gtk_prefs_init();
+
+	/* This kind of has to be here.. sucks, but it's important. */
+	gaim_set_debug_ui_ops(gaim_get_gtk_debug_ui_ops());
+	gaim_gtk_debug_init();
+
 	/* Set the UI operation structures. */
-	gaim_set_debug_ui_ops(gaim_get_gtk_debug_ui_ops());
 	gaim_set_win_ui_ops(gaim_get_gtk_window_ui_ops());
 	gaim_set_xfer_ui_ops(gaim_get_gtk_xfer_ui_ops());
 	gaim_set_blist_ui_ops(gaim_get_gtk_blist_ui_ops());
 	gaim_set_notify_ui_ops(gaim_get_gtk_notify_ui_ops());
 	gaim_set_request_ui_ops(gaim_get_gtk_request_ui_ops());
+	gaim_set_sound_ui_ops(gaim_get_gtk_sound_ui_ops());
 
-	gaim_prefs_init();
 	gaim_proxy_init();
+	gaim_sound_init();
 
-	gaim_gtk_prefs_init();
 	gaim_gtk_conversation_init();
 
 	plugin_search_paths[0] = LIBDIR;
@@ -907,8 +915,6 @@
 		gaim_prefs_sync();
 	}
 
-	/* This kind of has to be here.. sucks, but it's important. */
-	gaim_gtk_debug_init();
 
 	gaim_accounts_load();
 
@@ -960,7 +966,7 @@
 
 	gtk_main();
 	core_quit();
-	gaim_sound_quit();
+	gaim_sound_shutdown();
 #ifdef _WIN32
 	wgaim_cleanup();
 #endif
--- a/src/prefs.c	Tue Jun 03 02:30:30 2003 +0000
+++ b/src/prefs.c	Tue Jun 03 03:33:20 2003 +0000
@@ -137,15 +137,6 @@
 	gaim_prefs_add_bool("/core/conversations/im/show_login", TRUE);
 	gaim_prefs_add_bool("/core/conversations/im/send_typing", TRUE);
 
-	/* Sound */
-	gaim_prefs_add_none("/core/sound");
-	gaim_prefs_add_bool("/core/sound/use_sys_default", TRUE);
-	gaim_prefs_add_bool("/core/sound/use_esd", FALSE);
-	gaim_prefs_add_bool("/core/sound/use_arts", FALSE);
-	gaim_prefs_add_bool("/core/sound/use_beep", FALSE);
-	gaim_prefs_add_bool("/core/sound/use_custom", FALSE);
-	gaim_prefs_add_string("/core/sound/command", "");
-	gaim_prefs_add_bool("/core/sound/while_away", FALSE);
 }
 
 static char *pref_full_name(struct gaim_pref *pref) {
@@ -356,6 +347,13 @@
 	}
 }
 
+void gaim_prefs_trigger_callback(const char *name) {
+	struct gaim_pref *pref = find_pref(name);
+
+	g_return_if_fail(pref != NULL);
+	do_callbacks(name, pref);
+}
+
 void gaim_prefs_set_generic(const char *name, gpointer value) {
 	struct gaim_pref *pref = find_pref(name);
 
--- a/src/prefs.h	Tue Jun 03 02:30:30 2003 +0000
+++ b/src/prefs.h	Tue Jun 03 03:33:20 2003 +0000
@@ -190,6 +190,11 @@
 void gaim_prefs_disconnect_callback(guint callback_id);
 
 /**
+ * Trigger callbacks as if the pref changed
+ */
+void gaim_prefs_trigger_callback(const char *name);
+
+/**
  * Read preferences
  */
 gboolean gaim_prefs_load();
--- a/src/sound.c	Tue Jun 03 02:30:30 2003 +0000
+++ b/src/sound.c	Tue Jun 03 03:33:20 2003 +0000
@@ -1,7 +1,6 @@
 /*
  * gaim
  *
- * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
  * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -23,368 +22,57 @@
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 
-#ifndef _WIN32
-#include <unistd.h>
-#else
-#include <windows.h>
-#include <mmsystem.h>
-#endif
-
-#ifdef HAVE_ENDIAN_H
-#include <endian.h>
-#endif
-
-#ifdef USE_AO
-#include <ao/ao.h>
-#include <audiofile.h>
-#endif /* USE_AO */
-#ifdef USE_NAS_AUDIO
-#include <audio/audiolib.h>
-#include <audio/soundlib.h>
-#endif /* USE_NAS_AUDIO */
-
-#include "gaim.h"
 #include "sound.h"
-#include "notify.h"
 #include "prefs.h"
+#include "gaim.h" /* XXX: this goes away when away messages become sane */
 
 #ifdef _WIN32
 #include "win32dep.h"
 #endif
 
-struct gaim_sound_event {
-	char *label;
-	char *pref;
-	char *def;
-};
-
-#ifdef USE_AO
-static gboolean ao_initialized=FALSE;
-static int ao_driver = -1;
-#endif /* USE_AO */
-
-
-static gboolean mute_login_sounds = FALSE;
-static gboolean mute_sounds = FALSE;
-static char *sound_cmd = NULL;
+static GaimSoundUiOps *sound_ui_ops = NULL;
 
-/* description, option bit, default sound file             *
- * set the option bit to 0 to have it not display in prefs *
- * the order here has to match the defines in gaim.h.      *
- *                                               -Robot101 */
-static struct gaim_sound_event sounds[GAIM_NUM_SOUNDS] = {
-	{N_("Buddy logs in"), "/gaim/gtk/sound/login", "arrive.wav"},
-	{N_("Buddy logs out"), "/gaim/gtk/sound/logout", "leave.wav"},
-	{N_("Message received"), "/gaim/gtk/sound/im_recv", "receive.wav"},
-	{N_("Message received begins conversation"), "/gaim/gtk/sound/first_im_recv", "receive.wav"},
-	{N_("Message sent"), "/gaim/gtk/sound/send_im", "send.wav"},
-	{N_("Person enters chat"), "/gaim/gtk/sound/join_chat", "arrive.wav"},
-	{N_("Person leaves chat"), "/gaim/gtk/sound/left_chat", "leave.wav"},
-	{N_("You talk in chat"), "/gaim/gtk/sound/send_chat_msg", "send.wav"},
-	{N_("Others talk in chat"), "/gaim/gtk/sound/chat_msg_recv", "receive.wav"},
-	/* this isn't a terminator, it's the buddy pounce default sound event ;-) */
-	{NULL, 0, "redalert.wav"},
-	{N_("Someone says your name in chat"), "/gaim/gtk/sound/nick_said", "redalert.wav"}
-};
-
-static char *sound_file[GAIM_NUM_SOUNDS];
-
-
-#ifdef USE_AO
-static void check_ao_init()
+void gaim_set_sound_ui_ops(GaimSoundUiOps *ops)
 {
-	if(!ao_initialized) {
-		gaim_debug(GAIM_DEBUG_INFO, "sound",
-				   "Initializing sound output drivers.\n");
-		ao_initialize();
-		ao_initialized = TRUE;
-	}
-}
-#endif /* USE_AO */
-
-void gaim_sound_change_output_method() {
-#ifdef USE_AO
-	ao_driver = -1;
-
-	if (gaim_prefs_get_bool("/core/sound/use_esd") ||
-		gaim_prefs_get_bool("/core/sound/use_arts") ||
-		gaim_prefs_get_bool("/core/sound/use_sys_default")) {
-
-		check_ao_init();
-
-		if (ao_driver == -1 && gaim_prefs_get_bool("/core/sound/use_esd"))
-			ao_driver = ao_driver_id("esd");
-
-		if (ao_driver == -1 && gaim_prefs_get_bool("/core/sound/use_arts"))
-			ao_driver = ao_driver_id("arts");
-
-		if (ao_driver == -1)
-			ao_driver = ao_default_driver_id();
-	}
-
-	if(ao_driver != -1) {
-		ao_info *info = ao_driver_info(ao_driver);
-		gaim_debug(GAIM_DEBUG_INFO, "sound",
-				   "Sound output driver loaded: %s\n", info->name);
-	}
-#endif /* USE_AO */
-#ifdef USE_NAS
-	if (gaim_prefs_get_bool("/core/sound/use_nas"))
-		gaim_debug(GAIM_DEBUG_INFO, "sound",
-				   "Sound output driver loaded: NAS output\n");
-#endif /* USE_NAS */
+	if(sound_ui_ops && sound_ui_ops->shutdown)
+		sound_ui_ops->shutdown();
+	sound_ui_ops = ops;
+	if(sound_ui_ops && sound_ui_ops->init)
+		sound_ui_ops->init();
 }
 
-void gaim_sound_quit()
+GaimSoundUiOps *gaim_get_sound_ui_ops(void)
 {
-#ifdef USE_AO
-	if(ao_initialized)
-		ao_shutdown();
-#endif
-}
-
-
-#ifdef USE_NAS_AUDIO
-static gboolean play_file_nas(const char *filename)
-{
-	AuServer *nas_serv;
-	gboolean ret = FALSE;
-
-	if((nas_serv = AuOpenServer(NULL, 0, NULL, 0, NULL, NULL))) {
-		ret = AuSoundPlaySynchronousFromFile(nas_serv, filename, 100);
-		AuCloseServer(nas_serv);
-	}
-
-	return ret;
+	return sound_ui_ops;
 }
 
-#endif /* USE_NAS_AUDIO */
+void gaim_sound_init()
+{
+	gaim_prefs_add_none("/core/sound");
+	gaim_prefs_add_bool("/core/sound/while_away", FALSE);
+}
 
-void gaim_sound_play_file(char *filename)
+void gaim_sound_shutdown()
 {
-#if defined(USE_NAS_AUDIO) || defined(USE_AO)
-	pid_t pid;
-#ifdef USE_AO
-	AFfilehandle file;
-#endif
-#endif
+	if(sound_ui_ops && sound_ui_ops->shutdown)
+		sound_ui_ops->shutdown();
+}
 
-	if (mute_sounds)
+void gaim_sound_play_file(const char *filename)
+{
+	if(awaymessage && !gaim_prefs_get_bool("/core/sound/while_away"))
 		return;
 
-	if (awaymessage && !gaim_prefs_get_bool("/core/sound/while_away"))
-		return; /* check here in case a buddy pounce plays a file while away */
-
-	if (gaim_prefs_get_bool("/core/sound/use_beep")) {
-		gdk_beep();
-		return;
-	}
-
-	if (!g_file_test(filename, G_FILE_TEST_EXISTS)) {
-		char *tmp = g_strdup_printf(_("Unable to play sound because the chosen file (%s) does not exist."), filename);
-		gaim_notify_error(NULL, NULL, tmp, NULL);
-		g_free(tmp);
-		return;
-	}
-
-#ifndef _WIN32
-	if (gaim_prefs_get_bool("/core/sound/use_custom")) {
-		const char *sound_cmd;
-		char *command;
-		GError *error = NULL;
-
-		sound_cmd = gaim_prefs_get_string("/core/sound/command");
-
-		if (!sound_cmd || *sound_cmd == '\0') {
-			gaim_notify_error(NULL, NULL,
-							  _("Unable to play sound because the "
-								"'Command' sound method has been chosen, "
-								"but no command has been set."), NULL);
-			return;
-		}
-
-		command = g_strdup_printf(sound_cmd, filename);
-
-		if(!g_spawn_command_line_async(command, &error)) {
-			char *tmp = g_strdup_printf(_("Unable to play sound because the configured sound command could not be launched: %s"), error->message);
-			gaim_notify_error(NULL, NULL, tmp, NULL);
-			g_free(tmp);
-			g_error_free(error);
-		}
-
-		g_free(command);
-		return;
-	}
-#if defined(USE_NAS_AUDIO) || defined(USE_AO)
-	pid = fork();
-	if (pid < 0)
-		return;
-	else if (pid == 0) {
-#ifdef USE_NAS_AUDIO
-		if (gaim_prefs_get_bool("/core/sound/use_nas")) {
-			if (play_file_nas(filename))
-				_exit(0);
-		}
-#endif /* USE_NAS_AUDIO */
-
-#ifdef USE_AO
-		file = afOpenFile(filename, "rb", NULL);
-		if(file) {
-			ao_device *device;
-			ao_sample_format format;
-			int in_fmt;
-			int bytes_per_frame;
-
-			format.rate = afGetRate(file, AF_DEFAULT_TRACK);
-			format.channels = afGetChannels(file, AF_DEFAULT_TRACK);
-			afGetSampleFormat(file, AF_DEFAULT_TRACK, &in_fmt,
-					&format.bits);
-
-			/* XXX: libao doesn't seem to like 8-bit sounds, so we'll
-			 * let libaudiofile make them a bit better for us */
-			if(format.bits == 8)
-				format.bits = 16;
-
-			afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK,
-					AF_SAMPFMT_TWOSCOMP, format.bits);
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-			format.byte_format = AO_FMT_BIG;
-			afSetVirtualByteOrder(file, AF_DEFAULT_TRACK,
-					AF_BYTEORDER_BIGENDIAN);
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-			format.byte_format = AO_FMT_LITTLE;
-			afSetVirtualByteOrder(file, AF_DEFAULT_TRACK,
-					AF_BYTEORDER_LITTLEENDIAN);
-#endif
-
-			bytes_per_frame = format.bits * format.channels / 8;
-
-			device = ao_open_live(ao_driver, &format, NULL);
-
-			if(device) {
-				int frames_read;
-				char buf[4096];
-				int buf_frames = sizeof(buf) / bytes_per_frame;
-
-				while((frames_read = afReadFrames(file, AF_DEFAULT_TRACK,
-								buf, buf_frames))) {
-					if(!ao_play(device, buf, frames_read * bytes_per_frame))
-						break;
-				}
-				ao_close(device);
-			}
-			afCloseFile(file);
-		}
-		ao_shutdown();
-#endif /* USE_AO */
-		_exit(0);
-	}
-#else /* USE_NAS_AUDIO || USE_AO */
-	gdk_beep();
-	return;
-#endif /* USE_NAS_AUDIO || USE_AO */
-#else /* _WIN32 */
-	gaim_debug(GAIM_DEBUG_INFO, "sound", "Playing %s\n", filename);
-
-	if (!PlaySound(filename, 0, SND_ASYNC | SND_FILENAME))
-		gaim_debug(GAIM_DEBUG_ERROR, "sound", "Error playing sound.\n");
-#endif /* _WIN32 */
+	if(sound_ui_ops && sound_ui_ops->play_file)
+		sound_ui_ops->play_file(filename);
 }
 
 void gaim_sound_play_event(GaimSoundEventID event)
 {
-	if ((event == GAIM_SOUND_BUDDY_ARRIVE) && mute_login_sounds)
-		return;
-
-	if (event >= GAIM_NUM_SOUNDS) {
-		gaim_debug(GAIM_DEBUG_MISC, "sound",
-				   "got request for unknown sound: %d\n", event);
-		return;
-	}
-
-	/* check NULL for sounds that don't have an option, ie buddy pounce */
-	if (sounds[event].pref == NULL || gaim_prefs_get_bool(sounds[event].pref)) {
-		if (sound_file[event]) {
-			gaim_sound_play_file(sound_file[event]);
-		} else {
-			gchar *filename = NULL;
-
-			filename = g_build_filename(DATADIR, "sounds", "gaim", sounds[event].def, NULL);
-			gaim_sound_play_file(filename);
-			g_free(filename);
-		}
-	}
-}
-
-void gaim_sound_set_mute(gboolean mute)
-{
-	mute_sounds = mute;
-}
-
-gboolean gaim_sound_get_mute()
-{
-	return mute_sounds;
-}
-
-void gaim_sound_set_login_mute(gboolean mute)
-{
-	mute_login_sounds = mute;
-}
-
-void gaim_sound_set_event_file(GaimSoundEventID event, const char *filename)
-{
-	if(event >= GAIM_NUM_SOUNDS)
+	if(awaymessage && !gaim_prefs_get_bool("/core/sound/while_away"))
 		return;
 
-	if(sound_file[event])
-		g_free(sound_file[event]);
-
-	sound_file[event] = g_strdup(filename);
-}
-
-
-char *gaim_sound_get_event_file(GaimSoundEventID event)
-{
-	if(event >= GAIM_NUM_SOUNDS)
-		return NULL;
-
-	return sound_file[event];
-}
-
-const char *gaim_sound_get_event_option(GaimSoundEventID event)
-{
-	if(event >= GAIM_NUM_SOUNDS)
-		return 0;
-
-	return sounds[event].pref;
+	if(sound_ui_ops && sound_ui_ops->play_event)
+		sound_ui_ops->play_event(event);
 }
-
-char *gaim_sound_get_event_label(GaimSoundEventID event)
-{
-	if(event >= GAIM_NUM_SOUNDS)
-		return NULL;
-
-	return sounds[event].label;
-}
-
-
-void gaim_sound_set_command(const char *cmd)
-{
-	if(sound_cmd)
-		g_free(sound_cmd);
-	if(strlen(cmd) > 0)
-		sound_cmd = g_strdup(cmd);
-	else
-		sound_cmd = NULL;
-}
-
-char *gaim_sound_get_command()
-{
-	return sound_cmd;
-}
-
--- a/src/sound.h	Tue Jun 03 02:30:30 2003 +0000
+++ b/src/sound.h	Tue Jun 03 03:33:20 2003 +0000
@@ -29,7 +29,7 @@
 
 
 /**
- * A type of conversation.
+ * A type of sound.
  */
 
 typedef enum _GaimSoundEventID
@@ -48,27 +48,50 @@
 	GAIM_NUM_SOUNDS              /**< Total number of sounds.               */
 } GaimSoundEventID;
 
+typedef struct _GaimSoundUiOps
+{
+	void (*init)(void);
+	void (*shutdown)(void);
+	void (*play_file)(const char *filename);
+	void (*play_event)(GaimSoundEventID event);
+
+} GaimSoundUiOps;
+
 /**************************************************************************/
 /** @name Sound API                                                       */
 /**************************************************************************/
 /*@{*/
 
 /**
- * Lets the sound subsystem know when the sound output method has changed.
+ * Sets the UI sound operations
+ *
+ * @param ops The UI sound operations structure.
  */
-void gaim_sound_change_output_method();
+void gaim_set_sound_ui_ops(GaimSoundUiOps *ops);
 
 /**
- * Properly shuts down the sound system.
+ * Gets the UI sound operations
+ *
+ * @return The UI sound operations structure.
  */
-void gaim_sound_quit();
+GaimSoundUiOps *gaim_get_sound_ui_ops(void);
+
+/**
+ * Initializes the sound subsystem
+ */
+void gaim_sound_init(void);
+
+/**
+ * Shuts down the sound subsystem
+ */
+void gaim_sound_shutdown(void);
 
 /**
  * Plays the specified sound file.
  *
  * @param filename The file to play.
  */
-void gaim_sound_play_file(char *filename);
+void gaim_sound_play_file(const char *filename);
 
 /**
  * Plays the sound associated with the specified event.
@@ -77,72 +100,6 @@
  */
 void gaim_sound_play_event(GaimSoundEventID event);
 
-/**
- * Mutes or un-mutes sounds.
- *
- * @param mute The mute state.
- */
-void gaim_sound_set_mute(gboolean mute);
-
-/**
- * Gets mute state for sounds.
- *
- * @return The mute state.
- */
-gboolean gaim_sound_get_mute();
-
-/**
- * Mutes or un-mutes login sounds.
- *
- * @param mute The mute state.
- */
-void gaim_sound_set_login_mute(gboolean mute);
-
-/**
- * Set sound file for an event.
- *
- * @param event The event.
- * @param filename The sound file.
- */
-void gaim_sound_set_event_file(GaimSoundEventID event, const char *filename);
-
-/** Get sound file for an event.
- *
- * @param event The event.
- * @return The filename if set, otherwise @c NULL.
- */
-char *gaim_sound_get_event_file(GaimSoundEventID event);
-
-/**
- * Get the prefs option for an event.
- *
- * @param event The event.
- * @return The option.
- */
-const char *gaim_sound_get_event_option(GaimSoundEventID event);
-
-/**
- * Get the label for an event.
- *
- * @param event The event.
- * @return The label.
- */
-char *gaim_sound_get_event_label(GaimSoundEventID event);
-
-/**
- * Set sound command for command mode.
- *
- * @param cmd The command.
- */
-void gaim_sound_set_command(const char *cmd);
-
-/**
- * Get sound command for command mode.
- *
- * @return The command if set, otherwise @c NULL.
- */
-char *gaim_sound_get_command();
-
 /*@}*/
 
 #endif /* _GAIM_SOUND_H_ */