Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | pj | 1 | /* |
2 | * Mpeg Layer audio decoder (see version.h for version number) |
||
3 | * ------------------------ |
||
4 | * copyright (c) 1995,1996,1997 by Michael Hipp, All rights reserved. |
||
5 | * See also 'README' ! |
||
6 | * |
||
7 | */ |
||
8 | |||
9 | #include <stdlib.h> |
||
10 | #include <sys/types.h> |
||
11 | #include <sys/wait.h> |
||
12 | #include <sys/time.h> |
||
13 | #include <sys/resource.h> |
||
14 | |||
15 | /* #define SET_PRIO */ |
||
16 | |||
17 | #include "mpg123.h" |
||
18 | #include "getlopt.h" |
||
19 | |||
20 | #include "version.h" |
||
21 | |||
22 | static void usage(char *dummy); |
||
23 | static void print_title(void); |
||
24 | |||
25 | static long rates[3][3] = { |
||
26 | { 32000,44100,48000 } , |
||
27 | { 16000,22050,24000 } , |
||
28 | { 8000,11025,12000 } |
||
29 | }; |
||
30 | |||
31 | int supported_rates = 0; |
||
32 | |||
33 | int outmode = DECODE_AUDIO; |
||
34 | |||
35 | char *listname = NULL; |
||
36 | long outscale = 32768; |
||
37 | int checkrange = FALSE; |
||
38 | int tryresync = TRUE; |
||
39 | int quiet = FALSE; |
||
40 | int verbose = 0; |
||
41 | int doublespeed= 0; |
||
42 | int halfspeed = 0; |
||
43 | int shuffle = 0; |
||
44 | int change_always = 1; |
||
45 | int force_8bit = 0; |
||
46 | int force_frequency = -1; |
||
47 | long numframes = -1; |
||
48 | long startFrame= 0; |
||
49 | int usebuffer = 0; |
||
50 | int frontend_type = 0; |
||
51 | int remote = 0; |
||
52 | int buffer_fd[2]; |
||
53 | int buffer_pid; |
||
54 | |||
55 | static void catch_child(void) |
||
56 | { |
||
57 | while (waitpid(-1, NULL, WNOHANG) > 0); |
||
58 | } |
||
59 | |||
60 | static int intflag = FALSE; |
||
61 | static int remflag = FALSE; |
||
62 | |||
63 | static void catch_interrupt(void) |
||
64 | { |
||
65 | intflag = TRUE; |
||
66 | } |
||
67 | |||
68 | static char remote_buffer[1024]; |
||
69 | static struct frame fr; |
||
70 | static struct audio_info_struct ai; |
||
71 | txfermem *buffermem; |
||
72 | #define FRAMEBUFUNIT (18 * 64 * 4) |
||
73 | |||
74 | void print_rheader(struct frame *fr); |
||
75 | |||
76 | static void catch_remote(void) |
||
77 | { |
||
78 | remflag = TRUE; |
||
79 | intflag = TRUE; |
||
80 | if(usebuffer) |
||
81 | kill(buffer_pid,SIGINT); |
||
82 | } |
||
83 | |||
84 | |||
85 | char *handle_remote(void) |
||
86 | { |
||
87 | switch(frontend_type) { |
||
88 | case FRONTEND_SAJBER: |
||
89 | #ifdef FRONTEND |
||
90 | control_sajber(&fr); |
||
91 | #endif |
||
92 | break; |
||
93 | case FRONTEND_TK3PLAY: |
||
94 | #ifdef FRONTEND |
||
95 | control_tk3play(&fr); |
||
96 | #endif |
||
97 | break; |
||
98 | default: |
||
99 | fgets(remote_buffer,1024,stdin); |
||
100 | remote_buffer[strlen(remote_buffer)-1]=0; |
||
101 | |||
102 | switch(remote_buffer[0]) { |
||
103 | case 'P': |
||
104 | return remote_buffer+1; |
||
105 | } |
||
106 | |||
107 | if(usebuffer) |
||
108 | kill(buffer_pid,SIGINT); |
||
109 | break; |
||
110 | } |
||
111 | |||
112 | return NULL; |
||
113 | } |
||
114 | |||
115 | void init_output(void) |
||
116 | { |
||
117 | static int init_done = FALSE; |
||
118 | |||
119 | if (init_done) |
||
120 | return; |
||
121 | init_done = TRUE; |
||
122 | #ifndef OS2 |
||
123 | if (usebuffer) { |
||
124 | unsigned int bufferbytes; |
||
125 | sigset_t newsigset, oldsigset; |
||
126 | |||
127 | if (usebuffer < 32) |
||
128 | usebuffer = 32; /* minimum is 32 Kbytes! */ |
||
129 | bufferbytes = (usebuffer * 1024); |
||
130 | bufferbytes -= bufferbytes % FRAMEBUFUNIT; |
||
131 | xfermem_init (&buffermem, bufferbytes, sizeof(ai.rate)); |
||
132 | pcm_sample = (unsigned char *) buffermem->data; |
||
133 | pcm_point = 0; |
||
134 | sigemptyset (&newsigset); |
||
135 | sigaddset (&newsigset, SIGUSR1); |
||
136 | sigprocmask (SIG_BLOCK, &newsigset, &oldsigset); |
||
137 | catchsignal (SIGCHLD, catch_child); |
||
138 | switch ((buffer_pid = fork())) { |
||
139 | case -1: /* error */ |
||
140 | perror("fork()"); |
||
141 | exit(1); |
||
142 | case 0: /* child */ |
||
143 | xfermem_init_reader (buffermem); |
||
144 | buffer_loop (&ai, &oldsigset); |
||
145 | xfermem_done_reader (buffermem); |
||
146 | xfermem_done (buffermem); |
||
147 | _exit(0); |
||
148 | default: /* parent */ |
||
149 | xfermem_init_writer (buffermem); |
||
150 | outmode = DECODE_BUFFER; |
||
151 | } |
||
152 | } |
||
153 | else { |
||
154 | #endif |
||
155 | if (!(pcm_sample = (unsigned char *) malloc(audiobufsize * 2))) { |
||
156 | perror ("malloc()"); |
||
157 | exit (1); |
||
158 | #ifndef OS2 |
||
159 | } |
||
160 | #endif |
||
161 | } |
||
162 | |||
163 | if(outmode==DECODE_AUDIO) { |
||
164 | if(audio_open(&ai) < 0) { |
||
165 | perror("audio"); |
||
166 | exit(1); |
||
167 | } |
||
168 | /* audio_set_rate (&ai); should already be done in audio_open() [OF] */ |
||
169 | } |
||
170 | } |
||
171 | |||
172 | char *get_next_file (int argc, char *argv[]) |
||
173 | { |
||
174 | static FILE *listfile = NULL; |
||
175 | static char line[1024]; |
||
176 | |||
177 | #ifdef SHUFFLESUPPORT |
||
178 | static int ord[2048]; |
||
179 | int temp, randomized,pos; |
||
180 | static char initialized=0; |
||
181 | time_t t; |
||
182 | #endif |
||
183 | |||
184 | if (remote) |
||
185 | return handle_remote(); |
||
186 | |||
187 | if (listname || listfile) { |
||
188 | if (!listfile) { |
||
189 | if (!*listname || !strcmp(listname, "-")) { |
||
190 | listfile = stdin; |
||
191 | listname = NULL; |
||
192 | } |
||
193 | else if (!strncmp(listname, "http://", 7)) |
||
194 | listfile = http_open(listname); |
||
195 | else if (!(listfile = fopen(listname, "rb"))) { |
||
196 | perror (listname); |
||
197 | exit (1); |
||
198 | } |
||
199 | if (verbose) |
||
200 | fprintf (stderr, "Using playlist from %s ...\n", |
||
201 | listname ? listname : "standard input"); |
||
202 | } |
||
203 | do { |
||
204 | if (fgets(line, 1023, listfile)) { |
||
205 | line[strcspn(line, "\t\n\r")] = '\0'; |
||
206 | if (line[0]=='\0' || line[0]=='#') |
||
207 | continue; |
||
208 | return (line); |
||
209 | } |
||
210 | else { |
||
211 | if (*listname) |
||
212 | fclose (listfile); |
||
213 | listname = NULL; |
||
214 | listfile = NULL; |
||
215 | } |
||
216 | } while (listfile); |
||
217 | } |
||
218 | |||
219 | #ifdef SHUFFLESUPPORT |
||
220 | if(!initialized){ |
||
221 | for(pos=0;pos<=argc; pos++) ord[pos]=pos; |
||
222 | initialized=1; |
||
223 | } |
||
224 | if(shuffle){ |
||
225 | fprintf(stderr, "\nShuffle play - %u file(s) in loop.\n", argc-loptind); |
||
226 | srandom(time(&t)); |
||
227 | for(pos=loptind;pos<argc;pos++){ |
||
228 | randomized=(random()%(argc-pos))+pos; |
||
229 | temp=ord[pos]; |
||
230 | ord[pos]=ord[randomized]; |
||
231 | ord[randomized]=temp; |
||
232 | } |
||
233 | shuffle=0; |
||
234 | } |
||
235 | if (loptind < argc) |
||
236 | return (argv[ord[loptind++]]); |
||
237 | return (NULL); |
||
238 | #else |
||
239 | if (loptind < argc) |
||
240 | return (argv[loptind++]); |
||
241 | return (NULL); |
||
242 | #endif |
||
243 | } |
||
244 | |||
245 | void set_synth (char *arg) |
||
246 | { |
||
247 | if (*arg == '2') { |
||
248 | fr.down_sample = 1; |
||
249 | } |
||
250 | else { |
||
251 | fr.down_sample = 2; |
||
252 | } |
||
253 | } |
||
254 | |||
255 | #ifdef VARMODESUPPORT |
||
256 | void set_varmode (char *arg) |
||
257 | { |
||
258 | audiobufsize = ((audiobufsize >> 1) + 63) & 0xffffc0; |
||
259 | } |
||
260 | #endif |
||
261 | |||
262 | void set_output (char *arg) |
||
263 | { |
||
264 | switch (*arg) { |
||
265 | case 'h': ai.output = AUDIO_OUT_HEADPHONES; break; |
||
266 | case 's': ai.output = AUDIO_OUT_INTERNAL_SPEAKER; break; |
||
267 | case 'l': ai.output = AUDIO_OUT_LINE_OUT; break; |
||
268 | default: |
||
269 | fprintf (stderr, "%s: Unknown argument \"%s\" to option \"%s\".\n", |
||
270 | prgName, arg, loptarg); |
||
271 | exit (1); |
||
272 | } |
||
273 | } |
||
274 | |||
275 | void set_verbose (char *arg) |
||
276 | { |
||
277 | verbose++; |
||
278 | } |
||
279 | |||
280 | topt opts[] = { |
||
281 | {'k', "skip", GLO_ARG | GLO_NUM, 0, &startFrame, 0}, |
||
282 | {'a', "audiodevice", GLO_ARG | GLO_CHAR, 0, &ai.device, 0}, |
||
283 | {'2', "2to1", 0, set_synth, 0, 0}, |
||
284 | {'4', "4to1", 0, set_synth, 0, 0}, |
||
285 | {'t', "test", 0, 0, &outmode, DECODE_TEST}, |
||
286 | {'s', "stdout", 0, 0, &outmode, DECODE_STDOUT}, |
||
287 | {'c', "check", 0, 0, &checkrange, TRUE}, |
||
288 | {'v', "verbose", 0, set_verbose, 0, 0}, |
||
289 | {'q', "quiet", 0, 0, &quiet, TRUE}, |
||
290 | {'y', "resync", 0, 0, &tryresync, FALSE}, |
||
291 | {'0', "single0", 0, 0, &fr.single, 0}, |
||
292 | {0, "left", 0, 0, &fr.single, 0}, |
||
293 | {'1', "single1", 0, 0, &fr.single, 1}, |
||
294 | {0, "right", 0, 0, &fr.single, 1}, |
||
295 | {'m', "singlemix", 0, 0, &fr.single, 3}, |
||
296 | {0, "mix", 0, 0, &fr.single, 3}, |
||
297 | {'g', "gain", GLO_ARG | GLO_NUM, 0, &ai.gain, 0}, |
||
298 | {'r', "rate", GLO_ARG | GLO_NUM, 0, &force_frequency, 0}, |
||
299 | {0, "8bit", 0, 0, &force_8bit, 1}, |
||
300 | {0, "headphones", 0, 0, &ai.output, AUDIO_OUT_HEADPHONES}, |
||
301 | {0, "speaker", 0, 0, &ai.output, AUDIO_OUT_INTERNAL_SPEAKER}, |
||
302 | {0, "lineout", 0, 0, &ai.output, AUDIO_OUT_LINE_OUT}, |
||
303 | {'o', "output", GLO_ARG | GLO_CHAR, set_output, 0, 0}, |
||
304 | {'f', "scale", GLO_ARG | GLO_NUM, 0, &outscale, 0}, |
||
305 | {'n', "frames", GLO_ARG | GLO_NUM, 0, &numframes, 0}, |
||
306 | #ifdef VARMODESUPPORT |
||
307 | {'v', "var", 0, set_varmode, &varmode, TRUE}, |
||
308 | #endif |
||
309 | {'b', "buffer", GLO_ARG | GLO_NUM, 0, &usebuffer, 0}, |
||
310 | {'R', "remote", 0, 0, &remote, TRUE}, |
||
311 | {'d', "doublespeed", GLO_ARG | GLO_NUM, 0, &doublespeed,0}, |
||
312 | {'h', "halfspeed", GLO_ARG | GLO_NUM, 0, &halfspeed, 0}, |
||
313 | {'p', "proxy", GLO_ARG | GLO_CHAR, 0, &proxyurl, 0}, |
||
314 | {'@', "list", GLO_ARG | GLO_CHAR, 0, &listname, 0}, |
||
315 | #ifdef SHUFFLESUPPORT |
||
316 | /* 'z' comes from the the german word 'zufall' (eng: random) */ |
||
317 | {'z', "shuffle", 0, 0, &shuffle, 1}, |
||
318 | #endif |
||
319 | {'?', "help", 0, usage, 0, 0}, |
||
320 | {0, 0, 0, 0, 0, 0} |
||
321 | }; |
||
322 | |||
323 | /* |
||
324 | * Change the playback sample rate. |
||
325 | */ |
||
326 | static void reset_audio_samplerate(void) |
||
327 | { |
||
328 | if (usebuffer) { |
||
329 | /* wait until the buffer is empty, |
||
330 | * then tell the buffer process to |
||
331 | * change the sample rate. [OF] |
||
332 | */ |
||
333 | while (xfermem_get_usedspace(buffermem) > 0) |
||
334 | if (xfermem_block(XF_WRITER, buffermem) == XF_CMD_TERMINATE) { |
||
335 | intflag = TRUE; |
||
336 | break; |
||
337 | } |
||
338 | buffermem->freeindex = -1; |
||
339 | buffermem->readindex = 0; /* I know what I'm doing! ;-) */ |
||
340 | buffermem->freeindex = 0; |
||
341 | if (intflag) |
||
342 | return; |
||
343 | memcpy (buffermem->metadata, &ai.rate, sizeof(ai.rate)); |
||
344 | kill (buffer_pid, SIGUSR1); |
||
345 | } |
||
346 | else if (outmode == DECODE_AUDIO) { |
||
347 | /* audio_reset_parameters(&ai); */ |
||
348 | /* close and re-open in order to flush |
||
349 | * the device's internal buffer before |
||
350 | * changing the sample rate. [OF] |
||
351 | */ |
||
352 | audio_close (&ai); |
||
353 | if (audio_open(&ai) < 0) { |
||
354 | perror("audio"); |
||
355 | exit(1); |
||
356 | } |
||
357 | } |
||
358 | } |
||
359 | |||
360 | /* |
||
361 | * play a frame read read_frame(); |
||
362 | * (re)initialize audio if necessary. |
||
363 | */ |
||
364 | void play_frame(int init,struct frame *fr) |
||
365 | { |
||
366 | int clip; |
||
367 | |||
368 | if((fr->header_change && change_always) || init) { |
||
369 | int reset_audio = 0; |
||
370 | |||
371 | if(remote) |
||
372 | print_rheader(fr); |
||
373 | |||
374 | if (!quiet && init) |
||
375 | if (verbose) |
||
376 | print_header(fr); |
||
377 | else |
||
378 | print_header_compact(fr); |
||
379 | |||
380 | if(force_frequency < 0) { |
||
381 | if(ai.rate != freqs[fr->sampling_frequency]>>(fr->down_sample)) { |
||
382 | ai.rate = freqs[fr->sampling_frequency]>>(fr->down_sample); |
||
383 | reset_audio = 1; |
||
384 | } |
||
385 | } |
||
386 | else if(ai.rate != force_frequency) { |
||
387 | ai.rate = force_frequency; |
||
388 | reset_audio = 1; |
||
389 | } |
||
390 | init_output(); |
||
391 | if(reset_audio) { |
||
392 | reset_audio_samplerate(); |
||
393 | if (intflag) |
||
394 | return; |
||
395 | } |
||
396 | } |
||
397 | |||
398 | if (fr->error_protection) { |
||
399 | getbits(16); /* crc */ |
||
400 | } |
||
401 | |||
402 | clip = (fr->do_layer)(fr,outmode,&ai); |
||
403 | |||
404 | #ifndef OS2 |
||
405 | if (usebuffer) { |
||
406 | if (!intflag) { |
||
407 | buffermem->freeindex = |
||
408 | (buffermem->freeindex + pcm_point) % buffermem->size; |
||
409 | if (buffermem->wakeme[XF_READER]) |
||
410 | xfermem_putcmd(buffermem->fd[XF_WRITER], XF_CMD_WAKEUP); |
||
411 | } |
||
412 | pcm_sample = (unsigned char *) (buffermem->data + buffermem->freeindex); |
||
413 | pcm_point = 0; |
||
414 | while (xfermem_get_freespace(buffermem) < (FRAMEBUFUNIT << 1)) |
||
415 | if (xfermem_block(XF_WRITER, buffermem) == XF_CMD_TERMINATE) { |
||
416 | intflag = TRUE; |
||
417 | break; |
||
418 | } |
||
419 | if (intflag) |
||
420 | return; |
||
421 | } |
||
422 | #endif |
||
423 | |||
424 | if(clip > 0 && checkrange) |
||
425 | fprintf(stderr,"%d samples clipped\n", clip); |
||
426 | } |
||
427 | |||
428 | |||
429 | int main(int argc, char *argv[]) |
||
430 | { |
||
431 | int result; |
||
432 | unsigned long frameNum = 0; |
||
433 | char *fname; |
||
434 | struct timeval start_time, now; |
||
435 | unsigned long secdiff; |
||
436 | int init; |
||
437 | |||
438 | #ifdef OS2 |
||
439 | _wildcard(&argc,&argv); |
||
440 | #endif |
||
441 | |||
442 | #ifdef SET_PRIO |
||
443 | int mypid = getpid(); |
||
444 | setpriority(PRIO_PROCESS,mypid,-20); |
||
445 | #endif |
||
446 | |||
447 | if(!strcmp("sajberplay",argv[0])) |
||
448 | frontend_type = FRONTEND_SAJBER; |
||
449 | if(!strcmp("mpg123m",argv[0])) |
||
450 | frontend_type = FRONTEND_TK3PLAY; |
||
451 | |||
452 | fr.single = -1; /* both channels */ |
||
453 | fr.synth = synth_1to1; |
||
454 | fr.down_sample = 0; |
||
455 | |||
456 | ai.format = AUDIO_FORMAT_SIGNED_16; |
||
457 | ai.gain = ai.rate = ai.output = -1; |
||
458 | ai.device = NULL; |
||
459 | ai.channels = 2; |
||
460 | |||
461 | (prgName = strrchr(argv[0], '/')) ? prgName++ : (prgName = argv[0]); |
||
462 | |||
463 | while ((result = getlopt(argc, argv, opts))) |
||
464 | switch (result) { |
||
465 | case GLO_UNKNOWN: |
||
466 | fprintf (stderr, "%s: Unknown option \"%s\".\n", prgName, loptarg); |
||
467 | exit (1); |
||
468 | case GLO_NOARG: |
||
469 | fprintf (stderr, "%s: Missing argument for option \"%s\".\n", |
||
470 | prgName, loptarg); |
||
471 | exit (1); |
||
472 | } |
||
473 | if (loptind >= argc && !listname && !frontend_type) |
||
474 | usage(NULL); |
||
475 | |||
476 | if (remote){ |
||
477 | verbose = 0; |
||
478 | quiet = 1; |
||
479 | catchsignal(SIGUSR1, catch_remote); |
||
480 | fprintf(stderr,"@R MPG123\n"); |
||
481 | } |
||
482 | |||
483 | if (!quiet) |
||
484 | print_title(); |
||
485 | |||
486 | |||
487 | { |
||
488 | int fmts; |
||
489 | int i,j; |
||
490 | |||
491 | struct audio_info_struct ai; |
||
492 | |||
493 | audio_info_struct_init(&ai); |
||
494 | if (outmode == DECODE_AUDIO) { |
||
495 | audio_open(&ai); |
||
496 | fmts = audio_get_formats(&ai); |
||
497 | } |
||
498 | else |
||
499 | fmts = AUDIO_FORMAT_SIGNED_16; |
||
500 | |||
501 | supported_rates = 0; |
||
502 | for(i=0;i<3;i++) { |
||
503 | for(j=0;j<3;j++) { |
||
504 | ai.rate = rates[i][j]; |
||
505 | if (outmode == DECODE_AUDIO) |
||
506 | audio_rate_best_match(&ai); |
||
507 | /* allow about 2% difference */ |
||
508 | if( ((rates[i][j]*98) < (ai.rate*100)) && |
||
509 | ((rates[i][j]*102) > (ai.rate*100)) ) |
||
510 | supported_rates |= 1<<(i*3+j); |
||
511 | } |
||
512 | } |
||
513 | |||
514 | if (outmode == DECODE_AUDIO) |
||
515 | audio_close(&ai); |
||
516 | |||
517 | if(!force_8bit && !(fmts & AUDIO_FORMAT_SIGNED_16)) |
||
518 | force_8bit = 1; |
||
519 | |||
520 | if(force_8bit && !(fmts & AUDIO_FORMAT_ULAW_8)) { |
||
521 | fprintf(stderr,"No supported audio format found!\n"); |
||
522 | exit(1); |
||
523 | } |
||
524 | } |
||
525 | |||
526 | if(force_8bit) { |
||
527 | #if 0 |
||
528 | ai.format = AUDIO_FORMAT_UNSIGNED_8; |
||
529 | ai.format = AUDIO_FORMAT_SIGNED_8; |
||
530 | #endif |
||
531 | ai.format = AUDIO_FORMAT_ULAW_8; |
||
532 | make_conv16to8_table(ai.format); |
||
533 | switch(fr.down_sample) { |
||
534 | case 0: |
||
535 | fr.synth = synth_1to1_8bit; |
||
536 | fr.synth_mono = synth_1to1_8bit_mono; |
||
537 | fr.block_size = 64; |
||
538 | break; |
||
539 | case 1: |
||
540 | fr.synth = synth_2to1_8bit; |
||
541 | fr.synth_mono = synth_2to1_8bit_mono; |
||
542 | fr.block_size = 32; |
||
543 | break; |
||
544 | case 2: |
||
545 | fr.synth = synth_4to1_8bit; |
||
546 | fr.synth_mono = synth_4to1_8bit_mono; |
||
547 | fr.block_size = 16; |
||
548 | break; |
||
549 | } |
||
550 | } |
||
551 | else { |
||
552 | switch(fr.down_sample) { |
||
553 | case 0: |
||
554 | fr.synth = synth_1to1; |
||
555 | fr.synth_mono = synth_1to1_mono; |
||
556 | fr.block_size = 128; |
||
557 | break; |
||
558 | case 1: |
||
559 | fr.synth = synth_2to1; |
||
560 | fr.synth_mono = synth_2to1_mono; |
||
561 | fr.block_size = 64; |
||
562 | break; |
||
563 | case 2: |
||
564 | fr.synth = synth_4to1; |
||
565 | fr.synth_mono = synth_4to1_mono; |
||
566 | fr.block_size = 32; |
||
567 | break; |
||
568 | } |
||
569 | } |
||
570 | |||
571 | make_decode_tables(outscale); |
||
572 | init_layer2(); /* inits also shared tables with layer1 */ |
||
573 | init_layer3(fr.down_sample); |
||
574 | catchsignal (SIGINT, catch_interrupt); |
||
575 | |||
576 | if(frontend_type) { |
||
577 | handle_remote(); |
||
578 | exit(0); |
||
579 | } |
||
580 | |||
581 | while ((fname = get_next_file(argc, argv))) { |
||
582 | char *dirname, *filename; |
||
583 | |||
584 | if(!*fname || !strcmp(fname, "-")) |
||
585 | fname = NULL; |
||
586 | open_stream(fname,-1); |
||
587 | |||
588 | if (!quiet) { |
||
589 | if (split_dir_file(fname ? fname : "standard input", |
||
590 | &dirname, &filename)) |
||
591 | fprintf(stderr, "\nDirectory: %s", dirname); |
||
592 | fprintf(stderr, "\nPlaying MPEG stream from %s ...\n", filename); |
||
593 | } |
||
594 | |||
595 | gettimeofday (&start_time, NULL); |
||
596 | read_frame_init(); |
||
597 | |||
598 | init = 1; |
||
599 | for(frameNum=0;read_frame(&fr) && numframes && !intflag;frameNum++) { |
||
600 | if(frameNum < startFrame || (doublespeed && (frameNum % doublespeed))) { |
||
601 | if(fr.lay == 3) |
||
602 | set_pointer(512); |
||
603 | continue; |
||
604 | } |
||
605 | numframes--; |
||
606 | play_frame(init,&fr); |
||
607 | init = 0; |
||
608 | if(verbose) { |
||
609 | if (verbose > 1 || !(frameNum & 0xf)) |
||
610 | fprintf(stderr, "\r{%4lu} ",frameNum); |
||
611 | #ifndef OS2 |
||
612 | if (verbose > 1 && usebuffer) |
||
613 | fprintf (stderr, "%7d ", xfermem_get_usedspace(buffermem)); |
||
614 | #endif |
||
615 | } |
||
616 | |||
617 | } |
||
618 | |||
619 | close_stream(); |
||
620 | if (!quiet) { |
||
621 | /* This formula seems to work at least for |
||
622 | * MPEG 1.0/2.0 layer 3 streams. |
||
623 | */ |
||
624 | int sfd = freqs[fr.sampling_frequency] * (fr.lsf + 1); |
||
625 | int secs = (frameNum * (fr.lay==1 ? 384 : 1152) + sfd / 2) / sfd; |
||
626 | fprintf(stderr,"[%d:%02d] Decoding of %s finished.\n", secs / 60, |
||
627 | secs % 60, filename); |
||
628 | } |
||
629 | |||
630 | if(remote) |
||
631 | fprintf(stderr,"@R MPG123\n"); |
||
632 | if (remflag) { |
||
633 | intflag = FALSE; |
||
634 | remflag = FALSE; |
||
635 | } |
||
636 | |||
637 | if (intflag) { |
||
638 | gettimeofday (&now, NULL); |
||
639 | secdiff = (now.tv_sec - start_time.tv_sec) * 1000; |
||
640 | if (now.tv_usec >= start_time.tv_usec) |
||
641 | secdiff += (now.tv_usec - start_time.tv_usec) / 1000; |
||
642 | else |
||
643 | secdiff -= (start_time.tv_usec - now.tv_usec) / 1000; |
||
644 | if (secdiff < 1000) |
||
645 | break; |
||
646 | intflag = FALSE; |
||
647 | } |
||
648 | } |
||
649 | #ifndef OS2 |
||
650 | if (usebuffer) { |
||
651 | xfermem_done_writer (buffermem); |
||
652 | waitpid (buffer_pid, NULL, 0); |
||
653 | xfermem_done (buffermem); |
||
654 | } |
||
655 | else { |
||
656 | #endif |
||
657 | audio_flush(outmode, &ai); |
||
658 | free (pcm_sample); |
||
659 | #ifndef OS2 |
||
660 | } |
||
661 | #endif |
||
662 | |||
663 | if(outmode==DECODE_AUDIO) |
||
664 | audio_close(&ai); |
||
665 | exit( 0 ); |
||
666 | } |
||
667 | |||
668 | static void print_title(void) |
||
669 | { |
||
670 | fprintf(stderr,"High Performance MPEG 1.0/2.0 Audio Player for Layer 1, 2 and 3.\n"); |
||
671 | fprintf(stderr,"Version %s (%s). Written and copyrights by Michael Hipp.\n", prgVersion, prgDate); |
||
672 | fprintf(stderr,"Uses code from various people. See 'README' for more!\n"); |
||
673 | fprintf(stderr,"THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! USE AT YOUR OWN RISK!\n"); |
||
674 | } |
||
675 | |||
676 | static void usage(char *dummy) /* print syntax & exit */ |
||
677 | { |
||
678 | print_title(); |
||
679 | fprintf(stderr,"\nusage: %s [option(s)] [file(s) | URL(s) | -]\n", prgName); |
||
680 | fprintf(stderr,"supported options [defaults in brackets]:\n"); |
||
681 | fprintf(stderr," -v increase verbosity level -q quiet (don't print title)\n"); |
||
682 | fprintf(stderr," -t testmode (no output) -s write to stdout\n"); |
||
683 | fprintf(stderr," -k n skip first n frames [0] -n n decode only n frames [all]\n"); |
||
684 | fprintf(stderr," -c check range violations -y DISABLE resync on errors\n"); |
||
685 | fprintf(stderr," -b n output buffer: n Kbytes [0] -f n change scalefactor [32768]\n"); |
||
686 | fprintf(stderr," -r n override samplerate [auto] -g n set audio hardware output gain\n"); |
||
687 | fprintf(stderr," -os output to built-in speaker -oh output to headphones\n"); |
||
688 | fprintf(stderr," -ol output to line-out connector -a d set audio device\n"); |
||
689 | fprintf(stderr," -2 downsample 1:2 (22 kHz) -4 downsample 1:4 (11 kHz)\n"); |
||
690 | fprintf(stderr," -d n play every n'th frame only -h n play every frame n times\n"); |
||
691 | fprintf(stderr," -0 decode channel 0 (left) only -1 decode channel 1 (right) only\n"); |
||
692 | fprintf(stderr," -m mix both channels (mono) -p p use HTTP proxy p [$HTTP_PROXY]\n"); |
||
693 | fprintf(stderr," -@ f read filenames/URLs from f -z shuffle play (with wildcards)\n"); |
||
694 | fprintf(stderr,"See the manpage %s(1) for more information.\n", prgName); |
||
695 | exit(1); |
||
696 | } |
||
697 | |||
698 |