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