Mercurial > audlegacy-plugins
annotate src/wavpack/libwavpack.cxx @ 233:7b7660c9f31c trunk
[svn] - rewrite to take advantage of already existant object-oriented framework
- add VFS support
author | nenolod |
---|---|
date | Tue, 07 Nov 2006 00:35:18 -0800 |
parents | 16e2c64d8b2b |
children | f0117679cd26 |
rev | line source |
---|---|
109 | 1 #include <assert.h> |
2 #include <string.h> | |
3 #include <stdio.h> | |
4 #include <stdlib.h> | |
5 #include <unistd.h> | |
6 #include <wavpack/wputils.h> | |
7 extern "C" { | |
8 #include <audacious/plugin.h> | |
111 | 9 #include <audacious/output.h> |
109 | 10 #include <audacious/configdb.h> |
11 #include <audacious/titlestring.h> | |
12 #include <audacious/util.h> | |
233
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
13 #include <audacious/vfs.h> |
109 | 14 } |
15 #include <glib.h> | |
16 #include <gtk/gtk.h> | |
17 #include <iconv.h> | |
18 #include <math.h> | |
19 #include "tags.h" | |
20 #ifndef M_LN10 | |
21 #define M_LN10 2.3025850929940456840179914546843642 | |
22 #endif | |
23 | |
112 | 24 #ifdef DEBUG |
25 # define DBG(format, args...) fprintf(stderr, format, ## args) | |
26 #else | |
27 # define DBG(format, args...) | |
28 #endif | |
29 | |
109 | 30 #define BUFFER_SIZE 256 // read buffer size, in samples |
31 | |
32 extern "C" InputPlugin * get_iplugin_info(void); | |
33 static void wv_load_config(); | |
34 static int wv_is_our_file(char *); | |
35 static void wv_play(char *); | |
36 static void wv_stop(void); | |
37 static void wv_pause(short); | |
38 static void wv_seek(int); | |
39 static int wv_get_time(void); | |
40 static void wv_get_song_info(char *, char **, int *); | |
41 static char *generate_title(const char *, WavpackContext *ctx); | |
42 static double isSeek; | |
43 static short paused; | |
44 static bool killDecodeThread; | |
45 static bool AudioError; | |
46 static GThread *thread_handle; | |
114 | 47 static TitleInput *wv_get_song_tuple(char *); |
109 | 48 |
49 // in ui.cpp | |
50 void wv_configure(); | |
51 void wv_about_box(void); | |
52 void wv_file_info_box(char *); | |
53 extern gboolean clipPreventionEnabled; | |
54 extern gboolean dynBitrateEnabled; | |
55 extern gboolean replaygainEnabled; | |
56 extern gboolean albumReplaygainEnabled; | |
57 extern gboolean openedAudio; | |
58 | |
59 InputPlugin mod = { | |
60 NULL, //handle | |
61 NULL, //filename | |
62 NULL, | |
63 wv_load_config, | |
64 wv_about_box, | |
65 wv_configure, | |
66 wv_is_our_file, | |
67 NULL, //no use | |
68 wv_play, | |
69 wv_stop, | |
70 wv_pause, | |
71 wv_seek, | |
72 NULL, //set eq | |
73 wv_get_time, | |
74 NULL, //get volume | |
75 NULL, //set volume | |
76 NULL, //cleanup | |
77 NULL, //obsolete | |
78 NULL, //add_vis | |
79 NULL, | |
80 NULL, | |
81 wv_get_song_info, | |
82 wv_file_info_box, //info box | |
83 NULL, //output | |
114 | 84 wv_get_song_tuple, |
109 | 85 }; |
86 | |
233
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
87 int32_t read_bytes (void *id, void *data, int32_t bcount) |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
88 { |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
89 return vfs_fread (data, 1, bcount, (VFSFile *) id); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
90 } |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
91 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
92 uint32_t get_pos (void *id) |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
93 { |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
94 return vfs_ftell ((VFSFile *) id); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
95 } |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
96 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
97 int set_pos_abs (void *id, uint32_t pos) |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
98 { |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
99 return vfs_fseek ((VFSFile *) id, pos, SEEK_SET); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
100 } |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
101 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
102 int set_pos_rel (void *id, int32_t delta, int mode) |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
103 { |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
104 return vfs_fseek ((VFSFile *) id, delta, mode); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
105 } |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
106 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
107 int push_back_byte (void *id, int c) |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
108 { |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
109 return vfs_ungetc (c, (VFSFile *) id); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
110 } |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
111 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
112 uint32_t get_length (void *id) |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
113 { |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
114 VFSFile *file = (VFSFile *) id; |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
115 uint32_t sz = 0; |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
116 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
117 if (file == NULL) |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
118 return 0; |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
119 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
120 vfs_fseek(file, 0, SEEK_END); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
121 sz = vfs_ftell(file); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
122 vfs_fseek(file, 0, SEEK_SET); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
123 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
124 return sz; |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
125 } |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
126 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
127 /* XXX streams?? */ |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
128 int can_seek (void *id) |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
129 { |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
130 return 1; |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
131 } |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
132 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
133 int32_t write_bytes (void *id, void *data, int32_t bcount) |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
134 { |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
135 return vfs_fwrite (data, 1, bcount, (VFSFile *) id); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
136 } |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
137 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
138 WavpackStreamReader reader = { |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
139 read_bytes, get_pos, set_pos_abs, set_pos_rel, push_back_byte, get_length, can_seek, |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
140 write_bytes |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
141 }; |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
142 |
109 | 143 class WavpackDecoder |
144 { | |
145 public: | |
146 InputPlugin *mod; | |
147 int32_t *input; | |
148 int16_t *output; | |
149 int sample_rate; | |
150 int num_channels; | |
151 WavpackContext *ctx; | |
152 char error_buff[4096]; // TODO: fixme! | |
233
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
153 VFSFile *wv_Input, *wvc_Input; |
109 | 154 |
155 WavpackDecoder(InputPlugin *mod) : mod(mod) | |
156 { | |
157 ctx = NULL; | |
158 input = NULL; | |
159 output = NULL; | |
160 } | |
161 | |
162 ~WavpackDecoder() | |
163 { | |
164 if (input != NULL) { | |
165 free(input); | |
166 input = NULL; | |
167 } | |
168 if (output != NULL) { | |
169 free(output); | |
170 output = NULL; | |
171 } | |
172 if (ctx != NULL) { | |
233
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
173 vfs_fclose(wv_Input); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
174 vfs_fclose(wvc_Input); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
175 g_free(ctx); |
109 | 176 ctx = NULL; |
177 } | |
178 } | |
179 | |
180 bool attach(const char *filename) | |
181 { | |
233
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
182 wv_Input = vfs_fopen(filename, "rb"); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
183 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
184 char *corrFilename = g_strconcat(filename, "c", NULL); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
185 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
186 wvc_Input = vfs_fopen(corrFilename, "rb"); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
187 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
188 g_free(corrFilename); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
189 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
190 ctx = WavpackOpenFileInputEx(&reader, wv_Input, wvc_Input, error_buff, OPEN_TAGS | OPEN_WVC, 0); |
109 | 191 |
192 if (ctx == NULL) { | |
193 return false; | |
194 } | |
195 | |
196 sample_rate = WavpackGetSampleRate(ctx); | |
197 num_channels = WavpackGetNumChannels(ctx); | |
198 input = (int32_t *)calloc(BUFFER_SIZE, num_channels * sizeof(int32_t)); | |
199 output = (int16_t *)calloc(BUFFER_SIZE, num_channels * sizeof(int16_t)); | |
200 mod->set_info(generate_title(filename, ctx), | |
201 (int) (WavpackGetNumSamples(ctx) / sample_rate) * 1000, | |
202 (int) WavpackGetAverageBitrate(ctx, num_channels), | |
203 (int) sample_rate, num_channels); | |
204 return true; | |
205 } | |
206 | |
207 bool open_audio() | |
208 { | |
112 | 209 return mod->output->open_audio(FMT_S16_NE, sample_rate, num_channels); |
109 | 210 } |
211 | |
212 void process_buffer(size_t num_samples) | |
213 { | |
214 for (int i = 0; i < num_samples * num_channels; i++) { | |
215 output[i] = input[i]; | |
216 } | |
112 | 217 produce_audio(mod->output->output_time(), FMT_S16_NE, |
111 | 218 num_channels, |
219 num_samples * num_channels * sizeof(int16_t), | |
220 output, | |
221 NULL); | |
109 | 222 } |
223 }; | |
224 | |
225 extern "C" InputPlugin * | |
226 get_iplugin_info(void) | |
227 { | |
228 mod.description = | |
229 g_strdup_printf(("Wavpack Decoder Plugin %s"), VERSION); | |
230 return &mod; | |
231 } | |
232 | |
233 static int | |
234 wv_is_our_file(char *filename) | |
235 { | |
236 char *ext; | |
237 | |
238 ext = strrchr(filename, '.'); | |
239 if (ext) { | |
240 if (!strcasecmp(ext, ".wv")) { | |
241 return TRUE; | |
242 } | |
243 } | |
244 return FALSE; | |
245 } | |
246 | |
247 void | |
248 load_tag(ape_tag *tag, WavpackContext *ctx) | |
249 { | |
250 memset(tag, 0, sizeof(ape_tag)); | |
251 WavpackGetTagItem(ctx, "Album", tag->album, sizeof(tag->album)); | |
252 WavpackGetTagItem(ctx, "Artist", tag->artist, sizeof(tag->artist)); | |
253 WavpackGetTagItem(ctx, "Comment", tag->comment, sizeof(tag->comment)); | |
254 WavpackGetTagItem(ctx, "Genre", tag->genre, sizeof(tag->genre)); | |
255 WavpackGetTagItem(ctx, "Title", tag->title, sizeof(tag->title)); | |
256 WavpackGetTagItem(ctx, "Track", tag->track, sizeof(tag->track)); | |
257 WavpackGetTagItem(ctx, "Year", tag->year, sizeof(tag->year)); | |
258 } | |
259 | |
260 static char * | |
261 convertUTF8toLocale(char *utf8) | |
262 { | |
263 // note - opens a new iconv descriptor for each call | |
264 // will have to find a way to reuse the descriptor if this turns | |
265 // out to be too slow | |
266 iconv_t idesc = iconv_open("", "UTF-8"); | |
267 if (idesc == (iconv_t) -1) { | |
268 perror("iconv_open failed"); | |
269 return g_strdup(utf8); | |
270 } | |
271 | |
272 size_t in_left = strlen(utf8); | |
273 size_t out_left = 2 * in_left + 1; | |
274 char *buf = (char *)g_malloc(out_left); | |
275 char *in = utf8; | |
276 char *out = buf; | |
277 | |
278 memset(buf, 0, out_left); | |
279 size_t err = iconv(idesc, &in, &in_left, &out, &out_left); | |
280 iconv_close(idesc); | |
281 return buf; | |
282 } | |
283 | |
284 static void * | |
285 end_thread() | |
286 { | |
287 return 0; | |
288 } | |
289 | |
290 static void * | |
291 DecodeThread(void *a) | |
292 { | |
293 ape_tag tag; | |
294 char *filename = (char *) a; | |
295 int bps_updateCounter = 0; | |
296 int bps; | |
297 int i; | |
298 WavpackDecoder d(&mod); | |
299 | |
300 if (!d.attach(filename)) { | |
301 printf("wavpack: Error opening file: \"%s\"\n", filename); | |
302 killDecodeThread = true; | |
303 return end_thread(); | |
304 } | |
305 bps = WavpackGetBytesPerSample(d.ctx) * d.num_channels; | |
306 DBG("reading %s at %d rate with %d channels\n", filename, d.sample_rate, d.num_channels); | |
307 | |
308 if (!d.open_audio()) { | |
309 DBG("error opening xmms audio channel\n"); | |
310 killDecodeThread = true; | |
311 AudioError = true; | |
312 openedAudio = false; | |
313 } | |
314 else { | |
315 DBG("opened xmms audio channel\n"); | |
316 openedAudio = true; | |
317 } | |
318 unsigned status; | |
319 char *display = generate_title(filename, d.ctx); | |
320 int length = (int) (1000 * WavpackGetNumSamples(d.ctx)); | |
321 | |
322 while (!killDecodeThread) { | |
323 if (isSeek != -1) { | |
324 DBG("seeking to position %d\n", isSeek); | |
325 WavpackSeekSample(d.ctx, isSeek * d.sample_rate); | |
326 isSeek = -1; | |
327 } | |
328 if (paused == 0 | |
329 && (mod.output->buffer_free() >= | |
330 (1152 * 2 * | |
331 (16 / 8)) << (mod.output->buffer_playing()? 1 : 0))) { | |
332 status = | |
333 WavpackUnpackSamples(d.ctx, d.input, BUFFER_SIZE); | |
334 if (status == (unsigned) (-1)) { | |
335 printf("wavpack: Error decoding file.\n"); | |
336 break; | |
337 } | |
338 else if (status == 0) { | |
339 killDecodeThread = true; | |
340 break; | |
341 } | |
342 else { | |
343 d.process_buffer(status); | |
344 } | |
345 } | |
346 else { | |
347 xmms_usleep(10000); | |
348 } | |
349 } | |
350 return end_thread(); | |
351 } | |
352 | |
353 static void | |
354 wv_play(char *filename) | |
355 { | |
356 paused = 0; | |
357 isSeek = -1; | |
358 killDecodeThread = false; | |
359 AudioError = false; | |
360 thread_handle = g_thread_create(DecodeThread, (void *) filename, TRUE, NULL); | |
361 return; | |
362 } | |
363 | |
114 | 364 static TitleInput * |
365 tuple_from_WavpackContext(const char *fn, WavpackContext *ctx) | |
366 { | |
367 ape_tag tag; | |
368 TitleInput *ti; | |
369 int sample_rate = WavpackGetSampleRate(ctx); | |
370 | |
371 ti = bmp_title_input_new(); | |
372 | |
130
16e2c64d8b2b
[svn] - provide a complete tuple (fixes albumart and such; path was missing.)
nenolod
parents:
115
diff
changeset
|
373 ti->file_name = g_path_get_basename(fn); |
16e2c64d8b2b
[svn] - provide a complete tuple (fixes albumart and such; path was missing.)
nenolod
parents:
115
diff
changeset
|
374 ti->file_path = g_path_get_dirname(fn); |
114 | 375 ti->file_ext = "wv"; |
376 | |
377 load_tag(&tag, ctx); | |
378 | |
115
2e77e3fdd3c1
[svn] - make sure the tuple data is copied, not referenced (oops)
nenolod
parents:
114
diff
changeset
|
379 ti->track_name = g_strdup(tag.title); |
2e77e3fdd3c1
[svn] - make sure the tuple data is copied, not referenced (oops)
nenolod
parents:
114
diff
changeset
|
380 ti->performer = g_strdup(tag.artist); |
2e77e3fdd3c1
[svn] - make sure the tuple data is copied, not referenced (oops)
nenolod
parents:
114
diff
changeset
|
381 ti->album_name = g_strdup(tag.album); |
2e77e3fdd3c1
[svn] - make sure the tuple data is copied, not referenced (oops)
nenolod
parents:
114
diff
changeset
|
382 ti->date = g_strdup(tag.year); |
114 | 383 ti->track_number = atoi(tag.track); |
384 if (ti->track_number < 0) | |
385 ti->track_number = 0; | |
386 ti->year = atoi(tag.year); | |
387 if (ti->year < 0) | |
388 ti->year = 0; | |
115
2e77e3fdd3c1
[svn] - make sure the tuple data is copied, not referenced (oops)
nenolod
parents:
114
diff
changeset
|
389 ti->genre = g_strdup(tag.genre); |
2e77e3fdd3c1
[svn] - make sure the tuple data is copied, not referenced (oops)
nenolod
parents:
114
diff
changeset
|
390 ti->comment = g_strdup(tag.comment); |
114 | 391 ti->length = (int)(WavpackGetNumSamples(ctx) / sample_rate) * 1000; |
392 | |
393 return ti; | |
394 } | |
395 | |
109 | 396 static char * |
397 generate_title(const char *fn, WavpackContext *ctx) | |
398 { | |
399 static char *displaytitle = NULL; | |
400 TitleInput *ti; | |
401 | |
114 | 402 ti = tuple_from_WavpackContext(fn, ctx); |
109 | 403 |
404 displaytitle = xmms_get_titlestring(xmms_get_gentitle_format(), ti); | |
115
2e77e3fdd3c1
[svn] - make sure the tuple data is copied, not referenced (oops)
nenolod
parents:
114
diff
changeset
|
405 if (!displaytitle || *displaytitle == '\0') |
2e77e3fdd3c1
[svn] - make sure the tuple data is copied, not referenced (oops)
nenolod
parents:
114
diff
changeset
|
406 displaytitle = g_strdup(fn); |
114 | 407 |
408 bmp_title_input_free(ti); | |
109 | 409 |
410 return displaytitle; | |
411 } | |
412 | |
114 | 413 static TitleInput * |
414 wv_get_song_tuple(char *filename) | |
415 { | |
416 TitleInput *ti; | |
233
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
417 WavpackDecoder d(&mod); |
114 | 418 |
233
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
419 if (!d.attach(filename)) { |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
420 printf("wavpack: Error opening file: \"%s\"\n", filename); |
114 | 421 return NULL; |
422 } | |
423 | |
233
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
424 ti = tuple_from_WavpackContext(filename, d.ctx); |
114 | 425 |
426 return ti; | |
427 } | |
428 | |
109 | 429 static void |
430 wv_get_song_info(char *filename, char **title, int *length) | |
431 { | |
432 assert(filename != NULL); | |
233
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
433 WavpackDecoder d(&mod); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
434 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
435 if (!d.attach(filename)) { |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
436 printf("wavpack: Error opening file: \"%s\"\n", filename); |
109 | 437 return; |
438 } | |
233
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
439 |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
440 int sample_rate = WavpackGetSampleRate(d.ctx); |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
441 int num_channels = WavpackGetNumChannels(d.ctx); |
109 | 442 DBG("reading %s at %d rate with %d channels\n", filename, sample_rate, num_channels); |
443 | |
233
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
444 *length = (int)(WavpackGetNumSamples(d.ctx) / sample_rate) * 1000, |
7b7660c9f31c
[svn] - rewrite to take advantage of already existant object-oriented framework
nenolod
parents:
130
diff
changeset
|
445 *title = generate_title(filename, d.ctx); |
109 | 446 DBG("title for %s = %s\n", filename, *title); |
447 } | |
448 | |
449 static int | |
450 wv_get_time(void) | |
451 { | |
452 if (!mod.output) | |
453 return -1; | |
454 if (AudioError) | |
455 return -2; | |
456 if (killDecodeThread && !mod.output->buffer_playing()) | |
457 return -1; | |
458 return mod.output->output_time(); | |
459 } | |
460 | |
461 | |
462 static void | |
463 wv_seek(int sec) | |
464 { | |
465 isSeek = sec; | |
466 mod.output->flush((int) (1000 * isSeek)); | |
467 } | |
468 | |
469 static void | |
470 wv_pause(short pause) | |
471 { | |
472 mod.output->pause(paused = pause); | |
473 } | |
474 | |
475 static void | |
476 wv_stop(void) | |
477 { | |
478 killDecodeThread = true; | |
479 if (thread_handle != 0) { | |
480 g_thread_join(thread_handle); | |
481 if (openedAudio) { | |
482 mod.output->buffer_free(); | |
483 mod.output->close_audio(); | |
484 } | |
485 openedAudio = false; | |
486 if (AudioError) | |
487 printf("Could not open Audio\n"); | |
488 } | |
489 | |
490 } | |
491 | |
492 static void | |
493 wv_load_config() | |
494 { | |
495 ConfigDb *cfg; | |
496 | |
497 cfg = bmp_cfg_db_open(); | |
498 | |
499 bmp_cfg_db_get_bool(cfg, "wavpack", "clip_prevention", | |
500 &clipPreventionEnabled); | |
501 bmp_cfg_db_get_bool(cfg, "wavpack", "album_replaygain", | |
502 &albumReplaygainEnabled); | |
503 bmp_cfg_db_get_bool(cfg, "wavpack", "dyn_bitrate", &dynBitrateEnabled); | |
504 bmp_cfg_db_get_bool(cfg, "wavpack", "replaygain", &replaygainEnabled); | |
505 bmp_cfg_db_close(cfg); | |
506 | |
507 openedAudio = false; | |
508 } |