changeset 392:b09d74eb71e6

Working on getting STIL and SLDB using completely dynamically allocated structures. Indentation cleanups, etc.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 31 May 2006 10:02:00 +0000
parents 3cc7455360ad
children 0844db548c06
files src/xmms-sid.c src/xmms-sid.h src/xs_config.c src/xs_config.h src/xs_fileinfo.c src/xs_filter.h src/xs_length.c src/xs_length.h src/xs_stil.c src/xs_stil.h src/xs_support.h src/xs_title.c
diffstat 12 files changed, 241 insertions(+), 172 deletions(-) [+]
line wrap: on
line diff
--- a/src/xmms-sid.c	Tue May 30 04:50:04 2006 +0000
+++ b/src/xmms-sid.c	Wed May 31 10:02:00 2006 +0000
@@ -99,7 +99,7 @@
 /*
  * Error messages
  */
-void XSERR(const char *fmt, ...)
+void xs_error(const char *fmt, ...)
 {
 	va_list ap;
 	fprintf(stderr, "XMMS-SID: ");
@@ -197,13 +197,13 @@
 	/* Initialize song-length database */
 	xs_songlen_close();
 	if (xs_cfg.songlenDBEnable && (xs_songlen_init() != 0)) {
-		XSERR("Error initializing song-length database!\n");
+		xs_error("Error initializing song-length database!\n");
 	}
 
 	/* Initialize STIL database */
 	xs_stil_close();
 	if (xs_cfg.stilDBEnable && (xs_stil_init() != 0)) {
-		XSERR("Error initializing STIL database!\n");
+		xs_error("Error initializing STIL database!\n");
 	}
 }
 
@@ -298,7 +298,6 @@
 	t_xs_status myStatus;
 	t_xs_tuneinfo *myTune;
 	gboolean audioOpen = FALSE, doPlay = FALSE, isFound = FALSE;
-	gboolean playedTune[XS_STIL_MAXENTRY + 1];
 	gint audioGot, songLength, i;
 	gchar *audioBuffer = NULL, *oversampleBuffer = NULL;
 
@@ -316,14 +315,14 @@
 	/* Allocate audio buffer */
 	audioBuffer = (gchar *) g_malloc(XS_AUDIOBUF_SIZE);
 	if (audioBuffer == NULL) {
-		XSERR("Couldn't allocate memory for audio data buffer!\n");
+		xs_error("Couldn't allocate memory for audio data buffer!\n");
 		goto xs_err_exit;
 	}
 
 	if (myStatus.oversampleEnable) {
 		oversampleBuffer = (gchar *) g_malloc(XS_AUDIOBUF_SIZE * myStatus.oversampleFactor);
 		if (oversampleBuffer == NULL) {
-			XSERR("Couldn't allocate memory for audio oversampling buffer!\n");
+			xs_error("Couldn't allocate memory for audio oversampling buffer!\n");
 			goto xs_err_exit;
 		}
 	}
@@ -396,7 +395,7 @@
 
 		/* Initialize song */
 		if (!myStatus.sidPlayer->plrInitSong(&myStatus)) {
-			XSERR("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n",
+			xs_error("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n",
 			      myTune->sidFilename, myStatus.currSong);
 			goto xs_err_exit;
 		}
@@ -405,7 +404,7 @@
 		/* Open the audio output */
 		if (!xs_plugin_ip.output->
 		    open_audio(myStatus.audioFormat, myStatus.audioFrequency, myStatus.audioChannels)) {
-			XSERR("Couldn't open XMMS audio output (fmt=%x, freq=%i, nchan=%i)!\n", myStatus.audioFormat,
+			xs_error("Couldn't open XMMS audio output (fmt=%x, freq=%i, nchan=%i)!\n", myStatus.audioFormat,
 			      myStatus.audioFrequency, myStatus.audioChannels);
 
 			XS_MUTEX_LOCK(xs_status);
@@ -443,7 +442,7 @@
 				/* Execute rate-conversion with filtering */
 				if (xs_filter_rateconv(audioBuffer, oversampleBuffer,
 						       myStatus.audioFormat, myStatus.oversampleFactor, audioGot) < 0) {
-					XSERR("Oversampling rate-conversion pass failed.\n");
+					xs_error("Oversampling rate-conversion pass failed.\n");
 					XS_MUTEX_LOCK(xs_status);
 					xs_status.isError = TRUE;
 					XS_MUTEX_UNLOCK(xs_status);
@@ -555,7 +554,7 @@
 
 	/* Start the playing thread! */
 	if (pthread_create(&xs_decode_thread, NULL, xs_playthread, NULL) < 0) {
-		XSERR("Couldn't start playing thread!\n");
+		xs_error("Couldn't start playing thread!\n");
 		xs_tuneinfo_free(xs_status.tuneInfo);
 		xs_status.tuneInfo = NULL;
 		xs_status.sidPlayer->plrDeleteSID(&xs_status);
@@ -937,13 +936,13 @@
 	/* Allocate structure */
 	pResult = (t_xs_tuneinfo *) g_malloc0(sizeof(t_xs_tuneinfo));
 	if (!pResult) {
-		XSERR("Could not allocate memory for t_xs_tuneinfo ('%s')\n", pcFilename);
+		xs_error("Could not allocate memory for t_xs_tuneinfo ('%s')\n", pcFilename);
 		return NULL;
 	}
 
 	pResult->sidFilename = g_strdup(pcFilename);
 	if (!pResult->sidFilename) {
-		XSERR("Could not allocate sidFilename ('%s')\n", pcFilename);
+		xs_error("Could not allocate sidFilename ('%s')\n", pcFilename);
 		g_free(pResult);
 		return NULL;
 	}
@@ -952,7 +951,7 @@
 	if (nsubTunes > 0) {
 		pResult->subTunes = g_malloc0(sizeof(t_xs_subtuneinfo) * nsubTunes);
 		if (!pResult->subTunes) {
-			XSERR("Could not allocate memory for t_xs_subtuneinfo ('%s', %i)\n", pcFilename, nsubTunes);
+			xs_error("Could not allocate memory for t_xs_subtuneinfo ('%s', %i)\n", pcFilename, nsubTunes);
 
 			g_free(pResult->sidFilename);
 			g_free(pResult);
--- a/src/xmms-sid.h	Tue May 30 04:50:04 2006 +0000
+++ b/src/xmms-sid.h	Wed May 31 10:02:00 2006 +0000
@@ -95,8 +95,6 @@
 
 #define XS_BIN_BAILOUT		(32)	/* Binary search bailout treshold */
 
-#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 */
@@ -134,6 +132,7 @@
 	gint		tuneSpeed;
 	gint		tuneLength;
 	gchar		*tuneTitle;
+	gboolean	tunePlayed;
 } t_xs_subtuneinfo;
 
 
--- a/src/xs_config.c	Tue May 30 04:50:04 2006 +0000
+++ b/src/xs_config.c	Wed May 31 10:02:00 2006 +0000
@@ -307,7 +307,7 @@
 			break;
 
 		default:
-			XSERR
+			xs_error
 			    ("Internal: Unsupported setting type found while reading configuration file. Please report to author!\n");
 			break;
 		}
@@ -372,7 +372,7 @@
 			break;
 
 		default:
-			XSERR
+			xs_error
 			    ("Internal: Unsupported setting type found while writing configuration file. Please report to author!\n");
 			break;
 		}
--- a/src/xs_config.h	Tue May 30 04:50:04 2006 +0000
+++ b/src/xs_config.h	Wed May 31 10:02:00 2006 +0000
@@ -1,5 +1,5 @@
-#ifndef XS_CONFIG_H
-#define XS_CONFIG_H
+#ifndef _XS_CONFIG_H
+#define _XS_CONFIG_H
 
 #include "xmms-sid.h"
 
@@ -164,4 +164,4 @@
 #ifdef __cplusplus
 }
 #endif
-#endif /* XS_CONFIG_H */
+#endif /* _XS_CONFIG_H */
--- a/src/xs_fileinfo.c	Tue May 30 04:50:04 2006 +0000
+++ b/src/xs_fileinfo.c	Wed May 31 10:02:00 2006 +0000
@@ -131,22 +131,24 @@
 	gtk_text_set_point(GTK_TEXT(tmpText), 0);
 	gtk_text_forward_delete(GTK_TEXT(tmpText), gtk_text_get_length(GTK_TEXT(tmpText)));
 
-	if (xs_fileinfostil) {
-		/* Get subtune number */
-		tmpItem = gtk_menu_get_active(GTK_MENU(data));
-		tmpIndex = g_list_index(GTK_MENU_SHELL(data)->children, tmpItem);
+	/* Get subtune information */
+	tmpItem = gtk_menu_get_active(GTK_MENU(data));
+	tmpIndex = g_list_index(GTK_MENU_SHELL(data)->children, tmpItem);
 
-		/* Get subtune information */
-		tmpNode = &xs_fileinfostil->subTunes[tmpIndex];
+	if (xs_fileinfostil)
+		tmpNode = xs_fileinfostil->subTunes[tmpIndex];
+	else
+		tmpNode = NULL;
+
+	if (tmpNode) {
 		subName = tmpNode->pName;
 		subAuthor = tmpNode->pAuthor;
 
-		/* Put in the new text, if available */
 		if (tmpNode->pInfo) {
-			gtk_text_insert(GTK_TEXT(tmpText), NULL, NULL, NULL, tmpNode->pInfo, strlen(tmpNode->pInfo));
+			gtk_text_insert(GTK_TEXT(tmpText), NULL, NULL, NULL,
+				tmpNode->pInfo, strlen(tmpNode->pInfo));
 		}
 	} else {
-		/* We don't have any information */
 		subName = NULL;
 		subAuthor = NULL;
 	}
@@ -223,10 +225,12 @@
 	for (n = 1; n <= tmpInfo->nsubTunes; n++) {
 		if (xs_fileinfostil) {
 			snprintf(tmpStr, sizeof(tmpStr), "Tune #%i: ", n);
-			tmpNode = &xs_fileinfostil->subTunes[n];
-			if (tmpNode->pName)
+			
+			tmpNode = xs_fileinfostil->subTunes[n];
+			
+			if (tmpNode && tmpNode->pName)
 				xs_pnstrcat(tmpStr, sizeof(tmpStr), tmpNode->pName);
-			else if (tmpNode->pInfo)
+			else if (tmpNode && tmpNode->pInfo)
 				xs_pnstrcat(tmpStr, sizeof(tmpStr), tmpNode->pInfo);
 			else
 				xs_pnstrcat(tmpStr, sizeof(tmpStr), "---");
--- a/src/xs_filter.h	Tue May 30 04:50:04 2006 +0000
+++ b/src/xs_filter.h	Wed May 31 10:02:00 2006 +0000
@@ -1,5 +1,5 @@
-#ifndef XS_FILTER_H
-#define XS_FILTER_H
+#ifndef _XS_FILTER_H
+#define _XS_FILTER_H
 
 #include "xmms-sid.h"
 
@@ -18,4 +18,4 @@
 #ifdef __cplusplus
 }
 #endif
-#endif /* XS_FILTER_H */
+#endif /* _XS_FILTER_H */
--- a/src/xs_length.c	Tue May 30 04:50:04 2006 +0000
+++ b/src/xs_length.c	Wed May 31 10:02:00 2006 +0000
@@ -29,25 +29,13 @@
 #include <string.h>
 
 
-/* Database handling functions
+/* Free memory allocated for given SLDB node
  */
-static t_xs_sldb_node *xs_sldb_node_new(void)
-{
-	t_xs_sldb_node *pResult;
-
-	/* Allocate memory for new node */
-	pResult = (t_xs_sldb_node *) g_malloc0(sizeof(t_xs_sldb_node));
-	if (!pResult)
-		return NULL;
-
-	return pResult;
-}
-
-
-static void xs_sldb_node_free(t_xs_sldb_node * pNode)
+static void xs_sldb_node_free(t_xs_sldb_node *pNode)
 {
 	if (pNode) {
 		/* Nothing much to do here ... */
+		g_free(pNode->sLengths);
 		g_free(pNode);
 	}
 }
@@ -55,7 +43,7 @@
 
 /* Insert given node to db linked list
  */
-static void xs_sldb_node_insert(t_xs_sldb * db, t_xs_sldb_node * pNode)
+static void xs_sldb_node_insert(t_xs_sldb *db, t_xs_sldb_node *pNode)
 {
 	assert(db);
 
@@ -73,9 +61,9 @@
 }
 
 
-/* Parses a time-entry in SLDB format
+/* Parse a time-entry in SLDB format
  */
-static gint xs_sldb_gettime(gchar * pcStr, size_t * piPos)
+static gint xs_sldb_gettime(gchar *pcStr, gint *piPos)
 {
 	gint iResult, iTemp;
 
@@ -111,37 +99,32 @@
 }
 
 
+/* Parse one SLDB definition line, return SLDB node
+ */
 t_xs_sldb_node * xs_sldb_read_entry(gchar *inLine)
 {
-	size_t linePos, savePos, tmpI, tmpLen;
+	gint linePos, savePos, i, tmpLen;
+	gboolean iOK;
 	t_xs_sldb_node *tmpNode;
 
 	/* Allocate new node */
-	if ((tmpNode = xs_sldb_node_new()) == NULL) {
-		XSERR("Error allocating new node. Fatal error.\n");
+	tmpNode = (t_xs_sldb_node *) g_malloc0(sizeof(t_xs_sldb_node));
+	if (!tmpNode) {
+		xs_error("Error allocating new node. Fatal error.\n");
 		return NULL;
 	}
 
 	/* Get hash value */
-#if (XS_MD5HASH_LENGTH != 16)
-#error Mismatch in hashcode length. Check against xs_md5.h and fix here.
-#endif
-	sscanf(&inLine[0], "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
-	       (guint *) & (tmpNode->md5Hash[0]), (guint *) & (tmpNode->md5Hash[1]),
-	       (guint *) & (tmpNode->md5Hash[2]), (guint *) & (tmpNode->md5Hash[3]),
-	       (guint *) & (tmpNode->md5Hash[4]), (guint *) & (tmpNode->md5Hash[5]),
-	       (guint *) & (tmpNode->md5Hash[6]), (guint *) & (tmpNode->md5Hash[7]),
-	       (guint *) & (tmpNode->md5Hash[8]), (guint *) & (tmpNode->md5Hash[9]),
-	       (guint *) & (tmpNode->md5Hash[10]), (guint *) & (tmpNode->md5Hash[11]),
-	       (guint *) & (tmpNode->md5Hash[12]), (guint *) & (tmpNode->md5Hash[13]),
-	       (guint *) & (tmpNode->md5Hash[14]), (guint *) & (tmpNode->md5Hash[15]));
-
+	linePos = 0;
+	for (i = 0; i < XS_MD5HASH_LENGTH; i++, linePos += 2) {
+		sscanf(&inLine[linePos], "%2x",
+		(guint *) &(tmpNode->md5Hash[i]));
+	}
+		
 	/* Get playtimes */
 	if (inLine[linePos] != 0) {
 		if (inLine[linePos] != '=') {
-			XSERR("'=' expected in SongLengthDB file '%s' line #%d, column #%d\n",
-				dbFilename, lineNum, linePos);
-
+			xs_error("'=' expected on column #%d.\n", linePos);
 			xs_sldb_node_free(tmpNode);
 			return NULL;
 		} else {
@@ -160,7 +143,7 @@
 			}
 			
 			if (!iOK) {
-				XSERR("Invalid plaaplaa\n");
+				xs_error("Invalid sub-tune length.\n");
 				xs_sldb_node_free(tmpNode);
 				return NULL;
 			}
@@ -168,19 +151,21 @@
 			/* Allocate memory for lengths */
 			tmpNode->sLengths = (gint *) g_malloc0(tmpNode->nLengths * sizeof(gint));
 			if (!tmpNode->sLengths) {
-				XSERR("Could not allocate memory for SongLengthDB entry.\n");
+				xs_error("Could not allocate memory for node.\n");
 				xs_sldb_node_free(tmpNode);
 				return NULL;
 			}
 			
 			/* Read lengths in */
-			tmpI = 0; linePos = savePos; iOK = TRUE;
+			i = 0;
+			linePos = savePos;
+			iOK = TRUE;
 			while ((linePos < tmpLen) && iOK) {
 				xs_findnext(inLine, &linePos);
 
-				if (tmpI < tmpNode->nLengths) {
-					tmpNode->sLengths[tmpI] = xs_sldb_gettime(inLine, &linePos);
-					tmpI++;
+				if (i < tmpNode->nLengths) {
+					tmpNode->sLengths[i] = xs_sldb_gettime(inLine, &linePos);
+					i++;
 				} else
 					iOK = FALSE;
 			}
@@ -199,18 +184,17 @@
 
 /* Read database to memory
  */
-gint xs_sldb_read(t_xs_sldb * db, gchar * dbFilename)
+gint xs_sldb_read(t_xs_sldb *db, gchar *dbFilename)
 {
 	FILE *inFile;
 	gchar inLine[XS_BUF_SIZE];
-	size_t lineNum, linePos;
-	gboolean iOK;
+	gint lineNum;
 	t_xs_sldb_node *tmpNode;
 	assert(db);
 
 	/* Try to open the file */
 	if ((inFile = fopen(dbFilename, "ra")) == NULL) {
-		XSERR("Could not open SongLengthDB '%s'\n", dbFilename);
+		xs_error("Could not open SongLengthDB '%s'\n", dbFilename);
 		return -1;
 	}
 
@@ -218,6 +202,7 @@
 	lineNum = 0;
 
 	while (!feof(inFile)) {
+		gint linePos;
 		fgets(inLine, XS_BUF_SIZE, inFile);
 		inLine[XS_BUF_SIZE - 1] = 0;
 		linePos = 0;
@@ -225,20 +210,25 @@
 
 		/* Check if it is datafield */
 		if (isxdigit(inLine[linePos])) {
-			size_t tmpI;
+			/* Check the length of the hash */
+			gint hashLen;
+			for (hashLen = 0; isxdigit(inLine[linePos]); hashLen++, linePos++);
 
-			/* Check the length of the hash */
-			for (tmpI = 0; isxdigit(inLine[linePos]); linePos++, tmpI++);
-
-			if (tmpI != XS_MD5HASH_LENGTH_CH) {
-				XSERR("Invalid hash in SongLengthDB file '%s' line #%d!\n", dbFilename, lineNum);
+			if (hashLen != XS_MD5HASH_LENGTH_CH) {
+				xs_error("Invalid MD5-hash in SongLengthDB file '%s' line #%d!\n",
+					dbFilename, lineNum);
 			} else {
 				/* Parse and add node to db */
-				if ((tmpNode = xs_sldb_read_entry(inLine)) != NULL)
+				if ((tmpNode = xs_sldb_read_entry(inLine)) != NULL) {
 					xs_sldb_node_insert(db, tmpNode);
+				} else {
+					xs_error("Invalid entry in SongLengthDB file '%s' line #%d!\n",
+						dbFilename, lineNum);
+				}
 			}
-		} else if ((inLine[0] != ';') && (inLine[0] != '[')) {
-			XSERR("Invalid line in SongLengthDB file '%s' line #%d\n", dbFilename, lineNum);
+		} else if ((inLine[linePos] != ';') && (inLine[linePos] != '[')) {
+			xs_error("Invalid line in SongLengthDB file '%s' line #%d\n",
+				dbFilename, lineNum);
 		}
 
 	}
@@ -257,13 +247,13 @@
  */
 static gint xs_sldb_cmphash(t_xs_md5hash testHash1, t_xs_md5hash testHash2)
 {
-	register gint i, res = 0;
+	gint i, d;
 
 	/* Compute difference of hashes */
-	for (i = 0; (i < XS_MD5HASH_LENGTH) && (!res); i++)
-		res = (testHash1[i] - testHash2[i]);
+	for (i = 0, d = 0; (i < XS_MD5HASH_LENGTH) && !d; i++)
+		d = (testHash1[i] - testHash2[i]);
 
-	return res;
+	return d;
 }
 
 
@@ -445,11 +435,7 @@
 	t_xs_md5state inState;
 	t_xs_psidv1_header psidH;
 	t_xs_psidv2_header psidH2;
-#ifdef XS_BUF_DYNAMIC
 	guint8 *songData;
-#else
-	guint8 songData[XS_SIDBUF_SIZE];
-#endif
 	guint8 ib8[2], i8;
 	gint iIndex, iRes;
 
@@ -487,14 +473,12 @@
 		psidH2.reserved = xs_rd_be16(inFile);
 	}
 
-#ifdef XS_BUF_DYNAMIC
 	/* Allocate buffer */
 	songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE * sizeof(guint8));
 	if (!songData) {
 		fclose(inFile);
 		return -3;
 	}
-#endif
 
 	/* Read data to buffer */
 	iRes = fread(songData, sizeof(guint8), XS_SIDBUF_SIZE, inFile);
@@ -511,10 +495,8 @@
 		xs_md5_append(&inState, songData, iRes);
 	}
 
-#ifdef XS_BUF_DYNAMIC
 	/* Free buffer */
 	g_free(songData);
-#endif
 
 	/* Append header data to hash */
 #define XSADDHASH(QDATAB) { ib8[0] = (QDATAB & 0xff); ib8[1] = (QDATAB >> 8); xs_md5_append(&inState, (guint8 *) &ib8, sizeof(ib8)); }
@@ -553,7 +535,7 @@
 
 /* Get song lengths
  */
-t_xs_sldb_node *xs_sldb_get(t_xs_sldb * db, gchar * pcFilename)
+t_xs_sldb_node *xs_sldb_get(t_xs_sldb *db, gchar *pcFilename)
 {
 	t_xs_sldb_node *pResult;
 	t_xs_md5hash dbHash;
--- a/src/xs_length.h	Tue May 30 04:50:04 2006 +0000
+++ b/src/xs_length.h	Wed May 31 10:02:00 2006 +0000
@@ -1,5 +1,5 @@
-#ifndef XS_LENGTH_H
-#define XS_LENGTH_H
+#ifndef _XS_LENGTH_H
+#define _XS_LENGTH_H
 
 #include "xmms-sid.h"
 #include "xs_md5.h"
@@ -14,12 +14,11 @@
 typedef struct _t_xs_sldb_node {
 	t_xs_md5hash	md5Hash;	/* 128-bit MD5 hash-digest */
 	gint		nLengths;	/* Number of lengths */
-	gint32		sLengths[XS_STIL_MAXENTRY+1];
-					/* Lengths in seconds */
-
+	gint		*sLengths;	/* Lengths in seconds */
 	struct _t_xs_sldb_node *pPrev, *pNext;
 } t_xs_sldb_node;
 
+
 typedef struct {
 	t_xs_sldb_node	*pNodes,
 			**ppIndex;
@@ -43,4 +42,4 @@
 #ifdef __cplusplus
 }
 #endif
-#endif /* XS_LENGTH_H */
+#endif /* _XS_LENGTH_H */
--- a/src/xs_stil.c	Tue May 30 04:50:04 2006 +0000
+++ b/src/xs_stil.c	Wed May 31 10:02:00 2006 +0000
@@ -26,11 +26,69 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
+#include <stdarg.h>
 
 
 /* Database handling functions
  */
-static t_xs_stil_node *xs_stildb_node_new(gchar * pcFilename)
+static gboolean xs_stildb_node_realloc(t_xs_stil_node *pNode, gint nsubTunes)
+{
+	if (!pNode) return FALSE;
+	
+	/* Re-allocate subTune structure if needed */
+	if (nsubTunes >= pNode->nsubTunes) {
+		pNode->subTunes =
+			(t_xs_stil_subnode **) g_realloc(pNode->subTunes,
+			(nsubTunes + 1) * sizeof(t_xs_stil_subnode **));
+
+		if (!pNode->subTunes)
+			return FALSE;
+		
+		/* Clear the newly allocated memory */
+		memset(&(pNode->subTunes[pNode->nsubTunes]), 0,
+			(nsubTunes + 1 - pNode->nsubTunes) *
+			sizeof(t_xs_stil_subnode **));
+	}
+			
+	/* Allocate memory for subTune */
+	if (!pNode->subTunes[nsubTunes]) {
+		pNode->subTunes[nsubTunes] = (t_xs_stil_subnode *)
+			g_malloc0(sizeof(t_xs_stil_subnode));
+		
+		if (!pNode->subTunes[nsubTunes])
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+static void xs_stildb_node_free(t_xs_stil_node *pNode)
+{
+	gint i;
+	t_xs_stil_subnode *pSub;
+
+	if (pNode) {
+		/* Free subtune information */
+		for (i = 0; i < pNode->nsubTunes; i++) {
+			pSub = pNode->subTunes[i];
+			if (pSub) {
+				g_free(pSub->pName);
+				g_free(pSub->pAuthor);
+				g_free(pSub->pInfo);
+
+				g_free(pSub);
+			}
+		}
+		
+		g_free(pNode->subTunes);
+		g_free(pNode->pcFilename);
+		g_free(pNode);
+	}
+}
+
+
+static t_xs_stil_node *xs_stildb_node_new(gchar *pcFilename)
 {
 	t_xs_stil_node *pResult;
 
@@ -39,37 +97,20 @@
 	if (!pResult)
 		return NULL;
 
+	/* Allocate filename and initial space for one subtune */
 	pResult->pcFilename = g_strdup(pcFilename);
-	if (!pResult->pcFilename) {
-		g_free(pResult);
+	if (!pResult->pcFilename || !xs_stildb_node_realloc(pResult, 1)) {
+		xs_stildb_node_free(pResult);
 		return NULL;
 	}
-
+	
 	return pResult;
 }
 
 
-static void xs_stildb_node_free(t_xs_stil_node * pNode)
-{
-	gint i;
-
-	if (pNode) {
-		/* Free subtune information */
-		for (i = 0; i <= XS_STIL_MAXENTRY; i++) {
-			g_free(pNode->subTunes[i].pName);
-			g_free(pNode->subTunes[i].pAuthor);
-			g_free(pNode->subTunes[i].pInfo);
-		}
-
-		g_free(pNode->pcFilename);
-		g_free(pNode);
-	}
-}
-
-
 /* Insert given node to db linked list
  */
-static void xs_stildb_node_insert(t_xs_stildb * db, t_xs_stil_node * pNode)
+static void xs_stildb_node_insert(t_xs_stildb *db, t_xs_stil_node *pNode)
 {
 	assert(db);
 
@@ -89,10 +130,24 @@
 
 /* Read database (additively) to given db-structure
  */
-#define XS_STILDB_MULTI if (isMulti) { isMulti = FALSE; xs_pstrcat(&(tmpNode->subTunes[subEntry].pInfo), "\n"); }
+#define XS_STILDB_MULTI							\
+	if (isMulti) {							\
+		isMulti = FALSE;					\
+		xs_pstrcat(&(tmpNode->subTunes[subEntry]->pInfo), "\n");\
+	}
 
+void XS_STILDB_ERR(gint lineNum, gchar *inLine, const char *fmt, ...)
+{
+	va_list ap;
 
-gint xs_stildb_read(t_xs_stildb * db, gchar * dbFilename)
+	va_start(ap, fmt);
+	xs_error(fmt, ap);
+	va_end(ap);
+	
+	fprintf(stderr, "#%d: '%s'\n", lineNum, inLine);
+}
+
+gint xs_stildb_read(t_xs_stildb *db, gchar *dbFilename)
 {
 	FILE *inFile;
 	gchar inLine[XS_BUF_SIZE + 16];	/* Since we add some chars here and there */
@@ -104,7 +159,7 @@
 
 	/* Try to open the file */
 	if ((inFile = fopen(dbFilename, "ra")) == NULL) {
-		XSERR("Could not open STILDB '%s'\n", dbFilename);
+		xs_error("Could not open STILDB '%s'\n", dbFilename);
 		return -1;
 	}
 
@@ -128,9 +183,9 @@
 			/* Check if we are already parsing entry */
 			isMulti = FALSE;
 			if (tmpNode) {
-				XSERR("New entry ('%s') before end of current ('%s')! Possibly malformed STIL-file!\n",
-				      inLine, tmpNode->pcFilename);
-
+				XS_STILDB_ERR(lineNum, inLine,
+					"New entry found before end of current ('%s')!\n",
+					tmpNode->pcFilename);
 				xs_stildb_node_free(tmpNode);
 			}
 
@@ -139,7 +194,8 @@
 			tmpNode = xs_stildb_node_new(inLine);
 			if (!tmpNode) {
 				/* Allocation failed */
-				XSERR("Could not allocate new STILdb-node for '%s'!\n", inLine);
+				XS_STILDB_ERR(lineNum, inLine,
+					"Could not allocate new STILdb-node!\n");
 				isError = TRUE;
 			}
 			break;
@@ -156,12 +212,16 @@
 					subEntry = atol(&inLine[2]);
 
 					/* Sanity check */
-					if ((subEntry < 1) || (subEntry > XS_STIL_MAXENTRY)) {
-						XSERR("Number of subEntry (%i) for '%s' is invalid\n", subEntry,
-						      tmpNode->pcFilename);
+					if (subEntry < 1) {
+						XS_STILDB_ERR(lineNum, inLine,
+							"Number of subEntry (%i) for '%s' is invalid\n",
+							subEntry, tmpNode->pcFilename);
 						subEntry = 0;
 					}
 				}
+			} else {
+				XS_STILDB_ERR(lineNum, inLine,
+					"Syntax error, expected subEntry number.\n");
 			}
 
 			break;
@@ -182,30 +242,48 @@
 		default:
 			/* Check if we are parsing an entry */
 			if (!tmpNode) {
-				XSERR("Entry data encountered outside of entry!\n");
+				XS_STILDB_ERR(lineNum, inLine,
+					"Entry data encountered outside of entry or syntax error!\n");
 				break;
 			}
 
+			if (xs_stildb_node_realloc(tmpNode, subEntry)) {
+				XS_STILDB_ERR(lineNum, inLine,
+					"Could not (re)allocate memory for subEntries!\n");
+				isError = TRUE;
+				break;
+			}
+			
 			/* Some other type */
 			if (strncmp(inLine, "   NAME:", 8) == 0) {
-				XS_STILDB_MULTI g_free(tmpNode->subTunes[subEntry].pName);
-				tmpNode->subTunes[subEntry].pName = g_strdup(&inLine[9]);
+				XS_STILDB_MULTI;
+				g_free(tmpNode->subTunes[subEntry]->pName);
+				tmpNode->subTunes[subEntry]->pName = g_strdup(&inLine[9]);
 			} else if (strncmp(inLine, " AUTHOR:", 8) == 0) {
-				XS_STILDB_MULTI g_free(tmpNode->subTunes[subEntry].pAuthor);
-				tmpNode->subTunes[subEntry].pAuthor = g_strdup(&inLine[9]);
+				XS_STILDB_MULTI;
+				g_free(tmpNode->subTunes[subEntry]->pAuthor);
+				tmpNode->subTunes[subEntry]->pAuthor = g_strdup(&inLine[9]);
 			} else if (strncmp(inLine, "  TITLE:", 8) == 0) {
-				XS_STILDB_MULTI inLine[eolPos++] = '\n';
+				XS_STILDB_MULTI;
+				inLine[eolPos++] = '\n';
 				inLine[eolPos++] = 0;
-				xs_pstrcat(&(tmpNode->subTunes[subEntry].pInfo), &inLine[2]);
+				xs_pstrcat(&(tmpNode->subTunes[subEntry]->pInfo), &inLine[2]);
 			} else if (strncmp(inLine, " ARTIST:", 8) == 0) {
-				XS_STILDB_MULTI inLine[eolPos++] = '\n';
+				XS_STILDB_MULTI;
+				inLine[eolPos++] = '\n';
 				inLine[eolPos++] = 0;
-				xs_pstrcat(&(tmpNode->subTunes[subEntry].pInfo), &inLine[1]);
+				xs_pstrcat(&(tmpNode->subTunes[subEntry]->pInfo), &inLine[1]);
 			} else if (strncmp(inLine, "COMMENT:", 8) == 0) {
-				XS_STILDB_MULTI isMulti = TRUE;
-				xs_pstrcat(&(tmpNode->subTunes[subEntry].pInfo), inLine);
+				XS_STILDB_MULTI;
+				isMulti = TRUE;
+				xs_pstrcat(&(tmpNode->subTunes[subEntry]->pInfo), inLine);
 			} else if (strncmp(inLine, "        ", 8) == 0) {
-				xs_pstrcat(&(tmpNode->subTunes[subEntry].pInfo), &inLine[8]);
+				if (isMulti) {
+					xs_pstrcat(&(tmpNode->subTunes[subEntry]->pInfo), &inLine[8]);
+				} else {
+					XS_STILDB_ERR(lineNum, inLine,
+					"Entry continuation found when isMulti == FALSE.\n");
+				}
 			}
 			break;
 		}
@@ -228,13 +306,15 @@
 static gint xs_stildb_cmp(const void *pNode1, const void *pNode2)
 {
 	/* We assume here that we never ever get NULL-pointers or similar */
-	return strcmp((*(t_xs_stil_node **) pNode1)->pcFilename, (*(t_xs_stil_node **) pNode2)->pcFilename);
+	return strcmp(
+		(*(t_xs_stil_node **) pNode1)->pcFilename,
+		(*(t_xs_stil_node **) pNode2)->pcFilename);
 }
 
 
 /* (Re)create index
  */
-gint xs_stildb_index(t_xs_stildb * db)
+gint xs_stildb_index(t_xs_stildb *db)
 {
 	t_xs_stil_node *pCurr;
 	gint i;
@@ -275,9 +355,10 @@
 	return 0;
 }
 
+
 /* Free a given STIL database
  */
-void xs_stildb_free(t_xs_stildb * db)
+void xs_stildb_free(t_xs_stildb *db)
 {
 	t_xs_stil_node *pCurr, *pNext;
 
@@ -308,7 +389,7 @@
 
 /* Get STIL information node from database
  */
-static t_xs_stil_node *xs_stildb_get_node(t_xs_stildb * db, gchar * pcFilename)
+static t_xs_stil_node *xs_stildb_get_node(t_xs_stildb *db, gchar *pcFilename)
 {
 	gint iStartNode, iEndNode, iQNode, r, i;
 	gboolean iFound;
@@ -426,7 +507,7 @@
 }
 
 
-t_xs_stil_node *xs_stil_get(gchar * pcFilename)
+t_xs_stil_node *xs_stil_get(gchar *pcFilename)
 {
 	t_xs_stil_node *pResult;
 	gchar *tmpFilename;
--- a/src/xs_stil.h	Tue May 30 04:50:04 2006 +0000
+++ b/src/xs_stil.h	Wed May 31 10:02:00 2006 +0000
@@ -1,5 +1,5 @@
-#ifndef XS_STIL_H
-#define XS_STIL_H
+#ifndef _XS_STIL_H
+#define _XS_STIL_H
 
 #include "xmms-sid.h"
 
@@ -16,9 +16,12 @@
 		*pInfo;
 } t_xs_stil_subnode;
 
+
 typedef struct _t_xs_stil_node {
 	gchar			*pcFilename;
-	t_xs_stil_subnode	subTunes[XS_STIL_MAXENTRY+1];
+	gint			nsubTunes;
+	t_xs_stil_subnode	**subTunes;
+	
 	struct _t_xs_stil_node	*pPrev, *pNext;
 } t_xs_stil_node;
 
@@ -46,4 +49,4 @@
 #ifdef __cplusplus
 }
 #endif
-#endif /* XS_STIL_H */
+#endif /* _XS_STIL_H */
--- a/src/xs_support.h	Tue May 30 04:50:04 2006 +0000
+++ b/src/xs_support.h	Wed May 31 10:02:00 2006 +0000
@@ -1,5 +1,5 @@
-#ifndef XS_SUPPORT_H
-#define XS_SUPPORT_H
+#ifndef _XS_SUPPORT_H
+#define _XS_SUPPORT_H
 
 #ifdef __cplusplus
 extern "C" {
@@ -45,4 +45,4 @@
 #ifdef __cplusplus
 }
 #endif
-#endif /* XS_SUPPORT_H */
+#endif /* _XS_SUPPORT_H */
--- a/src/xs_title.c	Tue May 30 04:50:04 2006 +0000
+++ b/src/xs_title.c	Wed May 31 10:02:00 2006 +0000
@@ -30,23 +30,25 @@
  * Create a title string based on given information and settings.
  */
 #define VPUTCH(MCH)	\
-if (iIndex < XS_BUF_SIZE) tmpBuf[iIndex++] = MCH;
+	if (iIndex < XS_BUF_SIZE) tmpBuf[iIndex++] = MCH;
+
 #define VPUTSTR(MSTR) {						\
 	if (MSTR) {						\
 		if ((iIndex + strlen(MSTR) + 1) < XS_BUF_SIZE) {	\
 			strcpy(&tmpBuf[iIndex], MSTR);		\
 			iIndex += strlen(MSTR); 		\
-			} else					\
+		} else						\
 			iIndex = XS_BUF_SIZE;			\
-		}						\
-	}
+	}							\
+}
 
 
 gchar *xs_make_titlestring(gchar * pcFilename, gint iSubTune, gint nSubTunes, gint iSidModel,
 			   const gchar * formatString, const gchar * infoString0,
 			   const gchar * infoString1, const gchar * infoString2)
 {
-	gchar *tmpFilename, *tmpFilePath, *tmpFileExt, *pcStr, *pcResult, tmpStr[XS_BUF_SIZE], tmpBuf[XS_BUF_SIZE];
+	gchar *tmpFilename, *tmpFilePath, *tmpFileExt, *pcStr,
+		*pcResult, tmpStr[XS_BUF_SIZE], tmpBuf[XS_BUF_SIZE];
 	gint iIndex;
 #ifdef HAVE_XMMSEXTRA
 	TitleInput *ptInput;