Mercurial > hg > xmms-sid
comparison src/xmms-sid.c @ 230:608f31f6c095
Raw cleanup.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 21 Dec 2004 09:25:03 +0000 |
parents | 2986069309c6 |
children | e613873c3379 |
comparison
equal
deleted
inserted
replaced
229:7bb9e20e3092 | 230:608f31f6c095 |
---|---|
57 #include "xs_sidplay1.h" | 57 #include "xs_sidplay1.h" |
58 #endif | 58 #endif |
59 #ifdef HAVE_SIDPLAY2 | 59 #ifdef HAVE_SIDPLAY2 |
60 #include "xs_sidplay2.h" | 60 #include "xs_sidplay2.h" |
61 #endif | 61 #endif |
62 | |
63 | |
64 /* | |
65 * Structure defining methods/functions of each player | |
66 */ | |
67 typedef struct { | |
68 gint plrIdent; | |
69 gboolean (*plrIsOurFile)(gchar *); | |
70 gboolean (*plrInit)(t_xs_status *); | |
71 void (*plrClose)(t_xs_status *); | |
72 gboolean (*plrInitSong)(t_xs_status *); | |
73 guint (*plrFillBuffer)(t_xs_status *, gchar *, guint); | |
74 gboolean (*plrLoadSID)(t_xs_status *, gchar *); | |
75 void (*plrDeleteSID)(t_xs_status *); | |
76 t_xs_tune* (*plrGetSIDInfo)(gchar *); | |
77 } t_xs_player; | |
78 | 62 |
79 | 63 |
80 /* | 64 /* |
81 * List of players and links to their functions | 65 * List of players and links to their functions |
82 */ | 66 */ |
105 | 89 |
106 | 90 |
107 /* | 91 /* |
108 * Global variables | 92 * Global variables |
109 */ | 93 */ |
110 struct t_xs_cfg xs_cfg; | 94 t_xs_status xs_status; |
111 t_xs_status xs_status; | 95 XS_MUTEX(xs_status); |
112 t_xs_player *xs_player = NULL; | 96 static pthread_t xs_decode_thread; |
113 static pthread_t xs_decode_thread; | 97 |
114 static pthread_mutex_t xs_mutex = PTHREAD_MUTEX_INITIALIZER; | 98 static GtkWidget *xs_subctrl = NULL; |
115 static GtkWidget *xs_subctrl = NULL; | 99 static GtkObject *xs_subctrl_adj = NULL; |
116 static GtkObject *xs_subctrl_adj = NULL; | 100 XS_MUTEX(xs_subctrl); |
117 static t_xs_tune *xs_fileinfotune = NULL; | |
118 static t_xs_stil_node *xs_fileinfostil = NULL; | |
119 | |
120 | 101 |
121 void xs_subctrl_close(void); | 102 void xs_subctrl_close(void); |
122 void xs_subctrl_update(void); | 103 void xs_subctrl_update(void); |
123 | 104 |
124 | 105 |
125 /* | 106 /* |
126 * Re-initialize some settings | 107 * Initialization functions |
127 */ | 108 */ |
128 void xs_reinit(void) | 109 void xs_reinit(void) |
129 { | 110 { |
130 gint iPlayer; | 111 gint iPlayer; |
131 gboolean isInitialized; | 112 gboolean isInitialized; |
151 if (xs_playerlist[iPlayer].plrIdent == xs_cfg.playerEngine) | 132 if (xs_playerlist[iPlayer].plrIdent == xs_cfg.playerEngine) |
152 { | 133 { |
153 if (xs_playerlist[iPlayer].plrInit(&xs_status)) | 134 if (xs_playerlist[iPlayer].plrInit(&xs_status)) |
154 { | 135 { |
155 isInitialized = TRUE; | 136 isInitialized = TRUE; |
156 xs_player = (t_xs_player *) &xs_playerlist[iPlayer]; | 137 xs_status.sidPlayer = (t_xs_player *) &xs_playerlist[iPlayer]; |
157 } | 138 } |
158 } | 139 } |
159 iPlayer++; | 140 iPlayer++; |
160 } | 141 } |
161 | 142 |
165 while ((iPlayer < xs_nplayerlist) && !isInitialized) | 146 while ((iPlayer < xs_nplayerlist) && !isInitialized) |
166 { | 147 { |
167 if (xs_playerlist[iPlayer].plrInit(&xs_status)) | 148 if (xs_playerlist[iPlayer].plrInit(&xs_status)) |
168 { | 149 { |
169 isInitialized = TRUE; | 150 isInitialized = TRUE; |
170 xs_player = (t_xs_player *) &xs_playerlist[iPlayer]; | 151 xs_status.sidPlayer = (t_xs_player *) &xs_playerlist[iPlayer]; |
171 } else | 152 } else |
172 iPlayer++; | 153 iPlayer++; |
173 } | 154 } |
174 | 155 |
175 XSDEBUG("init#2: %s, %i\n", (isInitialized) ? "OK" : "FAILED", iPlayer); | 156 XSDEBUG("init#2: %s, %i\n", (isInitialized) ? "OK" : "FAILED", iPlayer); |
176 | 157 |
177 /* Initialize song-length database */ | 158 /* Initialize song-length database */ |
178 xs_songlen_close(); | 159 xs_songlen_close(); |
179 if (xs_cfg.songlenDBEnable && (xs_songlen_init() < 0)) | 160 if (xs_cfg.songlenDBEnable && (xs_songlen_init() != 0)) |
180 { | 161 { |
181 XSERR("Error initializing song-length database!\n"); | 162 XSERR("Error initializing song-length database!\n"); |
182 } | 163 } |
183 | 164 |
184 /* Initialize STIL database */ | 165 /* Initialize STIL database */ |
185 xs_stil_close(); | 166 xs_stil_close(); |
186 if (xs_cfg.stilDBEnable && (xs_stil_init() < 0)) | 167 if (xs_cfg.stilDBEnable && (xs_stil_init() != 0)) |
187 { | 168 { |
188 XSERR("Error initializing STIL database!\n"); | 169 XSERR("Error initializing STIL database!\n"); |
189 } | 170 } |
190 } | 171 } |
191 | 172 |
216 XSDEBUG("xs_close(): shutting down...\n"); | 197 XSDEBUG("xs_close(): shutting down...\n"); |
217 | 198 |
218 /* Stop playing, free structures */ | 199 /* Stop playing, free structures */ |
219 xs_stop(); | 200 xs_stop(); |
220 | 201 |
221 xs_tune_free(xs_status.pTune); | 202 xs_tuneinfo_free(xs_status.tuneInfo); |
222 xs_status.pTune = NULL; | 203 xs_status.tuneInfo = NULL; |
223 | 204 |
224 xs_player->plrDeleteSID(&xs_status); | 205 xs_status.sidPlayer->plrDeleteSID(&xs_status); |
225 xs_player->plrClose(&xs_status); | 206 xs_status.sidPlayer->plrClose(&xs_status); |
226 | 207 |
227 xs_songlen_close(); | 208 xs_songlen_close(); |
228 xs_stil_close(); | 209 xs_stil_close(); |
229 | 210 |
230 XSDEBUG("shutdown finished.\n"); | 211 XSDEBUG("shutdown finished.\n"); |
235 * Check whether the given file is handled by this plugin | 216 * Check whether the given file is handled by this plugin |
236 */ | 217 */ |
237 gint xs_is_our_file(gchar *pcFilename) | 218 gint xs_is_our_file(gchar *pcFilename) |
238 { | 219 { |
239 gchar *pcExt; | 220 gchar *pcExt; |
240 assert(xs_player); | 221 assert(xs_status.sidPlayer); |
241 | 222 |
242 /* Check the filename */ | 223 /* Check the filename */ |
243 if (pcFilename == NULL) | 224 if (pcFilename == NULL) |
244 return FALSE; | 225 return FALSE; |
245 | 226 |
246 /* Try to detect via detection routine, if required */ | 227 /* Try to detect via detection routine, if required */ |
247 if (xs_cfg.detectMagic && xs_player->plrIsOurFile(pcFilename)) | 228 if (xs_cfg.detectMagic && xs_status.sidPlayer->plrIsOurFile(pcFilename)) |
248 return TRUE; | 229 return TRUE; |
249 | 230 |
250 /* Detect just by checking filename extension */ | 231 /* Detect just by checking filename extension */ |
251 pcExt = xs_strrchr(pcFilename, '.'); | 232 pcExt = xs_strrchr(pcFilename, '.'); |
252 if (pcExt) | 233 if (pcExt) |
272 * Main playing thread loop | 253 * Main playing thread loop |
273 */ | 254 */ |
274 void *xs_play_loop(void *argPointer) | 255 void *xs_play_loop(void *argPointer) |
275 { | 256 { |
276 t_xs_status myStatus; | 257 t_xs_status myStatus; |
277 t_xs_tune *myTune; | 258 t_xs_tuneinfo *myTune; |
278 gboolean audioOpen = FALSE, doPlay = FALSE; | 259 gboolean audioOpen = FALSE, doPlay = FALSE; |
279 guint audioGot; | 260 guint audioGot; |
280 gint songLength; | 261 gint songLength; |
281 gchar audioBuffer[XS_BUFSIZE]; | 262 gchar audioBuffer[XS_BUFSIZE]; |
282 | 263 |
283 /* Initialize */ | 264 /* Initialize */ |
284 pthread_mutex_lock(&xs_mutex); | 265 XSDEBUG("entering player thread\n"); |
285 XSDEBUG("entering play thread\n"); | 266 XS_MUTEX_LOCK(xs_status); |
286 memcpy(&myStatus, &xs_status, sizeof(t_xs_status)); | 267 memcpy(&myStatus, &xs_status, sizeof(t_xs_status)); |
287 myTune = xs_status.pTune; | 268 myTune = xs_status.tuneInfo; |
288 pthread_mutex_unlock(&xs_mutex); | 269 XS_MUTEX_UNLOCK(xs_status); |
289 | 270 |
290 | 271 |
291 /* | 272 /* |
292 * Main player loop: while not stopped, loop here - play subtunes | 273 * Main player loop: while not stopped, loop here - play subtunes |
293 */ | 274 */ |
294 doPlay = TRUE; | 275 doPlay = TRUE; |
295 while (xs_status.isPlaying && doPlay) | 276 while (xs_status.isPlaying && doPlay) |
296 { | 277 { |
297 pthread_mutex_lock(&xs_mutex); | 278 XS_MUTEX_LOCK(xs_status); |
298 myStatus.currSong = xs_status.currSong; | 279 myStatus.currSong = xs_status.currSong; |
299 pthread_mutex_unlock(&xs_mutex); | 280 XS_MUTEX_UNLOCK(xs_status); |
281 XS_MUTEX_LOCK(xs_subctrl); | |
300 xs_subctrl_update(); | 282 xs_subctrl_update(); |
283 XS_MUTEX_UNLOCK(xs_subctrl); | |
301 | 284 |
302 XSDEBUG("subtune #%i selected, initializing...\n", myStatus.currSong); | 285 XSDEBUG("subtune #%i selected, initializing...\n", myStatus.currSong); |
303 | 286 |
304 songLength = myTune->subTunes[myStatus.currSong - 1].tuneLength; | 287 songLength = myTune->subTunes[myStatus.currSong - 1].tuneLength; |
305 | 288 |
306 /* Check minimum playtime */ | 289 /* Check minimum playtime */ |
290 XS_MUTEX_LOCK(xs_cfg); | |
307 if (xs_cfg.playMinTimeEnable) | 291 if (xs_cfg.playMinTimeEnable) |
308 { | 292 { |
309 if (songLength < xs_cfg.playMinTime) | 293 if (songLength < xs_cfg.playMinTime) |
310 songLength = xs_cfg.playMinTime; | 294 songLength = xs_cfg.playMinTime; |
311 } | 295 } |
296 XS_MUTEX_UNLOCK(xs_cfg); | |
312 | 297 |
313 /* Initialize song */ | 298 /* Initialize song */ |
314 if (!xs_player->plrInitSong(&myStatus)) | 299 if (!myStatus.sidPlayer->plrInitSong(&myStatus)) |
315 { | 300 { |
316 XSERR("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n", | 301 XSERR("Couldn't initialize SID-tune '%s' (sub-tune #%i)!\n", |
317 myTune->tuneFilename, myStatus.currSong); | 302 myTune->sidFilename, myStatus.currSong); |
318 goto xs_err_exit; | 303 goto xs_err_exit; |
319 } | 304 } |
320 | 305 |
321 | 306 |
322 /* Get song information for current subtune */ | 307 /* Get song information for current subtune */ |
331 /* Open the audio output */ | 316 /* Open the audio output */ |
332 if (!xs_plugin_ip.output->open_audio(myStatus.audioFormat, myStatus.audioFrequency, myStatus.audioChannels)) | 317 if (!xs_plugin_ip.output->open_audio(myStatus.audioFormat, myStatus.audioFrequency, myStatus.audioChannels)) |
333 { | 318 { |
334 XSERR("Couldn't open XMMS audio output (fmt=%x, freq=%i, nchan=%i)!\n", | 319 XSERR("Couldn't open XMMS audio output (fmt=%x, freq=%i, nchan=%i)!\n", |
335 myStatus.audioFormat, myStatus.audioFrequency, myStatus.audioChannels); | 320 myStatus.audioFormat, myStatus.audioFrequency, myStatus.audioChannels); |
336 pthread_mutex_lock(&xs_mutex); | 321 |
322 XS_MUTEX_LOCK(xs_status); | |
337 xs_status.isError = TRUE; | 323 xs_status.isError = TRUE; |
338 pthread_mutex_unlock(&xs_mutex); | 324 XS_MUTEX_UNLOCK(xs_status); |
339 goto xs_err_exit; | 325 goto xs_err_exit; |
340 } | 326 } |
341 | 327 |
342 audioOpen = TRUE; | 328 audioOpen = TRUE; |
343 | 329 |
345 * Play the subtune | 331 * Play the subtune |
346 */ | 332 */ |
347 while (xs_status.isPlaying && myStatus.isPlaying && (xs_status.currSong == myStatus.currSong)) | 333 while (xs_status.isPlaying && myStatus.isPlaying && (xs_status.currSong == myStatus.currSong)) |
348 { | 334 { |
349 /* Render audio data */ | 335 /* Render audio data */ |
350 audioGot = xs_player->plrFillBuffer(&myStatus, audioBuffer, XS_BUFSIZE); | 336 audioGot = myStatus.sidPlayer->plrFillBuffer(&myStatus, audioBuffer, XS_BUFSIZE); |
351 | 337 |
352 /* I <3 visualice/haujobb */ | 338 /* I <3 visualice/haujobb */ |
353 xs_plugin_ip.add_vis_pcm( | 339 xs_plugin_ip.add_vis_pcm( |
354 xs_plugin_ip.output->written_time(), | 340 xs_plugin_ip.output->written_time(), |
355 myStatus.audioFormat, myStatus.audioChannels, | 341 myStatus.audioFormat, myStatus.audioChannels, |
364 /* Output audio */ | 350 /* Output audio */ |
365 if (xs_status.isPlaying && (xs_status.currSong == myStatus.currSong)) | 351 if (xs_status.isPlaying && (xs_status.currSong == myStatus.currSong)) |
366 xs_plugin_ip.output->write_audio(audioBuffer, audioGot); | 352 xs_plugin_ip.output->write_audio(audioBuffer, audioGot); |
367 | 353 |
368 /* Check if we have played enough */ | 354 /* Check if we have played enough */ |
355 XS_MUTEX_LOCK(xs_cfg); | |
369 if (xs_cfg.playMaxTimeEnable) | 356 if (xs_cfg.playMaxTimeEnable) |
370 { | 357 { |
371 if (xs_cfg.playMaxTimeUnknown) | 358 if (xs_cfg.playMaxTimeUnknown) |
372 { | 359 { |
373 if ((songLength == -1) && | 360 if ((songLength == -1) && |
376 } else { | 363 } else { |
377 if (xs_plugin_ip.output->output_time() >= (xs_cfg.playMaxTime * 1000)) | 364 if (xs_plugin_ip.output->output_time() >= (xs_cfg.playMaxTime * 1000)) |
378 myStatus.isPlaying = FALSE; | 365 myStatus.isPlaying = FALSE; |
379 } | 366 } |
380 } | 367 } |
368 XS_MUTEX_UNLOCK(xs_cfg); | |
381 | 369 |
382 if (songLength > 0) | 370 if (songLength > 0) |
383 { | 371 { |
384 if (xs_plugin_ip.output->output_time() >= (songLength * 1000)) | 372 if (xs_plugin_ip.output->output_time() >= (songLength * 1000)) |
385 myStatus.isPlaying = FALSE; | 373 myStatus.isPlaying = FALSE; |
409 } | 397 } |
410 | 398 |
411 /* Exit the playing thread */ | 399 /* Exit the playing thread */ |
412 XSDEBUG("exiting thread, bye.\n"); | 400 XSDEBUG("exiting thread, bye.\n"); |
413 | 401 |
414 pthread_mutex_lock(&xs_mutex); | 402 XS_MUTEX_LOCK(xs_status); |
415 xs_status.isPlaying = FALSE; | 403 xs_status.isPlaying = FALSE; |
416 pthread_mutex_unlock(&xs_mutex); | 404 XS_MUTEX_UNLOCK(xs_status); |
417 pthread_exit(NULL); | 405 pthread_exit(NULL); |
418 } | 406 } |
419 | 407 |
420 | 408 |
421 /* | 409 /* |
424 * Usually you would also initialize the output-plugin, but | 412 * Usually you would also initialize the output-plugin, but |
425 * this is XMMS-SID and we do it on the player thread instead. | 413 * this is XMMS-SID and we do it on the player thread instead. |
426 */ | 414 */ |
427 void xs_play_file(gchar *pcFilename) | 415 void xs_play_file(gchar *pcFilename) |
428 { | 416 { |
417 assert(xs_status.sidPlayer); | |
418 | |
429 XSDEBUG("play '%s'\n", pcFilename); | 419 XSDEBUG("play '%s'\n", pcFilename); |
430 | 420 |
431 /* Get tune information */ | 421 /* Get tune information */ |
432 if ((xs_status.pTune = xs_player->plrGetSIDInfo(pcFilename)) == NULL) | 422 if ((xs_status.tuneInfo = xs_status.sidPlayer->plrGetSIDInfo(pcFilename)) == NULL) |
433 return; | 423 return; |
434 | 424 |
435 /* Initialize the tune */ | 425 /* Initialize the tune */ |
436 if (!xs_player->plrLoadSID(&xs_status, pcFilename)) | 426 if (!xs_status.sidPlayer->plrLoadSID(&xs_status, pcFilename)) |
437 { | 427 { |
438 xs_tune_free(xs_status.pTune); | 428 xs_tuneinfo_free(xs_status.tuneInfo); |
439 xs_status.pTune = NULL; | 429 xs_status.tuneInfo = NULL; |
440 return; | 430 return; |
441 } | 431 } |
442 | 432 |
443 XSDEBUG("load ok\n"); | 433 XSDEBUG("load ok\n"); |
444 | 434 |
445 /* Set general status information */ | 435 /* Set general status information */ |
446 xs_status.isPlaying = TRUE; | 436 xs_status.isPlaying = TRUE; |
447 xs_status.isError = FALSE; | 437 xs_status.isError = FALSE; |
448 xs_status.currSong = xs_status.pTune->startTune; | 438 xs_status.currSong = xs_status.tuneInfo->startTune; |
449 | 439 |
450 /* Start the playing thread! */ | 440 /* Start the playing thread! */ |
451 if (pthread_create(&xs_decode_thread, NULL, xs_play_loop, NULL) < 0) | 441 if (pthread_create(&xs_decode_thread, NULL, xs_play_loop, NULL) < 0) |
452 { | 442 { |
453 XSERR("Couldn't start playing thread! Possible reason reported by system: %s\n", strerror(errno)); | 443 XSERR("Couldn't start playing thread! Possible reason reported by system: %s\n", strerror(errno)); |
454 xs_tune_free(xs_status.pTune); | 444 xs_tuneinfo_free(xs_status.tuneInfo); |
455 xs_status.pTune = NULL; | 445 xs_status.tuneInfo = NULL; |
456 xs_player->plrDeleteSID(&xs_status); | 446 xs_status.sidPlayer->plrDeleteSID(&xs_status); |
457 } | 447 } |
458 | 448 |
459 XSDEBUG("systems should be up?\n"); | 449 XSDEBUG("systems should be up?\n"); |
460 } | 450 } |
461 | 451 |
477 | 467 |
478 if (xs_status.isPlaying) | 468 if (xs_status.isPlaying) |
479 { | 469 { |
480 /* Stop playing */ | 470 /* Stop playing */ |
481 XSDEBUG("stopping...\n"); | 471 XSDEBUG("stopping...\n"); |
482 pthread_mutex_lock(&xs_mutex); | 472 XS_MUTEX_LOCK(xs_status); |
483 xs_status.isPlaying = FALSE; | 473 xs_status.isPlaying = FALSE; |
484 pthread_mutex_unlock(&xs_mutex); | 474 XS_MUTEX_UNLOCK(xs_status); |
485 pthread_join(xs_decode_thread, NULL); | 475 pthread_join(xs_decode_thread, NULL); |
486 } | 476 } |
487 | 477 |
488 /* Free tune information */ | 478 /* Free tune information */ |
489 xs_player->plrDeleteSID(&xs_status); | 479 xs_status.sidPlayer->plrDeleteSID(&xs_status); |
490 xs_tune_free(xs_status.pTune); | 480 xs_tuneinfo_free(xs_status.tuneInfo); |
491 xs_status.pTune = NULL; | 481 xs_status.tuneInfo = NULL; |
492 | 482 |
493 /* Update subtune control */ | 483 /* Update subtune control */ |
494 xs_subctrl_update(); | 484 xs_subctrl_update(); |
495 } | 485 } |
496 | 486 |
504 xs_plugin_ip.output->pause(pauseState); | 494 xs_plugin_ip.output->pause(pauseState); |
505 } | 495 } |
506 | 496 |
507 | 497 |
508 /* | 498 /* |
499 * Set or change sub-tune | |
500 */ | |
501 void xs_set_subtune(int n) | |
502 { | |
503 XS_MUTEX_LOCK(xs_status); | |
504 | |
505 if (xs_status.tuneInfo && xs_status.isPlaying) | |
506 { | |
507 if ((n >= 1) && (n <= xs_status.tuneInfo->nsubTunes)) | |
508 xs_status.currSong = n; | |
509 } | |
510 | |
511 XS_MUTEX_UNLOCK(xs_status); | |
512 | |
513 xs_subctrl_update(); | |
514 } | |
515 | |
516 | |
517 void xs_change_subtune(int n) | |
518 { | |
519 XS_MUTEX_LOCK(xs_status); | |
520 | |
521 if (xs_status.tuneInfo && xs_status.isPlaying) | |
522 { | |
523 n += xs_status.currSong; | |
524 | |
525 if ((n >= 1) && (n <= xs_status.tuneInfo->nsubTunes)) | |
526 xs_status.currSong = n; | |
527 } | |
528 | |
529 XS_MUTEX_UNLOCK(xs_status); | |
530 | |
531 xs_subctrl_update(); | |
532 } | |
533 | |
534 | |
535 /* | |
509 * Pop-up subtune selector | 536 * Pop-up subtune selector |
510 */ | 537 */ |
511 #define LUW(x...) lookup_widget(xs_fileinfowin, ## x) | 538 void xs_subctrl_setsong(void) |
539 { | |
540 xs_set_subtune(GTK_ADJUSTMENT(xs_subctrl_adj)->value); | |
541 } | |
542 | |
543 | |
544 void xs_subctrl_prevsong(void) | |
545 { | |
546 xs_change_subtune(-1); | |
547 } | |
548 | |
549 | |
550 void xs_subctrl_nextsong(void) | |
551 { | |
552 xs_change_subtune( 1); | |
553 } | |
554 | |
512 | 555 |
513 void xs_subctrl_update(void) | 556 void xs_subctrl_update(void) |
514 { | 557 { |
515 GtkAdjustment *tmpAdj; | 558 GtkAdjustment *tmpAdj; |
516 gboolean isEnabled; | 559 gboolean isEnabled; |
560 | |
561 XS_MUTEX_LOCK(xs_status); | |
517 | 562 |
518 /* Check if control window exists, we are currently playing and have a tune */ | 563 /* Check if control window exists, we are currently playing and have a tune */ |
519 if (xs_subctrl) | 564 if (xs_subctrl) |
520 { | 565 { |
521 if (xs_status.pTune && xs_status.isPlaying) | 566 if (xs_status.tuneInfo && xs_status.isPlaying) |
522 { | 567 { |
568 XS_MUTEX_LOCK(xs_subctrl); | |
523 tmpAdj = GTK_ADJUSTMENT(xs_subctrl_adj); | 569 tmpAdj = GTK_ADJUSTMENT(xs_subctrl_adj); |
524 | 570 |
525 tmpAdj->value = xs_status.currSong; | 571 tmpAdj->value = xs_status.currSong; |
526 tmpAdj->lower = 1; | 572 tmpAdj->lower = 1; |
527 tmpAdj->upper = xs_status.pTune->nsubTunes; | 573 tmpAdj->upper = xs_status.tuneInfo->nsubTunes; |
528 gtk_adjustment_value_changed(tmpAdj); | 574 gtk_adjustment_value_changed(tmpAdj); |
575 XS_MUTEX_UNLOCK(xs_subctrl); | |
529 } else | 576 } else |
530 xs_subctrl_close(); | 577 xs_subctrl_close(); |
531 } | 578 } |
532 | 579 |
533 if (xs_fileinfowin) | 580 XS_MUTEX_UNLOCK(xs_status); |
534 { | |
535 /* Check if we are currently playing and have a tune */ | |
536 if (xs_status.pTune && xs_status.isPlaying && (xs_status.pTune->nsubTunes > 1)) | |
537 { | |
538 tmpAdj = gtk_range_get_adjustment(GTK_RANGE(LUW("fileinfo_subctrl_adj"))); | |
539 | |
540 tmpAdj->value = xs_status.currSong; | |
541 tmpAdj->lower = 1; | |
542 tmpAdj->upper = xs_status.pTune->nsubTunes; | |
543 gtk_adjustment_value_changed(tmpAdj); | |
544 isEnabled = TRUE; | |
545 } else | |
546 isEnabled = FALSE; | |
547 | |
548 /* Enable or disable subtune-control in fileinfo window */ | |
549 gtk_widget_set_sensitive(LUW("fileinfo_subctrl_prev"), isEnabled); | |
550 gtk_widget_set_sensitive(LUW("fileinfo_subctrl_adj"), isEnabled); | |
551 gtk_widget_set_sensitive(LUW("fileinfo_subctrl_next"), isEnabled); | |
552 } | |
553 } | |
554 | |
555 | |
556 void xs_fileinfo_setsong(void) | |
557 { | |
558 pthread_mutex_lock(&xs_mutex); | |
559 xs_status.currSong = gtk_range_get_adjustment(GTK_RANGE(LUW("fileinfo_subctrl_adj")))->value; | |
560 pthread_mutex_unlock(&xs_mutex); | |
561 } | |
562 | |
563 | |
564 void xs_subctrl_setsong(void) | |
565 { | |
566 pthread_mutex_lock(&xs_mutex); | |
567 xs_status.currSong = GTK_ADJUSTMENT(xs_subctrl_adj)->value; | |
568 pthread_mutex_unlock(&xs_mutex); | |
569 } | |
570 | |
571 | |
572 void xs_subctrl_prevsong(void) | |
573 { | |
574 if (xs_status.pTune && xs_status.isPlaying) | |
575 { | |
576 pthread_mutex_lock(&xs_mutex); | |
577 if (xs_status.currSong > 1) | |
578 xs_status.currSong--; | |
579 pthread_mutex_unlock(&xs_mutex); | |
580 } | |
581 | |
582 xs_subctrl_update(); | |
583 } | |
584 | |
585 | |
586 void xs_subctrl_nextsong(void) | |
587 { | |
588 if (xs_status.pTune && xs_status.isPlaying) | |
589 { | |
590 pthread_mutex_lock(&xs_mutex); | |
591 if (xs_status.currSong < xs_status.pTune->nsubTunes) | |
592 xs_status.currSong++; | |
593 pthread_mutex_unlock(&xs_mutex); | |
594 } | |
595 | |
596 xs_subctrl_update(); | |
597 } | 581 } |
598 | 582 |
599 | 583 |
600 void xs_subctrl_close(void) | 584 void xs_subctrl_close(void) |
601 { | 585 { |
586 XS_MUTEX_LOCK(xs_subctrl); | |
602 if (xs_subctrl) | 587 if (xs_subctrl) |
603 { | 588 { |
604 gtk_widget_destroy(xs_subctrl); | 589 gtk_widget_destroy(xs_subctrl); |
605 xs_subctrl = NULL; | 590 xs_subctrl = NULL; |
606 } | 591 } |
592 XS_MUTEX_UNLOCK(xs_subctrl); | |
607 } | 593 } |
608 | 594 |
609 | 595 |
610 gboolean xs_subctrl_keypress(GtkWidget *win, GdkEventKey *ev) | 596 gboolean xs_subctrl_keypress(GtkWidget *win, GdkEventKey *ev) |
611 { | 597 { |
618 | 604 |
619 void xs_subctrl_open() | 605 void xs_subctrl_open() |
620 { | 606 { |
621 GtkWidget *frame25, *hbox15, *subctrl_prev, *subctrl_current, *subctrl_next; | 607 GtkWidget *frame25, *hbox15, *subctrl_prev, *subctrl_current, *subctrl_next; |
622 | 608 |
623 if (!xs_status.pTune || !xs_status.isPlaying || | 609 XS_MUTEX_LOCK(xs_subctrl); |
624 xs_subctrl || (xs_status.pTune->nsubTunes <= 1)) return; | 610 |
611 if (!xs_status.tuneInfo || !xs_status.isPlaying || | |
612 xs_subctrl || (xs_status.tuneInfo->nsubTunes <= 1)) | |
613 { | |
614 XS_MUTEX_UNLOCK(xs_subctrl); | |
615 return; | |
616 } | |
625 | 617 |
626 /* Create the pop-up window */ | 618 /* Create the pop-up window */ |
627 xs_subctrl = gtk_window_new (GTK_WINDOW_DIALOG); | 619 xs_subctrl = gtk_window_new (GTK_WINDOW_DIALOG); |
628 gtk_widget_set_name (xs_subctrl, "xs_subctrl"); | 620 gtk_widget_set_name (xs_subctrl, "xs_subctrl"); |
629 gtk_object_set_data (GTK_OBJECT (xs_subctrl), "xs_subctrl", xs_subctrl); | 621 gtk_object_set_data (GTK_OBJECT (xs_subctrl), "xs_subctrl", xs_subctrl); |
654 | 646 |
655 subctrl_prev = gtk_button_new_with_label (" < "); | 647 subctrl_prev = gtk_button_new_with_label (" < "); |
656 gtk_widget_set_name (subctrl_prev, "subctrl_prev"); | 648 gtk_widget_set_name (subctrl_prev, "subctrl_prev"); |
657 gtk_box_pack_start (GTK_BOX (hbox15), subctrl_prev, FALSE, FALSE, 0); | 649 gtk_box_pack_start (GTK_BOX (hbox15), subctrl_prev, FALSE, FALSE, 0); |
658 | 650 |
659 xs_subctrl_adj = gtk_adjustment_new (xs_status.currSong, 1, xs_status.pTune->nsubTunes, 1, 1, 0); | 651 xs_subctrl_adj = gtk_adjustment_new (xs_status.currSong, 1, xs_status.tuneInfo->nsubTunes, 1, 1, 0); |
660 gtk_signal_connect (GTK_OBJECT (xs_subctrl_adj), "value_changed", | 652 gtk_signal_connect (GTK_OBJECT (xs_subctrl_adj), "value_changed", |
661 GTK_SIGNAL_FUNC (xs_subctrl_setsong), NULL); | 653 GTK_SIGNAL_FUNC (xs_subctrl_setsong), NULL); |
662 | 654 |
663 subctrl_current = gtk_hscale_new (GTK_ADJUSTMENT(xs_subctrl_adj)); | 655 subctrl_current = gtk_hscale_new (GTK_ADJUSTMENT(xs_subctrl_adj)); |
664 gtk_widget_set_name (subctrl_current, "subctrl_current"); | 656 gtk_widget_set_name (subctrl_current, "subctrl_current"); |
679 | 671 |
680 gtk_signal_connect (GTK_OBJECT (xs_subctrl), "key_press_event", | 672 gtk_signal_connect (GTK_OBJECT (xs_subctrl), "key_press_event", |
681 GTK_SIGNAL_FUNC (xs_subctrl_keypress), NULL); | 673 GTK_SIGNAL_FUNC (xs_subctrl_keypress), NULL); |
682 | 674 |
683 gtk_widget_show_all(xs_subctrl); | 675 gtk_widget_show_all(xs_subctrl); |
676 | |
677 XS_MUTEX_UNLOCK(xs_subctrl); | |
684 } | 678 } |
685 | 679 |
686 | 680 |
687 /* | 681 /* |
688 * Set the time-seek position | 682 * Set the time-seek position |
694 * other method of seeking is used (keyboard, etc.) | 688 * other method of seeking is used (keyboard, etc.) |
695 */ | 689 */ |
696 void xs_seek(gint iTime) | 690 void xs_seek(gint iTime) |
697 { | 691 { |
698 /* Check status */ | 692 /* Check status */ |
699 if (!xs_status.pTune || !xs_status.isPlaying) return; | 693 XS_MUTEX_LOCK(xs_status); |
700 | 694 if (!xs_status.tuneInfo || !xs_status.isPlaying) |
701 /* Act according to settings */ | 695 { |
696 XS_MUTEX_UNLOCK(xs_status); | |
697 return; | |
698 } | |
699 | |
700 /* Act according to settings */ | |
701 XS_MUTEX_LOCK(xs_cfg); | |
702 switch (xs_cfg.subsongControl) { | 702 switch (xs_cfg.subsongControl) { |
703 case XS_SSC_SEEK: | 703 case XS_SSC_SEEK: |
704 if (iTime < xs_status.lastTime) | 704 if (iTime < xs_status.lastTime) |
705 xs_subctrl_prevsong(); | 705 xs_change_subtune(-1); |
706 else | 706 else |
707 if (iTime > xs_status.lastTime) | 707 if (iTime > xs_status.lastTime) |
708 xs_subctrl_nextsong(); | 708 xs_change_subtune(1); |
709 break; | 709 break; |
710 | 710 |
711 case XS_SSC_POPUP: | 711 case XS_SSC_POPUP: |
712 xs_subctrl_open(); | 712 xs_subctrl_open(); |
713 break; | 713 break; |
714 | 714 |
715 /* If we have song-position patch, check settings */ | 715 /* If we have song-position patch, check settings */ |
716 #ifdef HAVE_SONG_POSITION | 716 #ifdef HAVE_SONG_POSITION |
717 case XS_SSC_PATCH: | 717 case XS_SSC_PATCH: |
718 pthread_mutex_lock(&xs_mutex); | 718 if ((iTime > 0) && (iTime <= xs_status.tuneInfo->nsubTunes)) |
719 | |
720 if ((iTime > 0) && (iTime <= xs_status.pTune->nsubTunes)) | |
721 xs_status.currSong = iTime; | 719 xs_status.currSong = iTime; |
722 | |
723 pthread_mutex_unlock(&xs_mutex); | |
724 break; | 720 break; |
725 #endif | 721 #endif |
726 | |
727 default: | |
728 break; | |
729 } | 722 } |
723 | |
724 XS_MUTEX_UNLOCK(xs_cfg); | |
725 XS_MUTEX_UNLOCK(xs_status); | |
730 } | 726 } |
731 | 727 |
732 | 728 |
733 /* | 729 /* |
734 * Return the playing "position/time" | 730 * Return the playing "position/time" |
738 * error dialog. -1 means end of song (if one was playing currently). | 734 * error dialog. -1 means end of song (if one was playing currently). |
739 */ | 735 */ |
740 gint xs_get_time(void) | 736 gint xs_get_time(void) |
741 { | 737 { |
742 /* If errorflag is set, return -2 to signal it to XMMS's idle callback */ | 738 /* If errorflag is set, return -2 to signal it to XMMS's idle callback */ |
739 XS_MUTEX_LOCK(xs_status); | |
740 | |
743 if (xs_status.isError) | 741 if (xs_status.isError) |
742 { | |
743 XS_MUTEX_UNLOCK(xs_status); | |
744 return -2; | 744 return -2; |
745 } | |
745 | 746 |
746 /* If there is no tune, return -1 */ | 747 /* If there is no tune, return -1 */ |
747 if (!xs_status.pTune) | 748 if (!xs_status.tuneInfo) |
749 { | |
750 XS_MUTEX_UNLOCK(xs_status); | |
748 return -1; | 751 return -1; |
752 } | |
749 | 753 |
750 /* If tune has ended, return -1 */ | 754 /* If tune has ended, return -1 */ |
751 if (!xs_status.isPlaying) | 755 if (!xs_status.isPlaying) |
756 { | |
757 XS_MUTEX_UNLOCK(xs_status); | |
752 return -1; | 758 return -1; |
759 } | |
753 | 760 |
754 /* Let's see what we do */ | 761 /* Let's see what we do */ |
762 XS_MUTEX_LOCK(xs_cfg); | |
755 switch (xs_cfg.subsongControl) { | 763 switch (xs_cfg.subsongControl) { |
756 case XS_SSC_SEEK: | 764 case XS_SSC_SEEK: |
757 xs_status.lastTime = (xs_plugin_ip.output->output_time() / 1000); | 765 xs_status.lastTime = (xs_plugin_ip.output->output_time() / 1000); |
758 break; | 766 break; |
759 | 767 |
760 #ifdef HAVE_SONG_POSITION | 768 #ifdef HAVE_SONG_POSITION |
761 case XS_SSC_PATCH: | 769 case XS_SSC_PATCH: |
762 pthread_mutex_lock(&xs_mutex); | 770 set_song_position(xs_status.currSong, 1, xs_status.tuneInfo->nsubTunes); |
763 set_song_position(xs_status.currSong, 1, xs_status.pTune->nsubTunes); | |
764 pthread_mutex_unlock(&xs_mutex); | |
765 break; | 771 break; |
766 #endif | 772 #endif |
767 } | 773 } |
768 | 774 |
775 XS_MUTEX_UNLOCK(xs_cfg); | |
776 XS_MUTEX_UNLOCK(xs_status); | |
777 | |
769 /* Return output time reported by audio output plugin */ | 778 /* Return output time reported by audio output plugin */ |
770 return xs_plugin_ip.output->output_time(); | 779 return xs_plugin_ip.output->output_time(); |
771 } | 780 } |
772 | 781 |
773 | 782 |
777 * Subsequent changes to information are made by the player thread, | 786 * Subsequent changes to information are made by the player thread, |
778 * which uses xs_plugin_ip.set_info(); | 787 * which uses xs_plugin_ip.set_info(); |
779 */ | 788 */ |
780 void xs_get_song_info(gchar *songFilename, gchar **songTitle, gint *songLength) | 789 void xs_get_song_info(gchar *songFilename, gchar **songTitle, gint *songLength) |
781 { | 790 { |
782 t_xs_tune *pInfo; | 791 t_xs_tuneinfo *pInfo; |
783 gint tmpInt; | 792 gint tmpInt; |
784 | 793 |
785 /* Get tune information from emulation engine */ | 794 /* Get tune information from emulation engine */ |
786 pInfo = xs_player->plrGetSIDInfo(songFilename); | 795 pInfo = xs_status.sidPlayer->plrGetSIDInfo(songFilename); |
787 if (!pInfo) return; | 796 if (!pInfo) return; |
788 | 797 |
789 /* Get sub-tune information, if available */ | 798 /* Get sub-tune information, if available */ |
790 if ((pInfo->startTune >= 0) && (pInfo->startTune <= pInfo->nsubTunes)) | 799 if ((pInfo->startTune >= 0) && (pInfo->startTune <= pInfo->nsubTunes)) |
791 { | 800 { |
797 else | 806 else |
798 (*songLength) = (tmpInt * 1000); | 807 (*songLength) = (tmpInt * 1000); |
799 } | 808 } |
800 | 809 |
801 /* Free tune information */ | 810 /* Free tune information */ |
802 xs_tune_free(pInfo); | 811 xs_tuneinfo_free(pInfo); |
803 } | 812 } |
804 | 813 |
805 | 814 |
806 /* | 815 /* Allocate a new tune information structure |
807 * Allocate a new tune structure | 816 */ |
808 */ | 817 t_xs_tuneinfo *xs_tuneinfo_new(gchar *pcFilename, gint nsubTunes, gint startTune, |
809 t_xs_tune *xs_tune_new(gchar *pcFilename, gint nsubTunes, gint startTune, | 818 gchar *sidName, gchar *sidComposer, gchar *sidCopyright, |
810 gchar *tuneName, gchar *tuneComposer, gchar *tuneCopyright) | 819 gint loadAddr, gint initAddr, gint playAddr, gint dataFileLen) |
811 { | 820 { |
812 t_xs_tune *pResult; | 821 t_xs_tuneinfo *pResult; |
813 | 822 |
814 pResult = (t_xs_tune *) g_malloc0(sizeof(t_xs_tune)); | 823 pResult = (t_xs_tuneinfo *) g_malloc0(sizeof(t_xs_tuneinfo)); |
815 if (!pResult) return NULL; | 824 if (!pResult) return NULL; |
816 | 825 |
817 pResult->tuneFilename = g_strdup(pcFilename); | 826 pResult->sidFilename = g_strdup(pcFilename); |
818 if (!pResult->tuneFilename) | 827 if (!pResult->sidFilename) |
819 { | 828 { |
820 g_free(pResult); | 829 g_free(pResult); |
821 return NULL; | 830 return NULL; |
822 } | 831 } |
823 | 832 |
824 pResult->tuneName = g_strdup(tuneName); | 833 pResult->sidName = g_strdup(sidName); |
825 pResult->tuneComposer = g_strdup(tuneComposer); | 834 pResult->sidComposer = g_strdup(sidComposer); |
826 pResult->tuneCopyright = g_strdup(tuneCopyright); | 835 pResult->sidCopyright = g_strdup(sidCopyright); |
827 pResult->nsubTunes = nsubTunes; | 836 pResult->nsubTunes = nsubTunes; |
828 pResult->startTune = startTune; | 837 pResult->startTune = startTune; |
838 | |
839 pResult->loadAddr = loadAddr; | |
840 pResult->initAddr = initAddr; | |
841 pResult->playAddr = playAddr; | |
842 pResult->dataFileLen = dataFileLen; | |
829 | 843 |
830 return pResult; | 844 return pResult; |
831 } | 845 } |
832 | 846 |
833 | 847 |
834 /* | 848 /* Free given tune information structure |
835 * Free tune information | 849 */ |
836 */ | 850 void xs_tuneinfo_free(t_xs_tuneinfo *pTune) |
837 void xs_tune_free(t_xs_tune *pTune) | |
838 { | 851 { |
839 gint i; | 852 gint i; |
840 if (!pTune) return; | 853 if (!pTune) return; |
841 | 854 |
842 g_free(pTune->tuneFilename); pTune->tuneFilename = NULL; | 855 g_free(pTune->sidFilename); pTune->sidFilename = NULL; |
843 g_free(pTune->tuneName); pTune->tuneName = NULL; | 856 g_free(pTune->sidName); pTune->sidName = NULL; |
844 g_free(pTune->tuneComposer); pTune->tuneComposer = NULL; | 857 g_free(pTune->sidComposer); pTune->sidComposer = NULL; |
845 g_free(pTune->tuneCopyright); pTune->tuneCopyright = NULL; | 858 g_free(pTune->sidCopyright); pTune->sidCopyright = NULL; |
846 | 859 |
847 for (i = 0; i < pTune->nsubTunes; i++) | 860 for (i = 0; i < pTune->nsubTunes; i++) |
848 { | 861 { |
849 if (pTune->subTunes[i].tuneTitle) | 862 if (pTune->subTunes[i].tuneTitle) |
850 { | 863 { |
854 } | 867 } |
855 | 868 |
856 g_free(pTune); | 869 g_free(pTune); |
857 } | 870 } |
858 | 871 |
872 | |
873 void xs_fileinfo_ok(void) | |
874 { | |
875 } |