view src/xs_stil.c @ 99:2bc56809ec0b

STIL-support fixes, variable renaming
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 10 Jan 2004 23:51:04 +0000
parents 086681f70910
children 4614f58ab169
line wrap: on
line source

/*  
   xmms-sid - SIDPlay input plugin for X MultiMedia System (XMMS)

   STIL-database parsing functions
   
   Mostly written by Matti "ccr" Hamalainen <ccr@tnsp.org>,
   some parts written by Willem Monsuwe <willem@stack.nl>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include "xs_stil.h"
#include "xs_support.h"
#include "xs_config.h"
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

/*
 * Pointer to database in memory
 */
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)
{
 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;
 
 return pResult;
}


void xs_stildb_node_free(t_xs_stil_node *pNode)
{
 gint i;
 
 if (pNode)
 	{
 	for (i = 0; i < pNode->nsubTunes; i++)
 		{
 		g_free(pNode->subTune[i].pName);
 		g_free(pNode->subTune[i].pTitle);
 		g_free(pNode->subTune[i].pArtist);
 		g_free(pNode->subTune[i].pComment);
 		}
 	
 	g_free(pNode->pcFilename);
 	g_free(pNode);
 	}
}


/*
 * 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)
{
 if (xs_stildb)
 	{
 	/* 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 */
	LNEXT = NULL;				/* But next is NULL! */
 	} else {
 	xs_stildb = pNode;			/* First node ... */
 	LPREV = pNode;				/* ... it's also last */
 	LNEXT = NULL;				/* But next is NULL! */
 	}
}


/*
 * Get STIL information from database
 */
t_xs_stil_node * xs_stildb_get(gchar *pcFilename)
{
 gint iStartNode, iEndNode, iQNode, r, i;
 gboolean iFound;
 t_xs_stil_node *pResult;

 /* Check the database pointers */
 if (!xs_stildb || !xs_stildbi)
 	return NULL;
 	
 /* Look-up via index using binary search */
 pResult = NULL;
 iStartNode = 0;
 iEndNode = (xs_stildbn - 1);
 iQNode = (iEndNode / 2);
 iFound = FALSE;

 while ((!iFound) && ((iEndNode - iStartNode) > 128))
 	{
 	r = strcmp(pcFilename, xs_stildbi[iQNode]->pcFilename);
 	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 (strcmp(pcFilename, xs_stildbi[iQNode]->pcFilename) == 0)
			iFound = TRUE;
			else
			i++;
		}
	
	/* Check the result */
	if (iFound)
		pResult = xs_stildbi[i];

 	} else {
	/* Found via binary search */
 	pResult = xs_stildbi[iQNode];
	}


 return pResult;
}


/*
 * Read database to memory
 */
gint xs_stildb_read(gchar *dbFilename)
{
 FILE *inFile;
 gchar inLine[XS_BUFSIZE];
 guint lineNum, linePos;
 gboolean iOK;
 t_xs_stil_node *tmpNode;
 
 /* Try to open the file */
 if ((inFile = fopen(dbFilename, "ra")) == NULL)
 	{
 	XSERR("Could not open STILDB '%s'\n", dbFilename);
 	return -1;
 	}
 
 /* Read and parse the data */
 lineNum = 0;

 while (!feof(inFile))
 {
 fgets(inLine, sizeof(inLine), inFile);
 lineNum++;

 } /* while */

 /* Close the file */  
 fclose(inFile);
 return 0;
}


/*
 * Compare two nodes' hashes
 */
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);
}


/*
 * Initialize the song-length system
 */
gint xs_stil_init(void)
{
 t_xs_stil_node *pCurr;
 gint i;

XSDEBUG("stil_init()\n");
 
 /* 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;
 while (pCurr)
 	{
 	xs_stildbn++;
 	pCurr = pCurr->pNext;
 	}

 /* Check number of nodes */
 if (xs_stildbn > 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;

	/* Get node-pointers to table */
	i = 0;
	pCurr = xs_stildb;
	while (pCurr)
		{
		xs_stildbi[i++] = pCurr;
		pCurr = pCurr->pNext;
		}

	/* Sort the indexes */
	qsort(xs_stildbi, xs_stildbn, sizeof(t_xs_stil_node *), xs_stildb_cmp);
	}

 /* OK */
XSDEBUG("init ok.\n");
 return 0;
}


/*
 * Close song-length system
 */
void xs_stil_close(void)
{
 t_xs_stil_node *pCurr, *pNext;
 
 /* Free the memory allocated for database */
XSDEBUG("stildb_close()\n");
 pCurr = xs_stildb;
 while (pCurr)
 	{
 	pNext = pCurr->pNext;
	xs_stildb_node_free(pCurr);
 	pCurr = pNext;
 	}

 xs_stildb = NULL;
 
 /* Free memory allocated for indexes */
 if (xs_stildbi)
 	{
 	g_free(xs_stildbi);
 	xs_stildbi = NULL;
 	}
}


/*
 * Get STIL information
 */
t_xs_stil_node * xs_stil_get(gchar *pcFilename)
{
 t_xs_stil_node *pResult;

 return pResult;
}