Subversion Repositories shark

Rev

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