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

📄 player.c

📁 linux下MPEG播放器
💻 C
📖 第 1 页 / 共 5 页
字号:
    player->control = PLAYER_CONTROL_REPLAY;    flow = MAD_FLOW_STOP;    /* fall through */  case KEY_PAUSE:    stop_audio(player, stopped);    message(" --%s--", stopped ? _("Stopped") : _("Paused"));    command = readkey(1);    message("");    if (command == -1)      return MAD_FLOW_BREAK;    if (command != KEY_PAUSE)      goto again;    break;  case KEY_FORWARD:  case KEY_CTRL('n'):  case '>':    player->control = PLAYER_CONTROL_NEXT;    goto stop;  case KEY_BACK:  case KEY_CTRL('p'):  case '<':    {      mad_timer_t threshold;      mad_timer_set(&threshold, 4, 0, 0);      player->control =	(stopped ||	 mad_timer_compare(player->stats.play_timer, threshold) < 0) ?	PLAYER_CONTROL_PREVIOUS : PLAYER_CONTROL_REPLAY;    }    goto stop;  case KEY_QUIT:  case KEY_CTRL('c'):  case 'Q':    player->control = PLAYER_CONTROL_STOP;    goto stop;  case KEY_INFO:  case '?':    if (player->verbosity <= 0) {      show_status(&player->stats, 0, player->input.path, 1);      message("\n");    }    break;  case KEY_TIME:    if (player->verbosity > 0) {      char const *label = 0;      switch (player->stats.show) {      case STATS_SHOW_OVERALL:	player->stats.show = STATS_SHOW_REMAINING;	label = N_("[Current Time Remaining]");	break;      case STATS_SHOW_REMAINING:	player->stats.show = STATS_SHOW_CURRENT;	label = N_("[Current Time]");	break;      case STATS_SHOW_CURRENT:	player->stats.show = STATS_SHOW_OVERALL;	label = N_("[Overall Time]");	break;      }      show_status(&player->stats, 0, gettext(label), 1);    }    break;  case KEY_GAINDECR:  case KEY_GAININCR:  case KEY_GAINZERO:  case KEY_GAININFO:    {      double db;      switch (command) {      case KEY_GAINDECR:	db = set_gain(player, GAIN_ATTAMP | GAIN_RELATIVE, -0.5);	break;      case KEY_GAININCR:	db = set_gain(player, GAIN_ATTAMP | GAIN_RELATIVE, +0.5);	break;      case KEY_GAINZERO:	db = set_gain(player, GAIN_ATTAMP, 0);	break;      default:	db = set_gain(player, 0, 0);	break;      }      if (player->verbosity > 0) {	static char status[15];	sprintf(status, "%+.1f dB gain", db);	show_status(&player->stats, 0, status, 1);      }    }    break;  }  return flow; stop:  stop_audio(player, 1);  return MAD_FLOW_STOP;}# endif/* * NAME:	addfilter() * DESCRIPTION:	insert a filter at the beginning of the filter chain */staticint addfilter(struct player *player, filter_func_t *func, void *data){  struct filter *filter;  filter = filter_new(func, data, player->output.filters);  if (filter == 0)    return -1;  player->output.filters = filter;  return 0;}/* * NAME:	setup_filters() * DESCRIPTION:	create output filters */staticint setup_filters(struct player *player){  /* filters must be added in reverse order */# if defined(EXPERIMENTAL)  if ((player->options & PLAYER_OPTION_EXTERNALMIX) &&      addfilter(player, mixer_filter, stdout) == -1)    return -1;  if ((player->options & PLAYER_OPTION_EXPERIMENTAL) &&      addfilter(player, experimental_filter, 0) == -1)    return -1;# endif  if ((player->options & PLAYER_OPTION_FADEIN) &&      addfilter(player, fadein_filter, player) == -1)    return -1;  addfilter(player, gain_filter, &player->output.gain);  if (player->output.select == PLAYER_CHANNEL_MONO &&      addfilter(player, mono_filter, player) == -1)    return -1;# if defined(USE_TTY)  if ((player->options & PLAYER_OPTION_TTYCONTROL) &&      addfilter(player, tty_filter, player) == -1)    return -1;# endif  return 0;}# if defined(USE_TTY) && !defined(_WIN32)/* * NAME:	restore_tty() * DESCRIPTION:	revert to previous terminal settings */staticint restore_tty(int interrupt){  struct termios tty;  struct sigaction action;  int result = 0;  if (tcgetattr(tty_fd, &tty) == 0 &&      tcsetattr(tty_fd, interrupt ? TCSAFLUSH : TCSADRAIN,		&save_tty) == -1) {    if (!interrupt)      error("tty", ":tcsetattr");    result = -1;  }  save_tty = tty;  if (sigaction(SIGINT, 0, &action) == 0 &&      sigaction(SIGINT, &save_sigint, 0) == -1) {    if (!interrupt)      error("tty", ":sigaction(SIGINT)");    result = -1;  }  save_sigint = action;  if (sigaction(SIGTSTP, 0, &action) == 0 &&      sigaction(SIGTSTP, &save_sigtstp, 0) == -1) {    if (!interrupt)      error("tty", ":sigaction(SIGTSTP)");    result = -1;  }  save_sigtstp = action;  if (!interrupt) {    if (close(tty_fd) == -1) {      error("tty", ":close");      result = -1;    }    tty_fd = -1;  }  return result;}/* * NAME:	signal_handler() * DESCRIPTION:	restore tty state after software interrupt */staticvoid signal_handler(int signal){  static struct sigaction save_sigcont;  /* restore tty state and previous signal actions */  restore_tty(1);  /* handle SIGCONT after SIGTSTP */  switch (signal) {  case SIGTSTP:    {      struct sigaction action;      sigaction(SIGCONT, 0, &save_sigcont);      action = save_sigcont;      action.sa_handler = signal_handler;      sigemptyset(&action.sa_mask);      sigaddset(&action.sa_mask, SIGTSTP);      sigaddset(&action.sa_mask, SIGINT);      action.sa_flags = 0;      sigaction(SIGCONT, &action, 0);    }    break;  case SIGCONT:    sigaction(SIGCONT, &save_sigcont, 0);    on_same_line = 0;  /* redraw status line */    break;  }  /* re-send signal, which is currently blocked */  kill(getpid(), signal);  /* return to previous thread, which should immediately receive the signal */  return;}/* * NAME:	setup_tty() * DESCRIPTION:	change terminal parameters and signal handlers */staticint setup_tty(void){  struct termios tty;  struct sigaction action;  /* open controlling terminal */  tty_fd = open(TTY_DEVICE, O_RDONLY);  if (tty_fd == -1) {    error("tty", ":", TTY_DEVICE);    return -1;  }  /* save current terminal and signal settings */  if (tcgetattr(tty_fd, &save_tty) == -1) {    error("tty", ":tcgetattr");    return -1;  }  if (sigaction(SIGTSTP, 0, &save_sigtstp) == -1) {    error("tty", ":sigaction(SIGTSTP)");    return -1;  }  if (sigaction(SIGINT, 0, &save_sigint) == -1) {    error("tty", ":sigaction(SIGINT)");    return -1;  }  /* catch SIGTSTP and SIGINT so the tty state can be restored */  action = save_sigtstp;  action.sa_handler = signal_handler;  sigemptyset(&action.sa_mask);  sigaddset(&action.sa_mask, SIGINT);# if 0  /* on some systems (Mac OS X) this remains masked upon continue (?!) */  sigaddset(&action.sa_mask, SIGCONT);# endif  action.sa_flags = 0;  if (sigaction(SIGTSTP, &action, 0) == -1) {    error("tty", ":sigaction(SIGTSTP)");    goto fail;  }  action = save_sigint;  action.sa_handler = signal_handler;  sigemptyset(&action.sa_mask);  sigaddset(&action.sa_mask, SIGTSTP);  sigaddset(&action.sa_mask, SIGCONT);  action.sa_flags = 0;  if (sigaction(SIGINT, &action, 0) == -1) {    error("tty", ":sigaction(SIGINT)");    goto fail;  }  /* turn off echo and canonical mode */  tty = save_tty;  tty.c_lflag &= ~(ECHO | ICANON);  /* set VMIN = VTIME = 0 so read() always returns immediately */  tty.c_cc[VMIN]  = 0;  tty.c_cc[VTIME] = 0;  if (tcsetattr(tty_fd, TCSAFLUSH, &tty) == -1) {    error("tty", ":tcsetattr");    goto fail;  }  return 0; fail:  sigaction(SIGINT,  &save_sigint,  0);  sigaction(SIGTSTP, &save_sigtstp, 0);  return -1;}# endif/* * NAME:	silence() * DESCRIPTION:	output silence for a period of time */staticint silence(struct player *player, mad_timer_t duration, char const *label){  union audio_control control;  unsigned int nchannels, speed, nsamples;  mad_fixed_t *samples;  mad_timer_t unit;  int result = 0;  audio_control_init(&control, AUDIO_COMMAND_CONFIG);  control.config.channels = 2;  control.config.speed    = 44100;  if (player->output.command(&control) == -1) {    error("audio", audio_error);    return -1;  }  nchannels = control.config.channels;  speed     = control.config.speed;  nsamples  = speed > MAX_NSAMPLES ? MAX_NSAMPLES : speed;  player->output.channels_in  = nchannels;  player->output.channels_out = nchannels;  player->output.speed_in     = speed;  player->output.speed_out    = speed;  samples = calloc(nsamples, sizeof(mad_fixed_t));  if (samples == 0) {    error("silence", _("not enough memory to allocate sample buffer"));    return -1;  }  audio_control_init(&control, AUDIO_COMMAND_PLAY);  control.play.nsamples   = nsamples;  control.play.samples[0] = samples;  control.play.samples[1] = (nchannels == 2) ? samples : 0;  control.play.mode       = player->output.mode;  control.play.stats      = &player->stats.audio;  mad_timer_set(&unit, 0, nsamples, speed);  for (mad_timer_negate(&duration);       mad_timer_sign(duration) < 0;       mad_timer_add(&duration, unit)) {    if (mad_timer_compare(unit, mad_timer_abs(duration)) > 0) {      unit = mad_timer_abs(duration);      control.play.nsamples = mad_timer_fraction(unit, speed);    }# if defined(USE_TTY)    if ((player->options & PLAYER_OPTION_TTYCONTROL) &&	tty_filter(player, 0) != MAD_FLOW_CONTINUE)      goto fail;# endif    if (player->output.command(&control) == -1) {      error("audio", audio_error);      goto fail;    }    mad_timer_add(&player->stats.global_timer, unit);    if (player->verbosity > 0)      show_status(&player->stats, 0, label, 0);  }  if (0) {  fail:    result = -1;  }  free(samples);  return result;}/* * NAME:	player->run() * DESCRIPTION:	begin playback */int player_run(struct player *player, int argc, char const *argv[]){  int result = 0;  union audio_control control;  player->playlist.entries = argv;  player->playlist.length  = argc;  /* set up terminal settings */# if defined(USE_TTY) && !defined(_WIN32)  if ((player->options & PLAYER_OPTION_TTYCONTROL) &&      setup_tty() == -1)    player->options &= ~PLAYER_OPTION_TTYCONTROL;# endif  /* initialize ancillary data output file */  if (player->ancillary.path) {    if (player->output.path &&	strcmp(player->ancillary.path, player->output.path) == 0) {      error("output", _("ancillary and audio output have same path"));      goto fail;    }    if (strcmp(player->ancillary.path, "-") == 0)      player->ancillary.file = stdout;    else {      player->ancillary.file = fopen(player->ancillary.path, "wb");      if (player->ancillary.file == 0) {	error("ancillary", ":", player->ancillary.path);	goto fail;      }    }  }  /* set up filters */  if (setup_filters(player) == -1) {    error("filter", _("not enough memory to allocate filters"));    goto fail;  }  set_gain(player, 0, 0);  /* initialize audio */  if (player->output.command) {    audio_control_init(&control, AUDIO_COMMAND_INIT);    control.init.path = player->output.path;    if (player->output.command(&control) == -1) {      error("audio", audio_error, control.init.path);      goto fail;    }    if ((player->options & PLAYER_OPTION_SKIP) &&	mad_timer_sign(player->global_start) < 0) {      player->stats.global_timer = player->global_start;      if (silence(player, mad_timer_abs(player->global_start),		  _("lead-in")) == -1)	result = -1;    }  }  /* run playlist */  if (result == 0)    result = play_all(player);  /* drain and close audio */  if (player->output.command) {    audio_control_init(&control, AUDIO_COMMAND_FINISH);    if (player->output.command(&control) == -1) {      error("audio", audio_error);      goto fail;    }  }  if (0) {  fail:    result = -1;  }  /* drain and close ancillary data output file */  if (player->ancillary.file) {    if (player->ancillary.length) {      if (fputc(player->ancillary.buffer << (8 - player->ancillary.length),		player->ancillary.file) == EOF &&	  result == 0) {	error("ancillary", ":fputc");	result = -1;      }      player->ancillary.length = 0;    }    if (player->ancillary.file != stdout &&	fclose(player->ancillary.file) == EOF &&	result == 0) {      error("ancillary", ":fclose");      result = -1;    }    player->ancill

⌨️ 快捷键说明

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