changeset 5:5b7009eef767

Updated to 0.8
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 03 Jun 2003 11:07:00 +0000
parents 4bb09e405eab
children ff6b3a556a15
files src/Makefile.am src/xmms-sid.cc
diffstat 2 files changed, 353 insertions(+), 252 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile.am	Tue Jun 03 11:03:04 2003 +0000
+++ b/src/Makefile.am	Tue Jun 03 11:07:00 2003 +0000
@@ -1,23 +1,23 @@
 # Generated libraries
-lib_LTLIBRARIES = libsid.la
+lib_LTLIBRARIES = libxmmssid.la
 
 # Generals
-
-CFLAGS   = -O2 -W -Wall -I$(top_builddir) -I$(top_srcdir) -I$(includedir) -D_REENTRANT @GTK_CFLAGS@ @SIDPLAY_CFLAGS@ -lstdc++
+CFLAGS   = -D_REENTRANT @GTK_CFLAGS@ @SIDPLAY_CFLAGS@
 CXXFLAGS = $(CFLAGS)
-LIBS     = -lsidplay
 
-libsid_la_LDFLAGS = -module -avoid-version
-libsid_la_LIBADD  = @GTK_LIBS@ @PTHREAD_LIBS@
+libxmmssid_la_LDFLAGS = -module -avoid-version
+libxmmssid_la_LIBADD  = @GTK_LIBS@ @PTHREAD_LIBS@ @SIDPLAY_LIBS@ -lstdc++
 
 # Plugin sources
-libsid_la_SOURCES =	\
-	xmms-sid.cc	\
+libxmmssid_la_SOURCES =	\
+	xmms-sid.cpp	xmms-sid.h	\
 	xs_init.c	\
-	xs_config.c	\
-	xs_fileinfo.cc	\
-	xs_stil.c	\
-	xs_about.c	\
-	xmms-sid.h	\
-	xmms-sid-logo.xpm
-
+	xs_title.cpp	\
+	xs_support.c	xs_support.h	\
+	xs_config.c	xs_config.h	\
+	xs_md5.c	xs_md5.h	\
+	xs_length.c	xs_length.h	\
+	xs_stil.c	xs_stil.h	\
+	xs_genui.c	xs_genui.h	\
+	xs_glade.c	xs_glade.h	\
+	xs_interface.c	xs_interface.h
--- a/src/xmms-sid.cc	Tue Jun 03 11:03:04 2003 +0000
+++ b/src/xmms-sid.cc	Tue Jun 03 11:07:00 2003 +0000
@@ -1,10 +1,10 @@
 /*
-   xmms-sid - SIDPlay input plugin for X MultiMedia System (XMMS)
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
 
    Main source file
 
-   Originally by Willem Monsuwe <willem@stack.nl>
-   Additions, fixes, etc by Matti "ccr" Hamalainen <mhamalai@ratol.fi>
+   Written by Matti "ccr" Hamalainen <ccr@tnsp.org>
+   (few bits may still be by Willem Monsuwe)
 
    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
@@ -26,13 +26,13 @@
 #include <sidplay/myendian.h>
 #include <sidplay/fformat.h>
 
-
 extern "C" {
 #include <pthread.h>
 
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <errno.h>
 
 #include <xmms/plugin.h>
 #include <xmms/util.h>
@@ -40,235 +40,302 @@
 
 
 /*
- *	General variables
+ *	Global variables
  */
 static struct emuConfig	xs_emuConf;
 static emuEngine	xs_emuEngine;
 static pthread_t	xs_decode_thread;
-static int		xs_error = 0, xs_going = 0, xs_songs = 0;
-struct T_sid_cfg	xs_cfg;
+struct t_xs_cfg		xs_cfg;
+
+struct {
+	int	s_error, s_playing, s_songs, s_allownext;
+	sidTune	*s_tune;
+	gchar	*s_fname;
+} xs_status;
+
+pthread_mutex_t xs_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 
 /*
- *	Initialize xmms-sid plugin
+ * Initialize XMMS-SID
  */
 void xs_init(void)
 {
+ XSDEBUG("xs_init()\n");
 
-	if (!xs_emuEngine) {
-		xs_error = 1;
-		XSERR("Couldn't start SIDPlay emulator engine!\n");
-		return;
+ /* Try to initialize libSIDPlay */
+ if (!xs_emuEngine)
+	{
+	XSERR("Couldn't start SIDPlay emulator engine!\n");
+	return;
 	}
 
-	if (!xs_emuEngine.verifyEndianess()) {
-		xs_error = 1;
-		XSERR("Wrong hardware endianess (SIDPlay error)!\n");
-		return;
+ if (!xs_emuEngine.verifyEndianess())
+	{
+	XSERR("Wrong hardware endianess (SIDPlay error)!\n");
+	return;
 	}
 
-	// Initialize STIL structures
-	memset(&xs_stil_info, 0, sizeof(xs_stil_info));
-	xs_stil_clear();
-
-	// Get configuration
-	xs_get_configure();
-}
-
+ /* Initialize and get configuration */
+ memset(&xs_cfg, 0, sizeof(xs_cfg));
+ xs_get_configure();
 
-/*
- *	Special, custom hand-made strcpy with smooth leather coating.
- */
-int xs_strcpy(char *dest, const char *src, unsigned int *j)
-{
- unsigned int i;
+ xs_status.s_error = 0;
+ xs_status.s_playing = 0;
+ xs_status.s_songs = 0;
+ xs_status.s_allownext = 1;	// Initialize to TRUE to allow first song
+ xs_status.s_tune = NULL;
+ xs_status.s_fname = NULL;
+	
+ /* Initialize STIL structures */
+// FIXME FIXME FIx ME
 
- if ((dest == NULL) || (src == NULL)) return -1;
-
- for (i = 0; i < strlen(src); i++) {
-	dest[(*j)++] = src[i];
-	}
-
- return 0;
+ /* Create sub-song control window */
+// FIX ME FIXME
 }
 
 
 /*
-	Create the SID-tune description string from the
-	tune's information formatted by the user-specified
-	format-string.
-*/
-static char * xs_make_filedesc(struct sidTuneInfo *s)
+ * Shut down XMMS-SID
+ */
+void xs_close(void)
 {
-	unsigned int i, len, j;
-	char *result;
-
-	/* Check the info strings */
-	if (s->numberOfInfoStrings != 3) {
-		if (s->numberOfInfoStrings < 1) {
-			return 0;
-		}
-		return g_strdup(s->infoString[0]);
-	}
-
-	/* Check the format-string for NULL */
-	if (xs_cfg.fileInfo == NULL) {
-		return g_strdup_printf("%s - %s", s->nameString, s->authorString);
-		}
+ XSDEBUG("shutting down...\n");
 
-	/* Pre-calculate the length of the result-string */
-	len = 2;
-	for (i = 0; i < strlen(xs_cfg.fileInfo); i++) {
-	if (xs_cfg.fileInfo[i] == '%') {
-		switch (xs_cfg.fileInfo[++i]) {
-		case '1': len += strlen(s->authorString); break;
-		case '2': len += strlen(s->nameString); break;
-		case '3': len += strlen(s->copyrightString); break;
-		case '4': len += strlen(s->formatString); break;
-		}
-	} else len++;
-	}
-
-	/* Allocate the result-string */
-	result = (char *) g_malloc(len);
+ /* Stop playing */
+ xmms_sid_ip.stop();
 
-	/* Construct the final result info */
-	j = 0;
-	for (i = 0; i < strlen(xs_cfg.fileInfo); i++) {
+ /* Free allocated memory */
 
-	if (xs_cfg.fileInfo[i] == '%') {
-		switch (xs_cfg.fileInfo[++i]) {
-		case '1': xs_strcpy(result, s->authorString, &j); break;
-		case '2': xs_strcpy(result, s->nameString, &j); break;
-		case '3': xs_strcpy(result, s->copyrightString, &j); break;
-		case '4': xs_strcpy(result, s->formatString, &j); break;
-		}
+ // FIXME FIXME: STIL-entries, songlendb
 
-		} else {
-		result[j++] = xs_cfg.fileInfo[i];
-		} /* if */
-
-	} /* for */
-
-	result[j] = '\0';
-
-	return result;
 }
 
 
 /*
  *	Check whether the given file is handled by this plugin
  */
-int xs_is_our_file(char *filename) 
+gint xs_is_our_file(char *fileName)
 {
-	if (xs_cfg.detectMagic) {
-		sidTune *t = new sidTune(filename);
+ char *pcExt;
+
+ /* Check the filename */
+ if (fileName == NULL)
+	return FALSE;
+
+ /* Try to detect via libSIDPlay's detection routine, if required */
+ if (xs_cfg.detectMagic) {
 
-		if (!t->getStatus()) {
-			delete t;
-			return FALSE;
-			}
+	sidTune *testTune = new sidTune(fileName);
 
-		delete t;
-		return TRUE;
+	if (!testTune) return FALSE;
+	if (!testTune->getStatus())
+		{
+		delete testTune;
+		return FALSE;
+		}
+
+	delete testTune;
+	return TRUE;
 	}
 
-	char *ext = strrchr(filename, '.');
-	if (ext) {
-		ext++;
-		if (!strcasecmp(ext, "psid")) return TRUE;
-		if (!strcasecmp(ext, "sid")) return TRUE;
-		if (!strcasecmp(ext, "dat")) return TRUE;
-		if (!strcasecmp(ext, "inf")) return TRUE;
-		if (!strcasecmp(ext, "info")) return TRUE;
+
+ /* Detect just by checking filename extension */
+ pcExt = strrchr(fileName, '.');
+ if (pcExt)
+	{
+	pcExt++;
+	if (!strcasecmp(pcExt, "psid")) return TRUE;
+	if (!strcasecmp(pcExt, "sid"))	return TRUE;
+	if (!strcasecmp(pcExt, "dat"))	return TRUE;
+	if (!strcasecmp(pcExt, "inf"))	return TRUE;
+	if (!strcasecmp(pcExt, "info"))	return TRUE;
 	}
-	return FALSE;
+
+ return FALSE;
 }
 
 
 /*
  *	Playing thread loop function
  */
-static void * xs_play_loop(void *arg)
+static void *xs_play_loop(void *argPointer)
 {
-	sidTune *tune = (sidTune *)arg;
-	char data[XMMS_SID_BUFSIZE];
-	int fxlen, tn;
-	struct sidTuneInfo sidInf;
-	char *name;
-	enum AFormat fmt = (xs_emuConf.bitsPerSample == 16) ? FMT_S16_NE : FMT_U8;
-	gint chn = xs_emuConf.channels;
+ gchar		plr_data[XMMS_SID_BUFSIZE];
+ struct sidTuneInfo plr_sidInf;
+ gchar		*plr_tune_title = NULL;
+ gint		plr_fxlen;
+ enum AFormat	plr_fmt;
+ gint		plr_tune_num;
+ gint32		plr_tune_len;
+	
+
+ /* Don't allow next song to be set yet */
+ pthread_mutex_lock(&xs_mutex);
+ xs_status.s_allownext = 0;
+ pthread_mutex_unlock(&xs_mutex);
+
+
+ /* Check tune number */
+ plr_tune_num = xs_status.s_playing;
+
+ if (plr_tune_num <= 0)
+	plr_tune_num = 1;
+
+XSDEBUG("xs_play_loop(%d, %d)\n", plr_tune_num, xs_status.s_playing);
+
+ /* Get song information */
+ xs_status.s_tune->getInfo(plr_sidInf);
+ plr_tune_len = xs_get_length(xs_status.s_fname, plr_tune_num);
+ plr_tune_title = xs_get_filetitle(&plr_sidInf, plr_tune_num);
 
-	tune->getInfo(sidInf);
-	name = xs_make_filedesc(&sidInf);
+XSDEBUG("title='%s', len=%d\n", plr_tune_title, plr_tune_len);
+
+
+ /* Initialize audio output */
+ // FIXME FIXME: FMT_S16_XXX -- different architechtures??
+ // the patch may break something ...
+ plr_fmt = (xs_emuConf.bitsPerSample == 16) ? FMT_S16_NE : FMT_U8;
+
 
-play_loop_new_tune:
-	tn = xs_going;
-	if (tn <= 0) tn = 1;
-	if (!xmms_sid_ip.output->open_audio(fmt, xs_emuConf.frequency, chn))
+ if (!xmms_sid_ip.output->open_audio(plr_fmt, xs_emuConf.frequency, xs_emuConf.channels))
 	{
-		xs_error = 1;
-		XSERR("Couldn't open XMMS audio output!\n");
-		delete tune;
-		pthread_exit(NULL);
-		xs_stop();
+	pthread_mutex_lock(&xs_mutex);
+	xs_status.s_error = 1;
+	if (plr_tune_title) g_free(plr_tune_title);
+	if (xs_status.s_tune) delete xs_status.s_tune;
+	xs_status.s_allownext = 1;
+	pthread_mutex_unlock(&xs_mutex);
+	return NULL;
+	}
+
+
+ /* Initialize the SIDPlay-emulator for song */
+ if (!sidEmuInitializeSong(xs_emuEngine, *xs_status.s_tune, plr_tune_num))
+	{
+	XSERR("Couldn't initialize SIDPlay emulator engine! This may be a problem with your sound settings, or possibly a bug in XMMS-SID.\n");
+	pthread_mutex_lock(&xs_mutex);
+	xs_status.s_error = 1;
+	pthread_mutex_unlock(&xs_mutex);
+	goto pl_cleanup;
 	}
 
-	if (!sidEmuInitializeSong(xs_emuEngine, *tune, tn)) {
-		xs_error = 1;
-		XSERR("Couldn't initialize SIDPlay emulator engine!\n");
-		delete tune;
-		pthread_exit(NULL);
-		xs_stop();
-	}
+
+ /* Set song title information */
+ xmms_sid_ip.set_info(
+	plr_tune_title, 
+	(plr_tune_len * 1000),
+	(1000 * (plr_sidInf.songSpeed ? plr_sidInf.songSpeed : (plr_sidInf.clockSpeed == SIDTUNE_CLOCK_NTSC) ? 60 : 50)),
+	xs_emuConf.frequency,
+	xs_emuConf.channels);
+
 
-	tune->getInfo(sidInf);
+ /* Run playing loop: loop as long as xs_playing is same as current tune number */
+ while (xs_status.s_playing == plr_tune_num)
+	{
+	plr_fxlen = XMMS_SID_BUFSIZE;
+
+	/* Run emulator to fill output buffer with audio data */
+	sidEmuFillBuffer(xs_emuEngine, *xs_status.s_tune, plr_data, plr_fxlen);
+
+	/* If Max Playtime option set, check playtime */
+	if (xs_cfg.playUseMaxTime)
+		{
+		if ((xmms_sid_ip.output->output_time() / 1000) >= xs_cfg.playMaxTime)
+			{
+			pthread_mutex_lock(&xs_mutex);
+			xs_status.s_playing = 0;
+			pthread_mutex_unlock(&xs_mutex);
+			}
+		}
 
-	xmms_sid_ip.set_info(name, -1,
-		1000 * (sidInf.songSpeed ? sidInf.songSpeed : (sidInf.clockSpeed == SIDTUNE_CLOCK_NTSC) ? 60 : 50),
-		xs_emuConf.frequency, chn);
+	/* Check playtime against database */
+	if (xs_cfg.playMethod == XMMS_SID_PMETHOD_DATABASE)
+		{
+		if ((xmms_sid_ip.output->output_time() / 1000) >= plr_tune_len)
+			{
+			pthread_mutex_lock(&xs_mutex);
+			xs_status.s_playing = 0;
+			pthread_mutex_unlock(&xs_mutex);
+			}
+
+		}
+#if 0
+		else
 
-	while (xs_going == tn)
-	{
-		fxlen = XMMS_SID_BUFSIZE;
-		sidEmuFillBuffer(xs_emuEngine, *tune, data, fxlen);
+	/* Check for silence */
+	if (xs_cfg.playMethod == XMMS_SID_PMETHOD_MAXSILENCE)
+		{
+		}
+
+	/* Add static noise */
+
+	/* Muffle waveform (low-pass filter) */
 
+#endif
+
+
+		/* Send audio data to visualization plugin */
 		xmms_sid_ip.add_vis_pcm(xmms_sid_ip.output->written_time(),
-					fmt, chn, fxlen, data);
+					plr_fmt, xs_emuConf.channels, plr_fxlen, plr_data);
 
-		while ((xs_going == tn) && (xmms_sid_ip.output->buffer_free() < fxlen))
+		/* Wait for a while */
+		while ((xs_status.s_playing == plr_tune_num) && (xmms_sid_ip.output->buffer_free() < plr_fxlen))
 			xmms_usleep(10000);
 
-		if (xs_going == tn)
-			xmms_sid_ip.output->write_audio(data, fxlen);
-	}
+
+		/* If playing, send final audio data to output plugin */
+		if (xs_status.s_playing == plr_tune_num)
+			xmms_sid_ip.output->write_audio(plr_data, plr_fxlen);
 
-	/* Exit the playing thread */
+	}	/* End of playerloop */
+
+
+pl_cleanup:
+	XSDEBUG("cleaning up...\n");
+
+	/* Cleanup & shutdown */
 	xmms_sid_ip.output->close_audio();
 
-	if (xs_going) goto play_loop_new_tune;
-
-	g_free(name);
+	if (plr_tune_title) g_free(plr_tune_title);
 
-	delete tune;
+	pthread_mutex_lock(&xs_mutex);
+	xs_status.s_playing = 0;
+	if (xs_status.s_tune) delete xs_status.s_tune;
+	xs_status.s_allownext = 1;
+	pthread_mutex_unlock(&xs_mutex);
 
-	pthread_exit(NULL);
+	XSDEBUG("exiting thread, bye.\n");
+	return NULL;
 }
 
 
 /*
  *	Start playing the given file
  */
-void xs_play_file(char *filename)
+void xs_play_file(char *fileName)
 {
-	sidTune *tune = new sidTune(filename);
-	struct sidTuneInfo sidInf;
+ sidTune *newTune;
+ struct sidTuneInfo sidInf;
+
+ XSDEBUG("request to start '%s'\n", fileName);
+
+ /* Wait until the previous song has finished for sure */
+ if (!xs_status.s_allownext)
+	pthread_join(xs_decode_thread, NULL);
 
-	/* Get current configuration */
-	xs_emuEngine.getConfig(xs_emuConf);
+ /* Try to get the tune */
+ newTune = new sidTune(fileName);
+ if (newTune == NULL) return;
+
+ XSDEBUG("tune ok, status %i\n", xs_status.s_playing);
 
-	/* Configure channels and stuff */
-	switch (xs_cfg.channels) {
+ /* Get current configuration */
+ xs_emuEngine.getConfig(xs_emuConf);
+
+
+ /* Configure channels and stuff */
+ switch (xs_cfg.fmtChannels) {
 
 	case XMMS_SID_CHN_AUTOPAN:
 		xs_emuConf.channels = SIDEMU_STEREO;
@@ -288,14 +355,14 @@
 		xs_emuConf.volumeControl = SIDEMU_NONE;
 		break;
 
-	default:xs_error = 1;
-		XSERR("Internal: Invalid channels setting. Please report to author!\n");
-		delete tune;
-		break;
-	}
+	default:
+		XSERR("Internal: Invalid channels setting. Possibly corrupted configuration file.\n");
+		delete newTune;
+		return;
+ }
 
-	/* Memory mode settings */
-	switch (xs_cfg.memoryMode) {
+ /* Memory mode settings */
+ switch (xs_cfg.memoryMode) {
 	case XMMS_SID_MPU_BANK_SWITCHING:
 		xs_emuConf.memoryMode = MPU_BANK_SWITCHING;
 		break;
@@ -308,15 +375,15 @@
 		xs_emuConf.memoryMode = MPU_PLAYSID_ENVIRONMENT;
 		break;
 
-	default:xs_error = 1;
-		XSERR("Internal: Invalid memoryMode setting. Please report to author!\n");
-		delete tune;
-		break;
-	}
+	default:
+		XSERR("Internal: Invalid memoryMode setting. Possibly corrupted configuration file.\n");
+		delete newTune;
+		return;
+ }
 
 
-	/* Clockspeed settings */
-	switch (xs_cfg.clockSpeed) {
+ /* Clockspeed settings */
+ switch (xs_cfg.clockSpeed) {
 	case XMMS_SID_CLOCK_PAL:
 		xs_emuConf.clockSpeed = SIDTUNE_CLOCK_PAL;
 		break;
@@ -325,101 +392,135 @@
 		xs_emuConf.clockSpeed = SIDTUNE_CLOCK_NTSC;
 		break;
 
-	default:xs_error = 1;
-		XSERR("Internal: Invalid clockSpeed setting. Please report to author!\n");
-		delete tune;
-		break;
+	default:
+		XSERR("Internal: Invalid clockSpeed setting. Possibly corrupted configuration file.\n");
+		delete newTune;
+		return;
+ }
+
+
+ /* Configure rest of the emulation */
+ xs_emuConf.bitsPerSample = xs_cfg.fmtBitsPerSample;
+ xs_emuConf.frequency = xs_cfg.fmtFrequency;
+ xs_emuConf.sampleFormat = SIDEMU_SIGNED_PCM;
+ xs_emuConf.mos8580 = xs_cfg.mos8580;
+ xs_emuConf.emulateFilter = xs_cfg.emulateFilter;
+ xs_emuConf.filterFs = xs_cfg.filterFs;
+ xs_emuConf.filterFm = xs_cfg.filterFm;
+ xs_emuConf.filterFt = xs_cfg.filterFt;
+
+ XSDEBUG("configuring engine..\n");
+
+ /* Now set the emulator configuration */
+ xs_emuEngine.setConfig(xs_emuConf);
+ newTune->getInfo(sidInf);
+
+ pthread_mutex_lock(&xs_mutex);
+ xs_status.s_error = 0;
+ xs_status.s_playing = sidInf.startSong;
+ xs_status.s_songs = sidInf.songs;
+ xs_status.s_tune = newTune;
+ pthread_mutex_unlock(&xs_mutex);
+
+ XSDEBUG("starting thread!\n");
+
+ /* Start the playing thread! */
+ if (pthread_create(&xs_decode_thread, NULL, xs_play_loop, NULL) < 0)
+	{
+	XSERR("Couldn't start playing thread! Possible reason reported by system: %s\n", strerror(errno));
+	delete newTune;
 	}
 
-	/* Configure rest of the paske */
-	xs_emuConf.bitsPerSample	= xs_cfg.bitsPerSample;
-	xs_emuConf.frequency		= xs_cfg.frequency;
-	xs_emuConf.sampleFormat		= SIDEMU_SIGNED_PCM;
-	xs_emuConf.mos8580		= xs_cfg.mos8580;
-	xs_emuConf.emulateFilter	= xs_cfg.emulateFilter;
-	xs_emuConf.filterFs		= xs_cfg.filterFs;
-	xs_emuConf.filterFm		= xs_cfg.filterFm;
-	xs_emuConf.filterFt		= xs_cfg.filterFt;
-
-	/* Now set the emulator configuration */
-	xs_emuEngine.setConfig(xs_emuConf);
-	tune->getInfo(sidInf);
-	xs_error = 0;
-	xs_going = sidInf.startSong;
-	xs_songs = sidInf.songs;
-
-	/* Start the playing thread! */
-	if (pthread_create(&xs_decode_thread, NULL, xs_play_loop, tune) < 0) {
-		xs_error = 1;
-		XSERR("Couldn't start playing thread!\n");
-		delete tune;
-	}
+ /* Exit */
 }
 
 
 /*
- *	Stop playing
+ * Stop playing
  */
 void xs_stop(void)
 {
-	if (xs_going)
+ /* If playing, stop. */
+ if (xs_status.s_playing)
 	{
-		xs_going = 0;
-		pthread_join(xs_decode_thread, NULL);
+	pthread_mutex_lock(&xs_mutex);
+	xs_status.s_playing = 0;
+	pthread_mutex_unlock(&xs_mutex);
+
+	pthread_join(xs_decode_thread, NULL);
 	}
 }
 
 
 /*
- *	Pause the playing
+ * Pause the playing
  */
-void xs_pause(short p)
+void xs_pause(short pauseState)
 {
-	xmms_sid_ip.output->pause(p);
+ xmms_sid_ip.output->pause(pauseState);
 }
 
 
 /*
- *	Set the time-seek position
- *	(the playing thread will do the "seeking" aka song-change)
+ * Set the time-seek position
+ * (the playing thread will do the "seeking" aka song-change)
  */
-void xs_seek(int time)
+void xs_seek(int iTime)
 {
-	if ((time > 0) && (time <= xs_songs)) {
-		xs_going = time;
+#ifdef HAVE_SONG_POSITION
+ if ((iTime > 0) && (iTime <= xs_songs))
+	{
+	pthread_mutex_lock(&xs_mutex);
+	xs_status.s_playing = iTime;
+	pthread_mutex_unlock(&xs_mutex);
 	}
+#endif
 }
 
 
 /*
- *	Return the playing "position/time" aka song number
+ * Return the playing "position/time"
  */
 int xs_get_time(void)
 {
-	if (xs_error) return -2;
-	if (!xs_going) return -1;
-#ifdef HAVE_SONG_POSITION
-	set_song_position(xs_going, 1, xs_songs);
-#endif
-	return xmms_sid_ip.output->output_time();
-}
-	
+ if (xs_status.s_error)
+	return -2;
+
+ if (!xs_status.s_playing)
+	return -1;
 
-/*
- *	Return song information
- */
-void xs_get_song_info(char *filename, char **title, int *length)
-{
-	struct sidTuneInfo sidInf;
-	sidTune t(filename);
+#ifdef HAVE_SONG_POSITION
+ set_song_position(xs_status.s_playing, 1, xs_status.s_songs);
+#endif
 
-	if (!t) return;
-
-	t.getInfo(sidInf);
-
-	*title = xs_make_filedesc(&sidInf);
-
-	*length = -1;
+ return xmms_sid_ip.output->output_time();
 }
 
 
+/*
+ * Return song information
+ */
+void xs_get_song_info(char *songFilename, char **songTitle, int *songLength)
+{
+ struct sidTuneInfo sidInf;
+ sidTune *testTune = new sidTune(songFilename);
+
+ /* Check if the tune exists and is readable */
+ if (!testTune) return;
+ if (!testTune->getStatus())
+	{
+	delete testTune;
+	return;
+	}
+
+ /* Get general tune information */
+ testTune->getInfo(sidInf);
+ delete testTune;
+
+ /* Get titlestring */
+ *songTitle = xs_get_filetitle(&sidInf, sidInf.startSong);
+
+ /* Get song length (in seconds), negative if no known length */
+ *songLength = xs_get_length(songFilename, sidInf.startSong);
+}
+