Mercurial > audlegacy
annotate Plugins/Input/console/Audacious_Driver.cpp @ 421:147325df7461 trunk
[svn] SPC titleinput fix. Contributed by Kiyoshi Aman <kiyoshi.aman -at- gmail.com>.
author | nenolod |
---|---|
date | Fri, 13 Jan 2006 14:57:57 -0800 |
parents | 8ddd961ef0ff |
children | fc98032223d1 |
rev | line source |
---|---|
90
252843aac42f
[svn] Import the initial sources for console music support.
nenolod
parents:
diff
changeset
|
1 /* |
252843aac42f
[svn] Import the initial sources for console music support.
nenolod
parents:
diff
changeset
|
2 * Audacious: Cross platform multimedia player |
252843aac42f
[svn] Import the initial sources for console music support.
nenolod
parents:
diff
changeset
|
3 * Copyright (c) 2005 Audacious Team |
252843aac42f
[svn] Import the initial sources for console music support.
nenolod
parents:
diff
changeset
|
4 * |
252843aac42f
[svn] Import the initial sources for console music support.
nenolod
parents:
diff
changeset
|
5 * Driver for Game_Music_Emu library. See details at: |
252843aac42f
[svn] Import the initial sources for console music support.
nenolod
parents:
diff
changeset
|
6 * http://www.slack.net/~ant/libs/ |
252843aac42f
[svn] Import the initial sources for console music support.
nenolod
parents:
diff
changeset
|
7 */ |
252843aac42f
[svn] Import the initial sources for console music support.
nenolod
parents:
diff
changeset
|
8 |
94 | 9 #include "Audacious_Driver.h" |
90
252843aac42f
[svn] Import the initial sources for console music support.
nenolod
parents:
diff
changeset
|
10 |
98
e42694a28331
[svn] More progress -- now loads as an audacious module. :)
nenolod
parents:
96
diff
changeset
|
11 extern "C" { |
e42694a28331
[svn] More progress -- now loads as an audacious module. :)
nenolod
parents:
96
diff
changeset
|
12 |
109 | 13 #include <glib.h> |
96 | 14 #include <glib/gi18n.h> |
109 | 15 #include <gtk/gtk.h> |
319
1e642d74d68c
[svn] Do not abort if libmpc is not found, just disable musepack plugin.
chainsaw
parents:
288
diff
changeset
|
16 #include "libaudacious/configdb.h" |
94 | 17 #include "libaudacious/util.h" |
18 #include "libaudacious/titlestring.h" | |
366
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
19 #include "libaudacious/vfs.h" |
145 | 20 #include "audacious/input.h" |
95 | 21 #include "audacious/output.h" |
288 | 22 #include "libaudcore/playback.h" |
94 | 23 |
98
e42694a28331
[svn] More progress -- now loads as an audacious module. :)
nenolod
parents:
96
diff
changeset
|
24 }; |
e42694a28331
[svn] More progress -- now loads as an audacious module. :)
nenolod
parents:
96
diff
changeset
|
25 |
145 | 26 struct AudaciousConsoleConfig audcfg = { 180, FALSE, 32000 }; |
27 | |
94 | 28 #include <cstring> |
213 | 29 #include <stdio.h> |
94 | 30 |
31 static Spc_Emu *spc = NULL; | |
213 | 32 static Nsf_Emu *nsf = NULL; |
214 | 33 static Gbs_Emu *gbs = NULL; |
334 | 34 static Gym_Emu *gym = NULL; |
364 | 35 static Vgm_Emu *vgm = NULL; |
95 | 36 static GThread *decode_thread; |
213 | 37 GStaticMutex playback_mutex = G_STATIC_MUTEX_INIT; |
95 | 38 |
147
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
39 static void *play_loop_spc(gpointer arg); |
213 | 40 static void *play_loop_nsf(gpointer arg); |
214 | 41 static void *play_loop_gbs(gpointer arg); |
334 | 42 static void *play_loop_gym(gpointer arg); |
364 | 43 static void *play_loop_vgm(gpointer arg); |
100 | 44 static void console_init(void); |
109 | 45 extern "C" void console_aboutbox(void); |
96 | 46 static void console_stop(void); |
47 static void console_pause(gshort p); | |
48 static int get_time(void); | |
103 | 49 static gboolean console_ip_is_going; |
100 | 50 extern InputPlugin console_ip; |
147
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
51 static int playing_type; |
100 | 52 |
94 | 53 static int is_our_file(gchar *filename) |
54 { | |
366
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
55 VFSFile *file; |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
56 gchar magic[4]; |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
57 if (file = vfs_fopen(filename, "rb")) { |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
58 vfs_fread(magic, 1, 4, file); |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
59 if (!strncmp(magic, "SNES", 4)) { |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
60 vfs_fclose(file); |
213 | 61 return PLAY_TYPE_SPC; |
366
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
62 } |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
63 if (!strncmp(magic, "NESM", 4)) { |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
64 vfs_fclose(file); |
213 | 65 return PLAY_TYPE_NSF; |
366
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
66 } |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
67 if (!strncmp(magic, "GYMX", 4)) { |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
68 vfs_fclose(file); |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
69 return PLAY_TYPE_GYM; |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
70 } |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
71 vfs_fclose(file); |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
72 } |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
73 if (file = vfs_fopen(filename, "rb")) { |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
74 vfs_fread(magic, 1, 3, file); |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
75 if (!strncmp(magic, "GBS", 3)) { |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
76 vfs_fclose(file); |
214 | 77 return PLAY_TYPE_GBS; |
366
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
78 } |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
79 if (!strncmp(magic, "Vgm", 3)) { |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
80 vfs_fclose(file); |
364 | 81 return PLAY_TYPE_VGM; |
366
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
82 } |
4a9139a7b53e
[svn] Use file magic instead of extensions (Phase 2).
chainsaw
parents:
365
diff
changeset
|
83 vfs_fclose(file); |
94 | 84 } |
85 return 0; | |
86 } | |
87 | |
148 | 88 static gchar *get_title_spc(gchar *filename) |
94 | 89 { |
90 gchar *title; | |
91 Emu_Std_Reader reader; | |
92 Spc_Emu::header_t header; | |
93 | |
94 reader.open(filename); | |
95 reader.read(&header, sizeof(header)); | |
96 | |
363
eaaee9e0519c
[svn] Properly fall back to file name if the tag information is invalid (SPC).
chainsaw
parents:
362
diff
changeset
|
97 if (header.version > 10) |
104 | 98 { |
99 TitleInput *tinput; | |
100 | |
101 tinput = bmp_title_input_new(); | |
102 | |
421
147325df7461
[svn] SPC titleinput fix. Contributed by Kiyoshi Aman <kiyoshi.aman -at- gmail.com>.
nenolod
parents:
417
diff
changeset
|
103 tinput->performer = g_strdup(header.author); |
104 | 104 tinput->album_name = g_strdup(header.game); |
105 tinput->track_name = g_strdup(header.song); | |
94 | 106 |
104 | 107 tinput->file_name = g_path_get_basename(filename); |
108 tinput->file_path = g_path_get_dirname(filename); | |
109 | |
110 title = xmms_get_titlestring(xmms_get_gentitle_format(), | |
111 tinput); | |
112 | |
113 g_free(tinput); | |
114 } | |
115 else | |
213 | 116 title = g_path_get_basename(filename); |
117 | |
118 return title; | |
119 } | |
99 | 120 |
213 | 121 static gchar *get_title_nsf(gchar *filename) |
122 { | |
123 gchar *title; | |
124 title = g_path_get_basename(filename); | |
94 | 125 return title; |
126 } | |
95 | 127 |
214 | 128 static gchar *get_title_gbs(gchar *filename) |
129 { | |
130 gchar *title; | |
131 title = g_path_get_basename(filename); | |
132 return title; | |
133 } | |
134 | |
334 | 135 static gchar *get_title_gym(gchar *filename) |
136 { | |
137 gchar *title; | |
365 | 138 Emu_Std_Reader reader; |
139 Gym_Emu::header_t header; | |
140 | |
141 reader.open(filename); | |
142 reader.read(&header, sizeof(header)); | |
143 | |
144 if (header.song) | |
145 { | |
146 TitleInput *tinput; | |
147 | |
148 tinput = bmp_title_input_new(); | |
149 | |
150 tinput->performer = g_strdup(header.game); | |
151 tinput->album_name = g_strdup(header.game); | |
152 tinput->track_name = g_strdup(header.song); | |
153 | |
154 tinput->file_name = g_path_get_basename(filename); | |
155 tinput->file_path = g_path_get_dirname(filename); | |
156 | |
157 title = xmms_get_titlestring(xmms_get_gentitle_format(), | |
158 tinput); | |
159 | |
160 g_free(tinput); | |
161 } | |
162 else | |
163 title = g_path_get_basename(filename); | |
164 | |
334 | 165 return title; |
166 } | |
167 | |
364 | 168 static gchar *get_title_vgm(gchar *filename) |
169 { | |
170 gchar *title; | |
171 title = g_path_get_basename(filename); | |
172 return title; | |
173 } | |
174 | |
148 | 175 static gchar *get_title(gchar *filename) |
176 { | |
213 | 177 switch (is_our_file(filename)) |
148 | 178 { |
213 | 179 case PLAY_TYPE_SPC: |
148 | 180 return get_title_spc(filename); |
213 | 181 break; |
182 case PLAY_TYPE_NSF: | |
183 return get_title_nsf(filename); | |
184 break; | |
214 | 185 case PLAY_TYPE_GBS: |
186 return get_title_gbs(filename); | |
187 break; | |
334 | 188 case PLAY_TYPE_GYM: |
189 return get_title_gym(filename); | |
190 break; | |
364 | 191 case PLAY_TYPE_VGM: |
192 return get_title_vgm(filename); | |
193 break; | |
148 | 194 } |
195 | |
196 return NULL; | |
197 } | |
198 | |
95 | 199 static void get_song_info(char *filename, char **title, int *length) |
200 { | |
201 (*title) = get_title(filename); | |
145 | 202 |
203 if (audcfg.loop_length) | |
204 (*length) = audcfg.loop_length; | |
205 else | |
206 (*length) = -1; | |
95 | 207 } |
208 | |
147
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
209 static void play_file_spc(char *filename) |
95 | 210 { |
106
d2b88d78ccd7
[svn] Tell the player that the decoder has fired up :)
nenolod
parents:
105
diff
changeset
|
211 gchar *name; |
95 | 212 Emu_Std_Reader reader; |
213 Spc_Emu::header_t header; | |
149 | 214 gint samplerate; |
215 | |
216 if (audcfg.resample == TRUE) | |
217 samplerate = audcfg.resample_rate; | |
218 else | |
219 samplerate = Spc_Emu::native_sample_rate; | |
95 | 220 |
221 reader.open(filename); | |
222 reader.read(&header, sizeof(header)); | |
223 | |
224 spc = new Spc_Emu; | |
149 | 225 spc->init(samplerate); |
95 | 226 spc->load(header, reader); |
227 spc->start_track(0); | |
228 | |
103 | 229 console_ip_is_going = TRUE; |
230 | |
106
d2b88d78ccd7
[svn] Tell the player that the decoder has fired up :)
nenolod
parents:
105
diff
changeset
|
231 name = get_title(filename); |
d2b88d78ccd7
[svn] Tell the player that the decoder has fired up :)
nenolod
parents:
105
diff
changeset
|
232 |
145 | 233 if (audcfg.loop_length) |
234 console_ip.set_info(name, audcfg.loop_length * 1000, | |
149 | 235 spc->voice_count() * 1000, samplerate, 2); |
145 | 236 else |
149 | 237 console_ip.set_info(name, -1, spc->voice_count() * 1000, |
238 samplerate, 2); | |
106
d2b88d78ccd7
[svn] Tell the player that the decoder has fired up :)
nenolod
parents:
105
diff
changeset
|
239 |
d2b88d78ccd7
[svn] Tell the player that the decoder has fired up :)
nenolod
parents:
105
diff
changeset
|
240 g_free(name); |
d2b88d78ccd7
[svn] Tell the player that the decoder has fired up :)
nenolod
parents:
105
diff
changeset
|
241 |
417
8ddd961ef0ff
[svn] Use FMT_S16_NE instead of unnecessary #ifdef WORDS_BIGENDIAN trickery.
chainsaw
parents:
371
diff
changeset
|
242 if (!console_ip.output->open_audio(FMT_S16_NE, samplerate, 2)) |
100 | 243 return; |
133
3fb426494de8
[svn] Open the output channel before firing up the thread.
nenolod
parents:
109
diff
changeset
|
244 |
147
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
245 playing_type = PLAY_TYPE_SPC; |
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
246 |
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
247 decode_thread = g_thread_create(play_loop_spc, spc, TRUE, NULL); |
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
248 } |
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
249 |
213 | 250 static void play_file_nsf(char *filename) |
251 { | |
252 gchar *name; | |
253 Emu_Std_Reader reader; | |
254 Nsf_Emu::header_t header; | |
255 gint samplerate; | |
256 | |
257 if (audcfg.resample == TRUE) | |
258 samplerate = audcfg.resample_rate; | |
259 else | |
260 samplerate = 44100; | |
261 | |
262 reader.open(filename); | |
263 reader.read(&header, sizeof(header)); | |
264 | |
265 nsf = new Nsf_Emu; | |
266 nsf->init(samplerate); | |
267 nsf->load(header, reader); | |
268 nsf->start_track(0); | |
269 | |
270 console_ip_is_going = TRUE; | |
271 | |
272 name = get_title(filename); | |
273 | |
274 if (audcfg.loop_length) | |
275 console_ip.set_info(name, audcfg.loop_length * 1000, | |
276 nsf->voice_count() * 1000, samplerate, 2); | |
277 else | |
278 console_ip.set_info(name, -1, nsf->voice_count() * 1000, | |
279 samplerate, 2); | |
280 | |
281 g_free(name); | |
282 | |
417
8ddd961ef0ff
[svn] Use FMT_S16_NE instead of unnecessary #ifdef WORDS_BIGENDIAN trickery.
chainsaw
parents:
371
diff
changeset
|
283 if (!console_ip.output->open_audio(FMT_S16_NE, samplerate, 2)) |
213 | 284 return; |
285 | |
286 playing_type = PLAY_TYPE_NSF; | |
287 | |
288 decode_thread = g_thread_create(play_loop_nsf, nsf, TRUE, NULL); | |
289 } | |
290 | |
214 | 291 static void play_file_gbs(char *filename) |
292 { | |
293 gchar *name; | |
294 Emu_Std_Reader reader; | |
295 Gbs_Emu::header_t header; | |
296 gint samplerate; | |
297 | |
298 if (audcfg.resample == TRUE) | |
299 samplerate = audcfg.resample_rate; | |
300 else | |
301 samplerate = 44100; | |
302 | |
303 reader.open(filename); | |
304 reader.read(&header, sizeof(header)); | |
305 | |
306 gbs = new Gbs_Emu; | |
307 gbs->init(samplerate); | |
308 gbs->load(header, reader); | |
309 gbs->start_track(0); | |
310 | |
311 console_ip_is_going = TRUE; | |
312 | |
313 name = get_title(filename); | |
314 | |
315 if (audcfg.loop_length) | |
316 console_ip.set_info(name, audcfg.loop_length * 1000, | |
317 gbs->voice_count() * 1000, samplerate, 2); | |
318 else | |
334 | 319 console_ip.set_info(name, -1, gbs->voice_count() * 1000, |
214 | 320 samplerate, 2); |
321 | |
322 g_free(name); | |
323 | |
417
8ddd961ef0ff
[svn] Use FMT_S16_NE instead of unnecessary #ifdef WORDS_BIGENDIAN trickery.
chainsaw
parents:
371
diff
changeset
|
324 if (!console_ip.output->open_audio(FMT_S16_NE, samplerate, 2)) |
214 | 325 return; |
326 | |
327 playing_type = PLAY_TYPE_GBS; | |
328 | |
329 decode_thread = g_thread_create(play_loop_gbs, gbs, TRUE, NULL); | |
330 } | |
331 | |
334 | 332 static void play_file_gym(char *filename) |
333 { | |
334 gchar *name; | |
335 Emu_Std_Reader reader; | |
336 Gym_Emu::header_t header; | |
337 gint samplerate; | |
338 | |
339 if (audcfg.resample == TRUE) | |
340 samplerate = audcfg.resample_rate; | |
341 else | |
342 samplerate = 44100; | |
343 | |
344 reader.open(filename); | |
345 reader.read(&header, sizeof(header)); | |
346 | |
347 gym = new Gym_Emu; | |
348 gym->init(samplerate); | |
349 gym->load(header, reader); | |
350 gym->start_track(0); | |
351 | |
352 console_ip_is_going = TRUE; | |
353 | |
354 name = get_title(filename); | |
355 | |
362 | 356 if (gym->track_length() > 0) |
357 console_ip.set_info(name, gym->track_length() * 1000, | |
358 gym->voice_count() * 1000, samplerate, 2); | |
359 else if (audcfg.loop_length) | |
334 | 360 console_ip.set_info(name, audcfg.loop_length * 1000, |
361 gym->voice_count() * 1000, samplerate, 2); | |
362 else | |
363 console_ip.set_info(name, -1, gym->voice_count() * 1000, | |
364 samplerate, 2); | |
365 | |
366 g_free(name); | |
367 | |
417
8ddd961ef0ff
[svn] Use FMT_S16_NE instead of unnecessary #ifdef WORDS_BIGENDIAN trickery.
chainsaw
parents:
371
diff
changeset
|
368 if (!console_ip.output->open_audio(FMT_S16_NE, samplerate, 2)) |
334 | 369 return; |
370 | |
371 playing_type = PLAY_TYPE_GYM; | |
372 | |
373 decode_thread = g_thread_create(play_loop_gym, gym, TRUE, NULL); | |
374 } | |
375 | |
364 | 376 static void play_file_vgm(char *filename) |
377 { | |
378 gchar *name; | |
379 Emu_Std_Reader reader; | |
380 Vgm_Emu::header_t header; | |
381 gint samplerate; | |
382 | |
383 if (audcfg.resample == TRUE) | |
384 samplerate = audcfg.resample_rate; | |
385 else | |
386 samplerate = 44100; | |
387 | |
388 reader.open(filename); | |
389 reader.read(&header, sizeof(header)); | |
390 | |
391 vgm = new Vgm_Emu; | |
392 vgm->init(samplerate); | |
393 vgm->load(header, reader); | |
394 vgm->start_track(0); | |
395 | |
396 console_ip_is_going = TRUE; | |
397 | |
398 name = get_title(filename); | |
399 | |
400 if (audcfg.loop_length) | |
401 console_ip.set_info(name, audcfg.loop_length * 1000, | |
402 vgm->voice_count() * 1000, samplerate, 2); | |
403 else | |
404 console_ip.set_info(name, -1, vgm->voice_count() * 1000, | |
405 samplerate, 2); | |
406 | |
407 g_free(name); | |
408 | |
417
8ddd961ef0ff
[svn] Use FMT_S16_NE instead of unnecessary #ifdef WORDS_BIGENDIAN trickery.
chainsaw
parents:
371
diff
changeset
|
409 if (!console_ip.output->open_audio(FMT_S16_NE, samplerate, 2)) |
364 | 410 return; |
411 | |
412 playing_type = PLAY_TYPE_VGM; | |
413 | |
414 decode_thread = g_thread_create(play_loop_vgm, vgm, TRUE, NULL); | |
415 } | |
416 | |
147
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
417 static void play_file(char *filename) |
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
418 { |
213 | 419 switch (is_our_file(filename)) |
147
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
420 { |
213 | 421 case PLAY_TYPE_SPC: |
147
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
422 play_file_spc(filename); |
213 | 423 break; |
424 case PLAY_TYPE_NSF: | |
425 play_file_nsf(filename); | |
426 break; | |
214 | 427 case PLAY_TYPE_GBS: |
428 play_file_gbs(filename); | |
429 break; | |
334 | 430 case PLAY_TYPE_GYM: |
431 play_file_gym(filename); | |
432 break; | |
364 | 433 case PLAY_TYPE_VGM: |
434 play_file_vgm(filename); | |
435 break; | |
147
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
436 } |
95 | 437 } |
438 | |
96 | 439 static void seek(gint time) |
440 { | |
441 // XXX: Not yet implemented | |
442 } | |
443 | |
444 InputPlugin console_ip = { | |
445 NULL, | |
446 NULL, | |
447 NULL, | |
448 console_init, | |
109 | 449 console_aboutbox, |
96 | 450 NULL, |
451 is_our_file, | |
452 NULL, | |
453 play_file, | |
454 console_stop, | |
455 console_pause, | |
456 seek, | |
457 NULL, | |
458 get_time, | |
459 NULL, | |
460 NULL, | |
461 NULL, | |
462 NULL, | |
463 NULL, | |
464 NULL, | |
465 NULL, | |
104 | 466 get_song_info, |
96 | 467 NULL, |
468 NULL | |
469 }; | |
470 | |
471 static void console_stop(void) | |
472 { | |
103 | 473 console_ip_is_going = FALSE; |
96 | 474 g_thread_join(decode_thread); |
475 console_ip.output->close_audio(); | |
476 } | |
477 | |
98
e42694a28331
[svn] More progress -- now loads as an audacious module. :)
nenolod
parents:
96
diff
changeset
|
478 extern "C" InputPlugin *get_iplugin_info(void) |
96 | 479 { |
109 | 480 console_ip.description = g_strdup_printf(_("SPC, GYM, NSF, VGM and GBS module decoder")); |
96 | 481 return &console_ip; |
482 } | |
483 | |
484 static void console_pause(gshort p) | |
485 { | |
486 console_ip.output->pause(p); | |
487 } | |
488 | |
147
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
489 static void *play_loop_spc(gpointer arg) |
95 | 490 { |
213 | 491 g_static_mutex_lock(&playback_mutex); |
99 | 492 Spc_Emu *my_spc = (Spc_Emu *) arg; |
213 | 493 Music_Emu::sample_t buf[1024]; |
95 | 494 |
145 | 495 for (;;) |
496 { | |
497 if (!console_ip_is_going) | |
498 break; | |
499 | |
500 my_spc->play(1024, buf); | |
501 | |
502 if ((console_ip.output->output_time() / 1000) > | |
503 audcfg.loop_length && audcfg.loop_length != 0) | |
504 break; | |
349 | 505 produce_audio(console_ip.output->written_time(), |
417
8ddd961ef0ff
[svn] Use FMT_S16_NE instead of unnecessary #ifdef WORDS_BIGENDIAN trickery.
chainsaw
parents:
371
diff
changeset
|
506 FMT_S16_NE, 1, 2048, buf, NULL); |
108 | 507 while(console_ip.output->buffer_free() < 2048) |
101
59ba6595fdf1
[svn] More accurate sound reproduction, but there is warbling. Still locks up player on completion.
nenolod
parents:
100
diff
changeset
|
508 xmms_usleep(10000); |
100 | 509 } |
95 | 510 |
96 | 511 delete spc; |
145 | 512 console_ip.output->close_audio(); |
513 console_ip_is_going = FALSE; | |
147
6fe2bfbe6fc2
[svn] Move SPC-specific code into SPC-specific routines.
nenolod
parents:
146
diff
changeset
|
514 playing_type = PLAY_TYPE_NONE; |
213 | 515 g_static_mutex_unlock(&playback_mutex); |
516 g_thread_exit(NULL); | |
517 | |
518 return NULL; | |
519 } | |
520 | |
521 static void *play_loop_nsf(gpointer arg) | |
522 { | |
523 g_static_mutex_lock(&playback_mutex); | |
524 Nsf_Emu *my_nsf = (Nsf_Emu *) arg; | |
525 Music_Emu::sample_t buf[1024]; | |
526 | |
527 for (;;) | |
528 { | |
529 if (!console_ip_is_going) | |
530 break; | |
531 | |
532 my_nsf->play(1024, buf); | |
533 | |
534 if ((console_ip.output->output_time() / 1000) > | |
535 audcfg.loop_length && audcfg.loop_length != 0) | |
536 break; | |
349 | 537 produce_audio(console_ip.output->written_time(), |
417
8ddd961ef0ff
[svn] Use FMT_S16_NE instead of unnecessary #ifdef WORDS_BIGENDIAN trickery.
chainsaw
parents:
371
diff
changeset
|
538 FMT_S16_NE, 1, 2048, buf, NULL); |
213 | 539 while(console_ip.output->buffer_free() < 2048) |
540 xmms_usleep(10000); | |
541 } | |
542 | |
543 delete nsf; | |
544 console_ip.output->close_audio(); | |
545 console_ip_is_going = FALSE; | |
546 playing_type = PLAY_TYPE_NONE; | |
547 g_static_mutex_unlock(&playback_mutex); | |
96 | 548 g_thread_exit(NULL); |
95 | 549 |
96 | 550 return NULL; |
95 | 551 } |
552 | |
214 | 553 static void *play_loop_gbs(gpointer arg) |
554 { | |
555 g_static_mutex_lock(&playback_mutex); | |
556 Gbs_Emu *my_gbs = (Gbs_Emu *) arg; | |
557 Music_Emu::sample_t buf[1024]; | |
558 | |
559 for (;;) | |
560 { | |
561 if (!console_ip_is_going) | |
562 break; | |
563 | |
564 my_gbs->play(1024, buf); | |
565 | |
566 if ((console_ip.output->output_time() / 1000) > | |
567 audcfg.loop_length && audcfg.loop_length != 0) | |
568 break; | |
349 | 569 produce_audio(console_ip.output->written_time(), |
417
8ddd961ef0ff
[svn] Use FMT_S16_NE instead of unnecessary #ifdef WORDS_BIGENDIAN trickery.
chainsaw
parents:
371
diff
changeset
|
570 FMT_S16_NE, 1, 2048, buf, NULL); |
214 | 571 while(console_ip.output->buffer_free() < 2048) |
572 xmms_usleep(10000); | |
573 } | |
574 | |
575 delete gbs; | |
576 console_ip.output->close_audio(); | |
577 console_ip_is_going = FALSE; | |
578 playing_type = PLAY_TYPE_NONE; | |
579 g_static_mutex_unlock(&playback_mutex); | |
580 g_thread_exit(NULL); | |
581 | |
582 return NULL; | |
583 } | |
584 | |
334 | 585 static void *play_loop_gym(gpointer arg) |
586 { | |
587 g_static_mutex_lock(&playback_mutex); | |
588 Gym_Emu *my_gym = (Gym_Emu *) arg; | |
589 Music_Emu::sample_t buf[1024]; | |
590 | |
591 for (;;) | |
592 { | |
593 if (!console_ip_is_going) | |
594 break; | |
595 | |
596 my_gym->play(1024, buf); | |
597 | |
598 if ((console_ip.output->output_time() / 1000) > | |
371
e296500f595a
[svn] Stop GYM playback at the right time, if the length is known.
chainsaw
parents:
366
diff
changeset
|
599 gym->track_length() && gym->track_length() != 0) |
e296500f595a
[svn] Stop GYM playback at the right time, if the length is known.
chainsaw
parents:
366
diff
changeset
|
600 break; |
e296500f595a
[svn] Stop GYM playback at the right time, if the length is known.
chainsaw
parents:
366
diff
changeset
|
601 if ((console_ip.output->output_time() / 1000) > |
334 | 602 audcfg.loop_length && audcfg.loop_length != 0) |
603 break; | |
349 | 604 produce_audio(console_ip.output->written_time(), |
417
8ddd961ef0ff
[svn] Use FMT_S16_NE instead of unnecessary #ifdef WORDS_BIGENDIAN trickery.
chainsaw
parents:
371
diff
changeset
|
605 FMT_S16_NE, 1, 2048, buf, NULL); |
334 | 606 while(console_ip.output->buffer_free() < 2048) |
607 xmms_usleep(10000); | |
608 } | |
609 | |
610 delete gym; | |
611 console_ip.output->close_audio(); | |
612 console_ip_is_going = FALSE; | |
613 playing_type = PLAY_TYPE_NONE; | |
614 g_static_mutex_unlock(&playback_mutex); | |
615 g_thread_exit(NULL); | |
616 | |
617 return NULL; | |
618 } | |
619 | |
364 | 620 static void *play_loop_vgm(gpointer arg) |
621 { | |
622 g_static_mutex_lock(&playback_mutex); | |
623 Vgm_Emu *my_vgm = (Vgm_Emu *) arg; | |
624 Music_Emu::sample_t buf[1024]; | |
625 | |
626 for (;;) | |
627 { | |
628 if (!console_ip_is_going) | |
629 break; | |
630 | |
631 my_vgm->play(1024, buf); | |
632 | |
633 if ((console_ip.output->output_time() / 1000) > | |
634 audcfg.loop_length && audcfg.loop_length != 0) | |
635 break; | |
636 produce_audio(console_ip.output->written_time(), | |
417
8ddd961ef0ff
[svn] Use FMT_S16_NE instead of unnecessary #ifdef WORDS_BIGENDIAN trickery.
chainsaw
parents:
371
diff
changeset
|
637 FMT_S16_NE, 1, 2048, buf, NULL); |
364 | 638 while(console_ip.output->buffer_free() < 2048) |
639 xmms_usleep(10000); | |
640 } | |
641 | |
642 delete vgm; | |
643 console_ip.output->close_audio(); | |
644 console_ip_is_going = FALSE; | |
645 playing_type = PLAY_TYPE_NONE; | |
646 g_static_mutex_unlock(&playback_mutex); | |
647 g_thread_exit(NULL); | |
648 | |
649 return NULL; | |
650 } | |
651 | |
96 | 652 static int get_time(void) |
653 { | |
145 | 654 if (console_ip_is_going == TRUE) |
655 return console_ip.output->output_time(); | |
656 else | |
657 return -1; | |
96 | 658 } |
95 | 659 |
100 | 660 static void console_init(void) |
661 { | |
319
1e642d74d68c
[svn] Do not abort if libmpc is not found, just disable musepack plugin.
chainsaw
parents:
288
diff
changeset
|
662 ConfigDb *db; |
100 | 663 |
319
1e642d74d68c
[svn] Do not abort if libmpc is not found, just disable musepack plugin.
chainsaw
parents:
288
diff
changeset
|
664 db = bmp_cfg_db_open(); |
150
1997ecd9dcb1
[svn] Add ability to override defaults via .audacious/config until we can get a GUI.
nenolod
parents:
149
diff
changeset
|
665 |
319
1e642d74d68c
[svn] Do not abort if libmpc is not found, just disable musepack plugin.
chainsaw
parents:
288
diff
changeset
|
666 bmp_cfg_db_get_int(db, "console", "loop_length", &audcfg.loop_length); |
1e642d74d68c
[svn] Do not abort if libmpc is not found, just disable musepack plugin.
chainsaw
parents:
288
diff
changeset
|
667 bmp_cfg_db_get_bool(db, "console", "resample", &audcfg.resample); |
1e642d74d68c
[svn] Do not abort if libmpc is not found, just disable musepack plugin.
chainsaw
parents:
288
diff
changeset
|
668 bmp_cfg_db_get_int(db, "console", "resample_rate", &audcfg.resample_rate); |
150
1997ecd9dcb1
[svn] Add ability to override defaults via .audacious/config until we can get a GUI.
nenolod
parents:
149
diff
changeset
|
669 |
319
1e642d74d68c
[svn] Do not abort if libmpc is not found, just disable musepack plugin.
chainsaw
parents:
288
diff
changeset
|
670 bmp_cfg_db_close(db); |
100 | 671 } |
672 | |
109 | 673 extern "C" void console_aboutbox(void) |
674 { | |
675 xmms_show_message(_("About the Console Music Decoder"), | |
676 _("Console music decoder engine based on Game_Music_Emu 0.2.4.\n" | |
677 "Audacious implementation by: William Pitcock <nenolod@nenolod.net>"), | |
678 _("Ok"), | |
679 FALSE, NULL, NULL); | |
680 } |