changeset 230:608f31f6c095

Raw cleanup.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 21 Dec 2004 09:25:03 +0000
parents 7bb9e20e3092
children 9d7274a11fb1
files src/xmms-sid.c src/xmms-sid.h src/xs_config.c src/xs_fileinfo.c src/xs_init.c src/xs_length.c src/xs_length.h src/xs_sidplay.h src/xs_sidplay1.cc src/xs_sidplay1.h src/xs_sidplay2.cc src/xs_sidplay2.h src/xs_stil.c src/xs_stil.h src/xs_support.c src/xs_title.c src/xs_title.h
diffstat 17 files changed, 634 insertions(+), 385 deletions(-) [+]
line wrap: on
line diff
--- a/src/xmms-sid.c	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xmms-sid.c	Tue Dec 21 09:25:03 2004 +0000
@@ -62,22 +62,6 @@
 
 
 /*
- * Structure defining methods/functions of each player
- */
-typedef struct {
-	gint		plrIdent;
-	gboolean	(*plrIsOurFile)(gchar *);
-	gboolean	(*plrInit)(t_xs_status *);
-	void		(*plrClose)(t_xs_status *);
-	gboolean	(*plrInitSong)(t_xs_status *);
-	guint		(*plrFillBuffer)(t_xs_status *, gchar *, guint);
-	gboolean	(*plrLoadSID)(t_xs_status *, gchar *);
-	void		(*plrDeleteSID)(t_xs_status *);
-	t_xs_tune*	(*plrGetSIDInfo)(gchar *);
-} t_xs_player;
-
-
-/*
  * List of players and links to their functions
  */
 t_xs_player xs_playerlist[] = {
@@ -107,23 +91,20 @@
 /*
  * Global variables
  */
-struct t_xs_cfg			xs_cfg;
-t_xs_status			xs_status;
-t_xs_player			*xs_player	= NULL;
-static pthread_t		xs_decode_thread;
-static pthread_mutex_t		xs_mutex	= PTHREAD_MUTEX_INITIALIZER;
-static GtkWidget		*xs_subctrl	= NULL;
-static GtkObject		*xs_subctrl_adj = NULL;
-static t_xs_tune		*xs_fileinfotune = NULL;
-static t_xs_stil_node		*xs_fileinfostil = NULL;
+t_xs_status		xs_status;
+XS_MUTEX(xs_status);
+static pthread_t	xs_decode_thread;
 
+static GtkWidget	*xs_subctrl	= NULL;
+static GtkObject	*xs_subctrl_adj = NULL;
+XS_MUTEX(xs_subctrl);
 
 void	xs_subctrl_close(void);
 void	xs_subctrl_update(void);
 
 
 /*
- * Re-initialize some settings
+ * Initialization functions
  */
 void xs_reinit(void)
 {
@@ -153,7 +134,7 @@
  		if (xs_playerlist[iPlayer].plrInit(&xs_status))
  			{
  			isInitialized = TRUE;
- 			xs_player = (t_xs_player *) &xs_playerlist[iPlayer];
+ 			xs_status.sidPlayer = (t_xs_player *) &xs_playerlist[iPlayer];
  			}
  		}
 	iPlayer++;
@@ -167,7 +148,7 @@
 	if (xs_playerlist[iPlayer].plrInit(&xs_status))
 		{
 		isInitialized = TRUE;
-		xs_player = (t_xs_player *) &xs_playerlist[iPlayer];
+		xs_status.sidPlayer = (t_xs_player *) &xs_playerlist[iPlayer];
  		} else
  		iPlayer++;
  	}
@@ -176,14 +157,14 @@
 
  /* Initialize song-length database */
  xs_songlen_close();
- if (xs_cfg.songlenDBEnable && (xs_songlen_init() < 0))
+ if (xs_cfg.songlenDBEnable && (xs_songlen_init() != 0))
  	{
 	XSERR("Error initializing song-length database!\n");
 	}
 	
  /* Initialize STIL database */
  xs_stil_close();
- if (xs_cfg.stilDBEnable && (xs_stil_init() < 0))
+ if (xs_cfg.stilDBEnable && (xs_stil_init() != 0))
  	{
  	XSERR("Error initializing STIL database!\n");
  	}
@@ -218,11 +199,11 @@
  /* Stop playing, free structures */
  xs_stop();
 
- xs_tune_free(xs_status.pTune);
- xs_status.pTune = NULL;
+ xs_tuneinfo_free(xs_status.tuneInfo);
+ xs_status.tuneInfo = NULL;
  
- xs_player->plrDeleteSID(&xs_status);
- xs_player->plrClose(&xs_status);
+ xs_status.sidPlayer->plrDeleteSID(&xs_status);
+ xs_status.sidPlayer->plrClose(&xs_status);
 
  xs_songlen_close();
  xs_stil_close();
@@ -237,14 +218,14 @@
 gint xs_is_our_file(gchar *pcFilename)
 {
  gchar *pcExt;
- assert(xs_player);
+ assert(xs_status.sidPlayer);
 
  /* Check the filename */
  if (pcFilename == NULL)
 	return FALSE;
 
  /* Try to detect via detection routine, if required */
- if (xs_cfg.detectMagic && xs_player->plrIsOurFile(pcFilename))
+ if (xs_cfg.detectMagic && xs_status.sidPlayer->plrIsOurFile(pcFilename))
  	return TRUE;
 
  /* Detect just by checking filename extension */
@@ -274,18 +255,18 @@
 void *xs_play_loop(void *argPointer)
 {
  t_xs_status myStatus;
- t_xs_tune *myTune;
+ t_xs_tuneinfo *myTune;
  gboolean audioOpen = FALSE, doPlay = FALSE;
  guint audioGot;
  gint songLength;
  gchar audioBuffer[XS_BUFSIZE];
 
  /* Initialize */
- pthread_mutex_lock(&xs_mutex);
- XSDEBUG("entering play thread\n");
+ XSDEBUG("entering player thread\n");
+ XS_MUTEX_LOCK(xs_status);
  memcpy(&myStatus, &xs_status, sizeof(t_xs_status));
- myTune = xs_status.pTune;
- pthread_mutex_unlock(&xs_mutex);
+ myTune = xs_status.tuneInfo;
+ XS_MUTEX_UNLOCK(xs_status);
 
 
  /*
@@ -294,27 +275,31 @@
  doPlay = TRUE;
  while (xs_status.isPlaying && doPlay)
  {
- pthread_mutex_lock(&xs_mutex);
+ XS_MUTEX_LOCK(xs_status);
  myStatus.currSong = xs_status.currSong;
- pthread_mutex_unlock(&xs_mutex);
+ XS_MUTEX_UNLOCK(xs_status);
+ XS_MUTEX_LOCK(xs_subctrl);
  xs_subctrl_update();
+ XS_MUTEX_UNLOCK(xs_subctrl);
 
  XSDEBUG("subtune #%i selected, initializing...\n", myStatus.currSong);
 
  songLength = myTune->subTunes[myStatus.currSong - 1].tuneLength;
  
  /* Check minimum playtime */
+ XS_MUTEX_LOCK(xs_cfg);
  if (xs_cfg.playMinTimeEnable)
  	{
 	if (songLength < xs_cfg.playMinTime)
 		songLength = xs_cfg.playMinTime;
 	}
+ XS_MUTEX_UNLOCK(xs_cfg);
 
  /* Initialize song */
- if (!xs_player->plrInitSong(&myStatus))
+ if (!myStatus.sidPlayer->plrInitSong(&myStatus))
 	{
 	XSERR("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n",
-		myTune->tuneFilename, myStatus.currSong);
+		myTune->sidFilename, myStatus.currSong);
 	goto xs_err_exit;
 	}
 
@@ -333,9 +318,10 @@
 	{
 	XSERR("Couldn't open XMMS audio output (fmt=%x, freq=%i, nchan=%i)!\n",
 	myStatus.audioFormat, myStatus.audioFrequency, myStatus.audioChannels);
-	pthread_mutex_lock(&xs_mutex);
+	
+	XS_MUTEX_LOCK(xs_status);
 	xs_status.isError = TRUE;
-	pthread_mutex_unlock(&xs_mutex);
+	XS_MUTEX_UNLOCK(xs_status);
 	goto xs_err_exit;
 	}
 
@@ -347,7 +333,7 @@
  while (xs_status.isPlaying && myStatus.isPlaying && (xs_status.currSong == myStatus.currSong))
 	{
 	/* Render audio data */
-	audioGot = xs_player->plrFillBuffer(&myStatus, audioBuffer, XS_BUFSIZE);
+	audioGot = myStatus.sidPlayer->plrFillBuffer(&myStatus, audioBuffer, XS_BUFSIZE);
 
 	/* I <3 visualice/haujobb */
 	xs_plugin_ip.add_vis_pcm(
@@ -366,6 +352,7 @@
 		xs_plugin_ip.output->write_audio(audioBuffer, audioGot);
 
 	/* Check if we have played enough */
+	XS_MUTEX_LOCK(xs_cfg);
 	if (xs_cfg.playMaxTimeEnable)
 		{
 		if (xs_cfg.playMaxTimeUnknown)
@@ -378,6 +365,7 @@
 				myStatus.isPlaying = FALSE;
 			}
 		}
+	XS_MUTEX_UNLOCK(xs_cfg);
 
 	if (songLength > 0)
 		{
@@ -411,9 +399,9 @@
  /* Exit the playing thread */
  XSDEBUG("exiting thread, bye.\n");
 
- pthread_mutex_lock(&xs_mutex);
+ XS_MUTEX_LOCK(xs_status);
  xs_status.isPlaying = FALSE;
- pthread_mutex_unlock(&xs_mutex);
+ XS_MUTEX_UNLOCK(xs_status);
  pthread_exit(NULL);
 }
 
@@ -426,17 +414,19 @@
  */
 void xs_play_file(gchar *pcFilename)
 {
+ assert(xs_status.sidPlayer);
+
  XSDEBUG("play '%s'\n", pcFilename);
  
  /* Get tune information */
- if ((xs_status.pTune = xs_player->plrGetSIDInfo(pcFilename)) == NULL)
+ if ((xs_status.tuneInfo = xs_status.sidPlayer->plrGetSIDInfo(pcFilename)) == NULL)
  	return;
 
  /* Initialize the tune */
- if (!xs_player->plrLoadSID(&xs_status, pcFilename))
+ if (!xs_status.sidPlayer->plrLoadSID(&xs_status, pcFilename))
  	{
- 	xs_tune_free(xs_status.pTune);
- 	xs_status.pTune = NULL;
+ 	xs_tuneinfo_free(xs_status.tuneInfo);
+ 	xs_status.tuneInfo = NULL;
  	return;
  	}
 
@@ -445,15 +435,15 @@
  /* Set general status information */
  xs_status.isPlaying	= TRUE;
  xs_status.isError	= FALSE;
- xs_status.currSong	= xs_status.pTune->startTune;
+ xs_status.currSong	= xs_status.tuneInfo->startTune;
  
  /* 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));
- 	xs_tune_free(xs_status.pTune);
-	xs_status.pTune = NULL;
-	xs_player->plrDeleteSID(&xs_status);
+ 	xs_tuneinfo_free(xs_status.tuneInfo);
+	xs_status.tuneInfo = NULL;
+	xs_status.sidPlayer->plrDeleteSID(&xs_status);
 	}
 
  XSDEBUG("systems should be up?\n");
@@ -479,16 +469,16 @@
 	{
 	/* Stop playing */
 	XSDEBUG("stopping...\n");
-	pthread_mutex_lock(&xs_mutex);
+	XS_MUTEX_LOCK(xs_status);
 	xs_status.isPlaying = FALSE;
-	pthread_mutex_unlock(&xs_mutex);
+	XS_MUTEX_UNLOCK(xs_status);
 	pthread_join(xs_decode_thread, NULL);
 	}
 
  /* Free tune information */
- xs_player->plrDeleteSID(&xs_status);
- xs_tune_free(xs_status.pTune);
- xs_status.pTune = NULL;
+ xs_status.sidPlayer->plrDeleteSID(&xs_status);
+ xs_tuneinfo_free(xs_status.tuneInfo);
+ xs_status.tuneInfo = NULL;
 
  /* Update subtune control */
  xs_subctrl_update();
@@ -506,104 +496,100 @@
 
 
 /*
+ * Set or change sub-tune
+ */
+void xs_set_subtune(int n)
+{
+ XS_MUTEX_LOCK(xs_status);
+ 
+ if (xs_status.tuneInfo && xs_status.isPlaying)
+ 	{
+ 	if ((n >= 1) && (n <= xs_status.tuneInfo->nsubTunes))
+ 		xs_status.currSong = n;
+	}
+
+ XS_MUTEX_UNLOCK(xs_status);
+
+ xs_subctrl_update();
+}
+
+
+void xs_change_subtune(int n)
+{
+ XS_MUTEX_LOCK(xs_status);
+ 
+ if (xs_status.tuneInfo && xs_status.isPlaying)
+ 	{
+ 	n += xs_status.currSong;
+ 	
+ 	if ((n >= 1) && (n <= xs_status.tuneInfo->nsubTunes))
+ 		xs_status.currSong = n;
+	}
+
+ XS_MUTEX_UNLOCK(xs_status);
+
+ xs_subctrl_update();
+}
+
+
+/*
  * Pop-up subtune selector
  */
-#define LUW(x...)	lookup_widget(xs_fileinfowin, ## x)
+void xs_subctrl_setsong(void)
+{
+ xs_set_subtune(GTK_ADJUSTMENT(xs_subctrl_adj)->value);
+}
+
+
+void xs_subctrl_prevsong(void)
+{
+ xs_change_subtune(-1);
+}
+
+
+void xs_subctrl_nextsong(void)
+{
+ xs_change_subtune( 1);
+}
+
 
 void xs_subctrl_update(void)
 {
  GtkAdjustment *tmpAdj;
  gboolean isEnabled;
  
+ XS_MUTEX_LOCK(xs_status);
+ 
  /* Check if control window exists, we are currently playing and have a tune */
  if (xs_subctrl)
 	{
-	if (xs_status.pTune && xs_status.isPlaying)
+	if (xs_status.tuneInfo && xs_status.isPlaying)
 		{
+		XS_MUTEX_LOCK(xs_subctrl);
 	 	tmpAdj = GTK_ADJUSTMENT(xs_subctrl_adj);
  	
  		tmpAdj->value = xs_status.currSong;
  		tmpAdj->lower = 1;
-		tmpAdj->upper = xs_status.pTune->nsubTunes;
+		tmpAdj->upper = xs_status.tuneInfo->nsubTunes;
  		gtk_adjustment_value_changed(tmpAdj);
+ 		XS_MUTEX_UNLOCK(xs_subctrl);
  		} else
  		xs_subctrl_close();
  	}
 
- if (xs_fileinfowin)
- 	{
- 	/* Check if we are currently playing and have a tune */
- 	if (xs_status.pTune && xs_status.isPlaying && (xs_status.pTune->nsubTunes > 1))
- 		{
-		tmpAdj = gtk_range_get_adjustment(GTK_RANGE(LUW("fileinfo_subctrl_adj")));
-
- 		tmpAdj->value = xs_status.currSong;
- 		tmpAdj->lower = 1;
-		tmpAdj->upper = xs_status.pTune->nsubTunes;
- 		gtk_adjustment_value_changed(tmpAdj);
- 		isEnabled = TRUE; 		
- 		} else
- 		isEnabled = FALSE;
-	
-	/* Enable or disable subtune-control in fileinfo window */
-	gtk_widget_set_sensitive(LUW("fileinfo_subctrl_prev"), isEnabled);
-	gtk_widget_set_sensitive(LUW("fileinfo_subctrl_adj"), isEnabled);
-	gtk_widget_set_sensitive(LUW("fileinfo_subctrl_next"), isEnabled);
-	}
-}
-
-
-void xs_fileinfo_setsong(void)
-{
- pthread_mutex_lock(&xs_mutex);
- xs_status.currSong = gtk_range_get_adjustment(GTK_RANGE(LUW("fileinfo_subctrl_adj")))->value;
- pthread_mutex_unlock(&xs_mutex);
-}
-
-
-void xs_subctrl_setsong(void)
-{
- pthread_mutex_lock(&xs_mutex);
- xs_status.currSong = GTK_ADJUSTMENT(xs_subctrl_adj)->value;
- pthread_mutex_unlock(&xs_mutex);
-}
-
-
-void xs_subctrl_prevsong(void)
-{
- if (xs_status.pTune && xs_status.isPlaying)
- 	{
- 	pthread_mutex_lock(&xs_mutex);
- 	if (xs_status.currSong > 1)
-		xs_status.currSong--;
-	pthread_mutex_unlock(&xs_mutex);
-	}
-
- xs_subctrl_update();
-}
-
-
-void xs_subctrl_nextsong(void)
-{
- if (xs_status.pTune && xs_status.isPlaying)
- 	{
- 	pthread_mutex_lock(&xs_mutex);
- 	if (xs_status.currSong < xs_status.pTune->nsubTunes)
-		xs_status.currSong++;
-	pthread_mutex_unlock(&xs_mutex);
-	}
-
- xs_subctrl_update();
+ XS_MUTEX_UNLOCK(xs_status);
 }
 
 
 void xs_subctrl_close(void)
 {
+ XS_MUTEX_LOCK(xs_subctrl);
  if (xs_subctrl)
  	{
 	gtk_widget_destroy(xs_subctrl);
 	xs_subctrl = NULL;
 	}
+ XS_MUTEX_UNLOCK(xs_subctrl);
 }
 
 
@@ -620,8 +606,14 @@
 {
  GtkWidget *frame25, *hbox15, *subctrl_prev, *subctrl_current, *subctrl_next;
 
- if (!xs_status.pTune || !xs_status.isPlaying ||
-    xs_subctrl || (xs_status.pTune->nsubTunes <= 1)) return;
+ XS_MUTEX_LOCK(xs_subctrl);
+ 
+ if (!xs_status.tuneInfo || !xs_status.isPlaying ||
+    xs_subctrl || (xs_status.tuneInfo->nsubTunes <= 1))
+    {
+    XS_MUTEX_UNLOCK(xs_subctrl);
+    return;
+    }
 
  /* Create the pop-up window */
  xs_subctrl = gtk_window_new (GTK_WINDOW_DIALOG);
@@ -656,7 +648,7 @@
  gtk_widget_set_name (subctrl_prev, "subctrl_prev");
  gtk_box_pack_start (GTK_BOX (hbox15), subctrl_prev, FALSE, FALSE, 0);
 
- xs_subctrl_adj = gtk_adjustment_new (xs_status.currSong, 1, xs_status.pTune->nsubTunes, 1, 1, 0);
+ xs_subctrl_adj = gtk_adjustment_new (xs_status.currSong, 1, xs_status.tuneInfo->nsubTunes, 1, 1, 0);
  gtk_signal_connect (GTK_OBJECT (xs_subctrl_adj), "value_changed",
 	GTK_SIGNAL_FUNC (xs_subctrl_setsong), NULL);
 
@@ -681,6 +673,8 @@
  	GTK_SIGNAL_FUNC (xs_subctrl_keypress), NULL);
  
  gtk_widget_show_all(xs_subctrl);
+
+ XS_MUTEX_UNLOCK(xs_subctrl);
 }
 
 
@@ -696,16 +690,22 @@
 void xs_seek(gint iTime)
 {
  /* Check status */
- if (!xs_status.pTune || !xs_status.isPlaying) return;
+ XS_MUTEX_LOCK(xs_status);
+ if (!xs_status.tuneInfo || !xs_status.isPlaying)
+ 	{
+ 	XS_MUTEX_UNLOCK(xs_status);
+ 	return;
+ 	}
 
- /* Act according to settings */ 
+ /* Act according to settings */
+ XS_MUTEX_LOCK(xs_cfg); 
  switch (xs_cfg.subsongControl) {
  case XS_SSC_SEEK:
 	if (iTime < xs_status.lastTime)
-		xs_subctrl_prevsong();
+		xs_change_subtune(-1);
 		else
 	if (iTime > xs_status.lastTime)
-		xs_subctrl_nextsong();
+		xs_change_subtune(1);
 	break;
 
  case XS_SSC_POPUP:
@@ -715,18 +715,14 @@
  /* If we have song-position patch, check settings */
 #ifdef HAVE_SONG_POSITION
  case XS_SSC_PATCH:
-	pthread_mutex_lock(&xs_mutex);
-
-	if ((iTime > 0) && (iTime <= xs_status.pTune->nsubTunes))
+	if ((iTime > 0) && (iTime <= xs_status.tuneInfo->nsubTunes))
 		xs_status.currSong = iTime;
-	
-	pthread_mutex_unlock(&xs_mutex);
 	break;
 #endif
+ }
 
- default:
- 	break;
- }
+ XS_MUTEX_UNLOCK(xs_cfg);
+ XS_MUTEX_UNLOCK(xs_status);
 }
 
 
@@ -740,18 +736,30 @@
 gint xs_get_time(void)
 {
  /* If errorflag is set, return -2 to signal it to XMMS's idle callback */
+ XS_MUTEX_LOCK(xs_status);
+ 
  if (xs_status.isError)
+ 	{
+ 	XS_MUTEX_UNLOCK(xs_status);
 	return -2;
+	}
 
  /* If there is no tune, return -1 */
- if (!xs_status.pTune)
+ if (!xs_status.tuneInfo)
+ 	{
+ 	XS_MUTEX_UNLOCK(xs_status);
  	return -1;
+ 	}
  
  /* If tune has ended, return -1 */
  if (!xs_status.isPlaying)
+ 	{
+ 	XS_MUTEX_UNLOCK(xs_status);
 	return -1;
+	}
 
  /* Let's see what we do */
+ XS_MUTEX_LOCK(xs_cfg);
  switch (xs_cfg.subsongControl) {
  case XS_SSC_SEEK:
  	xs_status.lastTime = (xs_plugin_ip.output->output_time() / 1000);
@@ -759,13 +767,14 @@
  
 #ifdef HAVE_SONG_POSITION
  case XS_SSC_PATCH:
-	pthread_mutex_lock(&xs_mutex);
-	set_song_position(xs_status.currSong, 1, xs_status.pTune->nsubTunes);
-	pthread_mutex_unlock(&xs_mutex);
+	set_song_position(xs_status.currSong, 1, xs_status.tuneInfo->nsubTunes);
 	break;
 #endif
  }
  
+ XS_MUTEX_UNLOCK(xs_cfg);
+ XS_MUTEX_UNLOCK(xs_status);
+
  /* Return output time reported by audio output plugin */
  return xs_plugin_ip.output->output_time();
 }
@@ -779,11 +788,11 @@
  */
 void xs_get_song_info(gchar *songFilename, gchar **songTitle, gint *songLength)
 {
- t_xs_tune *pInfo;
+ t_xs_tuneinfo *pInfo;
  gint tmpInt;
  
  /* Get tune information from emulation engine */
- pInfo = xs_player->plrGetSIDInfo(songFilename);
+ pInfo = xs_status.sidPlayer->plrGetSIDInfo(songFilename);
  if (!pInfo) return;
 
  /* Get sub-tune information, if available */
@@ -799,50 +808,54 @@
 	}
 
  /* Free tune information */	
- xs_tune_free(pInfo);
+ xs_tuneinfo_free(pInfo);
 }
 
 
-/*
- * Allocate a new tune structure
+/* Allocate a new tune information structure
  */
-t_xs_tune *xs_tune_new(gchar *pcFilename, gint nsubTunes, gint startTune,
-	gchar *tuneName, gchar *tuneComposer, gchar *tuneCopyright)
+t_xs_tuneinfo *xs_tuneinfo_new(gchar *pcFilename, gint nsubTunes, gint startTune,
+	gchar *sidName, gchar *sidComposer, gchar *sidCopyright,
+	gint loadAddr, gint initAddr, gint playAddr, gint dataFileLen)
 {
- t_xs_tune *pResult;
+ t_xs_tuneinfo *pResult;
  
- pResult = (t_xs_tune *) g_malloc0(sizeof(t_xs_tune));
+ pResult = (t_xs_tuneinfo *) g_malloc0(sizeof(t_xs_tuneinfo));
  if (!pResult) return NULL;
  
- pResult->tuneFilename = g_strdup(pcFilename);
- if (!pResult->tuneFilename)
+ pResult->sidFilename = g_strdup(pcFilename);
+ if (!pResult->sidFilename)
  	{
  	g_free(pResult);
  	return NULL;
  	}
  
- pResult->tuneName	= g_strdup(tuneName);
- pResult->tuneComposer	= g_strdup(tuneComposer);
- pResult->tuneCopyright	= g_strdup(tuneCopyright);
+ pResult->sidName	= g_strdup(sidName);
+ pResult->sidComposer	= g_strdup(sidComposer);
+ pResult->sidCopyright	= g_strdup(sidCopyright);
  pResult->nsubTunes	= nsubTunes;
  pResult->startTune	= startTune;
+
+ pResult->loadAddr	= loadAddr;
+ pResult->initAddr	= initAddr;
+ pResult->playAddr	= playAddr;
+ pResult->dataFileLen	= dataFileLen;
  
  return pResult;
 }
 
 
-/*
- * Free tune information
+/* Free given tune information structure
  */
-void xs_tune_free(t_xs_tune *pTune)
+void xs_tuneinfo_free(t_xs_tuneinfo *pTune)
 {
  gint i;
  if (!pTune) return;
 
- g_free(pTune->tuneFilename);	pTune->tuneFilename = NULL;
- g_free(pTune->tuneName);	pTune->tuneName = NULL;
- g_free(pTune->tuneComposer);	pTune->tuneComposer = NULL;
- g_free(pTune->tuneCopyright);	pTune->tuneCopyright = NULL;
+ g_free(pTune->sidFilename);	pTune->sidFilename = NULL;
+ g_free(pTune->sidName);	pTune->sidName = NULL;
+ g_free(pTune->sidComposer);	pTune->sidComposer = NULL;
+ g_free(pTune->sidCopyright);	pTune->sidCopyright = NULL;
  
  for (i = 0; i < pTune->nsubTunes; i++)
  	{
@@ -856,3 +869,7 @@
  g_free(pTune);
 }
 
+
+void xs_fileinfo_ok(void)
+{
+}
--- a/src/xmms-sid.h	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xmms-sid.h	Tue Dec 21 09:25:03 2004 +0000
@@ -22,10 +22,6 @@
 #ifndef _XMMS_SID_H
 #define _XMMS_SID_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
@@ -37,65 +33,125 @@
 #endif
 
 #include <glib.h>
+#include <pthread.h>
 #include <xmms/plugin.h>
 
-/*
- * Some defines
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Some defines
  */
 #define DEBUG
+
 #undef HAVE_HARDSID_BUILDER	/* HardSID-support is not working and is untested */
 
-/*
- * Generals
- */
 #define XS_BUFSIZE		(4096)		/* Size for some buffers */
 
+#define XS_SIDBUF_SIZE		(80*1024)	/* Size of data buffer used for SID-tune
+						MD5 hash calculation. If this is too small,
+						the computed hash will be incorrect.
+						Largest SID files I've seen are ~70kB.
+						*/
+
+#define XS_SIDBUF_DYNAMIC			/* If not defined, static buffer is used.
+						Probably faster than allocating/deallocating
+						from heap, but fails on systems with limited
+						stack space.
+						*/
+
+#define XS_STIL_MAXENTRY	(128)		/* Max number of sub-songs in STIL/SLDB node */
+
+
 #define XS_CONFIG_IDENT		"XMMS-SID"	/* Configuration file identifier */
 #define XS_CONFIG_FILE		"/.xmms/xmms-sid"	/* Use this configfile if autocyrpe fails */
 
-#define XS_STIL_MAXENTRY	(128)		/* Max number of sub-songs in STIL/SLDB node */
-
 #define XS_MIN_OVERSAMPLE	(2)		/* Minimum oversampling factor */
 #define XS_MAX_OVERSAMPLE	(8)		/* Maximum oversampling factor */
 
-extern InputPlugin xs_plugin_ip;		/* XMMS-SID plugin structure */
+
+/* Macros for mutexes and threads. These exist to be able to
+ * easily change from pthreads to glib threads, etc, if necessary.
+ */
+#define XS_MPP(M)	M ## _mutex
+#ifdef DEBUG
+#define XS_MUTEX(M)	pthread_mutex_t	XS_MPP(M) = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; int M ## _qq;
+#else
+#define XS_MUTEX(M)	pthread_mutex_t	XS_MPP(M) = PTHREAD_MUTEX_INITIALIZER
+#endif
+#define XS_MUTEX_H(M)	extern pthread_mutex_t XS_MPP(M); extern int M ## _qq;
+#define XS_MUTEX_LOCK(M)	{ M ## _qq = pthread_mutex_lock(&XS_MPP(M)); if (M ## _qq) XSDEBUG("XS_MUTEX_LOCK(" #M ") == %i\n", M ## _qq); }
+#define XS_MUTEX_UNLOCK(M)	{ M ## _qq = pthread_mutex_unlock(&XS_MPP(M)); if (M ## _qq) XSDEBUG("XS_MUTEX_UNLOCK(" #M ") == %i\n", M ## _qq); }
+
+/* Shorthands for linked lists
+ */
+#define LPREV	(pNode->pPrev)
+#define LTHIS	(pNode)
+#define LNEXT	(pNode->pNext)
 
 
+/* Plugin-wide typedefs
+ */
 typedef struct {
 	gint		tuneSpeed;
 	gint		tuneLength;
 	gchar		*tuneTitle;
-} t_xs_subtune;
-
-
-typedef struct {
-	gchar		*tuneFilename,
-			*tuneName,
-			*tuneComposer,
-			*tuneCopyright;
-	gint		nsubTunes, startTune;
-	t_xs_subtune	subTunes[XS_STIL_MAXENTRY];
-} t_xs_tune;
+} t_xs_subtuneinfo;
 
 
 typedef struct {
-	gint		audioFrequency,
+	gchar		*sidFilename,
+			*sidName,
+			*sidComposer,
+			*sidCopyright;
+	gint		loadAddr,
+			initAddr,
+			playAddr,
+			dataFileLen;
+	gint		nsubTunes, startTune;
+	t_xs_subtuneinfo	subTunes[XS_STIL_MAXENTRY];
+} t_xs_tuneinfo;
+
+
+struct t_xs_status;
+
+typedef struct {
+	gint		plrIdent;
+	gboolean	(*plrIsOurFile)(gchar *);
+	gboolean	(*plrInit)(struct t_xs_status *);
+	void		(*plrClose)(struct t_xs_status *);
+	gboolean	(*plrInitSong)(struct t_xs_status *);
+	guint		(*plrFillBuffer)(struct t_xs_status *, gchar *, guint);
+	gboolean	(*plrLoadSID)(struct t_xs_status *, gchar *);
+	void		(*plrDeleteSID)(struct t_xs_status *);
+	t_xs_tuneinfo*	(*plrGetSIDInfo)(gchar *);
+} t_xs_player;
+
+
+typedef struct t_xs_status {
+	gint		audioFrequency,		/* Audio settings */
 			audioFormat,
 			audioChannels,
 			audioBitsPerSample;
-	void		*player;
+	void		*sidEngine;		/* SID-emulation internal engine data */
+	t_xs_player	*sidPlayer;		/* Selected player engine */
 	gboolean	isError, isPlaying;
-	gint		currSong,
+	gint		currSong,		/* Current sub-tune */
 			lastTime;
-	t_xs_tune	*pTune;
+	t_xs_tuneinfo	*tuneInfo;
 } t_xs_status;
 
 
-extern t_xs_status xs_status;
+/* Global variables
+ */
+extern InputPlugin	xs_plugin_ip;
+
+extern t_xs_status	xs_status;
+XS_MUTEX_H(xs_status);
 
 
-/*
- * Plugin function prototypes
+
+/* Plugin function prototypes
  */
 void	xs_init(void);
 void	xs_reinit(void);
@@ -109,16 +165,16 @@
 void	xs_get_song_info(gchar *, gchar **, gint *);
 void	xs_fileinfo(gchar *);
 void	xs_about(void);
+void	xs_set_subtune(gint);
 
-t_xs_tune *xs_tune_new(gchar *, gint, gint, gchar *, gchar *, gchar *);
-void	xs_tune_free(t_xs_tune *);
+t_xs_tuneinfo *xs_tuneinfo_new(gchar *, gint, gint, gchar *, gchar *, gchar *, gint, gint, gint, gint);
+void	xs_tuneinfo_free(t_xs_tuneinfo *);
 
 
-/*
- * Debugging and error handling macros
+/* Debugging and error handling macros
  */
 #ifdef DEBUG
-#define XSDEBUG(x...) { fprintf(stderr, "XS[%s:%d]: ", __FILE__, (int) __LINE__); fprintf(stderr, ## x); }
+#define XSDEBUG(x...) { fprintf(stderr, "XS[%s:%s:%d]: ", __FILE__, __FUNCTION__, (int) __LINE__); fprintf(stderr, ## x); }
 #else
 #define XSDEBUG(x...) /* foo */
 #endif
--- a/src/xs_config.c	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_config.c	Tue Dec 21 09:25:03 2004 +0000
@@ -145,21 +145,10 @@
 static const gint xs_widtable_max = (sizeof(xs_widtable) / sizeof(t_xs_wid_item));
 
 
-/*
- * Reset the filter settings
- */
-void xs_reset_filters(void)
-{
- /* Reset filter values (copied from libsidplay1's headers) */
- XS_MUTEX_LOCK(xs_cfg);
-
- xs_cfg.filterFs = 400.0f;
- xs_cfg.filterFm = 60.0f;
- xs_cfg.filterFt = 0.05f;
-
- XS_MUTEX_UNLOCK(xs_cfg);
-}
-
+/* libSIDPlay1 default filter values (copied from libsidplay1's headers) */
+#define	XS_SIDPLAY1_FS	(400.0f)
+#define XS_SIDPLAY1_FM	(60.0f)
+#define XS_SIDPLAY1_FT	(0.05f)
 
 /*
  * Get the configuration (from file or default)
@@ -179,8 +168,11 @@
  xs_cfg.audioFrequency		= 44100;
 
  xs_cfg.mos8580			= FALSE;
+
  xs_cfg.emulateFilters		= TRUE;
- xs_reset_filters();
+ xs_cfg.filterFs		= XS_SIDPLAY1_FS;
+ xs_cfg.filterFm		= XS_SIDPLAY1_FM;
+ xs_cfg.filterFt		= XS_SIDPLAY1_FT;
 
 #ifdef HAVE_SIDPLAY2
  xs_cfg.playerEngine		= XS_ENG_SIDPLAY2;
@@ -463,15 +455,17 @@
  */
 void xs_cfg_filter_reset(void)
 {
- XS_MUTEX_LOCK(xs_cfg);
-
- xs_reset_filters();
+ gtk_adjustment_set_value(
+ 	gtk_range_get_adjustment(GTK_RANGE(LUW("cfg_emu_filt_fs"))),
+ 	XS_SIDPLAY1_FS);
 
- gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(LUW("cfg_emu_filt_fs"))), xs_cfg.filterFs);
- gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(LUW("cfg_emu_filt_fm"))), xs_cfg.filterFm);
- gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(LUW("cfg_emu_filt_ft"))), xs_cfg.filterFt);
+ gtk_adjustment_set_value(
+ 	gtk_range_get_adjustment(GTK_RANGE(LUW("cfg_emu_filt_fm"))),
+ 	XS_SIDPLAY1_FM);
 
- XS_MUTEX_UNLOCK(xs_cfg);
+ gtk_adjustment_set_value(
+ 	gtk_range_get_adjustment(GTK_RANGE(LUW("cfg_emu_filt_ft"))),
+ 	XS_SIDPLAY1_FT);
 }
 
 
--- a/src/xs_fileinfo.c	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_fileinfo.c	Tue Dec 21 09:25:03 2004 +0000
@@ -29,10 +29,17 @@
 #include "xs_glade.h"
 
 static GtkWidget		*xs_fileinfowin = NULL;
+static t_xs_stil_node		*xs_fileinfostil = NULL;
+static t_xs_tuneinfo		*xs_fileinfotune = NULL;
 
 #define LUW(x...)	lookup_widget(xs_fileinfowin, ## x)
 
 
+void xs_fileinfo_setsong(void)
+{
+}
+
+
 void xs_fileinfo_ok(void)
 {
  gtk_widget_destroy(xs_fileinfowin);
@@ -95,7 +102,7 @@
 
  /* Free old info, if set */
  if (xs_fileinfotune)
- 	xs_tune_free(xs_fileinfotune);
+ 	xs_tuneinfo_free(xs_fileinfotune);
  
  /* Get new tune information */
  if ((xs_fileinfotune = xs_player->plrGetSIDInfo(pcFilename)) == NULL)
@@ -174,9 +181,6 @@
  /* Set the subtune information */
  xs_fileinfo_subtune(NULL, tmpMenu);
 
- /* Update subtune controls */
- xs_subctrl_update();
-
  /* Show the window */
  gtk_widget_show(xs_fileinfowin);
 }
--- a/src/xs_init.c	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_init.c	Tue Dec 21 09:25:03 2004 +0000
@@ -46,7 +46,7 @@
 	NULL,			/* Send data to Visualization plugin */
 	NULL, NULL,		/* FILLED BY XMMS */
 	xs_get_song_info,	/* Get song title and length */
-	xs_fileinfo,		/* Show file-information dialog */
+	NULL, /*xs_fileinfo,		Show file-information dialog */
 	NULL			/* FILLED BY XMMS */
 };
 
--- a/src/xs_length.c	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_length.c	Tue Dec 21 09:25:03 2004 +0000
@@ -21,6 +21,7 @@
 */
 #include "xs_length.h"
 #include "xs_support.h"
+#include "xs_config.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -553,3 +554,86 @@
  
  return pResult;
 }
+
+
+/*
+ * These should be moved out of this module some day ...
+ */
+static t_xs_sldb	*xs_sldb_db = NULL;
+XS_MUTEX(xs_sldb_db);
+
+gint xs_songlen_init(void)
+{
+ XS_MUTEX_LOCK(xs_cfg);
+ 
+ if (!xs_cfg.songlenDBPath)
+ 	{
+ 	XS_MUTEX_UNLOCK(xs_cfg);
+ 	return -1;
+ 	}
+
+ XS_MUTEX_LOCK(xs_sldb_db);
+ 
+ /* Check if already initialized */
+ if (xs_sldb_db) xs_sldb_free(xs_sldb_db);
+ 
+ /* Allocate database */
+ xs_sldb_db = (t_xs_sldb *) g_malloc0(sizeof(t_xs_sldb));
+ if (!xs_sldb_db)
+ 	{
+ 	XS_MUTEX_UNLOCK(xs_cfg);
+ 	XS_MUTEX_UNLOCK(xs_sldb_db);
+ 	return -2;
+ 	}
+ 
+ /* Read the database */
+ if (xs_sldb_read(xs_sldb_db, xs_cfg.songlenDBPath) != 0)
+ 	{
+ 	xs_sldb_free(xs_sldb_db);
+ 	xs_sldb_db = NULL;
+ 	XS_MUTEX_UNLOCK(xs_cfg);
+ 	XS_MUTEX_UNLOCK(xs_sldb_db);
+ 	return -3;
+ 	}
+
+ /* Create index */
+ if (xs_sldb_index(xs_sldb_db) != 0)
+ 	{
+ 	xs_sldb_free(xs_sldb_db);
+ 	xs_sldb_db = NULL;
+ 	XS_MUTEX_UNLOCK(xs_cfg);
+ 	XS_MUTEX_UNLOCK(xs_sldb_db);
+ 	return -4;
+ 	}
+
+ XS_MUTEX_UNLOCK(xs_cfg);
+ XS_MUTEX_UNLOCK(xs_sldb_db);
+ return 0;
+}
+
+
+void xs_songlen_close(void)
+{
+ XS_MUTEX_LOCK(xs_sldb_db);
+ xs_sldb_free(xs_sldb_db);
+ xs_sldb_db = NULL;
+ XS_MUTEX_UNLOCK(xs_sldb_db);
+}
+
+
+t_xs_sldb_node * xs_songlen_get(gchar *pcFilename)
+{
+ t_xs_sldb_node *pResult;
+
+ XS_MUTEX_LOCK(xs_sldb_db);
+
+ if (xs_cfg.songlenDBEnable && xs_sldb_db)
+ 	pResult = xs_sldb_get(xs_sldb_db, pcFilename);
+ 	else
+ 	pResult = NULL;
+
+ XS_MUTEX_UNLOCK(xs_sldb_db);
+ 
+ return pResult;
+}
+
--- a/src/xs_length.h	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_length.h	Tue Dec 21 09:25:03 2004 +0000
@@ -36,6 +36,10 @@
 t_xs_sldb_node *	xs_sldb_get(t_xs_sldb *, gchar *);
 
 
+gint			xs_songlen_init(void);
+void			xs_songlen_close(void);
+t_xs_sldb_node *	xs_songlen_get(gchar *);
+
 #ifdef __cplusplus
 }
 #endif
--- a/src/xs_sidplay.h	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_sidplay.h	Tue Dec 21 09:25:03 2004 +0000
@@ -3,10 +3,10 @@
  * Get all SID-tune information (for all sub-tunes)
  * including name, length, etc.
  */
-t_xs_tune * TFUNCTION(gchar *pcFilename)
+t_xs_tuneinfo * TFUNCTION(gchar *pcFilename)
 {
  t_xs_sldb_node *tuneLength = NULL;
- t_xs_tune *pResult;
+ t_xs_tuneinfo *pResult;
  TTUNEINFO tuneInfo;
  TTUNE *testTune;
  gboolean haveInfo = TRUE;
@@ -35,7 +35,7 @@
  tuneLength = xs_songlen_get(pcFilename);
 
  /* Allocate tuneinfo structure */
- pResult = xs_tune_new(pcFilename,
+ pResult = xs_tuneinfo_new(pcFilename,
  	tuneInfo.songs, tuneInfo.startSong,
  	tuneInfo.infoString[0], tuneInfo.infoString[1], tuneInfo.infoString[2],
  	tuneInfo.loadAddr, tuneInfo.initAddr, tuneInfo.playAddr,
--- a/src/xs_sidplay1.cc	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_sidplay1.cc	Tue Dec 21 09:25:03 2004 +0000
@@ -23,13 +23,11 @@
 
 #ifdef HAVE_SIDPLAY1
 
-extern "C" {
 #include "xs_sidplay1.h"
 #include <stdio.h>
 #include "xs_config.h"
 #include "xs_length.h"
 #include "xs_title.h"
-}
 
 #include <sidplay/player.h>
 #include <sidplay/myendian.h>
@@ -73,32 +71,32 @@
  */
 gboolean xs_sidplay1_init(t_xs_status *myStatus)
 {
- t_xs_sidplay1 *myPlayer;
+ t_xs_sidplay1 *myEngine;
  assert(myStatus);
 
  /* Allocate internal structures */
- myPlayer = (t_xs_sidplay1 *) g_malloc0(sizeof(t_xs_sidplay1));
- if (!myPlayer) return FALSE;
+ myEngine = (t_xs_sidplay1 *) g_malloc0(sizeof(t_xs_sidplay1));
+ if (!myEngine) return FALSE;
 
  /* Initialize engine */
- myPlayer->currEng = new emuEngine();
- if (!myPlayer->currEng)
+ myEngine->currEng = new emuEngine();
+ if (!myEngine->currEng)
 	{
 	XSERR("Could not initialize libSIDPlay1 emulation engine\n");
-	g_free(myPlayer);
+	g_free(myEngine);
 	return FALSE;
 	}
 
  /* Verify endianess */
- if (!myPlayer->currEng->verifyEndianess())
+ if (!myEngine->currEng->verifyEndianess())
 	{
 	XSERR("Endianess verification failed\n");
-	delete myPlayer->currEng;
-	g_free(myPlayer);
+	delete myEngine->currEng;
+	g_free(myEngine);
 	return FALSE;
 	}
 
- myStatus->player = myPlayer;
+ myStatus->sidEngine = myEngine;
  return TRUE;
 }
 
@@ -108,56 +106,56 @@
  */
 void xs_sidplay1_close(t_xs_status *myStatus)
 {
- t_xs_sidplay1 *myPlayer;
+ t_xs_sidplay1 *myEngine;
  assert(myStatus);
 
  /* Free internals */
- myPlayer = (t_xs_sidplay1 *) myStatus->player;
- if (myPlayer->currEng)
+ myEngine = (t_xs_sidplay1 *) myStatus->sidEngine;
+ if (myEngine->currEng)
 	{
-	delete myPlayer->currEng;
-	myPlayer->currEng = NULL;	
+	delete myEngine->currEng;
+	myEngine->currEng = NULL;	
 	}
 
- g_free(myPlayer);
- myStatus->player = NULL;
+ g_free(myEngine);
+ myStatus->sidEngine = NULL;
 }
 
 
 gboolean xs_sidplay1_initsong(t_xs_status *myStatus)
 {
- t_xs_sidplay1 *myPlayer = (t_xs_sidplay1 *) myStatus->player;
+ t_xs_sidplay1 *myEngine = (t_xs_sidplay1 *) myStatus->sidEngine;
 
- if (!myPlayer) return FALSE;
+ if (!myEngine) return FALSE;
 
- if (!myPlayer->currTune)
+ if (!myEngine->currTune)
 	{
 	XSERR("Tune was NULL\n");
 	return FALSE;
 	}
 
- if (!myPlayer->currTune->getStatus())
+ if (!myEngine->currTune->getStatus())
 	{
 	XSERR("Tune status check failed\n");
 	return FALSE;
 	}
 
  return sidEmuInitializeSong(
-	*myPlayer->currEng,
-	*myPlayer->currTune,
+	*myEngine->currEng,
+	*myEngine->currTune,
 	myStatus->currSong);
 }
 
 
 guint xs_sidplay1_fillbuffer(t_xs_status *myStatus, gchar *audioBuffer, guint audioBufSize)
 {
- t_xs_sidplay1 *myPlayer = (t_xs_sidplay1 *) myStatus->player;
+ t_xs_sidplay1 *myEngine = (t_xs_sidplay1 *) myStatus->sidEngine;
 
- if (!myPlayer) return FALSE;
+ if (!myEngine) return FALSE;
 
  sidEmuFillBuffer(
-	*myPlayer->currEng,
-	*myPlayer->currTune,
+	*myEngine->currEng,
+	*myEngine->currTune,
 	audioBuffer,
 	audioBufSize);
 
@@ -167,7 +165,7 @@
 
 gboolean xs_sidplay1_loadsid(t_xs_status *myStatus, gchar *pcFilename)
 {
- t_xs_sidplay1 *myPlayer = (t_xs_sidplay1 *) myStatus->player;
+ t_xs_sidplay1 *myEngine = (t_xs_sidplay1 *) myStatus->sidEngine;
  sidTune *newTune;
  assert(myStatus);
 
@@ -177,28 +175,28 @@
  if (!newTune) return FALSE;
 
  /* Get current configuration */
- myPlayer->currEng->getConfig(myPlayer->currConfig);
+ myEngine->currEng->getConfig(myEngine->currConfig);
 
  /* Configure channels and stuff */
  switch (myStatus->audioChannels) {
 
 	case XS_CHN_AUTOPAN:
-		myPlayer->currConfig.channels = SIDEMU_STEREO;
-		myPlayer->currConfig.autoPanning = SIDEMU_CENTEREDAUTOPANNING;
-		myPlayer->currConfig.volumeControl = SIDEMU_FULLPANNING;
+		myEngine->currConfig.channels = SIDEMU_STEREO;
+		myEngine->currConfig.autoPanning = SIDEMU_CENTEREDAUTOPANNING;
+		myEngine->currConfig.volumeControl = SIDEMU_FULLPANNING;
 		break;
 
 	case XS_CHN_STEREO:
-		myPlayer->currConfig.channels = SIDEMU_STEREO;
-		myPlayer->currConfig.autoPanning = SIDEMU_NONE;
-		myPlayer->currConfig.volumeControl = SIDEMU_NONE;
+		myEngine->currConfig.channels = SIDEMU_STEREO;
+		myEngine->currConfig.autoPanning = SIDEMU_NONE;
+		myEngine->currConfig.volumeControl = SIDEMU_NONE;
 		break;
 
 	case XS_CHN_MONO:
 	default:
-		myPlayer->currConfig.channels = SIDEMU_MONO;
-		myPlayer->currConfig.autoPanning = SIDEMU_NONE;
-		myPlayer->currConfig.volumeControl = SIDEMU_NONE;
+		myEngine->currConfig.channels = SIDEMU_MONO;
+		myEngine->currConfig.autoPanning = SIDEMU_NONE;
+		myEngine->currConfig.volumeControl = SIDEMU_NONE;
 		break;
  }
 
@@ -206,19 +204,19 @@
  /* Memory mode settings */
  switch (xs_cfg.memoryMode) {
 	case XS_MPU_BANK_SWITCHING:
-		myPlayer->currConfig.memoryMode = MPU_BANK_SWITCHING;
+		myEngine->currConfig.memoryMode = MPU_BANK_SWITCHING;
 		break;
 
 	case XS_MPU_TRANSPARENT_ROM:
-		myPlayer->currConfig.memoryMode = MPU_TRANSPARENT_ROM;
+		myEngine->currConfig.memoryMode = MPU_TRANSPARENT_ROM;
 		break;
 
 	case XS_MPU_PLAYSID_ENVIRONMENT:
-		myPlayer->currConfig.memoryMode = MPU_PLAYSID_ENVIRONMENT;
+		myEngine->currConfig.memoryMode = MPU_PLAYSID_ENVIRONMENT;
 		break;
 
 	default:
-		myPlayer->currConfig.memoryMode = MPU_BANK_SWITCHING;
+		myEngine->currConfig.memoryMode = MPU_BANK_SWITCHING;
 		break;
  }
 
@@ -226,37 +224,37 @@
  /* Clockspeed settings */
  switch (xs_cfg.clockSpeed) {
 	case XS_CLOCK_NTSC:
-		myPlayer->currConfig.clockSpeed = SIDTUNE_CLOCK_NTSC;
+		myEngine->currConfig.clockSpeed = SIDTUNE_CLOCK_NTSC;
 		break;
 
 	case XS_CLOCK_PAL:
 	default:
-		myPlayer->currConfig.clockSpeed = SIDTUNE_CLOCK_PAL;
+		myEngine->currConfig.clockSpeed = SIDTUNE_CLOCK_PAL;
 		break;
  }
 
 
  /* Configure rest of the emulation */
- myPlayer->currConfig.mos8580		= xs_cfg.mos8580;
- myPlayer->currConfig.emulateFilter	= xs_cfg.emulateFilters;
- myPlayer->currConfig.filterFs		= xs_cfg.filterFs;
- myPlayer->currConfig.filterFm		= xs_cfg.filterFm;
- myPlayer->currConfig.filterFt		= xs_cfg.filterFt;
+ myEngine->currConfig.mos8580		= xs_cfg.mos8580;
+ myEngine->currConfig.emulateFilter	= xs_cfg.emulateFilters;
+ myEngine->currConfig.filterFs		= xs_cfg.filterFs;
+ myEngine->currConfig.filterFm		= xs_cfg.filterFm;
+ myEngine->currConfig.filterFt		= xs_cfg.filterFt;
 
- myPlayer->currConfig.bitsPerSample	= myStatus->audioBitsPerSample;
- myPlayer->currConfig.frequency		= myStatus->audioFrequency;
+ myEngine->currConfig.bitsPerSample	= myStatus->audioBitsPerSample;
+ myEngine->currConfig.frequency		= myStatus->audioFrequency;
 
  switch (myStatus->audioBitsPerSample) {
  case XS_RES_8BIT:
 	switch (myStatus->audioFormat) {
 	case FMT_S8:
-		myPlayer->currConfig.sampleFormat	= SIDEMU_SIGNED_PCM;
+		myEngine->currConfig.sampleFormat	= SIDEMU_SIGNED_PCM;
 		break;
 
 	case FMT_U8:
 	default:
 		myStatus->audioFormat			= FMT_U8;
-		myPlayer->currConfig.sampleFormat	= SIDEMU_UNSIGNED_PCM;
+		myEngine->currConfig.sampleFormat	= SIDEMU_UNSIGNED_PCM;
 		break;
 	}
 	break;
@@ -267,7 +265,7 @@
 	case FMT_U16_LE:
 	case FMT_U16_BE:
 		myStatus->audioFormat			= FMT_U16_NE;
-		myPlayer->currConfig.sampleFormat       = SIDEMU_UNSIGNED_PCM;
+		myEngine->currConfig.sampleFormat       = SIDEMU_UNSIGNED_PCM;
 		break;
 
 	case FMT_S16_NE:
@@ -275,21 +273,21 @@
 	case FMT_S16_BE:
 	default:
 		myStatus->audioFormat			= FMT_S16_NE;
-		myPlayer->currConfig.sampleFormat       = SIDEMU_SIGNED_PCM;
+		myEngine->currConfig.sampleFormat       = SIDEMU_SIGNED_PCM;
 		break;
 	}
 	break;
  }
 
  /* Now set the emulator configuration */
- if (!myPlayer->currEng->setConfig(myPlayer->currConfig))
+ if (!myEngine->currEng->setConfig(myEngine->currConfig))
 	{
 	XSERR("Emulator engine configuration failed!\n");
 	return FALSE;
 	}
 
  /* Initialize status information */
- myPlayer->currTune = newTune;
+ myEngine->currTune = newTune;
 
  return TRUE;
 }
@@ -300,16 +298,16 @@
  */
 void xs_sidplay1_deletesid(t_xs_status *myStatus)
 {
- t_xs_sidplay1 *myPlayer;
+ t_xs_sidplay1 *myEngine;
  assert(myStatus);
 
- myPlayer = (t_xs_sidplay1 *) myStatus->player;
- if (!myPlayer) return;
+ myEngine = (t_xs_sidplay1 *) myStatus->sidEngine;
+ if (!myEngine) return;
 
- if (myPlayer->currTune)
+ if (myEngine->currTune)
 	{
-	delete myPlayer->currTune;
-	myPlayer->currTune = NULL;
+	delete myEngine->currTune;
+	myEngine->currTune = NULL;
 	}
 }
 
--- a/src/xs_sidplay1.h	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_sidplay1.h	Tue Dec 21 09:25:03 2004 +0000
@@ -3,6 +3,10 @@
 
 #include "xmms-sid.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 gboolean	xs_sidplay1_isourfile(gchar *);
 void		xs_sidplay1_close(t_xs_status *);
 gboolean	xs_sidplay1_init(t_xs_status *);
@@ -10,6 +14,9 @@
 guint		xs_sidplay1_fillbuffer(t_xs_status *, gchar *, guint);
 gboolean	xs_sidplay1_loadsid(t_xs_status *, gchar *);
 void		xs_sidplay1_deletesid(t_xs_status *);
-t_xs_tune*	xs_sidplay1_getsidinfo(gchar *);
+t_xs_tuneinfo*	xs_sidplay1_getsidinfo(gchar *);
 
+#ifdef __cplusplus
+}
+#endif
 #endif /* _XS_SIDPLAY1_H */
--- a/src/xs_sidplay2.cc	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_sidplay2.cc	Tue Dec 21 09:25:03 2004 +0000
@@ -23,14 +23,12 @@
 
 #ifdef HAVE_SIDPLAY2
 
-extern "C" {
 #include "xs_sidplay2.h"
 #include <stdio.h>
-#include <xmms/titlestring.h>
 #include "xs_config.h"
 #include "xs_support.h"
 #include "xs_length.h"
-}
+#include "xs_title.h"
 
 #include <sidplay/sidplay2.h>
 #ifdef HAVE_RESID_BUILDER
@@ -79,17 +77,17 @@
  */
 gboolean xs_sidplay2_init(t_xs_status *myStatus)
 {
- t_xs_sidplay2 *myPlayer;
+ t_xs_sidplay2 *myEngine;
  assert(myStatus);
 
  /* Allocate internal structures */
- myPlayer = (t_xs_sidplay2 *) g_malloc0(sizeof(t_xs_sidplay2));
- if (!myPlayer) return FALSE;
+ myEngine = (t_xs_sidplay2 *) g_malloc0(sizeof(t_xs_sidplay2));
+ if (!myEngine) return FALSE;
 
 
  /* Initialize the engine */
- myPlayer->currEng = new sidplay2;
- if (!myPlayer->currEng)
+ myEngine->currEng = new sidplay2;
+ if (!myEngine->currEng)
 	{
 	XSERR("Could not initialize libSIDPlay2 emulation engine\n");
 	return FALSE;
@@ -103,9 +101,9 @@
 	ReSIDBuilder *tmpb = new ReSIDBuilder("SIDPlay2 suxx and is made by a fag - ReSID builder");
 
 	/* Create the builder -- WHAT IS THIS MEANT FOR??? */
-	tmpb->create(myPlayer->currEng->info().maxsids);
+	tmpb->create(myEngine->currEng->info().maxsids);
 
-	myPlayer->currBuilder = (sidbuilder *) tmpb;
+	myEngine->currBuilder = (sidbuilder *) tmpb;
 	}
 #endif
 #ifdef HAVE_HARDSID_BUILDER
@@ -114,25 +112,25 @@
 	}
 #endif
 
- if (!myPlayer->currBuilder)
+ if (!myEngine->currBuilder)
 	{
 	XSERR("Could not initialize SIDBuilder object.\n");
 	return FALSE;
 	}
 
- XSDEBUG("%s\n", myPlayer->currBuilder->credits());
+ XSDEBUG("%s\n", myEngine->currBuilder->credits());
 
 
  /* Create the sidtune */
- myPlayer->currTune = new SidTune(0);
- if (!myPlayer->currTune)
+ myEngine->currTune = new SidTune(0);
+ if (!myEngine->currTune)
 	{
 	XSERR("Could not initialize SIDTune object.\n");
 	return FALSE;
 	}
  
  /* OK */
- myStatus->player = myPlayer;
+ myStatus->sidEngine = myEngine;
  return TRUE;
 }
 
@@ -142,50 +140,50 @@
  */
 void xs_sidplay2_close(t_xs_status *myStatus)
 {
- t_xs_sidplay2 *myPlayer;
+ t_xs_sidplay2 *myEngine;
  assert(myStatus);
 
  /* Free internals */
- myPlayer = (t_xs_sidplay2 *) myStatus->player;
+ myEngine = (t_xs_sidplay2 *) myStatus->sidEngine;
 
- if (myPlayer->currBuilder)
+ if (myEngine->currBuilder)
 	{
-	delete myPlayer->currBuilder;
-	myPlayer->currBuilder = NULL;
+	delete myEngine->currBuilder;
+	myEngine->currBuilder = NULL;
 	}
 
- if (myPlayer->currEng)
+ if (myEngine->currEng)
 	{
-	delete myPlayer->currEng;
-	myPlayer->currEng = NULL;
+	delete myEngine->currEng;
+	myEngine->currEng = NULL;
 	}
 
- if (myPlayer->currTune)
+ if (myEngine->currTune)
 	{
-	delete myPlayer->currTune;
-	myPlayer->currTune = NULL;
+	delete myEngine->currTune;
+	myEngine->currTune = NULL;
 	}
 
  xs_sidplay2_deletesid(myStatus);
 
- g_free(myPlayer);
- myStatus->player = NULL;
+ g_free(myEngine);
+ myStatus->sidEngine = NULL;
 }
 
 
 gboolean xs_sidplay2_initsong(t_xs_status *myStatus)
 {
- t_xs_sidplay2 *myPlayer = (t_xs_sidplay2 *) myStatus->player;
+ t_xs_sidplay2 *myEngine = (t_xs_sidplay2 *) myStatus->sidEngine;
 
- if (!myPlayer) return FALSE;
+ if (!myEngine) return FALSE;
 
- if (!myPlayer->currTune->selectSong(myStatus->currSong))
+ if (!myEngine->currTune->selectSong(myStatus->currSong))
 	{
 	XSERR("ENGINE selectSong() failed\n");
 	return FALSE;
 	}
 
- if (myPlayer->currEng->load(myPlayer->currTune) < 0)
+ if (myEngine->currEng->load(myEngine->currTune) < 0)
 	{
 	XSERR("ENGINE load() failed\n");
 	return FALSE;
@@ -197,38 +195,38 @@
 
 guint xs_sidplay2_fillbuffer(t_xs_status *myStatus, gchar *audioBuffer, guint audioBufSize)
 {
- t_xs_sidplay2 *myPlayer = (t_xs_sidplay2 *) myStatus->player;
+ t_xs_sidplay2 *myEngine = (t_xs_sidplay2 *) myStatus->sidEngine;
 
- return myPlayer->currEng->play(audioBuffer, audioBufSize);
+ return myEngine->currEng->play(audioBuffer, audioBufSize);
 }
 
 
 gboolean xs_sidplay2_loadsid(t_xs_status *myStatus, gchar *pcFilename)
 {
- t_xs_sidplay2 *myPlayer = (t_xs_sidplay2 *) myStatus->player;
+ t_xs_sidplay2 *myEngine = (t_xs_sidplay2 *) myStatus->sidEngine;
  assert(myStatus);
 
  /* Try to get the tune */
  if (!pcFilename) return FALSE;
- if (!myPlayer->currTune->load(pcFilename)) return FALSE;
+ if (!myEngine->currTune->load(pcFilename)) return FALSE;
 
  /* Get current configuration */
- myPlayer->currConfig = myPlayer->currEng->config();
+ myEngine->currConfig = myEngine->currEng->config();
 
  /* Configure channels and stuff */
  switch (myStatus->audioChannels) {
 
 	case XS_CHN_AUTOPAN:
-		myPlayer->currConfig.playback = sid2_stereo;
+		myEngine->currConfig.playback = sid2_stereo;
 		break;
 
 	case XS_CHN_STEREO:
-		myPlayer->currConfig.playback = sid2_stereo;
+		myEngine->currConfig.playback = sid2_stereo;
 		break;
 
 	case XS_CHN_MONO:
 	default:
-		myPlayer->currConfig.playback = sid2_mono;
+		myEngine->currConfig.playback = sid2_mono;
 		break;
  }
 
@@ -236,20 +234,20 @@
  /* Memory mode settings */
  switch (xs_cfg.memoryMode) {
 	case XS_MPU_BANK_SWITCHING:
-		myPlayer->currConfig.environment = sid2_envBS;
+		myEngine->currConfig.environment = sid2_envBS;
 		break;
 
 	case XS_MPU_TRANSPARENT_ROM:
-		myPlayer->currConfig.environment = sid2_envTP;
+		myEngine->currConfig.environment = sid2_envTP;
 		break;
 
 	case XS_MPU_PLAYSID_ENVIRONMENT:
-		myPlayer->currConfig.environment = sid2_envPS;
+		myEngine->currConfig.environment = sid2_envPS;
 		break;
 
 	case XS_MPU_REAL:
 	default:
-		myPlayer->currConfig.environment = sid2_envR;
+		myEngine->currConfig.environment = sid2_envR;
 		break;
  }
 
@@ -257,64 +255,64 @@
  /* Clockspeed settings */
  switch (xs_cfg.clockSpeed) {
 	case XS_CLOCK_NTSC:
-		myPlayer->currConfig.clockSpeed = myPlayer->currConfig.clockDefault = SID2_CLOCK_NTSC;
+		myEngine->currConfig.clockSpeed = myEngine->currConfig.clockDefault = SID2_CLOCK_NTSC;
 		break;
 
 	case XS_CLOCK_PAL:
 	default:
-		myPlayer->currConfig.clockSpeed = myPlayer->currConfig.clockDefault = SID2_CLOCK_PAL;
+		myEngine->currConfig.clockSpeed = myEngine->currConfig.clockDefault = SID2_CLOCK_PAL;
 		break;
  }
 
 
  /* Configure rest of the emulation */
- myPlayer->currConfig.sidEmulation	= myPlayer->currBuilder;
- myPlayer->currConfig.clockForced	= xs_cfg.forceSpeed;
- myPlayer->currConfig.optimisation	= (xs_cfg.sid2OptLevel) ? 1 : 0;
- myPlayer->currConfig.sidDefault	= myPlayer->currConfig.sidModel = (xs_cfg.mos8580) ? SID2_MOS8580 : SID2_MOS6581;
- myPlayer->currConfig.sidSamples	= TRUE;	// FIXME FIX ME, make configurable!
- myPlayer->currConfig.precision		= myStatus->audioBitsPerSample;
- myPlayer->currConfig.frequency		= myStatus->audioFrequency; 
+ myEngine->currConfig.sidEmulation	= myEngine->currBuilder;
+ myEngine->currConfig.clockForced	= xs_cfg.forceSpeed;
+ myEngine->currConfig.optimisation	= (xs_cfg.sid2OptLevel) ? 1 : 0;
+ myEngine->currConfig.sidDefault	= myEngine->currConfig.sidModel = (xs_cfg.mos8580) ? SID2_MOS8580 : SID2_MOS6581;
+ myEngine->currConfig.sidSamples	= TRUE;	// FIXME FIX ME, make configurable!
+ myEngine->currConfig.precision		= myStatus->audioBitsPerSample;
+ myEngine->currConfig.frequency		= myStatus->audioFrequency; 
 
  switch (myStatus->audioBitsPerSample) {
  case XS_RES_8BIT:
 	myStatus->audioFormat 			= FMT_U8;
-	myPlayer->currConfig.sampleFormat	= SID2_LITTLE_UNSIGNED;
+	myEngine->currConfig.sampleFormat	= SID2_LITTLE_UNSIGNED;
 	break;
 
  case XS_RES_16BIT:
 	switch (myStatus->audioFormat) {
 	case FMT_U16_LE:
-		myPlayer->currConfig.sampleFormat	= SID2_LITTLE_UNSIGNED;
+		myEngine->currConfig.sampleFormat	= SID2_LITTLE_UNSIGNED;
 		break;
 
 	case FMT_U16_BE:
-		myPlayer->currConfig.sampleFormat	= SID2_BIG_UNSIGNED;
+		myEngine->currConfig.sampleFormat	= SID2_BIG_UNSIGNED;
 		break;
 
 	case FMT_U16_NE:
 		myStatus->audioFormat			= FMT_U16_NE;
 #ifdef WORDS_BIGENDIAN
-		myPlayer->currConfig.sampleFormat	= SID2_BIG_UNSIGNED;
+		myEngine->currConfig.sampleFormat	= SID2_BIG_UNSIGNED;
 #else
-		myPlayer->currConfig.sampleFormat	= SID2_LITTLE_UNSIGNED;
+		myEngine->currConfig.sampleFormat	= SID2_LITTLE_UNSIGNED;
 #endif
 		break;
 
 	case FMT_S16_LE:
-		myPlayer->currConfig.sampleFormat	= SID2_LITTLE_SIGNED;
+		myEngine->currConfig.sampleFormat	= SID2_LITTLE_SIGNED;
 		break;
 
 	case FMT_S16_BE:
-		myPlayer->currConfig.sampleFormat	= SID2_BIG_SIGNED;
+		myEngine->currConfig.sampleFormat	= SID2_BIG_SIGNED;
 		break;
 
 	default:
 		myStatus->audioFormat			= FMT_S16_NE;
 #ifdef WORDS_BIGENDIAN
-		myPlayer->currConfig.sampleFormat	= SID2_BIG_SIGNED;
+		myEngine->currConfig.sampleFormat	= SID2_BIG_SIGNED;
 #else
-		myPlayer->currConfig.sampleFormat	= SID2_LITTLE_SIGNED;
+		myEngine->currConfig.sampleFormat	= SID2_LITTLE_SIGNED;
 #endif
 		break;
 
@@ -324,7 +322,7 @@
 
 
  /* Now set the emulator configuration */
- if (myPlayer->currEng->config(myPlayer->currConfig) < 0)
+ if (myEngine->currEng->config(myEngine->currConfig) < 0)
 	{
 	XSERR("Emulator engine configuration failed!\n");
 	return FALSE;
@@ -348,8 +346,7 @@
 /*
  * Return song information
  */
-#define TFUNCTION1	xs_sidplay2_filetitle
-#define TFUNCTION2	xs_sidplay2_getsidinfo
+#define TFUNCTION	xs_sidplay2_getsidinfo
 #define TTUNEINFO	SidTuneInfo
 #define TTUNE		SidTune
 #include "xs_sidplay.h"
--- a/src/xs_sidplay2.h	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_sidplay2.h	Tue Dec 21 09:25:03 2004 +0000
@@ -3,6 +3,10 @@
 
 #include "xmms-sid.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 gboolean	xs_sidplay2_isourfile(gchar *);
 void		xs_sidplay2_close(t_xs_status *);
 gboolean	xs_sidplay2_init(t_xs_status *);
@@ -10,6 +14,9 @@
 guint		xs_sidplay2_fillbuffer(t_xs_status *, gchar *, guint);
 gboolean	xs_sidplay2_loadsid(t_xs_status *, gchar *);
 void		xs_sidplay2_deletesid(t_xs_status *);
-t_xs_tune*	xs_sidplay2_getsidinfo(gchar *);
+t_xs_tuneinfo*	xs_sidplay2_getsidinfo(gchar *);
 
+#ifdef __cplusplus
+}
+#endif
 #endif /* _XS_SIDPLAY2_H */
--- a/src/xs_stil.c	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_stil.c	Tue Dec 21 09:25:03 2004 +0000
@@ -21,6 +21,7 @@
 */
 #include "xs_stil.h"
 #include "xs_support.h"
+#include "xs_config.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -383,24 +384,100 @@
 }
 
 
-/* Get from STIL database
+/*
+ * These should be moved out of this module some day ...
  */
-t_xs_stil_node * xs_stildb_get(t_xs_stildb *db, gchar *hvscPath, gchar *pcFilename)
+static t_xs_stildb	*xs_stildb_db = NULL;
+XS_MUTEX(xs_stildb_db);
+
+gint xs_stil_init(void)
 {
+ XS_MUTEX_LOCK(xs_cfg);
+
+ if (!xs_cfg.stilDBPath)
+ 	{
+ 	XS_MUTEX_UNLOCK(xs_cfg);
+ 	return -1;
+ 	}
+
+ XS_MUTEX_LOCK(xs_stildb_db);
+ 
+ /* Check if already initialized */
+ if (xs_stildb_db) xs_stildb_free(xs_stildb_db);
+ 
+ /* Allocate database */
+ xs_stildb_db = (t_xs_stildb *) g_malloc0(sizeof(t_xs_stildb));
+ if (!xs_stildb_db)
+ 	{
+ 	XS_MUTEX_UNLOCK(xs_cfg);
+ 	XS_MUTEX_UNLOCK(xs_stildb_db);
+ 	return -2;
+ 	}
+ 
+ /* Read the database */
+ if (xs_stildb_read(xs_stildb_db, xs_cfg.stilDBPath) != 0)
+ 	{
+ 	xs_stildb_free(xs_stildb_db);
+ 	xs_stildb_db = NULL;
+ 	XS_MUTEX_UNLOCK(xs_cfg);
+ 	XS_MUTEX_UNLOCK(xs_stildb_db);
+ 	return -3;
+ 	}
+
+ /* Create index */
+ if (xs_stildb_index(xs_stildb_db) != 0)
+ 	{
+ 	xs_stildb_free(xs_stildb_db);
+ 	xs_stildb_db = NULL;
+ 	XS_MUTEX_UNLOCK(xs_cfg);
+ 	XS_MUTEX_UNLOCK(xs_stildb_db);
+ 	return -4;
+ 	}
+
+ XS_MUTEX_UNLOCK(xs_cfg);
+ XS_MUTEX_UNLOCK(xs_stildb_db);
+ return 0;
+}
+
+
+void xs_stil_close(void)
+{
+ XS_MUTEX_LOCK(xs_stildb_db);
+ xs_stildb_free(xs_stildb_db);
+ xs_stildb_db = NULL;
+ XS_MUTEX_UNLOCK(xs_stildb_db);
+}
+
+
+t_xs_stil_node * xs_stil_get(gchar *pcFilename)
+{
+ t_xs_stil_node *pResult;
  gchar *tmpFilename;
 
- /* Remove postfixed directory separator from HVSC-path */
- tmpFilename = xs_strrchr(hvscPath, '/');
- if (tmpFilename && (tmpFilename[1] == 0))
-	tmpFilename[0] = 0;
+ XS_MUTEX_LOCK(xs_stildb_db);
+ XS_MUTEX_LOCK(xs_cfg);
+
+ if (xs_cfg.hvscPath)
+ 	{
+ 	/* Remove postfixed directory separator from HVSC-path */
+ 	tmpFilename = xs_strrchr(xs_cfg.hvscPath, '/');
+ 	if (tmpFilename && (tmpFilename[1] == 0))
+ 		tmpFilename[0] = 0;
  
- /* Remove HVSC location-prefix from filename */
- tmpFilename = strstr(pcFilename, hvscPath);
- if (tmpFilename)
-	tmpFilename += strlen(hvscPath);
-	else
-	tmpFilename = pcFilename; 
+	/* Remove HVSC location-prefix from filename */
+	tmpFilename = strstr(pcFilename, xs_cfg.hvscPath);
+	if (tmpFilename)
+		tmpFilename += strlen(xs_cfg.hvscPath);
+		else
+		tmpFilename = pcFilename; 
+	} else
+	tmpFilename = pcFilename;
+	
+ pResult = xs_stildb_get_node(xs_stildb_db, tmpFilename);
 
- return xs_stildb_get_node(db, pcFilename);
+ XS_MUTEX_UNLOCK(xs_stildb_db);
+ XS_MUTEX_UNLOCK(xs_cfg);
+ 
+ return pResult;
 }
 
--- a/src/xs_stil.h	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_stil.h	Tue Dec 21 09:25:03 2004 +0000
@@ -39,6 +39,10 @@
 t_xs_stil_node *	xs_stildb_get(t_xs_stildb *, gchar *, gchar *);
 
 
+gint			xs_stil_init(void);
+void			xs_stil_close(void);
+t_xs_stil_node *	xs_stil_get(gchar *);
+
 #ifdef __cplusplus
 }
 #endif
--- a/src/xs_support.c	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_support.c	Tue Dec 21 09:25:03 2004 +0000
@@ -93,7 +93,7 @@
 
 /* Concatenates a given string into string pointed by *ppResult.
  */
-gint th_pstrcat(gchar **ppResult, const gchar *pStr)
+gint xs_pstrcat(gchar **ppResult, const gchar *pStr)
 {
  /* Check the string pointers */
  if (!ppResult || !pStr) return -1;
--- a/src/xs_title.c	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_title.c	Tue Dec 21 09:25:03 2004 +0000
@@ -45,8 +45,8 @@
 gchar *xs_make_titlestring(gchar *pcFilename,
 				gint iSubTune,
 				gint iSidModel,
-				gchar *formatString, gchar *infoString0,
-				gchar *infoString1, gchar *infoString2)
+				const gchar *formatString, const gchar *infoString0,
+				const gchar *infoString1, const gchar *infoString2)
 {
  gchar *tmpFilename, *tmpFilePath, *tmpFileExt, *pcStr, *pcResult,
  	tmpStr[VBUFSIZE], tmpBuf[VBUFSIZE];
--- a/src/xs_title.h	Sun Dec 19 16:57:01 2004 +0000
+++ b/src/xs_title.h	Tue Dec 21 09:25:03 2004 +0000
@@ -10,7 +10,7 @@
 /*
  * Functions
  */
-gchar *xs_make_titlestring(gchar *, gint, gint, gchar *, gchar *, gchar *, gchar *);
+gchar *xs_make_titlestring(gchar *, gint, gint, const gchar *, const gchar *, const gchar *, const gchar *);
 
 #ifdef __cplusplus
 }