changeset 65:bf7b647b3239

The fabled 0.8-rewrite now works to some extent
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 29 Jun 2003 22:16:04 +0000
parents d3bb914e3af3
children debb9584f638
files src/xmms-sid.cc src/xmms-sid.h src/xs_about.c src/xs_config.c src/xs_config.h src/xs_length.c
diffstat 6 files changed, 295 insertions(+), 142 deletions(-) [+]
line wrap: on
line diff
--- a/src/xmms-sid.cc	Sun Jun 29 01:17:01 2003 +0000
+++ b/src/xmms-sid.cc	Sun Jun 29 22:16:04 2003 +0000
@@ -19,22 +19,25 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
-extern "C" {
 #include <pthread.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <errno.h>
+
+extern "C" {
 #include <xmms/plugin.h>
 #include <xmms/util.h>
 #include <xmms/titlestring.h>
-#include "xmms-sid.h"
 #include "xs_interface.h"
 #include "xs_glade.h"
+}
+
+#include "xmms-sid.h"
 #include "xs_support.h"
 #include "xs_config.h"
 #include "xs_length.h"
-}
+
 
 #ifdef HAVE_SIDPLAY1
 #include <sidplay/player.h>
@@ -51,34 +54,41 @@
  * Global variables
  */
 #ifdef HAVE_SIDPLAY1
-static struct emuConfig		xs_emuConf;
-static emuEngine		xs_emuEngine;
 typedef	sidTune			t_xs_tune;
 typedef struct sidTuneInfo	t_xs_tuneinfo;
 #endif
 
 #ifdef HAVE_SIDPLAY2
-static struct sid2_config_t	xs_emuConf;
-static sidplay2			xs_emuEngine;
 typedef SidTune			t_xs_tune;
 typedef struct SidTuneInfo	t_xs_tuneinfo;
 #endif
 
-static GtkWidget		*xs_ctrlwin	= NULL;
-static pthread_t		xs_decode_thread;
-struct t_xs_cfg			xs_cfg;
+#ifdef HAVE_SIDPLAY1
+	struct emuConfig	xs_emuConf;
+	emuEngine		xs_emuEngine;
+#endif
+#ifdef HAVE_SIDPLAY2
+	struct sid2_config_t	xs_emuConf;
+	sidplay2		xs_emuEngine;
+#endif
 
-struct {
+typedef struct {
 	gboolean	isError, isPlaying, allowNext;
 	gint		currSong, nSongs;
 	t_xs_tune	*currTune;
-	gchar		*currFilename;
-} xs_status;
+	gchar		*currFileName;
+} t_xs_status;
 
-pthread_mutex_t			xs_mutex = PTHREAD_MUTEX_INITIALIZER;
+static GtkWidget		*xs_ctrlwin	= NULL;
+static pthread_t		xs_decode_thread;
+static pthread_mutex_t		xs_mutex = PTHREAD_MUTEX_INITIALIZER;
+struct t_xs_cfg			xs_cfg;
+t_xs_status			xs_status;
+
 
 gchar *xs_filetitle_get(gchar *, t_xs_tuneinfo *, gint);
 
+
 /*
  * Create sub-song control window
  */
@@ -110,27 +120,20 @@
  xs_read_configuration();
 
  /* Initialize status */
- xs_status.isError	= FALSE;
- xs_status.isPlaying	= FALSE;
- xs_status.nSongs	= 0;
- xs_status.currSong	= 0;
- xs_status.allowNext	= TRUE;	// Initialize to TRUE to allow first song
- xs_status.currTune	= NULL;
- xs_status.currFilename	= NULL;
+ memset(&xs_status, 0, sizeof(xs_status));
+ xs_status.allowNext = TRUE;	// Initialize to TRUE to allow first song
 
+ /* Try to initialize emulator engine(s) */
+ XSDEBUG("initializing emulator engine(s)...\n");
 
- /* Try to initialize libSIDPlay(s) */
 #ifdef HAVE_SIDPLAY1
  if (!xs_emuEngine || !xs_emuEngine.verifyEndianess())
 	{
-	XSERR("Couldn't start SIDPlay1 emulator engine!\n");
+	XSERR("Couldn't initialize SIDPlay1 emulator engine!\n");
 	return;
 	}
 #endif
 
-#ifdef HAVE_SIDPLAY2
-#endif
-
  /* Read song-length database */
  if (xs_cfg.songlenDBEnable)
  if (xs_songlen_init() < 0)
@@ -144,6 +147,7 @@
 
 // FIXME FIXME FIx ME
 
+ XSDEBUG("xs_init() done\n");
 }
 
 
@@ -152,10 +156,10 @@
  */
 void xs_close(void)
 {
- XSDEBUG("shutting down...\n");
+ XSDEBUG("xs_close(): shutting down...\n");
 
  /* Stop playing */
- xs_plugin_ip.stop();
+ xs_stop();
 
  /* Shutdown libSIDPlay(s) */
 #ifdef HAVE_SIDPLAY1
@@ -170,42 +174,44 @@
  xs_songlen_close();
 
 // FIXME FIXME: STIL-entries
+ XSDEBUG("shutdown finished.\n");
 }
 
 
 /*
  * Check whether the given file is handled by this plugin
  */
-gint xs_is_our_file(char *fileName)
+gint xs_is_our_file(gchar *pcFileName)
 {
  char *pcExt;
+ t_xs_tune *testTune;
 
  /* Check the filename */
- if (fileName == NULL)
+ if (pcFileName == NULL)
 	return FALSE;
 
+ XSDEBUG("testFile('%s')\n", pcFileName);
+
  /* Try to detect via libSIDPlay's detection routine, if required */
  if (xs_cfg.detectMagic)
 	{
-#ifdef HAVE_SIDPLAY1
-	t_xs_tune *testTune = new sidTune(fileName);
-	if (!testTune) return FALSE;
-	if (!testTune->getStatus())
+	testTune = new t_xs_tune(pcFileName);
+	if (testTune == NULL) return FALSE;
+	if (testTune->getStatus())
 		{
 		delete testTune;
-		return FALSE;
+		XSDEBUG("file = OK\n");
+		return TRUE;
 		}
 
+	/* We DON'T fall back to filename extension checking ... */
 	delete testTune;
-	return TRUE;
-#endif
-
-#ifdef HAVE_SIDPLAY2
-#endif
+	XSDEBUG("file = kyrpe\n");
+	return FALSE;
 	}
 
  /* Detect just by checking filename extension */
- pcExt = xs_strrchr(fileName, '.');
+ pcExt = xs_strrchr(pcFileName, '.');
  if (pcExt)
 	{
 	pcExt++;
@@ -216,6 +222,7 @@
 	if (!g_strcasecmp(pcExt, "info")) return TRUE;
 	}
 
+ XSDEBUG("file was KYRPE\n");
  return FALSE;
 }
 
@@ -223,49 +230,195 @@
 /*
  * Main playing thread loop
  */
-static void *xs_play_loop(void *argPointer)
+void *xs_play_loop(void *argPointer)
 {
+ t_xs_status myStatus;
+ t_xs_tuneinfo tuneInfo;
+ gboolean audioOpen;
+ gint audioFreq, audioChannels, songLength;
+ enum AFormat audioFmt;
+ gchar audioBuffer[XS_BUFSIZE];
+
+ /* Check status */
+ XSDEBUG("entering play thread\n");
+ pthread_mutex_lock(&xs_mutex);
+ if (!xs_status.allowNext)
+	{
+	pthread_mutex_unlock(&xs_mutex);
+	pthread_exit(NULL);
+	}
+
  /* Don't allow next song to be set yet */
+ xs_status.allowNext = FALSE;
+ xs_status.isPlaying = TRUE;
+ memcpy(&myStatus, &xs_status, sizeof(t_xs_status));
+ pthread_mutex_unlock(&xs_mutex);
+
+ /* Copy and check audio options here (they might change in config while running) */
+#ifdef HAVE_UNSIGNEDPCM
+ audioFmt = (xs_cfg.fmtBitsPerSample == XS_RES_16BIT) ? FMT_U16_NE : FMT_U8;
+#else
+ audioFmt = (xs_cfg.fmtBitsPerSample == XS_RES_16BIT) ? FMT_S16_NE : FMT_S8;
+#endif
+ audioFreq = xs_cfg.fmtFrequency;
+ audioChannels = (xs_cfg.fmtChannels == XS_CHN_MONO) ? 1 : 2;
+ audioOpen = FALSE;
+
+ /*
+  * Main player loop: while not stopped, loop here - play subtunes
+  */
+ while (xs_status.isPlaying)
+ {
  pthread_mutex_lock(&xs_mutex);
- xs_status.allowNext = FALSE;
+ myStatus.currSong = xs_status.currSong;
  pthread_mutex_unlock(&xs_mutex);
 
+ XSDEBUG("sub-song %i selected, initializing...\n", myStatus.currSong);
+
+ /* Get song length for current subtune */
+ songLength = xs_songlen_get(myStatus.currFileName, myStatus.currSong);
+
+ /* Initialize song */
+#ifdef HAVE_SIDPLAY1
+ if ((myStatus.currTune == NULL) || !myStatus.currTune->getStatus() ||
+	!sidEmuInitializeSong(xs_emuEngine, *myStatus.currTune, myStatus.currSong))
+#endif
+#ifdef HAVE_SIDPLAY2
+ if ()
+#endif
+	{
+	XSERR("Couldn't initialize SID-tune!\n");
+	pthread_mutex_lock(&xs_mutex);
+	xs_status.isError = TRUE;
+	pthread_mutex_unlock(&xs_mutex);
+	goto err_exit;
+	}
+
+ myStatus.currTune->getInfo(tuneInfo);
+
+ /* Open the audio output */
+ if (!xs_plugin_ip.output->open_audio(audioFmt, audioFreq, audioChannels))
+	{
+	XSERR("Couldn't open XMMS audio output!\n");
+	pthread_mutex_lock(&xs_mutex);
+	xs_status.isError = TRUE;
+	pthread_mutex_unlock(&xs_mutex);
+	goto err_exit;
+	}
+
+ audioOpen = TRUE;
+
+ /* Set some infoz */
+ xs_plugin_ip.set_info(tuneInfo.infoString[0], (songLength > 0) ? songLength * 1000 : -1,
+ 1000 * (tuneInfo.songSpeed ? tuneInfo.songSpeed : (tuneInfo.clockSpeed == SIDTUNE_CLOCK_NTSC) ? 60 : 50),
+ audioFreq, audioChannels);
+
+ XSDEBUG("rendering audio...\n");
+
+ /* Play the tune */
+ while (xs_status.isPlaying && (xs_status.currSong == myStatus.currSong))
+	{
+#ifdef HAVE_SIDPLAY1
+	sidEmuFillBuffer(xs_emuEngine, *myStatus.currTune, audioBuffer, XS_BUFSIZE);
+#endif
+
+#ifdef HAVE_SIDPLAY2
+#endif
+
+	/* Visualice/haujobb */
+	xs_plugin_ip.add_vis_pcm(
+		xs_plugin_ip.output->written_time(),
+		audioFmt, audioChannels, XS_BUFSIZE, audioBuffer);
+
+	/* Wait a little */
+	while (xs_status.isPlaying &&
+		(xs_status.currSong == myStatus.currSong) &&
+		(xs_plugin_ip.output->buffer_free() < XS_BUFSIZE))
+		xmms_usleep(10000);
+
+	/* Output audio */
+	if (xs_status.isPlaying && (xs_status.currSong == myStatus.currSong))
+		xs_plugin_ip.output->write_audio(audioBuffer, XS_BUFSIZE);
+
+	/* Check if we have played enough */
+	if (xs_cfg.playMaxTimeEnable)
+		{
+		if (xs_cfg.playMaxTimeUnknown)
+			{
+			if ((songLength == -1) &&
+				(xs_plugin_ip.output->output_time() >= (xs_cfg.playMaxTime * 1000)))
+				xs_status.isPlaying = FALSE;
+			} else {
+			if (xs_plugin_ip.output->output_time() >= (xs_cfg.playMaxTime * 1000))
+				xs_status.isPlaying = FALSE;
+			}
+		}
+
+	if (songLength > 0)
+		{
+		if (xs_plugin_ip.output->output_time() >= (songLength * 1000))
+			xs_status.isPlaying = FALSE;
+		}
+	}
+
+ XSDEBUG("tune ended/stopped\n");
+
+ /* Close audio */
+ if (audioOpen)
+	{
+	XSDEBUG("close audio #1\n");
+	xs_plugin_ip.output->close_audio();
+	audioOpen = FALSE;
+	}
+ }
+
+ /* When exiting, delete data */
+err_exit:
+ pthread_mutex_lock(&xs_mutex);
+ xs_status.isPlaying = FALSE;
+ pthread_mutex_unlock(&xs_mutex);
+
+ if (audioOpen)
+	{
+	XSDEBUG("close audio #2\n");
+	xs_plugin_ip.output->close_audio();
+	}
+
+ if (myStatus.currTune != NULL)
+	{
+	delete myStatus.currTune;
+	myStatus.currTune = NULL;
+	}
+
+ g_free(myStatus.currFileName);
 
  /* Exit the playing thread */
  XSDEBUG("exiting thread, bye.\n");
- return NULL;
+ pthread_mutex_lock(&xs_mutex);
+ xs_status.allowNext = TRUE;
+ pthread_mutex_unlock(&xs_mutex);
+
+ pthread_exit(NULL);
 }
 
 
 /*
  * Start playing the given file
  */
-void xs_play_file(char *fileName)
+void xs_play_file(char *pcFileName)
 {
  t_xs_tune *newTune;
- t_xs_tuneinfo sidInf;
-
- XSDEBUG("request to load '%s'\n", fileName);
-
+ t_xs_tuneinfo tuneInfo;
 
- /* Initialize audio output */
- XSDEBUG("opening audio output plugin...\n");
- if (!xs_plugin_ip.output->open_audio(
-	((xs_cfg.fmtBitsPerSample == 16) ? FMT_S16_NE : FMT_U8), xs_cfg.fmtFrequency,
-	((xs_cfg.fmtChannels == XS_CHN_MONO) ? 1 : 2)))
-	{
-	XSERR("Couldn't open audio output plugin!\n");
-	delete newTune;
-	return;
-	}
-
+ /* Can we set the next tune? */ 
+ XSDEBUG("request to play '%s'\n", pcFileName);
 
  /* Try to get the tune */
- newTune = new t_xs_tune(fileName);
+ XSDEBUG("initializing tune from file\n");
+ newTune = new t_xs_tune(pcFileName);
  if (newTune == NULL) return;
 
- XSDEBUG("tune ok, configuring SIDPlay engine\n");
-
+ XSDEBUG("status: allowNext=%i, isPlaying=%i\n", xs_status.allowNext, xs_status.isPlaying);
 
 #ifdef HAVE_SIDPLAY1
  /* Get current configuration */
@@ -287,15 +440,11 @@
 		break;
 
 	case XS_CHN_MONO:
+	default:
 		xs_emuConf.channels = SIDEMU_MONO;
 		xs_emuConf.autoPanning = SIDEMU_NONE;
 		xs_emuConf.volumeControl = SIDEMU_NONE;
 		break;
-
-	default:
-		XSERR("Internal: Invalid channels setting. Possibly corrupted configuration file.\n");
-		delete newTune;
-		return;
  }
 
 
@@ -314,26 +463,21 @@
 		break;
 
 	default:
-		XSERR("Internal: Invalid memoryMode setting. Possibly corrupted configuration file.\n");
-		delete newTune;
-		return;
+		xs_emuConf.memoryMode = MPU_BANK_SWITCHING;
+		break;
  }
 
 
  /* Clockspeed settings */
  switch (xs_cfg.clockSpeed) {
-	case XS_CLOCK_PAL:
-		xs_emuConf.clockSpeed = SIDTUNE_CLOCK_PAL;
-		break;
-
 	case XS_CLOCK_NTSC:
 		xs_emuConf.clockSpeed = SIDTUNE_CLOCK_NTSC;
 		break;
 
+	case XS_CLOCK_PAL:
 	default:
-		XSERR("Internal: Invalid clockSpeed setting. Possibly corrupted configuration file.\n");
-		delete newTune;
-		return;
+		xs_emuConf.clockSpeed = SIDTUNE_CLOCK_PAL;
+		break;
  }
 
 
@@ -356,7 +500,6 @@
 #endif
 
 
-
 #ifdef HAVE_SIDPLAY2
  /* Get current configuration */
  xs_emuConf = xs_emuEngine.config();
@@ -373,13 +516,9 @@
 		break;
 
 	case XS_CHN_MONO:
+	default:
 		xs_emuConf.playback = sid2_mono;
 		break;
-
-	default:
-		XSERR("Internal: Invalid channels setting. Possibly corrupted configuration file.\n");
-		delete newTune;
-		return;
  }
 
 
@@ -398,30 +537,22 @@
 		break;
 
 	case XS_MPU_REAL:
+	default:
 		xs_emuConf.environment = sid2_envR;
 		break;
-
-	default:
-		XSERR("Internal: Invalid memoryMode setting. Possibly corrupted configuration file.\n");
-		delete newTune;
-		return;
  }
 
 
  /* Clockspeed settings */
  switch (xs_cfg.clockSpeed) {
-	case XS_CLOCK_PAL:
-		xs_emuConf.clockSpeed = xs_emuConf.clockDefault = SID2_CLOCK_PAL;
-		break;
-
 	case XS_CLOCK_NTSC:
 		xs_emuConf.clockSpeed = xs_emuConf.clockDefault = SID2_CLOCK_NTSC;
 		break;
 
+	case XS_CLOCK_PAL:
 	default:
-		XSERR("Internal: Invalid clockSpeed setting. Possibly corrupted configuration file.\n");
-		delete newTune;
-		return;
+		xs_emuConf.clockSpeed = xs_emuConf.clockDefault = SID2_CLOCK_PAL;
+		break;
  }
 
 
@@ -453,17 +584,16 @@
 
 
  /* Initialize status information */
- XSDEBUG("initializing and starting playing thread!\n");
+ XSDEBUG("starting playing thread!\n");
 
- newTune->getInfo(sidInf);
+ newTune->getInfo(tuneInfo);
 
- xs_status.isError	= FALSE;
  xs_status.isPlaying	= TRUE;
- xs_status.allowNext	= TRUE;
- xs_status.currSong	= sidInf.startSong;
- xs_status.nSongs	= sidInf.songs;
+ xs_status.isError	= FALSE;
+ xs_status.currSong	= tuneInfo.startSong;
+ xs_status.nSongs	= tuneInfo.songs;
  xs_status.currTune	= newTune;
-
+ xs_status.currFileName = g_strdup(pcFileName);
 
  /* Start the playing thread! */
  if (pthread_create(&xs_decode_thread, NULL, xs_play_loop, NULL) < 0)
@@ -472,6 +602,8 @@
 	delete newTune;
 	}
 
+ XSDEBUG("systems should be up?\n");
+
  /* Exit */
 }
 
@@ -482,18 +614,14 @@
 void xs_stop(void)
 {
  /* If playing, stop. */
- XSDEBUG("request to stop.\n");
-
- if (xs_status.isPlaying)
+ XSDEBUG("STOP_REQ\n");
+ if (xs_status.isPlaying || !xs_status.allowNext)
 	{
 	XSDEBUG("stopping...\n");
 	pthread_mutex_lock(&xs_mutex);
-	xs_status.isPlaying = 0;
+	xs_status.isPlaying = FALSE;
 	pthread_mutex_unlock(&xs_mutex);
-
 	pthread_join(xs_decode_thread, NULL);
-
-	xs_plugin_ip.output->close_audio();
 	}
 }
 
@@ -511,7 +639,7 @@
  * Set the time-seek position
  * (the playing thread will do the "seeking" aka song-change)
  */
-void xs_seek(int iTime)
+void xs_seek(gint iTime)
 {
 #ifdef HAVE_SONG_POSITION
  pthread_mutex_lock(&xs_mutex);
@@ -529,21 +657,22 @@
 /*
  * Return the playing "position/time"
  */
-int xs_get_time(void)
+gint xs_get_time(void)
 {
- pthread_mutex_lock(&xs_mutex);
+ XSDEBUG("kyrve? %i : %i\n", xs_status.isError, xs_status.isPlaying);
  if (xs_status.isError)
 	return -2;
 
  if (!xs_status.isPlaying)
 	return -1;
 
+
 #ifdef HAVE_SONG_POSITION
+ pthread_mutex_lock(&xs_mutex);
  set_song_position(xs_status.currSong, 1, xs_status.nSongs);
+ pthread_mutex_unlock(&xs_mutex);
 #endif
 
- pthread_mutex_unlock(&xs_mutex);
-
  return xs_plugin_ip.output->output_time();
 }
 
@@ -551,14 +680,15 @@
 /*
  * Return song information
  */
-void xs_get_song_info(char *songFilename, char **songTitle, int *songLength)
+void xs_get_song_info(gchar *songFileName, gchar **songTitle, gint *songLength)
 {
- t_xs_tuneinfo sidInf;
- t_xs_tune *testTune = new t_xs_tune(songFilename);
+ t_xs_tuneinfo tuneInfo;
+ t_xs_tune *testTune;
  gint tmpInt;
 
  /* Check if the tune exists and is readable */
- if (!testTune) return;
+ testTune = new t_xs_tune(songFileName);
+ if (testTune == NULL) return;
  if (!testTune->getStatus())
 	{
 	delete testTune;
@@ -566,14 +696,14 @@
 	}
 
  /* Get general tune information */
- testTune->getInfo(sidInf);
+ testTune->getInfo(tuneInfo);
  delete testTune;
 
  /* Get titlestring */
- *songTitle = xs_filetitle_get(songFilename, &sidInf, sidInf.startSong);
+ *songTitle = xs_filetitle_get(songFileName, &tuneInfo, tuneInfo.startSong);
 
  /* Get song length (in milliseconds), negative if no known length */
- tmpInt = xs_songlen_get(songFilename, sidInf.startSong);
+ tmpInt = xs_songlen_get(songFileName, tuneInfo.startSong);
  if (tmpInt >= 0)
 	*songLength = (tmpInt * 1000);
 	else
@@ -585,7 +715,7 @@
  * Create the SID-tune description string from the tune's information
  * formatted by the user-specified format-string.
  */
-gchar *xs_filetitle_get(gchar *pcFilename, t_xs_tuneinfo *pfInfo, gint iSubTune)
+gchar *xs_filetitle_get(gchar *pcFileName, t_xs_tuneinfo *pfInfo, gint iSubTune)
 {
  gint j, iLength;
  gchar *pcStr, *pcResult;
@@ -594,6 +724,7 @@
 #endif
 
  // FIXME FIXME: get STIL-info
+ 
 	
  /* Check the info strings */
  if (pfInfo->numberOfInfoStrings < 3)
@@ -659,6 +790,8 @@
 		}
 		} else
 		iLength++;
+
+	pcStr++;
 	}
 
 	/* Allocate memory */
@@ -682,6 +815,8 @@
 		}
 		} else
 		pcResult[j++] = *pcStr;
+
+	pcStr++;
 	}
 
 	pcResult[j] = 0;
--- a/src/xmms-sid.h	Sun Jun 29 01:17:01 2003 +0000
+++ b/src/xmms-sid.h	Sun Jun 29 22:16:04 2003 +0000
@@ -56,14 +56,14 @@
  */
 void	xs_init(void);
 void	xs_close(void);
-int	xs_is_our_file(char *);
-void	xs_play_file(char *);
+gint	xs_is_our_file(gchar *);
+void	xs_play_file(gchar *);
 void	xs_stop(void);
 void	xs_pause(short);
-void	xs_seek(int);
-int	xs_get_time(void);
-void	xs_get_song_info(char *, char **, int *);
-// void	xs_file_info_box(char *);
+void	xs_seek(gint);
+gint	xs_get_time(void);
+void	xs_get_song_info(gchar *, gchar **, gint *);
+//void	xs_file_info_box(gchar *);
 void	xs_about(void);
 
 
--- a/src/xs_about.c	Sun Jun 29 01:17:01 2003 +0000
+++ b/src/xs_about.c	Sun Jun 29 22:16:04 2003 +0000
@@ -133,7 +133,7 @@
 	"\n"
 	"Original XMMS-SID created by\n"
 	"\tWillem Monsuwe\n"
-	"\n"
+	"\n", -1);
 #if 0
 	"\"XMMS-SID Theme\"-song (SIDtune)\n"
 	"\tPeter 'Brite-Lite' Halin of Dekadence\n"
@@ -141,12 +141,15 @@
 	"\thttp://www.dekadence64.org/\n"
 	"\n"
 #endif
+
+ gtk_text_insert (GTK_TEXT (about_text), NULL, NULL, NULL,
 	"Thanks and greetings ...\n"
 	"\tEveryone at #Linux.Fi, #Fireball,\n"
 	"\t#TNSP and #c-64 of IRCNet...\n"
 	"\n"
 	"\tPwP, iSO, Byterapers, Fairlight,\n"
 	"\tmfx, Unique, Static, Dekadence,\n"
+	"\tWrath Designs, Padua, Extend,\n"
 	"\tPHn, Creators, Cosine, tAAt ...\n"
 	"\n"
 	"Special thanks\n"
--- a/src/xs_config.c	Sun Jun 29 01:17:01 2003 +0000
+++ b/src/xs_config.c	Sun Jun 29 22:16:04 2003 +0000
@@ -58,6 +58,8 @@
 
 	{CTYPE_BOOL,	&xs_cfg.playMaxTimeEnable,	"playMaxTimeEnable"},
 	{CTYPE_INT,	&xs_cfg.playMaxTime,		"playMaxTime"},
+	{CTYPE_BOOL,	&xs_cfg.playMaxTimeUnknown,	"playMaxTimeUnknown"},
+
 	{CTYPE_BOOL,	&xs_cfg.songlenDBEnable,	"songlenDBEnable"},
 	{CTYPE_STR,	&xs_cfg.songlenDBPath,		"songlenDBPath"},
 
@@ -102,8 +104,9 @@
 
 { WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_emu_sidplay2_opt",	&xs_cfg.optimiseLevel,		0 },
 
-{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_sld_usemaxtime",	&xs_cfg.playMaxTimeEnable,	0 },
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_sld_maxtime_enable",&xs_cfg.playMaxTimeEnable,	0 },
 { WTYPE_SPIN,	CTYPE_INT,	"cfg_sld_maxtime",	&xs_cfg.playMaxTime,		0 },
+{ WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_sld_onlyunknown",	&xs_cfg.playMaxTimeUnknown,	0 },
 { WTYPE_BUTTON,	CTYPE_BOOL,	"cfg_sld_enable",	&xs_cfg.songlenDBEnable,	0 },
 { WTYPE_TEXT,	CTYPE_STR,	"cfg_sld_dbpath",	&xs_cfg.songlenDBPath,		0 },
 
--- a/src/xs_config.h	Sun Jun 29 01:17:01 2003 +0000
+++ b/src/xs_config.h	Sun Jun 29 22:16:04 2003 +0000
@@ -65,6 +65,7 @@
 	/* Playing settings */
 	gboolean	playMaxTimeEnable;
 	gint		playMaxTime;		/* MAX playtime in seconds */
+	gboolean	playMaxTimeUnknown;	/* Use max-time only when song-length is unknown */
 	gboolean	songlenDBEnable;
 	gchar		*songlenDBPath;		/* Path to Songlengths.txt */
 
--- a/src/xs_length.c	Sun Jun 29 01:17:01 2003 +0000
+++ b/src/xs_length.c	Sun Jun 29 22:16:04 2003 +0000
@@ -97,7 +97,8 @@
  */
 t_xs_sldb_node * xs_db_get(t_xs_md5hash pHash)
 {
- gint iStartNode, iEndNode, iQNode, iFound, r, i;
+ gint iStartNode, iEndNode, iQNode, r, i;
+ gboolean iFound;
  t_xs_sldb_node *pResult;
 
  /* Check the database pointers */
@@ -109,7 +110,7 @@
  iStartNode = 0;
  iEndNode = (xs_dbnodes - 1);
  iQNode = (iEndNode / 2);
- iFound = 0;
+ iFound = FALSE;
 
  while ((!iFound) && ((iEndNode - iStartNode) > 128))
  	{
@@ -126,19 +127,19 @@
  		iStartNode = iQNode;
  		iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
  		} else
- 		iFound = 1;
+ 		iFound = TRUE;
  	}
 
  /* If not found already */
  if (!iFound)
  	{
 	/* Search the are linearly */
-	iFound = 0;
+	iFound = FALSE;
 	i = iStartNode;
 	while ((i <= iEndNode) && (!iFound))
 		{
 		if (xs_db_cmphash(pHash, xs_dbindex[i]->md5Hash) == 0)
-			iFound = 1;
+			iFound = TRUE;
 			else
 			i++;
 		}
@@ -149,7 +150,7 @@
 
  	} else {
 	/* Found via binary search */
- 	pResult = xs_dbindex[iEndNode];
+ 	pResult = xs_dbindex[iQNode];
 	}
 
 
@@ -321,6 +322,8 @@
 {
  t_xs_sldb_node *pCurr;
  gint i;
+
+XSDEBUG("sldb_init()\n");
  
  /* Read the database */
  if (xs_cfg.songlenDBPath == NULL)
@@ -329,6 +332,8 @@
  if (xs_db_read(xs_cfg.songlenDBPath) < 0)
  	return -9;
 
+XSDEBUG("indexing...\n");
+
  /* Get size of db */
  pCurr = xs_database;
  xs_dbnodes = 0;
@@ -359,6 +364,7 @@
 	}
 
  /* OK */
+XSDEBUG("init ok.\n");
  return 0;
 }
 
@@ -371,6 +377,7 @@
  t_xs_sldb_node *pCurr, *pNext;
  
  /* Free the memory allocated for database */
+XSDEBUG("sldb_close()\n");
  pCurr = xs_database;
  while (pCurr)
  	{
@@ -563,14 +570,18 @@
 		{
 		dbNode = xs_db_get(dbHash);
 
-		if (dbNode && (subTune >= 0) && (subTune < dbNode->nLengths))
+		if (dbNode && (subTune >= 1) && (subTune <= dbNode->nLengths))
+			{
+			/* Get the length */
 			iResult = dbNode->sLengths[subTune - 1];
+
+			/* Take off few last seconds */
+			if (iResult > 2)
+				iResult -= 2;
+			}
   		}
 	}
-#if 0
- XSDEBUG("fname='%s', sub=%i, res=%i\n", fileName, subTune, iResult);
-#endif
-  
+
  return iResult;
 }