~ubuntu-branches/ubuntu/lucid/mpg123/lucid

« back to all changes in this revision

Viewing changes to src/mpg123.c

Tags: upstream-0.60
ImportĀ upstreamĀ versionĀ 0.60

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
        mpg123: main code of the program (not of the decoder...)
 
3
 
 
4
        copyright 1995-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
 
5
        see COPYING and AUTHORS files in distribution or http://mpg123.de
 
6
        initially written by Michael Hipp
 
7
*/
 
8
 
 
9
#include "config.h"
 
10
#include "debug.h"
 
11
#define ME "main"
 
12
 
 
13
#include <stdlib.h>
 
14
#include <sys/types.h>
 
15
#if !defined(WIN32) && !defined(GENERIC)
 
16
#include <sys/wait.h>
 
17
#include <sys/time.h>
 
18
#include <sys/resource.h>
 
19
#endif
 
20
 
 
21
#include <errno.h>
 
22
#include <string.h>
 
23
#include <fcntl.h>
 
24
#include <time.h>
 
25
 
 
26
#ifdef HAVE_SCHED_H
 
27
#include <sched.h>
 
28
#endif
 
29
 
 
30
#include "mpg123.h"
 
31
#include "getlopt.h"
 
32
#include "buffer.h"
 
33
#include "term.h"
 
34
#ifdef GAPLESS
 
35
#include "layer3.h"
 
36
#endif
 
37
#include "playlist.h"
 
38
#include "id3.h"
 
39
 
 
40
static void usage(int err);
 
41
static void want_usage(char* arg);
 
42
static void long_usage(int err);
 
43
static void want_long_usage(char* arg);
 
44
static void print_title(FILE* o);
 
45
static void give_version(char* arg);
 
46
 
 
47
struct parameter param = { 
 
48
  FALSE , /* aggressiv */
 
49
  FALSE , /* shuffle */
 
50
  FALSE , /* remote */
 
51
  FALSE , /* remote to stderr */
 
52
  DECODE_AUDIO , /* write samples to audio device */
 
53
  FALSE , /* silent operation */
 
54
  FALSE , /* xterm title on/off */
 
55
  0 ,     /* second level buffer size */
 
56
  TRUE ,  /* resync after stream error */
 
57
  0 ,     /* verbose level */
 
58
#ifdef HAVE_TERMIOS
 
59
  FALSE , /* term control */
 
60
#endif
 
61
  -1 ,     /* force mono */
 
62
  0 ,     /* force stereo */
 
63
  0 ,     /* force 8bit */
 
64
  0 ,     /* force rate */
 
65
  0 ,     /* down sample */
 
66
  FALSE , /* checkrange */
 
67
  0 ,     /* doublespeed */
 
68
  0 ,     /* halfspeed */
 
69
  0 ,     /* force_reopen, always (re)opens audio device for next song */
 
70
#ifdef USE_3DNOW
 
71
  0 ,     /* autodetect from CPUFLAGS */
 
72
  FALSE , /* normal operation */
 
73
#endif
 
74
  FALSE,  /* try to run process in 'realtime mode' */   
 
75
  { 0,},  /* wav,cdr,au Filename */
 
76
#ifdef GAPLESS
 
77
        0, /* gapless off per default - yet */
 
78
#endif
 
79
        0, /* default is to play all titles in playlist */
 
80
        -1, /* do not use rva per default */
 
81
        NULL /* no playlist per default */
 
82
};
 
83
 
 
84
char *prgName = NULL;
 
85
char *equalfile = NULL;
 
86
/* ThOr: pointers are not TRUE or FALSE */
 
87
int have_eq_settings = FALSE;
 
88
long outscale  = MAXOUTBURST;
 
89
long numframes = -1;
 
90
long startFrame= 0;
 
91
int buffer_fd[2];
 
92
int buffer_pid;
 
93
 
 
94
static int intflag = FALSE;
 
95
 
 
96
int OutputDescriptor;
 
97
 
 
98
#if !defined(WIN32) && !defined(GENERIC)
 
99
static void catch_child(void)
 
100
{
 
101
  while (waitpid(-1, NULL, WNOHANG) > 0);
 
102
}
 
103
 
 
104
static void catch_interrupt(void)
 
105
{
 
106
  intflag = TRUE;
 
107
}
 
108
#endif
 
109
 
 
110
/* oh, what a mess... */
 
111
void next_track(void)
 
112
{
 
113
        intflag = TRUE;
 
114
}
 
115
 
 
116
static struct frame fr;
 
117
struct audio_info_struct ai,pre_ai;
 
118
txfermem *buffermem = NULL;
 
119
#define FRAMEBUFUNIT (18 * 64 * 4)
 
120
 
 
121
void set_synth_functions(struct frame *fr);
 
122
 
 
123
void init_output(void)
 
124
{
 
125
  static int init_done = FALSE;
 
126
 
 
127
  if (init_done)
 
128
    return;
 
129
  init_done = TRUE;
 
130
#ifndef NOXFERMEM
 
131
  /*
 
132
   * Only DECODE_AUDIO and DECODE_FILE are sanely handled by the
 
133
   * buffer process. For now, we just ignore the request
 
134
   * to buffer the output. [dk]
 
135
   */
 
136
  if (param.usebuffer && (param.outmode != DECODE_AUDIO) &&
 
137
      (param.outmode != DECODE_FILE)) {
 
138
    fprintf(stderr, "Sorry, won't buffer output unless writing plain audio.\n");
 
139
    param.usebuffer = 0;
 
140
  } 
 
141
  
 
142
  if (param.usebuffer) {
 
143
    unsigned int bufferbytes;
 
144
    sigset_t newsigset, oldsigset;
 
145
    if (param.usebuffer < 32)
 
146
      param.usebuffer = 32; /* minimum is 32 Kbytes! */
 
147
    bufferbytes = (param.usebuffer * 1024);
 
148
    bufferbytes -= bufferbytes % FRAMEBUFUNIT;
 
149
        /* +1024 for NtoM rounding problems */
 
150
    xfermem_init (&buffermem, bufferbytes ,0,1024);
 
151
    pcm_sample = (unsigned char *) buffermem->data;
 
152
    pcm_point = 0;
 
153
    sigemptyset (&newsigset);
 
154
    sigaddset (&newsigset, SIGUSR1);
 
155
    sigprocmask (SIG_BLOCK, &newsigset, &oldsigset);
 
156
    catchsignal (SIGCHLD, catch_child);
 
157
    switch ((buffer_pid = fork())) {
 
158
      case -1: /* error */
 
159
        perror("fork()");
 
160
#ifdef HAVE_TERMIOS
 
161
        if(param.term_ctrl)
 
162
                term_restore();
 
163
#endif
 
164
        exit(1);
 
165
      case 0: /* child */
 
166
        if(rd)
 
167
          rd->close(rd); /* child doesn't need the input stream */
 
168
        xfermem_init_reader (buffermem);
 
169
        buffer_loop (&ai, &oldsigset);
 
170
        xfermem_done_reader (buffermem);
 
171
        xfermem_done (buffermem);
 
172
        _exit(0);
 
173
      default: /* parent */
 
174
        xfermem_init_writer (buffermem);
 
175
        param.outmode = DECODE_BUFFER;
 
176
    }
 
177
  }
 
178
  else {
 
179
#endif
 
180
        /* + 1024 for NtoM rate converter */
 
181
    if (!(pcm_sample = (unsigned char *) malloc(audiobufsize * 2 + 1024))) {
 
182
      perror ("malloc()");
 
183
#ifdef HAVE_TERMIOS
 
184
      if(param.term_ctrl)
 
185
        term_restore();
 
186
#endif
 
187
      exit (1);
 
188
#ifndef NOXFERMEM
 
189
    }
 
190
#endif
 
191
  }
 
192
 
 
193
  switch(param.outmode) {
 
194
    case DECODE_AUDIO:
 
195
      if(audio_open(&ai) < 0) {
 
196
        perror("audio");
 
197
#ifdef HAVE_TERMIOS
 
198
        if(param.term_ctrl)
 
199
                term_restore();
 
200
#endif
 
201
        exit(1);
 
202
      }
 
203
      break;
 
204
    case DECODE_WAV:
 
205
      wav_open(&ai,param.filename);
 
206
      break;
 
207
    case DECODE_AU:
 
208
      au_open(&ai,param.filename);
 
209
      break;
 
210
    case DECODE_CDR:
 
211
      cdr_open(&ai,param.filename);
 
212
      break;
 
213
  }
 
214
}
 
215
 
 
216
static void set_output_h(char *a)
 
217
{
 
218
  if(ai.output <= 0)
 
219
    ai.output = AUDIO_OUT_HEADPHONES;
 
220
  else
 
221
    ai.output |= AUDIO_OUT_HEADPHONES;
 
222
}
 
223
static void set_output_s(char *a)
 
224
{
 
225
  if(ai.output <= 0)
 
226
    ai.output = AUDIO_OUT_INTERNAL_SPEAKER;
 
227
  else
 
228
    ai.output |= AUDIO_OUT_INTERNAL_SPEAKER;
 
229
}
 
230
static void set_output_l(char *a)
 
231
{
 
232
  if(ai.output <= 0)
 
233
    ai.output = AUDIO_OUT_LINE_OUT;
 
234
  else
 
235
    ai.output |= AUDIO_OUT_LINE_OUT;
 
236
}
 
237
 
 
238
static void set_output (char *arg)
 
239
{
 
240
    switch (*arg) {
 
241
        case 'h': set_output_h(arg); break;
 
242
        case 's': set_output_s(arg); break;
 
243
        case 'l': set_output_l(arg); break;
 
244
        default:
 
245
            fprintf (stderr, "%s: Unknown argument \"%s\" to option \"%s\".\n",
 
246
                prgName, arg, loptarg);
 
247
            exit (1);
 
248
    }
 
249
}
 
250
 
 
251
void set_verbose (char *arg)
 
252
{
 
253
    param.verbose++;
 
254
}
 
255
void set_wav(char *arg)
 
256
{
 
257
  param.outmode = DECODE_WAV;
 
258
  strncpy(param.filename,arg,255);
 
259
  param.filename[255] = 0;
 
260
}
 
261
void set_cdr(char *arg)
 
262
{
 
263
  param.outmode = DECODE_CDR;
 
264
  strncpy(param.filename,arg,255);
 
265
  param.filename[255] = 0;
 
266
}
 
267
void set_au(char *arg)
 
268
{
 
269
  param.outmode = DECODE_AU;
 
270
  strncpy(param.filename,arg,255);
 
271
  param.filename[255] = 0;
 
272
}
 
273
static void SetOutFile(char *Arg)
 
274
{
 
275
  param.outmode=DECODE_FILE;
 
276
  OutputDescriptor=open(Arg,O_WRONLY,0);
 
277
  if(OutputDescriptor==-1) {
 
278
    fprintf(stderr,"Can't open %s for writing (%s).\n",Arg,strerror(errno));
 
279
    exit(1);
 
280
  }
 
281
}
 
282
static void SetOutStdout(char *Arg)
 
283
{
 
284
  param.outmode=DECODE_FILE;
 
285
  OutputDescriptor=1;
 
286
}
 
287
static void SetOutStdout1(char *Arg)
 
288
{
 
289
  param.outmode=DECODE_AUDIOFILE;
 
290
  OutputDescriptor=1;
 
291
}
 
292
 
 
293
void realtime_not_compiled(char *arg)
 
294
{
 
295
  fprintf(stderr,"Option '-T / --realtime' not compiled into this binary.\n");
 
296
}
 
297
 
 
298
/* Please note: GLO_NUM expects point to LONG! */
 
299
/* ThOr:
 
300
 *  Yeah, and despite that numerous addresses to int variables were 
 
301
passed.
 
302
 *  That's not good on my Alpha machine with int=32bit and long=64bit!
 
303
 *  Introduced GLO_INT and GLO_LONG as different bits to make that clear.
 
304
 *  GLO_NUM no longer exists.
 
305
 */
 
306
topt opts[] = {
 
307
        {'k', "skip",        GLO_ARG | GLO_LONG, 0, &startFrame, 0},
 
308
        {'a', "audiodevice", GLO_ARG | GLO_CHAR, 0, &ai.device,  0},
 
309
        {'2', "2to1",        GLO_INT,  0, &param.down_sample, 1},
 
310
        {'4', "4to1",        GLO_INT,  0, &param.down_sample, 2},
 
311
        {'t', "test",        GLO_INT,  0, &param.outmode, DECODE_TEST},
 
312
        {'s', "stdout",      GLO_INT,  SetOutStdout, &param.outmode, DECODE_FILE},
 
313
        {'S', "STDOUT",      GLO_INT,  SetOutStdout1, &param.outmode,DECODE_AUDIOFILE},
 
314
        {'O', "outfile",     GLO_ARG | GLO_CHAR, SetOutFile, NULL, 0},
 
315
        {'c', "check",       GLO_INT,  0, &param.checkrange, TRUE},
 
316
        {'v', "verbose",     0,        set_verbose, 0,           0},
 
317
        {'q', "quiet",       GLO_INT,  0, &param.quiet, TRUE},
 
318
        {'y', "resync",      GLO_INT,  0, &param.tryresync, FALSE},
 
319
        {'0', "single0",     GLO_INT,  0, &param.force_mono, 0},
 
320
        {0,   "left",        GLO_INT,  0, &param.force_mono, 0},
 
321
        {'1', "single1",     GLO_INT,  0, &param.force_mono, 1},
 
322
        {0,   "right",       GLO_INT,  0, &param.force_mono, 1},
 
323
        {'m', "singlemix",   GLO_INT,  0, &param.force_mono, 3},
 
324
        {0,   "mix",         GLO_INT,  0, &param.force_mono, 3},
 
325
        {0,   "mono",        GLO_INT,  0, &param.force_mono, 3},
 
326
        {0,   "stereo",      GLO_INT,  0, &param.force_stereo, 1},
 
327
        {0,   "reopen",      GLO_INT,  0, &param.force_reopen, 1},
 
328
        {'g', "gain",        GLO_ARG | GLO_LONG, 0, &ai.gain,    0},
 
329
        {'r', "rate",        GLO_ARG | GLO_LONG, 0, &param.force_rate,  0},
 
330
        {0,   "8bit",        GLO_INT,  0, &param.force_8bit, 1},
 
331
        {0,   "headphones",  0,                  set_output_h, 0,0},
 
332
        {0,   "speaker",     0,                  set_output_s, 0,0},
 
333
        {0,   "lineout",     0,                  set_output_l, 0,0},
 
334
        {'o', "output",      GLO_ARG | GLO_CHAR, set_output, 0,  0},
 
335
        {'f', "scale",       GLO_ARG | GLO_LONG, 0, &outscale,   0},
 
336
        {'n', "frames",      GLO_ARG | GLO_LONG, 0, &numframes,  0},
 
337
        #ifdef HAVE_TERMIOS
 
338
        {'C', "control",     GLO_INT,  0, &param.term_ctrl, TRUE},
 
339
        #endif
 
340
        {'b', "buffer",      GLO_ARG | GLO_LONG, 0, &param.usebuffer,  0},
 
341
        {'R', "remote",      GLO_INT,  0, &param.remote, TRUE},
 
342
        {0,   "remote-err",  GLO_INT,  0, &param.remote_err, TRUE},
 
343
        {'d', "doublespeed", GLO_ARG | GLO_LONG, 0, &param.doublespeed,0},
 
344
        {'h', "halfspeed",   GLO_ARG | GLO_LONG, 0, &param.halfspeed,  0},
 
345
        {'p', "proxy",       GLO_ARG | GLO_CHAR, 0, &proxyurl,   0},
 
346
        {'@', "list",        GLO_ARG | GLO_CHAR, 0, &param.listname,   0},
 
347
        /* 'z' comes from the the german word 'zufall' (eng: random) */
 
348
        {'z', "shuffle",     GLO_INT,  0, &param.shuffle, 1},
 
349
        {'Z', "random",      GLO_INT,  0, &param.shuffle, 2},
 
350
        {'E', "equalizer",       GLO_ARG | GLO_CHAR, 0, &equalfile,1},
 
351
        #ifdef HAVE_SETPRIORITY
 
352
        {0,   "aggressive",      GLO_INT,  0, &param.aggressive, 2},
 
353
        #endif
 
354
        #ifdef USE_3DNOW
 
355
        {0,   "force-3dnow", GLO_INT,  0, &param.stat_3dnow, 1},
 
356
        {0,   "no-3dnow",    GLO_INT,  0, &param.stat_3dnow, 2},
 
357
        {0,   "test-3dnow",  GLO_INT,  0, &param.test_3dnow, TRUE},
 
358
        #endif
 
359
        #if !defined(WIN32) && !defined(GENERIC)
 
360
        {'u', "auth",        GLO_ARG | GLO_CHAR, 0, &httpauth,   0},
 
361
        #endif
 
362
        #ifdef HAVE_SCHED_SETSCHEDULER
 
363
        /* check why this should be a long variable instead of int! */
 
364
        {'T', "realtime",    GLO_LONG,  0, &param.realtime, TRUE },
 
365
        #else
 
366
        {'T', "realtime",    0,  realtime_not_compiled, 0,           0 },    
 
367
        #endif
 
368
        {0, "title",         GLO_INT,  0, &param.xterm_title, TRUE },
 
369
        {'w', "wav",         GLO_ARG | GLO_CHAR, set_wav, 0 , 0 },
 
370
        {0, "cdr",           GLO_ARG | GLO_CHAR, set_cdr, 0 , 0 },
 
371
        {0, "au",            GLO_ARG | GLO_CHAR, set_au, 0 , 0 },
 
372
        #ifdef GAPLESS
 
373
        {0,   "gapless",         GLO_INT,  0, &param.gapless, 1},
 
374
        #endif
 
375
        {'?', "help",            0,  want_usage, 0,           0 },
 
376
        {0 , "longhelp" ,        0,  want_long_usage, 0,      0 },
 
377
        {0 , "version" ,         0,  give_version, 0,         0 },
 
378
        {'l', "listentry",       GLO_ARG | GLO_LONG, 0, &param.listentry, 0 },
 
379
        {0, "rva-mix",         GLO_INT,  0, &param.rva, 0 },
 
380
        {0, "rva-radio",         GLO_INT,  0, &param.rva, 0 },
 
381
        {0, "rva-album",         GLO_INT,  0, &param.rva, 1 },
 
382
        {0, "rva-audiophile",         GLO_INT,  0, &param.rva, 1 },
 
383
        {0, 0, 0, 0, 0, 0}
 
384
};
 
385
 
 
386
/*
 
387
 *   Change the playback sample rate.
 
388
 *   Consider that changing it after starting playback is not covered by gapless code!
 
389
 */
 
390
static void reset_audio(void)
 
391
{
 
392
#ifndef NOXFERMEM
 
393
        if (param.usebuffer) {
 
394
                /* wait until the buffer is empty,
 
395
                 * then tell the buffer process to
 
396
                 * change the sample rate.   [OF]
 
397
                 */
 
398
                while (xfermem_get_usedspace(buffermem) > 0)
 
399
                        if (xfermem_block(XF_WRITER, buffermem) == XF_CMD_TERMINATE) {
 
400
                                intflag = TRUE;
 
401
                                break;
 
402
                        }
 
403
                buffermem->freeindex = -1;
 
404
                buffermem->readindex = 0; /* I know what I'm doing! ;-) */
 
405
                buffermem->freeindex = 0;
 
406
                if (intflag)
 
407
                        return;
 
408
                buffermem->buf[0] = ai.rate; 
 
409
                buffermem->buf[1] = ai.channels; 
 
410
                buffermem->buf[2] = ai.format;
 
411
                buffer_reset();
 
412
        }
 
413
        else 
 
414
#endif
 
415
        if (param.outmode == DECODE_AUDIO) {
 
416
                /* audio_reset_parameters(&ai); */
 
417
                /*   close and re-open in order to flush
 
418
                 *   the device's internal buffer before
 
419
                 *   changing the sample rate.   [OF]
 
420
                 */
 
421
                audio_close (&ai);
 
422
                if (audio_open(&ai) < 0) {
 
423
                        perror("audio");
 
424
#ifdef HAVE_TERMIOS
 
425
                        if(param.term_ctrl)
 
426
                                term_restore();
 
427
#endif
 
428
                        exit(1);
 
429
                }
 
430
        }
 
431
}
 
432
 
 
433
 
 
434
/*
 
435
        precog the audio rate that will be set before output begins
 
436
        this is needed to give gapless code a chance to keep track for firstframe != 0
 
437
*/
 
438
void prepare_audioinfo(struct frame *fr, struct audio_info_struct *nai)
 
439
{
 
440
        long newrate = freqs[fr->sampling_frequency]>>(param.down_sample);
 
441
        fr->down_sample = param.down_sample;
 
442
        audio_fit_capabilities(nai,fr->stereo,newrate);
 
443
}
 
444
 
 
445
/*
 
446
 * play a frame read by read_frame();
 
447
 * (re)initialize audio if necessary.
 
448
 *
 
449
 * needs a major rewrite .. it's incredible ugly!
 
450
 */
 
451
void play_frame(int init,struct frame *fr)
 
452
{
 
453
        int clip;
 
454
        long newrate;
 
455
        long old_rate,old_format,old_channels;
 
456
 
 
457
        if(fr->header_change || init) {
 
458
 
 
459
                if (!param.quiet && init) {
 
460
                        if (param.verbose)
 
461
                                print_header(fr);
 
462
                        else
 
463
                                print_header_compact(fr);
 
464
                }
 
465
 
 
466
                if(fr->header_change > 1 || init) {
 
467
                        old_rate = ai.rate;
 
468
                        old_format = ai.format;
 
469
                        old_channels = ai.channels;
 
470
 
 
471
                        newrate = freqs[fr->sampling_frequency]>>(param.down_sample);
 
472
                        prepare_audioinfo(fr, &ai);
 
473
                        if(param.verbose > 1) fprintf(stderr, "Note: audio output rate = %li\n", ai.rate);
 
474
                        #ifdef GAPLESS
 
475
                        if(param.gapless && (fr->lay == 3)) layer3_gapless_bytify(fr, &ai);
 
476
                        #endif
 
477
                        
 
478
                        /* check, whether the fitter set our proposed rate */
 
479
                        if(ai.rate != newrate) {
 
480
                                if(ai.rate == (newrate>>1) )
 
481
                                        fr->down_sample++;
 
482
                                else if(ai.rate == (newrate>>2) )
 
483
                                        fr->down_sample+=2;
 
484
                                else {
 
485
                                        fr->down_sample = 3;
 
486
                                        fprintf(stderr,"Warning, flexible rate not heavily tested!\n");
 
487
                                }
 
488
                                if(fr->down_sample > 3)
 
489
                                        fr->down_sample = 3;
 
490
                        }
 
491
 
 
492
                        switch(fr->down_sample) {
 
493
                                case 0:
 
494
                                case 1:
 
495
                                case 2:
 
496
                                        fr->down_sample_sblimit = SBLIMIT>>(fr->down_sample);
 
497
                                        break;
 
498
                                case 3:
 
499
                                        {
 
500
                                                long n = freqs[fr->sampling_frequency];
 
501
                                                long m = ai.rate;
 
502
 
 
503
                                                synth_ntom_set_step(n,m);
 
504
 
 
505
                                                if(n>m) {
 
506
                                                        fr->down_sample_sblimit = SBLIMIT * m;
 
507
                                                        fr->down_sample_sblimit /= n;
 
508
                                                }
 
509
                                                else {
 
510
                                                        fr->down_sample_sblimit = SBLIMIT;
 
511
                                                }
 
512
                                        }
 
513
                                        break;
 
514
                        }
 
515
 
 
516
                        init_output();
 
517
                        if(ai.rate != old_rate || ai.channels != old_channels ||
 
518
                           ai.format != old_format || param.force_reopen) {
 
519
                                if(param.force_mono < 0) {
 
520
                                        if(ai.channels == 1)
 
521
                                                fr->single = 3;
 
522
                                        else
 
523
                                                fr->single = -1;
 
524
                                }
 
525
                                else
 
526
                                        fr->single = param.force_mono;
 
527
 
 
528
                                param.force_stereo &= ~0x2;
 
529
                                if(fr->single >= 0 && ai.channels == 2) {
 
530
                                        param.force_stereo |= 0x2;
 
531
                                }
 
532
 
 
533
                                set_synth_functions(fr);
 
534
                                init_layer3(fr->down_sample_sblimit);
 
535
                                reset_audio();
 
536
                                if(param.verbose) {
 
537
                                        if(fr->down_sample == 3) {
 
538
                                                long n = freqs[fr->sampling_frequency];
 
539
                                                long m = ai.rate;
 
540
                                                if(n > m) {
 
541
                                                        fprintf(stderr,"Audio: %2.4f:1 conversion,",(float)n/(float)m);
 
542
                                                }
 
543
                                                else {
 
544
                                                        fprintf(stderr,"Audio: 1:%2.4f conversion,",(float)m/(float)n);
 
545
                                                }
 
546
                                        }
 
547
                                        else {
 
548
                                                fprintf(stderr,"Audio: %ld:1 conversion,",(long)pow(2.0,fr->down_sample));
 
549
                                        }
 
550
                                        fprintf(stderr," rate: %ld, encoding: %s, channels: %d\n",ai.rate,audio_encoding_name(ai.format),ai.channels);
 
551
                                }
 
552
                        }
 
553
                        if (intflag)
 
554
                                return;
 
555
                }
 
556
        }
 
557
 
 
558
        if (fr->error_protection) {
 
559
                getbits(16); /* skip crc */
 
560
        }
 
561
 
 
562
        /* do the decoding */
 
563
        clip = (fr->do_layer)(fr,param.outmode,&ai);
 
564
 
 
565
#ifndef NOXFERMEM
 
566
        if (param.usebuffer) {
 
567
                if (!intflag) {
 
568
                        buffermem->freeindex =
 
569
                                (buffermem->freeindex + pcm_point) % buffermem->size;
 
570
                        if (buffermem->wakeme[XF_READER])
 
571
                                xfermem_putcmd(buffermem->fd[XF_WRITER], XF_CMD_WAKEUP_INFO);
 
572
                }
 
573
                pcm_sample = (unsigned char *) (buffermem->data + buffermem->freeindex);
 
574
                pcm_point = 0;
 
575
                while (xfermem_get_freespace(buffermem) < (FRAMEBUFUNIT << 1))
 
576
                        if (xfermem_block(XF_WRITER, buffermem) == XF_CMD_TERMINATE) {
 
577
                                intflag = TRUE;
 
578
                                break;
 
579
                        }
 
580
                if (intflag)
 
581
                        return;
 
582
        }
 
583
#endif
 
584
 
 
585
        if(clip > 0 && param.checkrange)
 
586
                fprintf(stderr,"%d samples clipped\n", clip);
 
587
}
 
588
 
 
589
void set_synth_functions(struct frame *fr)
 
590
{
 
591
        typedef int (*func)(real *,int,unsigned char *,int *);
 
592
        typedef int (*func_mono)(real *,unsigned char *,int *);
 
593
        typedef void (*func_dct36)(real *,real *,real *,real *,real *);
 
594
        int ds = fr->down_sample;
 
595
        int p8=0;
 
596
#ifdef USE_3DNOW
 
597
        static func funcs[3][4] = {
 
598
#else
 
599
        static func funcs[2][4] = { 
 
600
#endif
 
601
                { synth_1to1,
 
602
                  synth_2to1,
 
603
                  synth_4to1,
 
604
                  synth_ntom } ,
 
605
                { synth_1to1_8bit,
 
606
                  synth_2to1_8bit,
 
607
                  synth_4to1_8bit,
 
608
                  synth_ntom_8bit } 
 
609
#ifdef USE_3DNOW
 
610
               ,{ synth_1to1_3dnow,
 
611
                  synth_2to1,
 
612
                  synth_4to1,
 
613
                  synth_ntom }
 
614
#endif
 
615
        };
 
616
 
 
617
        static func_mono funcs_mono[2][2][4] = {    
 
618
                { { synth_1to1_mono2stereo ,
 
619
                    synth_2to1_mono2stereo ,
 
620
                    synth_4to1_mono2stereo ,
 
621
                    synth_ntom_mono2stereo } ,
 
622
                  { synth_1to1_8bit_mono2stereo ,
 
623
                    synth_2to1_8bit_mono2stereo ,
 
624
                    synth_4to1_8bit_mono2stereo ,
 
625
                    synth_ntom_8bit_mono2stereo } } ,
 
626
                { { synth_1to1_mono ,
 
627
                    synth_2to1_mono ,
 
628
                    synth_4to1_mono ,
 
629
                    synth_ntom_mono } ,
 
630
                  { synth_1to1_8bit_mono ,
 
631
                    synth_2to1_8bit_mono ,
 
632
                    synth_4to1_8bit_mono ,
 
633
                    synth_ntom_8bit_mono } }
 
634
        };
 
635
 
 
636
#ifdef USE_3DNOW        
 
637
        static func_dct36 funcs_dct36[2] = {dct36 , dct36_3dnow};
 
638
#endif
 
639
 
 
640
        if((ai.format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_8)
 
641
                p8 = 1;
 
642
        fr->synth = funcs[p8][ds];
 
643
        fr->synth_mono = funcs_mono[param.force_stereo?0:1][p8][ds];
 
644
 
 
645
/* TODO: make autodetection for _all_ x86 optimizations (maybe just for i586+ and keep separate 486 build?) */
 
646
#ifdef USE_3DNOW
 
647
        /* check cpuflags bit 31 (3DNow!) and 23 (MMX) */
 
648
        if((param.stat_3dnow < 2) && 
 
649
           ((param.stat_3dnow == 1) ||
 
650
            (getcpuflags() & 0x80800000) == 0x80800000))
 
651
        {
 
652
          fr->synth = funcs[2][ds]; /* 3DNow! optimized synth_1to1() */
 
653
          fr->dct36 = funcs_dct36[1]; /* 3DNow! optimized dct36() */
 
654
        }
 
655
        else
 
656
        {
 
657
                  fr->dct36 = funcs_dct36[0];
 
658
        }
 
659
#endif
 
660
 
 
661
        if(p8) {
 
662
                make_conv16to8_table(ai.format);
 
663
        }
 
664
}
 
665
 
 
666
int main(int argc, char *argv[])
 
667
{
 
668
        int result;
 
669
        char *fname;
 
670
#if !defined(WIN32) && !defined(GENERIC)
 
671
        struct timeval start_time, now;
 
672
        unsigned long secdiff;
 
673
#endif  
 
674
        int init;
 
675
        #ifdef GAPLESS
 
676
        int pre_init;
 
677
        #endif
 
678
        int j;
 
679
 
 
680
#ifdef OS2
 
681
        _wildcard(&argc,&argv);
 
682
#endif
 
683
 
 
684
        if(sizeof(short) != 2) {
 
685
                fprintf(stderr,"Ouch SHORT has size of %d bytes (required: '2')\n",(int)sizeof(short));
 
686
                exit(1);
 
687
        }
 
688
        if(sizeof(long) < 4) {
 
689
                fprintf(stderr,"Ouch LONG has size of %d bytes (required: at least 4)\n",(int)sizeof(long));
 
690
        }
 
691
 
 
692
        (prgName = strrchr(argv[0], '/')) ? prgName++ : (prgName = argv[0]);
 
693
 
 
694
        audio_info_struct_init(&ai);
 
695
 
 
696
        while ((result = getlopt(argc, argv, opts)))
 
697
        switch (result) {
 
698
                case GLO_UNKNOWN:
 
699
                        fprintf (stderr, "%s: Unknown option \"%s\".\n", 
 
700
                                prgName, loptarg);
 
701
                        usage(1);
 
702
                case GLO_NOARG:
 
703
                        fprintf (stderr, "%s: Missing argument for option \"%s\".\n",
 
704
                                prgName, loptarg);
 
705
                        usage(1);
 
706
        }
 
707
#ifdef USE_3DNOW
 
708
        if (param.test_3dnow) {
 
709
                int cpuflags = getcpuflags();
 
710
                fprintf(stderr,"CPUFLAGS = %08x\n",cpuflags);
 
711
                if ((cpuflags & 0x00800000) == 0x00800000) {
 
712
                        fprintf(stderr,"MMX instructions are supported.\n");
 
713
                }
 
714
                if ((cpuflags & 0x80000000) == 0x80000000) {
 
715
                        fprintf(stderr,"3DNow! instructions are supported.\n");
 
716
                }
 
717
                exit(0);
 
718
        }
 
719
#endif
 
720
 
 
721
        if (loptind >= argc && !param.listname && !param.remote)
 
722
                usage(1);
 
723
 
 
724
#if !defined(WIN32) && !defined(GENERIC)
 
725
        if (param.remote) {
 
726
                param.verbose = 0;        
 
727
                param.quiet = 1;
 
728
        }
 
729
#endif
 
730
 
 
731
        if (!(param.listentry < 0) && !param.quiet)
 
732
                print_title(stderr); /* do not pollute stdout! */
 
733
 
 
734
        if(param.force_mono >= 0) {
 
735
                fr.single = param.force_mono;
 
736
        }
 
737
 
 
738
        if(param.force_rate && param.down_sample) {
 
739
                fprintf(stderr,"Down sampling and fixed rate options not allowed together!\n");
 
740
                exit(1);
 
741
        }
 
742
 
 
743
        audio_capabilities(&ai);
 
744
        /* equalizer initialization regardless of equalfile */
 
745
        for(j=0; j<32; j++) {
 
746
                equalizer[0][j] = equalizer[1][j] = 1.0;
 
747
                equalizer_sum[0][j] = equalizer_sum[1][j] = 0.0;
 
748
        }
 
749
        if(equalfile != NULL) { /* tst; ThOr: not TRUE or FALSE: allocated or not... */
 
750
                FILE *fe;
 
751
                int i;
 
752
 
 
753
                equalizer_cnt = 0;
 
754
 
 
755
                fe = fopen(equalfile,"r");
 
756
                if(fe) {
 
757
                        char line[256];
 
758
                        for(i=0;i<32;i++) {
 
759
                                float e1,e0; /* %f -> float! */
 
760
                                line[0]=0;
 
761
                                fgets(line,255,fe);
 
762
                                if(line[0]=='#')
 
763
                                        continue;
 
764
                                sscanf(line,"%f %f",&e0,&e1);
 
765
                                equalizer[0][i] = e0;
 
766
                                equalizer[1][i] = e1;   
 
767
                        }
 
768
                        fclose(fe);
 
769
                        have_eq_settings = TRUE;                        
 
770
                }
 
771
                else
 
772
                        fprintf(stderr,"Can't open equalizer file '%s'\n",equalfile);
 
773
        }
 
774
 
 
775
#ifdef HAVE_SETPRIORITY
 
776
        if(param.aggressive) { /* tst */
 
777
                int mypid = getpid();
 
778
                setpriority(PRIO_PROCESS,mypid,-20);
 
779
        }
 
780
#endif
 
781
 
 
782
#ifdef HAVE_SCHED_SETSCHEDULER
 
783
        if (param.realtime) {  /* Get real-time priority */
 
784
          struct sched_param sp;
 
785
          fprintf(stderr,"Getting real-time priority\n");
 
786
          memset(&sp, 0, sizeof(struct sched_param));
 
787
          sp.sched_priority = sched_get_priority_min(SCHED_FIFO);
 
788
          if (sched_setscheduler(0, SCHED_RR, &sp) == -1)
 
789
            fprintf(stderr,"Can't get real-time priority\n");
 
790
        }
 
791
#endif
 
792
 
 
793
        set_synth_functions(&fr);
 
794
 
 
795
        if(!param.remote) prepare_playlist(argc, argv);
 
796
 
 
797
        make_decode_tables(outscale);
 
798
        init_layer2(); /* inits also shared tables with layer1 */
 
799
        init_layer3(fr.down_sample);
 
800
 
 
801
#if !defined(WIN32) && !defined(GENERIC)
 
802
        /* This ctrl+c for title skip only when not in some control mode */
 
803
        if
 
804
        (
 
805
                !param.remote 
 
806
                #ifdef HAVE_TERMIOS
 
807
                && !param.term_ctrl
 
808
                #endif
 
809
        )
 
810
        catchsignal (SIGINT, catch_interrupt);
 
811
 
 
812
        if(param.remote) {
 
813
                int ret;
 
814
                init_id3();
 
815
                ret = control_generic(&fr);
 
816
                exit_id3();
 
817
                exit(ret);
 
818
        }
 
819
#endif
 
820
 
 
821
        init_id3(); /* prepare id3 memory */
 
822
        while ((fname = get_next_file())) {
 
823
                char *dirname, *filename;
 
824
                long leftFrames,newFrame;
 
825
 
 
826
                if(!*fname || !strcmp(fname, "-"))
 
827
                        fname = NULL;
 
828
               if (open_stream(fname,-1) < 0)
 
829
                       continue;
 
830
      
 
831
                if (!param.quiet) {
 
832
                        if (split_dir_file(fname ? fname : "standard input",
 
833
                                &dirname, &filename))
 
834
                                fprintf(stderr, "\nDirectory: %s", dirname);
 
835
                        fprintf(stderr, "\nPlaying MPEG stream %lu of %lu: %s ...\n", (unsigned long)pl.pos, (unsigned long)pl.fill, filename);
 
836
 
 
837
#if !defined(GENERIC)
 
838
{
 
839
        const char *term_type;
 
840
        term_type = getenv("TERM");
 
841
        if (term_type && param.xterm_title &&
 
842
            (!strncmp(term_type,"xterm",5) || !strncmp(term_type,"rxvt",4)))
 
843
        {
 
844
                fprintf(stderr, "\033]0;%s\007", filename);
 
845
        }
 
846
}
 
847
#endif
 
848
 
 
849
                }
 
850
 
 
851
#if !defined(WIN32) && !defined(GENERIC)
 
852
#ifdef HAVE_TERMIOS
 
853
                if(!param.term_ctrl)
 
854
#endif
 
855
                        gettimeofday (&start_time, NULL);
 
856
#endif
 
857
                read_frame_init(&fr);
 
858
 
 
859
                init = 1;
 
860
                #ifdef GAPLESS
 
861
                pre_init = 1;
 
862
                #endif
 
863
                newFrame = startFrame;
 
864
                
 
865
#ifdef HAVE_TERMIOS
 
866
                debug1("param.term_ctrl: %i", param.term_ctrl);
 
867
                if(param.term_ctrl)
 
868
                        term_init();
 
869
#endif
 
870
                leftFrames = numframes;
 
871
                /* read_frame is counting the frames! */
 
872
                for(;read_frame(&fr) && leftFrames && !intflag;) {
 
873
#ifdef HAVE_TERMIOS                     
 
874
tc_hack:
 
875
#endif
 
876
                        if(fr.num < startFrame || (param.doublespeed && (fr.num % param.doublespeed))) {
 
877
                                if(fr.lay == 3)
 
878
                                {
 
879
                                        set_pointer(512);
 
880
                                        #ifdef GAPLESS
 
881
                                        if(param.gapless)
 
882
                                        {
 
883
                                                if(pre_init)
 
884
                                                {
 
885
                                                        prepare_audioinfo(&fr, &pre_ai);
 
886
                                                        pre_init = 0;
 
887
                                                }
 
888
                                                /* keep track... */
 
889
                                                layer3_gapless_set_position(fr.num, &fr, &pre_ai);
 
890
                                        }
 
891
                                        #endif
 
892
                                }
 
893
                                continue;
 
894
                        }
 
895
                        if(leftFrames > 0)
 
896
                          leftFrames--;
 
897
                        play_frame(init,&fr);
 
898
                        init = 0;
 
899
 
 
900
                        if(param.verbose) {
 
901
#ifndef NOXFERMEM
 
902
                                if (param.verbose > 1 || !(fr.num & 0x7))
 
903
                                        print_stat(&fr,fr.num,xfermem_get_usedspace(buffermem),&ai); 
 
904
                                if(param.verbose > 2 && param.usebuffer)
 
905
                                        fprintf(stderr,"[%08x %08x]",buffermem->readindex,buffermem->freeindex);
 
906
#else
 
907
                                if (param.verbose > 1 || !(fr.num & 0x7))
 
908
                                        print_stat(&fr,fr.num,0,&ai);
 
909
#endif
 
910
                        }
 
911
#ifdef HAVE_TERMIOS
 
912
                        if(!param.term_ctrl) {
 
913
                                continue;
 
914
                        } else {
 
915
                                long offset;
 
916
                                if((offset=term_control(&fr))) {
 
917
                                        if(!rd->back_frame(rd, &fr, -offset)) {
 
918
                                                debug1("seeked to %lu", fr.num);
 
919
                                                #ifdef GAPLESS
 
920
                                                if(param.gapless && (fr.lay == 3))
 
921
                                                layer3_gapless_set_position(fr.num, &fr, &ai);
 
922
                                                #endif
 
923
                                        } else { error("seek failed!"); }
 
924
                                }
 
925
                        }
 
926
#endif
 
927
 
 
928
                }
 
929
                #ifdef GAPLESS
 
930
                /* make sure that the correct padding is skipped after track ended */
 
931
                if(param.gapless) audio_flush(param.outmode, &ai);
 
932
                #endif
 
933
 
 
934
#ifndef NOXFERMEM
 
935
        if(param.usebuffer) {
 
936
                int s;
 
937
                while ((s = xfermem_get_usedspace(buffermem))) {
 
938
                        struct timeval wait170 = {0, 170000};
 
939
 
 
940
                        buffer_ignore_lowmem();
 
941
                        
 
942
                        if(param.verbose)
 
943
                                print_stat(&fr,fr.num,s,&ai);
 
944
#ifdef HAVE_TERMIOS
 
945
                        if(param.term_ctrl) {
 
946
                                long offset;
 
947
                                if((offset=term_control(&fr))) {
 
948
                                        if((!rd->back_frame(rd, &fr, -offset)) 
 
949
                                                && read_frame(&fr))
 
950
                                        {
 
951
                                                debug1("seeked to %lu", fr.num);
 
952
                                                #ifdef GAPLESS
 
953
                                                if(param.gapless && (fr.lay == 3))
 
954
                                                layer3_gapless_set_position(fr.num, &fr, &ai);
 
955
                                                #endif
 
956
                                                goto tc_hack;   /* Doh! Gag me with a spoon! */
 
957
                                        } else { error("seek failed!"); }
 
958
                                }
 
959
                        }
 
960
#endif
 
961
                        select(0, NULL, NULL, NULL, &wait170);
 
962
                }
 
963
        }
 
964
#endif
 
965
        if(param.verbose)
 
966
                print_stat(&fr,fr.num,xfermem_get_usedspace(buffermem),&ai); 
 
967
#ifdef HAVE_TERMIOS
 
968
        if(param.term_ctrl)
 
969
                term_restore();
 
970
#endif
 
971
 
 
972
        if (!param.quiet) {
 
973
                /* 
 
974
                 * This formula seems to work at least for
 
975
                 * MPEG 1.0/2.0 layer 3 streams.
 
976
                 */
 
977
                int secs = get_songlen(&fr,fr.num);
 
978
                fprintf(stderr,"\n[%d:%02d] Decoding of %s finished.\n", secs / 60,
 
979
                        secs % 60, filename);
 
980
        }
 
981
 
 
982
        rd->close(rd);
 
983
#if 0
 
984
        if(param.remote)
 
985
                fprintf(stderr,"@R MPG123\n");        
 
986
        if (remflag) {
 
987
                intflag = FALSE;
 
988
                remflag = FALSE;
 
989
        }
 
990
#endif
 
991
        
 
992
      if (intflag) {
 
993
 
 
994
/* 
 
995
 * When HAVE_TERMIOS is defined, there is 'q' to terminate a list of songs, so
 
996
 * no pressing need to keep up this first second SIGINT hack that was too
 
997
 * often mistaken as a bug. [dk]
 
998
 * ThOr: Yep, I deactivated the Ctrl+C hack for active control modes.
 
999
 */
 
1000
#if !defined(WIN32) && !defined(GENERIC)
 
1001
#ifdef HAVE_TERMIOS
 
1002
        if(!param.term_ctrl)
 
1003
#endif
 
1004
        {
 
1005
                gettimeofday (&now, NULL);
 
1006
                secdiff = (now.tv_sec - start_time.tv_sec) * 1000;
 
1007
                if (now.tv_usec >= start_time.tv_usec)
 
1008
                        secdiff += (now.tv_usec - start_time.tv_usec) / 1000;
 
1009
                else
 
1010
                        secdiff -= (start_time.tv_usec - now.tv_usec) / 1000;
 
1011
                if (secdiff < 1000)
 
1012
                        break;
 
1013
        }
 
1014
#endif
 
1015
        intflag = FALSE;
 
1016
 
 
1017
#ifndef NOXFERMEM
 
1018
        if(param.usebuffer) buffer_resync();
 
1019
#endif
 
1020
      }
 
1021
    } /* end of loop over input files */
 
1022
    exit_id3(); /* free id3 memory */
 
1023
#ifndef NOXFERMEM
 
1024
    if (param.usebuffer) {
 
1025
      buffer_end();
 
1026
      xfermem_done_writer (buffermem);
 
1027
      waitpid (buffer_pid, NULL, 0);
 
1028
      xfermem_done (buffermem);
 
1029
    }
 
1030
    else {
 
1031
#endif
 
1032
      audio_flush(param.outmode, &ai);
 
1033
      free (pcm_sample);
 
1034
#ifndef NOXFERMEM
 
1035
    }
 
1036
#endif
 
1037
 
 
1038
    switch(param.outmode) {
 
1039
      case DECODE_AUDIO:
 
1040
        audio_close(&ai);
 
1041
        break;
 
1042
      case DECODE_WAV:
 
1043
        wav_close();
 
1044
        break;
 
1045
      case DECODE_AU:
 
1046
        au_close();
 
1047
        break;
 
1048
      case DECODE_CDR:
 
1049
        cdr_close();
 
1050
        break;
 
1051
    }
 
1052
        if(!param.remote) free_playlist();
 
1053
    return 0;
 
1054
}
 
1055
 
 
1056
static void print_title(FILE *o)
 
1057
{
 
1058
        fprintf(o, "High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3\n");
 
1059
        fprintf(o, "\tversion %s; written and copyright by Michael Hipp and others\n", PACKAGE_VERSION);
 
1060
        fprintf(o, "\tfree software (LGPL/GPL) without any warranty but with best wishes\n");
 
1061
}
 
1062
 
 
1063
static void usage(int err)  /* print syntax & exit */
 
1064
{
 
1065
        FILE* o = stdout;
 
1066
        if(err)
 
1067
        {
 
1068
                o = stderr; 
 
1069
                fprintf(o, "You made some mistake in program usage... let me briefly remind you:\n\n");
 
1070
        }
 
1071
        print_title(o);
 
1072
        fprintf(o,"\nusage: %s [option(s)] [file(s) | URL(s) | -]\n", prgName);
 
1073
        fprintf(o,"supported options [defaults in brackets]:\n");
 
1074
        fprintf(o,"   -v    increase verbosity level       -q    quiet (don't print title)\n");
 
1075
        fprintf(o,"   -t    testmode (no output)           -s    write to stdout\n");
 
1076
        fprintf(o,"   -w <filename> write Output as WAV file\n");
 
1077
        fprintf(o,"   -k n  skip first n frames [0]        -n n  decode only n frames [all]\n");
 
1078
        fprintf(o,"   -c    check range violations         -y    DISABLE resync on errors\n");
 
1079
        fprintf(o,"   -b n  output buffer: n Kbytes [0]    -f n  change scalefactor [32768]\n");
 
1080
        fprintf(o,"   -r n  set/force samplerate [auto]    -g n  set audio hardware output gain\n");
 
1081
        fprintf(o,"   -os,-ol,-oh  output to built-in speaker,line-out connector,headphones\n");
 
1082
        #ifdef NAS
 
1083
        fprintf(o,"                                        -a d  set NAS server\n");
 
1084
        #elif defined(SGI)
 
1085
        fprintf(o,"                                        -a [1..4] set RAD device\n");
 
1086
        #else
 
1087
        fprintf(o,"                                        -a d  set audio device\n");
 
1088
        #endif
 
1089
        fprintf(o,"   -2    downsample 1:2 (22 kHz)        -4    downsample 1:4 (11 kHz)\n");
 
1090
        fprintf(o,"   -d n  play every n'th frame only     -h n  play every frame n times\n");
 
1091
        fprintf(o,"   -0    decode channel 0 (left) only   -1    decode channel 1 (right) only\n");
 
1092
        fprintf(o,"   -m    mix both channels (mono)       -p p  use HTTP proxy p [$HTTP_PROXY]\n");
 
1093
        #ifdef HAVE_SCHED_SETSCHEDULER
 
1094
        fprintf(o,"   -@ f  read filenames/URLs from f     -T get realtime priority\n");
 
1095
        #else
 
1096
        fprintf(o,"   -@ f  read filenames/URLs from f\n");
 
1097
        #endif
 
1098
        fprintf(o,"   -z    shuffle play (with wildcards)  -Z    random play\n");
 
1099
        fprintf(o,"   -u a  HTTP authentication string     -E f  Equalizer, data from file\n");
 
1100
        #ifdef GAPLESS
 
1101
        fprintf(o,"   -C    enable control keys            --gapless  skip junk/padding in some mp3s\n");
 
1102
        #else
 
1103
        fprintf(o,"   -C    enable control keys\n");
 
1104
        #endif
 
1105
        fprintf(o,"   -?    this help                      --version  print name + version\n");
 
1106
        fprintf(o,"See the manpage %s(1) or call %s with --longhelp for more parameters and information.\n", prgName,prgName);
 
1107
        exit(err);
 
1108
}
 
1109
 
 
1110
static void want_usage(char* arg)
 
1111
{
 
1112
        usage(0);
 
1113
}
 
1114
 
 
1115
static void long_usage(int err)
 
1116
{
 
1117
        FILE* o = stdout;
 
1118
        if(err)
 
1119
        {
 
1120
        o = stderr; 
 
1121
        fprintf(o, "You made some mistake in program usage... let me remind you:\n\n");
 
1122
        }
 
1123
        print_title(o);
 
1124
        fprintf(o,"\nusage: %s [option(s)] [file(s) | URL(s) | -]\n", prgName);
 
1125
 
 
1126
        fprintf(o,"\ninput options\n\n");
 
1127
        fprintf(o," -k <n> --skip <n>         skip n frames at beginning\n");
 
1128
        fprintf(o," -n     --frames <n>       play only <n> frames of every stream\n");
 
1129
        fprintf(o," -y     --resync           DISABLES resync on error\n");
 
1130
        fprintf(o," -p <f> --proxy <f>        set WWW proxy\n");
 
1131
        fprintf(o," -u     --auth             set auth values for HTTP access\n");
 
1132
        fprintf(o," -@ <f> --list <f>         play songs in playlist <f> (plain list, m3u, pls (shoutcast))\n");
 
1133
        fprintf(o," -l <n> --listentry <n>    play nth title in playlist; show whole playlist for n < 0\n");
 
1134
        fprintf(o," -z     --shuffle          shuffle song-list before playing\n");
 
1135
        fprintf(o," -Z     --random           full random play\n");
 
1136
 
 
1137
        fprintf(o,"\noutput/processing options\n\n");
 
1138
        fprintf(o," -a <d> --audiodevice <d>  select audio device\n");
 
1139
        fprintf(o," -s     --stdout           write raw audio to stdout (host native format)\n");
 
1140
        fprintf(o," -S     --STDOUT           play AND output stream (not implemented yet)\n");
 
1141
        fprintf(o," -w <f> --wav <f>          write samples as WAV file in <f> (- is stdout)\n");
 
1142
        fprintf(o,"        --au <f>           write samples as Sun AU file in <f> (- is stdout)\n");
 
1143
        fprintf(o,"        --cdr <f>          write samples as CDR file in <f> (- is stdout)\n");
 
1144
        fprintf(o,"        --reopen           force close/open on audiodevice\n");
 
1145
        fprintf(o," -g     --gain             set audio hardware output gain\n");
 
1146
        fprintf(o," -f <n> --scale <n>        scale output samples (soft gain, default=%li)\n", outscale);
 
1147
        fprintf(o,"        --rva-mix,\n");
 
1148
        fprintf(o,"        --rva-radio        use RVA2/ReplayGain values for mix/radio mode\n");
 
1149
        fprintf(o,"        --rva-album,\n");
 
1150
        fprintf(o,"        --rva-audiophile   use RVA2/ReplayGain values for album/audiophile mode\n");
 
1151
        fprintf(o,"        --reopen           force close/open on audiodevice\n");
 
1152
        fprintf(o," -0     --left --single0   play only left channel\n");
 
1153
        fprintf(o," -1     --right --single1  play only right channel\n");
 
1154
        fprintf(o," -m     --mono --mix       mix stereo to mono\n");
 
1155
        fprintf(o,"        --stereo           duplicate mono channel\n");
 
1156
        fprintf(o," -r     --rate             force a specific audio output rate\n");
 
1157
        fprintf(o," -2     --2to1             2:1 downsampling\n");
 
1158
        fprintf(o," -4     --4to1             4:1 downsampling\n");
 
1159
        fprintf(o,"        --8bit             force 8 bit output\n");
 
1160
        fprintf(o," -d     --doublespeed      play only every second frame\n");
 
1161
        fprintf(o," -h     --halfspeed        play every frame twice\n");
 
1162
        fprintf(o,"        --equalizer        exp.: scales freq. bands acrd. to 'equalizer.dat'\n");
 
1163
        #ifdef GAPLESS
 
1164
        fprintf(o,"        --gapless          remove padding/junk added by encoder/decoder\n");
 
1165
        #endif
 
1166
        fprintf(o,"                           (experimental, needs Lame tag, layer 3 only)\n");
 
1167
        fprintf(o," -o h   --headphones       (aix/hp/sun) output on headphones\n");
 
1168
        fprintf(o," -o s   --speaker          (aix/hp/sun) output on speaker\n");
 
1169
        fprintf(o," -o l   --lineout          (aix/hp/sun) output to lineout\n");
 
1170
        fprintf(o," -b <n> --buffer <n>       set play buffer (\"output cache\")\n");
 
1171
 
 
1172
        fprintf(o,"\nmisc options\n\n");
 
1173
        fprintf(o," -t     --test             only decode, no output (benchmark)\n");
 
1174
        fprintf(o," -c     --check            count and display clipped samples\n");
 
1175
        fprintf(o," -v[*]  --verbose          increase verboselevel\n");
 
1176
        fprintf(o," -q     --quiet            quiet mode\n");
 
1177
        #ifdef HAVE_TERMIOS
 
1178
        fprintf(o," -C     --control          enable terminal control keys\n");
 
1179
        #endif
 
1180
        #ifndef GENERIG
 
1181
        fprintf(o,"        --title            set xterm/rxvt title to filename\n");
 
1182
        #endif
 
1183
        fprintf(o," -R     --remote           generic remote interface\n");
 
1184
        fprintf(o,"        --remote-err       use stderr for generic remote interface\n");
 
1185
        #ifdef HAVE_SETPRIORITY
 
1186
        fprintf(o,"        --aggressive       tries to get higher priority (nice)\n");
 
1187
        #endif
 
1188
        #ifdef HAVE_SCHED_SETSCHEDULER
 
1189
        fprintf(o," -T     --realtime         tries to get realtime priority\n");
 
1190
        #endif
 
1191
        #ifdef USE_3DNOW
 
1192
        fprintf(o,"        --test-3dnow       display result of 3DNow! autodetect and exit\n");
 
1193
        fprintf(o,"        --force-3dnow      force use of 3DNow! optimized routine\n");
 
1194
        fprintf(o,"        --no-3dnow         force use of floating-pointer routine\n");
 
1195
        #endif
 
1196
        fprintf(o," -?     --help             give compact help\n");
 
1197
        fprintf(o,"        --longhelp         give this long help listing\n");
 
1198
        fprintf(o,"        --version          give name / version string\n");
 
1199
 
 
1200
        fprintf(o,"\nSee the manpage %s(1) for more information.\n", prgName);
 
1201
        exit(err);
 
1202
}
 
1203
 
 
1204
static void want_long_usage(char* arg)
 
1205
{
 
1206
        long_usage(0);
 
1207
}
 
1208
 
 
1209
static void give_version(char* arg)
 
1210
{
 
1211
        fprintf(stdout, PACKAGE_NAME" "PACKAGE_VERSION"\n");
 
1212
        exit(0);
 
1213
}