[xmp] Rewrite the Audacious plugin for Audacious 3.0 Preferences Widgets.

Michael Schwendt mschwendt at fedoraproject.org
Thu Jul 7 10:18:11 UTC 2011


commit 9d7c07570b5fda0b06a5b5b69c80acd272bbc876
Author: Michael Schwendt <mschwendt at fedoraproject.org>
Date:   Thu Jul 7 12:17:56 2011 +0200

    Rewrite the Audacious plugin for Audacious 3.0 Preferences Widgets.

 xmp-3.3.0-aud25.patch |  704 -----------------------------
 xmp-3.3.0-aud30.patch | 1189 +++++++++++++++++++++++++++++++++++++++++++++++++
 xmp.spec              |    9 +-
 3 files changed, 1195 insertions(+), 707 deletions(-)
---
diff --git a/xmp-3.3.0-aud30.patch b/xmp-3.3.0-aud30.patch
new file mode 100644
index 0000000..ebde451
--- /dev/null
+++ b/xmp-3.3.0-aud30.patch
@@ -0,0 +1,1189 @@
+diff -Nur xmp-3.3.0-orig/src/plugin/audacious.c xmp-3.3.0/src/plugin/audacious.c
+--- xmp-3.3.0-orig/src/plugin/audacious.c	2010-12-02 01:52:51.000000000 +0100
++++ xmp-3.3.0/src/plugin/audacious.c	2011-07-07 12:14:21.000000000 +0200
+@@ -4,79 +4,50 @@
+  * Based on J. Nick Koston's MikMod plugin for XMMS
+  */
+ 
++/* Audacious 3.0 port/rewrite for Fedora by Michael Schwendt
++ * TODO: list of supported formats missing in 'About' dialog
++ */
++
+ #include <stdlib.h>
+ #include <string.h>
+ #include <stdio.h>
+ #include <limits.h>
+-#include <pthread.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <ctype.h>
+ 
+ #include <audacious/configdb.h>
+ #include <audacious/plugin.h>
+-
+-#if __AUDACIOUS_PLUGIN_API__ < 16
+-#include <audacious/util.h>
+-#else
++#include <audacious/preferences.h>
++#include <libaudgui/libaudgui-gtk.h>
+ #include <gtk/gtk.h>
+-#define aud_tuple_new_from_filename	tuple_new_from_filename
+-#define aud_tuple_associate_string	tuple_associate_string
+-#define aud_tuple_associate_int		tuple_associate_int
+-#endif
++#include <glib.h>
+ 
+ #include "xmp.h"
+ #include "common.h"
+ #include "driver.h"
+ 
+-#if __AUDACIOUS_PLUGIN_API__ >= 12
+-#define CONST12 const
+-#else
+-#define CONST12
+-#endif
+-
+-static void	init		(void);
+-static int	is_our_file	(CONST12 char *);
+-static void	play_file	(InputPlayback *);
+-static void	stop		(InputPlayback *);
+-static void	mod_pause	(InputPlayback *, short);
+-static void	seek		(InputPlayback *, int);
+-static int	get_time	(InputPlayback *);
+-static void	*play_loop	(void *);
+-static void	aboutbox	(void);
+-#if __AUDACIOUS_PLUGIN_API__ >= 8
+-static int	is_our_file_from_vfs(CONST12 char *, VFSFile *);
+-#endif
+-#if __AUDACIOUS_PLUGIN_API__ < 12
+-static void	get_song_info	(char *, char **, int *);
+-#endif
+-static void	configure	(void);
+-static void	config_ok	(GtkWidget *, gpointer);
+-static void	mseek		(InputPlayback *, gulong);
+-static void	cleanup		(void);
+-
+-#if __AUDACIOUS_PLUGIN_API__ >= 2
+-static Tuple	*get_song_tuple	(CONST12 char *);
+-#endif
++static GMutex *seek_mutex;
++static GCond *seek_cond;
++static gint jumpToTime = -1;
++static gboolean stop_flag = FALSE;
+ 
+-static GThread *decode_thread;
+-static GStaticMutex load_mutex = G_STATIC_MUTEX_INIT;
++static xmp_context ctx;
+ 
++/* config values used for the Preferences UI */
++struct {
++    gboolean bits16, bits8;
++    gboolean stereo, mono;
++    gboolean freq44, freq22, freq11;
++    gboolean fixloops, modrange, convert8bit, interpolation, filter;
++    gfloat panamp;
++} guicfg;
++static void configure_init(void);
+ 
+ #define FREQ_SAMPLE_44 0
+ #define FREQ_SAMPLE_22 1
+ #define FREQ_SAMPLE_11 2
+ 
+-static struct {
+-	InputPlayback *ipb;
+-#if __AUDACIOUS_PLUGIN_API__ < 16
+-	AFormat fmt;
+-#else
+-	int fmt;
+-#endif
+-	int nch;
+-} play_data;
+-
+ typedef struct {
+ 	gint mixing_freq;
+ 	gint force8bit;
+@@ -92,84 +63,18 @@
+ 	struct xmp_module_info mod_info;
+ } XMPConfig;
+ 
+-
+ XMPConfig xmp_cfg;
+-static gboolean xmp_plugin_audio_error = FALSE;
+-
+-static GtkWidget *Res_16;
+-static GtkWidget *Res_8;
+-static GtkWidget *Chan_ST;
+-static GtkWidget *Chan_MO;
+-static GtkWidget *Sample_44;
+-static GtkWidget *Sample_22;
+-static GtkWidget *Sample_11;
+-static GtkWidget *Convert_Check;
+-static GtkWidget *Fixloops_Check;
+-static GtkWidget *Modrange_Check;
+-static GtkWidget *Interp_Check;
+-static GtkWidget *Filter_Check;
+-static GtkObject *pansep_adj;
+-
+-static GtkWidget *xmp_conf_window = NULL;
+-static GtkWidget *about_window = NULL;
+-
+-int skip = 0;
+-static short audio_open = FALSE;
+-
+-/* Filtering files by suffix is really stupid. */
+-static const gchar *fmts[] = {
+-	"xm", "mod", "m15", "it", "s2m", "s3m", "stm", "stx", "med", "dmf",
+-	"mtm", "ice", "imf", "ptm", "mdl", "ult", "liq", "psm", "amf",
+-        "rtm", "pt3", "tcb", "dt", "gtk", "dtt", "mgt", "digi", "dbm",
+-	"emod", "okt", "sfx", "far", "umx", "stim", "mtp", "ims", "669",
+-	"fnk", "funk", "amd", "rad", "hsc", "alm", "kris", "ksm", "unic",
+-	"zen", "crb", "tdd", "gmc", "gdm", "mdz", "xmz", "s3z", "j2b", NULL
+-};
+-
+-
+-InputPlugin xmp_ip = {
+-	.description	= "XMP Plugin " VERSION,
+-	.init		= init,
+-	.about		= aboutbox,
+-	.configure	= configure,
+-	.is_our_file	= is_our_file,
+-	.play_file	= play_file,
+-	.stop		= stop,
+-	.pause		= mod_pause,
+-	.seek		= seek,
+-	.get_time	= get_time,
+-#if __AUDACIOUS_PLUGIN_API__ >= 8
+-	.is_our_file_from_vfs = is_our_file_from_vfs,
+-#endif
+-#if __AUDACIOUS_PLUGIN_API__ < 12
+-	.get_song_info	= get_song_info,
+-#endif
+-	.cleanup	= cleanup,
+-#if __AUDACIOUS_PLUGIN_API__ >= 2
+-	.get_song_tuple	= get_song_tuple,
+-	.mseek		= mseek,
+-	.vfs_extensions = fmts,
+-#endif
+-};
+-
+-
+-#if __AUDACIOUS_PLUGIN_API__ >= 2
+-
+-InputPlugin *xmp_iplist[] = { &xmp_ip, NULL };
+ 
+-DECLARE_PLUGIN(xmp, NULL, NULL, xmp_iplist, NULL, NULL, NULL, NULL, NULL);
+-
+-#endif
+- 
+ extern struct xmp_drv_info drv_smix;
+ 
+ 
+-static void strip_vfs(char *s)
+-{
++static void strip_vfs(char *s) {
+ 	int len;
+ 	char *c;
+ 
+-	g_static_mutex_lock(&load_mutex);
++    if (!s) {
++        return;
++    }
+ 	_D("%s", s);
+ 	if (!memcmp(s, "file://", 7)) {
+ 		len = strlen(s);
+@@ -187,119 +92,35 @@
+ 			memmove(c, c + 2, len - 1);
+ 		}
+ 	}
+-	g_static_mutex_unlock(&load_mutex);
+ }
+ 
+-static void aboutbox()
+-{
+-	GtkWidget *vbox1;
+-	GtkWidget *label1;
+-	GtkWidget *about_exit;
+-	GtkWidget *scroll1;
+-	GtkWidget *table1;
+-	GtkWidget *label_fmt, *label_trk;
+-	struct xmp_fmt_info *f, *fmt;
+-	int i;
+-
+-	if (about_window) {
+-		gdk_window_raise(about_window->window);
+-		return;
+-	}
+-
+-	about_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+-	gtk_window_set_type_hint(GTK_WINDOW(about_window),
+-					GDK_WINDOW_TYPE_HINT_DIALOG);
+-	gtk_object_set_data(GTK_OBJECT(about_window),
+-		"about_window", about_window);
+-	gtk_window_set_title(GTK_WINDOW(about_window),"About the XMP Plugin");
+-	gtk_window_set_policy(GTK_WINDOW(about_window), FALSE, FALSE, FALSE);
+-	gtk_signal_connect(GTK_OBJECT(about_window), "destroy",
+-		GTK_SIGNAL_FUNC(gtk_widget_destroyed), &about_window);
+-	gtk_container_border_width(GTK_CONTAINER(about_window), 10);
+-	gtk_widget_realize(about_window);
+-
+-	vbox1 = gtk_vbox_new(FALSE, 4);
+-	gtk_container_add(GTK_CONTAINER(about_window), vbox1);
+-	gtk_object_set_data(GTK_OBJECT(about_window), "vbox1", vbox1);
+-	gtk_widget_show(vbox1);
+-	gtk_container_border_width(GTK_CONTAINER(vbox1), 10);
+-
+-	label1 = gtk_label_new(
+-		"Extended Module Player " VERSION "\n"
+-		"Written by Claudio Matsuoka and Hipolito Carraro Jr.\n"
+-		"\n"
+-		"Portions Copyright (C) 1998,2000 Olivier Lapicque,\n"
+-		"(C) 1998 Tammo Hinrichs, (C) 1998 Sylvain Chipaux,\n"
+-		"(C) 1997 Bert Jahn, (C) 1999 Tatsuyuki Satoh, (C)\n"
+-		"2001-2006 Russell Marks, (C) 2005-2006 Michael Kohn\n"
+-		"\n"
+-		"Supported module formats:"
+-	);
+-	gtk_object_set_data(GTK_OBJECT(label1), "label1", label1);
+-	gtk_box_pack_start(GTK_BOX(vbox1), label1, TRUE, TRUE, 0);
+-
+-	scroll1 = gtk_scrolled_window_new(NULL, NULL);
+-	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll1),
+-			GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+-	gtk_widget_set_size_request(scroll1, 290, 100);
+-	gtk_object_set_data(GTK_OBJECT(scroll1), "scroll1", scroll1);
+-	gtk_widget_set (scroll1, "height", 100, NULL);
+-	gtk_box_pack_start(GTK_BOX(vbox1), scroll1, TRUE, TRUE, 0);
+-
+-	xmp_get_fmt_info(&fmt);
+-	table1 = gtk_table_new(100, 2, FALSE);
+-	for (i = 0, f = fmt; f; i++, f = f->next) {
+-		label_fmt = gtk_label_new(f->id);
+-		label_trk = gtk_label_new(f->tracker);
+-		gtk_label_set_justify (GTK_LABEL (label_fmt), GTK_JUSTIFY_LEFT);
+-		gtk_label_set_justify (GTK_LABEL (label_trk), GTK_JUSTIFY_LEFT);
+-		gtk_table_attach_defaults (GTK_TABLE (table1),
+-						label_fmt, 0, 1, i, i + 1);
+-		gtk_table_attach_defaults (GTK_TABLE (table1),
+-						label_trk, 1, 2, i, i + 1);
+-	}
+-
+-	gtk_table_resize (GTK_TABLE (table1), i + 1, 3);
+-	gtk_object_set_data(GTK_OBJECT(table1), "table1", table1);
+-	
+-	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll1),
+-								table1);
+-
+-	about_exit = gtk_button_new_with_label("Ok");
+-	gtk_signal_connect_object(GTK_OBJECT(about_exit), "clicked",
+-		GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(about_window));
+-
+-	gtk_object_set_data(GTK_OBJECT(about_window), "about_exit", about_exit);
+-	gtk_box_pack_start(GTK_BOX(vbox1), about_exit, FALSE, FALSE, 0);
+ 
+-	gtk_widget_show_all(about_window);
++static void stop(InputPlayback *playback) {
++	_D("*** stop!");
++    g_mutex_lock(seek_mutex);
++    if (!stop_flag) {
++        xmp_stop_module(ctx); 
++        stop_flag = TRUE;
++        playback->output->abort_write();
++        g_cond_signal(seek_cond);
++    }
++    g_mutex_unlock(seek_mutex);
+ }
+ 
+ 
+-static xmp_context ctx;
+-
+-
+-static void stop(InputPlayback *ipb)
+-{
+-	if (!ipb->playing)
+-		return;
+-
+-	_D("*** stop!");
+-	xmp_stop_module(ctx); 
+-
+-	ipb->playing = 0;
+-	g_thread_join(decode_thread);
+-	ipb->output->close_audio();
+-        audio_open = FALSE;
++static void mseek(InputPlayback *playback, gint msec) {
++    g_mutex_lock(seek_mutex);
++    if (!stop_flag) {
++        jumpToTime = msec;
++        playback->output->abort_write();
++        g_cond_signal(seek_cond);
++        g_cond_wait(seek_cond, seek_mutex);
++    }
++    g_mutex_unlock(seek_mutex);
+ }
+ 
+-static void seek(InputPlayback *ipb, int time)
+-{
+-	mseek(ipb, time * 1000);
+-}
+ 
+-static void mseek(InputPlayback *ipb, unsigned long time)
+-{
++static void seek_ctx(gint time) {
+ 	int i, t;
+ 	struct xmp_player_context *p = &((struct xmp_context *)ctx)->p;
+ 
+@@ -315,59 +136,32 @@
+ 			if (i > 0)
+ 				i--;
+ 			a = xmp_ord_set(ctx, i);
+-#if __AUDACIOUS_PLUGIN_API__ < 13
+-			ipb->output->flush(p->m.xxo_info[i].time);
+-#else
+-			ipb->output->flush(p->m.xxo_info[i].time / 1000);
+-#endif
+ 			break;
+ 		}
+ 	}
+ }
+ 
+-static void mod_pause(InputPlayback *ipb, short p)
+-{
+-	ipb->output->pause(p);
+-}
+-
+-
+-static int get_time(InputPlayback *ipb)
+-{
+-	if (xmp_plugin_audio_error)
+-		return -2;
+-	if (!ipb->playing)
+-		return -1;
+-
+-#if __AUDACIOUS_PLUGIN_API__ < 13
+-	return ipb->output->output_time();
+-#else
+-	return ipb->output->written_time();
+-#endif
+-}
+-
+-
+-#if __AUDACIOUS_PLUGIN_API__ < 2
+ 
+-InputPlugin *get_iplugin_info()
+-{
+-	return &xmp_ip;
++static void mod_pause(InputPlayback *playback, gboolean p) {
++    g_mutex_lock(seek_mutex);
++    if (!stop_flag) {
++        playback->output->pause(p);
++    }
++    g_mutex_unlock(seek_mutex);
+ }
+ 
+-#endif
+ 
+-
+-static void init(void)
+-{
+-#if __AUDACIOUS_PLUGIN_API__ < 16
+-	ConfigDb *cfg;
+-#else
++static gboolean init(void) {
+ 	mcs_handle_t *cfg;
+-#endif
+ 
+ 	_D("Plugin init");
+ 	xmp_drv_register(&drv_smix);
+ 	ctx = xmp_create_context();
+ 
++    jumpToTime = -1;
++    seek_mutex = g_mutex_new();
++    seek_cond = g_cond_new();
++
+ 	xmp_cfg.mixing_freq = 0;
+ 	xmp_cfg.convert8bit = 0;
+ 	xmp_cfg.fixloops = 0;
+@@ -394,151 +188,96 @@
+ 		aud_cfg_db_close(cfg);
+ 	}
+ 
++    configure_init();
++
+ 	xmp_init(ctx, 0, NULL);
++    return TRUE;
+ }
+ 
+ 
+-static void cleanup()
+-{
++static void cleanup() {
++    g_cond_free(seek_cond);
++    g_mutex_free(seek_mutex);
+ 	xmp_free_context(ctx);
+ }
+ 
+ 
+-static int is_our_file(CONST12 char *filename)
+-{
+-	_D("filename = %s", filename);
+-	strip_vfs((char *)filename);		/* Sorry, no VFS support */
+-
+-	if (xmp_test_module(ctx, (char *)filename, NULL) == 0)
+-		return 1;
+-
+-	return 0;
+-}
+-
+-#if __AUDACIOUS_PLUGIN_API__ >= 8
+-
+-static int is_our_file_from_vfs(CONST12 char* filename, VFSFile *vfsfile)
+-{
+-	_D("filename = %s", filename);
+-	strip_vfs((char *)filename);		/* Sorry, no VFS support */
+-
+-	if (xmp_test_module(ctx, (char *)filename, NULL) == 0)
+-		return 1;
+-
+-	return 0;
+-}
+-
+-#endif
+-
+-#if __AUDACIOUS_PLUGIN_API__ < 12
+-
+-static void get_song_info(char *filename, char **title, int *length)
+-{
+-	xmp_context ctx2;
+-	int lret;
+-	struct xmp_module_info mi;
+-	struct xmp_options *opt;
++static int is_our_file_from_vfs(const char* _filename, VFSFile *vfsfile) {
++    gchar *filename = g_strdup(_filename);
++    gboolean ret;
+ 
+ 	_D("filename = %s", filename);
+ 	strip_vfs(filename);		/* Sorry, no VFS support */
+ 
+-	/* Create new context to load a file and get the length */
+-
+-	ctx2 = xmp_create_context();
+-	opt = xmp_get_options(ctx2);
+-	opt->skipsmp = 1;	/* don't load samples */
+-
+-	g_static_mutex_lock(&load_mutex);
+-	lret = xmp_load_module(ctx2, filename);
+-	g_static_mutex_unlock(&load_mutex);
+-
+-	if (lret < 0) {
+-		xmp_free_context(ctx2);
+-		return;
+-	}
+-
+-	*length = lret;
+-	xmp_get_module_info(ctx2, &mi);
+-	*title = g_strdup(mi.name);
++	ret = (xmp_test_module(ctx, filename, NULL) == 0);
+ 
+-	xmp_release_module(ctx2);
+-	xmp_free_context(ctx2);
++    g_free(filename);
++	return ret;
+ }
+ 
+-#endif
+ 
+-#if __AUDACIOUS_PLUGIN_API__ >= 2
+-
+-static Tuple *get_song_tuple(CONST12 char *filename)
+-{
+-	Tuple *tuple;
+-	xmp_context ctx2;
+-	int lret;
++Tuple *probe_for_tuple(const gchar *_filename, VFSFile *fd) {
++    gchar *filename = g_strdup(_filename);
++    xmp_context ctx;
++    int len;
++    Tuple *tuple;
+ 	struct xmp_module_info mi;
+ 	struct xmp_options *opt;
+ 
+ 	_D("filename = %s", filename);
+-	strip_vfs((char *)filename);		/* Sorry, no VFS support */
+-
+-	tuple = aud_tuple_new_from_filename(filename);
+-
+-	/* Create new context to load a file and get the length */
++	strip_vfs(filename);		/* Sorry, no VFS support */
+ 
+-	ctx2 = xmp_create_context();
+-	opt = xmp_get_options(ctx2);
++	ctx = xmp_create_context();
++	opt = xmp_get_options(ctx);
+ 	opt->skipsmp = 1;	/* don't load samples */
++	len = xmp_load_module(ctx, filename);
++    g_free(filename);
++    if (len < 0) {
++        xmp_free_context(ctx);
++        return NULL;
++    }
++
++	xmp_get_module_info(ctx, &mi);
++
++	tuple = tuple_new_from_filename(filename);
++	tuple_associate_string(tuple, FIELD_TITLE, NULL, mi.name);
++	tuple_associate_string(tuple, FIELD_CODEC, NULL, mi.type);
++	tuple_associate_int(tuple, FIELD_LENGTH, NULL, len);
+ 
+-	g_static_mutex_lock(&load_mutex);
+-	lret = xmp_load_module(ctx2, (char *)filename);
+-	g_static_mutex_unlock(&load_mutex);
+-
+-	if (lret < 0) {
+-		xmp_free_context(ctx2);
+-		return NULL;
+-	}
+-
+-	xmp_get_module_info(ctx2, &mi);
+-
+-	aud_tuple_associate_string(tuple, FIELD_TITLE, NULL, mi.name);
+-	aud_tuple_associate_string(tuple, FIELD_CODEC, NULL, mi.type);
+-	aud_tuple_associate_int(tuple, FIELD_LENGTH, NULL, lret);
+-
+-	xmp_release_module(ctx2);
+-	xmp_free_context(ctx2);
+-
+-	return tuple;
++	xmp_release_module(ctx);
++    xmp_free_context(ctx);
++    return tuple;
+ }
+ 
+-#endif
+ 
+-
+-static void play_file(InputPlayback *ipb)
+-{
+-	char *filename = ipb->filename;
++static gboolean play(InputPlayback *ipb, const gchar *_filename, VFSFile *file, gint start_time, gint stop_time, gboolean pause) {
+ 	int channelcnt = 1;
+ 	FILE *f;
+ 	struct xmp_options *opt;
+-	int lret;
++	int lret, fmt, nch;
++	void *data;
++	int size;
++    gchar *filename = g_strdup(_filename);
++	Tuple *tuple;
+ 	
+ 	_D("play: %s\n", filename);
++    if (file == NULL) {
++        return FALSE;
++    }
+ 	opt = xmp_get_options(ctx);
+ 
+-	/* Sorry, no VFS support */
+-	strip_vfs(filename);
++	strip_vfs(filename);  /* Sorry, no VFS support */
+ 
+ 	_D("play_file: %s", filename);
+ 
+-	stop(ipb);	/* sanity check */
++    jumpToTime = (start_time > 0) ? start_time : -1;
++    stop_flag = FALSE;
+ 
+ 	if ((f = fopen(filename,"rb")) == 0) {
+-		ipb->playing = 0;
+-		return;
++		goto PLAY_ERROR_1;
+ 	}
+ 	fclose(f);
+ 
+-	xmp_plugin_audio_error = FALSE;
+-	ipb->playing = 1;
+-
+ 	opt->resol = 8;
+ 	opt->verbosity = 0;
+ 	opt->drv_id = "smix";
+@@ -577,363 +316,107 @@
+ 
+ 	opt->mix = xmp_cfg.pan_amplitude;
+ 
+-	play_data.ipb = ipb;
+-	play_data.fmt = opt->resol == 16 ? FMT_S16_NE : FMT_U8;
+-	play_data.nch = opt->outfmt & XMP_FMT_MONO ? 1 : 2;
++	fmt = opt->resol == 16 ? FMT_S16_NE : FMT_U8;
++	nch = opt->outfmt & XMP_FMT_MONO ? 1 : 2;
+ 	
+-	if (audio_open)
+-	    ipb->output->close_audio();
+-	
+-	if (!ipb->output->open_audio(play_data.fmt, opt->freq, play_data.nch)) {
+-	    ipb->error = TRUE;
+-	    xmp_plugin_audio_error = TRUE;
+-	    return;
++	if (!ipb->output->open_audio(fmt, opt->freq, nch)) {
++		goto PLAY_ERROR_1;
+ 	}
+-	
+-	audio_open = TRUE;
+ 
+ 	xmp_open_audio(ctx);
+ 
+ 	_D("*** loading: %s", filename);
+ 
+-	g_static_mutex_lock(&load_mutex);
+ 	lret =  xmp_load_module(ctx, filename);
+-	g_static_mutex_unlock(&load_mutex);
++    g_free(filename);
+ 
+ 	if (lret < 0) {
+-#if __AUDACIOUS_PLUGIN_API__ < 13
+-		xmp_ip.set_info_text("Error loading mod");
+-#endif
+-		ipb->playing = 0;
+-		return;
++		xmp_close_audio(ctx);
++		goto PLAY_ERROR_1;
+ 	}
+ 
+ 	xmp_cfg.time = lret;
+ 	xmp_get_module_info(ctx, &xmp_cfg.mod_info);
+ 
+-#if __AUDACIOUS_PLUGIN_API__ >= 2
+-#if __AUDACIOUS_PLUGIN_API__ >= 12
+-	ipb->set_params(ipb, xmp_cfg.mod_info.name, lret,
+-		xmp_cfg.mod_info.chn * 1000, opt->freq, channelcnt);
+-#else
+-	ipb->set_params(ipb, xmp_cfg.mod_info.name, lret, 0,
+-						opt->freq, channelcnt);
+-#endif
+-	ipb->playing = 1;
+-	ipb->eof = 0;
+-	ipb->error = FALSE;
++	tuple = tuple_new_from_filename(filename);
++	tuple_associate_string(tuple, FIELD_TITLE, NULL, xmp_cfg.mod_info.name);
++	tuple_associate_string(tuple, FIELD_CODEC, NULL, xmp_cfg.mod_info.type);
++	tuple_associate_int(tuple, FIELD_LENGTH, NULL, lret);
++    ipb->set_tuple( ipb, tuple );
+ 
+-	decode_thread = g_thread_self();
++	ipb->set_params(ipb, xmp_cfg.mod_info.chn * 1000, opt->freq, channelcnt);
+ 	ipb->set_pb_ready(ipb);
+-	play_loop(ipb);
+-#else
+-	xmp_ip.set_info(xmp_cfg.mod_info.name, lret, 0, opt->freq, channelcnt);
+-	decode_thread = g_thread_create(play_loop, ipb, TRUE, NULL);
+-#endif
+-}
+-
+-
+-static gpointer play_loop(gpointer arg)
+-{
+-	InputPlayback *ipb = arg;
+-	void *data;
+-	int size;
+ 
++	stop_flag = FALSE;
+ 	xmp_player_start(ctx);
+-	while (xmp_player_frame(ctx) == 0) {
+-		xmp_get_buffer(ctx, &data, &size);
+ 
+-#if __AUDACIOUS_PLUGIN_API__ >= 2
+-		play_data.ipb->pass_audio(play_data.ipb, play_data.fmt,
+-			play_data.nch, size, data, &play_data.ipb->playing);
+-
+-#else
+-		xmp_ip.add_vis_pcm(xmp_ip.output->written_time(),
+-			xmp_cfg.force8bit ? FMT_U8 : FMT_S16_NE,
+-			xmp_cfg.force_mono ? 1 : 2, size, data);
+-	
+-		while (xmp_ip.output->buffer_free() < size && play_data.ipb->playing)
+-			usleep(10000);
+-
+-		if (play_data.ipb->playing)
+-			xmp_ip.output->write_audio(data, size);
+-#endif
+-	}
++	while ( !stop_flag ) {
++        if (stop_time >= 0 && ipb->output->written_time () >= stop_time) {
++            goto DRAIN;
++        }
++        g_mutex_lock(seek_mutex);
++        if ( jumpToTime != -1 ) {
++            seek_ctx(jumpToTime);
++            ipb->output->flush(jumpToTime);
++            jumpToTime = -1;
++            g_cond_signal(seek_cond);
++        }
++        g_mutex_unlock(seek_mutex);
+ 
++		xmp_get_buffer(ctx, &data, &size);
++        if ( !stop_flag && jumpToTime<0 ) {
++            ipb->output->write_audio(data,size);
++        }
++        if ( (xmp_player_frame(ctx) != 0) && jumpToTime<0 ) {
++            stop_flag = TRUE;
++ DRAIN:
++            while ( !stop_flag && ipb->output->buffer_playing() ) {
++                g_usleep(20000);
++            }
++            break;
++        }
++	}
++    g_mutex_lock(seek_mutex);
++    stop_flag = TRUE;
++    g_cond_signal(seek_cond);  /* wake up any waiting request */
++    g_mutex_unlock(seek_mutex);
+ 
++    ipb->output->close_audio();
+ 	xmp_player_end(ctx);
+-
+ 	xmp_release_module(ctx);
+ 	xmp_close_audio(ctx);
++    return TRUE;
+ 
+-	ipb->eof = 1;
+-	ipb->playing = 0;
+-
+-	return NULL;
++ PLAY_ERROR_1:
++    g_free(filename);
++    return FALSE;
+ }
+ 
+ 
+-static void configure()
+-{
+-	GtkWidget *notebook1;
+-	GtkWidget *vbox;
+-	GtkWidget *vbox1;
+-	GtkWidget *hbox1;
+-	GtkWidget *Resolution_Frame;
+-	GtkWidget *vbox4;
+-	GSList *resolution_group = NULL;
+-	GtkWidget *Channels_Frame;
+-	GtkWidget *vbox5;
+-	GSList *vbox5_group = NULL;
+-	GtkWidget *Downsample_Frame;
+-	GtkWidget *vbox3;
+-	GSList *sample_group = NULL;
+-	GtkWidget *vbox6;
+-	GtkWidget *Quality_Label;
+-	GtkWidget *Options_Label;
+-	GtkWidget *pansep_label, *pansep_hscale;
+-	GtkWidget *bbox;
+-	GtkWidget *ok;
+-	GtkWidget *cancel;
+-
+-	if (xmp_conf_window) {
+-		gdk_window_raise(xmp_conf_window->window);
+-		return;
+-	}
+-
+-	xmp_conf_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+-	gtk_window_set_type_hint(GTK_WINDOW(xmp_conf_window),
+-					GDK_WINDOW_TYPE_HINT_DIALOG);
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window),
+-		"xmp_conf_window", xmp_conf_window);
+-	gtk_window_set_title(GTK_WINDOW(xmp_conf_window), "XMP Configuration");
+-	gtk_window_set_policy(GTK_WINDOW(xmp_conf_window), FALSE, FALSE, FALSE);
+-	gtk_window_set_position(GTK_WINDOW(xmp_conf_window), GTK_WIN_POS_MOUSE);
+-	gtk_signal_connect(GTK_OBJECT(xmp_conf_window), "destroy",
+-		GTK_SIGNAL_FUNC(gtk_widget_destroyed),&xmp_conf_window);
+-	gtk_container_border_width(GTK_CONTAINER(xmp_conf_window), 10);
+-
+-	vbox = gtk_vbox_new(FALSE, 10);
+-	gtk_container_add(GTK_CONTAINER(xmp_conf_window), vbox);
+-
+-	notebook1 = gtk_notebook_new();
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window),"notebook1", notebook1);
+-	gtk_widget_show(notebook1);
+-	gtk_box_pack_start(GTK_BOX(vbox), notebook1, TRUE, TRUE, 0);
+-	gtk_container_border_width(GTK_CONTAINER(notebook1), 3);
+-
+-	vbox1 = gtk_vbox_new(FALSE, 0);
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window),"vbox1", vbox1);
+-	gtk_widget_show(vbox1);
+-
+-	hbox1 = gtk_hbox_new(FALSE, 0);
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window),"hbox1", hbox1);
+-	gtk_widget_show(hbox1);
+-	gtk_box_pack_start(GTK_BOX(vbox1), hbox1, TRUE, TRUE, 0);
+-
+-	Resolution_Frame = gtk_frame_new("Resolution");
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window),
+-		"Resolution_Frame", Resolution_Frame);
+-	gtk_widget_show(Resolution_Frame);
+-	gtk_box_pack_start(GTK_BOX(hbox1), Resolution_Frame, TRUE, TRUE, 0);
+-	gtk_container_set_border_width(GTK_CONTAINER (Resolution_Frame), 5);
+-
+-	vbox4 = gtk_vbox_new(FALSE, 0);
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window),"vbox4", vbox4);
+-	gtk_widget_show(vbox4);
+-	gtk_container_add(GTK_CONTAINER(Resolution_Frame), vbox4);
+-
+-	Res_16 = gtk_radio_button_new_with_label(resolution_group, "16 bit");
+-	resolution_group = gtk_radio_button_group(GTK_RADIO_BUTTON(Res_16));
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window), "Res_16", Res_16);
+-	gtk_widget_show(Res_16);
+-	gtk_box_pack_start(GTK_BOX(vbox4), Res_16, TRUE, TRUE, 0);
+-	if (xmp_cfg.force8bit == 0)
+-		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Res_16), TRUE);
+-
+-	Res_8 = gtk_radio_button_new_with_label(resolution_group, "8 bit");
+-	resolution_group = gtk_radio_button_group(GTK_RADIO_BUTTON(Res_8));
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window), "Res_8", Res_8);
+-	gtk_widget_show(Res_8);
+-	gtk_box_pack_start(GTK_BOX(vbox4), Res_8, TRUE, TRUE, 0);
+-	if (xmp_cfg.force8bit == 1)
+-		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Res_8), TRUE);
+-
+-	Channels_Frame = gtk_frame_new("Channels");
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window),
+-		"Channels_Frame", Channels_Frame);
+-	gtk_widget_show(Channels_Frame);
+-	gtk_box_pack_start(GTK_BOX(hbox1), Channels_Frame, TRUE, TRUE, 0);
+-	gtk_container_set_border_width(GTK_CONTAINER(Channels_Frame), 5);
+-
+-	vbox5 = gtk_vbox_new(FALSE, 0);
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window), "vbox5", vbox5);
+-	gtk_widget_show(vbox5);
+-	gtk_container_add(GTK_CONTAINER(Channels_Frame), vbox5);
+-
+-	Chan_ST = gtk_radio_button_new_with_label(vbox5_group, "Stereo");
+-	vbox5_group = gtk_radio_button_group(GTK_RADIO_BUTTON(Chan_ST));
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window), "Chan_ST", Chan_ST);
+-	gtk_widget_show(Chan_ST);
+-	gtk_box_pack_start(GTK_BOX(vbox5), Chan_ST, TRUE, TRUE, 0);
+-	if (xmp_cfg.force_mono == 0)
+-		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Chan_ST), TRUE);
+-
+-	Chan_MO = gtk_radio_button_new_with_label(vbox5_group, "Mono");
+-	vbox5_group = gtk_radio_button_group(GTK_RADIO_BUTTON(Chan_MO));
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window), "Chan_MO", Chan_MO);
+-	gtk_widget_show(Chan_MO);
+-	gtk_box_pack_start(GTK_BOX(vbox5), Chan_MO, TRUE, TRUE, 0);
+-	if (xmp_cfg.force_mono == 1)
+-		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Chan_MO), TRUE);
+-
+-	Downsample_Frame = gtk_frame_new("Sampling rate");
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window),
+-		"Downsample_Frame", Downsample_Frame);
+-	gtk_widget_show(Downsample_Frame);
+-	gtk_box_pack_start(GTK_BOX(vbox1), Downsample_Frame, TRUE, TRUE, 0);
+-	gtk_container_set_border_width(GTK_CONTAINER(Downsample_Frame), 5);
+-
+-	vbox3 = gtk_vbox_new(FALSE, 0);
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window), "vbox3", vbox3);
+-	gtk_widget_show(vbox3);
+-	gtk_container_add(GTK_CONTAINER(Downsample_Frame), vbox3);
+-
+-	Sample_44 = gtk_radio_button_new_with_label(sample_group, "44 kHz");
+-	sample_group = gtk_radio_button_group(GTK_RADIO_BUTTON(Sample_44));
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window),"Sample_44", Sample_44);
+-	gtk_widget_show(Sample_44);
+-	gtk_box_pack_start(GTK_BOX(vbox3), Sample_44, TRUE, TRUE, 0);
+-	if (xmp_cfg.mixing_freq == FREQ_SAMPLE_44)
+-		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Sample_44),TRUE);
+-
+-	Sample_22 = gtk_radio_button_new_with_label(sample_group, "22 kHz");
+-	sample_group = gtk_radio_button_group(GTK_RADIO_BUTTON(Sample_22));
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window), "Sample_22",Sample_22);
+-	gtk_widget_show(Sample_22);
+-	gtk_box_pack_start(GTK_BOX(vbox3), Sample_22, TRUE, TRUE, 0);
+-	if (xmp_cfg.mixing_freq == FREQ_SAMPLE_22)
+-		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Sample_22),TRUE);
+-
+-	Sample_11 = gtk_radio_button_new_with_label(sample_group, "11 kHz");
+-	sample_group = gtk_radio_button_group(GTK_RADIO_BUTTON(Sample_11));
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window), "Sample_11",Sample_11);
+-	gtk_widget_show(Sample_11);
+-	gtk_box_pack_start(GTK_BOX(vbox3), Sample_11, TRUE, TRUE, 0);
+-	if (xmp_cfg.mixing_freq == FREQ_SAMPLE_11)
+-		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(Sample_11),TRUE);
+-
+-	vbox6 = gtk_vbox_new(FALSE, 0);
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window), "vbox6", vbox6);
+-	gtk_widget_show(vbox6);
+-
+-	/* Options */
+-
+-#define OPTCHECK(w,l,o) {						\
+-	w = gtk_check_button_new_with_label(l);				\
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window), #w, w);	\
+-	gtk_widget_show(w);						\
+-	gtk_box_pack_start(GTK_BOX(vbox6), w, TRUE, TRUE, 0);		\
+-	if (xmp_cfg.o == 1)						\
+-		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), TRUE); \
+-}
+-
+-	OPTCHECK(Convert_Check, "Convert 16 bit samples to 8 bit", convert8bit);
+-	OPTCHECK(Fixloops_Check, "Fix sample loops", fixloops);
+-	OPTCHECK(Modrange_Check, "Force 3 octave range in standard MOD files",
+-		modrange);
+-	OPTCHECK(Interp_Check, "Enable 32-bit linear interpolation",
+-		interpolation);
+-	OPTCHECK(Filter_Check, "Enable IT filters", filter);
+-
+-	pansep_label = gtk_label_new("Pan amplitude (%)");
+-	gtk_widget_show(pansep_label);
+-	gtk_box_pack_start(GTK_BOX(vbox6), pansep_label, TRUE, TRUE, 0);
+-	pansep_adj = gtk_adjustment_new(xmp_cfg.pan_amplitude,
+-		0.0, 100.0, 1.0, 10.0, 1.0);
+-	pansep_hscale = gtk_hscale_new(GTK_ADJUSTMENT(pansep_adj));
+-	gtk_scale_set_digits(GTK_SCALE(pansep_hscale), 0);
+-	gtk_scale_set_draw_value(GTK_SCALE(pansep_hscale), TRUE);
+-	gtk_scale_set_value_pos(GTK_SCALE(pansep_hscale), GTK_POS_BOTTOM);
+-	gtk_widget_show(pansep_hscale);
+-	gtk_box_pack_start(GTK_BOX(vbox6), pansep_hscale, TRUE, TRUE, 0);
+-
+-	Quality_Label = gtk_label_new("Quality");
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window),
+-		"Quality_Label", Quality_Label);
+-	gtk_widget_show(Quality_Label);
+-	gtk_notebook_append_page(GTK_NOTEBOOK(notebook1), vbox1, Quality_Label);
+-
+-	Options_Label = gtk_label_new("Options");
+-	gtk_object_set_data(GTK_OBJECT(xmp_conf_window),
+-		"Options_Label", Options_Label);
+-	gtk_widget_show(Options_Label);
+-	gtk_notebook_append_page(GTK_NOTEBOOK(notebook1), vbox6, Options_Label);
+-
+-	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(config_ok), NULL);
+-	GTK_WIDGET_SET_FLAGS(ok, GTK_CAN_DEFAULT);
+-	gtk_box_pack_start(GTK_BOX(bbox), ok, TRUE, TRUE, 0);
+-	gtk_widget_show(ok);
+-	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(xmp_conf_window));
+-	GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT);
+-	gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0);
+-	gtk_widget_show(cancel);
+-
+-	gtk_widget_show(bbox);
+-
+-	gtk_widget_show(vbox);
+-	gtk_widget_show(xmp_conf_window);
+-}
+-
+-
+-static void config_ok(GtkWidget *widget, gpointer data)
+-{
+-#if __AUDACIOUS_PLUGIN_API__ < 16
+-	ConfigDb *cfg;
+-#else
++static void configure_apply() {
+ 	mcs_handle_t *cfg;
+-#endif
+ 	struct xmp_options *opt;
+ 
+-	opt = xmp_get_options(ctx);
+-
+-	if (GTK_TOGGLE_BUTTON(Res_16)->active)
+-		xmp_cfg.force8bit = 0;
+-	if (GTK_TOGGLE_BUTTON(Res_8)->active)
+-		xmp_cfg.force8bit = 1;
+-
+-	if (GTK_TOGGLE_BUTTON(Chan_ST)->active)
+-		xmp_cfg.force_mono = 0;
+-	if (GTK_TOGGLE_BUTTON(Chan_MO)->active)
+-		xmp_cfg.force_mono = 1;
+-
+-	if (GTK_TOGGLE_BUTTON(Sample_44)->active)
+-		xmp_cfg.mixing_freq = 0;
+-	if (GTK_TOGGLE_BUTTON(Sample_22)->active)
+-		xmp_cfg.mixing_freq = 1;
+-	if (GTK_TOGGLE_BUTTON(Sample_11)->active)
+-		xmp_cfg.mixing_freq = 2;
+-
+-	xmp_cfg.interpolation = !!GTK_TOGGLE_BUTTON(Interp_Check)->active;
+-	xmp_cfg.filter = !!GTK_TOGGLE_BUTTON(Filter_Check)->active;
+-	xmp_cfg.convert8bit = !!GTK_TOGGLE_BUTTON(Convert_Check)->active;
+-	xmp_cfg.modrange = !!GTK_TOGGLE_BUTTON(Modrange_Check)->active;
+-	xmp_cfg.fixloops = !!GTK_TOGGLE_BUTTON(Fixloops_Check)->active;
++    /* transfer Preferences UI config values back into XMPConfig */
++    if (guicfg.freq11) {
++        xmp_cfg.mixing_freq = FREQ_SAMPLE_11;
++    }
++    else if (guicfg.freq22) {
++        xmp_cfg.mixing_freq = FREQ_SAMPLE_22;
++    }
++    else {  /* if (guicfg.freq44) { */
++        xmp_cfg.mixing_freq = FREQ_SAMPLE_44;
++    }
++    xmp_cfg.convert8bit = guicfg.bits8;
++    xmp_cfg.force_mono = guicfg.mono;
++    xmp_cfg.fixloops = guicfg.fixloops;
++    xmp_cfg.modrange = guicfg.modrange;
++    xmp_cfg.interpolation = guicfg.interpolation;
++    xmp_cfg.filter = guicfg.filter;
++    xmp_cfg.pan_amplitude = (gint)guicfg.panamp;
+ 
+-	xmp_cfg.pan_amplitude = (guchar)GTK_ADJUSTMENT(pansep_adj)->value;
+-        opt->mix = xmp_cfg.pan_amplitude;
++	opt = xmp_get_options(ctx);
++    opt->mix = xmp_cfg.pan_amplitude;
+ 
+ 	cfg = aud_cfg_db_open();
+ 
+@@ -950,7 +433,150 @@
+ 	CFGWRITEINT (pan_amplitude);
+ 
+ 	aud_cfg_db_close(cfg);
++}
+ 
+-	gtk_widget_destroy(xmp_conf_window);
++static void configure_init(void) {
++    /* transfer XMPConfig into Preferences UI config */
++    /* keeping compatibility with older releases */
++    guicfg.freq11 = (xmp_cfg.mixing_freq == FREQ_SAMPLE_11);
++    guicfg.freq22 = (xmp_cfg.mixing_freq == FREQ_SAMPLE_22);
++    guicfg.freq44 = (xmp_cfg.mixing_freq == FREQ_SAMPLE_44);
++    guicfg.mono = xmp_cfg.force_mono;
++    guicfg.stereo = !xmp_cfg.force_mono;
++    guicfg.bits8 = xmp_cfg.convert8bit;
++    guicfg.bits16 = !xmp_cfg.convert8bit;
++    guicfg.convert8bit = xmp_cfg.convert8bit;
++    guicfg.fixloops = xmp_cfg.fixloops;
++    guicfg.modrange = xmp_cfg.modrange;
++    guicfg.interpolation = xmp_cfg.interpolation;
++    guicfg.filter = xmp_cfg.filter;
++    guicfg.panamp = xmp_cfg.pan_amplitude;
++}
++
++void xmp_aud_about() {
++    static GtkWidget *about_window = NULL;
++
++    audgui_simple_message(&about_window, GTK_MESSAGE_INFO,
++                          g_strdup_printf(
++                "Extended Module Player %s",VERSION),
++                "Written by Claudio Matsuoka and Hipolito Carraro Jr.\n"
++                "\n"
++                "Portions Copyright (C) 1998,2000 Olivier Lapicque,\n"
++                "(C) 1998 Tammo Hinrichs, (C) 1998 Sylvain Chipaux,\n"
++                "(C) 1997 Bert Jahn, (C) 1999 Tatsuyuki Satoh, (C)\n"
++                "2001-2006 Russell Marks, (C) 2005-2006 Michael Kohn\n"
++                "\n"
++                          /* TODO: list */
++                          /* "Supported module formats:" */
++                          );
+ }
+ 
++
++static PreferencesWidget prefs_precision[] = {
++    {WIDGET_RADIO_BTN, "16 bit", &guicfg.bits16, NULL, NULL, FALSE, .cfg_type = VALUE_BOOLEAN},
++    {WIDGET_RADIO_BTN, "8 bit", &guicfg.bits8, NULL, NULL, FALSE, .cfg_type = VALUE_BOOLEAN},
++};
++
++static PreferencesWidget prefs_channels[] = {
++    {WIDGET_RADIO_BTN, "Stereo", &guicfg.stereo, NULL, NULL, FALSE, .cfg_type = VALUE_BOOLEAN},
++    {WIDGET_RADIO_BTN, "Mono", &guicfg.mono, NULL, NULL, FALSE, .cfg_type = VALUE_BOOLEAN},
++};
++
++static PreferencesWidget prefs_frequency[] = {
++    {WIDGET_RADIO_BTN, "44 kHz", &guicfg.freq44, NULL, NULL, FALSE, .cfg_type = VALUE_BOOLEAN},
++    {WIDGET_RADIO_BTN, "22 kHz", &guicfg.freq22, NULL, NULL, FALSE, .cfg_type = VALUE_BOOLEAN},
++    {WIDGET_RADIO_BTN, "11 kHz", &guicfg.freq11, NULL, NULL, FALSE, .cfg_type = VALUE_BOOLEAN},
++};
++
++static PreferencesWidget prefs_opts[] = {
++    {WIDGET_CHK_BTN, "Convert 16 bit samples to 8 bit", &guicfg.convert8bit, NULL, NULL, FALSE,
++     .cfg_type = VALUE_BOOLEAN},
++    {WIDGET_CHK_BTN, "Fix sample loops", &guicfg.fixloops, NULL, NULL, FALSE,
++     .cfg_type = VALUE_BOOLEAN},
++    {WIDGET_CHK_BTN, "Force 3 octave range in standard MOD files", &guicfg.modrange, NULL, NULL, FALSE,
++     .cfg_type = VALUE_BOOLEAN},
++    {WIDGET_CHK_BTN, "Enable 32-bit linear interpolation", &guicfg.interpolation, NULL, NULL, FALSE,
++     .cfg_type = VALUE_BOOLEAN},
++    {WIDGET_CHK_BTN, "Enable IT filters", &guicfg.filter, NULL, NULL, FALSE,
++     .cfg_type = VALUE_BOOLEAN},
++    {WIDGET_LABEL, "Pan amplitude (%)", NULL, NULL, NULL, FALSE},
++    {WIDGET_SPIN_BTN, "", &guicfg.panamp, NULL, NULL, FALSE,
++     {.spin_btn = {0.0,100.0,1.0,""}},
++     .cfg_type = VALUE_FLOAT},
++};
++
++static PreferencesWidget prefs_opts_tab[] = {
++    {WIDGET_BOX, NULL, NULL, NULL, NULL, FALSE,
++     {.box = {prefs_opts, G_N_ELEMENTS(prefs_opts), FALSE, FALSE}}},
++};
++
++static PreferencesWidget prefs_qual_row1[] = {
++    {WIDGET_BOX, "Resolution", NULL, NULL, NULL, FALSE,
++     {.box = {prefs_precision, G_N_ELEMENTS(prefs_precision), FALSE, TRUE}}},
++    {WIDGET_BOX, "Channels", NULL, NULL, NULL, FALSE,
++     {.box = {prefs_channels, G_N_ELEMENTS(prefs_channels), FALSE, TRUE}}},
++};
++
++static PreferencesWidget prefs_qual_row2[] = {
++    {WIDGET_BOX, "Sampling rate", NULL, NULL, NULL, FALSE,
++     {.box = {prefs_frequency, G_N_ELEMENTS(prefs_frequency), FALSE, TRUE}}},
++};
++
++static PreferencesWidget prefs_qual_box1[] = {
++    {WIDGET_BOX, NULL, NULL, NULL, NULL, FALSE,
++     {.box = {prefs_qual_row1, G_N_ELEMENTS(prefs_qual_row1), TRUE, TRUE}}},
++    {WIDGET_BOX, NULL, NULL, NULL, NULL, FALSE,
++     {.box = {prefs_qual_row2, G_N_ELEMENTS(prefs_qual_row2), FALSE, TRUE}}},
++};
++
++static PreferencesWidget prefs_qual_tab[] = {
++    {WIDGET_BOX, NULL, NULL, NULL, NULL, FALSE,
++     {.box = {prefs_qual_box1, G_N_ELEMENTS(prefs_qual_box1), FALSE, TRUE}}},
++};
++
++static NotebookTab prefs_tabs[] = {
++    {"Quality", prefs_qual_tab, G_N_ELEMENTS(prefs_qual_tab)},
++    {"Options", prefs_opts_tab, G_N_ELEMENTS(prefs_opts_tab)},
++};
++
++static PreferencesWidget prefs[] = {
++    {WIDGET_NOTEBOOK, NULL, NULL, NULL, NULL, FALSE,
++     {.notebook = {prefs_tabs, G_N_ELEMENTS(prefs_tabs)}},
++    },
++};
++
++PluginPreferences xmp_aud_preferences = {
++    .domain = "xmpaudplugin",
++    .title = "Extended Module Player Configuration",
++    .prefs = prefs,
++    .n_prefs = G_N_ELEMENTS(prefs),
++    .type = PREFERENCES_WINDOW,
++    .init = configure_init,
++    .apply = configure_apply,
++};
++
++/* Filtering files by suffix is really stupid. */
++const gchar* const fmts[] = {
++	"xm", "mod", "m15", "it", "s2m", "s3m", "stm", "stx", "med", "dmf",
++	"mtm", "ice", "imf", "ptm", "mdl", "ult", "liq", "psm", "amf",
++        "rtm", "pt3", "tcb", "dt", "gtk", "dtt", "mgt", "digi", "dbm",
++	"emod", "okt", "sfx", "far", "umx", "stim", "mtp", "ims", "669",
++	"fnk", "funk", "amd", "rad", "hsc", "alm", "kris", "ksm", "unic",
++	"zen", "crb", "tdd", "gmc", "gdm", "mdz", "xmz", "s3z", "j2b", NULL
++};
++
++AUD_INPUT_PLUGIN
++(
++	.name		= "XMP Plugin " VERSION,
++	.init		= init,
++	.about		= xmp_aud_about,
++    .settings	= &xmp_aud_preferences,
++	.play		= play,
++	.stop		= stop,
++	.pause		= mod_pause,
++    .probe_for_tuple = probe_for_tuple,
++	.is_our_file_from_vfs = is_our_file_from_vfs,
++	.cleanup	= cleanup,
++	.mseek		= mseek,
++	.extensions = fmts,
++)
diff --git a/xmp.spec b/xmp.spec
index 67d4bbd..3bb9fd1 100644
--- a/xmp.spec
+++ b/xmp.spec
@@ -8,7 +8,7 @@
 
 Name: xmp
 Version: 3.3.0
-Release: 7%{?dist}
+Release: 8%{?dist}
 Summary: A multi-format module player
 Group: Applications/Multimedia
 #Source: http://downloads.sourceforge.net/sourceforge/xmp/xmp-%{version}.tar.gz
@@ -18,7 +18,7 @@ Source: %{name}-%{version}-free.tar.gz
 Source1: mktarball.sh
 #Patch0: 0001-Don-t-crash-Audacious-if-module-is-invalid.patch
 #Patch1: 0002-Fix-Audacious-plugin-seek-position.patch
-Patch2: xmp-3.3.0-aud25.patch
+Patch2: xmp-3.3.0-aud30.patch
 License: GPLv2+
 URL: http://xmp.sourceforge.net/
 Buildrequires: alsa-lib-devel
@@ -73,7 +73,7 @@ This package contains the xmp plugin for XMMS.
 %setup -q
 #patch0 -p1
 #patch1 -p1
-%patch2 -p1 -b audacious-2.5
+%patch2 -p1 -b audacious-3.0
 pushd docs
 for file in ChangeLog CREDITS ; do
 	iconv -f iso8859-1 -t utf8 -o $file.utf $file && touch -r $file $file.utf && mv $file.utf $file
@@ -110,6 +110,9 @@ rm -rf %{buildroot}
 %{xmms_input_plugin_dir}/*
 
 %changelog
+* Thu Jul  7 2011 Michael Schwendt <mschwendt at fedoraproject.org> - 3.3.0-8
+- Rewrite the Audacious plugin for Audacious 3.0 Preferences Widgets.
+
 * Sun Mar 27 2011 Michael Schwendt <mschwendt at fedoraproject.org> - 3.3.0-7
 - Rewrite the Audacious plugin for Audacious 2.5.
 - Verbose build log with V=1 make.


More information about the scm-commits mailing list