[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