Mercurial > hg > xmms-sid
comparison src/xmms-sid.cc @ 5:5b7009eef767
Updated to 0.8
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 03 Jun 2003 11:07:00 +0000 |
parents | 183e7cbc1036 |
children | ac2972a7ccd5 |
comparison
equal
deleted
inserted
replaced
4:4bb09e405eab | 5:5b7009eef767 |
---|---|
1 /* | 1 /* |
2 xmms-sid - SIDPlay input plugin for X MultiMedia System (XMMS) | 2 XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS) |
3 | 3 |
4 Main source file | 4 Main source file |
5 | 5 |
6 Originally by Willem Monsuwe <willem@stack.nl> | 6 Written by Matti "ccr" Hamalainen <ccr@tnsp.org> |
7 Additions, fixes, etc by Matti "ccr" Hamalainen <mhamalai@ratol.fi> | 7 (few bits may still be by Willem Monsuwe) |
8 | 8 |
9 This program is free software; you can redistribute it and/or modify | 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 | 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 | 11 the Free Software Foundation; either version 2 of the License, or |
12 (at your option) any later version. | 12 (at your option) any later version. |
24 #include "xmms-sid.h" | 24 #include "xmms-sid.h" |
25 #include <sidplay/player.h> | 25 #include <sidplay/player.h> |
26 #include <sidplay/myendian.h> | 26 #include <sidplay/myendian.h> |
27 #include <sidplay/fformat.h> | 27 #include <sidplay/fformat.h> |
28 | 28 |
29 | |
30 extern "C" { | 29 extern "C" { |
31 #include <pthread.h> | 30 #include <pthread.h> |
32 | 31 |
33 #include <stdlib.h> | 32 #include <stdlib.h> |
34 #include <string.h> | 33 #include <string.h> |
35 #include <stdio.h> | 34 #include <stdio.h> |
35 #include <errno.h> | |
36 | 36 |
37 #include <xmms/plugin.h> | 37 #include <xmms/plugin.h> |
38 #include <xmms/util.h> | 38 #include <xmms/util.h> |
39 } | 39 } |
40 | 40 |
41 | 41 |
42 /* | 42 /* |
43 * General variables | 43 * Global variables |
44 */ | 44 */ |
45 static struct emuConfig xs_emuConf; | 45 static struct emuConfig xs_emuConf; |
46 static emuEngine xs_emuEngine; | 46 static emuEngine xs_emuEngine; |
47 static pthread_t xs_decode_thread; | 47 static pthread_t xs_decode_thread; |
48 static int xs_error = 0, xs_going = 0, xs_songs = 0; | 48 struct t_xs_cfg xs_cfg; |
49 struct T_sid_cfg xs_cfg; | 49 |
50 | 50 struct { |
51 | 51 int s_error, s_playing, s_songs, s_allownext; |
52 /* | 52 sidTune *s_tune; |
53 * Initialize xmms-sid plugin | 53 gchar *s_fname; |
54 } xs_status; | |
55 | |
56 pthread_mutex_t xs_mutex = PTHREAD_MUTEX_INITIALIZER; | |
57 | |
58 | |
59 /* | |
60 * Initialize XMMS-SID | |
54 */ | 61 */ |
55 void xs_init(void) | 62 void xs_init(void) |
56 { | 63 { |
57 | 64 XSDEBUG("xs_init()\n"); |
58 if (!xs_emuEngine) { | 65 |
59 xs_error = 1; | 66 /* Try to initialize libSIDPlay */ |
60 XSERR("Couldn't start SIDPlay emulator engine!\n"); | 67 if (!xs_emuEngine) |
61 return; | 68 { |
62 } | 69 XSERR("Couldn't start SIDPlay emulator engine!\n"); |
63 | 70 return; |
64 if (!xs_emuEngine.verifyEndianess()) { | 71 } |
65 xs_error = 1; | 72 |
66 XSERR("Wrong hardware endianess (SIDPlay error)!\n"); | 73 if (!xs_emuEngine.verifyEndianess()) |
67 return; | 74 { |
68 } | 75 XSERR("Wrong hardware endianess (SIDPlay error)!\n"); |
69 | 76 return; |
70 // Initialize STIL structures | 77 } |
71 memset(&xs_stil_info, 0, sizeof(xs_stil_info)); | 78 |
72 xs_stil_clear(); | 79 /* Initialize and get configuration */ |
73 | 80 memset(&xs_cfg, 0, sizeof(xs_cfg)); |
74 // Get configuration | 81 xs_get_configure(); |
75 xs_get_configure(); | 82 |
76 } | 83 xs_status.s_error = 0; |
77 | 84 xs_status.s_playing = 0; |
78 | 85 xs_status.s_songs = 0; |
79 /* | 86 xs_status.s_allownext = 1; // Initialize to TRUE to allow first song |
80 * Special, custom hand-made strcpy with smooth leather coating. | 87 xs_status.s_tune = NULL; |
81 */ | 88 xs_status.s_fname = NULL; |
82 int xs_strcpy(char *dest, const char *src, unsigned int *j) | 89 |
83 { | 90 /* Initialize STIL structures */ |
84 unsigned int i; | 91 // FIXME FIXME FIx ME |
85 | 92 |
86 if ((dest == NULL) || (src == NULL)) return -1; | 93 /* Create sub-song control window */ |
87 | 94 // FIX ME FIXME |
88 for (i = 0; i < strlen(src); i++) { | 95 } |
89 dest[(*j)++] = src[i]; | 96 |
90 } | 97 |
91 | 98 /* |
92 return 0; | 99 * Shut down XMMS-SID |
93 } | 100 */ |
94 | 101 void xs_close(void) |
95 | 102 { |
96 /* | 103 XSDEBUG("shutting down...\n"); |
97 Create the SID-tune description string from the | 104 |
98 tune's information formatted by the user-specified | 105 /* Stop playing */ |
99 format-string. | 106 xmms_sid_ip.stop(); |
100 */ | 107 |
101 static char * xs_make_filedesc(struct sidTuneInfo *s) | 108 /* Free allocated memory */ |
102 { | 109 |
103 unsigned int i, len, j; | 110 // FIXME FIXME: STIL-entries, songlendb |
104 char *result; | 111 |
105 | 112 } |
106 /* Check the info strings */ | 113 |
107 if (s->numberOfInfoStrings != 3) { | 114 |
108 if (s->numberOfInfoStrings < 1) { | 115 /* |
109 return 0; | 116 * Check whether the given file is handled by this plugin |
117 */ | |
118 gint xs_is_our_file(char *fileName) | |
119 { | |
120 char *pcExt; | |
121 | |
122 /* Check the filename */ | |
123 if (fileName == NULL) | |
124 return FALSE; | |
125 | |
126 /* Try to detect via libSIDPlay's detection routine, if required */ | |
127 if (xs_cfg.detectMagic) { | |
128 | |
129 sidTune *testTune = new sidTune(fileName); | |
130 | |
131 if (!testTune) return FALSE; | |
132 if (!testTune->getStatus()) | |
133 { | |
134 delete testTune; | |
135 return FALSE; | |
110 } | 136 } |
111 return g_strdup(s->infoString[0]); | 137 |
112 } | 138 delete testTune; |
113 | 139 return TRUE; |
114 /* Check the format-string for NULL */ | 140 } |
115 if (xs_cfg.fileInfo == NULL) { | 141 |
116 return g_strdup_printf("%s - %s", s->nameString, s->authorString); | 142 |
143 /* Detect just by checking filename extension */ | |
144 pcExt = strrchr(fileName, '.'); | |
145 if (pcExt) | |
146 { | |
147 pcExt++; | |
148 if (!strcasecmp(pcExt, "psid")) return TRUE; | |
149 if (!strcasecmp(pcExt, "sid")) return TRUE; | |
150 if (!strcasecmp(pcExt, "dat")) return TRUE; | |
151 if (!strcasecmp(pcExt, "inf")) return TRUE; | |
152 if (!strcasecmp(pcExt, "info")) return TRUE; | |
153 } | |
154 | |
155 return FALSE; | |
156 } | |
157 | |
158 | |
159 /* | |
160 * Playing thread loop function | |
161 */ | |
162 static void *xs_play_loop(void *argPointer) | |
163 { | |
164 gchar plr_data[XMMS_SID_BUFSIZE]; | |
165 struct sidTuneInfo plr_sidInf; | |
166 gchar *plr_tune_title = NULL; | |
167 gint plr_fxlen; | |
168 enum AFormat plr_fmt; | |
169 gint plr_tune_num; | |
170 gint32 plr_tune_len; | |
171 | |
172 | |
173 /* Don't allow next song to be set yet */ | |
174 pthread_mutex_lock(&xs_mutex); | |
175 xs_status.s_allownext = 0; | |
176 pthread_mutex_unlock(&xs_mutex); | |
177 | |
178 | |
179 /* Check tune number */ | |
180 plr_tune_num = xs_status.s_playing; | |
181 | |
182 if (plr_tune_num <= 0) | |
183 plr_tune_num = 1; | |
184 | |
185 XSDEBUG("xs_play_loop(%d, %d)\n", plr_tune_num, xs_status.s_playing); | |
186 | |
187 /* Get song information */ | |
188 xs_status.s_tune->getInfo(plr_sidInf); | |
189 plr_tune_len = xs_get_length(xs_status.s_fname, plr_tune_num); | |
190 plr_tune_title = xs_get_filetitle(&plr_sidInf, plr_tune_num); | |
191 | |
192 XSDEBUG("title='%s', len=%d\n", plr_tune_title, plr_tune_len); | |
193 | |
194 | |
195 /* Initialize audio output */ | |
196 // FIXME FIXME: FMT_S16_XXX -- different architechtures?? | |
197 // the patch may break something ... | |
198 plr_fmt = (xs_emuConf.bitsPerSample == 16) ? FMT_S16_NE : FMT_U8; | |
199 | |
200 | |
201 if (!xmms_sid_ip.output->open_audio(plr_fmt, xs_emuConf.frequency, xs_emuConf.channels)) | |
202 { | |
203 pthread_mutex_lock(&xs_mutex); | |
204 xs_status.s_error = 1; | |
205 if (plr_tune_title) g_free(plr_tune_title); | |
206 if (xs_status.s_tune) delete xs_status.s_tune; | |
207 xs_status.s_allownext = 1; | |
208 pthread_mutex_unlock(&xs_mutex); | |
209 return NULL; | |
210 } | |
211 | |
212 | |
213 /* Initialize the SIDPlay-emulator for song */ | |
214 if (!sidEmuInitializeSong(xs_emuEngine, *xs_status.s_tune, plr_tune_num)) | |
215 { | |
216 XSERR("Couldn't initialize SIDPlay emulator engine! This may be a problem with your sound settings, or possibly a bug in XMMS-SID.\n"); | |
217 pthread_mutex_lock(&xs_mutex); | |
218 xs_status.s_error = 1; | |
219 pthread_mutex_unlock(&xs_mutex); | |
220 goto pl_cleanup; | |
221 } | |
222 | |
223 | |
224 /* Set song title information */ | |
225 xmms_sid_ip.set_info( | |
226 plr_tune_title, | |
227 (plr_tune_len * 1000), | |
228 (1000 * (plr_sidInf.songSpeed ? plr_sidInf.songSpeed : (plr_sidInf.clockSpeed == SIDTUNE_CLOCK_NTSC) ? 60 : 50)), | |
229 xs_emuConf.frequency, | |
230 xs_emuConf.channels); | |
231 | |
232 | |
233 /* Run playing loop: loop as long as xs_playing is same as current tune number */ | |
234 while (xs_status.s_playing == plr_tune_num) | |
235 { | |
236 plr_fxlen = XMMS_SID_BUFSIZE; | |
237 | |
238 /* Run emulator to fill output buffer with audio data */ | |
239 sidEmuFillBuffer(xs_emuEngine, *xs_status.s_tune, plr_data, plr_fxlen); | |
240 | |
241 /* If Max Playtime option set, check playtime */ | |
242 if (xs_cfg.playUseMaxTime) | |
243 { | |
244 if ((xmms_sid_ip.output->output_time() / 1000) >= xs_cfg.playMaxTime) | |
245 { | |
246 pthread_mutex_lock(&xs_mutex); | |
247 xs_status.s_playing = 0; | |
248 pthread_mutex_unlock(&xs_mutex); | |
249 } | |
117 } | 250 } |
118 | 251 |
119 /* Pre-calculate the length of the result-string */ | 252 /* Check playtime against database */ |
120 len = 2; | 253 if (xs_cfg.playMethod == XMMS_SID_PMETHOD_DATABASE) |
121 for (i = 0; i < strlen(xs_cfg.fileInfo); i++) { | 254 { |
122 if (xs_cfg.fileInfo[i] == '%') { | 255 if ((xmms_sid_ip.output->output_time() / 1000) >= plr_tune_len) |
123 switch (xs_cfg.fileInfo[++i]) { | 256 { |
124 case '1': len += strlen(s->authorString); break; | 257 pthread_mutex_lock(&xs_mutex); |
125 case '2': len += strlen(s->nameString); break; | 258 xs_status.s_playing = 0; |
126 case '3': len += strlen(s->copyrightString); break; | 259 pthread_mutex_unlock(&xs_mutex); |
127 case '4': len += strlen(s->formatString); break; | 260 } |
261 | |
128 } | 262 } |
129 } else len++; | 263 #if 0 |
130 } | 264 else |
131 | 265 |
132 /* Allocate the result-string */ | 266 /* Check for silence */ |
133 result = (char *) g_malloc(len); | 267 if (xs_cfg.playMethod == XMMS_SID_PMETHOD_MAXSILENCE) |
134 | 268 { |
135 /* Construct the final result info */ | |
136 j = 0; | |
137 for (i = 0; i < strlen(xs_cfg.fileInfo); i++) { | |
138 | |
139 if (xs_cfg.fileInfo[i] == '%') { | |
140 switch (xs_cfg.fileInfo[++i]) { | |
141 case '1': xs_strcpy(result, s->authorString, &j); break; | |
142 case '2': xs_strcpy(result, s->nameString, &j); break; | |
143 case '3': xs_strcpy(result, s->copyrightString, &j); break; | |
144 case '4': xs_strcpy(result, s->formatString, &j); break; | |
145 } | 269 } |
146 | 270 |
147 } else { | 271 /* Add static noise */ |
148 result[j++] = xs_cfg.fileInfo[i]; | 272 |
149 } /* if */ | 273 /* Muffle waveform (low-pass filter) */ |
150 | 274 |
151 } /* for */ | 275 #endif |
152 | 276 |
153 result[j] = '\0'; | 277 |
154 | 278 /* Send audio data to visualization plugin */ |
155 return result; | |
156 } | |
157 | |
158 | |
159 /* | |
160 * Check whether the given file is handled by this plugin | |
161 */ | |
162 int xs_is_our_file(char *filename) | |
163 { | |
164 if (xs_cfg.detectMagic) { | |
165 sidTune *t = new sidTune(filename); | |
166 | |
167 if (!t->getStatus()) { | |
168 delete t; | |
169 return FALSE; | |
170 } | |
171 | |
172 delete t; | |
173 return TRUE; | |
174 } | |
175 | |
176 char *ext = strrchr(filename, '.'); | |
177 if (ext) { | |
178 ext++; | |
179 if (!strcasecmp(ext, "psid")) return TRUE; | |
180 if (!strcasecmp(ext, "sid")) return TRUE; | |
181 if (!strcasecmp(ext, "dat")) return TRUE; | |
182 if (!strcasecmp(ext, "inf")) return TRUE; | |
183 if (!strcasecmp(ext, "info")) return TRUE; | |
184 } | |
185 return FALSE; | |
186 } | |
187 | |
188 | |
189 /* | |
190 * Playing thread loop function | |
191 */ | |
192 static void * xs_play_loop(void *arg) | |
193 { | |
194 sidTune *tune = (sidTune *)arg; | |
195 char data[XMMS_SID_BUFSIZE]; | |
196 int fxlen, tn; | |
197 struct sidTuneInfo sidInf; | |
198 char *name; | |
199 enum AFormat fmt = (xs_emuConf.bitsPerSample == 16) ? FMT_S16_NE : FMT_U8; | |
200 gint chn = xs_emuConf.channels; | |
201 | |
202 tune->getInfo(sidInf); | |
203 name = xs_make_filedesc(&sidInf); | |
204 | |
205 play_loop_new_tune: | |
206 tn = xs_going; | |
207 if (tn <= 0) tn = 1; | |
208 if (!xmms_sid_ip.output->open_audio(fmt, xs_emuConf.frequency, chn)) | |
209 { | |
210 xs_error = 1; | |
211 XSERR("Couldn't open XMMS audio output!\n"); | |
212 delete tune; | |
213 pthread_exit(NULL); | |
214 xs_stop(); | |
215 } | |
216 | |
217 if (!sidEmuInitializeSong(xs_emuEngine, *tune, tn)) { | |
218 xs_error = 1; | |
219 XSERR("Couldn't initialize SIDPlay emulator engine!\n"); | |
220 delete tune; | |
221 pthread_exit(NULL); | |
222 xs_stop(); | |
223 } | |
224 | |
225 tune->getInfo(sidInf); | |
226 | |
227 xmms_sid_ip.set_info(name, -1, | |
228 1000 * (sidInf.songSpeed ? sidInf.songSpeed : (sidInf.clockSpeed == SIDTUNE_CLOCK_NTSC) ? 60 : 50), | |
229 xs_emuConf.frequency, chn); | |
230 | |
231 while (xs_going == tn) | |
232 { | |
233 fxlen = XMMS_SID_BUFSIZE; | |
234 sidEmuFillBuffer(xs_emuEngine, *tune, data, fxlen); | |
235 | |
236 xmms_sid_ip.add_vis_pcm(xmms_sid_ip.output->written_time(), | 279 xmms_sid_ip.add_vis_pcm(xmms_sid_ip.output->written_time(), |
237 fmt, chn, fxlen, data); | 280 plr_fmt, xs_emuConf.channels, plr_fxlen, plr_data); |
238 | 281 |
239 while ((xs_going == tn) && (xmms_sid_ip.output->buffer_free() < fxlen)) | 282 /* Wait for a while */ |
283 while ((xs_status.s_playing == plr_tune_num) && (xmms_sid_ip.output->buffer_free() < plr_fxlen)) | |
240 xmms_usleep(10000); | 284 xmms_usleep(10000); |
241 | 285 |
242 if (xs_going == tn) | 286 |
243 xmms_sid_ip.output->write_audio(data, fxlen); | 287 /* If playing, send final audio data to output plugin */ |
244 } | 288 if (xs_status.s_playing == plr_tune_num) |
245 | 289 xmms_sid_ip.output->write_audio(plr_data, plr_fxlen); |
246 /* Exit the playing thread */ | 290 |
291 } /* End of playerloop */ | |
292 | |
293 | |
294 pl_cleanup: | |
295 XSDEBUG("cleaning up...\n"); | |
296 | |
297 /* Cleanup & shutdown */ | |
247 xmms_sid_ip.output->close_audio(); | 298 xmms_sid_ip.output->close_audio(); |
248 | 299 |
249 if (xs_going) goto play_loop_new_tune; | 300 if (plr_tune_title) g_free(plr_tune_title); |
250 | 301 |
251 g_free(name); | 302 pthread_mutex_lock(&xs_mutex); |
252 | 303 xs_status.s_playing = 0; |
253 delete tune; | 304 if (xs_status.s_tune) delete xs_status.s_tune; |
254 | 305 xs_status.s_allownext = 1; |
255 pthread_exit(NULL); | 306 pthread_mutex_unlock(&xs_mutex); |
307 | |
308 XSDEBUG("exiting thread, bye.\n"); | |
309 return NULL; | |
256 } | 310 } |
257 | 311 |
258 | 312 |
259 /* | 313 /* |
260 * Start playing the given file | 314 * Start playing the given file |
261 */ | 315 */ |
262 void xs_play_file(char *filename) | 316 void xs_play_file(char *fileName) |
263 { | 317 { |
264 sidTune *tune = new sidTune(filename); | 318 sidTune *newTune; |
265 struct sidTuneInfo sidInf; | 319 struct sidTuneInfo sidInf; |
266 | 320 |
267 /* Get current configuration */ | 321 XSDEBUG("request to start '%s'\n", fileName); |
268 xs_emuEngine.getConfig(xs_emuConf); | 322 |
269 | 323 /* Wait until the previous song has finished for sure */ |
270 /* Configure channels and stuff */ | 324 if (!xs_status.s_allownext) |
271 switch (xs_cfg.channels) { | 325 pthread_join(xs_decode_thread, NULL); |
326 | |
327 /* Try to get the tune */ | |
328 newTune = new sidTune(fileName); | |
329 if (newTune == NULL) return; | |
330 | |
331 XSDEBUG("tune ok, status %i\n", xs_status.s_playing); | |
332 | |
333 /* Get current configuration */ | |
334 xs_emuEngine.getConfig(xs_emuConf); | |
335 | |
336 | |
337 /* Configure channels and stuff */ | |
338 switch (xs_cfg.fmtChannels) { | |
272 | 339 |
273 case XMMS_SID_CHN_AUTOPAN: | 340 case XMMS_SID_CHN_AUTOPAN: |
274 xs_emuConf.channels = SIDEMU_STEREO; | 341 xs_emuConf.channels = SIDEMU_STEREO; |
275 xs_emuConf.autoPanning = SIDEMU_CENTEREDAUTOPANNING; | 342 xs_emuConf.autoPanning = SIDEMU_CENTEREDAUTOPANNING; |
276 xs_emuConf.volumeControl = SIDEMU_FULLPANNING; | 343 xs_emuConf.volumeControl = SIDEMU_FULLPANNING; |
286 xs_emuConf.channels = SIDEMU_MONO; | 353 xs_emuConf.channels = SIDEMU_MONO; |
287 xs_emuConf.autoPanning = SIDEMU_NONE; | 354 xs_emuConf.autoPanning = SIDEMU_NONE; |
288 xs_emuConf.volumeControl = SIDEMU_NONE; | 355 xs_emuConf.volumeControl = SIDEMU_NONE; |
289 break; | 356 break; |
290 | 357 |
291 default:xs_error = 1; | 358 default: |
292 XSERR("Internal: Invalid channels setting. Please report to author!\n"); | 359 XSERR("Internal: Invalid channels setting. Possibly corrupted configuration file.\n"); |
293 delete tune; | 360 delete newTune; |
294 break; | 361 return; |
295 } | 362 } |
296 | 363 |
297 /* Memory mode settings */ | 364 /* Memory mode settings */ |
298 switch (xs_cfg.memoryMode) { | 365 switch (xs_cfg.memoryMode) { |
299 case XMMS_SID_MPU_BANK_SWITCHING: | 366 case XMMS_SID_MPU_BANK_SWITCHING: |
300 xs_emuConf.memoryMode = MPU_BANK_SWITCHING; | 367 xs_emuConf.memoryMode = MPU_BANK_SWITCHING; |
301 break; | 368 break; |
302 | 369 |
303 case XMMS_SID_MPU_TRANSPARENT_ROM: | 370 case XMMS_SID_MPU_TRANSPARENT_ROM: |
306 | 373 |
307 case XMMS_SID_MPU_PLAYSID_ENVIRONMENT: | 374 case XMMS_SID_MPU_PLAYSID_ENVIRONMENT: |
308 xs_emuConf.memoryMode = MPU_PLAYSID_ENVIRONMENT; | 375 xs_emuConf.memoryMode = MPU_PLAYSID_ENVIRONMENT; |
309 break; | 376 break; |
310 | 377 |
311 default:xs_error = 1; | 378 default: |
312 XSERR("Internal: Invalid memoryMode setting. Please report to author!\n"); | 379 XSERR("Internal: Invalid memoryMode setting. Possibly corrupted configuration file.\n"); |
313 delete tune; | 380 delete newTune; |
314 break; | 381 return; |
315 } | 382 } |
316 | 383 |
317 | 384 |
318 /* Clockspeed settings */ | 385 /* Clockspeed settings */ |
319 switch (xs_cfg.clockSpeed) { | 386 switch (xs_cfg.clockSpeed) { |
320 case XMMS_SID_CLOCK_PAL: | 387 case XMMS_SID_CLOCK_PAL: |
321 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_PAL; | 388 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_PAL; |
322 break; | 389 break; |
323 | 390 |
324 case XMMS_SID_CLOCK_NTSC: | 391 case XMMS_SID_CLOCK_NTSC: |
325 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_NTSC; | 392 xs_emuConf.clockSpeed = SIDTUNE_CLOCK_NTSC; |
326 break; | 393 break; |
327 | 394 |
328 default:xs_error = 1; | 395 default: |
329 XSERR("Internal: Invalid clockSpeed setting. Please report to author!\n"); | 396 XSERR("Internal: Invalid clockSpeed setting. Possibly corrupted configuration file.\n"); |
330 delete tune; | 397 delete newTune; |
331 break; | 398 return; |
332 } | 399 } |
333 | 400 |
334 /* Configure rest of the paske */ | 401 |
335 xs_emuConf.bitsPerSample = xs_cfg.bitsPerSample; | 402 /* Configure rest of the emulation */ |
336 xs_emuConf.frequency = xs_cfg.frequency; | 403 xs_emuConf.bitsPerSample = xs_cfg.fmtBitsPerSample; |
337 xs_emuConf.sampleFormat = SIDEMU_SIGNED_PCM; | 404 xs_emuConf.frequency = xs_cfg.fmtFrequency; |
338 xs_emuConf.mos8580 = xs_cfg.mos8580; | 405 xs_emuConf.sampleFormat = SIDEMU_SIGNED_PCM; |
339 xs_emuConf.emulateFilter = xs_cfg.emulateFilter; | 406 xs_emuConf.mos8580 = xs_cfg.mos8580; |
340 xs_emuConf.filterFs = xs_cfg.filterFs; | 407 xs_emuConf.emulateFilter = xs_cfg.emulateFilter; |
341 xs_emuConf.filterFm = xs_cfg.filterFm; | 408 xs_emuConf.filterFs = xs_cfg.filterFs; |
342 xs_emuConf.filterFt = xs_cfg.filterFt; | 409 xs_emuConf.filterFm = xs_cfg.filterFm; |
343 | 410 xs_emuConf.filterFt = xs_cfg.filterFt; |
344 /* Now set the emulator configuration */ | 411 |
345 xs_emuEngine.setConfig(xs_emuConf); | 412 XSDEBUG("configuring engine..\n"); |
346 tune->getInfo(sidInf); | 413 |
347 xs_error = 0; | 414 /* Now set the emulator configuration */ |
348 xs_going = sidInf.startSong; | 415 xs_emuEngine.setConfig(xs_emuConf); |
349 xs_songs = sidInf.songs; | 416 newTune->getInfo(sidInf); |
350 | 417 |
351 /* Start the playing thread! */ | 418 pthread_mutex_lock(&xs_mutex); |
352 if (pthread_create(&xs_decode_thread, NULL, xs_play_loop, tune) < 0) { | 419 xs_status.s_error = 0; |
353 xs_error = 1; | 420 xs_status.s_playing = sidInf.startSong; |
354 XSERR("Couldn't start playing thread!\n"); | 421 xs_status.s_songs = sidInf.songs; |
355 delete tune; | 422 xs_status.s_tune = newTune; |
356 } | 423 pthread_mutex_unlock(&xs_mutex); |
357 } | 424 |
358 | 425 XSDEBUG("starting thread!\n"); |
359 | 426 |
360 /* | 427 /* Start the playing thread! */ |
361 * Stop playing | 428 if (pthread_create(&xs_decode_thread, NULL, xs_play_loop, NULL) < 0) |
429 { | |
430 XSERR("Couldn't start playing thread! Possible reason reported by system: %s\n", strerror(errno)); | |
431 delete newTune; | |
432 } | |
433 | |
434 /* Exit */ | |
435 } | |
436 | |
437 | |
438 /* | |
439 * Stop playing | |
362 */ | 440 */ |
363 void xs_stop(void) | 441 void xs_stop(void) |
364 { | 442 { |
365 if (xs_going) | 443 /* If playing, stop. */ |
366 { | 444 if (xs_status.s_playing) |
367 xs_going = 0; | 445 { |
368 pthread_join(xs_decode_thread, NULL); | 446 pthread_mutex_lock(&xs_mutex); |
369 } | 447 xs_status.s_playing = 0; |
370 } | 448 pthread_mutex_unlock(&xs_mutex); |
371 | 449 |
372 | 450 pthread_join(xs_decode_thread, NULL); |
373 /* | 451 } |
374 * Pause the playing | 452 } |
375 */ | 453 |
376 void xs_pause(short p) | 454 |
377 { | 455 /* |
378 xmms_sid_ip.output->pause(p); | 456 * Pause the playing |
379 } | 457 */ |
380 | 458 void xs_pause(short pauseState) |
381 | 459 { |
382 /* | 460 xmms_sid_ip.output->pause(pauseState); |
383 * Set the time-seek position | 461 } |
384 * (the playing thread will do the "seeking" aka song-change) | 462 |
385 */ | 463 |
386 void xs_seek(int time) | 464 /* |
387 { | 465 * Set the time-seek position |
388 if ((time > 0) && (time <= xs_songs)) { | 466 * (the playing thread will do the "seeking" aka song-change) |
389 xs_going = time; | 467 */ |
390 } | 468 void xs_seek(int iTime) |
391 } | 469 { |
392 | 470 #ifdef HAVE_SONG_POSITION |
393 | 471 if ((iTime > 0) && (iTime <= xs_songs)) |
394 /* | 472 { |
395 * Return the playing "position/time" aka song number | 473 pthread_mutex_lock(&xs_mutex); |
474 xs_status.s_playing = iTime; | |
475 pthread_mutex_unlock(&xs_mutex); | |
476 } | |
477 #endif | |
478 } | |
479 | |
480 | |
481 /* | |
482 * Return the playing "position/time" | |
396 */ | 483 */ |
397 int xs_get_time(void) | 484 int xs_get_time(void) |
398 { | 485 { |
399 if (xs_error) return -2; | 486 if (xs_status.s_error) |
400 if (!xs_going) return -1; | 487 return -2; |
488 | |
489 if (!xs_status.s_playing) | |
490 return -1; | |
491 | |
401 #ifdef HAVE_SONG_POSITION | 492 #ifdef HAVE_SONG_POSITION |
402 set_song_position(xs_going, 1, xs_songs); | 493 set_song_position(xs_status.s_playing, 1, xs_status.s_songs); |
403 #endif | 494 #endif |
404 return xmms_sid_ip.output->output_time(); | 495 |
405 } | 496 return xmms_sid_ip.output->output_time(); |
406 | 497 } |
407 | 498 |
408 /* | 499 |
409 * Return song information | 500 /* |
410 */ | 501 * Return song information |
411 void xs_get_song_info(char *filename, char **title, int *length) | 502 */ |
412 { | 503 void xs_get_song_info(char *songFilename, char **songTitle, int *songLength) |
413 struct sidTuneInfo sidInf; | 504 { |
414 sidTune t(filename); | 505 struct sidTuneInfo sidInf; |
415 | 506 sidTune *testTune = new sidTune(songFilename); |
416 if (!t) return; | 507 |
417 | 508 /* Check if the tune exists and is readable */ |
418 t.getInfo(sidInf); | 509 if (!testTune) return; |
419 | 510 if (!testTune->getStatus()) |
420 *title = xs_make_filedesc(&sidInf); | 511 { |
421 | 512 delete testTune; |
422 *length = -1; | 513 return; |
423 } | 514 } |
424 | 515 |
425 | 516 /* Get general tune information */ |
517 testTune->getInfo(sidInf); | |
518 delete testTune; | |
519 | |
520 /* Get titlestring */ | |
521 *songTitle = xs_get_filetitle(&sidInf, sidInf.startSong); | |
522 | |
523 /* Get song length (in seconds), negative if no known length */ | |
524 *songLength = xs_get_length(songFilename, sidInf.startSong); | |
525 } | |
526 |