comparison src/mpg123/mpg123.c @ 12:3da1b8942b8b trunk

[svn] - remove src/Input src/Output src/Effect src/General src/Visualization src/Container
author nenolod
date Mon, 18 Sep 2006 03:14:20 -0700
parents src/Input/mpg123/mpg123.c@088092a52fea
children 98de08786b0a
comparison
equal deleted inserted replaced
11:cff1d04026ae 12:3da1b8942b8b
1 #include "mpg123.h"
2 #include "common.h"
3
4 #include <glib.h>
5 #include <glib/gi18n.h>
6 #include <gtk/gtk.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <sys/time.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <netdb.h>
20
21 #include "audacious/util.h"
22 #include "audacious/configdb.h"
23 #include "audacious/vfs.h"
24 #include "audacious/titlestring.h"
25 #include "audacious/util.h"
26 #include <tag_c.h>
27
28 #define BUFSIZE_X 2048
29
30 static struct frame fr, temp_fr;
31
32 PlayerInfo *mpgdec_info = NULL;
33 static GThread *decode_thread;
34
35 static gboolean audio_error = FALSE, output_opened = FALSE, dopause = FALSE;
36 gint mpgdec_bitrate, mpgdec_frequency, mpgdec_length, mpgdec_layer,
37 mpgdec_lsf;
38 gchar *mpgdec_title = NULL, *mpgdec_filename = NULL;
39 static int disp_bitrate, skip_frames = 0;
40 static int cpu_fflags, cpu_efflags;
41 gboolean mpgdec_stereo, mpgdec_mpeg25;
42 int mpgdec_mode;
43
44 mpgdec_t *ins;
45
46 gchar **mpgdec_id3_encoding_list = NULL;
47
48 const char *mpgdec_id3_genres[GENRE_MAX] = {
49 N_("Blues"), N_("Classic Rock"), N_("Country"), N_("Dance"),
50 N_("Disco"), N_("Funk"), N_("Grunge"), N_("Hip-Hop"),
51 N_("Jazz"), N_("Metal"), N_("New Age"), N_("Oldies"),
52 N_("Other"), N_("Pop"), N_("R&B"), N_("Rap"), N_("Reggae"),
53 N_("Rock"), N_("Techno"), N_("Industrial"), N_("Alternative"),
54 N_("Ska"), N_("Death Metal"), N_("Pranks"), N_("Soundtrack"),
55 N_("Euro-Techno"), N_("Ambient"), N_("Trip-Hop"), N_("Vocal"),
56 N_("Jazz+Funk"), N_("Fusion"), N_("Trance"), N_("Classical"),
57 N_("Instrumental"), N_("Acid"), N_("House"), N_("Game"),
58 N_("Sound Clip"), N_("Gospel"), N_("Noise"), N_("AlternRock"),
59 N_("Bass"), N_("Soul"), N_("Punk"), N_("Space"),
60 N_("Meditative"), N_("Instrumental Pop"),
61 N_("Instrumental Rock"), N_("Ethnic"), N_("Gothic"),
62 N_("Darkwave"), N_("Techno-Industrial"), N_("Electronic"),
63 N_("Pop-Folk"), N_("Eurodance"), N_("Dream"),
64 N_("Southern Rock"), N_("Comedy"), N_("Cult"),
65 N_("Gangsta Rap"), N_("Top 40"), N_("Christian Rap"),
66 N_("Pop/Funk"), N_("Jungle"), N_("Native American"),
67 N_("Cabaret"), N_("New Wave"), N_("Psychedelic"), N_("Rave"),
68 N_("Showtunes"), N_("Trailer"), N_("Lo-Fi"), N_("Tribal"),
69 N_("Acid Punk"), N_("Acid Jazz"), N_("Polka"), N_("Retro"),
70 N_("Musical"), N_("Rock & Roll"), N_("Hard Rock"), N_("Folk"),
71 N_("Folk/Rock"), N_("National Folk"), N_("Swing"),
72 N_("Fast-Fusion"), N_("Bebob"), N_("Latin"), N_("Revival"),
73 N_("Celtic"), N_("Bluegrass"), N_("Avantgarde"),
74 N_("Gothic Rock"), N_("Progressive Rock"),
75 N_("Psychedelic Rock"), N_("Symphonic Rock"), N_("Slow Rock"),
76 N_("Big Band"), N_("Chorus"), N_("Easy Listening"),
77 N_("Acoustic"), N_("Humour"), N_("Speech"), N_("Chanson"),
78 N_("Opera"), N_("Chamber Music"), N_("Sonata"), N_("Symphony"),
79 N_("Booty Bass"), N_("Primus"), N_("Porn Groove"),
80 N_("Satire"), N_("Slow Jam"), N_("Club"), N_("Tango"),
81 N_("Samba"), N_("Folklore"), N_("Ballad"), N_("Power Ballad"),
82 N_("Rhythmic Soul"), N_("Freestyle"), N_("Duet"),
83 N_("Punk Rock"), N_("Drum Solo"), N_("A Cappella"),
84 N_("Euro-House"), N_("Dance Hall"), N_("Goa"),
85 N_("Drum & Bass"), N_("Club-House"), N_("Hardcore"),
86 N_("Terror"), N_("Indie"), N_("BritPop"), N_("Negerpunk"),
87 N_("Polsk Punk"), N_("Beat"), N_("Christian Gangsta Rap"),
88 N_("Heavy Metal"), N_("Black Metal"), N_("Crossover"),
89 N_("Contemporary Christian"), N_("Christian Rock"),
90 N_("Merengue"), N_("Salsa"), N_("Thrash Metal"),
91 N_("Anime"), N_("JPop"), N_("Synthpop")
92 };
93
94 double
95 mpgdec_compute_tpf(struct frame *fr)
96 {
97 const int bs[4] = { 0, 384, 1152, 1152 };
98 double tpf;
99
100 tpf = bs[fr->lay];
101 tpf /= mpgdec_freqs[fr->sampling_frequency] << (fr->lsf);
102 return tpf;
103 }
104
105 static void
106 set_synth_functions(struct frame *fr)
107 {
108 typedef int (*func) (mpgdec_real *, int, unsigned char *, int *);
109 typedef int (*func_mono) (mpgdec_real *, unsigned char *, int *);
110 typedef void (*func_dct36) (mpgdec_real *, mpgdec_real *, mpgdec_real *, mpgdec_real *, mpgdec_real *);
111
112 int ds = fr->down_sample;
113 int p8 = 0;
114
115 static func funcs[2][2] = {
116 {mpgdec_synth_1to1,
117 mpgdec_synth_ntom},
118 {mpgdec_synth_1to1_8bit,
119 mpgdec_synth_ntom_8bit}
120 };
121
122 static func_mono funcs_mono[2][2] = {
123 {mpgdec_synth_1to1_mono,
124 mpgdec_synth_ntom_mono},
125 {mpgdec_synth_1to1_8bit_mono,
126 mpgdec_synth_ntom_8bit_mono}
127 };
128
129 /* Compatibility with older configs. */
130 if (ds > 1)
131 ds = 1;
132
133 if (mpgdec_cfg.resolution == 8)
134 p8 = 1;
135 fr->synth = funcs[p8][ds];
136 fr->synth_mono = funcs_mono[p8][ds];
137 fr->synth_type = SYNTH_FPU;
138
139 if (p8) {
140 mpgdec_make_conv16to8_table();
141 }
142 }
143
144 static void
145 init(void)
146 {
147 ConfigDb *db;
148 gchar *tmp = NULL;
149
150 ins = mpgdec_new();
151
152 memset(&mpgdec_cfg, 0, sizeof(mpgdec_cfg));
153
154 mpgdec_cfg.resolution = 16;
155 mpgdec_cfg.channels = 2;
156 mpgdec_cfg.downsample = 0;
157 mpgdec_cfg.http_buffer_size = 128;
158 mpgdec_cfg.http_prebuffer = 25;
159 mpgdec_cfg.proxy_port = 8080;
160 mpgdec_cfg.proxy_use_auth = FALSE;
161 mpgdec_cfg.proxy_user = NULL;
162 mpgdec_cfg.proxy_pass = NULL;
163 mpgdec_cfg.use_udp_channel = TRUE;
164 mpgdec_cfg.title_override = FALSE;
165 mpgdec_cfg.disable_id3v2 = FALSE;
166 mpgdec_cfg.default_synth = SYNTH_AUTO;
167
168 mpgdec_cfg.title_encoding_enabled = FALSE;
169 mpgdec_cfg.title_encoding = NULL;
170
171 db = bmp_cfg_db_open();
172
173 bmp_cfg_db_get_int(db, "MPG123", "resolution", &mpgdec_cfg.resolution);
174 bmp_cfg_db_get_int(db, "MPG123", "channels", &mpgdec_cfg.channels);
175 bmp_cfg_db_get_int(db, "MPG123", "downsample", &mpgdec_cfg.downsample);
176 bmp_cfg_db_get_int(db, "MPG123", "http_buffer_size",
177 &mpgdec_cfg.http_buffer_size);
178 bmp_cfg_db_get_int(db, "MPG123", "http_prebuffer",
179 &mpgdec_cfg.http_prebuffer);
180 bmp_cfg_db_get_bool(db, "MPG123", "save_http_stream",
181 &mpgdec_cfg.save_http_stream);
182 if (!bmp_cfg_db_get_string
183 (db, "MPG123", "save_http_path", &mpgdec_cfg.save_http_path))
184 mpgdec_cfg.save_http_path = g_strdup(g_get_home_dir());
185
186 bmp_cfg_db_get_bool(db, "MPG123", "use_udp_channel",
187 &mpgdec_cfg.use_udp_channel);
188
189 bmp_cfg_db_get_bool(db, "MPG123", "title_override",
190 &mpgdec_cfg.title_override);
191 bmp_cfg_db_get_bool(db, "MPG123", "disable_id3v2",
192 &mpgdec_cfg.disable_id3v2);
193 if (!bmp_cfg_db_get_string
194 (db, "MPG123", "id3_format", &mpgdec_cfg.id3_format))
195 mpgdec_cfg.id3_format = g_strdup("%p - %t");
196 bmp_cfg_db_get_int(db, "MPG123", "default_synth",
197 &mpgdec_cfg.default_synth);
198
199 bmp_cfg_db_get_bool(db, "MPG123", "title_encoding_enabled", &mpgdec_cfg.title_encoding_enabled);
200 bmp_cfg_db_get_string(db, "MPG123", "title_encoding", &mpgdec_cfg.title_encoding);
201 if (mpgdec_cfg.title_encoding_enabled)
202 mpgdec_id3_encoding_list = g_strsplit_set(mpgdec_cfg.title_encoding, ENCODING_SEPARATOR, 0);
203
204 bmp_cfg_db_get_bool(db, NULL, "use_proxy", &mpgdec_cfg.use_proxy);
205 bmp_cfg_db_get_string(db, NULL, "proxy_host", &mpgdec_cfg.proxy_host);
206 bmp_cfg_db_get_string(db, NULL, "proxy_port", &tmp);
207
208 if (tmp != NULL)
209 mpgdec_cfg.proxy_port = atoi(tmp);
210
211 bmp_cfg_db_get_bool(db, NULL, "proxy_use_auth", &mpgdec_cfg.proxy_use_auth);
212 bmp_cfg_db_get_string(db, NULL, "proxy_user", &mpgdec_cfg.proxy_user);
213 bmp_cfg_db_get_string(db, NULL, "proxy_pass", &mpgdec_cfg.proxy_pass);
214
215 bmp_cfg_db_close(db);
216
217 if (mpgdec_cfg.resolution != 16 && mpgdec_cfg.resolution != 8)
218 mpgdec_cfg.resolution = 16;
219
220 mpgdec_cfg.channels = CLAMP(mpgdec_cfg.channels, 0, 2);
221 mpgdec_cfg.downsample = CLAMP(mpgdec_cfg.downsample, 0, 2);
222 mpgdec_getcpuflags(&cpu_fflags, &cpu_efflags);
223 }
224
225 static void
226 cleanup(void)
227 {
228 g_free(mpgdec_ip.description);
229 mpgdec_ip.description = NULL;
230
231 if (mpgdec_cfg.save_http_path) {
232 free(mpgdec_cfg.save_http_path);
233 mpgdec_cfg.save_http_path = NULL;
234 }
235
236 if (mpgdec_cfg.proxy_host) {
237 free(mpgdec_cfg.proxy_host);
238 mpgdec_cfg.proxy_host = NULL;
239 }
240
241 if (mpgdec_cfg.proxy_user) {
242 free(mpgdec_cfg.proxy_user);
243 mpgdec_cfg.proxy_user = NULL;
244 }
245
246 if (mpgdec_cfg.proxy_pass) {
247 free(mpgdec_cfg.proxy_pass);
248 mpgdec_cfg.proxy_pass = NULL;
249 }
250
251 if (mpgdec_cfg.id3_format) {
252 free(mpgdec_cfg.id3_format);
253 mpgdec_cfg.id3_format = NULL;
254 }
255
256 if (mpgdec_cfg.title_encoding) {
257 free(mpgdec_cfg.title_encoding);
258 mpgdec_cfg.title_encoding = NULL;
259 }
260
261 g_strfreev(mpgdec_id3_encoding_list);
262 }
263
264 static guint32
265 convert_to_header(guint8 * buf)
266 {
267 return (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
268 }
269
270
271 #define DET_BUF_SIZE 4096
272
273 static gboolean
274 mpgdec_detect_by_content(char *filename)
275 {
276 VFSFile *file;
277 guchar tmp[4];
278 guint32 head;
279 struct frame fr;
280 guchar buf[DET_BUF_SIZE];
281 int in_buf, i;
282 gboolean ret = FALSE;
283 guint cyc = 0;
284
285 if ((file = vfs_fopen(filename, "rb")) == NULL)
286 return FALSE;
287 if (vfs_fread(tmp, 1, 4, file) != 4)
288 goto done;
289 if (!memcmp(tmp, "ID3", 3))
290 {
291 ret = TRUE;
292 goto done;
293 }
294 head = convert_to_header(tmp);
295 while (!mpgdec_head_check(head)) {
296 /*
297 * The mpeg-stream can start anywhere in the file,
298 * so we check the entire file
299 *
300 * Incorrect! We give up past twenty iterations of this
301 * code for safety's sake. Buffer overflows suck. --nenolod
302 */
303 /* Optimize this */
304 in_buf = vfs_fread(buf, 1, DET_BUF_SIZE, file);
305 if (in_buf == 0)
306 goto done;
307
308 for (i = 0; i < in_buf; i++) {
309 head <<= 8;
310 head |= buf[i];
311 if (mpgdec_head_check(head)) {
312 vfs_fseek(file, i + 1 - in_buf, SEEK_CUR);
313 break;
314 }
315 }
316
317 if (++cyc > 1024)
318 goto done;
319 }
320 if (mpgdec_decode_header(&fr, head)) {
321 /*
322 * We found something which looks like a MPEG-header.
323 * We check the next frame too, to be sure
324 */
325
326 if (vfs_fseek(file, fr.framesize, SEEK_CUR) != 0)
327 goto done;
328 if (vfs_fread(tmp, 1, 4, file) != 4)
329 goto done;
330 head = convert_to_header(tmp);
331 if (mpgdec_head_check(head) && mpgdec_decode_header(&fr, head))
332 ret = TRUE;
333 }
334
335 done:
336 vfs_fclose(file);
337 return ret;
338 }
339
340 static int
341 is_our_file(char *filename)
342 {
343 gchar *ext = strrchr(filename, '.');
344
345 if (CHECK_STREAM(filename) &&
346 (ext && strncasecmp(ext, ".ogg", 4)) &&
347 (ext && strncasecmp(ext, ".flac", 5)))
348 return TRUE;
349 else if (mpgdec_detect_by_content(filename))
350 return TRUE;
351 #if 0
352 else if (ext && (!strncasecmp(ext, ".mp3", 4)
353 || !strncasecmp(ext, ".mp2", 4)
354 || !strncasecmp(ext, ".mpg", 4)))
355 return TRUE;
356 #endif
357
358 return FALSE;
359 }
360
361 static void
362 play_frame(struct frame *fr)
363 {
364 if (fr->error_protection) {
365 bsi.wordpointer += 2;
366 /* mpgdec_getbits(16); *//* skip crc */
367 }
368 if (!fr->do_layer(fr)) {
369 skip_frames = 2;
370 mpgdec_info->output_audio = FALSE;
371 }
372 else {
373 if (!skip_frames)
374 mpgdec_info->output_audio = TRUE;
375 else
376 skip_frames--;
377 }
378 }
379
380 static const char *
381 get_id3_genre(unsigned char genre_code)
382 {
383 if (genre_code < GENRE_MAX)
384 return gettext(mpgdec_id3_genres[genre_code]);
385
386 return "";
387 }
388
389 guint
390 mpgdec_strip_spaces(char *src, size_t n)
391 {
392 gchar *space = NULL, /* last space in src */
393 *start = src;
394
395 while (n--)
396 switch (*src++) {
397 case '\0':
398 n = 0; /* breaks out of while loop */
399
400 src--;
401 break;
402 case ' ':
403 if (space == NULL)
404 space = src - 1;
405 break;
406 default:
407 space = NULL; /* don't terminate intermediate spaces */
408
409 break;
410 }
411 if (space != NULL) {
412 src = space;
413 *src = '\0';
414 }
415 return src - start;
416 }
417
418 /*
419 * Function extname (filename)
420 *
421 * Return pointer within filename to its extenstion, or NULL if
422 * filename has no extension.
423 *
424 */
425 static gchar *
426 extname(const char *filename)
427 {
428 gchar *ext = strrchr(filename, '.');
429
430 if (ext != NULL)
431 ++ext;
432
433 return ext;
434 }
435
436 /*
437 * Function id3v1_to_id3v2 (v1, v2)
438 *
439 * Convert ID3v1 tag `v1' to ID3v2 tag `v2'.
440 *
441 */
442 void
443 mpgdec_id3v1_to_id3v2(struct id3v1tag_t *v1, struct id3tag_t *v2)
444 {
445 memset(v2, 0, sizeof(struct id3tag_t));
446 strncpy(v2->title, v1->title, 30);
447 strncpy(v2->artist, v1->artist, 30);
448 strncpy(v2->album, v1->album, 30);
449 strncpy(v2->comment, v1->u.v1_0.comment, 30);
450 strncpy(v2->genre, get_id3_genre(v1->genre), sizeof(v2->genre));
451 g_strstrip(v2->title);
452 g_strstrip(v2->artist);
453 g_strstrip(v2->album);
454 g_strstrip(v2->comment);
455 g_strstrip(v2->genre);
456 {
457 char y[5];
458 memcpy(y, v1->year, 4); y[4]=0;
459 v2->year = atoi(y);
460 }
461
462 /* Check for v1.1 tags. */
463 if (v1->u.v1_1.__zero == 0)
464 v2->track_number = v1->u.v1_1.track_number;
465 else
466 v2->track_number = 0;
467 }
468
469 #define REMOVE_NONEXISTANT_TAG(x) if (!*x) { x = NULL; }
470
471 static long
472 get_song_length(VFSFile * file)
473 {
474 int len;
475 char tmp[4];
476
477 vfs_fseek(file, 0, SEEK_END);
478 len = vfs_ftell(file);
479 vfs_fseek(file, -128, SEEK_END);
480 vfs_fread(tmp, 1, 3, file);
481 if (!strncmp(tmp, "TAG", 3))
482 len -= 128;
483 return len;
484 }
485
486
487 static guint
488 get_song_time(VFSFile * file)
489 {
490 guint32 head;
491 guchar tmp[4], *buf;
492 struct frame frm;
493 xing_header_t xing_header;
494 double tpf, bpf;
495 guint32 len;
496
497 if (!file)
498 return -1;
499
500 vfs_fseek(file, 0, SEEK_SET);
501 if (vfs_fread(tmp, 1, 4, file) != 4)
502 return 0;
503 head = convert_to_header(tmp);
504 while (!mpgdec_head_check(head)) {
505 head <<= 8;
506 if (vfs_fread(tmp, 1, 1, file) != 1)
507 return 0;
508 head |= tmp[0];
509 }
510 if (mpgdec_decode_header(&frm, head)) {
511 buf = g_malloc(frm.framesize + 4);
512 vfs_fseek(file, -4, SEEK_CUR);
513 vfs_fread(buf, 1, frm.framesize + 4, file);
514 tpf = mpgdec_compute_tpf(&frm);
515 if (mpgdec_get_xing_header(&xing_header, buf)) {
516 g_free(buf);
517 if (xing_header.bytes == 0)
518 xing_header.bytes = get_song_length(file);
519 return (tpf * xing_header.frames * 1000);
520 }
521 g_free(buf);
522 bpf = mpgdec_compute_bpf(&frm);
523 len = get_song_length(file);
524 return ((guint) (len / bpf) * tpf * 1000);
525 }
526 return 0;
527 }
528
529 static TitleInput *
530 get_song_tuple(char *filename)
531 {
532 VFSFile *file;
533 TitleInput *tuple = NULL;
534 TagLib_File *taglib_file;
535 TagLib_Tag *taglib_tag;
536
537 #ifdef USE_CHARDET
538 taglib_set_strings_unicode(FALSE);
539 #endif
540
541 if ((file = vfs_fopen(filename, "rb")) != NULL)
542 {
543 tuple = bmp_title_input_new();
544
545 taglib_file = taglib_file_new(filename);
546 taglib_tag = NULL;
547
548 if (taglib_file != NULL)
549 {
550 taglib_tag = taglib_file_tag(taglib_file);
551 }
552
553 if (taglib_tag != NULL)
554 {
555 tuple->performer = g_strdup(taglib_tag_artist(taglib_tag));
556 tuple->album_name = g_strdup(taglib_tag_album(taglib_tag));
557 tuple->track_name = g_strdup(taglib_tag_title(taglib_tag));
558
559 mpgdec_strip_spaces(tuple->performer, strlen(tuple->performer));
560 mpgdec_strip_spaces(tuple->album_name, strlen(tuple->album_name));
561 mpgdec_strip_spaces(tuple->track_name, strlen(tuple->track_name));
562
563 tuple->year = taglib_tag_year(taglib_tag);
564 tuple->track_number = taglib_tag_track(taglib_tag);
565 tuple->genre = g_strdup(taglib_tag_genre(taglib_tag));
566 tuple->comment = g_strdup(taglib_tag_comment(taglib_tag));
567
568 /* remove any blank tags, fucking taglib */
569 REMOVE_NONEXISTANT_TAG(tuple->performer);
570 REMOVE_NONEXISTANT_TAG(tuple->album_name);
571 REMOVE_NONEXISTANT_TAG(tuple->track_name);
572 REMOVE_NONEXISTANT_TAG(tuple->genre);
573 REMOVE_NONEXISTANT_TAG(tuple->comment);
574 }
575
576 if (tuple->performer != NULL)
577 tuple->performer = str_to_utf8(tuple->performer);
578
579 if (tuple->album_name != NULL)
580 tuple->album_name = str_to_utf8(tuple->album_name);
581
582 if (tuple->track_name != NULL)
583 tuple->track_name = str_to_utf8(tuple->track_name);
584
585 if (tuple->comment != NULL)
586 tuple->comment = str_to_utf8(tuple->comment);
587
588 tuple->file_name = g_path_get_basename(filename);
589 tuple->file_path = g_path_get_dirname(filename);
590 tuple->file_ext = extname(filename);
591 tuple->length = get_song_time(file);
592
593 if (taglib_file != NULL)
594 taglib_file_free(taglib_file);
595
596 taglib_tag_free_strings();
597 vfs_fclose(file);
598 }
599
600 return tuple;
601 }
602
603 static gchar *
604 get_song_title(TitleInput *tuple)
605 {
606 return xmms_get_titlestring(mpgdec_cfg.title_override ?
607 mpgdec_cfg.id3_format :
608 xmms_get_gentitle_format(), tuple);
609 }
610
611 static void
612 get_song_info(char *filename, char **title_real, int *len_real)
613 {
614 TitleInput *tuple;
615
616 (*len_real) = -1;
617 (*title_real) = NULL;
618
619 /*
620 * TODO: Getting song info from http streams.
621 */
622 if (CHECK_STREAM(filename))
623 return;
624
625 if ((tuple = get_song_tuple(filename)) != NULL) {
626 (*len_real) = tuple->length;
627 (*title_real) = get_song_title(tuple);
628 }
629
630 bmp_title_input_free(tuple);
631 }
632
633 static int
634 open_output(void)
635 {
636 int r;
637 AFormat fmt = mpgdec_cfg.resolution == 16 ? FMT_S16_NE : FMT_U8;
638 /* int freq = mpgdec_freqs[fr.sampling_frequency] >> mpgdec_cfg.downsample; */
639 int freq = mpgdec_frequency;
640 int channels = mpgdec_cfg.channels == 2 ? fr.stereo : 1;
641 r = mpgdec_ip.output->open_audio(fmt, freq, channels);
642
643 if (r && dopause) {
644 mpgdec_ip.output->pause(TRUE);
645 dopause = FALSE;
646 }
647
648 return r;
649 }
650
651
652 static int
653 mpgdec_seek(struct frame *fr, xing_header_t * xh, gboolean vbr, int time)
654 {
655 int jumped = -1;
656
657 if (xh) {
658 int percent = ((double) time * 100.0) /
659 (mpgdec_info->num_frames * mpgdec_info->tpf);
660 int byte = mpgdec_seek_point(xh, percent);
661 jumped = mpgdec_stream_jump_to_byte(fr, byte);
662 }
663 else if (vbr && mpgdec_length > 0) {
664 int byte = ((guint64) time * 1000 * mpgdec_info->filesize) /
665 mpgdec_length;
666 jumped = mpgdec_stream_jump_to_byte(fr, byte);
667 }
668 else {
669 int frame = time / mpgdec_info->tpf;
670 jumped = mpgdec_stream_jump_to_frame(fr, frame);
671 }
672
673 return jumped;
674 }
675
676
677 static void *
678 decode_loop(void *arg)
679 {
680 gboolean have_xing_header = FALSE, vbr = FALSE;
681 int disp_count = 0;
682 char *filename = arg;
683 xing_header_t xing_header;
684
685 /* This is used by fileinfo on http streams */
686 mpgdec_bitrate = 0;
687
688 mpgdec_pcm_sample = g_malloc0(32768);
689 mpgdec_pcm_point = 0;
690 mpgdec_filename = filename;
691
692 mpgdec_read_frame_init();
693
694 mpgdec_open_stream(filename, -1);
695
696 if (mpgdec_info->eof || !mpgdec_read_frame(&fr))
697 mpgdec_info->eof = TRUE;
698
699 if (!mpgdec_info->eof && mpgdec_info->going) {
700 if (mpgdec_cfg.channels == 2)
701 fr.single = -1;
702 else
703 fr.single = 3;
704
705 fr.down_sample = mpgdec_cfg.downsample;
706 fr.down_sample_sblimit = SBLIMIT >> mpgdec_cfg.downsample;
707 set_synth_functions(&fr);
708
709 mpgdec_info->tpf = mpgdec_compute_tpf(&fr);
710 if (!CHECK_STREAM(filename)) {
711 if (mpgdec_stream_check_for_xing_header(&fr, &xing_header)) {
712 mpgdec_info->num_frames = xing_header.frames;
713 have_xing_header = TRUE;
714 mpgdec_read_frame(&fr);
715 }
716 }
717
718 for (;;) {
719 memcpy(&temp_fr, &fr, sizeof(struct frame));
720 if (!mpgdec_read_frame(&temp_fr)) {
721 mpgdec_info->eof = TRUE;
722 break;
723 }
724 if (fr.lay != temp_fr.lay ||
725 fr.sampling_frequency != temp_fr.sampling_frequency ||
726 fr.stereo != temp_fr.stereo || fr.lsf != temp_fr.lsf)
727 memcpy(&fr, &temp_fr, sizeof(struct frame));
728 else
729 break;
730 }
731
732 if (!have_xing_header && !CHECK_STREAM(filename))
733 mpgdec_info->num_frames = mpgdec_calc_numframes(&fr);
734
735 memcpy(&fr, &temp_fr, sizeof(struct frame));
736 mpgdec_bitrate = tabsel_123[fr.lsf][fr.lay - 1][fr.bitrate_index];
737 disp_bitrate = mpgdec_bitrate;
738 mpgdec_frequency = mpgdec_freqs[fr.sampling_frequency];
739 mpgdec_stereo = fr.stereo;
740 mpgdec_layer = fr.lay;
741 mpgdec_lsf = fr.lsf;
742 mpgdec_mpeg25 = fr.mpeg25;
743 mpgdec_mode = fr.mode;
744
745 /* XXX: note that this is temporary, until custom resampling is implemented
746 * in prefs.
747 */
748 if (fr.down_sample)
749 {
750 long n = mpgdec_freqs[fr.sampling_frequency];
751 long m = n / (fr.down_sample * 2);
752
753 mpgdec_synth_ntom_set_step(n, m);
754
755 mpgdec_frequency = (gint) m;
756 }
757
758 if (strncasecmp(filename, "http://", 7)) {
759 TitleInput *tuple = NULL;
760 mpgdec_length = mpgdec_info->num_frames * mpgdec_info->tpf * 1000;
761 if (!mpgdec_title)
762 {
763 tuple = get_song_tuple(filename);
764 mpgdec_title = get_song_title(tuple);
765 bmp_title_input_free(tuple);
766 }
767 }
768 else {
769 if (!mpgdec_title)
770 mpgdec_title = mpgdec_http_get_title(filename);
771 mpgdec_length = -1;
772 }
773
774 set_synth_functions(&fr);
775 mpgdec_init_layer3(fr.down_sample_sblimit);
776
777 mpgdec_ip.set_info(mpgdec_title, mpgdec_length,
778 mpgdec_bitrate * 1000,
779 mpgdec_freqs[fr.sampling_frequency], fr.stereo);
780
781 output_opened = TRUE;
782
783 if (!open_output()) {
784 audio_error = TRUE;
785 mpgdec_info->eof = TRUE;
786 }
787 else
788 play_frame(&fr);
789 }
790
791 mpgdec_info->first_frame = FALSE;
792 while (mpgdec_info->going) {
793 if (mpgdec_info->jump_to_time != -1) {
794 void *xp = NULL;
795 if (have_xing_header)
796 xp = &xing_header;
797 if (mpgdec_seek(&fr, xp, vbr, mpgdec_info->jump_to_time) > -1) {
798 mpgdec_ip.output->flush(mpgdec_info->jump_to_time * 1000);
799 mpgdec_info->eof = FALSE;
800 }
801 mpgdec_info->jump_to_time = -1;
802 }
803 if (!mpgdec_info->eof) {
804 if (mpgdec_read_frame(&fr) != 0) {
805 if (fr.lay != mpgdec_layer || fr.lsf != mpgdec_lsf) {
806 memcpy(&temp_fr, &fr, sizeof(struct frame));
807 if (mpgdec_read_frame(&temp_fr) != 0) {
808 if (fr.lay == temp_fr.lay && fr.lsf == temp_fr.lsf) {
809 mpgdec_layer = fr.lay;
810 mpgdec_lsf = fr.lsf;
811 memcpy(&fr, &temp_fr, sizeof(struct frame));
812 }
813 else {
814 memcpy(&fr, &temp_fr, sizeof(struct frame));
815 skip_frames = 2;
816 mpgdec_info->output_audio = FALSE;
817 continue;
818 }
819
820 }
821 }
822
823 if (tabsel_123[fr.lsf][fr.lay - 1][fr.bitrate_index] !=
824 mpgdec_bitrate)
825 mpgdec_bitrate =
826 tabsel_123[fr.lsf][fr.lay - 1][fr.bitrate_index];
827
828 if (!disp_count) {
829 disp_count = 20;
830 if (mpgdec_bitrate != disp_bitrate) {
831 /* FIXME networks streams */
832 disp_bitrate = mpgdec_bitrate;
833 if (!have_xing_header
834 && !CHECK_STREAM(filename)) {
835 double rel = mpgdec_relative_pos();
836 if (rel) {
837 mpgdec_length =
838 mpgdec_ip.output->written_time() / rel;
839 vbr = TRUE;
840 }
841
842 if (rel == 0 || !(mpgdec_length > 0)) {
843 mpgdec_info->num_frames =
844 mpgdec_calc_numframes(&fr);
845 mpgdec_info->tpf = mpgdec_compute_tpf(&fr);
846 mpgdec_length =
847 mpgdec_info->num_frames *
848 mpgdec_info->tpf * 1000;
849 }
850
851
852 }
853 mpgdec_ip.set_info(mpgdec_title, mpgdec_length,
854 mpgdec_bitrate * 1000,
855 mpgdec_frequency, mpgdec_stereo);
856 }
857 }
858 else
859 disp_count--;
860 play_frame(&fr);
861 }
862 else {
863 mpgdec_ip.output->buffer_free();
864 mpgdec_ip.output->buffer_free();
865 mpgdec_info->eof = TRUE;
866 g_usleep(10000);
867 }
868 }
869 else {
870 g_usleep(10000);
871 }
872 }
873 g_free(mpgdec_title);
874 mpgdec_title = NULL;
875 mpgdec_stream_close();
876 if (output_opened && !audio_error)
877 mpgdec_ip.output->close_audio();
878 g_free(mpgdec_pcm_sample);
879 mpgdec_filename = NULL;
880 g_free(filename);
881
882 return NULL;
883 }
884
885 static void
886 play_file(char *filename)
887 {
888 memset(&fr, 0, sizeof(struct frame));
889 memset(&temp_fr, 0, sizeof(struct frame));
890
891 mpgdec_info = g_malloc0(sizeof(PlayerInfo));
892 mpgdec_info->going = 1;
893 mpgdec_info->first_frame = TRUE;
894 mpgdec_info->output_audio = TRUE;
895 mpgdec_info->jump_to_time = -1;
896 skip_frames = 0;
897 audio_error = FALSE;
898 output_opened = FALSE;
899 dopause = FALSE;
900
901 decode_thread = g_thread_create(decode_loop, g_strdup(filename), TRUE,
902 NULL);
903 }
904
905 static void
906 stop(void)
907 {
908 if (mpgdec_info && mpgdec_info->going) {
909 mpgdec_info->going = FALSE;
910 g_thread_join(decode_thread);
911 g_free(mpgdec_info);
912 mpgdec_info = NULL;
913 }
914 }
915
916 static void
917 seek(int time)
918 {
919 mpgdec_info->jump_to_time = time;
920
921 while (mpgdec_info->jump_to_time != -1)
922 g_usleep(10000);
923 }
924
925 static void
926 do_pause(short p)
927 {
928 if (output_opened)
929 mpgdec_ip.output->pause(p);
930 else
931 dopause = p;
932 }
933
934 static int
935 get_time(void)
936 {
937 if (audio_error)
938 return -2;
939 if (!mpgdec_info)
940 return -1;
941 if (!mpgdec_info->going
942 || (mpgdec_info->eof && !mpgdec_ip.output->buffer_playing()))
943 return -1;
944 return mpgdec_ip.output->output_time();
945 }
946
947 static void
948 aboutbox(void)
949 {
950 static GtkWidget *aboutbox;
951
952 if (aboutbox != NULL)
953 return;
954
955 aboutbox = xmms_show_message(_("About MPEG Audio Plugin"),
956 _("Audacious decoding engine by William Pitcock <nenolod@nenolod.net>, derived from:\n"
957 "mpg123 decoding engine by Michael Hipp <mh@mpg123.de>\n"
958 "Derived partially from mpg123 0.59s.mc3 as well.\n"
959 "Based on the original XMMS plugin."),
960 _("Ok"),
961 FALSE, NULL, NULL);
962
963 g_signal_connect(G_OBJECT(aboutbox), "destroy",
964 G_CALLBACK(gtk_widget_destroyed), &aboutbox);
965 }
966
967 InputPlugin mpgdec_ip = {
968 NULL,
969 NULL,
970 NULL, /* Description */
971 init,
972 aboutbox,
973 mpgdec_configure,
974 is_our_file,
975 NULL,
976 play_file,
977 stop,
978 do_pause,
979 seek,
980 NULL,
981 get_time,
982 NULL, NULL,
983 cleanup,
984 NULL,
985 NULL, NULL, NULL,
986 get_song_info,
987 mpgdec_file_info_box, /* file_info_box */
988 NULL,
989 get_song_tuple
990 };
991
992 InputPlugin *
993 get_iplugin_info(void)
994 {
995 mpgdec_ip.description = g_strdup_printf(_("MPEG Audio Plugin"));
996 return &mpgdec_ip;
997 }