comparison src/xmms-sid.cc @ 65:bf7b647b3239

The fabled 0.8-rewrite now works to some extent
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 29 Jun 2003 22:16:04 +0000
parents d3bb914e3af3
children bf6a524cf7ca
comparison
equal deleted inserted replaced
64:d3bb914e3af3 65:bf7b647b3239
17 17
18 You should have received a copy of the GNU General Public License 18 You should have received a copy of the GNU General Public License
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 extern "C" {
23 #include <pthread.h> 22 #include <pthread.h>
24 #include <stdlib.h> 23 #include <stdlib.h>
25 #include <string.h> 24 #include <string.h>
26 #include <stdio.h> 25 #include <stdio.h>
27 #include <errno.h> 26 #include <errno.h>
27
28 extern "C" {
28 #include <xmms/plugin.h> 29 #include <xmms/plugin.h>
29 #include <xmms/util.h> 30 #include <xmms/util.h>
30 #include <xmms/titlestring.h> 31 #include <xmms/titlestring.h>
31 #include "xmms-sid.h"
32 #include "xs_interface.h" 32 #include "xs_interface.h"
33 #include "xs_glade.h" 33 #include "xs_glade.h"
34 }
35
36 #include "xmms-sid.h"
34 #include "xs_support.h" 37 #include "xs_support.h"
35 #include "xs_config.h" 38 #include "xs_config.h"
36 #include "xs_length.h" 39 #include "xs_length.h"
37 } 40
38 41
39 #ifdef HAVE_SIDPLAY1 42 #ifdef HAVE_SIDPLAY1
40 #include <sidplay/player.h> 43 #include <sidplay/player.h>
41 #include <sidplay/myendian.h> 44 #include <sidplay/myendian.h>
42 #include <sidplay/fformat.h> 45 #include <sidplay/fformat.h>
49 52
50 /* 53 /*
51 * Global variables 54 * Global variables
52 */ 55 */
53 #ifdef HAVE_SIDPLAY1 56 #ifdef HAVE_SIDPLAY1
54 static struct emuConfig xs_emuConf;
55 static emuEngine xs_emuEngine;
56 typedef sidTune t_xs_tune; 57 typedef sidTune t_xs_tune;
57 typedef struct sidTuneInfo t_xs_tuneinfo; 58 typedef struct sidTuneInfo t_xs_tuneinfo;
58 #endif 59 #endif
59 60
60 #ifdef HAVE_SIDPLAY2 61 #ifdef HAVE_SIDPLAY2
61 static struct sid2_config_t xs_emuConf;
62 static sidplay2 xs_emuEngine;
63 typedef SidTune t_xs_tune; 62 typedef SidTune t_xs_tune;
64 typedef struct SidTuneInfo t_xs_tuneinfo; 63 typedef struct SidTuneInfo t_xs_tuneinfo;
65 #endif 64 #endif
66 65
67 static GtkWidget *xs_ctrlwin = NULL; 66 #ifdef HAVE_SIDPLAY1
68 static pthread_t xs_decode_thread; 67 struct emuConfig xs_emuConf;
69 struct t_xs_cfg xs_cfg; 68 emuEngine xs_emuEngine;
70 69 #endif
71 struct { 70 #ifdef HAVE_SIDPLAY2
71 struct sid2_config_t xs_emuConf;
72 sidplay2 xs_emuEngine;
73 #endif
74
75 typedef struct {
72 gboolean isError, isPlaying, allowNext; 76 gboolean isError, isPlaying, allowNext;
73 gint currSong, nSongs; 77 gint currSong, nSongs;
74 t_xs_tune *currTune; 78 t_xs_tune *currTune;
75 gchar *currFilename; 79 gchar *currFileName;
76 } xs_status; 80 } t_xs_status;
77 81
78 pthread_mutex_t xs_mutex = PTHREAD_MUTEX_INITIALIZER; 82 static GtkWidget *xs_ctrlwin = NULL;
83 static pthread_t xs_decode_thread;
84 static pthread_mutex_t xs_mutex = PTHREAD_MUTEX_INITIALIZER;
85 struct t_xs_cfg xs_cfg;
86 t_xs_status xs_status;
87
79 88
80 gchar *xs_filetitle_get(gchar *, t_xs_tuneinfo *, gint); 89 gchar *xs_filetitle_get(gchar *, t_xs_tuneinfo *, gint);
90
81 91
82 /* 92 /*
83 * Create sub-song control window 93 * Create sub-song control window
84 */ 94 */
85 void xs_ctrlwin_open(void) 95 void xs_ctrlwin_open(void)
108 memset(&xs_cfg, 0, sizeof(xs_cfg)); 118 memset(&xs_cfg, 0, sizeof(xs_cfg));
109 119
110 xs_read_configuration(); 120 xs_read_configuration();
111 121
112 /* Initialize status */ 122 /* Initialize status */
113 xs_status.isError = FALSE; 123 memset(&xs_status, 0, sizeof(xs_status));
114 xs_status.isPlaying = FALSE; 124 xs_status.allowNext = TRUE; // Initialize to TRUE to allow first song
115 xs_status.nSongs = 0; 125
116 xs_status.currSong = 0; 126 /* Try to initialize emulator engine(s) */
117 xs_status.allowNext = TRUE; // Initialize to TRUE to allow first song 127 XSDEBUG("initializing emulator engine(s)...\n");
118 xs_status.currTune = NULL; 128
119 xs_status.currFilename = NULL;
120
121
122 /* Try to initialize libSIDPlay(s) */
123 #ifdef HAVE_SIDPLAY1 129 #ifdef HAVE_SIDPLAY1
124 if (!xs_emuEngine || !xs_emuEngine.verifyEndianess()) 130 if (!xs_emuEngine || !xs_emuEngine.verifyEndianess())
125 { 131 {
126 XSERR("Couldn't start SIDPlay1 emulator engine!\n"); 132 XSERR("Couldn't initialize SIDPlay1 emulator engine!\n");
127 return; 133 return;
128 } 134 }
129 #endif
130
131 #ifdef HAVE_SIDPLAY2
132 #endif 135 #endif
133 136
134 /* Read song-length database */ 137 /* Read song-length database */
135 if (xs_cfg.songlenDBEnable) 138 if (xs_cfg.songlenDBEnable)
136 if (xs_songlen_init() < 0) 139 if (xs_songlen_init() < 0)
142 145
143 // xs_ctrlwin_open(); 146 // xs_ctrlwin_open();
144 147
145 // FIXME FIXME FIx ME 148 // FIXME FIXME FIx ME
146 149
150 XSDEBUG("xs_init() done\n");
147 } 151 }
148 152
149 153
150 /* 154 /*
151 * Shut down XMMS-SID 155 * Shut down XMMS-SID
152 */ 156 */
153 void xs_close(void) 157 void xs_close(void)
154 { 158 {
155 XSDEBUG("shutting down...\n"); 159 XSDEBUG("xs_close(): shutting down...\n");
156 160
157 /* Stop playing */ 161 /* Stop playing */
158 xs_plugin_ip.stop(); 162 xs_stop();
159 163
160 /* Shutdown libSIDPlay(s) */ 164 /* Shutdown libSIDPlay(s) */
161 #ifdef HAVE_SIDPLAY1 165 #ifdef HAVE_SIDPLAY1
162 #endif 166 #endif
163 167
168 172
169 /* Free allocated memory */ 173 /* Free allocated memory */
170 xs_songlen_close(); 174 xs_songlen_close();
171 175
172 // FIXME FIXME: STIL-entries 176 // FIXME FIXME: STIL-entries
177 XSDEBUG("shutdown finished.\n");
173 } 178 }
174 179
175 180
176 /* 181 /*
177 * Check whether the given file is handled by this plugin 182 * Check whether the given file is handled by this plugin
178 */ 183 */
179 gint xs_is_our_file(char *fileName) 184 gint xs_is_our_file(gchar *pcFileName)
180 { 185 {
181 char *pcExt; 186 char *pcExt;
187 t_xs_tune *testTune;
182 188
183 /* Check the filename */ 189 /* Check the filename */
184 if (fileName == NULL) 190 if (pcFileName == NULL)
185 return FALSE; 191 return FALSE;
192
193 XSDEBUG("testFile('%s')\n", pcFileName);
186 194
187 /* Try to detect via libSIDPlay's detection routine, if required */ 195 /* Try to detect via libSIDPlay's detection routine, if required */
188 if (xs_cfg.detectMagic) 196 if (xs_cfg.detectMagic)
189 { 197 {
190 #ifdef HAVE_SIDPLAY1 198 testTune = new t_xs_tune(pcFileName);
191 t_xs_tune *testTune = new sidTune(fileName); 199 if (testTune == NULL) return FALSE;
192 if (!testTune) return FALSE; 200 if (testTune->getStatus())
193 if (!testTune->getStatus())
194 { 201 {
195 delete testTune; 202 delete testTune;
196 return FALSE; 203 XSDEBUG("file = OK\n");
204 return TRUE;
197 } 205 }
198 206
207 /* We DON'T fall back to filename extension checking ... */
199 delete testTune; 208 delete testTune;
200 return TRUE; 209 XSDEBUG("file = kyrpe\n");
201 #endif 210 return FALSE;
202
203 #ifdef HAVE_SIDPLAY2
204 #endif
205 } 211 }
206 212
207 /* Detect just by checking filename extension */ 213 /* Detect just by checking filename extension */
208 pcExt = xs_strrchr(fileName, '.'); 214 pcExt = xs_strrchr(pcFileName, '.');
209 if (pcExt) 215 if (pcExt)
210 { 216 {
211 pcExt++; 217 pcExt++;
212 if (!g_strcasecmp(pcExt, "psid")) return TRUE; 218 if (!g_strcasecmp(pcExt, "psid")) return TRUE;
213 if (!g_strcasecmp(pcExt, "sid")) return TRUE; 219 if (!g_strcasecmp(pcExt, "sid")) return TRUE;
214 if (!g_strcasecmp(pcExt, "dat")) return TRUE; 220 if (!g_strcasecmp(pcExt, "dat")) return TRUE;
215 if (!g_strcasecmp(pcExt, "inf")) return TRUE; 221 if (!g_strcasecmp(pcExt, "inf")) return TRUE;
216 if (!g_strcasecmp(pcExt, "info")) return TRUE; 222 if (!g_strcasecmp(pcExt, "info")) return TRUE;
217 } 223 }
218 224
225 XSDEBUG("file was KYRPE\n");
219 return FALSE; 226 return FALSE;
220 } 227 }
221 228
222 229
223 /* 230 /*
224 * Main playing thread loop 231 * Main playing thread loop
225 */ 232 */
226 static void *xs_play_loop(void *argPointer) 233 void *xs_play_loop(void *argPointer)
227 { 234 {
235 t_xs_status myStatus;
236 t_xs_tuneinfo tuneInfo;
237 gboolean audioOpen;
238 gint audioFreq, audioChannels, songLength;
239 enum AFormat audioFmt;
240 gchar audioBuffer[XS_BUFSIZE];
241
242 /* Check status */
243 XSDEBUG("entering play thread\n");
244 pthread_mutex_lock(&xs_mutex);
245 if (!xs_status.allowNext)
246 {
247 pthread_mutex_unlock(&xs_mutex);
248 pthread_exit(NULL);
249 }
250
228 /* Don't allow next song to be set yet */ 251 /* Don't allow next song to be set yet */
252 xs_status.allowNext = FALSE;
253 xs_status.isPlaying = TRUE;
254 memcpy(&myStatus, &xs_status, sizeof(t_xs_status));
255 pthread_mutex_unlock(&xs_mutex);
256
257 /* Copy and check audio options here (they might change in config while running) */
258 #ifdef HAVE_UNSIGNEDPCM
259 audioFmt = (xs_cfg.fmtBitsPerSample == XS_RES_16BIT) ? FMT_U16_NE : FMT_U8;
260 #else
261 audioFmt = (xs_cfg.fmtBitsPerSample == XS_RES_16BIT) ? FMT_S16_NE : FMT_S8;
262 #endif
263 audioFreq = xs_cfg.fmtFrequency;
264 audioChannels = (xs_cfg.fmtChannels == XS_CHN_MONO) ? 1 : 2;
265 audioOpen = FALSE;
266
267 /*
268 * Main player loop: while not stopped, loop here - play subtunes
269 */
270 while (xs_status.isPlaying)
271 {
229 pthread_mutex_lock(&xs_mutex); 272 pthread_mutex_lock(&xs_mutex);
230 xs_status.allowNext = FALSE; 273 myStatus.currSong = xs_status.currSong;
231 pthread_mutex_unlock(&xs_mutex); 274 pthread_mutex_unlock(&xs_mutex);
232 275
276 XSDEBUG("sub-song %i selected, initializing...\n", myStatus.currSong);
277
278 /* Get song length for current subtune */
279 songLength = xs_songlen_get(myStatus.currFileName, myStatus.currSong);
280
281 /* Initialize song */
282 #ifdef HAVE_SIDPLAY1
283 if ((myStatus.currTune == NULL) || !myStatus.currTune->getStatus() ||
284 !sidEmuInitializeSong(xs_emuEngine, *myStatus.currTune, myStatus.currSong))
285 #endif
286 #ifdef HAVE_SIDPLAY2
287 if ()
288 #endif
289 {
290 XSERR("Couldn't initialize SID-tune!\n");
291 pthread_mutex_lock(&xs_mutex);
292 xs_status.isError = TRUE;
293 pthread_mutex_unlock(&xs_mutex);
294 goto err_exit;
295 }
296
297 myStatus.currTune->getInfo(tuneInfo);
298
299 /* Open the audio output */
300 if (!xs_plugin_ip.output->open_audio(audioFmt, audioFreq, audioChannels))
301 {
302 XSERR("Couldn't open XMMS audio output!\n");
303 pthread_mutex_lock(&xs_mutex);
304 xs_status.isError = TRUE;
305 pthread_mutex_unlock(&xs_mutex);
306 goto err_exit;
307 }
308
309 audioOpen = TRUE;
310
311 /* Set some infoz */
312 xs_plugin_ip.set_info(tuneInfo.infoString[0], (songLength > 0) ? songLength * 1000 : -1,
313 1000 * (tuneInfo.songSpeed ? tuneInfo.songSpeed : (tuneInfo.clockSpeed == SIDTUNE_CLOCK_NTSC) ? 60 : 50),
314 audioFreq, audioChannels);
315
316 XSDEBUG("rendering audio...\n");
317
318 /* Play the tune */
319 while (xs_status.isPlaying && (xs_status.currSong == myStatus.currSong))
320 {
321 #ifdef HAVE_SIDPLAY1
322 sidEmuFillBuffer(xs_emuEngine, *myStatus.currTune, audioBuffer, XS_BUFSIZE);
323 #endif
324
325 #ifdef HAVE_SIDPLAY2
326 #endif
327
328 /* Visualice/haujobb */
329 xs_plugin_ip.add_vis_pcm(
330 xs_plugin_ip.output->written_time(),
331 audioFmt, audioChannels, XS_BUFSIZE, audioBuffer);
332
333 /* Wait a little */
334 while (xs_status.isPlaying &&
335 (xs_status.currSong == myStatus.currSong) &&
336 (xs_plugin_ip.output->buffer_free() < XS_BUFSIZE))
337 xmms_usleep(10000);
338
339 /* Output audio */
340 if (xs_status.isPlaying && (xs_status.currSong == myStatus.currSong))
341 xs_plugin_ip.output->write_audio(audioBuffer, XS_BUFSIZE);
342
343 /* Check if we have played enough */
344 if (xs_cfg.playMaxTimeEnable)
345 {
346 if (xs_cfg.playMaxTimeUnknown)
347 {
348 if ((songLength == -1) &&
349 (xs_plugin_ip.output->output_time() >= (xs_cfg.playMaxTime * 1000)))
350 xs_status.isPlaying = FALSE;
351 } else {
352 if (xs_plugin_ip.output->output_time() >= (xs_cfg.playMaxTime * 1000))
353 xs_status.isPlaying = FALSE;
354 }
355 }
356
357 if (songLength > 0)
358 {
359 if (xs_plugin_ip.output->output_time() >= (songLength * 1000))
360 xs_status.isPlaying = FALSE;
361 }
362 }
363
364 XSDEBUG("tune ended/stopped\n");
365
366 /* Close audio */
367 if (audioOpen)
368 {
369 XSDEBUG("close audio #1\n");
370 xs_plugin_ip.output->close_audio();
371 audioOpen = FALSE;
372 }
373 }
374
375 /* When exiting, delete data */
376 err_exit:
377 pthread_mutex_lock(&xs_mutex);
378 xs_status.isPlaying = FALSE;
379 pthread_mutex_unlock(&xs_mutex);
380
381 if (audioOpen)
382 {
383 XSDEBUG("close audio #2\n");
384 xs_plugin_ip.output->close_audio();
385 }
386
387 if (myStatus.currTune != NULL)
388 {
389 delete myStatus.currTune;
390 myStatus.currTune = NULL;
391 }
392
393 g_free(myStatus.currFileName);
233 394
234 /* Exit the playing thread */ 395 /* Exit the playing thread */
235 XSDEBUG("exiting thread, bye.\n"); 396 XSDEBUG("exiting thread, bye.\n");
236 return NULL; 397 pthread_mutex_lock(&xs_mutex);
398 xs_status.allowNext = TRUE;
399 pthread_mutex_unlock(&xs_mutex);
400
401 pthread_exit(NULL);
237 } 402 }
238 403
239 404
240 /* 405 /*
241 * Start playing the given file 406 * Start playing the given file
242 */ 407 */
243 void xs_play_file(char *fileName) 408 void xs_play_file(char *pcFileName)
244 { 409 {
245 t_xs_tune *newTune; 410 t_xs_tune *newTune;
246 t_xs_tuneinfo sidInf; 411 t_xs_tuneinfo tuneInfo;
247 412
248 XSDEBUG("request to load '%s'\n", fileName); 413 /* Can we set the next tune? */
249 414 XSDEBUG("request to play '%s'\n", pcFileName);
250
251 /* Initialize audio output */
252 XSDEBUG("opening audio output plugin...\n");
253 if (!xs_plugin_ip.output->open_audio(
254 ((xs_cfg.fmtBitsPerSample == 16) ? FMT_S16_NE : FMT_U8), xs_cfg.fmtFrequency,
255 ((xs_cfg.fmtChannels == XS_CHN_MONO) ? 1 : 2)))
256 {
257 XSERR("Couldn't open audio output plugin!\n");
258 delete newTune;
259 return;
260 }
261
262 415
263 /* Try to get the tune */ 416 /* Try to get the tune */
264 newTune = new t_xs_tune(fileName); 417 XSDEBUG("initializing tune from file\n");
418 newTune = new t_xs_tune(pcFileName);
265 if (newTune == NULL) return; 419 if (newTune == NULL) return;
266 420
267 XSDEBUG("tune ok, configuring SIDPlay engine\n"); 421 XSDEBUG("status: allowNext=%i, isPlaying=%i\n", xs_status.allowNext, xs_status.isPlaying);
268
269 422
270 #ifdef HAVE_SIDPLAY1 423 #ifdef HAVE_SIDPLAY1
271 /* Get current configuration */ 424 /* Get current configuration */
272 xs_emuEngine.getConfig(xs_emuConf); 425 xs_emuEngine.getConfig(xs_emuConf);
273 426
285 xs_emuConf.autoPanning = SIDEMU_NONE; 438 xs_emuConf.autoPanning = SIDEMU_NONE;
286 xs_emuConf.volumeControl = SIDEMU_NONE; 439 xs_emuConf.volumeControl = SIDEMU_NONE;
287 break; 440 break;
288 441
289 case XS_CHN_MONO: 442 case XS_CHN_MONO:
443 default:
290 xs_emuConf.channels = SIDEMU_MONO; 444 xs_emuConf.channels = SIDEMU_MONO;
291 xs_emuConf.autoPanning = SIDEMU_NONE; 445 xs_emuConf.autoPanning = SIDEMU_NONE;
292 xs_emuConf.volumeControl = SIDEMU_NONE; 446 xs_emuConf.volumeControl = SIDEMU_NONE;
293 break; 447 break;
294
295 default:
296 XSERR("Internal: Invalid channels setting. Possibly corrupted configuration file.\n");
297 delete newTune;
298 return;
299 } 448 }
300 449
301 450
302 /* Memory mode settings */ 451 /* Memory mode settings */
303 switch (xs_cfg.memoryMode) { 452 switch (xs_cfg.memoryMode) {
312 case XS_MPU_PLAYSID_ENVIRONMENT: 461 case XS_MPU_PLAYSID_ENVIRONMENT:
313 xs_emuConf.memoryMode = MPU_PLAYSID_ENVIRONMENT; 462 xs_emuConf.memoryMode = MPU_PLAYSID_ENVIRONMENT;
314 break; 463 break;
315 464
316 default: 465 default:
317 XSERR("Internal: Invalid memoryMode setting. Possibly corrupted configuration file.\n"); 466 xs_emuConf.memoryMode = MPU_BANK_SWITCHING;
318 delete newTune; 467 break;
319 return;
320 } 468 }
321 469
322 470
323 /* Clockspeed settings */ 471 /* Clockspeed settings */
324 switch (xs_cfg.clockSpeed) { 472 switch (xs_cfg.clockSpeed) {
325 case XS_CLOCK_PAL:
326 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_PAL;
327 break;
328
329 case XS_CLOCK_NTSC: 473 case XS_CLOCK_NTSC:
330 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_NTSC; 474 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_NTSC;
331 break; 475 break;
332 476
477 case XS_CLOCK_PAL:
333 default: 478 default:
334 XSERR("Internal: Invalid clockSpeed setting. Possibly corrupted configuration file.\n"); 479 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_PAL;
335 delete newTune; 480 break;
336 return;
337 } 481 }
338 482
339 483
340 /* Configure rest of the emulation */ 484 /* Configure rest of the emulation */
341 xs_emuConf.bitsPerSample = xs_cfg.fmtBitsPerSample; 485 xs_emuConf.bitsPerSample = xs_cfg.fmtBitsPerSample;
354 /* Now set the emulator configuration */ 498 /* Now set the emulator configuration */
355 xs_emuEngine.setConfig(xs_emuConf); 499 xs_emuEngine.setConfig(xs_emuConf);
356 #endif 500 #endif
357 501
358 502
359
360 #ifdef HAVE_SIDPLAY2 503 #ifdef HAVE_SIDPLAY2
361 /* Get current configuration */ 504 /* Get current configuration */
362 xs_emuConf = xs_emuEngine.config(); 505 xs_emuConf = xs_emuEngine.config();
363 506
364 /* Configure channels and stuff */ 507 /* Configure channels and stuff */
371 case XS_CHN_STEREO: 514 case XS_CHN_STEREO:
372 xs_emuConf.playback = sid2_stereo; 515 xs_emuConf.playback = sid2_stereo;
373 break; 516 break;
374 517
375 case XS_CHN_MONO: 518 case XS_CHN_MONO:
519 default:
376 xs_emuConf.playback = sid2_mono; 520 xs_emuConf.playback = sid2_mono;
377 break; 521 break;
378
379 default:
380 XSERR("Internal: Invalid channels setting. Possibly corrupted configuration file.\n");
381 delete newTune;
382 return;
383 } 522 }
384 523
385 524
386 /* Memory mode settings */ 525 /* Memory mode settings */
387 switch (xs_cfg.memoryMode) { 526 switch (xs_cfg.memoryMode) {
396 case XS_MPU_PLAYSID_ENVIRONMENT: 535 case XS_MPU_PLAYSID_ENVIRONMENT:
397 xs_emuConf.environment = sid2_envPS; 536 xs_emuConf.environment = sid2_envPS;
398 break; 537 break;
399 538
400 case XS_MPU_REAL: 539 case XS_MPU_REAL:
540 default:
401 xs_emuConf.environment = sid2_envR; 541 xs_emuConf.environment = sid2_envR;
402 break; 542 break;
403
404 default:
405 XSERR("Internal: Invalid memoryMode setting. Possibly corrupted configuration file.\n");
406 delete newTune;
407 return;
408 } 543 }
409 544
410 545
411 /* Clockspeed settings */ 546 /* Clockspeed settings */
412 switch (xs_cfg.clockSpeed) { 547 switch (xs_cfg.clockSpeed) {
413 case XS_CLOCK_PAL:
414 xs_emuConf.clockSpeed = xs_emuConf.clockDefault = SID2_CLOCK_PAL;
415 break;
416
417 case XS_CLOCK_NTSC: 548 case XS_CLOCK_NTSC:
418 xs_emuConf.clockSpeed = xs_emuConf.clockDefault = SID2_CLOCK_NTSC; 549 xs_emuConf.clockSpeed = xs_emuConf.clockDefault = SID2_CLOCK_NTSC;
419 break; 550 break;
420 551
552 case XS_CLOCK_PAL:
421 default: 553 default:
422 XSERR("Internal: Invalid clockSpeed setting. Possibly corrupted configuration file.\n"); 554 xs_emuConf.clockSpeed = xs_emuConf.clockDefault = SID2_CLOCK_PAL;
423 delete newTune; 555 break;
424 return;
425 } 556 }
426 557
427 558
428 /* Configure rest of the emulation */ 559 /* Configure rest of the emulation */
429 xs_emuConf.precision = xs_cfg.fmtBitsPerSample; 560 xs_emuConf.precision = xs_cfg.fmtBitsPerSample;
451 xs_emuEngine.config(xs_emuConf); 582 xs_emuEngine.config(xs_emuConf);
452 #endif 583 #endif
453 584
454 585
455 /* Initialize status information */ 586 /* Initialize status information */
456 XSDEBUG("initializing and starting playing thread!\n"); 587 XSDEBUG("starting playing thread!\n");
457 588
458 newTune->getInfo(sidInf); 589 newTune->getInfo(tuneInfo);
459 590
591 xs_status.isPlaying = TRUE;
460 xs_status.isError = FALSE; 592 xs_status.isError = FALSE;
461 xs_status.isPlaying = TRUE; 593 xs_status.currSong = tuneInfo.startSong;
462 xs_status.allowNext = TRUE; 594 xs_status.nSongs = tuneInfo.songs;
463 xs_status.currSong = sidInf.startSong;
464 xs_status.nSongs = sidInf.songs;
465 xs_status.currTune = newTune; 595 xs_status.currTune = newTune;
466 596 xs_status.currFileName = g_strdup(pcFileName);
467 597
468 /* Start the playing thread! */ 598 /* Start the playing thread! */
469 if (pthread_create(&xs_decode_thread, NULL, xs_play_loop, NULL) < 0) 599 if (pthread_create(&xs_decode_thread, NULL, xs_play_loop, NULL) < 0)
470 { 600 {
471 XSERR("Couldn't start playing thread! Possible reason reported by system: %s\n", strerror(errno)); 601 XSERR("Couldn't start playing thread! Possible reason reported by system: %s\n", strerror(errno));
472 delete newTune; 602 delete newTune;
473 } 603 }
474 604
605 XSDEBUG("systems should be up?\n");
606
475 /* Exit */ 607 /* Exit */
476 } 608 }
477 609
478 610
479 /* 611 /*
480 * Stop playing 612 * Stop playing
481 */ 613 */
482 void xs_stop(void) 614 void xs_stop(void)
483 { 615 {
484 /* If playing, stop. */ 616 /* If playing, stop. */
485 XSDEBUG("request to stop.\n"); 617 XSDEBUG("STOP_REQ\n");
486 618 if (xs_status.isPlaying || !xs_status.allowNext)
487 if (xs_status.isPlaying)
488 { 619 {
489 XSDEBUG("stopping...\n"); 620 XSDEBUG("stopping...\n");
490 pthread_mutex_lock(&xs_mutex); 621 pthread_mutex_lock(&xs_mutex);
491 xs_status.isPlaying = 0; 622 xs_status.isPlaying = FALSE;
492 pthread_mutex_unlock(&xs_mutex); 623 pthread_mutex_unlock(&xs_mutex);
493
494 pthread_join(xs_decode_thread, NULL); 624 pthread_join(xs_decode_thread, NULL);
495
496 xs_plugin_ip.output->close_audio();
497 } 625 }
498 } 626 }
499 627
500 628
501 /* 629 /*
509 637
510 /* 638 /*
511 * Set the time-seek position 639 * Set the time-seek position
512 * (the playing thread will do the "seeking" aka song-change) 640 * (the playing thread will do the "seeking" aka song-change)
513 */ 641 */
514 void xs_seek(int iTime) 642 void xs_seek(gint iTime)
515 { 643 {
516 #ifdef HAVE_SONG_POSITION 644 #ifdef HAVE_SONG_POSITION
517 pthread_mutex_lock(&xs_mutex); 645 pthread_mutex_lock(&xs_mutex);
518 646
519 if ((iTime > 0) && (iTime <= xs_status.nSongs) && xs_status.isPlaying) 647 if ((iTime > 0) && (iTime <= xs_status.nSongs) && xs_status.isPlaying)
527 655
528 656
529 /* 657 /*
530 * Return the playing "position/time" 658 * Return the playing "position/time"
531 */ 659 */
532 int xs_get_time(void) 660 gint xs_get_time(void)
533 { 661 {
534 pthread_mutex_lock(&xs_mutex); 662 XSDEBUG("kyrve? %i : %i\n", xs_status.isError, xs_status.isPlaying);
535 if (xs_status.isError) 663 if (xs_status.isError)
536 return -2; 664 return -2;
537 665
538 if (!xs_status.isPlaying) 666 if (!xs_status.isPlaying)
539 return -1; 667 return -1;
540 668
669
541 #ifdef HAVE_SONG_POSITION 670 #ifdef HAVE_SONG_POSITION
671 pthread_mutex_lock(&xs_mutex);
542 set_song_position(xs_status.currSong, 1, xs_status.nSongs); 672 set_song_position(xs_status.currSong, 1, xs_status.nSongs);
543 #endif
544
545 pthread_mutex_unlock(&xs_mutex); 673 pthread_mutex_unlock(&xs_mutex);
674 #endif
546 675
547 return xs_plugin_ip.output->output_time(); 676 return xs_plugin_ip.output->output_time();
548 } 677 }
549 678
550 679
551 /* 680 /*
552 * Return song information 681 * Return song information
553 */ 682 */
554 void xs_get_song_info(char *songFilename, char **songTitle, int *songLength) 683 void xs_get_song_info(gchar *songFileName, gchar **songTitle, gint *songLength)
555 { 684 {
556 t_xs_tuneinfo sidInf; 685 t_xs_tuneinfo tuneInfo;
557 t_xs_tune *testTune = new t_xs_tune(songFilename); 686 t_xs_tune *testTune;
558 gint tmpInt; 687 gint tmpInt;
559 688
560 /* Check if the tune exists and is readable */ 689 /* Check if the tune exists and is readable */
561 if (!testTune) return; 690 testTune = new t_xs_tune(songFileName);
691 if (testTune == NULL) return;
562 if (!testTune->getStatus()) 692 if (!testTune->getStatus())
563 { 693 {
564 delete testTune; 694 delete testTune;
565 return; 695 return;
566 } 696 }
567 697
568 /* Get general tune information */ 698 /* Get general tune information */
569 testTune->getInfo(sidInf); 699 testTune->getInfo(tuneInfo);
570 delete testTune; 700 delete testTune;
571 701
572 /* Get titlestring */ 702 /* Get titlestring */
573 *songTitle = xs_filetitle_get(songFilename, &sidInf, sidInf.startSong); 703 *songTitle = xs_filetitle_get(songFileName, &tuneInfo, tuneInfo.startSong);
574 704
575 /* Get song length (in milliseconds), negative if no known length */ 705 /* Get song length (in milliseconds), negative if no known length */
576 tmpInt = xs_songlen_get(songFilename, sidInf.startSong); 706 tmpInt = xs_songlen_get(songFileName, tuneInfo.startSong);
577 if (tmpInt >= 0) 707 if (tmpInt >= 0)
578 *songLength = (tmpInt * 1000); 708 *songLength = (tmpInt * 1000);
579 else 709 else
580 *songLength = -1; 710 *songLength = -1;
581 } 711 }
583 713
584 /* 714 /*
585 * Create the SID-tune description string from the tune's information 715 * Create the SID-tune description string from the tune's information
586 * formatted by the user-specified format-string. 716 * formatted by the user-specified format-string.
587 */ 717 */
588 gchar *xs_filetitle_get(gchar *pcFilename, t_xs_tuneinfo *pfInfo, gint iSubTune) 718 gchar *xs_filetitle_get(gchar *pcFileName, t_xs_tuneinfo *pfInfo, gint iSubTune)
589 { 719 {
590 gint j, iLength; 720 gint j, iLength;
591 gchar *pcStr, *pcResult; 721 gchar *pcStr, *pcResult;
592 #ifdef HAVE_XMMSEXTRA 722 #ifdef HAVE_XMMSEXTRA
593 TitleInput *ptInput; 723 TitleInput *ptInput;
594 #endif 724 #endif
595 725
596 // FIXME FIXME: get STIL-info 726 // FIXME FIXME: get STIL-info
727
597 728
598 /* Check the info strings */ 729 /* Check the info strings */
599 if (pfInfo->numberOfInfoStrings < 3) 730 if (pfInfo->numberOfInfoStrings < 3)
600 { 731 {
601 if (pfInfo->numberOfInfoStrings < 1) 732 if (pfInfo->numberOfInfoStrings < 1)
657 case '4': iLength += strlen(pfInfo->formatString); break; 788 case '4': iLength += strlen(pfInfo->formatString); break;
658 case '%': iLength++; 789 case '%': iLength++;
659 } 790 }
660 } else 791 } else
661 iLength++; 792 iLength++;
793
794 pcStr++;
662 } 795 }
663 796
664 /* Allocate memory */ 797 /* Allocate memory */
665 pcResult = (gchar *) g_malloc(iLength + 2); 798 pcResult = (gchar *) g_malloc(iLength + 2);
666 if (pcResult == NULL) 799 if (pcResult == NULL)
680 case '4': xs_strpcat(pcResult, &j, pfInfo->formatString); break; 813 case '4': xs_strpcat(pcResult, &j, pfInfo->formatString); break;
681 case '%': pcResult[j++] = '%'; break; 814 case '%': pcResult[j++] = '%'; break;
682 } 815 }
683 } else 816 } else
684 pcResult[j++] = *pcStr; 817 pcResult[j++] = *pcStr;
818
819 pcStr++;
685 } 820 }
686 821
687 pcResult[j] = 0; 822 pcResult[j] = 0;
688 } 823 }
689 824