Mercurial > hg > xmms-sid
comparison src/xmms-sid.cc @ 40:1788f4ce6a44
Numerous changes towards 0.8
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 19 Jun 2003 22:38:01 +0000 |
parents | 15250dd0c326 |
children | 0f00ebab063d |
comparison
equal
deleted
inserted
replaced
39:85a7753e2a9a | 40:1788f4ce6a44 |
---|---|
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 | 22 extern "C" { |
23 #include <pthread.h> | 23 #include <pthread.h> |
24 #include <stdlib.h> | 24 #include <stdlib.h> |
25 #include <string.h> | 25 #include <string.h> |
26 #include <stdio.h> | 26 #include <stdio.h> |
27 #include <errno.h> | 27 #include <errno.h> |
28 #include <xmms/plugin.h> | 28 #include <xmms/plugin.h> |
29 #include <xmms/util.h> | 29 #include <xmms/util.h> |
30 #include <xmms/titlestring.h> | |
30 #include "xmms-sid.h" | 31 #include "xmms-sid.h" |
32 #include "xs_support.h" | |
31 #include "xs_config.h" | 33 #include "xs_config.h" |
32 #include "xs_length.h" | 34 #include "xs_length.h" |
33 #include "xs_title.h" | 35 } |
34 | 36 |
35 extern "C++" { | 37 #ifdef HAVE_SIDPLAY1 |
36 #include <sidplay/player.h> | 38 #include <sidplay/player.h> |
37 #include <sidplay/myendian.h> | 39 #include <sidplay/myendian.h> |
38 #include <sidplay/fformat.h> | 40 #include <sidplay/fformat.h> |
39 } | 41 #endif |
42 | |
43 #ifdef HAVE_SIDPLAY2 | |
44 #include <sidplay/sidplay2.h> | |
45 #endif | |
40 | 46 |
41 | 47 |
42 /* | 48 /* |
43 * Global variables | 49 * Global variables |
44 */ | 50 */ |
51 #ifdef HAVE_SIDPLAY1 | |
45 static struct emuConfig xs_emuConf; | 52 static struct emuConfig xs_emuConf; |
46 static emuEngine xs_emuEngine; | 53 static emuEngine xs_emuEngine; |
54 typedef sidTune t_xs_tune; | |
55 #endif | |
56 | |
57 #ifdef HAVE_SIDPLAY2 | |
58 #endif | |
59 | |
47 static pthread_t xs_decode_thread; | 60 static pthread_t xs_decode_thread; |
48 struct t_xs_cfg xs_cfg; | 61 struct t_xs_cfg xs_cfg; |
49 | 62 |
50 struct { | 63 struct { |
51 int s_error, s_playing, s_songs, s_allownext; | 64 gboolean isError, isPlaying, allowNext; |
52 sidTune *s_tune; | 65 gint currSong, nSongs; |
53 gchar *s_fname; | 66 t_xs_tune *currTune; |
67 gchar *currFilename; | |
54 } xs_status; | 68 } xs_status; |
55 | 69 |
56 pthread_mutex_t xs_mutex = PTHREAD_MUTEX_INITIALIZER; | 70 pthread_mutex_t xs_mutex = PTHREAD_MUTEX_INITIALIZER; |
57 | 71 |
58 | 72 |
64 XSDEBUG("xs_init()\n"); | 78 XSDEBUG("xs_init()\n"); |
65 | 79 |
66 /* Initialize and get configuration */ | 80 /* Initialize and get configuration */ |
67 memset(&xs_cfg, 0, sizeof(xs_cfg)); | 81 memset(&xs_cfg, 0, sizeof(xs_cfg)); |
68 | 82 |
69 xs_get_configure(); | 83 xs_read_configuration(); |
70 | 84 |
71 xs_status.s_error = 0; | 85 xs_status.isError = FALSE; |
72 xs_status.s_playing = 0; | 86 xs_status.isPlaying = FALSE; |
73 xs_status.s_songs = 0; | 87 xs_status.nSongs = 0; |
74 xs_status.s_allownext = 1; // Initialize to TRUE to allow first song | 88 xs_status.currSong = 0; |
75 xs_status.s_tune = NULL; | 89 xs_status.allowNext = TRUE; // Initialize to TRUE to allow first song |
76 xs_status.s_fname = NULL; | 90 xs_status.currTune = NULL; |
77 | 91 xs_status.currFilename = NULL; |
78 /* Try to initialize libSIDPlay */ | 92 |
79 if (!xs_emuEngine) | 93 |
80 { | 94 /* Try to initialize libSIDPlay(s) */ |
81 XSERR("Couldn't start SIDPlay emulator engine!\n"); | 95 #ifdef HAVE_SIDPLAY1 |
96 if (!xs_emuEngine || !xs_emuEngine.verifyEndianess()) | |
97 { | |
98 XSERR("Couldn't start SIDPlay1 emulator engine!\n"); | |
82 return; | 99 return; |
83 } | 100 } |
84 | 101 #endif |
85 if (!xs_emuEngine.verifyEndianess()) | 102 |
86 { | 103 #ifdef HAVE_SIDPLAY2 |
87 XSERR("Wrong hardware endianess (SIDPlay error)!\n"); | 104 #endif |
88 return; | |
89 } | |
90 | 105 |
91 /* Read song-length database */ | 106 /* Read song-length database */ |
107 if (xs_cfg.songlenDBEnable) | |
92 if (xs_songlen_init() < 0) | 108 if (xs_songlen_init() < 0) |
93 { | 109 { |
94 XSERR("Error initializing song-length database!\n"); | 110 XSERR("Error initializing song-length database!\n"); |
95 } | 111 } |
96 | 112 |
110 XSDEBUG("shutting down...\n"); | 126 XSDEBUG("shutting down...\n"); |
111 | 127 |
112 /* Stop playing */ | 128 /* Stop playing */ |
113 xs_plugin_ip.stop(); | 129 xs_plugin_ip.stop(); |
114 | 130 |
131 /* Shutdown libSIDPlay(s) */ | |
132 #ifdef HAVE_SIDPLAY1 | |
133 #endif | |
134 | |
135 #ifdef HAVE_SIDPLAY2 | |
136 #endif | |
137 | |
115 /* Close sub-song control window */ | 138 /* Close sub-song control window */ |
116 | 139 |
117 /* Free allocated memory */ | 140 /* Free allocated memory */ |
118 xs_songlen_close(); | 141 xs_songlen_close(); |
119 | 142 |
133 return FALSE; | 156 return FALSE; |
134 | 157 |
135 /* Try to detect via libSIDPlay's detection routine, if required */ | 158 /* Try to detect via libSIDPlay's detection routine, if required */ |
136 if (xs_cfg.detectMagic) | 159 if (xs_cfg.detectMagic) |
137 { | 160 { |
138 sidTune *testTune = new sidTune(fileName); | 161 #ifdef HAVE_SIDPLAY1 |
139 | 162 t_xs_tune *testTune = new sidTune(fileName); |
140 if (!testTune) return FALSE; | 163 if (!testTune) return FALSE; |
141 if (!testTune->getStatus()) | 164 if (!testTune->getStatus()) |
142 { | 165 { |
143 delete testTune; | 166 delete testTune; |
144 return FALSE; | 167 return FALSE; |
145 } | 168 } |
146 | 169 |
147 delete testTune; | 170 delete testTune; |
148 return TRUE; | 171 return TRUE; |
149 } | 172 #endif |
150 | 173 #ifdef HAVE_SIDPLAY2 |
174 #endif | |
175 } | |
151 | 176 |
152 /* Detect just by checking filename extension */ | 177 /* Detect just by checking filename extension */ |
153 pcExt = strrchr(fileName, '.'); | 178 pcExt = strrchr(fileName, '.'); |
154 if (pcExt) | 179 if (pcExt) |
155 { | 180 { |
168 /* | 193 /* |
169 * Main playing thread loop | 194 * Main playing thread loop |
170 */ | 195 */ |
171 static void *xs_play_loop(void *argPointer) | 196 static void *xs_play_loop(void *argPointer) |
172 { | 197 { |
173 guchar plr_data[XS_BUFSIZE]; | |
174 struct sidTuneInfo plr_sidInf; | |
175 gchar *plr_tune_title = NULL; | |
176 gint plr_fxlen; | |
177 enum AFormat plr_fmt; | |
178 gint plr_tune_num; | |
179 gint32 plr_tune_len; | |
180 | |
181 | |
182 /* Don't allow next song to be set yet */ | 198 /* Don't allow next song to be set yet */ |
183 pthread_mutex_lock(&xs_mutex); | 199 pthread_mutex_lock(&xs_mutex); |
184 xs_status.s_allownext = 0; | 200 xs_status.allowNext = FALSE; |
185 pthread_mutex_unlock(&xs_mutex); | 201 pthread_mutex_unlock(&xs_mutex); |
186 | 202 |
187 | 203 |
188 /* Check tune number */ | 204 |
189 plr_tune_num = xs_status.s_playing; | 205 XSDEBUG("exiting thread, bye.\n"); |
190 | 206 return NULL; |
191 if (plr_tune_num <= 0) | 207 } |
192 plr_tune_num = 1; | 208 |
193 | 209 |
194 XSDEBUG("xs_play_loop(%d, %d)\n", plr_tune_num, xs_status.s_playing); | 210 /* |
195 | 211 * Start playing the given file |
196 /* Get song information */ | 212 */ |
197 xs_status.s_tune->getInfo(plr_sidInf); | 213 void xs_play_file(char *fileName) |
198 plr_tune_len = xs_songlen_get(xs_status.s_fname, plr_tune_num); | 214 { |
199 plr_tune_title = xs_filetitle_get(&plr_sidInf, plr_tune_num); | 215 t_xs_tune *newTune; |
200 | 216 struct sidTuneInfo sidInf; |
201 XSDEBUG("title='%s', len=%d\n", plr_tune_title, plr_tune_len); | 217 |
218 XSDEBUG("request to load '%s'\n", fileName); | |
202 | 219 |
203 | 220 |
204 /* Initialize audio output */ | 221 /* Initialize audio output */ |
205 // FIXME FIXME: FMT_S16_XXX -- different architechtures?? | 222 XSDEBUG("opening audio output plugin...\n"); |
206 // the patch may break something ... | 223 if (!xs_plugin_ip.output->open_audio( |
207 plr_fmt = (xs_emuConf.bitsPerSample == 16) ? FMT_S16_NE : FMT_U8; | 224 ((xs_cfg.fmtBitsPerSample == 16) ? FMT_S16_NE : FMT_U8), xs_cfg.fmtFrequency, |
208 | 225 ((xs_cfg.fmtChannels == XS_CHN_MONO) ? 1 : 2))) |
209 | 226 { |
210 if (!xs_plugin_ip.output->open_audio(plr_fmt, xs_emuConf.frequency, xs_emuConf.channels)) | 227 XSERR("Couldn't open audio output plugin!\n"); |
211 { | 228 delete newTune; |
212 pthread_mutex_lock(&xs_mutex); | 229 return; |
213 xs_status.s_error = 1; | 230 } |
214 if (plr_tune_title) g_free(plr_tune_title); | 231 |
215 if (xs_status.s_tune) delete xs_status.s_tune; | |
216 xs_status.s_allownext = 1; | |
217 pthread_mutex_unlock(&xs_mutex); | |
218 return NULL; | |
219 } | |
220 | |
221 | |
222 /* Initialize the SIDPlay-emulator for song */ | |
223 if (!sidEmuInitializeSong(xs_emuEngine, *xs_status.s_tune, plr_tune_num)) | |
224 { | |
225 XSERR("Couldn't initialize SIDPlay emulator engine! This may be a problem with your sound settings, or possibly a bug in XMMS-SID.\n"); | |
226 pthread_mutex_lock(&xs_mutex); | |
227 xs_status.s_error = 1; | |
228 pthread_mutex_unlock(&xs_mutex); | |
229 goto pl_cleanup; | |
230 } | |
231 | |
232 | |
233 /* Set song title information */ | |
234 xs_plugin_ip.set_info( | |
235 plr_tune_title, | |
236 (plr_tune_len * 1000), | |
237 (1000 * (plr_sidInf.songSpeed ? plr_sidInf.songSpeed : (plr_sidInf.clockSpeed == SIDTUNE_CLOCK_NTSC) ? 60 : 50)), | |
238 xs_emuConf.frequency, | |
239 xs_emuConf.channels); | |
240 | |
241 | |
242 /* Run playing loop: loop as long as xs_playing is same as current tune number */ | |
243 while (xs_status.s_playing == plr_tune_num) | |
244 { | |
245 plr_fxlen = XS_BUFSIZE; | |
246 | |
247 /* Run emulator to fill output buffer with audio data */ | |
248 sidEmuFillBuffer(xs_emuEngine, *xs_status.s_tune, plr_data, plr_fxlen); | |
249 | |
250 /* If Max Playtime option set, check playtime */ | |
251 if (xs_cfg.playUseMaxTime) | |
252 { | |
253 if ((xs_plugin_ip.output->output_time() / 1000) >= xs_cfg.playMaxTime) | |
254 { | |
255 pthread_mutex_lock(&xs_mutex); | |
256 xs_status.s_playing = 0; | |
257 pthread_mutex_unlock(&xs_mutex); | |
258 } | |
259 } | |
260 | |
261 /* Check playtime against database */ | |
262 if (xs_cfg.playMethod == XMMS_SID_PMETHOD_DATABASE) | |
263 { | |
264 if ((xs_plugin_ip.output->output_time() / 1000) >= plr_tune_len) | |
265 { | |
266 pthread_mutex_lock(&xs_mutex); | |
267 xs_status.s_playing = 0; | |
268 pthread_mutex_unlock(&xs_mutex); | |
269 } | |
270 | |
271 } | |
272 #if 0 | |
273 else | |
274 | |
275 /* Check for silence */ | |
276 if (xs_cfg.playMethod == XMMS_SID_PMETHOD_MAXSILENCE) | |
277 { | |
278 } | |
279 | |
280 /* Add static noise */ | |
281 | |
282 /* Muffle waveform (low-pass filter) */ | |
283 | |
284 #endif | |
285 | |
286 | |
287 /* Send audio data to visualization plugin */ | |
288 xs_plugin_ip.add_vis_pcm(xs_plugin_ip.output->written_time(), | |
289 plr_fmt, xs_emuConf.channels, plr_fxlen, plr_data); | |
290 | |
291 /* Wait for a while */ | |
292 while ((xs_status.s_playing == plr_tune_num) && (xs_plugin_ip.output->buffer_free() < plr_fxlen)) | |
293 xmms_usleep(10000); | |
294 | |
295 | |
296 /* If playing, send final audio data to output plugin */ | |
297 if (xs_status.s_playing == plr_tune_num) | |
298 xs_plugin_ip.output->write_audio(plr_data, plr_fxlen); | |
299 | |
300 } /* End of playerloop */ | |
301 | |
302 | |
303 pl_cleanup: | |
304 XSDEBUG("cleaning up...\n"); | |
305 | |
306 /* Cleanup & shutdown */ | |
307 xs_plugin_ip.output->close_audio(); | |
308 | |
309 if (plr_tune_title) g_free(plr_tune_title); | |
310 | |
311 pthread_mutex_lock(&xs_mutex); | |
312 xs_status.s_playing = 0; | |
313 if (xs_status.s_tune) delete xs_status.s_tune; | |
314 xs_status.s_allownext = 1; | |
315 pthread_mutex_unlock(&xs_mutex); | |
316 | |
317 XSDEBUG("exiting thread, bye.\n"); | |
318 return NULL; | |
319 } | |
320 | |
321 | |
322 /* | |
323 * Start playing the given file | |
324 */ | |
325 void xs_play_file(char *fileName) | |
326 { | |
327 sidTune *newTune; | |
328 struct sidTuneInfo sidInf; | |
329 | |
330 XSDEBUG("request to start '%s'\n", fileName); | |
331 | |
332 /* Wait until the previous song has finished for sure */ | |
333 if (!xs_status.s_allownext) | |
334 pthread_join(xs_decode_thread, NULL); | |
335 | 232 |
336 /* Try to get the tune */ | 233 /* Try to get the tune */ |
337 newTune = new sidTune(fileName); | 234 newTune = new sidTune(fileName); |
338 if (newTune == NULL) return; | 235 if (newTune == NULL) return; |
339 | 236 |
340 XSDEBUG("tune ok, status %i\n", xs_status.s_playing); | 237 XSDEBUG("tune ok, configuring SIDPlay engine\n"); |
341 | 238 |
342 | 239 |
343 /* Get current configuration */ | 240 /* Get current configuration */ |
344 xs_emuEngine.getConfig(xs_emuConf); | 241 xs_emuEngine.getConfig(xs_emuConf); |
345 | 242 |
346 | 243 |
347 /* Configure channels and stuff */ | 244 /* Configure channels and stuff */ |
348 switch (xs_cfg.fmtChannels) { | 245 switch (xs_cfg.fmtChannels) { |
349 | 246 |
350 case XMMS_SID_CHN_AUTOPAN: | 247 case XS_CHN_AUTOPAN: |
351 xs_emuConf.channels = SIDEMU_STEREO; | 248 xs_emuConf.channels = SIDEMU_STEREO; |
352 xs_emuConf.autoPanning = SIDEMU_CENTEREDAUTOPANNING; | 249 xs_emuConf.autoPanning = SIDEMU_CENTEREDAUTOPANNING; |
353 xs_emuConf.volumeControl = SIDEMU_FULLPANNING; | 250 xs_emuConf.volumeControl = SIDEMU_FULLPANNING; |
354 break; | 251 break; |
355 | 252 |
356 case XMMS_SID_CHN_STEREO: | 253 case XS_CHN_STEREO: |
357 xs_emuConf.channels = SIDEMU_STEREO; | 254 xs_emuConf.channels = SIDEMU_STEREO; |
358 xs_emuConf.autoPanning = SIDEMU_NONE; | 255 xs_emuConf.autoPanning = SIDEMU_NONE; |
359 xs_emuConf.volumeControl = SIDEMU_NONE; | 256 xs_emuConf.volumeControl = SIDEMU_NONE; |
360 break; | 257 break; |
361 | 258 |
362 case XMMS_SID_CHN_MONO: | 259 case XS_CHN_MONO: |
363 xs_emuConf.channels = SIDEMU_MONO; | 260 xs_emuConf.channels = SIDEMU_MONO; |
364 xs_emuConf.autoPanning = SIDEMU_NONE; | 261 xs_emuConf.autoPanning = SIDEMU_NONE; |
365 xs_emuConf.volumeControl = SIDEMU_NONE; | 262 xs_emuConf.volumeControl = SIDEMU_NONE; |
366 break; | 263 break; |
367 | 264 |
372 } | 269 } |
373 | 270 |
374 | 271 |
375 /* Memory mode settings */ | 272 /* Memory mode settings */ |
376 switch (xs_cfg.memoryMode) { | 273 switch (xs_cfg.memoryMode) { |
377 case XMMS_SID_MPU_BANK_SWITCHING: | 274 case XS_MPU_BANK_SWITCHING: |
378 xs_emuConf.memoryMode = MPU_BANK_SWITCHING; | 275 xs_emuConf.memoryMode = MPU_BANK_SWITCHING; |
379 break; | 276 break; |
380 | 277 |
381 case XMMS_SID_MPU_TRANSPARENT_ROM: | 278 case XS_MPU_TRANSPARENT_ROM: |
382 xs_emuConf.memoryMode = MPU_TRANSPARENT_ROM; | 279 xs_emuConf.memoryMode = MPU_TRANSPARENT_ROM; |
383 break; | 280 break; |
384 | 281 |
385 case XMMS_SID_MPU_PLAYSID_ENVIRONMENT: | 282 case XS_MPU_PLAYSID_ENVIRONMENT: |
386 xs_emuConf.memoryMode = MPU_PLAYSID_ENVIRONMENT; | 283 xs_emuConf.memoryMode = MPU_PLAYSID_ENVIRONMENT; |
387 break; | 284 break; |
388 | 285 |
389 default: | 286 default: |
390 XSERR("Internal: Invalid memoryMode setting. Possibly corrupted configuration file.\n"); | 287 XSERR("Internal: Invalid memoryMode setting. Possibly corrupted configuration file.\n"); |
393 } | 290 } |
394 | 291 |
395 | 292 |
396 /* Clockspeed settings */ | 293 /* Clockspeed settings */ |
397 switch (xs_cfg.clockSpeed) { | 294 switch (xs_cfg.clockSpeed) { |
398 case XMMS_SID_CLOCK_PAL: | 295 case XS_CLOCK_PAL: |
399 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_PAL; | 296 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_PAL; |
400 break; | 297 break; |
401 | 298 |
402 case XMMS_SID_CLOCK_NTSC: | 299 case XS_CLOCK_NTSC: |
403 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_NTSC; | 300 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_NTSC; |
404 break; | 301 break; |
405 | 302 |
406 default: | 303 default: |
407 XSERR("Internal: Invalid clockSpeed setting. Possibly corrupted configuration file.\n"); | 304 XSERR("Internal: Invalid clockSpeed setting. Possibly corrupted configuration file.\n"); |
413 /* Configure rest of the emulation */ | 310 /* Configure rest of the emulation */ |
414 xs_emuConf.bitsPerSample = xs_cfg.fmtBitsPerSample; | 311 xs_emuConf.bitsPerSample = xs_cfg.fmtBitsPerSample; |
415 xs_emuConf.frequency = xs_cfg.fmtFrequency; | 312 xs_emuConf.frequency = xs_cfg.fmtFrequency; |
416 xs_emuConf.sampleFormat = SIDEMU_SIGNED_PCM; | 313 xs_emuConf.sampleFormat = SIDEMU_SIGNED_PCM; |
417 xs_emuConf.mos8580 = xs_cfg.mos8580; | 314 xs_emuConf.mos8580 = xs_cfg.mos8580; |
418 xs_emuConf.emulateFilter = xs_cfg.emulateFilter; | 315 xs_emuConf.emulateFilter = xs_cfg.emulateFilters; |
419 xs_emuConf.filterFs = xs_cfg.filterFs; | 316 xs_emuConf.filterFs = xs_cfg.filterFs; |
420 xs_emuConf.filterFm = xs_cfg.filterFm; | 317 xs_emuConf.filterFm = xs_cfg.filterFm; |
421 xs_emuConf.filterFt = xs_cfg.filterFt; | 318 xs_emuConf.filterFt = xs_cfg.filterFt; |
422 | 319 |
423 XSDEBUG("configuring engine..\n"); | 320 XSDEBUG("configuring engine..\n"); |
427 xs_emuEngine.setConfig(xs_emuConf); | 324 xs_emuEngine.setConfig(xs_emuConf); |
428 newTune->getInfo(sidInf); | 325 newTune->getInfo(sidInf); |
429 | 326 |
430 | 327 |
431 /* Initialize status information */ | 328 /* Initialize status information */ |
432 XSDEBUG("starting thread!\n"); | 329 XSDEBUG("initializing and starting playing thread!\n"); |
433 | 330 |
434 pthread_mutex_lock(&xs_mutex); | 331 xs_status.isError = FALSE; |
435 xs_status.s_error = 0; | 332 xs_status.isPlaying = TRUE; |
436 xs_status.s_playing = sidInf.startSong; | 333 xs_status.allowNext = TRUE; |
437 xs_status.s_songs = sidInf.songs; | 334 xs_status.currSong = sidInf.startSong; |
438 xs_status.s_tune = newTune; | 335 xs_status.nSongs = sidInf.songs; |
439 pthread_mutex_unlock(&xs_mutex); | 336 xs_status.currTune = newTune; |
337 | |
440 | 338 |
441 /* Start the playing thread! */ | 339 /* Start the playing thread! */ |
442 if (pthread_create(&xs_decode_thread, NULL, xs_play_loop, NULL) < 0) | 340 if (pthread_create(&xs_decode_thread, NULL, xs_play_loop, NULL) < 0) |
443 { | 341 { |
444 XSERR("Couldn't start playing thread! Possible reason reported by system: %s\n", strerror(errno)); | 342 XSERR("Couldn't start playing thread! Possible reason reported by system: %s\n", strerror(errno)); |
453 * Stop playing | 351 * Stop playing |
454 */ | 352 */ |
455 void xs_stop(void) | 353 void xs_stop(void) |
456 { | 354 { |
457 /* If playing, stop. */ | 355 /* If playing, stop. */ |
458 if (xs_status.s_playing) | 356 XSDEBUG("request to stop.\n"); |
459 { | 357 |
358 if (xs_status.isPlaying) | |
359 { | |
360 XSDEBUG("stopping...\n"); | |
460 pthread_mutex_lock(&xs_mutex); | 361 pthread_mutex_lock(&xs_mutex); |
461 xs_status.s_playing = 0; | 362 xs_status.isPlaying = 0; |
462 pthread_mutex_unlock(&xs_mutex); | 363 pthread_mutex_unlock(&xs_mutex); |
463 | 364 |
464 pthread_join(xs_decode_thread, NULL); | 365 pthread_join(xs_decode_thread, NULL); |
366 | |
367 xs_plugin_ip.output->close_audio(); | |
465 } | 368 } |
466 } | 369 } |
467 | 370 |
468 | 371 |
469 /* | 372 /* |
480 * (the playing thread will do the "seeking" aka song-change) | 383 * (the playing thread will do the "seeking" aka song-change) |
481 */ | 384 */ |
482 void xs_seek(int iTime) | 385 void xs_seek(int iTime) |
483 { | 386 { |
484 #ifdef HAVE_SONG_POSITION | 387 #ifdef HAVE_SONG_POSITION |
485 if ((iTime > 0) && (iTime <= xs_songs)) | 388 pthread_mutex_lock(&xs_mutex); |
486 { | 389 |
487 pthread_mutex_lock(&xs_mutex); | 390 if ((iTime > 0) && (iTime <= xs_status.nSongs) && xs_status.isPlaying) |
488 xs_status.s_playing = iTime; | 391 { |
489 pthread_mutex_unlock(&xs_mutex); | 392 xs_status.currSong = iTime; |
490 } | 393 } |
394 | |
395 pthread_mutex_unlock(&xs_mutex); | |
491 #endif | 396 #endif |
492 } | 397 } |
493 | 398 |
494 | 399 |
495 /* | 400 /* |
496 * Return the playing "position/time" | 401 * Return the playing "position/time" |
497 */ | 402 */ |
498 int xs_get_time(void) | 403 int xs_get_time(void) |
499 { | 404 { |
500 if (xs_status.s_error) | 405 pthread_mutex_lock(&xs_mutex); |
406 if (xs_status.isError) | |
501 return -2; | 407 return -2; |
502 | 408 |
503 if (!xs_status.s_playing) | 409 if (!xs_status.isPlaying) |
504 return -1; | 410 return -1; |
505 | 411 |
506 #ifdef HAVE_SONG_POSITION | 412 #ifdef HAVE_SONG_POSITION |
507 set_song_position(xs_status.s_playing, 1, xs_status.s_songs); | 413 set_song_position(xs_status.currSong, 1, xs_status.nSongs); |
508 #endif | 414 #endif |
415 | |
416 pthread_mutex_unlock(&xs_mutex); | |
509 | 417 |
510 return xs_plugin_ip.output->output_time(); | 418 return xs_plugin_ip.output->output_time(); |
511 } | 419 } |
512 | 420 |
513 | 421 |
515 * Return song information | 423 * Return song information |
516 */ | 424 */ |
517 void xs_get_song_info(char *songFilename, char **songTitle, int *songLength) | 425 void xs_get_song_info(char *songFilename, char **songTitle, int *songLength) |
518 { | 426 { |
519 struct sidTuneInfo sidInf; | 427 struct sidTuneInfo sidInf; |
520 sidTune *testTune = new sidTune(songFilename); | 428 t_xs_tune *testTune = new sidTune(songFilename); |
521 | 429 |
522 /* Check if the tune exists and is readable */ | 430 /* Check if the tune exists and is readable */ |
523 if (!testTune) return; | 431 if (!testTune) return; |
524 if (!testTune->getStatus()) | 432 if (!testTune->getStatus()) |
525 { | 433 { |
530 /* Get general tune information */ | 438 /* Get general tune information */ |
531 testTune->getInfo(sidInf); | 439 testTune->getInfo(sidInf); |
532 delete testTune; | 440 delete testTune; |
533 | 441 |
534 /* Get titlestring */ | 442 /* Get titlestring */ |
535 *songTitle = xs_filetitle_get(&sidInf, sidInf.startSong); | 443 *songTitle = NULL; |
536 | 444 |
537 /* Get song length (in seconds), negative if no known length */ | 445 /* Get song length (in milliseconds), negative if no known length */ |
538 *songLength = xs_songlen_get(songFilename, sidInf.startSong); | 446 *songLength = xs_songlen_get(songFilename, sidInf.startSong) * 1000; |
539 } | 447 } |
540 | 448 |
449 | |
450 /* | |
451 * Create the SID-tune description string from the tune's information | |
452 * formatted by the user-specified format-string. | |
453 */ | |
454 gchar *xs_filetitle_get(gchar *pcFilename, void *pfInfo, gint iSubTune) | |
455 { | |
456 gint i, j, iLength; | |
457 gchar *pcResult; | |
458 struct sidTuneInfo *finfo = (struct sidTuneInfo *) pfInfo; | |
459 #ifdef HAVE_XMMSEXTRA | |
460 TitleInput *ptInput; | |
461 #endif | |
462 | |
463 // FIXME FIXME: get STIL-info | |
464 | |
465 | |
466 #ifdef HAVE_XMMSEXTRA | |
467 /* Check if the titles are overridden or not */ | |
468 if (!xs_cfg.titleOverride) | |
469 { | |
470 /* Use generic XMMS titles */ | |
471 /* XMMS_NEW_TITLEINPUT(ptInput); | |
472 * We duplicate and add typecast to the code here due to XMMS's braindead headers | |
473 */ | |
474 ptInput = (TitleInput *) g_malloc0(sizeof(TitleInput)); | |
475 ptInput->__size = XMMS_TITLEINPUT_SIZE; | |
476 ptInput->__version = XMMS_TITLEINPUT_VERSION; | |
477 | |
478 /* Create the input fields */ | |
479 ptInput->file_name = pcFilename; | |
480 ptInput->file_ext = pcFilename; | |
481 ptInput->file_path = pcFilename; | |
482 | |
483 ptInput->track_name = finfo->nameString; | |
484 ptInput->track_number = iSubTune; | |
485 ptInput->album_name = NULL; | |
486 ptInput->performer = finfo->authorString; | |
487 xs_strcalloc(&ptInput->date, ""); | |
488 ptInput->year = 0; | |
489 xs_strcalloc(&ptInput->genre, "SID-tune"); | |
490 ptInput->comment = finfo->copyrightString; | |
491 | |
492 /* Create the string */ | |
493 pcResult = xmms_get_titlestring(xmms_get_gentitle_format(), ptInput); | |
494 | |
495 /* Dispose all allocated memory */ | |
496 g_free(ptInput->date); | |
497 g_free(ptInput->genre); | |
498 g_free(ptInput); | |
499 } else { | |
500 #endif | |
501 /* Check the info strings */ | |
502 if (finfo->numberOfInfoStrings != 3) | |
503 { | |
504 if (finfo->numberOfInfoStrings < 1) | |
505 return 0; | |
506 | |
507 return g_strdup(finfo->infoString[0]); | |
508 } | |
509 | |
510 /* Check the format-string for NULL */ | |
511 if (xs_cfg.titleFormat == NULL) | |
512 return g_strdup_printf("%s - %s", finfo->nameString, finfo->authorString); | |
513 | |
514 /* Construct the final result info */ | |
515 for (j = i = 0; i < strlen(xs_cfg.titleFormat); i++) | |
516 { | |
517 if (xs_cfg.titleFormat[i] == '%') | |
518 { | |
519 switch (xs_cfg.titleFormat[++i]) { | |
520 case '1': | |
521 xs_strpcat(&pcResult, &j, finfo->authorString); | |
522 break; | |
523 | |
524 case '2': | |
525 xs_strpcat(&pcResult, &j, finfo->nameString); | |
526 break; | |
527 | |
528 case '3': | |
529 xs_strpcat(&pcResult, &j, finfo->copyrightString); | |
530 break; | |
531 | |
532 case '4': | |
533 xs_strpcat(&pcResult, &j, finfo->formatString); | |
534 break; | |
535 } /* case */ | |
536 } else | |
537 pcResult[j++] = xs_cfg.titleFormat[i]; | |
538 } | |
539 | |
540 pcResult[j] = 0; | |
541 #ifdef HAVE_XMMSEXTRA | |
542 } | |
543 #endif | |
544 | |
545 return pcResult; | |
546 } | |
547 |