comparison src/xs_length.c @ 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 16e3b2446a73
children 608f31f6c095
comparison
equal deleted inserted replaced
226:858c09f59011 227:92bad4c7b998
19 along with this program; if not, write to the Free Software 19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */ 21 */
22 #include "xs_length.h" 22 #include "xs_length.h"
23 #include "xs_support.h" 23 #include "xs_support.h"
24 #include "xs_config.h"
25 #include <stdio.h> 24 #include <stdio.h>
26 #include <stdlib.h> 25 #include <stdlib.h>
27 #include <ctype.h> 26 #include <ctype.h>
28 #include <string.h> 27 #include <string.h>
29 28
30 29
31 /* 30 /* Database handling functions
32 * Pointer to database in memory 31 */
33 */ 32 static t_xs_sldb_node *xs_sldb_node_new(void)
34 static t_xs_sldb_node *xs_sldb = NULL;
35 static t_xs_sldb_node **xs_sldbi = NULL;
36 static gint xs_sldbn = 0;
37
38
39 /*
40 * Hash-database handling functions
41 */
42 t_xs_sldb_node *xs_sldb_node_new(void)
43 { 33 {
44 t_xs_sldb_node *pResult; 34 t_xs_sldb_node *pResult;
45 35
46 /* Allocate memory for new node */ 36 /* Allocate memory for new node */
47 pResult = (t_xs_sldb_node *) g_malloc0(sizeof(t_xs_sldb_node)); 37 pResult = (t_xs_sldb_node *) g_malloc0(sizeof(t_xs_sldb_node));
49 39
50 return pResult; 40 return pResult;
51 } 41 }
52 42
53 43
54 void xs_sldb_node_free(t_xs_sldb_node *pNode) 44 static void xs_sldb_node_free(t_xs_sldb_node *pNode)
55 { 45 {
56 if (pNode) g_free(pNode); 46 if (pNode)
57 } 47 {
58 48 /* Nothing much to do here ... */
59 49 g_free(pNode);
60 /* 50 }
61 * Insert given node to db linked list 51 }
62 */ 52
63 #define LPREV (pNode->pPrev) 53
64 #define LTHIS (pNode) 54 /* Insert given node to db linked list
65 #define LNEXT (pNode->pNext) 55 */
66 56 static void xs_sldb_node_insert(t_xs_sldb *db, t_xs_sldb_node *pNode)
67 void xs_sldb_node_insert(t_xs_sldb_node *pNode) 57 {
68 { 58 assert(db);
69 if (xs_sldb) 59
60 if (db->pNodes)
70 { 61 {
71 /* The first node's pPrev points to last node */ 62 /* The first node's pPrev points to last node */
72 LPREV = xs_sldb->pPrev; /* New node's prev = Previous last node */ 63 LPREV = db->pNodes->pPrev; /* New node's prev = Previous last node */
73 xs_sldb->pPrev->pNext = pNode; /* Previous last node's next = New node */ 64 db->pNodes->pPrev->pNext = pNode; /* Previous last node's next = New node */
74 xs_sldb->pPrev = pNode; /* New last node = New node */ 65 db->pNodes->pPrev = pNode; /* New last node = New node */
75 LNEXT = NULL; /* But next is NULL! */ 66 LNEXT = NULL; /* But next is NULL! */
76 } else { 67 } else {
77 xs_sldb = pNode; /* First node ... */ 68 db->pNodes = pNode; /* First node ... */
78 LPREV = pNode; /* ... it's also last */ 69 LPREV = pNode; /* ... it's also last */
79 LNEXT = NULL; /* But next is NULL! */ 70 LNEXT = NULL; /* But next is NULL! */
80 } 71 }
81 } 72 }
82 73
83 74
84 /* 75 /* Parses a time-entry in SLDB format
85 * Compare two given MD5-hashes. 76 */
86 * Return: 0 if equal 77 static gint32 xs_sldb_gettime(gchar *pcStr, int *piPos)
87 * negative if testHash1 < testHash2
88 * positive if testHash1 > testHash2
89 */
90 gint xs_sldb_cmphash(t_xs_md5hash testHash1, t_xs_md5hash testHash2)
91 {
92 register gint i, res = 0;
93
94 /* Compute difference of hashes */
95 for (i = 0; (i < XS_MD5HASH_LENGTH) && (!res); i++)
96 res = (testHash1[i] - testHash2[i]);
97
98 return res;
99 }
100
101
102 /*
103 * Get song length from database
104 */
105 t_xs_sldb_node * xs_sldb_get(t_xs_md5hash pHash)
106 {
107 gint iStartNode, iEndNode, iQNode, r, i;
108 gboolean iFound;
109 t_xs_sldb_node *pResult;
110
111 /* Check the database pointers */
112 if (!xs_sldb || !xs_sldbi)
113 return NULL;
114
115 /* Look-up via index using binary search */
116 pResult = NULL;
117 iStartNode = 0;
118 iEndNode = (xs_sldbn - 1);
119 iQNode = (iEndNode / 2);
120 iFound = FALSE;
121
122 while ((!iFound) && ((iEndNode - iStartNode) > 128))
123 {
124 r = xs_sldb_cmphash(pHash, xs_sldbi[iQNode]->md5Hash);
125 if (r < 0)
126 {
127 /* Hash was in the <- LEFT side */
128 iEndNode = iQNode;
129 iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
130 } else
131 if (r > 0)
132 {
133 /* Hash was in the RIGHT -> side */
134 iStartNode = iQNode;
135 iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
136 } else
137 iFound = TRUE;
138 }
139
140 /* If not found already */
141 if (!iFound)
142 {
143 /* Search the are linearly */
144 iFound = FALSE;
145 i = iStartNode;
146 while ((i <= iEndNode) && (!iFound))
147 {
148 if (xs_sldb_cmphash(pHash, xs_sldbi[i]->md5Hash) == 0)
149 iFound = TRUE;
150 else
151 i++;
152 }
153
154 /* Check the result */
155 if (iFound)
156 pResult = xs_sldbi[i];
157
158 } else {
159 /* Found via binary search */
160 pResult = xs_sldbi[iQNode];
161 }
162
163
164 return pResult;
165 }
166
167
168 /*
169 * Parses a time-entry in SLDB format
170 */
171 gint32 xs_gettime(gchar *pcStr, int *piPos)
172 { 78 {
173 gint32 iResult, iTemp; 79 gint32 iResult, iTemp;
174 80
175 /* Check if it starts with a digit */ 81 /* Check if it starts with a digit */
176 if (isdigit(pcStr[*piPos])) 82 if (isdigit(pcStr[*piPos]))
202 108
203 return iResult; 109 return iResult;
204 } 110 }
205 111
206 112
207 /* 113 /* Read database to memory
208 * Read database to memory 114 */
209 */ 115 gint xs_sldb_read(t_xs_sldb *db, gchar *dbFilename)
210 gint xs_sldb_read(gchar *dbFilename)
211 { 116 {
212 FILE *inFile; 117 FILE *inFile;
213 gchar inLine[XS_BUFSIZE]; 118 gchar inLine[XS_BUFSIZE];
214 guint lineNum, linePos; 119 guint lineNum, linePos;
215 gboolean iOK; 120 gboolean iOK;
216 t_xs_sldb_node *tmpNode; 121 t_xs_sldb_node *tmpNode;
122 assert(db);
217 123
218 /* Try to open the file */ 124 /* Try to open the file */
219 if ((inFile = fopen(dbFilename, "ra")) == NULL) 125 if ((inFile = fopen(dbFilename, "ra")) == NULL)
220 { 126 {
221 XSERR("Could not open SongLengthDB '%s'\n", dbFilename); 127 XSERR("Could not open SongLengthDB '%s'\n", dbFilename);
282 xs_findnext(inLine, &linePos); 188 xs_findnext(inLine, &linePos);
283 189
284 if (tmpNode->nLengths < XS_STIL_MAXENTRY) 190 if (tmpNode->nLengths < XS_STIL_MAXENTRY)
285 { 191 {
286 tmpNode->sLengths[tmpNode->nLengths] = 192 tmpNode->sLengths[tmpNode->nLengths] =
287 xs_gettime(inLine, &linePos); 193 xs_sldb_gettime(inLine, &linePos);
288 tmpNode->nLengths++; 194 tmpNode->nLengths++;
289 } else 195 } else
290 iOK = FALSE; 196 iOK = FALSE;
291 } 197 }
292 198
293 /* Add an node to db in memory */ 199 /* Add an node to db in memory */
294 if (iOK) 200 if (iOK)
295 xs_sldb_node_insert(tmpNode); 201 xs_sldb_node_insert(db, tmpNode);
296 else 202 else
297 xs_sldb_node_free(tmpNode); 203 xs_sldb_node_free(tmpNode);
298 } 204 }
299 } 205 }
300 } 206 }
312 218
313 return 0; 219 return 0;
314 } 220 }
315 221
316 222
317 /* 223 /* Compare two given MD5-hashes.
318 * Compare two nodes' hashes 224 * Return: 0 if equal
319 */ 225 * negative if testHash1 < testHash2
320 gint xs_sldb_cmp(const void *pNode1, const void *pNode2) 226 * positive if testHash1 > testHash2
227 */
228 static gint xs_sldb_cmphash(t_xs_md5hash testHash1, t_xs_md5hash testHash2)
229 {
230 register gint i, res = 0;
231
232 /* Compute difference of hashes */
233 for (i = 0; (i < XS_MD5HASH_LENGTH) && (!res); i++)
234 res = (testHash1[i] - testHash2[i]);
235
236 return res;
237 }
238
239
240 /* Get node from db index via binary search
241 */
242 static t_xs_sldb_node * xs_sldb_get_node(t_xs_sldb *db, t_xs_md5hash pHash)
243 {
244 gint iStartNode, iEndNode, iQNode, r, i;
245 gboolean iFound;
246 t_xs_sldb_node *pResult;
247
248 /* Check the database pointers */
249 if (!db || !db->pNodes || !db->ppIndex)
250 return NULL;
251
252 /* Look-up via index using binary search */
253 pResult = NULL;
254 iStartNode = 0;
255 iEndNode = (db->n - 1);
256 iQNode = (iEndNode / 2);
257 iFound = FALSE;
258
259 while ((!iFound) && ((iEndNode - iStartNode) > 128))
260 {
261 r = xs_sldb_cmphash(pHash, db->ppIndex[iQNode]->md5Hash);
262 if (r < 0)
263 {
264 /* Hash was in the <- LEFT side */
265 iEndNode = iQNode;
266 iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
267 } else
268 if (r > 0)
269 {
270 /* Hash was in the RIGHT -> side */
271 iStartNode = iQNode;
272 iQNode = iStartNode + ((iEndNode - iStartNode) / 2);
273 } else
274 iFound = TRUE;
275 }
276
277 /* If not found already */
278 if (!iFound)
279 {
280 /* Search the are linearly */
281 iFound = FALSE;
282 i = iStartNode;
283 while ((i <= iEndNode) && (!iFound))
284 {
285 if (xs_sldb_cmphash(pHash, db->ppIndex[i]->md5Hash) == 0)
286 iFound = TRUE;
287 else
288 i++;
289 }
290
291 /* Check the result */
292 if (iFound)
293 pResult = db->ppIndex[i];
294
295 } else {
296 /* Found via binary search */
297 pResult = db->ppIndex[iQNode];
298 }
299
300 return pResult;
301 }
302
303
304 /* Compare two nodes
305 */
306 static gint xs_sldb_cmp(const void *pNode1, const void *pNode2)
321 { 307 {
322 /* We assume here that we never ever get NULL-pointers or similar */ 308 /* We assume here that we never ever get NULL-pointers or similar */
323 return xs_sldb_cmphash((*(t_xs_sldb_node **) pNode1)->md5Hash, 309 return xs_sldb_cmphash((*(t_xs_sldb_node **) pNode1)->md5Hash,
324 (*(t_xs_sldb_node **) pNode2)->md5Hash); 310 (*(t_xs_sldb_node **) pNode2)->md5Hash);
325 } 311 }
326 312
327 313
328 /* 314 /* (Re)create index
329 * Initialize the song-length system 315 */
330 */ 316 gint xs_sldb_index(t_xs_sldb *db)
331 gint xs_songlen_init(void)
332 { 317 {
333 t_xs_sldb_node *pCurr; 318 t_xs_sldb_node *pCurr;
334 gint i; 319 gint i;
335 320 assert(db);
336 XSDEBUG("sldb_init()\n"); 321
337 322 /* Free old index */
338 /* Read the database */ 323 if (db->ppIndex)
339 if (!xs_cfg.songlenDBPath) 324 {
340 return -10; 325 g_free(db->ppIndex);
341 326 db->ppIndex = NULL;
342 if (xs_sldb_read(xs_cfg.songlenDBPath) < 0) 327 }
343 return -9; 328
344
345 XSDEBUG("indexing...\n");
346
347 /* Get size of db */ 329 /* Get size of db */
348 pCurr = xs_sldb; 330 pCurr = db->pNodes;
349 xs_sldbn = 0; 331 db->n = 0;
350 while (pCurr) 332 while (pCurr)
351 { 333 {
352 xs_sldbn++; 334 db->n++;
353 pCurr = pCurr->pNext; 335 pCurr = pCurr->pNext;
354 } 336 }
355 337
356 /* Check number of nodes */ 338 /* Check number of nodes */
357 if (xs_sldbn > 0) 339 if (db->n > 0)
358 { 340 {
359 /* Allocate memory for index-table */ 341 /* Allocate memory for index-table */
360 xs_sldbi = (t_xs_sldb_node **) g_malloc(sizeof(t_xs_sldb_node *) * xs_sldbn); 342 db->ppIndex = (t_xs_sldb_node **) g_malloc(sizeof(t_xs_sldb_node *) * db->n);
361 if (!xs_sldbi) return -6; 343 if (!db->ppIndex) return -1;
362 344
363 /* Get node-pointers to table */ 345 /* Get node-pointers to table */
364 i = 0; 346 i = 0;
365 pCurr = xs_sldb; 347 pCurr = db->pNodes;
366 while (pCurr) 348 while (pCurr && (i < db->n))
367 { 349 {
368 xs_sldbi[i++] = pCurr; 350 db->ppIndex[i++] = pCurr;
369 pCurr = pCurr->pNext; 351 pCurr = pCurr->pNext;
370 } 352 }
371 353
372 /* Sort the indexes */ 354 /* Sort the indexes */
373 qsort(xs_sldbi, xs_sldbn, sizeof(t_xs_sldb_node *), xs_sldb_cmp); 355 qsort(db->ppIndex, db->n, sizeof(t_xs_sldb_node *), xs_sldb_cmp);
374 } 356 }
375 357
376 /* OK */
377 XSDEBUG("init ok.\n");
378 return 0; 358 return 0;
379 } 359 }
380 360
381 361
382 /* 362 /* Free a given song-length database
383 * Close song-length system 363 */
384 */ 364 void xs_sldb_free(t_xs_sldb *db)
385 void xs_songlen_close(void)
386 { 365 {
387 t_xs_sldb_node *pCurr, *pNext; 366 t_xs_sldb_node *pCurr, *pNext;
388 367
389 /* Free the memory allocated for database */ 368 if (!db) return;
390 XSDEBUG("sldb_close()\n"); 369
391 pCurr = xs_sldb; 370 /* Free the memory allocated for nodes */
371 pCurr = db->pNodes;
392 while (pCurr) 372 while (pCurr)
393 { 373 {
394 pNext = pCurr->pNext; 374 pNext = pCurr->pNext;
395 xs_sldb_node_free(pCurr); 375 xs_sldb_node_free(pCurr);
396 pCurr = pNext; 376 pCurr = pNext;
397 } 377 }
398 378
399 xs_sldb = NULL; 379 db->pNodes = NULL;
400 380
401 /* Free memory allocated for indexes */ 381 /* Free memory allocated for index */
402 if (xs_sldbi) 382 if (db->ppIndex)
403 { 383 {
404 g_free(xs_sldbi); 384 g_free(db->ppIndex);
405 xs_sldbi = NULL; 385 db->ppIndex = NULL;
406 } 386 }
407 } 387
408 388 /* Free structure */
409 389 db->n = 0;
410 /* 390 g_free(db);
411 * Compute md5hash of given SID-file 391 }
392
393
394 /* Compute md5hash of given SID-file
412 */ 395 */
413 typedef struct { 396 typedef struct {
414 gchar magicID[4]; /* "PSID" magic identifier */ 397 gchar magicID[4]; /* "PSID" magic identifier */
415 guint16 version, /* Version number */ 398 guint16 version, /* Version number */
416 dataOffset, /* Start of actual c64 data in file */ 399 dataOffset, /* Start of actual c64 data in file */
432 pageLength; 415 pageLength;
433 guint16 reserved; 416 guint16 reserved;
434 } t_xs_psidv2_header; 417 } t_xs_psidv2_header;
435 418
436 419
437 guint16 rd_be16(FILE *f) 420 static gint xs_get_sid_hash(gchar *pcFilename, t_xs_md5hash hash)
438 {
439 return (((guint16) fgetc(f)) << 8) |
440 ((guint16) fgetc(f));
441 }
442
443
444 guint32 rd_be32(FILE *f)
445 {
446 return (((guint32) fgetc(f)) << 24) |
447 (((guint32) fgetc(f)) << 16) |
448 (((guint32) fgetc(f)) << 8) |
449 ((guint32) fgetc(f));
450 }
451
452
453 gint rd_str(FILE *f, gchar *s, gint l)
454 {
455 return fread(s, sizeof(gchar), l, f);
456 }
457
458 #define MAX_MEMBUF (80*1024)
459
460 gint xs_get_sid_hash(gchar *pcFilename, t_xs_md5hash hash)
461 { 421 {
462 FILE *inFile; 422 FILE *inFile;
463 t_xs_md5state inState; 423 t_xs_md5state inState;
464 t_xs_psidv1_header psidH; 424 t_xs_psidv1_header psidH;
465 t_xs_psidv2_header psidH2; 425 t_xs_psidv2_header psidH2;
466 guint8 songData[MAX_MEMBUF+1], ib8[2], i8; 426 #ifdef XS_SIDBUF_DYNAMIC
427 guint8 *songData;
428 #else
429 guint8 songData[XS_SIDBUF_SIZE];
430 #endif
431 guint8 ib8[2], i8;
467 gint iIndex, iRes; 432 gint iIndex, iRes;
468
469 433
470 /* Try to open the file */ 434 /* Try to open the file */
471 if ((inFile = fopen(pcFilename, "rb")) == NULL) 435 if ((inFile = fopen(pcFilename, "rb")) == NULL)
472 return -1; 436 return -1;
473 437
474 /* Read PSID header in */ 438 /* Read PSID header in */
475 rd_str(inFile, psidH.magicID, sizeof(psidH.magicID)); 439 xs_rd_str(inFile, psidH.magicID, sizeof(psidH.magicID));
476 if ((psidH.magicID[0] != 'P') || (psidH.magicID[1] != 'S') || 440 if ((psidH.magicID[0] != 'P') || (psidH.magicID[1] != 'S') ||
477 (psidH.magicID[2] != 'I') || (psidH.magicID[3] != 'D')) 441 (psidH.magicID[2] != 'I') || (psidH.magicID[3] != 'D'))
442 {
443 fclose(inFile);
478 return -2; 444 return -2;
479 445 }
480 psidH.version = rd_be16(inFile); 446
481 psidH.dataOffset = rd_be16(inFile); 447 psidH.version = xs_rd_be16(inFile);
482 psidH.loadAddress = rd_be16(inFile); 448 psidH.dataOffset = xs_rd_be16(inFile);
483 psidH.initAddress = rd_be16(inFile); 449 psidH.loadAddress = xs_rd_be16(inFile);
484 psidH.playAddress = rd_be16(inFile); 450 psidH.initAddress = xs_rd_be16(inFile);
485 psidH.nSongs = rd_be16(inFile); 451 psidH.playAddress = xs_rd_be16(inFile);
486 psidH.startSong = rd_be16(inFile); 452 psidH.nSongs = xs_rd_be16(inFile);
487 psidH.speed = rd_be32(inFile); 453 psidH.startSong = xs_rd_be16(inFile);
488 454 psidH.speed = xs_rd_be32(inFile);
489 rd_str(inFile, psidH.sidName, sizeof(psidH.sidName)); 455
490 rd_str(inFile, psidH.sidAuthor, sizeof(psidH.sidAuthor)); 456 xs_rd_str(inFile, psidH.sidName, sizeof(psidH.sidName));
491 rd_str(inFile, psidH.sidCopyright, sizeof(psidH.sidCopyright)); 457 xs_rd_str(inFile, psidH.sidAuthor, sizeof(psidH.sidAuthor));
458 xs_rd_str(inFile, psidH.sidCopyright, sizeof(psidH.sidCopyright));
492 459
493 /* Check if we need to load PSIDv2NG header ... */ 460 /* Check if we need to load PSIDv2NG header ... */
494 if (psidH.version == 2) 461 if (psidH.version == 2)
495 { 462 {
496 /* Yes, we need to */ 463 /* Yes, we need to */
497 psidH2.flags = rd_be16(inFile); 464 psidH2.flags = xs_rd_be16(inFile);
498 psidH2.startPage = fgetc(inFile); 465 psidH2.startPage = fgetc(inFile);
499 psidH2.pageLength = fgetc(inFile); 466 psidH2.pageLength = fgetc(inFile);
500 psidH2.reserved = rd_be16(inFile); 467 psidH2.reserved = xs_rd_be16(inFile);
501 } 468 }
502 469
470 #ifdef XS_SIDBUF_DYNAMIC
471 /* Allocate buffer */
472 songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE * sizeof(guint8));
473 if (!songData)
474 {
475 fclose(inFile);
476 return -3;
477 }
478 #endif
479
503 /* Read data to buffer */ 480 /* Read data to buffer */
504 iRes = fread(songData, sizeof(guint8), MAX_MEMBUF, inFile); 481 iRes = fread(songData, sizeof(guint8), XS_SIDBUF_SIZE, inFile);
505 fclose(inFile); 482 fclose(inFile);
506 483
507 /* Initialize and start MD5-hash calculation */ 484 /* Initialize and start MD5-hash calculation */
508 xs_md5_init(&inState); 485 xs_md5_init(&inState);
509 if (psidH.loadAddress == 0) 486 if (psidH.loadAddress == 0)
510 /* COULD SOMEONE EXPLAIN WHY DO WE NEED THIS +2 STRIP???? */ 487 {
488 /* Strip load address (2 first bytes) */
511 xs_md5_append(&inState, &songData[2], iRes-2); 489 xs_md5_append(&inState, &songData[2], iRes-2);
512 else 490 } else {
491 /* Append "as is" */
513 xs_md5_append(&inState, songData, iRes); 492 xs_md5_append(&inState, songData, iRes);
493 }
494
495
496 #ifdef XS_SIDBUF_DYNAMIC
497 /* Free buffer */
498 g_free(songData);
499 #endif
514 500
515 /* Append header data to hash */ 501 /* Append header data to hash */
516 #define XSADDHASH(QDATAB) { ib8[0] = (QDATAB & 0xff); ib8[1] = (QDATAB >> 8); xs_md5_append(&inState, (guint8 *) &ib8, sizeof(ib8)); } 502 #define XSADDHASH(QDATAB) { ib8[0] = (QDATAB & 0xff); ib8[1] = (QDATAB >> 8); xs_md5_append(&inState, (guint8 *) &ib8, sizeof(ib8)); }
517 503
518 XSADDHASH(psidH.initAddress) 504 XSADDHASH(psidH.initAddress)
550 536
551 return 0; 537 return 0;
552 } 538 }
553 539
554 540
555 /* 541 /* Get song lengths
556 * Get song lengths 542 */
557 */ 543 t_xs_sldb_node * xs_sldb_get(t_xs_sldb *db, gchar *pcFilename)
558 t_xs_sldb_node * xs_songlen_get(gchar *pcFilename)
559 { 544 {
560 t_xs_sldb_node *pResult; 545 t_xs_sldb_node *pResult;
561 t_xs_md5hash dbHash; 546 t_xs_md5hash dbHash;
562 547
563 pResult = NULL; 548 /* Get the hash and then look up from db */
564 549 if (xs_get_sid_hash(pcFilename, dbHash) == 0)
565 if (xs_cfg.songlenDBEnable) 550 pResult = xs_sldb_get_node(db, dbHash);
566 { 551 else
567 /* Get the hash and then look up from db */ 552 pResult = NULL;
568 if (xs_get_sid_hash(pcFilename, dbHash) == 0) 553
569 {
570 pResult = xs_sldb_get(dbHash);
571 }
572 }
573
574 return pResult; 554 return pResult;
575 } 555 }