⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpg123.c

📁 mpeg 2 source code for video compression
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	mpg123: main code of the program (not of the decoder...)	copyright 1995-2006 by the mpg123 project - free software under the terms of the LGPL 2.1	see COPYING and AUTHORS files in distribution or http://mpg123.de	initially written by Michael Hipp*/#include "config.h"#include "debug.h"#define ME "main"#include <stdlib.h>#include <sys/types.h>#if !defined(WIN32) && !defined(GENERIC)#include <sys/wait.h>#include <sys/time.h>#include <sys/resource.h>#endif#include <errno.h>#include <string.h>#include <fcntl.h>#include <time.h>#ifdef HAVE_SCHED_H#include <sched.h>#endif#include "mpg123.h"#include "getlopt.h"#include "buffer.h"#include "term.h"#ifdef GAPLESS#include "layer3.h"#endif#include "playlist.h"#include "id3.h"static void usage(int err);static void want_usage(char* arg);static void long_usage(int err);static void want_long_usage(char* arg);static void print_title(FILE* o);static void give_version(char* arg);struct parameter param = {   FALSE , /* aggressiv */  FALSE , /* shuffle */  FALSE , /* remote */  FALSE , /* remote to stderr */  DECODE_AUDIO , /* write samples to audio device */  FALSE , /* silent operation */  FALSE , /* xterm title on/off */  0 ,     /* second level buffer size */  TRUE ,  /* resync after stream error */  0 ,     /* verbose level */#ifdef HAVE_TERMIOS  FALSE , /* term control */#endif  -1 ,     /* force mono */  0 ,     /* force stereo */  0 ,     /* force 8bit */  0 ,     /* force rate */  0 , 	  /* down sample */  FALSE , /* checkrange */  0 ,	  /* doublespeed */  0 ,	  /* halfspeed */  0 ,	  /* force_reopen, always (re)opens audio device for next song */#ifdef USE_3DNOW  0 ,     /* autodetect from CPUFLAGS */  FALSE , /* normal operation */#endif  FALSE,  /* try to run process in 'realtime mode' */     { 0,},  /* wav,cdr,au Filename */#ifdef GAPLESS	0, /* gapless off per default - yet */#endif	0, /* default is to play all titles in playlist */	-1, /* do not use rva per default */	NULL /* no playlist per default */};char *prgName = NULL;char *equalfile = NULL;/* ThOr: pointers are not TRUE or FALSE */int have_eq_settings = FALSE;long outscale  = MAXOUTBURST;long numframes = -1;long startFrame= 0;int buffer_fd[2];int buffer_pid;static int intflag = FALSE;int OutputDescriptor;#if !defined(WIN32) && !defined(GENERIC)static void catch_child(void){  while (waitpid(-1, NULL, WNOHANG) > 0);}static void catch_interrupt(void){  intflag = TRUE;}#endif/* oh, what a mess... */void next_track(void){	intflag = TRUE;}static struct frame fr;struct audio_info_struct ai,pre_ai;txfermem *buffermem = NULL;#define FRAMEBUFUNIT (18 * 64 * 4)void set_synth_functions(struct frame *fr);void init_output(void){  static int init_done = FALSE;  if (init_done)    return;  init_done = TRUE;#ifndef NOXFERMEM  /*   * Only DECODE_AUDIO and DECODE_FILE are sanely handled by the   * buffer process. For now, we just ignore the request   * to buffer the output. [dk]   */  if (param.usebuffer && (param.outmode != DECODE_AUDIO) &&      (param.outmode != DECODE_FILE)) {    fprintf(stderr, "Sorry, won't buffer output unless writing plain audio.\n");    param.usebuffer = 0;  }     if (param.usebuffer) {    unsigned int bufferbytes;    sigset_t newsigset, oldsigset;    if (param.usebuffer < 32)      param.usebuffer = 32; /* minimum is 32 Kbytes! */    bufferbytes = (param.usebuffer * 1024);    bufferbytes -= bufferbytes % FRAMEBUFUNIT;	/* +1024 for NtoM rounding problems */    xfermem_init (&buffermem, bufferbytes ,0,1024);    pcm_sample = (unsigned char *) buffermem->data;    pcm_point = 0;    sigemptyset (&newsigset);    sigaddset (&newsigset, SIGUSR1);    sigprocmask (SIG_BLOCK, &newsigset, &oldsigset);    catchsignal (SIGCHLD, catch_child);    switch ((buffer_pid = fork())) {      case -1: /* error */        perror("fork()");#ifdef HAVE_TERMIOS	if(param.term_ctrl)		term_restore();#endif        exit(1);      case 0: /* child */        if(rd)          rd->close(rd); /* child doesn't need the input stream */        xfermem_init_reader (buffermem);        buffer_loop (&ai, &oldsigset);        xfermem_done_reader (buffermem);        xfermem_done (buffermem);        _exit(0);      default: /* parent */        xfermem_init_writer (buffermem);        param.outmode = DECODE_BUFFER;    }  }  else {#endif	/* + 1024 for NtoM rate converter */    if (!(pcm_sample = (unsigned char *) malloc(audiobufsize * 2 + 1024))) {      perror ("malloc()");#ifdef HAVE_TERMIOS      if(param.term_ctrl)      	term_restore();#endif      exit (1);#ifndef NOXFERMEM    }#endif  }  switch(param.outmode) {    case DECODE_AUDIO:      if(audio_open(&ai) < 0) {        perror("audio");#ifdef HAVE_TERMIOS	if(param.term_ctrl)		term_restore();#endif        exit(1);      }      break;    case DECODE_WAV:      wav_open(&ai,param.filename);      break;    case DECODE_AU:      au_open(&ai,param.filename);      break;    case DECODE_CDR:      cdr_open(&ai,param.filename);      break;  }}static void set_output_h(char *a){  if(ai.output <= 0)    ai.output = AUDIO_OUT_HEADPHONES;  else    ai.output |= AUDIO_OUT_HEADPHONES;}static void set_output_s(char *a){  if(ai.output <= 0)    ai.output = AUDIO_OUT_INTERNAL_SPEAKER;  else    ai.output |= AUDIO_OUT_INTERNAL_SPEAKER;}static void set_output_l(char *a){  if(ai.output <= 0)    ai.output = AUDIO_OUT_LINE_OUT;  else    ai.output |= AUDIO_OUT_LINE_OUT;}static void set_output (char *arg){    switch (*arg) {        case 'h': set_output_h(arg); break;        case 's': set_output_s(arg); break;        case 'l': set_output_l(arg); break;        default:            fprintf (stderr, "%s: Unknown argument \"%s\" to option \"%s\".\n",                prgName, arg, loptarg);            exit (1);    }}void set_verbose (char *arg){    param.verbose++;}void set_wav(char *arg){  param.outmode = DECODE_WAV;  strncpy(param.filename,arg,255);  param.filename[255] = 0;}void set_cdr(char *arg){  param.outmode = DECODE_CDR;  strncpy(param.filename,arg,255);  param.filename[255] = 0;}void set_au(char *arg){  param.outmode = DECODE_AU;  strncpy(param.filename,arg,255);  param.filename[255] = 0;}static void SetOutFile(char *Arg){  param.outmode=DECODE_FILE;  OutputDescriptor=open(Arg,O_WRONLY,0);  if(OutputDescriptor==-1) {    fprintf(stderr,"Can't open %s for writing (%s).\n",Arg,strerror(errno));    exit(1);  }}static void SetOutStdout(char *Arg){  param.outmode=DECODE_FILE;  OutputDescriptor=1;}static void SetOutStdout1(char *Arg){  param.outmode=DECODE_AUDIOFILE;  OutputDescriptor=1;}void realtime_not_compiled(char *arg){  fprintf(stderr,"Option '-T / --realtime' not compiled into this binary.\n");}/* Please note: GLO_NUM expects point to LONG! *//* ThOr: *  Yeah, and despite that numerous addresses to int variables were passed. *  That's not good on my Alpha machine with int=32bit and long=64bit! *  Introduced GLO_INT and GLO_LONG as different bits to make that clear. *  GLO_NUM no longer exists. */topt opts[] = {	{'k', "skip",        GLO_ARG | GLO_LONG, 0, &startFrame, 0},	{'a', "audiodevice", GLO_ARG | GLO_CHAR, 0, &ai.device,  0},	{'2', "2to1",        GLO_INT,  0, &param.down_sample, 1},	{'4', "4to1",        GLO_INT,  0, &param.down_sample, 2},	{'t', "test",        GLO_INT,  0, &param.outmode, DECODE_TEST},	{'s', "stdout",      GLO_INT,  SetOutStdout, &param.outmode, DECODE_FILE},	{'S', "STDOUT",      GLO_INT,  SetOutStdout1, &param.outmode,DECODE_AUDIOFILE},	{'O', "outfile",     GLO_ARG | GLO_CHAR, SetOutFile, NULL, 0},	{'c', "check",       GLO_INT,  0, &param.checkrange, TRUE},	{'v', "verbose",     0,        set_verbose, 0,           0},	{'q', "quiet",       GLO_INT,  0, &param.quiet, TRUE},	{'y', "resync",      GLO_INT,  0, &param.tryresync, FALSE},	{'0', "single0",     GLO_INT,  0, &param.force_mono, 0},	{0,   "left",        GLO_INT,  0, &param.force_mono, 0},	{'1', "single1",     GLO_INT,  0, &param.force_mono, 1},	{0,   "right",       GLO_INT,  0, &param.force_mono, 1},	{'m', "singlemix",   GLO_INT,  0, &param.force_mono, 3},	{0,   "mix",         GLO_INT,  0, &param.force_mono, 3},	{0,   "mono",        GLO_INT,  0, &param.force_mono, 3},	{0,   "stereo",      GLO_INT,  0, &param.force_stereo, 1},	{0,   "reopen",      GLO_INT,  0, &param.force_reopen, 1},	{'g', "gain",        GLO_ARG | GLO_LONG, 0, &ai.gain,    0},	{'r', "rate",        GLO_ARG | GLO_LONG, 0, &param.force_rate,  0},	{0,   "8bit",        GLO_INT,  0, &param.force_8bit, 1},	{0,   "headphones",  0,                  set_output_h, 0,0},	{0,   "speaker",     0,                  set_output_s, 0,0},	{0,   "lineout",     0,                  set_output_l, 0,0},	{'o', "output",      GLO_ARG | GLO_CHAR, set_output, 0,  0},	{'f', "scale",       GLO_ARG | GLO_LONG, 0, &outscale,   0},	{'n', "frames",      GLO_ARG | GLO_LONG, 0, &numframes,  0},	#ifdef HAVE_TERMIOS	{'C', "control",     GLO_INT,  0, &param.term_ctrl, TRUE},	#endif	{'b', "buffer",      GLO_ARG | GLO_LONG, 0, &param.usebuffer,  0},	{'R', "remote",      GLO_INT,  0, &param.remote, TRUE},	{0,   "remote-err",  GLO_INT,  0, &param.remote_err, TRUE},	{'d', "doublespeed", GLO_ARG | GLO_LONG, 0, &param.doublespeed,0},	{'h', "halfspeed",   GLO_ARG | GLO_LONG, 0, &param.halfspeed,  0},	{'p', "proxy",       GLO_ARG | GLO_CHAR, 0, &proxyurl,   0},	{'@', "list",        GLO_ARG | GLO_CHAR, 0, &param.listname,   0},	/* 'z' comes from the the german word 'zufall' (eng: random) */	{'z', "shuffle",     GLO_INT,  0, &param.shuffle, 1},	{'Z', "random",      GLO_INT,  0, &param.shuffle, 2},	{'E', "equalizer",	 GLO_ARG | GLO_CHAR, 0, &equalfile,1},	#ifdef HAVE_SETPRIORITY	{0,   "aggressive",	 GLO_INT,  0, &param.aggressive, 2},	#endif	#ifdef USE_3DNOW	{0,   "force-3dnow", GLO_INT,  0, &param.stat_3dnow, 1},	{0,   "no-3dnow",    GLO_INT,  0, &param.stat_3dnow, 2},	{0,   "test-3dnow",  GLO_INT,  0, &param.test_3dnow, TRUE},	#endif	#if !defined(WIN32) && !defined(GENERIC)	{'u', "auth",        GLO_ARG | GLO_CHAR, 0, &httpauth,   0},	#endif	#ifdef HAVE_SCHED_SETSCHEDULER	/* check why this should be a long variable instead of int! */	{'T', "realtime",    GLO_LONG,  0, &param.realtime, TRUE },	#else	{'T', "realtime",    0,  realtime_not_compiled, 0,           0 },    	#endif	{0, "title",         GLO_INT,  0, &param.xterm_title, TRUE },	{'w', "wav",         GLO_ARG | GLO_CHAR, set_wav, 0 , 0 },	{0, "cdr",           GLO_ARG | GLO_CHAR, set_cdr, 0 , 0 },	{0, "au",            GLO_ARG | GLO_CHAR, set_au, 0 , 0 },	#ifdef GAPLESS	{0,   "gapless",	 GLO_INT,  0, &param.gapless, 1},	#endif	{'?', "help",            0,  want_usage, 0,           0 },	{0 , "longhelp" ,        0,  want_long_usage, 0,      0 },	{0 , "version" ,         0,  give_version, 0,         0 },	{'l', "listentry",       GLO_ARG | GLO_LONG, 0, &param.listentry, 0 },	{0, "rva-mix",         GLO_INT,  0, &param.rva, 0 },	{0, "rva-radio",         GLO_INT,  0, &param.rva, 0 },	{0, "rva-album",         GLO_INT,  0, &param.rva, 1 },	{0, "rva-audiophile",         GLO_INT,  0, &param.rva, 1 },	{0, 0, 0, 0, 0, 0}};/* *   Change the playback sample rate. *   Consider that changing it after starting playback is not covered by gapless code! */static void reset_audio(void){#ifndef NOXFERMEM	if (param.usebuffer) {		/* wait until the buffer is empty,		 * then tell the buffer process to		 * change the sample rate.   [OF]		 */		while (xfermem_get_usedspace(buffermem)	> 0)			if (xfermem_block(XF_WRITER, buffermem) == XF_CMD_TERMINATE) {				intflag = TRUE;				break;			}		buffermem->freeindex = -1;		buffermem->readindex = 0; /* I know what I'm doing! ;-) */		buffermem->freeindex = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -