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

📄 player.c

📁 mp3 plyer linux version
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * madplay - MPEG audio decoder and player * Copyright (C) 2000-2004 Robert Leslie * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * $Id: player.c,v 1.69 2004/02/23 21:34:53 rob Exp $ */# ifdef HAVE_CONFIG_H#  include "config.h"# endif# include "global.h"# include <stdio.h># include <stdarg.h># include <stdlib.h># ifdef HAVE_SYS_TYPES_H#  include <sys/types.h># endif# include <sys/stat.h># ifdef HAVE_FCNTL_H#  include <fcntl.h># endif# ifdef HAVE_UNISTD_H#  include <unistd.h># endif# include <string.h># ifdef HAVE_ERRNO_H#  include <errno.h># endif# include <time.h># include <locale.h># include <math.h># ifdef HAVE_TERMIOS_H#  include <termios.h># endif# ifdef _WIN32#  include <windows.h># endif# include <signal.h># ifdef HAVE_ASSERT_H#  include <assert.h># endif# if defined(HAVE_MMAP)#  include <sys/mman.h># endif# if !defined(O_BINARY)#  define O_BINARY  0# endif# include <mad.h># include <id3tag.h># include "gettext.h"# include "player.h"# include "audio.h"# include "resample.h"# include "filter.h"# include "tag.h"# include "rgain.h"# define MPEG_BUFSZ	40000	/* 2.5 s at 128 kbps; 1 s at 320 kbps */# define FREQ_TOLERANCE	2	/* percent sampling frequency tolerance */# define TTY_DEVICE	"/dev/tty"# define KEY_CTRL(key)	((key) & 0x1f)enum {  KEY_PAUSE    = 'p',  KEY_STOP     = 's',  KEY_FORWARD  = 'f',  KEY_BACK     = 'b',  KEY_TIME     = 't',  KEY_QUIT     = 'q',  KEY_INFO     = 'i',  KEY_GAINDECR = '-',  KEY_GAININCR = '+',  KEY_GAINZERO = '_',  KEY_GAININFO = '='};static int on_same_line;# if defined(USE_TTY) && !defined(_WIN32)static int tty_fd = -1;static struct termios save_tty;static struct sigaction save_sigtstp, save_sigint;# endif/* * NAME:	player_init() * DESCRIPTION:	initialize player structure */void player_init(struct player *player){  player->verbosity = 0;  player->options = 0;  player->repeat  = 1;  player->control = PLAYER_CONTROL_DEFAULT;  player->playlist.entries = 0;  player->playlist.length  = 0;  player->playlist.current = 0;  player->global_start = mad_timer_zero;  player->global_stop  = mad_timer_zero;  player->fade_in      = mad_timer_zero;  player->fade_out     = mad_timer_zero;  player->gap          = mad_timer_zero;  player->input.path   = 0;  player->input.fd     = -1;# if defined(HAVE_MMAP)  player->input.fdm    = 0;# endif  player->input.data   = 0;  player->input.length = 0;  player->input.eof    = 0;  tag_init(&player->input.tag);  player->output.mode          = AUDIO_MODE_DITHER;  player->output.voladj_db     = 0;  player->output.attamp_db     = 0;  player->output.gain          = MAD_F_ONE;  player->output.replay_gain   = 0;  player->output.filters       = 0;  player->output.channels_in   = 0;  player->output.channels_out  = 0;  player->output.select        = PLAYER_CHANNEL_DEFAULT;  player->output.speed_in      = 0;  player->output.speed_out     = 0;  player->output.speed_request = 0;  player->output.precision_in  = 0;  player->output.precision_out = 0;  player->output.path          = 0;  player->output.command       = 0;  /* player->output.resample */  player->output.resampled     = 0;  player->ancillary.path       = 0;  player->ancillary.file       = 0;  player->ancillary.buffer     = 0;  player->ancillary.length     = 0;  player->stats.show                  = STATS_SHOW_OVERALL;  player->stats.label                 = 0;  player->stats.total_bytes           = 0;  player->stats.total_time            = mad_timer_zero;  player->stats.global_timer          = mad_timer_zero;  player->stats.absolute_timer        = mad_timer_zero;  player->stats.play_timer            = mad_timer_zero;  player->stats.global_framecount     = 0;  player->stats.absolute_framecount   = 0;  player->stats.play_framecount       = 0;  player->stats.error_frame           = -1;  player->stats.mute_frame            = 0;  player->stats.vbr                   = 0;  player->stats.bitrate               = 0;  player->stats.vbr_frames            = 0;  player->stats.vbr_rate              = 0;  player->stats.nsecs                 = 0;  player->stats.audio.clipped_samples = 0;  player->stats.audio.peak_clipping   = 0;  player->stats.audio.peak_sample     = 0;}/* * NAME:	player_finish() * DESCRIPTION:	destroy a player structure */void player_finish(struct player *player){  if (player->output.filters)    filter_free(player->output.filters);  if (player->output.resampled) {    resample_finish(&player->output.resample[0]);    resample_finish(&player->output.resample[1]);    free(player->output.resampled);    player->output.resampled = 0;  }}/* * NAME:	message() * DESCRIPTION:	show a message, possibly overwriting a previous w/o newline */staticint message(char const *format, ...){  int len, newline, result;  va_list args;  len = strlen(format);  newline = (len > 0 && format[len - 1] == '\n');  if (on_same_line && newline && len > 1)    fputc('\n', stderr);  va_start(args, format);  result = vfprintf(stderr, format, args);  va_end(args);  if (on_same_line && !newline && result < on_same_line) {    unsigned int i;    i = on_same_line - result;    while (i--)      putc(' ', stderr);  }  on_same_line = newline ? 0 : result;  if (!newline) {    fputc('\r', stderr);    fflush(stderr);  }  return result;}/* * NAME:	detail() * DESCRIPTION:	show right-aligned label and line-wrap corresponding text */staticvoid detail(char const *label, char const *format, ...){  char const spaces[] = "               ";  va_list args;# define LINEWRAP  (80 - sizeof(spaces) - 2 - 2)  if (on_same_line)    message("\n");  if (label) {    unsigned int len;    len = strlen(label);    assert(len < sizeof(spaces));    fprintf(stderr, "%s%s: ", &spaces[len], label);  }  else    fprintf(stderr, "%s  ", spaces);  va_start(args, format);  if (format) {    vfprintf(stderr, format, args);    fputc('\n', stderr);  }  else {    char *ptr, *newline, *linebreak;    /* N.B. this argument must be mutable! */    ptr = va_arg(args, char *);    do {      newline = strchr(ptr, '\n');      if (newline)	*newline = 0;      if (strlen(ptr) > LINEWRAP) {	linebreak = ptr + LINEWRAP;	while (linebreak > ptr && *linebreak != ' ')	  --linebreak;	if (*linebreak == ' ') {	  if (newline)	    *newline = '\n';	  *(newline = linebreak) = 0;	}      }      fprintf(stderr, "%s\n", ptr);      if (newline) {	ptr = newline + 1;	fprintf(stderr, "%s  ", spaces);      }    }    while (newline);  }  va_end(args);}/* * NAME:	error() * DESCRIPTION:	show an error using proper interaction with message() */staticvoid error(char const *id, char const *format, ...){  int err;  va_list args;  err = errno;  if (on_same_line)    message("\n");  if (id)    fprintf(stderr, "%s: ", id);  va_start(args, format);  if (*format == ':') {    if (format[1] == 0) {      format = va_arg(args, char const *);      errno = err;      perror(format);    }    else {      errno = err;      perror(format + 1);    }  }  else {    vfprintf(stderr, format, args);    fputc('\n', stderr);  }  va_end(args);}# if defined(HAVE_MMAP)/* * NAME:	map_file() * DESCRIPTION:	map the contents of a file into memory */staticvoid *map_file(int fd, unsigned long length){  void *fdm;  fdm = mmap(0, length, PROT_READ, MAP_SHARED, fd, 0);  if (fdm == MAP_FAILED)    return 0;# if defined(HAVE_MADVISE)  madvise(fdm, length, MADV_SEQUENTIAL);# endif  return fdm;}/* * NAME:	unmap_file() * DESCRIPTION:	undo a file mapping */staticint unmap_file(void *fdm, unsigned long length){  if (munmap(fdm, length) == -1)    return -1;  return 0;}/* * NAME:	decode->input_mmap() * DESCRIPTION:	(re)fill decoder input buffer from a memory map */staticenum mad_flow decode_input_mmap(void *data, struct mad_stream *stream){  struct player *player = data;  struct input *input = &player->input;  if (input->eof)    return MAD_FLOW_STOP;  if (stream->next_frame) {    struct stat stat;    unsigned long posn, left;    if (fstat(input->fd, &stat) == -1)      return MAD_FLOW_BREAK;    posn = stream->next_frame - input->fdm;    /* check for file size change and update map */    if (stat.st_size > input->length) {      if (unmap_file(input->fdm, input->length) == -1) {	input->fdm  = 0;	input->data = 0;	return MAD_FLOW_BREAK;      }      player->stats.total_bytes += stat.st_size - input->length;      input->length = stat.st_size;      input->fdm = map_file(input->fd, input->length);      if (input->fdm == 0) {	input->data = 0;	return MAD_FLOW_BREAK;      }      mad_stream_buffer(stream, input->fdm + posn, input->length - posn);      return MAD_FLOW_CONTINUE;    }    /* end of memory map; append MAD_BUFFER_GUARD zero bytes */    left = input->length - posn;    input->data = malloc(left + MAD_BUFFER_GUARD);    if (input->data == 0)      return MAD_FLOW_BREAK;    input->eof = 1;    memcpy(input->data, input->fdm + posn, left);    memset(input->data + left, 0, MAD_BUFFER_GUARD);    mad_stream_buffer(stream, input->data, left + MAD_BUFFER_GUARD);    return MAD_FLOW_CONTINUE;  }  /* first call */  mad_stream_buffer(stream, input->fdm, input->length);  return MAD_FLOW_CONTINUE;}# endif/* * NAME:	decode->input_read() * DESCRIPTION:	(re)fill decoder input buffer by reading a file descriptor */staticenum mad_flow decode_input_read(void *data, struct mad_stream *stream){  struct player *player = data;  struct input *input = &player->input;  int len;  if (input->eof)    return MAD_FLOW_STOP;  if (stream->next_frame) {    memmove(input->data, stream->next_frame,	    input->length = &input->data[input->length] - stream->next_frame);  }  do {    len = read(input->fd, input->data + input->length,	       MPEG_BUFSZ - input->length);  }  while (len == -1 && errno == EINTR);  if (len == -1) {    error("input", ":read");    return MAD_FLOW_BREAK;  }  else if (len == 0) {    input->eof = 1;    assert(MPEG_BUFSZ - input->length >= MAD_BUFFER_GUARD);    while (len < MAD_BUFFER_GUARD)      input->data[input->length + len++] = 0;  }  mad_stream_buffer(stream, input->data, input->length += len);  return MAD_FLOW_CONTINUE;}/* * NAME:	decode->header() * DESCRIPTION:	decide whether to continue decoding based on header */staticenum mad_flow decode_header(void *data, struct mad_header const *header){  struct player *player = data;  if ((player->options & PLAYER_OPTION_TIMED) &&      mad_timer_compare(player->stats.global_timer, player->global_stop) > 0)    return MAD_FLOW_STOP;  /* accounting (except first frame) */  if (player->stats.absolute_framecount) {    ++player->stats.absolute_framecount;    mad_timer_add(&player->stats.absolute_timer, header->duration);    ++player->stats.global_framecount;    mad_timer_add(&player->stats.global_timer, header->duration);    if ((player->options & PLAYER_OPTION_SKIP) &&	mad_timer_compare(player->stats.global_timer,			  player->global_start) < 0)      return MAD_FLOW_IGNORE;  }  return MAD_FLOW_CONTINUE;}/* * NAME:	write_ancillary() * DESCRIPTION:	pack ancillary data into octets and output */staticint write_ancillary(struct ancillary *ancillary,		    struct mad_bitptr ptr, unsigned int length){  if (ancillary->length) {    unsigned int balance;    balance = 8 - ancillary->length;    if (balance > length) {      ancillary->buffer =	(ancillary->buffer << length) | mad_bit_read(&ptr, length);      ancillary->length += length;      return 0;    }    else {

⌨️ 快捷键说明

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