1 /* -*- linux-c -*-
2 Copyright (C) 2004 Tom Szilagyi
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 $Id: file_decoder.c 1245 2012-02-04 10:33:30Z assworth $
19 */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <strings.h>
27
28 #include "../httpc.h"
29 #include "../metadata.h"
30 #include "../options.h"
31 #include "dec_null.h"
32 #ifdef HAVE_CDDA
33 #include "dec_cdda.h"
34 #endif /* HAVE_CDDA */
35 #ifdef HAVE_SNDFILE
36 #include "dec_sndfile.h"
37 #endif /* HAVE_SNDFILE */
38 #ifdef HAVE_FLAC
39 #include "dec_flac.h"
40 #endif /* HAVE_FLAC */
41 #ifdef HAVE_VORBIS
42 #include "dec_vorbis.h"
43 #endif /* HAVE_VORBIS */
44 #ifdef HAVE_SPEEX
45 #include "dec_speex.h"
46 #endif /* HAVE_SPEEX */
47 #ifdef HAVE_MPC
48 #include "dec_mpc.h"
49 #endif /* HAVE_MPC */
50 #ifdef HAVE_MPEG
51 #include "dec_mpeg.h"
52 #endif /* HAVE_MPEG */
53 #ifdef HAVE_MOD
54 #include "dec_mod.h"
55 #endif /* HAVE_MOD */
56 #ifdef HAVE_MAC
57 #include "dec_mac.h"
58 #endif /* HAVE_MAC */
59 #ifdef HAVE_LAVC
60 #include <libavformat/avformat.h>
61 #include "dec_lavc.h"
62 #endif /* HAVE_LAVC */
63 #ifdef HAVE_WAVPACK
64 #include "dec_wavpack.h"
65 #endif /* HAVE_WAVPACK */
66 #include "file_decoder.h"
67
68
69 extern options_t options;
70
71 typedef decoder_t * decoder_init_t(file_decoder_t * fdec);
72
73 /* this controls the order in which decoders are probed for a file */
74 static decoder_init_t * decoder_init_v[] = {
75 null_decoder_init,
76 #ifdef HAVE_CDDA
77 cdda_decoder_init,
78 #endif /* HAVE_CDDA */
79 #ifdef HAVE_SNDFILE
80 sndfile_decoder_init,
81 #endif /* HAVE_SNDFILE */
82 #ifdef HAVE_FLAC
83 flac_decoder_init,
84 #endif /* HAVE_FLAC */
85 #ifdef HAVE_VORBIS
86 vorbis_decoder_init,
87 #endif /* HAVE_VORBIS */
88 #ifdef HAVE_SPEEX
89 speex_dec_init,
90 #endif /* HAVE_SPEEX */
91 #ifdef HAVE_MPC
92 mpc_decoder_init_func,
93 #endif /* HAVE_MPC */
94 #ifdef HAVE_MAC
95 mac_decoder_init,
96 #endif /* HAVE_MAC */
97 #ifdef HAVE_MPEG
98 mpeg_decoder_init,
99 #endif /* HAVE_MPEG */
100 #ifdef HAVE_WAVPACK
101 wavpack_decoder_init,
102 #endif /* HAVE_WAVPACK */
103 #ifdef HAVE_MOD
104 mod_decoder_init,
105 #endif /* HAVE_MOD */
106 #ifdef HAVE_LAVC
107 lavc_decoder_init,
108 #endif /* HAVE_LAVC */
109 NULL
110 };
111
112
113 /* utility function used by some decoders to check file extension */
114 int
is_valid_extension(char ** valid_extensions,char * filename,int module)115 is_valid_extension(char ** valid_extensions, char * filename, int module) {
116
117 int i;
118 char * c = NULL, * d = NULL;
119 char *ext;
120
121 /* post ext */
122 i = 0;
123
124 if ((c = strrchr(filename, '.')) != NULL) {
125
126 ++c;
127
128 while (valid_extensions[i] != NULL) {
129
130 if (strcasecmp(c, valid_extensions[i]) == 0) {
131 return 1;
132 }
133 ++i;
134 }
135 }
136
137 if (module) { /* checking mod pre file extension */
138 /* lots of amiga modules has EXT.NAME filename format */
139
140 /* pre ext */
141 i = 0;
142 ext = strdup(filename);
143
144 if (ext && (c = strrchr(ext, '/')) != NULL) {
145
146 ++c;
147
148 if ((d = strchr(ext, '.')) != NULL) {
149
150 *d = '\0';
151
152 while (valid_extensions[i] != NULL) {
153
154 if (strcasecmp(c, valid_extensions[i]) == 0) {
155 free(ext);
156 return 1;
157 }
158 ++i;
159 }
160 }
161 }
162
163 free(ext);
164 }
165
166 return 0;
167 }
168
169
170 /* call this first before using file_decoder in program */
171 void
file_decoder_init(void)172 file_decoder_init(void) {
173
174 #ifdef HAVE_LAVC
175 av_register_all();
176 #endif /* HAVE_LAVC */
177 }
178
179
180 file_decoder_t *
file_decoder_new(void)181 file_decoder_new(void) {
182
183 file_decoder_t * fdec = NULL;
184
185 if ((fdec = calloc(1, sizeof(file_decoder_t))) == NULL) {
186 fprintf(stderr, "file_decoder.c: file_decoder_new() failed: calloc error\n");
187 return NULL;
188 }
189
190 fdec->file_open = 0;
191
192 fdec->voladj_db = 0.0f;
193 fdec->voladj_lin = 1.0f;
194
195 fdec->pdec = NULL;
196
197 return fdec;
198 }
199
200
201 void
file_decoder_delete(file_decoder_t * fdec)202 file_decoder_delete(file_decoder_t * fdec) {
203
204 if (fdec->file_open) {
205 file_decoder_close(fdec);
206 }
207
208 free(fdec);
209 }
210
211
212 int
file_decoder_finalize_open(file_decoder_t * fdec,decoder_t * dec,char * filename)213 file_decoder_finalize_open(file_decoder_t * fdec, decoder_t * dec, char * filename) {
214
215 if (fdec->fileinfo.channels == 1) {
216 fdec->fileinfo.is_mono = 1;
217 goto ok_open;
218
219 } else if (fdec->fileinfo.channels == 2) {
220 fdec->fileinfo.is_mono = 0;
221 goto ok_open;
222
223 } else {
224 fprintf(stderr, "file_decoder_open: programmer error: "
225 "soundfile with %d\n channels is unsupported.\n",
226 fdec->fileinfo.channels);
227 goto no_open;
228 }
229
230 ok_open:
231 fdec->file_open = 1;
232 fdec->samples_left = fdec->fileinfo.total_samples;
233 fdec->fileinfo.format_str = dec->format_str;
234 fdec->fileinfo.format_flags = dec->format_flags;
235 return 0;
236
237 no_open:
238 fprintf(stderr, "file_decoder_open: unable to open %s\n", filename);
239 return 1;
240 }
241
242
243 int
stream_decoder_open(file_decoder_t * fdec,char * URL)244 stream_decoder_open(file_decoder_t * fdec, char * URL) {
245
246 int ret;
247 decoder_t * dec;
248 http_session_t * session = httpc_new();
249
250 if ((ret = httpc_init(session, fdec, URL,
251 options.inet_use_proxy,
252 options.inet_proxy,
253 options.inet_proxy_port,
254 options.inet_noproxy_domains, 0L)) != HTTPC_OK) {
255 fprintf(stderr, "stream_decoder_open: httpc_init failed, ret = %d\n", ret);
256 httpc_del(session);
257 return DECODER_OPEN_FERROR;
258 }
259
260 #ifdef HAVE_MPEG
261 if ((session->headers.content_type == NULL) ||
262 (strcasecmp(session->headers.content_type, "audio/mp3") == 0) ||
263 (strcasecmp(session->headers.content_type, "audio/mpeg") == 0) ||
264 (strcasecmp(session->headers.content_type, "application/mp3") == 0) ||
265 (strcasecmp(session->headers.content_type, "application/mpeg") == 0)) {
266 int ret;
267
268 if (session->headers.content_type == NULL) {
269 fprintf(stderr, "Warning: no Content-Type, assuming audio/mpeg\n");
270 }
271
272 dec = mpeg_decoder_init(fdec);
273 if (!dec)
274 return DECODER_OPEN_FERROR;
275
276 ret = mpeg_stream_decoder_open(dec, session);
277 if (ret == DECODER_OPEN_FERROR) {
278 dec->destroy(dec);
279 return ret;
280 }
281 fdec->pdec = (void *)dec;
282 return file_decoder_finalize_open(fdec, dec, URL);
283 }
284 #else
285 if (session->headers.content_type == NULL) {
286 fprintf(stderr, "stream_decoder_open: error: no Content-Type found\n");
287 httpc_close(session);
288 httpc_del(session);
289 return DECODER_OPEN_FERROR;
290 }
291 #endif /* HAVE_MPEG */
292
293 #ifdef HAVE_VORBIS
294 if ((strcasecmp(session->headers.content_type, "application/ogg") == 0) ||
295 (strcasecmp(session->headers.content_type, "audio/ogg") == 0) ||
296 (strcasecmp(session->headers.content_type, "audio/x-vorbis") == 0)) {
297
298 int ret;
299
300 dec = vorbis_decoder_init(fdec);
301 if (!dec)
302 return DECODER_OPEN_FERROR;
303
304 ret = vorbis_stream_decoder_open(dec, session);
305 if (ret == DECODER_OPEN_FERROR) {
306 dec->destroy(dec);
307 return ret;
308 }
309 fdec->pdec = (void *)dec;
310 return file_decoder_finalize_open(fdec, dec, URL);
311 }
312 #endif /* HAVE_VORBIS */
313
314 fprintf(stderr, "Sorry, no handler for Content-Type: %s\n",
315 session->headers.content_type);
316 httpc_close(session);
317 httpc_del(session);
318 return 1;
319 }
320
321
322 /* return: 0 is OK, >0 is error */
323 int
file_decoder_open(file_decoder_t * fdec,char * filename)324 file_decoder_open(file_decoder_t * fdec, char * filename) {
325
326 int i, ret;
327 decoder_t * dec;
328
329 if (filename == NULL) {
330 fprintf(stderr, "Warning: filename == NULL passed to file_decoder_open()\n");
331 fprintf(stderr, "This is likely to be a programmer error, please report.\n");
332 return 1;
333 }
334 fdec->filename = strdup(filename);
335
336 if (httpc_is_url(filename))
337 return stream_decoder_open(fdec, filename);
338
339 for (i = 0; decoder_init_v[i] != NULL; i++) {
340 dec = decoder_init_v[i](fdec);
341 if (!dec) {
342 continue;
343 }
344 fdec->pdec = (void *)dec;
345 ret = dec->open(dec, filename);
346 if (ret == DECODER_OPEN_FERROR) {
347 dec->destroy(dec);
348 goto no_open;
349 } else if (ret == DECODER_OPEN_BADLIB) {
350 dec->destroy(dec);
351 continue;
352 } else if (ret != DECODER_OPEN_SUCCESS) {
353 printf("programmer error, please report: "
354 "illegal retvalue %d from dec->open() at %d\n", ret, i);
355 return 1;
356 }
357
358 break;
359 }
360
361 if (decoder_init_v[i] == NULL) {
362 goto no_open;
363 }
364
365 if (fdec->fileinfo.channels == 1) {
366 fdec->fileinfo.is_mono = 1;
367 goto ok_open;
368
369 } else if (fdec->fileinfo.channels == 2) {
370 fdec->fileinfo.is_mono = 0;
371 goto ok_open;
372
373 } else {
374 fprintf(stderr, "file_decoder_open: programmer error: "
375 "soundfile with %d\n channels is unsupported.\n",
376 fdec->fileinfo.channels);
377 goto no_open;
378 }
379
380 ok_open:
381 fdec->file_open = 1;
382 fdec->samples_left = fdec->fileinfo.total_samples;
383 fdec->fileinfo.format_str = dec->format_str;
384 fdec->fileinfo.format_flags = dec->format_flags;
385 return 0;
386
387 no_open:
388 fprintf(stderr, "file_decoder_open: unable to open %s\n", filename);
389 return 1;
390 }
391
392
393 void
file_decoder_send_metadata(file_decoder_t * fdec)394 file_decoder_send_metadata(file_decoder_t * fdec) {
395
396 decoder_t * dec = (decoder_t *)(fdec->pdec);
397
398 return dec->send_metadata(dec);
399 }
400
401 void
file_decoder_set_rva(file_decoder_t * fdec,float voladj)402 file_decoder_set_rva(file_decoder_t * fdec, float voladj) {
403
404 fdec->voladj_db = voladj;
405 fdec->voladj_lin = db2lin(voladj);
406 }
407
408
409 void
file_decoder_set_meta_cb(file_decoder_t * fdec,void (* meta_cb)(metadata_t * meta,void * data),void * data)410 file_decoder_set_meta_cb(file_decoder_t * fdec,
411 void (* meta_cb)(metadata_t * meta, void * data),
412 void * data) {
413
414 fdec->meta_cb = meta_cb;
415 fdec->meta_cbdata = data;
416 }
417
418
419 void
file_decoder_close(file_decoder_t * fdec)420 file_decoder_close(file_decoder_t * fdec) {
421
422 decoder_t * dec;
423
424 if (!fdec->file_open) {
425 return;
426 }
427
428 dec = (decoder_t *)(fdec->pdec);
429 dec->close(dec);
430 dec->destroy(dec);
431 fdec->pdec = NULL;
432 fdec->file_open = 0;
433 fdec->file_lib = 0;
434 if (fdec->filename != NULL) {
435 free(fdec->filename);
436 fdec->filename = NULL;
437 }
438 if (fdec->meta != NULL) {
439 metadata_free(fdec->meta);
440 fdec->meta = NULL;
441 }
442 }
443
444
445 unsigned int
file_decoder_read(file_decoder_t * fdec,float * dest,int num)446 file_decoder_read(file_decoder_t * fdec, float * dest, int num) {
447
448 decoder_t * dec = (decoder_t *)(fdec->pdec);
449
450 return dec->read(dec, dest, num);
451 }
452
453
454 void
file_decoder_seek(file_decoder_t * fdec,unsigned long long seek_to_pos)455 file_decoder_seek(file_decoder_t * fdec, unsigned long long seek_to_pos) {
456
457 decoder_t * dec = (decoder_t *)(fdec->pdec);
458
459 dec->seek(dec, seek_to_pos);
460 }
461
462
463 void
file_decoder_pause(file_decoder_t * fdec)464 file_decoder_pause(file_decoder_t * fdec) {
465
466 decoder_t * dec = (decoder_t *)(fdec->pdec);
467 if (dec->pause != NULL)
468 dec->pause(dec);
469 }
470
471
472 void
file_decoder_resume(file_decoder_t * fdec)473 file_decoder_resume(file_decoder_t * fdec) {
474
475 decoder_t * dec = (decoder_t *)(fdec->pdec);
476 if (dec->resume != NULL)
477 dec->resume(dec);
478 }
479
480
481 float
get_file_duration(char * file)482 get_file_duration(char * file) {
483
484 file_decoder_t * fdec;
485 float duration;
486
487 if ((fdec = file_decoder_new()) == NULL) {
488 fprintf(stderr, "get_file_duration: error: file_decoder_new() returned NULL\n");
489 return -1.0f;
490 }
491
492 if (file_decoder_open(fdec, file)) {
493 fprintf(stderr, "file_decoder_open() failed on %s\n", file);
494 file_decoder_delete(fdec);
495 return -1.0f;
496 }
497
498 duration = (float)fdec->fileinfo.total_samples / fdec->fileinfo.sample_rate;
499
500 file_decoder_close(fdec);
501 file_decoder_delete(fdec);
502
503 return duration;
504 }
505
506 /* taken from cdparanoia source */
507 int
bigendianp(void)508 bigendianp(void) {
509
510 int test=1;
511 char *hack=(char *)(&test);
512 if(hack[0])return(0);
513 return(1);
514 }
515
516
517 // vim: shiftwidth=8:tabstop=8:softtabstop=8 :
518
519