]>
Commit | Line | Data |
---|---|---|
a43fd45f SS |
1 | --- mpd-0.12.1/src/inputPlugins/_flac_common.h.orig 2007-01-01 20:16:07.000000000 +0000 |
2 | +++ mpd-0.12.1/src/inputPlugins/_flac_common.h 2007-01-01 21:10:31.000000000 +0000 | |
3 | @@ -30,7 +30,114 @@ | |
4 | #include "../inputStream.h" | |
5 | #include "../outputBuffer.h" | |
6 | #include "../decode.h" | |
7 | -#include <FLAC/seekable_stream_decoder.h> | |
8 | +#include <FLAC/export.h> | |
9 | +#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 | |
10 | +# include <FLAC/seekable_stream_decoder.h> | |
11 | +# define flac_decoder FLAC__SeekableStreamDecoder | |
12 | +# define flac_new(x) FLAC__seekable_stream_decoder_new(x) | |
13 | + | |
14 | +# define flac_ogg_init(a,b,c,d,e,f,g,h,i,j) (0) | |
15 | + | |
16 | +# define flac_get_decode_position(x,y) \ | |
17 | + FLAC__seekable_stream_decoder_get_decode_position(x,y) | |
18 | +# define flac_get_state(x) FLAC__seekable_stream_decoder_get_state(x) | |
19 | +# define flac_process_single(x) FLAC__seekable_stream_decoder_process_single(x) | |
20 | +# define flac_process_metadata(x) \ | |
21 | + FLAC__seekable_stream_decoder_process_until_end_of_metadata(x) | |
22 | +# define flac_seek_absolute(x,y) \ | |
23 | + FLAC__seekable_stream_decoder_seek_absolute(x,y) | |
24 | +# define flac_finish(x) FLAC__seekable_stream_decoder_finish(x) | |
25 | +# define flac_delete(x) FLAC__seekable_stream_decoder_delete(x) | |
26 | + | |
27 | +# define flac_decoder_eof FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM | |
28 | + | |
29 | +# define flac_read_status FLAC__SeekableStreamDecoderReadStatus | |
30 | +# define flac_read_status_continue \ | |
31 | + FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK | |
32 | +# define flac_read_status_eof FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK | |
33 | +# define flac_read_status_abort \ | |
34 | + FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR | |
35 | + | |
36 | +# define flac_seek_status FLAC__SeekableStreamDecoderSeekStatus | |
37 | +# define flac_seek_status_ok FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK | |
38 | +# define flac_seek_status_error FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR | |
39 | + | |
40 | +# define flac_tell_status FLAC__SeekableStreamDecoderTellStatus | |
41 | +# define flac_tell_status_ok FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK | |
42 | +# define flac_tell_status_error \ | |
43 | + FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR | |
44 | +# define flac_tell_status_unsupported \ | |
45 | + FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR | |
46 | + | |
47 | +# define flac_length_status FLAC__SeekableStreamDecoderLengthStatus | |
48 | +# define flac_length_status_ok FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK | |
49 | +# define flac_length_status_error \ | |
50 | + FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR | |
51 | +# define flac_length_status_unsupported \ | |
52 | + FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR | |
53 | + | |
54 | +# ifdef HAVE_OGGFLAC | |
55 | +# include <OggFLAC/seekable_stream_decoder.h> | |
56 | +# endif | |
57 | +#else /* FLAC_API_VERSION_CURRENT >= 7 */ | |
58 | + | |
59 | + /* OggFLAC support is handled by our flac_plugin already, and | |
60 | + * thus we *can* always have it if libFLAC was compiled with it */ | |
61 | +# ifndef HAVE_OGGFLAC | |
62 | +# define HAVE_OGGFLAC 1 | |
63 | +# endif | |
64 | +# include "_ogg_common.h" | |
65 | +# undef HAVE_OGGFLAC /* we don't need this defined anymore */ | |
66 | + | |
67 | +# include <FLAC/stream_decoder.h> | |
68 | +# define flac_decoder FLAC__StreamDecoder | |
69 | +# define flac_new(x) FLAC__stream_decoder_new(x) | |
70 | + | |
71 | +# define flac_init(a,b,c,d,e,f,g,h,i,j) \ | |
72 | + (FLAC__stream_decoder_init_stream(a,b,c,d,e,f,g,h,i,j) \ | |
73 | + == FLAC__STREAM_DECODER_INIT_STATUS_OK) | |
74 | +# define flac_ogg_init(a,b,c,d,e,f,g,h,i,j) \ | |
75 | + (FLAC__stream_decoder_init_ogg_stream(a,b,c,d,e,f,g,h,i,j) \ | |
76 | + == FLAC__STREAM_DECODER_INIT_STATUS_OK) | |
77 | + | |
78 | +# define flac_get_decode_position(x,y) \ | |
79 | + FLAC__stream_decoder_get_decode_position(x,y) | |
80 | +# define flac_get_state(x) FLAC__stream_decoder_get_state(x) | |
81 | +# define flac_process_single(x) FLAC__stream_decoder_process_single(x) | |
82 | +# define flac_process_metadata(x) \ | |
83 | + FLAC__stream_decoder_process_until_end_of_metadata(x) | |
84 | +# define flac_seek_absolute(x,y) FLAC__stream_decoder_seek_absolute(x,y) | |
85 | +# define flac_finish(x) FLAC__stream_decoder_finish(x) | |
86 | +# define flac_delete(x) FLAC__stream_decoder_delete(x) | |
87 | + | |
88 | +# define flac_decoder_eof FLAC__STREAM_DECODER_END_OF_STREAM | |
89 | + | |
90 | +# define flac_read_status FLAC__StreamDecoderReadStatus | |
91 | +# define flac_read_status_continue \ | |
92 | + FLAC__STREAM_DECODER_READ_STATUS_CONTINUE | |
93 | +# define flac_read_status_eof FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM | |
94 | +# define flac_read_status_abort FLAC__STREAM_DECODER_READ_STATUS_ABORT | |
95 | + | |
96 | +# define flac_seek_status FLAC__StreamDecoderSeekStatus | |
97 | +# define flac_seek_status_ok FLAC__STREAM_DECODER_SEEK_STATUS_OK | |
98 | +# define flac_seek_status_error FLAC__STREAM_DECODER_SEEK_STATUS_ERROR | |
99 | +# define flac_seek_status_unsupported \ | |
100 | + FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED | |
101 | + | |
102 | +# define flac_tell_status FLAC__StreamDecoderTellStatus | |
103 | +# define flac_tell_status_ok FLAC__STREAM_DECODER_TELL_STATUS_OK | |
104 | +# define flac_tell_status_error FLAC__STREAM_DECODER_TELL_STATUS_ERROR | |
105 | +# define flac_tell_status_unsupported \ | |
106 | + FLAC__STREAM_DECODER_TELL_STATUS_UNSUPPORTED | |
107 | + | |
108 | +# define flac_length_status FLAC__StreamDecoderLengthStatus | |
109 | +# define flac_length_status_ok FLAC__STREAM_DECODER_LENGTH_STATUS_OK | |
110 | +# define flac_length_status_error FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR | |
111 | +# define flac_length_status_unsupported \ | |
112 | + FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED | |
113 | + | |
114 | +#endif /* FLAC_API_VERSION_CURRENT >= 7 */ | |
115 | + | |
116 | #include <FLAC/metadata.h> | |
117 | ||
118 | #define FLAC_CHUNK_SIZE 4080 | |
119 | --- mpd-0.12.1/src/inputPlugins/flac_plugin.c.orig 2007-01-01 20:17:35.000000000 +0000 | |
120 | +++ mpd-0.12.1/src/inputPlugins/flac_plugin.c 2007-01-01 21:08:32.000000000 +0000 | |
121 | @@ -16,12 +16,10 @@ | |
122 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
123 | */ | |
124 | ||
125 | -#include "../inputPlugin.h" | |
126 | +#include "_flac_common.h" | |
127 | ||
128 | #ifdef HAVE_FLAC | |
129 | ||
130 | -#include "_flac_common.h" | |
131 | - | |
132 | #include "../utils.h" | |
133 | #include "../log.h" | |
134 | #include "../pcm_utils.h" | |
135 | @@ -33,166 +31,14 @@ | |
136 | #include <stdio.h> | |
137 | #include <string.h> | |
138 | #include <unistd.h> | |
139 | -#include <FLAC/seekable_stream_decoder.h> | |
140 | -#include <FLAC/metadata.h> | |
141 | +#include <assert.h> | |
142 | ||
143 | -/* this code is based on flac123, from flac-tools */ | |
144 | +/* this code was based on flac123, from flac-tools */ | |
145 | ||
146 | -static void flacError(const FLAC__SeekableStreamDecoder *, | |
147 | - FLAC__StreamDecoderErrorStatus, void *); | |
148 | -static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state); | |
149 | -static void flacMetadata(const FLAC__SeekableStreamDecoder *, | |
150 | - const FLAC__StreamMetadata *, void *); | |
151 | -static FLAC__StreamDecoderWriteStatus flacWrite(const | |
152 | - FLAC__SeekableStreamDecoder *, | |
153 | - const FLAC__Frame *, | |
154 | - const FLAC__int32 * const buf[], | |
155 | - void *); | |
156 | -static FLAC__SeekableStreamDecoderReadStatus flacRead(const | |
157 | - FLAC__SeekableStreamDecoder | |
158 | - *, FLAC__byte buf[], | |
159 | - unsigned *, void *); | |
160 | -static FLAC__SeekableStreamDecoderSeekStatus flacSeek(const | |
161 | - FLAC__SeekableStreamDecoder | |
162 | - *, FLAC__uint64, void *); | |
163 | -static FLAC__SeekableStreamDecoderTellStatus flacTell(const | |
164 | - FLAC__SeekableStreamDecoder | |
165 | - *, FLAC__uint64 *, | |
166 | - void *); | |
167 | -static FLAC__SeekableStreamDecoderLengthStatus flacLength(const | |
168 | - FLAC__SeekableStreamDecoder | |
169 | - *, FLAC__uint64 *, | |
170 | - void *); | |
171 | -static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder *, void *); | |
172 | - | |
173 | -static int flac_decode(OutputBuffer * cb, DecoderControl * dc, | |
174 | - InputStream * inStream) | |
175 | -{ | |
176 | - FLAC__SeekableStreamDecoder *flacDec = NULL; | |
177 | - FlacData data; | |
178 | - int status = 1; | |
179 | - int ret = 0; | |
180 | - | |
181 | - init_FlacData(&data, cb, dc, inStream); | |
182 | - | |
183 | - if (!(flacDec = FLAC__seekable_stream_decoder_new())) { | |
184 | - ret = -1; | |
185 | - goto fail; | |
186 | - } | |
187 | - /*status&=FLAC__file_decoder_set_md5_checking(flacDec,1); */ | |
188 | - status &= FLAC__seekable_stream_decoder_set_read_callback(flacDec, | |
189 | - flacRead); | |
190 | - status &= FLAC__seekable_stream_decoder_set_seek_callback(flacDec, | |
191 | - flacSeek); | |
192 | - status &= FLAC__seekable_stream_decoder_set_tell_callback(flacDec, | |
193 | - flacTell); | |
194 | - status &= FLAC__seekable_stream_decoder_set_length_callback(flacDec, | |
195 | - flacLength); | |
196 | - status &= | |
197 | - FLAC__seekable_stream_decoder_set_eof_callback(flacDec, flacEOF); | |
198 | - status &= | |
199 | - FLAC__seekable_stream_decoder_set_write_callback(flacDec, | |
200 | - flacWrite); | |
201 | - status &= | |
202 | - FLAC__seekable_stream_decoder_set_metadata_callback(flacDec, | |
203 | - flacMetadata); | |
204 | - status &= | |
205 | - FLAC__seekable_stream_decoder_set_metadata_respond(flacDec, | |
206 | - FLAC__METADATA_TYPE_VORBIS_COMMENT); | |
207 | - status &= | |
208 | - FLAC__seekable_stream_decoder_set_error_callback(flacDec, | |
209 | - flacError); | |
210 | - status &= | |
211 | - FLAC__seekable_stream_decoder_set_client_data(flacDec, | |
212 | - (void *)&data); | |
213 | - if (!status) { | |
214 | - ERROR("flac problem before init()\n"); | |
215 | - flacPrintErroredState(FLAC__seekable_stream_decoder_get_state | |
216 | - (flacDec)); | |
217 | - ret = -1; | |
218 | - goto fail; | |
219 | - } | |
220 | - | |
221 | - if (FLAC__seekable_stream_decoder_init(flacDec) != | |
222 | - FLAC__SEEKABLE_STREAM_DECODER_OK) { | |
223 | - ERROR("flac problem doing init()\n"); | |
224 | - flacPrintErroredState(FLAC__seekable_stream_decoder_get_state | |
225 | - (flacDec)); | |
226 | - ret = -1; | |
227 | - goto fail; | |
228 | - } | |
229 | - | |
230 | - if (!FLAC__seekable_stream_decoder_process_until_end_of_metadata | |
231 | - (flacDec)) { | |
232 | - ERROR("flac problem reading metadata\n"); | |
233 | - flacPrintErroredState(FLAC__seekable_stream_decoder_get_state | |
234 | - (flacDec)); | |
235 | - ret = -1; | |
236 | - goto fail; | |
237 | - } | |
238 | - | |
239 | - dc->state = DECODE_STATE_DECODE; | |
240 | - | |
241 | - while (1) { | |
242 | - FLAC__seekable_stream_decoder_process_single(flacDec); | |
243 | - if (FLAC__seekable_stream_decoder_get_state(flacDec) != | |
244 | - FLAC__SEEKABLE_STREAM_DECODER_OK) { | |
245 | - break; | |
246 | - } | |
247 | - if (dc->seek) { | |
248 | - FLAC__uint64 sampleToSeek = dc->seekWhere * | |
249 | - dc->audioFormat.sampleRate + 0.5; | |
250 | - if (FLAC__seekable_stream_decoder_seek_absolute(flacDec, | |
251 | - sampleToSeek)) | |
252 | - { | |
253 | - clearOutputBuffer(cb); | |
254 | - data.time = ((float)sampleToSeek) / | |
255 | - dc->audioFormat.sampleRate; | |
256 | - data.position = 0; | |
257 | - } else | |
258 | - dc->seekError = 1; | |
259 | - dc->seek = 0; | |
260 | - } | |
261 | - } | |
262 | - /* I don't think we need this bit here! -shank */ | |
263 | - /*FLAC__file_decoder_process_until_end_of_file(flacDec); */ | |
264 | - if (!dc->stop) { | |
265 | - flacPrintErroredState(FLAC__seekable_stream_decoder_get_state | |
266 | - (flacDec)); | |
267 | - FLAC__seekable_stream_decoder_finish(flacDec); | |
268 | - } | |
269 | - /* send last little bit */ | |
270 | - if (data.chunk_length > 0 && !dc->stop) { | |
271 | - flacSendChunk(&data); | |
272 | - flushOutputBuffer(data.cb); | |
273 | - } | |
274 | - | |
275 | - /*if(dc->seek) { | |
276 | - dc->seekError = 1; | |
277 | - dc->seek = 0; | |
278 | - } */ | |
279 | - | |
280 | - dc->state = DECODE_STATE_STOP; | |
281 | - dc->stop = 0; | |
282 | - | |
283 | -fail: | |
284 | - if (data.replayGainInfo) | |
285 | - freeReplayGainInfo(data.replayGainInfo); | |
286 | - | |
287 | - if (flacDec) | |
288 | - FLAC__seekable_stream_decoder_delete(flacDec); | |
289 | - | |
290 | - closeInputStream(inStream); | |
291 | - | |
292 | - return ret; | |
293 | -} | |
294 | - | |
295 | -static FLAC__SeekableStreamDecoderReadStatus flacRead(const | |
296 | - FLAC__SeekableStreamDecoder | |
297 | - * flacDec, | |
298 | - FLAC__byte buf[], | |
299 | - unsigned *bytes, | |
300 | - void *fdata) | |
301 | +static flac_read_status flacRead(const flac_decoder * flacDec, | |
302 | + FLAC__byte buf[], | |
303 | + unsigned *bytes, | |
304 | + void *fdata) | |
305 | { | |
306 | FlacData *data = (FlacData *) fdata; | |
307 | size_t r; | |
308 | @@ -207,55 +53,51 @@ | |
309 | } | |
310 | *bytes = r; | |
311 | ||
312 | - if (*bytes == 0 && !inputStreamAtEOF(data->inStream) && !data->dc->stop) | |
313 | - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; | |
314 | - | |
315 | - return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; | |
316 | + if (r == 0 && !data->dc->stop) { | |
317 | + if (inputStreamAtEOF(data->inStream)) | |
318 | + return flac_read_status_eof; | |
319 | + else | |
320 | + return flac_read_status_abort; | |
321 | + } | |
322 | + return flac_read_status_continue; | |
323 | } | |
324 | ||
325 | -static FLAC__SeekableStreamDecoderSeekStatus flacSeek(const | |
326 | - FLAC__SeekableStreamDecoder | |
327 | - * flacDec, | |
328 | - FLAC__uint64 offset, | |
329 | - void *fdata) | |
330 | +static flac_seek_status flacSeek(const flac_decoder * flacDec, | |
331 | + FLAC__uint64 offset, | |
332 | + void *fdata) | |
333 | { | |
334 | FlacData *data = (FlacData *) fdata; | |
335 | ||
336 | if (seekInputStream(data->inStream, offset, SEEK_SET) < 0) { | |
337 | - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; | |
338 | + return flac_seek_status_error; | |
339 | } | |
340 | ||
341 | - return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; | |
342 | + return flac_tell_status_ok; | |
343 | } | |
344 | ||
345 | -static FLAC__SeekableStreamDecoderTellStatus flacTell(const | |
346 | - FLAC__SeekableStreamDecoder | |
347 | - * flacDec, | |
348 | - FLAC__uint64 * offset, | |
349 | - void *fdata) | |
350 | +static flac_tell_status flacTell(const flac_decoder * flacDec, | |
351 | + FLAC__uint64 * offset, | |
352 | + void *fdata) | |
353 | { | |
354 | FlacData *data = (FlacData *) fdata; | |
355 | ||
356 | *offset = (long)(data->inStream->offset); | |
357 | ||
358 | - return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; | |
359 | + return flac_tell_status_ok; | |
360 | } | |
361 | ||
362 | -static FLAC__SeekableStreamDecoderLengthStatus flacLength(const | |
363 | - FLAC__SeekableStreamDecoder | |
364 | - * flacDec, | |
365 | - FLAC__uint64 * length, | |
366 | - void *fdata) | |
367 | +static flac_length_status flacLength(const flac_decoder * flacDec, | |
368 | + FLAC__uint64 * length, | |
369 | + void *fdata) | |
370 | { | |
371 | FlacData *data = (FlacData *) fdata; | |
372 | ||
373 | *length = (size_t) (data->inStream->size); | |
374 | ||
375 | - return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; | |
376 | + return flac_length_status_ok; | |
377 | } | |
378 | ||
379 | -static FLAC__bool flacEOF(const FLAC__SeekableStreamDecoder * flacDec, | |
380 | - void *fdata) | |
381 | +static FLAC__bool flacEOF(const flac_decoder * flacDec, void *fdata) | |
382 | { | |
383 | FlacData *data = (FlacData *) fdata; | |
384 | ||
385 | @@ -264,52 +106,112 @@ | |
386 | return false; | |
387 | } | |
388 | ||
389 | -static void flacError(const FLAC__SeekableStreamDecoder * dec, | |
390 | +static void flacError(const flac_decoder *dec, | |
391 | FLAC__StreamDecoderErrorStatus status, void *fdata) | |
392 | { | |
393 | flac_error_common_cb("flac", status, (FlacData *) fdata); | |
394 | } | |
395 | ||
396 | +#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 | |
397 | static void flacPrintErroredState(FLAC__SeekableStreamDecoderState state) | |
398 | { | |
399 | + const char *str = ""; /* "" to silence compiler warning */ | |
400 | switch (state) { | |
401 | + case FLAC__SEEKABLE_STREAM_DECODER_OK: | |
402 | + case FLAC__SEEKABLE_STREAM_DECODER_SEEKING: | |
403 | + case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM: | |
404 | + return; | |
405 | case FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR: | |
406 | - ERROR("flac allocation error\n"); | |
407 | + str = "allocation error"; | |
408 | break; | |
409 | case FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR: | |
410 | - ERROR("flac read error\n"); | |
411 | + str = "read error"; | |
412 | break; | |
413 | case FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR: | |
414 | - ERROR("flac seek error\n"); | |
415 | + str = "seek error"; | |
416 | break; | |
417 | case FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR: | |
418 | - ERROR("flac seekable stream error\n"); | |
419 | + str = "seekable stream error"; | |
420 | break; | |
421 | case FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED: | |
422 | - ERROR("flac decoder already initialized\n"); | |
423 | + str = "decoder already initialized"; | |
424 | break; | |
425 | case FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK: | |
426 | - ERROR("invalid flac callback\n"); | |
427 | + str = "invalid callback"; | |
428 | break; | |
429 | case FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED: | |
430 | - ERROR("flac decoder uninitialized\n"); | |
431 | + str = "decoder uninitialized"; | |
432 | + } | |
433 | + ERROR("flac %s\n", str); | |
434 | +} | |
435 | + | |
436 | +static int flac_init(FLAC__SeekableStreamDecoder *dec, | |
437 | + FLAC__SeekableStreamDecoderReadCallback read_cb, | |
438 | + FLAC__SeekableStreamDecoderSeekCallback seek_cb, | |
439 | + FLAC__SeekableStreamDecoderTellCallback tell_cb, | |
440 | + FLAC__SeekableStreamDecoderLengthCallback length_cb, | |
441 | + FLAC__SeekableStreamDecoderEofCallback eof_cb, | |
442 | + FLAC__SeekableStreamDecoderWriteCallback write_cb, | |
443 | + FLAC__SeekableStreamDecoderMetadataCallback metadata_cb, | |
444 | + FLAC__SeekableStreamDecoderErrorCallback error_cb, | |
445 | + void *data) | |
446 | +{ | |
447 | + int s = 1; | |
448 | + s &= FLAC__seekable_stream_decoder_set_read_callback(dec, read_cb); | |
449 | + s &= FLAC__seekable_stream_decoder_set_seek_callback(dec, seek_cb); | |
450 | + s &= FLAC__seekable_stream_decoder_set_tell_callback(dec, tell_cb); | |
451 | + s &= FLAC__seekable_stream_decoder_set_length_callback(dec, length_cb); | |
452 | + s &= FLAC__seekable_stream_decoder_set_eof_callback(dec, eof_cb); | |
453 | + s &= FLAC__seekable_stream_decoder_set_write_callback(dec, write_cb); | |
454 | + s &= FLAC__seekable_stream_decoder_set_metadata_callback(dec, | |
455 | + metadata_cb); | |
456 | + s &= FLAC__seekable_stream_decoder_set_metadata_respond(dec, | |
457 | + FLAC__METADATA_TYPE_VORBIS_COMMENT); | |
458 | + s &= FLAC__seekable_stream_decoder_set_error_callback(dec, error_cb); | |
459 | + s &= FLAC__seekable_stream_decoder_set_client_data(dec, data); | |
460 | + if (!s || (FLAC__seekable_stream_decoder_init(dec) != | |
461 | + FLAC__SEEKABLE_STREAM_DECODER_OK)) | |
462 | + return 0; | |
463 | + return 1; | |
464 | +} | |
465 | +#else /* FLAC_API_VERSION_CURRENT >= 7 */ | |
466 | +static void flacPrintErroredState(FLAC__StreamDecoderState state) | |
467 | +{ | |
468 | + const char *str = ""; /* "" to silence compiler warning */ | |
469 | + switch (state) { | |
470 | + case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA: | |
471 | + case FLAC__STREAM_DECODER_READ_METADATA: | |
472 | + case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: | |
473 | + case FLAC__STREAM_DECODER_READ_FRAME: | |
474 | + case FLAC__STREAM_DECODER_END_OF_STREAM: | |
475 | + return; | |
476 | + case FLAC__STREAM_DECODER_OGG_ERROR: | |
477 | + str = "error in the Ogg layer"; | |
478 | break; | |
479 | - case FLAC__SEEKABLE_STREAM_DECODER_OK: | |
480 | - case FLAC__SEEKABLE_STREAM_DECODER_SEEKING: | |
481 | - case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM: | |
482 | + case FLAC__STREAM_DECODER_SEEK_ERROR: | |
483 | + str = "seek error"; | |
484 | + break; | |
485 | + case FLAC__STREAM_DECODER_ABORTED: | |
486 | + str = "decoder aborted by read"; | |
487 | + break; | |
488 | + case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR: | |
489 | + str = "allocation error"; | |
490 | break; | |
491 | + case FLAC__STREAM_DECODER_UNINITIALIZED: | |
492 | + str = "decoder uninitialized"; | |
493 | } | |
494 | + ERROR("flac %s\n", str); | |
495 | } | |
496 | +#endif /* FLAC_API_VERSION_CURRENT >= 7 */ | |
497 | ||
498 | -static void flacMetadata(const FLAC__SeekableStreamDecoder * dec, | |
499 | +static void flacMetadata(const flac_decoder * dec, | |
500 | const FLAC__StreamMetadata * block, void *vdata) | |
501 | { | |
502 | flac_metadata_common_cb(block, (FlacData *) vdata); | |
503 | } | |
504 | ||
505 | -static FLAC__StreamDecoderWriteStatus flacWrite(const | |
506 | - FLAC__SeekableStreamDecoder * | |
507 | - dec, const FLAC__Frame * frame, | |
508 | +static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec, | |
509 | + const FLAC__Frame * frame, | |
510 | const FLAC__int32 * const buf[], | |
511 | void *vdata) | |
512 | { | |
513 | @@ -325,7 +227,7 @@ | |
514 | timeChange = ((float)samples) / frame->header.sample_rate; | |
515 | data->time += timeChange; | |
516 | ||
517 | - FLAC__seekable_stream_decoder_get_decode_position(dec, &newPosition); | |
518 | + flac_get_decode_position(dec, &newPosition); | |
519 | if (data->position) { | |
520 | data->bitRate = | |
521 | ((newPosition - data->position) * 8.0 / timeChange) | |
522 | @@ -438,12 +340,174 @@ | |
523 | return ret; | |
524 | } | |
525 | ||
526 | +static int flac_decode_internal(OutputBuffer * cb, DecoderControl * dc, | |
527 | + InputStream * inStream, int is_ogg) | |
528 | +{ | |
529 | + flac_decoder *flacDec; | |
530 | + FlacData data; | |
531 | + const char *err = NULL; | |
532 | + | |
533 | + if (!(flacDec = flac_new())) | |
534 | + return -1; | |
535 | + init_FlacData(&data, cb, dc, inStream); | |
536 | + if (is_ogg) { | |
537 | + if (!flac_ogg_init(flacDec, flacRead, flacSeek, flacTell, | |
538 | + flacLength, flacEOF, flacWrite, flacMetadata, | |
539 | + flacError, (void *)&data)) { | |
540 | + err = "doing Ogg init()"; | |
541 | + goto fail; | |
542 | + } | |
543 | + } else { | |
544 | + if (!flac_init(flacDec, flacRead, flacSeek, flacTell, | |
545 | + flacLength, flacEOF, flacWrite, flacMetadata, | |
546 | + flacError, (void *)&data)) { | |
547 | + err = "doing init()"; | |
548 | + goto fail; | |
549 | + } | |
550 | + if (!flac_process_metadata(flacDec)) { | |
551 | + err = "problem reading metadata"; | |
552 | + goto fail; | |
553 | + } | |
554 | + } | |
555 | + | |
556 | + dc->state = DECODE_STATE_DECODE; | |
557 | + | |
558 | + while (1) { | |
559 | + if (!flac_process_single(flacDec)) | |
560 | + break; | |
561 | + if (flac_get_state(flacDec) == flac_decoder_eof) | |
562 | + break; | |
563 | + if (dc->seek) { | |
564 | + FLAC__uint64 sampleToSeek = dc->seekWhere * | |
565 | + dc->audioFormat.sampleRate + 0.5; | |
566 | + if (flac_seek_absolute(flacDec, sampleToSeek)) { | |
567 | + clearOutputBuffer(cb); | |
568 | + data.time = ((float)sampleToSeek) / | |
569 | + dc->audioFormat.sampleRate; | |
570 | + data.position = 0; | |
571 | + } else | |
572 | + dc->seekError = 1; | |
573 | + dc->seek = 0; | |
574 | + } | |
575 | + } | |
576 | + if (!dc->stop) { | |
577 | + flacPrintErroredState(flac_get_state(flacDec)); | |
578 | + flac_finish(flacDec); | |
579 | + } | |
580 | + /* send last little bit */ | |
581 | + if (data.chunk_length > 0 && !dc->stop) { | |
582 | + flacSendChunk(&data); | |
583 | + flushOutputBuffer(data.cb); | |
584 | + } | |
585 | + | |
586 | + /*if(dc->seek) { | |
587 | + dc->seekError = 1; | |
588 | + dc->seek = 0; | |
589 | + } */ | |
590 | + | |
591 | + dc->state = DECODE_STATE_STOP; | |
592 | + dc->stop = 0; | |
593 | + | |
594 | +fail: | |
595 | + if (data.replayGainInfo) | |
596 | + freeReplayGainInfo(data.replayGainInfo); | |
597 | + | |
598 | + if (flacDec) | |
599 | + flac_delete(flacDec); | |
600 | + | |
601 | + closeInputStream(inStream); | |
602 | + | |
603 | + if (err) { | |
604 | + ERROR("flac %s\n", err); | |
605 | + return -1; | |
606 | + } | |
607 | + return 0; | |
608 | +} | |
609 | + | |
610 | +static int flac_decode(OutputBuffer * cb, DecoderControl * dc, | |
611 | + InputStream * inStream) | |
612 | +{ | |
613 | + return flac_decode_internal(cb, dc, inStream, 0); | |
614 | +} | |
615 | + | |
616 | +#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7 | |
617 | +# define flac_plugin_init NULL | |
618 | +#else /* FLAC_API_VERSION_CURRENT >= 7 */ | |
619 | +/* some of this stuff is duplicated from oggflac_plugin.c */ | |
620 | +extern InputPlugin oggflacPlugin; | |
621 | + | |
622 | +static MpdTag *oggflac_tag_dup(char *file) | |
623 | +{ | |
624 | + MpdTag *ret = NULL; | |
625 | + FLAC__Metadata_Iterator *it; | |
626 | + FLAC__StreamMetadata *block; | |
627 | + FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new(); | |
628 | + | |
629 | + if (!(FLAC__metadata_chain_read_ogg(chain, file))) | |
630 | + goto out; | |
631 | + it = FLAC__metadata_iterator_new(); | |
632 | + FLAC__metadata_iterator_init(it, chain); | |
633 | + do { | |
634 | + if (!(block = FLAC__metadata_iterator_get_block(it))) | |
635 | + break; | |
636 | + if (block->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) { | |
637 | + ret = copyVorbisCommentBlockToMpdTag(block, ret); | |
638 | + } else if (block->type == FLAC__METADATA_TYPE_STREAMINFO) { | |
639 | + if (!ret) | |
640 | + ret = newMpdTag(); | |
641 | + ret->time = ((float)block->data.stream_info. | |
642 | + total_samples) / | |
643 | + block->data.stream_info.sample_rate + 0.5; | |
644 | + } | |
645 | + } while (FLAC__metadata_iterator_next(it)); | |
646 | + FLAC__metadata_iterator_delete(it); | |
647 | +out: | |
648 | + FLAC__metadata_chain_delete(chain); | |
649 | + return ret; | |
650 | +} | |
651 | + | |
652 | +static int oggflac_decode(OutputBuffer * cb, DecoderControl * dc, | |
653 | + InputStream * inStream) | |
654 | +{ | |
655 | + return flac_decode_internal(cb, dc, inStream, 1); | |
656 | +} | |
657 | + | |
658 | +static unsigned int oggflac_try_decode(InputStream * inStream) | |
659 | +{ | |
660 | + return (ogg_stream_type_detect(inStream) == FLAC) ? 1 : 0; | |
661 | +} | |
662 | + | |
663 | +static char *oggflac_suffixes[] = { "ogg", NULL }; | |
664 | +static char *oggflac_mime_types[] = { "application/ogg", NULL }; | |
665 | + | |
666 | +static int flac_plugin_init(void) | |
667 | +{ | |
668 | + if (!FLAC_API_SUPPORTS_OGG_FLAC) { | |
669 | + DEBUG("libFLAC does not support OggFLAC\n"); | |
670 | + return 1; | |
671 | + } | |
672 | + DEBUG("libFLAC supports OggFLAC, initializing OggFLAC support\n"); | |
673 | + assert(oggflacPlugin.name == NULL); | |
674 | + oggflacPlugin.name = "oggflac"; | |
675 | + oggflacPlugin.tryDecodeFunc = oggflac_try_decode; | |
676 | + oggflacPlugin.streamDecodeFunc = oggflac_decode; | |
677 | + oggflacPlugin.tagDupFunc = oggflac_tag_dup; | |
678 | + oggflacPlugin.streamTypes = INPUT_PLUGIN_STREAM_URL | | |
679 | + INPUT_PLUGIN_STREAM_FILE; | |
680 | + oggflacPlugin.suffixes = oggflac_suffixes; | |
681 | + oggflacPlugin.mimeTypes = oggflac_mime_types; | |
682 | + loadInputPlugin(&oggflacPlugin); | |
683 | + return 1; | |
684 | +} | |
685 | + | |
686 | +#endif /* FLAC_API_VERSION_CURRENT >= 7 */ | |
687 | + | |
688 | static char *flacSuffixes[] = { "flac", NULL }; | |
689 | static char *flac_mime_types[] = { "application/x-flac", NULL }; | |
690 | ||
691 | InputPlugin flacPlugin = { | |
692 | "flac", | |
693 | - NULL, | |
694 | + flac_plugin_init, | |
695 | NULL, | |
696 | NULL, | |
697 | flac_decode, |