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