Mercurial > audlegacy
annotate Plugins/Input/sid/xs_length.c @ 553:82346a6312c2 trunk
[svn] make WMA plugin strings translatable
author | nenolod |
---|---|
date | Wed, 01 Feb 2006 13:09:00 -0800 |
parents | d0e9693d2115 |
children | e4089d6b0fcf |
rev | line source |
---|---|
269 | 1 /* |
2 XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS) | |
3 | |
4 Get song length from SLDB for PSID/RSID files | |
5 | |
6 Programmed and designed by Matti 'ccr' Hamalainen <ccr@tnsp.org> | |
7 (C) Copyright 1999-2005 Tecnic Software productions (TNSP) | |
8 | |
9 This program is free software; you can redistribute it and/or modify | |
10 it under the terms of the GNU General Public License as published by | |
11 the Free Software Foundation; either version 2 of the License, or | |
12 (at your option) any later version. | |
13 | |
14 This program is distributed in the hope that it will be useful, | |
15 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 GNU General Public License for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with this program; if not, write to the Free Software | |
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
22 */ | |
23 #include "xs_length.h" | |
24 #include "xs_support.h" | |
25 #include "xs_config.h" | |
26 #include <stdio.h> | |
27 #include <stdlib.h> | |
28 #include <ctype.h> | |
29 #include <string.h> | |
30 | |
31 | |
32 /* Database handling functions | |
33 */ | |
34 static t_xs_sldb_node *xs_sldb_node_new(void) | |
35 { | |
36 t_xs_sldb_node *pResult; | |
37 | |
38 /* Allocate memory for new node */ | |
39 pResult = (t_xs_sldb_node *) g_malloc0(sizeof(t_xs_sldb_node)); | |
40 if (!pResult) | |
41 return NULL; | |
42 | |
43 return pResult; | |
44 } | |
45 | |
46 | |
47 static void xs_sldb_node_free(t_xs_sldb_node * pNode) | |
48 { | |
49 if (pNode) { | |
50 /* Nothing much to do here ... */ | |
51 g_free(pNode); | |
52 } | |
53 } | |
54 | |
55 | |
56 /* Insert given node to db linked list | |
57 */ | |
58 static void xs_sldb_node_insert(t_xs_sldb * db, t_xs_sldb_node * pNode) | |
59 { | |
60 assert(db); | |
61 | |
62 if (db->pNodes) { | |
63 /* The first node's pPrev points to last node */ | |
64 LPREV = db->pNodes->pPrev; /* New node's prev = Previous last node */ | |
65 db->pNodes->pPrev->pNext = pNode; /* Previous last node's next = New node */ | |
66 db->pNodes->pPrev = pNode; /* New last node = New node */ | |
67 LNEXT = NULL; /* But next is NULL! */ | |
68 } else { | |
69 db->pNodes = pNode; /* First node ... */ | |
70 LPREV = pNode; /* ... it's also last */ | |
71 LNEXT = NULL; /* But next is NULL! */ | |
72 } | |
73 } | |
74 | |
75 | |
76 /* Parses a time-entry in SLDB format | |
77 */ | |
78 static gint32 xs_sldb_gettime(gchar * pcStr, size_t * piPos) | |
79 { | |
80 gint32 iResult, iTemp; | |
81 | |
82 /* Check if it starts with a digit */ | |
83 if (isdigit(pcStr[*piPos])) { | |
84 /* Get minutes-field */ | |
85 iResult = 0; | |
86 while (isdigit(pcStr[*piPos])) | |
87 iResult = (iResult * 10) + (pcStr[(*piPos)++] - '0'); | |
88 | |
89 iResult *= 60; | |
90 | |
91 /* Check the field separator char */ | |
92 if (pcStr[*piPos] == ':') { | |
93 /* Get seconds-field */ | |
94 (*piPos)++; | |
95 iTemp = 0; | |
96 while (isdigit(pcStr[*piPos])) | |
97 iTemp = (iTemp * 10) + (pcStr[(*piPos)++] - '0'); | |
98 | |
99 iResult += iTemp; | |
100 } else | |
101 iResult = -2; | |
102 } else | |
103 iResult = -1; | |
104 | |
105 /* Ignore and skip the possible attributes */ | |
106 while (pcStr[*piPos] && !isspace(pcStr[*piPos])) | |
107 (*piPos)++; | |
108 | |
109 return iResult; | |
110 } | |
111 | |
112 | |
113 /* Read database to memory | |
114 */ | |
115 gint xs_sldb_read(t_xs_sldb * db, gchar * dbFilename) | |
116 { | |
117 FILE *inFile; | |
118 gchar inLine[XS_BUF_SIZE]; | |
119 size_t lineNum, linePos; | |
120 gboolean iOK; | |
121 t_xs_sldb_node *tmpNode; | |
122 assert(db); | |
123 | |
124 /* Try to open the file */ | |
125 if ((inFile = fopen(dbFilename, "ra")) == NULL) { | |
126 XSERR("Could not open SongLengthDB '%s'\n", dbFilename); | |
127 return -1; | |
128 } | |
129 | |
130 /* Read and parse the data */ | |
131 lineNum = 0; | |
132 | |
133 while (!feof(inFile)) { | |
134 fgets(inLine, XS_BUF_SIZE, inFile); | |
135 inLine[XS_BUF_SIZE - 1] = 0; | |
136 lineNum++; | |
137 | |
138 /* Check if it is datafield */ | |
139 if (isxdigit(inLine[0])) { | |
140 /* Check the length of the hash */ | |
141 linePos = 0; | |
142 while (isxdigit(inLine[linePos])) | |
143 linePos++; | |
144 | |
145 if (linePos != XS_MD5HASH_LENGTH_CH) { | |
146 XSERR("Invalid hash in SongLengthDB file '%s' line #%d!\n", dbFilename, lineNum); | |
147 } else { | |
148 /* Allocate new node */ | |
149 if ((tmpNode = xs_sldb_node_new()) == NULL) { | |
150 XSERR("Error allocating new node. Fatal error.\n"); | |
151 exit(5); | |
152 } | |
153 | |
154 /* Get hash value */ | |
155 #if (XS_MD5HASH_LENGTH != 16) | |
156 #error Mismatch in hashcode length. Fix here. | |
157 #endif | |
158 sscanf(&inLine[0], "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", | |
159 (guint *) & (tmpNode->md5Hash[0]), (guint *) & (tmpNode->md5Hash[1]), | |
160 (guint *) & (tmpNode->md5Hash[2]), (guint *) & (tmpNode->md5Hash[3]), | |
161 (guint *) & (tmpNode->md5Hash[4]), (guint *) & (tmpNode->md5Hash[5]), | |
162 (guint *) & (tmpNode->md5Hash[6]), (guint *) & (tmpNode->md5Hash[7]), | |
163 (guint *) & (tmpNode->md5Hash[8]), (guint *) & (tmpNode->md5Hash[9]), | |
164 (guint *) & (tmpNode->md5Hash[10]), (guint *) & (tmpNode->md5Hash[11]), | |
165 (guint *) & (tmpNode->md5Hash[12]), (guint *) & (tmpNode->md5Hash[13]), | |
166 (guint *) & (tmpNode->md5Hash[14]), (guint *) & (tmpNode->md5Hash[15])); | |
167 | |
168 /* Get playtimes */ | |
169 if (inLine[linePos] != 0) { | |
170 if (inLine[linePos] != '=') { | |
171 XSERR("'=' expected in SongLengthDB file '%s' line #%d, column #%d\n", | |
172 dbFilename, lineNum, linePos); | |
173 | |
174 xs_sldb_node_free(tmpNode); | |
175 } else { | |
176 /* First playtime is after '=' */ | |
177 linePos++; | |
178 iOK = TRUE; | |
179 | |
180 while ((linePos < strlen(inLine)) && iOK) { | |
181 xs_findnext(inLine, &linePos); | |
182 | |
183 if (tmpNode->nLengths < XS_STIL_MAXENTRY) { | |
184 tmpNode->sLengths[tmpNode->nLengths] = | |
185 xs_sldb_gettime(inLine, &linePos); | |
186 tmpNode->nLengths++; | |
187 } else | |
188 iOK = FALSE; | |
189 } | |
190 | |
191 /* Add an node to db in memory */ | |
192 if (iOK) | |
193 xs_sldb_node_insert(db, tmpNode); | |
194 else | |
195 xs_sldb_node_free(tmpNode); | |
196 } | |
197 } | |
198 } | |
199 } else if ((inLine[0] != ';') && (inLine[0] != '[')) { | |
200 XSERR("Invalid line in SongLengthDB file '%s' line #%d\n", dbFilename, lineNum); | |
201 } | |
202 | |
203 } /* while */ | |
204 | |
205 /* Close the file */ | |
206 fclose(inFile); | |
207 | |
208 return 0; | |
209 } | |
210 | |
211 | |
212 /* Compare two given MD5-hashes. | |
213 * Return: 0 if equal | |
214 * negative if testHash1 < testHash2 | |
215 * positive if testHash1 > testHash2 | |
216 */ | |
217 static gint xs_sldb_cmphash(t_xs_md5hash testHash1, t_xs_md5hash testHash2) | |
218 { | |
219 register gint i, res = 0; | |
220 | |
221 /* Compute difference of hashes */ | |
222 for (i = 0; (i < XS_MD5HASH_LENGTH) && (!res); i++) | |
223 res = (testHash1[i] - testHash2[i]); | |
224 | |
225 return res; | |
226 } | |
227 | |
228 | |
229 /* Get node from db index via binary search | |
230 */ | |
231 static t_xs_sldb_node *xs_sldb_get_node(t_xs_sldb * db, t_xs_md5hash pHash) | |
232 { | |
233 gint iStartNode, iEndNode, iQNode, r, i; | |
234 gboolean iFound; | |
235 t_xs_sldb_node *pResult; | |
236 | |
237 /* Check the database pointers */ | |
238 if (!db || !db->pNodes || !db->ppIndex) | |
239 return NULL; | |
240 | |
241 /* Look-up via index using binary search */ | |
242 pResult = NULL; | |
243 iStartNode = 0; | |
244 iEndNode = (db->n - 1); | |
245 iQNode = (iEndNode / 2); | |
246 iFound = FALSE; | |
247 | |
248 while ((!iFound) && ((iEndNode - iStartNode) > XS_BIN_BAILOUT)) { | |
249 r = xs_sldb_cmphash(pHash, db->ppIndex[iQNode]->md5Hash); | |
250 if (r < 0) { | |
251 /* Hash was in the <- LEFT side */ | |
252 iEndNode = iQNode; | |
253 iQNode = iStartNode + ((iEndNode - iStartNode) / 2); | |
254 } else if (r > 0) { | |
255 /* Hash was in the RIGHT -> side */ | |
256 iStartNode = iQNode; | |
257 iQNode = iStartNode + ((iEndNode - iStartNode) / 2); | |
258 } else | |
259 iFound = TRUE; | |
260 } | |
261 | |
262 /* If not found already */ | |
263 if (!iFound) { | |
264 /* Search the are linearly */ | |
265 iFound = FALSE; | |
266 i = iStartNode; | |
267 while ((i <= iEndNode) && (!iFound)) { | |
268 if (xs_sldb_cmphash(pHash, db->ppIndex[i]->md5Hash) == 0) | |
269 iFound = TRUE; | |
270 else | |
271 i++; | |
272 } | |
273 | |
274 /* Check the result */ | |
275 if (iFound) | |
276 pResult = db->ppIndex[i]; | |
277 | |
278 } else { | |
279 /* Found via binary search */ | |
280 pResult = db->ppIndex[iQNode]; | |
281 } | |
282 | |
283 return pResult; | |
284 } | |
285 | |
286 | |
287 /* Compare two nodes | |
288 */ | |
289 static gint xs_sldb_cmp(const void *pNode1, const void *pNode2) | |
290 { | |
291 /* We assume here that we never ever get NULL-pointers or similar */ | |
292 return xs_sldb_cmphash((*(t_xs_sldb_node **) pNode1)->md5Hash, (*(t_xs_sldb_node **) pNode2)->md5Hash); | |
293 } | |
294 | |
295 | |
296 /* (Re)create index | |
297 */ | |
298 gint xs_sldb_index(t_xs_sldb * db) | |
299 { | |
300 t_xs_sldb_node *pCurr; | |
301 gint i; | |
302 assert(db); | |
303 | |
304 /* Free old index */ | |
305 if (db->ppIndex) { | |
306 g_free(db->ppIndex); | |
307 db->ppIndex = NULL; | |
308 } | |
309 | |
310 /* Get size of db */ | |
311 pCurr = db->pNodes; | |
312 db->n = 0; | |
313 while (pCurr) { | |
314 db->n++; | |
315 pCurr = pCurr->pNext; | |
316 } | |
317 | |
318 /* Check number of nodes */ | |
319 if (db->n > 0) { | |
320 /* Allocate memory for index-table */ | |
321 db->ppIndex = (t_xs_sldb_node **) g_malloc(sizeof(t_xs_sldb_node *) * db->n); | |
322 if (!db->ppIndex) | |
323 return -1; | |
324 | |
325 /* Get node-pointers to table */ | |
326 i = 0; | |
327 pCurr = db->pNodes; | |
328 while (pCurr && (i < db->n)) { | |
329 db->ppIndex[i++] = pCurr; | |
330 pCurr = pCurr->pNext; | |
331 } | |
332 | |
333 /* Sort the indexes */ | |
334 qsort(db->ppIndex, db->n, sizeof(t_xs_sldb_node *), xs_sldb_cmp); | |
335 } | |
336 | |
337 return 0; | |
338 } | |
339 | |
340 | |
341 /* Free a given song-length database | |
342 */ | |
343 void xs_sldb_free(t_xs_sldb * db) | |
344 { | |
345 t_xs_sldb_node *pCurr, *pNext; | |
346 | |
347 if (!db) | |
348 return; | |
349 | |
350 /* Free the memory allocated for nodes */ | |
351 pCurr = db->pNodes; | |
352 while (pCurr) { | |
353 pNext = pCurr->pNext; | |
354 xs_sldb_node_free(pCurr); | |
355 pCurr = pNext; | |
356 } | |
357 | |
358 db->pNodes = NULL; | |
359 | |
360 /* Free memory allocated for index */ | |
361 if (db->ppIndex) { | |
362 g_free(db->ppIndex); | |
363 db->ppIndex = NULL; | |
364 } | |
365 | |
366 /* Free structure */ | |
367 db->n = 0; | |
368 g_free(db); | |
369 } | |
370 | |
371 | |
372 /* Compute md5hash of given SID-file | |
373 */ | |
374 typedef struct | |
375 { | |
376 gchar magicID[4]; /* "PSID" / "RSID" magic identifier */ | |
377 guint16 version, /* Version number */ | |
378 dataOffset, /* Start of actual c64 data in file */ | |
379 loadAddress, /* Loading address */ | |
380 initAddress, /* Initialization address */ | |
381 playAddress, /* Play one frame */ | |
382 nSongs, /* Number of subsongs */ | |
383 startSong; /* Default starting song */ | |
384 guint32 speed; /* Speed */ | |
385 gchar sidName[32]; /* Descriptive text-fields, ASCIIZ */ | |
386 gchar sidAuthor[32]; | |
387 gchar sidCopyright[32]; | |
388 } t_xs_psidv1_header; | |
389 | |
390 | |
391 typedef struct | |
392 { | |
393 guint16 flags; /* Flags */ | |
394 guint8 startPage, pageLength; | |
395 guint16 reserved; | |
396 } t_xs_psidv2_header; | |
397 | |
398 | |
399 static gint xs_get_sid_hash(gchar * pcFilename, t_xs_md5hash hash) | |
400 { | |
401 FILE *inFile; | |
402 t_xs_md5state inState; | |
403 t_xs_psidv1_header psidH; | |
404 t_xs_psidv2_header psidH2; | |
405 #ifdef XS_BUF_DYNAMIC | |
406 guint8 *songData; | |
407 #else | |
408 guint8 songData[XS_SIDBUF_SIZE]; | |
409 #endif | |
410 guint8 ib8[2], i8; | |
411 gint iIndex, iRes; | |
412 | |
413 /* Try to open the file */ | |
414 if ((inFile = fopen(pcFilename, "rb")) == NULL) | |
415 return -1; | |
416 | |
417 /* Read PSID header in */ | |
418 xs_rd_str(inFile, psidH.magicID, sizeof(psidH.magicID)); | |
419 if ((psidH.magicID[0] != 'P' && psidH.magicID[0] != 'R') || | |
420 (psidH.magicID[1] != 'S') || (psidH.magicID[2] != 'I') || (psidH.magicID[3] != 'D')) { | |
421 fclose(inFile); | |
422 return -2; | |
423 } | |
424 | |
425 psidH.version = xs_rd_be16(inFile); | |
426 psidH.dataOffset = xs_rd_be16(inFile); | |
427 psidH.loadAddress = xs_rd_be16(inFile); | |
428 psidH.initAddress = xs_rd_be16(inFile); | |
429 psidH.playAddress = xs_rd_be16(inFile); | |
430 psidH.nSongs = xs_rd_be16(inFile); | |
431 psidH.startSong = xs_rd_be16(inFile); | |
432 psidH.speed = xs_rd_be32(inFile); | |
433 | |
434 xs_rd_str(inFile, psidH.sidName, sizeof(psidH.sidName)); | |
435 xs_rd_str(inFile, psidH.sidAuthor, sizeof(psidH.sidAuthor)); | |
436 xs_rd_str(inFile, psidH.sidCopyright, sizeof(psidH.sidCopyright)); | |
437 | |
438 /* Check if we need to load PSIDv2NG header ... */ | |
439 if (psidH.version == 2) { | |
440 /* Yes, we need to */ | |
441 psidH2.flags = xs_rd_be16(inFile); | |
442 psidH2.startPage = fgetc(inFile); | |
443 psidH2.pageLength = fgetc(inFile); | |
444 psidH2.reserved = xs_rd_be16(inFile); | |
445 } | |
446 #ifdef XS_BUF_DYNAMIC | |
447 /* Allocate buffer */ | |
448 songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE * sizeof(guint8)); | |
449 if (!songData) { | |
450 fclose(inFile); | |
451 return -3; | |
452 } | |
453 #endif | |
454 | |
455 /* Read data to buffer */ | |
456 iRes = fread(songData, sizeof(guint8), XS_SIDBUF_SIZE, inFile); | |
457 fclose(inFile); | |
458 | |
459 /* Initialize and start MD5-hash calculation */ | |
460 xs_md5_init(&inState); | |
461 if (psidH.loadAddress == 0) { | |
462 /* Strip load address (2 first bytes) */ | |
463 xs_md5_append(&inState, &songData[2], iRes - 2); | |
464 } else { | |
465 /* Append "as is" */ | |
466 xs_md5_append(&inState, songData, iRes); | |
467 } | |
468 | |
469 | |
470 #ifdef XS_BUF_DYNAMIC | |
471 /* Free buffer */ | |
472 g_free(songData); | |
473 #endif | |
474 | |
475 /* Append header data to hash */ | |
476 #define XSADDHASH(QDATAB) { ib8[0] = (QDATAB & 0xff); ib8[1] = (QDATAB >> 8); xs_md5_append(&inState, (guint8 *) &ib8, sizeof(ib8)); } | |
477 | |
478 XSADDHASH(psidH.initAddress) | |
479 XSADDHASH(psidH.playAddress) | |
480 XSADDHASH(psidH.nSongs) | |
481 #undef XSADDHASH | |
482 /* Append song speed data to hash */ | |
483 i8 = 0; | |
484 for (iIndex = 0; (iIndex < psidH.nSongs) && (iIndex < 32); iIndex++) { | |
485 i8 = (psidH.speed & (1 << iIndex)) ? 60 : 0; | |
486 xs_md5_append(&inState, &i8, sizeof(i8)); | |
487 } | |
488 | |
489 /* Rest of songs (more than 32) */ | |
490 for (iIndex = 32; iIndex < psidH.nSongs; iIndex++) { | |
491 xs_md5_append(&inState, &i8, sizeof(i8)); | |
492 } | |
493 | |
494 | |
495 /* PSIDv2NG specific */ | |
496 if (psidH.version == 2) { | |
497 /* SEE SIDPLAY HEADERS FOR INFO */ | |
498 i8 = (psidH2.flags >> 2) & 3; | |
499 if (i8 == 2) | |
500 xs_md5_append(&inState, &i8, sizeof(i8)); | |
501 } | |
502 | |
503 /* Calculate the hash */ | |
504 xs_md5_finish(&inState, hash); | |
505 | |
506 return 0; | |
507 } | |
508 | |
509 | |
510 /* Get song lengths | |
511 */ | |
512 t_xs_sldb_node *xs_sldb_get(t_xs_sldb * db, gchar * pcFilename) | |
513 { | |
514 t_xs_sldb_node *pResult; | |
515 t_xs_md5hash dbHash; | |
516 | |
517 /* Get the hash and then look up from db */ | |
518 if (xs_get_sid_hash(pcFilename, dbHash) == 0) | |
519 pResult = xs_sldb_get_node(db, dbHash); | |
520 else | |
521 pResult = NULL; | |
522 | |
523 return pResult; | |
524 } | |
525 | |
526 | |
527 /* | |
528 * These should be moved out of this module some day ... | |
529 */ | |
530 static t_xs_sldb *xs_sldb_db = NULL; | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
531 extern GStaticMutex xs_cfg_mutex; |
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
532 GStaticMutex xs_sldb_db_mutex = G_STATIC_MUTEX_INIT; |
269 | 533 |
534 gint xs_songlen_init(void) | |
535 { | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
536 g_static_mutex_lock(&xs_cfg_mutex); |
269 | 537 |
538 if (!xs_cfg.songlenDBPath) { | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
539 g_static_mutex_unlock(&xs_cfg_mutex); |
269 | 540 return -1; |
541 } | |
542 | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
543 g_static_mutex_lock(&xs_sldb_db_mutex); |
269 | 544 |
545 /* Check if already initialized */ | |
546 if (xs_sldb_db) | |
547 xs_sldb_free(xs_sldb_db); | |
548 | |
549 /* Allocate database */ | |
550 xs_sldb_db = (t_xs_sldb *) g_malloc0(sizeof(t_xs_sldb)); | |
551 if (!xs_sldb_db) { | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
552 g_static_mutex_unlock(&xs_cfg_mutex); |
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
553 g_static_mutex_unlock(&xs_sldb_db_mutex); |
269 | 554 return -2; |
555 } | |
556 | |
557 /* Read the database */ | |
558 if (xs_sldb_read(xs_sldb_db, xs_cfg.songlenDBPath) != 0) { | |
559 xs_sldb_free(xs_sldb_db); | |
560 xs_sldb_db = NULL; | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
561 g_static_mutex_unlock(&xs_cfg_mutex); |
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
562 g_static_mutex_unlock(&xs_sldb_db_mutex); |
269 | 563 return -3; |
564 } | |
565 | |
566 /* Create index */ | |
567 if (xs_sldb_index(xs_sldb_db) != 0) { | |
568 xs_sldb_free(xs_sldb_db); | |
569 xs_sldb_db = NULL; | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
570 g_static_mutex_unlock(&xs_cfg_mutex); |
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
571 g_static_mutex_unlock(&xs_sldb_db_mutex); |
269 | 572 return -4; |
573 } | |
574 | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
575 g_static_mutex_unlock(&xs_cfg_mutex); |
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
576 g_static_mutex_unlock(&xs_sldb_db_mutex); |
269 | 577 return 0; |
578 } | |
579 | |
580 | |
581 void xs_songlen_close(void) | |
582 { | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
583 g_static_mutex_lock(&xs_sldb_db_mutex); |
269 | 584 xs_sldb_free(xs_sldb_db); |
585 xs_sldb_db = NULL; | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
586 g_static_mutex_unlock(&xs_sldb_db_mutex); |
269 | 587 } |
588 | |
589 | |
590 t_xs_sldb_node *xs_songlen_get(gchar * pcFilename) | |
591 { | |
592 t_xs_sldb_node *pResult; | |
593 | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
594 g_static_mutex_lock(&xs_sldb_db_mutex); |
269 | 595 |
596 if (xs_cfg.songlenDBEnable && xs_sldb_db) | |
597 pResult = xs_sldb_get(xs_sldb_db, pcFilename); | |
598 else | |
599 pResult = NULL; | |
600 | |
304
d0e9693d2115
[svn] Convert to configdb. GThreadify and peel off layer of threading macro madness.
chainsaw
parents:
269
diff
changeset
|
601 g_static_mutex_unlock(&xs_sldb_db_mutex); |
269 | 602 |
603 return pResult; | |
604 } |