changeset 227:92bad4c7b998

Improved modularization of STIL and song-length database subsystems.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 19 Dec 2004 16:53:05 +0000
parents 858c09f59011
children a9a5924eb10c
files src/xs_length.c src/xs_length.h src/xs_stil.c src/xs_stil.h
diffstat 4 files changed, 312 insertions(+), 324 deletions(-) [+]
line wrap: on
line diff
--- a/src/xs_length.c	Sun Dec 19 15:25:03 2004 +0000
+++ b/src/xs_length.c	Sun Dec 19 16:53:05 2004 +0000
@@ -21,25 +21,15 @@
 */
 #include "xs_length.h"
 #include "xs_support.h"
-#include "xs_config.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
 
 
-/*
- * Pointer to database in memory
+/* Database handling functions
  */
-static t_xs_sldb_node	*xs_sldb = NULL;
-static t_xs_sldb_node	**xs_sldbi = NULL;
-static gint		xs_sldbn   = 0;
-
-
-/*
- * Hash-database handling functions
- */
-t_xs_sldb_node *xs_sldb_node_new(void)
+static t_xs_sldb_node *xs_sldb_node_new(void)
 {
  t_xs_sldb_node *pResult;
  
@@ -51,124 +41,40 @@
 }
 
 
-void xs_sldb_node_free(t_xs_sldb_node *pNode)
+static void xs_sldb_node_free(t_xs_sldb_node *pNode)
 {
- if (pNode) g_free(pNode);
+ if (pNode)
+ 	{
+ 	/* Nothing much to do here ... */
+ 	g_free(pNode);
+ 	}
 }
 
 
-/*
- * Insert given node to db linked list
+/* Insert given node to db linked list
  */
-#define LPREV	(pNode->pPrev)
-#define LTHIS	(pNode)
-#define LNEXT	(pNode->pNext)
-
-void xs_sldb_node_insert(t_xs_sldb_node *pNode)
+static void xs_sldb_node_insert(t_xs_sldb *db, t_xs_sldb_node *pNode)
 {
- if (xs_sldb)
+ assert(db);
+ 
+ if (db->pNodes)
  	{
  	/* The first node's pPrev points to last node */
-	LPREV = xs_sldb->pPrev;		/* New node's prev = Previous last node */
-	xs_sldb->pPrev->pNext = pNode;	/* Previous last node's next = New node */
-	xs_sldb->pPrev = pNode;		/* New last node = New node */
+	LPREV = db->pNodes->pPrev;		/* New node's prev = Previous last node */
+	db->pNodes->pPrev->pNext = pNode;	/* Previous last node's next = New node */
+	db->pNodes->pPrev = pNode;		/* New last node = New node */
 	LNEXT = NULL;				/* But next is NULL! */
  	} else {
- 	xs_sldb = pNode;			/* First node ... */
+ 	db->pNodes = pNode;			/* First node ... */
  	LPREV = pNode;				/* ... it's also last */
  	LNEXT = NULL;				/* But next is NULL! */
  	}
 }
 
 
-/*
- * Compare two given MD5-hashes.
- * Return: 0 if equal
- *         negative if testHash1 < testHash2
- *         positive if testHash1 > testHash2
- */
-gint xs_sldb_cmphash(t_xs_md5hash testHash1, t_xs_md5hash testHash2)
-{
- register gint i, res = 0;
-  
- /* Compute difference of hashes */
- for (i = 0; (i < XS_MD5HASH_LENGTH) && (!res); i++)
- 	res = (testHash1[i] - testHash2[i]);
-
- return res;
-}
-
-
-/*
- * Get song length from database
+/* Parses a time-entry in SLDB format
  */
-t_xs_sldb_node * xs_sldb_get(t_xs_md5hash pHash)
-{
- gint iStartNode, iEndNode, iQNode, r, i;
- gboolean iFound;
- t_xs_sldb_node *pResult;
-
- /* Check the database pointers */
- if (!xs_sldb || !xs_sldbi)
- 	return NULL;
- 	
- /* Look-up via index using binary search */
- pResult = NULL;
- iStartNode = 0;
- iEndNode = (xs_sldbn - 1);
- iQNode = (iEndNode / 2);
- iFound = FALSE;
-
- while ((!iFound) && ((iEndNode - iStartNode) > 128))
- 	{
- 	r = xs_sldb_cmphash(pHash, xs_sldbi[iQNode]->md5Hash);
- 	if (r < 0)
- 		{
- 		/* Hash was in the <- LEFT side */
- 		iEndNode = iQNode;
- 		iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
- 		} else
- 	if (r > 0)
- 		{
- 		/* Hash was in the RIGHT -> side */
- 		iStartNode = iQNode;
- 		iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
- 		} else
- 		iFound = TRUE;
- 	}
-
- /* If not found already */
- if (!iFound)
- 	{
-	/* Search the are linearly */
-	iFound = FALSE;
-	i = iStartNode;
-	while ((i <= iEndNode) && (!iFound))
-		{
-		if (xs_sldb_cmphash(pHash, xs_sldbi[i]->md5Hash) == 0)
-			iFound = TRUE;
-			else
-			i++;
-		}
-	
-	/* Check the result */
-	if (iFound)
-		pResult = xs_sldbi[i];
-
- 	} else {
-	/* Found via binary search */
- 	pResult = xs_sldbi[iQNode];
-	}
-
-
- return pResult;
-}
-
-
-/*
- * Parses a time-entry in SLDB format
- */
-gint32 xs_gettime(gchar *pcStr, int *piPos)
+static gint32 xs_sldb_gettime(gchar *pcStr, int *piPos)
 {
  gint32 iResult, iTemp;
 
@@ -204,16 +110,16 @@
 }
 
 
-/*
- * Read database to memory
+/* Read database to memory
  */
-gint xs_sldb_read(gchar *dbFilename)
+gint xs_sldb_read(t_xs_sldb *db, gchar *dbFilename)
 {
  FILE *inFile;
  gchar inLine[XS_BUFSIZE];
  guint lineNum, linePos;
  gboolean iOK;
  t_xs_sldb_node *tmpNode;
+ assert(db);
  
  /* Try to open the file */
  if ((inFile = fopen(dbFilename, "ra")) == NULL)
@@ -284,7 +190,7 @@
 			if (tmpNode->nLengths < XS_STIL_MAXENTRY)
 				{
 				tmpNode->sLengths[tmpNode->nLengths] =
-				xs_gettime(inLine, &linePos);
+				xs_sldb_gettime(inLine, &linePos);
 				tmpNode->nLengths++;
 				} else
 				iOK = FALSE;
@@ -292,7 +198,7 @@
 
 		/* Add an node to db in memory */
 		if (iOK)
-			xs_sldb_node_insert(tmpNode);
+			xs_sldb_node_insert(db, tmpNode);
 			else
 			xs_sldb_node_free(tmpNode);
 		}
@@ -314,10 +220,90 @@
 }
 
 
-/*
- * Compare two nodes' hashes
+/* Compare two given MD5-hashes.
+ * Return: 0 if equal
+ *         negative if testHash1 < testHash2
+ *         positive if testHash1 > testHash2
+ */
+static gint xs_sldb_cmphash(t_xs_md5hash testHash1, t_xs_md5hash testHash2)
+{
+ register gint i, res = 0;
+  
+ /* Compute difference of hashes */
+ for (i = 0; (i < XS_MD5HASH_LENGTH) && (!res); i++)
+ 	res = (testHash1[i] - testHash2[i]);
+
+ return res;
+}
+
+
+/* Get node from db index via binary search
  */
-gint xs_sldb_cmp(const void *pNode1, const void *pNode2)
+static t_xs_sldb_node * xs_sldb_get_node(t_xs_sldb *db, t_xs_md5hash pHash)
+{
+ gint iStartNode, iEndNode, iQNode, r, i;
+ gboolean iFound;
+ t_xs_sldb_node *pResult;
+ 
+ /* Check the database pointers */
+ if (!db || !db->pNodes || !db->ppIndex)
+ 	return NULL;
+ 	
+ /* Look-up via index using binary search */
+ pResult = NULL;
+ iStartNode = 0;
+ iEndNode = (db->n - 1);
+ iQNode = (iEndNode / 2);
+ iFound = FALSE;
+
+ while ((!iFound) && ((iEndNode - iStartNode) > 128))
+ 	{
+ 	r = xs_sldb_cmphash(pHash, db->ppIndex[iQNode]->md5Hash);
+ 	if (r < 0)
+ 		{
+ 		/* Hash was in the <- LEFT side */
+ 		iEndNode = iQNode;
+ 		iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
+ 		} else
+ 	if (r > 0)
+ 		{
+ 		/* Hash was in the RIGHT -> side */
+ 		iStartNode = iQNode;
+ 		iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
+ 		} else
+ 		iFound = TRUE;
+ 	}
+
+ /* If not found already */
+ if (!iFound)
+ 	{
+	/* Search the are linearly */
+	iFound = FALSE;
+	i = iStartNode;
+	while ((i <= iEndNode) && (!iFound))
+		{
+		if (xs_sldb_cmphash(pHash, db->ppIndex[i]->md5Hash) == 0)
+			iFound = TRUE;
+			else
+			i++;
+		}
+	
+	/* Check the result */
+	if (iFound)
+		pResult = db->ppIndex[i];
+
+ 	} else {
+	/* Found via binary search */
+ 	pResult = db->ppIndex[iQNode];
+	}
+
+ return pResult;
+}
+
+
+/* Compare two nodes
+ */
+static gint xs_sldb_cmp(const void *pNode1, const void *pNode2)
 {
  /* We assume here that we never ever get NULL-pointers or similar */
  return xs_sldb_cmphash((*(t_xs_sldb_node **) pNode1)->md5Hash,
@@ -325,70 +311,64 @@
 }
 
 
-/*
- * Initialize the song-length system
+/* (Re)create index
  */
-gint xs_songlen_init(void)
+gint xs_sldb_index(t_xs_sldb *db)
 {
  t_xs_sldb_node *pCurr;
  gint i;
-
-XSDEBUG("sldb_init()\n");
+ assert(db);
  
- /* Read the database */
- if (!xs_cfg.songlenDBPath)
- 	return -10;
-
- if (xs_sldb_read(xs_cfg.songlenDBPath) < 0)
- 	return -9;
-
-XSDEBUG("indexing...\n");
-
+ /* Free old index */
+ if (db->ppIndex)
+ 	{
+ 	g_free(db->ppIndex);
+ 	db->ppIndex = NULL;
+ 	}
+ 
  /* Get size of db */
- pCurr = xs_sldb;
- xs_sldbn = 0;
+ pCurr = db->pNodes;
+ db->n = 0;
  while (pCurr)
  	{
- 	xs_sldbn++;
+ 	db->n++;
  	pCurr = pCurr->pNext;
  	}
 
  /* Check number of nodes */
- if (xs_sldbn > 0)
+ if (db->n > 0)
 	{
 	/* Allocate memory for index-table */
-	xs_sldbi = (t_xs_sldb_node **) g_malloc(sizeof(t_xs_sldb_node *) * xs_sldbn);
-	if (!xs_sldbi) return -6;
+	db->ppIndex = (t_xs_sldb_node **) g_malloc(sizeof(t_xs_sldb_node *) * db->n);
+	if (!db->ppIndex) return -1;
 
 	/* Get node-pointers to table */
 	i = 0;
-	pCurr = xs_sldb;
-	while (pCurr)
+	pCurr = db->pNodes;
+	while (pCurr && (i < db->n))
 		{
-		xs_sldbi[i++] = pCurr;
+		db->ppIndex[i++] = pCurr;
 		pCurr = pCurr->pNext;
 		}
 
 	/* Sort the indexes */
-	qsort(xs_sldbi, xs_sldbn, sizeof(t_xs_sldb_node *), xs_sldb_cmp);
+	qsort(db->ppIndex, db->n, sizeof(t_xs_sldb_node *), xs_sldb_cmp);
 	}
 
- /* OK */
-XSDEBUG("init ok.\n");
  return 0;
 }
 
 
-/*
- * Close song-length system
+/* Free a given song-length database
  */
-void xs_songlen_close(void)
+void xs_sldb_free(t_xs_sldb *db)
 {
  t_xs_sldb_node *pCurr, *pNext;
  
- /* Free the memory allocated for database */
-XSDEBUG("sldb_close()\n");
- pCurr = xs_sldb;
+ if (!db) return;
+ 
+ /* Free the memory allocated for nodes */
+ pCurr = db->pNodes;
  while (pCurr)
  	{
  	pNext = pCurr->pNext;
@@ -396,19 +376,22 @@
  	pCurr = pNext;
  	}
 
- xs_sldb = NULL;
+ db->pNodes = NULL;
  
- /* Free memory allocated for indexes */
- if (xs_sldbi)
+ /* Free memory allocated for index */
+ if (db->ppIndex)
  	{
- 	g_free(xs_sldbi);
- 	xs_sldbi = NULL;
+ 	g_free(db->ppIndex);
+ 	db->ppIndex = NULL;
  	}
+
+ /* Free structure */
+ db->n = 0;
+ g_free(db);
 }
 
 
-/*
- * Compute md5hash of given SID-file
+/* Compute md5hash of given SID-file
  */
 typedef struct {
 	gchar	magicID[4];	/* "PSID" magic identifier */
@@ -434,83 +417,86 @@
 } t_xs_psidv2_header;
 
 
-guint16 rd_be16(FILE *f)
-{
- return (((guint16) fgetc(f)) << 8) |
- 	 ((guint16) fgetc(f));
-}
-
-
-guint32 rd_be32(FILE *f)
-{
- return (((guint32) fgetc(f)) << 24) |
- 	(((guint32) fgetc(f)) << 16) |
- 	(((guint32) fgetc(f)) << 8) |
- 	 ((guint32) fgetc(f));
-}
-
-
-gint rd_str(FILE *f, gchar *s, gint l)
-{
- return fread(s, sizeof(gchar), l, f);
-}
-
-#define MAX_MEMBUF (80*1024)
-
-gint xs_get_sid_hash(gchar *pcFilename, t_xs_md5hash hash)
+static gint xs_get_sid_hash(gchar *pcFilename, t_xs_md5hash hash)
 {
  FILE *inFile;
  t_xs_md5state inState;
  t_xs_psidv1_header psidH;
  t_xs_psidv2_header psidH2;
- guint8 songData[MAX_MEMBUF+1], ib8[2], i8;
+#ifdef XS_SIDBUF_DYNAMIC
+ guint8 *songData;
+#else
+ guint8 songData[XS_SIDBUF_SIZE];
+#endif
+ guint8 ib8[2], i8;
  gint iIndex, iRes;
 
-
  /* Try to open the file */
  if ((inFile = fopen(pcFilename, "rb")) == NULL)
  	return -1;
 
  /* Read PSID header in */
- rd_str(inFile, psidH.magicID, sizeof(psidH.magicID));
+ xs_rd_str(inFile, psidH.magicID, sizeof(psidH.magicID));
  if ((psidH.magicID[0] != 'P') || (psidH.magicID[1] != 'S') || 
      (psidH.magicID[2] != 'I') || (psidH.magicID[3] != 'D'))
+     {
+     fclose(inFile);
      return -2;
+     }
  
- psidH.version		= rd_be16(inFile);
- psidH.dataOffset	= rd_be16(inFile);
- psidH.loadAddress	= rd_be16(inFile);
- psidH.initAddress	= rd_be16(inFile);
- psidH.playAddress	= rd_be16(inFile);
- psidH.nSongs		= rd_be16(inFile);
- psidH.startSong	= rd_be16(inFile);
- psidH.speed		= rd_be32(inFile);
+ psidH.version		= xs_rd_be16(inFile);
+ psidH.dataOffset	= xs_rd_be16(inFile);
+ psidH.loadAddress	= xs_rd_be16(inFile);
+ psidH.initAddress	= xs_rd_be16(inFile);
+ psidH.playAddress	= xs_rd_be16(inFile);
+ psidH.nSongs		= xs_rd_be16(inFile);
+ psidH.startSong	= xs_rd_be16(inFile);
+ psidH.speed		= xs_rd_be32(inFile);
 
- rd_str(inFile, psidH.sidName, sizeof(psidH.sidName));
- rd_str(inFile, psidH.sidAuthor, sizeof(psidH.sidAuthor));
- rd_str(inFile, psidH.sidCopyright, sizeof(psidH.sidCopyright));
+ xs_rd_str(inFile, psidH.sidName, sizeof(psidH.sidName));
+ xs_rd_str(inFile, psidH.sidAuthor, sizeof(psidH.sidAuthor));
+ xs_rd_str(inFile, psidH.sidCopyright, sizeof(psidH.sidCopyright));
  
  /* Check if we need to load PSIDv2NG header ... */
  if (psidH.version == 2)
  	{
  	/* Yes, we need to */
- 	psidH2.flags		= rd_be16(inFile);
+ 	psidH2.flags		= xs_rd_be16(inFile);
  	psidH2.startPage	= fgetc(inFile);
  	psidH2.pageLength	= fgetc(inFile);
- 	psidH2.reserved		= rd_be16(inFile);
+ 	psidH2.reserved		= xs_rd_be16(inFile);
  	}
 
+#ifdef XS_SIDBUF_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), MAX_MEMBUF, inFile);
+ iRes = fread(songData, sizeof(guint8), XS_SIDBUF_SIZE, inFile);
  fclose(inFile);
 
  /* Initialize and start MD5-hash calculation */
  xs_md5_init(&inState);
  if (psidH.loadAddress == 0)
- 	/* COULD SOMEONE EXPLAIN WHY DO WE NEED THIS +2 STRIP???? */
+ 	{
+ 	/* Strip load address (2 first bytes) */
 	xs_md5_append(&inState, &songData[2], iRes-2);
-	else
+	} else {
+	/* Append "as is" */
 	xs_md5_append(&inState, songData, iRes);
+	}
+
+
+#ifdef XS_SIDBUF_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)); }
@@ -552,24 +538,18 @@
 }
 
 
-/*
- * Get song lengths
+/* Get song lengths
  */
-t_xs_sldb_node * xs_songlen_get(gchar *pcFilename)
+t_xs_sldb_node * xs_sldb_get(t_xs_sldb *db, gchar *pcFilename)
 {
  t_xs_sldb_node *pResult;
  t_xs_md5hash dbHash;
 
- pResult = NULL;
+ /* Get the hash and then look up from db */
+ if (xs_get_sid_hash(pcFilename, dbHash) == 0)
+	pResult = xs_sldb_get_node(db, dbHash);
+	else
+	pResult = NULL;
  
- if (xs_cfg.songlenDBEnable)
-	{
-	/* Get the hash and then look up from db */
-	if (xs_get_sid_hash(pcFilename, dbHash) == 0)
-		{
-		pResult = xs_sldb_get(dbHash);
-		}
-	}
-
  return pResult;
 }
--- a/src/xs_length.h	Sun Dec 19 15:25:03 2004 +0000
+++ b/src/xs_length.h	Sun Dec 19 16:53:05 2004 +0000
@@ -20,13 +20,20 @@
 	struct _t_xs_sldb_node *pPrev, *pNext;
 } t_xs_sldb_node;
 
+typedef struct {
+	t_xs_sldb_node	*pNodes,
+			**ppIndex;
+	gint		n;
+} t_xs_sldb;
+
 
 /*
  * Functions
  */
-gint	xs_songlen_init(void);		/* Initialize songlength subsystem */
-void	xs_songlen_close(void);		/* Close/shutdown */
-t_xs_sldb_node *xs_songlen_get(gchar *);
+gint			xs_sldb_read(t_xs_sldb *, gchar *);
+gint			xs_sldb_index(t_xs_sldb *);
+void			xs_sldb_free(t_xs_sldb *);
+t_xs_sldb_node *	xs_sldb_get(t_xs_sldb *, gchar *);
 
 
 #ifdef __cplusplus
--- a/src/xs_stil.c	Sun Dec 19 15:25:03 2004 +0000
+++ b/src/xs_stil.c	Sun Dec 19 16:53:05 2004 +0000
@@ -21,34 +21,33 @@
 */
 #include "xs_stil.h"
 #include "xs_support.h"
-#include "xs_config.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
 
 
-/*
- * Pointer to database in memory
+/* Database handling functions
  */
-static t_xs_stil_node	*xs_stildb = NULL;
-static t_xs_stil_node	**xs_stildbi = NULL;
-static gint		xs_stildbn   = 0;
-
-
-/*
- * Hash-database handling functions
- */
-t_xs_stil_node *xs_stildb_node_new(void)
+static t_xs_stil_node *xs_stildb_node_new(gchar *pcFilename)
 {
  t_xs_stil_node *pResult;
  
  /* Allocate memory for new node */
  pResult = (t_xs_stil_node *) g_malloc0(sizeof(t_xs_stil_node));
+ if (!pResult) return NULL;
+
+ pResult->pcFilename = g_strdup(pcFilename);
+ if (!pResult->pcFilename)
+ 	{
+ 	g_free(pResult);
+ 	return NULL;
+ 	}
+
  return pResult;
 }
 
 
-void xs_stildb_node_free(t_xs_stil_node *pNode)
+static void xs_stildb_node_free(t_xs_stil_node *pNode)
 {
  gint i;
  
@@ -68,34 +67,30 @@
 }
 
 
-/*
- * Insert given node to db linked list
+/* Insert given node to db linked list
  */
-#define LPREV	(pNode->pPrev)
-#define LTHIS	(pNode)
-#define LNEXT	(pNode->pNext)
-
-void xs_stildb_node_insert(t_xs_stil_node *pNode)
+static void xs_stildb_node_insert(t_xs_stildb *db, t_xs_stil_node *pNode)
 {
- if (xs_stildb)
+ assert(db);
+ 
+ if (db->pNodes)
  	{
  	/* The first node's pPrev points to last node */
-	LPREV = xs_stildb->pPrev;		/* New node's prev = Previous last node */
-	xs_stildb->pPrev->pNext = pNode;	/* Previous last node's next = New node */
-	xs_stildb->pPrev = pNode;		/* New last node = New node */
+	LPREV = db->pNodes->pPrev;		/* New node's prev = Previous last node */
+	db->pNodes->pPrev->pNext = pNode;	/* Previous last node's next = New node */
+	db->pNodes->pPrev = pNode;		/* New last node = New node */
 	LNEXT = NULL;				/* But next is NULL! */
  	} else {
- 	xs_stildb = pNode;			/* First node ... */
+ 	db->pNodes = pNode;			/* First node ... */
  	LPREV = pNode;				/* ... it's also last */
  	LNEXT = NULL;				/* But next is NULL! */
  	}
 }
 
 
-/*
- * Read database to memory
+/* Read database (additively) to given db-structure
  */
-gint xs_stildb_read(gchar *dbFilename)
+gint xs_stildb_read(t_xs_stildb *db, gchar *dbFilename)
 {
  FILE *inFile;
  gchar inLine[XS_BUFSIZE + 10];
@@ -103,6 +98,7 @@
  t_xs_stil_node *tmpNode;
  gboolean isError;
  gint subEntry;
+ assert(db);
  
  /* Try to open the file */
  if ((inFile = fopen(dbFilename, "ra")) == NULL)
@@ -137,13 +133,9 @@
  		}
  
  	/* A new node */
- 	tmpNode = xs_stildb_node_new();
- 	if (tmpNode)
- 		{
- 		/* Initialize the node */
- 		tmpNode->pcFilename = g_strdup(inLine);
-	 	subEntry = 0;
-	 	} else
+ 	subEntry = 0;
+ 	tmpNode = xs_stildb_node_new(inLine);
+ 	if (!tmpNode)
  		{
  		/* Allocation failed */
  		XSERR("Could not allocate new STILdb-node for '%s'!\n", inLine);
@@ -182,7 +174,7 @@
  	if (tmpNode)
  		{
  		/* Insert to database */
- 		xs_stildb_node_insert(tmpNode);
+ 		xs_stildb_node_insert(db, tmpNode);
 		tmpNode = NULL;
 		}
  	break;
@@ -230,18 +222,18 @@
 
  /* Check if there is one remaining node */
  if (tmpNode)
-	xs_stildb_node_free(tmpNode);
+	xs_stildb_node_insert(db, tmpNode);
 
  /* Close the file */  
  fclose(inFile);
+
  return 0;
 }
 
 
-/*
- * Compare two nodes' hashes
+/* Compare two nodes
  */
-gint xs_stildb_cmp(const void *pNode1, const void *pNode2)
+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,
@@ -249,70 +241,62 @@
 }
 
 
-/*
- * Initialize the song-length system
+/* (Re)create index
  */
-gint xs_stil_init(void)
+gint xs_stildb_index(t_xs_stildb *db)
 {
  t_xs_stil_node *pCurr;
  gint i;
 
-XSDEBUG("stil_init()\n");
+ /* Free old index */
+ if (db->ppIndex)
+ 	{
+ 	g_free(db->ppIndex);
+ 	db->ppIndex = NULL;
+ 	}
  
- /* Read the database */
- if (!xs_cfg.stilDBPath)
- 	return -10;
-
- if (xs_stildb_read(xs_cfg.stilDBPath) < 0)
- 	return -9;
-
-XSDEBUG("indexing...\n");
-
  /* Get size of db */
- pCurr = xs_stildb;
- xs_stildbn = 0;
+ pCurr = db->pNodes;
+ db->n = 0;
  while (pCurr)
  	{
- 	xs_stildbn++;
+ 	db->n++;
  	pCurr = pCurr->pNext;
  	}
 
  /* Check number of nodes */
- if (xs_stildbn > 0)
+ if (db->n > 0)
 	{
 	/* Allocate memory for index-table */
-	xs_stildbi = (t_xs_stil_node **) g_malloc(sizeof(t_xs_stil_node *) * xs_stildbn);
-	if (!xs_stildbi) return -6;
+	db->ppIndex = (t_xs_stil_node **) g_malloc(sizeof(t_xs_stil_node *) * db->n);
+	if (!db->ppIndex) return -1;
 
 	/* Get node-pointers to table */
 	i = 0;
-	pCurr = xs_stildb;
-	while (pCurr)
+	pCurr = db->pNodes;
+	while (pCurr && (i < db->n))
 		{
-		xs_stildbi[i++] = pCurr;
+		db->ppIndex[i++] = pCurr;
 		pCurr = pCurr->pNext;
 		}
 
 	/* Sort the indexes */
-	qsort(xs_stildbi, xs_stildbn, sizeof(t_xs_stil_node *), xs_stildb_cmp);
+	qsort(db->ppIndex, db->n, sizeof(t_xs_stil_node *), xs_stildb_cmp);
 	}
 
- /* OK */
-XSDEBUG("init ok.\n");
  return 0;
 }
 
-
-/*
- * Close song-length system
+/* Free a given STIL database
  */
-void xs_stil_close(void)
+void xs_stildb_free(t_xs_stildb *db)
 {
  t_xs_stil_node *pCurr, *pNext;
  
- /* Free the memory allocated for database */
-XSDEBUG("stildb_close()\n");
- pCurr = xs_stildb;
+ if (!db) return;
+ 
+ /* Free the memory allocated for nodes */
+ pCurr = db->pNodes;
  while (pCurr)
  	{
  	pNext = pCurr->pNext;
@@ -320,56 +304,43 @@
  	pCurr = pNext;
  	}
 
- xs_stildb = NULL;
+ db->pNodes = NULL;
  
- /* Free memory allocated for indexes */
- if (xs_stildbi)
+ /* Free memory allocated for index */
+ if (db->ppIndex)
  	{
- 	g_free(xs_stildbi);
- 	xs_stildbi = NULL;
+ 	g_free(db->ppIndex);
+ 	db->ppIndex = NULL;
  	}
+
+ /* Free structure */
+ db->n = 0;
+ g_free(db);
 }
 
 
-/*
- * Get STIL information from database
+/* Get STIL information node from database
  */
-t_xs_stil_node * xs_stil_get(gchar *pcFilename)
+static t_xs_stil_node * xs_stildb_get_node(t_xs_stildb *db, gchar *pcFilename)
 {
  gint iStartNode, iEndNode, iQNode, r, i;
- gchar *tmpFilename;
  gboolean iFound;
  t_xs_stil_node *pResult;
 
  /* Check the database pointers */
- if (!xs_stildb || !xs_stildbi || !xs_cfg.stilDBEnable || !xs_cfg.hvscPath)
+ if (!db || !db->pNodes || !db->ppIndex)
  	return NULL;
  
- /* Remove postfixed directory separator from HVSC-path */
- tmpFilename = strrchr(xs_cfg.hvscPath, '/');
- if (tmpFilename && (tmpFilename[1] == 0))
-	tmpFilename[0] = 0;
- 
- /* Remove HVSC location-prefix from filename */
- tmpFilename = strstr(pcFilename, xs_cfg.hvscPath);
- if (tmpFilename)
- 	{
-	tmpFilename += strlen(xs_cfg.hvscPath);
-	} else
-	tmpFilename = pcFilename; 
-
- XSDEBUG("'%s', '%s'\n", xs_cfg.hvscPath, tmpFilename);
- 	
  /* Look-up via index using binary search */
  pResult = NULL;
  iStartNode = 0;
- iEndNode = (xs_stildbn - 1);
+ iEndNode = (db->n - 1);
  iQNode = (iEndNode / 2);
  iFound = FALSE;
 
  while ((!iFound) && ((iEndNode - iStartNode) > 128))
  	{
- 	r = strcmp(tmpFilename, xs_stildbi[iQNode]->pcFilename);
+ 	r = strcmp(pcFilename, db->ppIndex[iQNode]->pcFilename);
  	if (r < 0)
  		{
  		/* Hash was in the <- LEFT side */
@@ -393,7 +364,7 @@
 	i = iStartNode;
 	while ((i <= iEndNode) && (!iFound))
 		{
-		if (strcmp(tmpFilename, xs_stildbi[i]->pcFilename) == 0)
+		if (strcmp(pcFilename, db->ppIndex[i]->pcFilename) == 0)
 			iFound = TRUE;
 			else
 			i++;
@@ -401,13 +372,35 @@
 	
 	/* Check the result */
 	if (iFound)
-		pResult = xs_stildbi[i];
+		pResult = db->ppIndex[i];
 
  	} else {
 	/* Found via binary search */
- 	pResult = xs_stildbi[iQNode];
+ 	pResult = db->ppIndex[iQNode];
 	}
 
  return pResult;
 }
 
+
+/* Get from STIL database
+ */
+t_xs_stil_node * xs_stildb_get(t_xs_stildb *db, gchar *hvscPath, gchar *pcFilename)
+{
+ gchar *tmpFilename;
+
+ /* Remove postfixed directory separator from HVSC-path */
+ tmpFilename = xs_strrchr(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; 
+
+ return xs_stildb_get_node(db, pcFilename);
+}
+
--- a/src/xs_stil.h	Sun Dec 19 15:25:03 2004 +0000
+++ b/src/xs_stil.h	Sun Dec 19 16:53:05 2004 +0000
@@ -23,12 +23,20 @@
 } t_xs_stil_node;
 
 
+typedef struct {
+	t_xs_stil_node	*pNodes,
+			**ppIndex;
+	gint		n;
+} t_xs_stildb;
+
+
 /*
  * Functions
  */
-gint	xs_stil_init(void);		/* Initialize STIL subsystem */
-void	xs_stil_close(void);		/* Close/shutdown */
-t_xs_stil_node*	xs_stil_get(gchar *);	/* Get STIL information */
+gint			xs_stildb_read(t_xs_stildb *, gchar *);
+gint			xs_stildb_index(t_xs_stildb *);
+void			xs_stildb_free(t_xs_stildb *);
+t_xs_stil_node *	xs_stildb_get(t_xs_stildb *, gchar *, gchar *);
 
 
 #ifdef __cplusplus