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

📄 mpg123.c

📁 xmms-1.2.10.tar.gz学习使用的就下吧
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Function mpg123_get_id3v2 (id3d, tag) * *    Get desired contents from the indicated id3tag and store it in *    `tag'.  * */void mpg123_get_id3v2(struct id3_tag *id3d, struct id3tag_t *tag){	struct id3_frame *id3frm;	gchar *txt;	gint tlen, num;#define ID3_SET(_tid,_fld) 						\{									\	id3frm = id3_get_frame( id3d, _tid, 1 );			\	if (id3frm) {							\		txt = _tid == ID3_TCON ? id3_get_content(id3frm)	\		    : id3_get_text(id3frm);				\		if(txt)							\		{							\			tlen = strlen(txt);				\			if ( tlen >= sizeof(tag->_fld) ) 		\				tlen = sizeof(tag->_fld)-1;		\			strncpy( tag->_fld, txt, tlen );		\			tag->_fld[tlen] = 0;				\			g_free(txt);					\		}							\		else							\			tag->_fld[0] = 0;				\	} else {							\		tag->_fld[0] = 0;					\	}								\}#define ID3_SET_NUM(_tid,_fld)				\{							\	id3frm = id3_get_frame(id3d, _tid, 1);		\	if (id3frm) {					\		num = id3_get_text_number(id3frm);	\		tag->_fld = num >= 0 ? num : 0;		\	} else						\		tag->_fld = 0;				\}	ID3_SET		(ID3_TIT2, title);	ID3_SET		(ID3_TPE1, artist);	if (strlen(tag->artist) == 0)		ID3_SET(ID3_TPE2, artist);	ID3_SET		(ID3_TALB, album);	ID3_SET_NUM	(ID3_TYER, year);	ID3_SET_NUM	(ID3_TRCK, track_number);	ID3_SET		(ID3_COMM, comment);	ID3_SET		(ID3_TCON, genre);}/* * Function get_song_title (fd, filename) * *    Get song title of file.  File position of `fd' will be *    clobbered.  `fd' may be NULL, in which case `filename' is opened *    separately.  The returned song title must be subsequently freed *    using g_free(). * */static gchar *get_song_title(FILE * fd, char *filename){	FILE *file = fd;	char *ret = NULL;	struct id3v1tag_t id3v1tag;	struct id3tag_t id3tag;	if (file || (file = fopen(filename, "rb")) != 0)	{		struct id3_tag *id3 = NULL;		/*		 * Try reading ID3v2 tag.		 */		if (!mpg123_cfg.disable_id3v2)		{			fseek(file, 0, SEEK_SET);			id3 = id3_open_fp(file, 0);			if (id3)			{				mpg123_get_id3v2(id3, &id3tag);				ret = mpg123_format_song_title(&id3tag, filename);				id3_close(id3);			}		}		/*		 * Try reading ID3v1 tag.		 */		if (!id3 && (fseek(file, -1 * sizeof (id3v1tag), SEEK_END) == 0) &&		    (fread(&id3v1tag, 1, sizeof (id3v1tag), file) == sizeof (id3v1tag)) &&		    (strncmp(id3v1tag.tag, "TAG", 3) == 0))		{			mpg123_id3v1_to_id3v2(&id3v1tag, &id3tag);			ret = mpg123_format_song_title(&id3tag, filename);		}		if (!fd)			/*			 * File was opened in this function.			 */			fclose(file);	}	if (ret == NULL)		/*		 * Unable to get ID3 tag.		 */		ret = mpg123_format_song_title(NULL, filename);	return ret;}static long get_song_length(FILE *file){	int len;	char tmp[4];	fseek(file, 0, SEEK_END);	len = ftell(file);	fseek(file, -128, SEEK_END);	fread(tmp, 1, 3, file);	if (!strncmp(tmp, "TAG", 3))		len -= 128;	return len;}static guint get_song_time(FILE * file){	guint32 head;	guchar tmp[4], *buf;	struct frame frm;	xing_header_t xing_header;	double tpf, bpf;	guint32 len;	if (!file)		return -1;	fseek(file, 0, SEEK_SET);	if (fread(tmp, 1, 4, file) != 4)		return 0;	head = convert_to_header(tmp);	while (!mpg123_head_check(head))	{		head <<= 8;		if (fread(tmp, 1, 1, file) != 1)			return 0;		head |= tmp[0];	}	if (mpg123_decode_header(&frm, head))	{		buf = g_malloc(frm.framesize + 4);		fseek(file, -4, SEEK_CUR);		fread(buf, 1, frm.framesize + 4, file);		tpf = mpg123_compute_tpf(&frm);		if (mpg123_get_xing_header(&xing_header, buf))		{			g_free(buf);			if (xing_header.bytes == 0)				xing_header.bytes = get_song_length(file);			return (tpf * xing_header.frames * 1000);		}		g_free(buf);		bpf = mpg123_compute_bpf(&frm);		len = get_song_length(file);		return ((guint)(len / bpf) * tpf * 1000);	}	return 0;}static void get_song_info(char *filename, char **title_real, int *len_real){	FILE *file;	(*len_real) = -1;	(*title_real) = NULL;	/*	 * TODO: Getting song info from http streams.	 */	if (strncasecmp(filename, "http://", 7))	{		if ((file = fopen(filename, "rb")) != NULL)		{			(*len_real) = get_song_time(file);			(*title_real) = get_song_title(file, filename);			fclose(file);		}	}}static int open_output(void){	int r;	AFormat fmt = mpg123_cfg.resolution == 16 ? FMT_S16_NE : FMT_U8;	int freq = mpg123_freqs[fr.sampling_frequency] >> mpg123_cfg.downsample;	int channels = mpg123_cfg.channels == 2 ? fr.stereo : 1;	r = mpg123_ip.output->open_audio(fmt, freq, channels);	if (r && dopause)	{		mpg123_ip.output->pause(TRUE);		dopause = FALSE;	}	return r;}static int mpg123_seek(struct frame *fr, xing_header_t *xh, gboolean vbr, int time){	int jumped = -1;		if (xh)	{		int percent = ((double) time * 100.0) /			(mpg123_info->num_frames * mpg123_info->tpf);		int byte = mpg123_seek_point(xh, percent);		jumped = mpg123_stream_jump_to_byte(fr, byte);	}	else if (vbr && mpg123_length > 0)	{		int byte = ((guint64)time * 1000 * mpg123_info->filesize) /			mpg123_length;		jumped = mpg123_stream_jump_to_byte(fr, byte);	}	else	{		int frame = time / mpg123_info->tpf;		jumped = mpg123_stream_jump_to_frame(fr, frame);	}	return jumped;}static void *decode_loop(void *arg){	gboolean have_xing_header = FALSE, vbr = FALSE;	int disp_count = 0, temp_time;	char *filename = arg;	xing_header_t xing_header;	/* This is used by fileinfo on http streams */	mpg123_bitrate = 0;	mpg123_pcm_sample = g_malloc0(32768);	mpg123_pcm_point = 0;	mpg123_filename = filename;	mpg123_read_frame_init();	mpg123_open_stream(filename, -1);	if (mpg123_info->eof || !mpg123_read_frame(&fr))		mpg123_info->eof = TRUE;	if (!mpg123_info->eof && mpg123_info->going)	{		if (mpg123_cfg.channels == 2)			fr.single = -1;		else			fr.single = 3;		fr.down_sample = mpg123_cfg.downsample;		fr.down_sample_sblimit = SBLIMIT >> mpg123_cfg.downsample;		set_synth_functions(&fr);		mpg123_init_layer3(fr.down_sample_sblimit);		mpg123_info->tpf = mpg123_compute_tpf(&fr);		if (strncasecmp(filename, "http://", 7))		{			if (mpg123_stream_check_for_xing_header(&fr, &xing_header))			{				mpg123_info->num_frames = xing_header.frames;				have_xing_header = TRUE;				if (xing_header.bytes == 0)				{					if (mpg123_info->filesize > 0)						xing_header.bytes = mpg123_info->filesize;					else						have_xing_header = FALSE;				}				mpg123_read_frame(&fr);			}		}		for (;;)		{			memcpy(&temp_fr, &fr, sizeof(struct frame));			if (!mpg123_read_frame(&temp_fr))			{				mpg123_info->eof = TRUE;				break;			}			if (fr.lay != temp_fr.lay ||			    fr.sampling_frequency != temp_fr.sampling_frequency ||	        	    fr.stereo != temp_fr.stereo || fr.lsf != temp_fr.lsf)				memcpy(&fr,&temp_fr,sizeof(struct frame));			else				break;		}		if (!have_xing_header && strncasecmp(filename, "http://", 7))			mpg123_info->num_frames = mpg123_calc_numframes(&fr);		memcpy(&fr, &temp_fr, sizeof(struct frame));		mpg123_bitrate = tabsel_123[fr.lsf][fr.lay - 1][fr.bitrate_index];		disp_bitrate = mpg123_bitrate;		mpg123_frequency = mpg123_freqs[fr.sampling_frequency];		mpg123_stereo = fr.stereo;		mpg123_layer = fr.lay;		mpg123_lsf = fr.lsf;		mpg123_mpeg25 = fr.mpeg25;		mpg123_mode = fr.mode;		if (strncasecmp(filename, "http://", 7))		{			mpg123_length =				mpg123_info->num_frames * mpg123_info->tpf * 1000;			if (!mpg123_title)				mpg123_title = get_song_title(NULL,filename);		}		else		{			if (!mpg123_title)				mpg123_title = mpg123_http_get_title(filename);			mpg123_length = -1;		}		mpg123_ip.set_info(mpg123_title, mpg123_length,				   mpg123_bitrate * 1000,				   mpg123_freqs[fr.sampling_frequency],				   fr.stereo);		output_opened = TRUE;		if (!open_output())		{			audio_error = TRUE;			mpg123_info->eof = TRUE;		}		else			play_frame(&fr);	}	mpg123_info->first_frame = FALSE;	while (mpg123_info->going)	{		if (mpg123_info->jump_to_time != -1)		{			void *xp = NULL;			if (have_xing_header)				xp = &xing_header;			if (mpg123_seek(&fr, xp, vbr,					mpg123_info->jump_to_time) > -1)			{				mpg123_ip.output->flush(mpg123_info->jump_to_time * 1000);				mpg123_info->eof = FALSE;			}			mpg123_info->jump_to_time = -1;		}		if (!mpg123_info->eof)		{			if (mpg123_read_frame(&fr) != 0)			{				if(fr.lay != mpg123_layer || fr.lsf != mpg123_lsf)				{					memcpy(&temp_fr, &fr, sizeof(struct frame));					if(mpg123_read_frame(&temp_fr) != 0)					{						if(fr.lay == temp_fr.lay && fr.lsf == temp_fr.lsf)						{							mpg123_layer = fr.lay;							mpg123_lsf = fr.lsf;							memcpy(&fr,&temp_fr,sizeof(struct frame));						}						else						{							memcpy(&fr,&temp_fr,sizeof(struct frame));							skip_frames = 2;							mpg123_info->output_audio = FALSE;							continue;						}											}				}				if(mpg123_freqs[fr.sampling_frequency] != mpg123_frequency || mpg123_stereo != fr.stereo)				{					memcpy(&temp_fr,&fr,sizeof(struct frame));					if(mpg123_read_frame(&temp_fr) != 0)					{						if(fr.sampling_frequency == temp_fr.sampling_frequency && temp_fr.stereo == fr.stereo)						{							mpg123_ip.output->buffer_free();							mpg123_ip.output->buffer_free();							while(mpg123_ip.output->buffer_playing() && mpg123_info->going && mpg123_info->jump_to_time == -1)								xmms_usleep(20000);							if(!mpg123_info->going)								break;							temp_time = mpg123_ip.output->output_time();							mpg123_ip.output->close_audio();							mpg123_frequency = mpg123_freqs[fr.sampling_frequency];							mpg123_stereo = fr.stereo;							if (!mpg123_ip.output->open_audio(mpg123_cfg.resolution == 16 ? FMT_S16_NE : FMT_U8,								mpg123_freqs[fr.sampling_frequency] >> mpg123_cfg.downsample,				  				mpg123_cfg.channels == 2 ? fr.stereo : 1))							{								audio_error = TRUE;								mpg123_info->eof = TRUE;							}							mpg123_ip.output->flush(temp_time);							mpg123_ip.set_info(mpg123_title, mpg123_length, mpg123_bitrate * 1000, mpg123_frequency, mpg123_stereo);							memcpy(&fr,&temp_fr,sizeof(struct frame));						}						else						{							memcpy(&fr,&temp_fr,sizeof(struct frame));							skip_frames = 2;							mpg123_info->output_audio = FALSE;							continue;						}					}									}								if (tabsel_123[fr.lsf][fr.lay - 1][fr.bitrate_index] != mpg123_bitrate)					mpg123_bitrate = tabsel_123[fr.lsf][fr.lay - 1][fr.bitrate_index];								if (!disp_count)				{					disp_count = 20;					if (mpg123_bitrate != disp_bitrate)					{						/* FIXME networks streams */						disp_bitrate = mpg123_bitrate;						if(!have_xing_header && strncasecmp(filename,"http://",7))						{							double rel = mpg123_relative_pos();							if (rel)							{								mpg123_length = mpg123_ip.output->written_time() / rel;								vbr = TRUE;							}							if (rel == 0 || !(mpg123_length > 0))							{								mpg123_info->num_frames = mpg123_calc_numframes(&fr);								mpg123_info->tpf = mpg123_compute_tpf(&fr);								mpg123_length = mpg123_info->num_frames * mpg123_info->tpf * 1000;							}						}						mpg123_ip.set_info(mpg123_title, mpg123_length, mpg123_bitrate * 1000, mpg123_frequency, mpg123_stereo);					}				}				else					disp_count--;				play_frame(&fr);			}			else			{				mpg123_ip.output->buffer_free();				mpg123_ip.output->buffer_free();				mpg123_info->eof = TRUE;				xmms_usleep(10000);			}		}		else		{			xmms_usleep(10000);		}	}	g_free(mpg123_title);	mpg123_title = NULL;	mpg123_stream_close();	if (output_opened && !audio_error)		mpg123_ip.output->close_audio();	g_free(mpg123_pcm_sample);	mpg123_filename = NULL;	g_free(filename);	pthread_exit(NULL);}static void play_file(char *filename){	memset(&fr, 0, sizeof (struct frame));	memset(&temp_fr, 0, sizeof (struct frame));	mpg123_info = g_malloc0(sizeof (PlayerInfo));	mpg123_info->going = 1;	mpg123_info->first_frame = TRUE;	mpg123_info->output_audio = TRUE;	mpg123_info->jump_to_time = -1;	skip_frames = 0;	audio_error = FALSE;	output_opened = FALSE;	dopause = FALSE;	pthread_create(&decode_thread, NULL, decode_loop, g_strdup(filename));}static void stop(void){	if (mpg123_info && mpg123_info->going)	{		mpg123_info->going = FALSE;		pthread_join(decode_thread, NULL);		g_free(mpg123_info);		mpg123_info = NULL;	}}static void seek(int time){	mpg123_info->jump_to_time = time;	while (mpg123_info->jump_to_time != -1)		xmms_usleep(10000);}static void do_pause(short p){	if (output_opened)		mpg123_ip.output->pause(p);	else		dopause = p;}static int get_time(void){	if (audio_error)		return -2;	if (!mpg123_info)		return -1;	if (!mpg123_info->going || (mpg123_info->eof && !mpg123_ip.output->buffer_playing()))		return -1;	return mpg123_ip.output->output_time();}static void aboutbox(void){	static GtkWidget *aboutbox;	if (aboutbox != NULL)		return;		aboutbox = xmms_show_message(		_("About MPEG Layer 1/2/3 plugin"),		_("mpg123 decoding engine by Michael Hipp <mh@mpg123.de>\n"		  "Plugin by The XMMS team"),		_("Ok"), FALSE, NULL, NULL);	gtk_signal_connect(GTK_OBJECT(aboutbox), "destroy",			   GTK_SIGNAL_FUNC(gtk_widget_destroyed), &aboutbox);}InputPlugin mpg123_ip ={	NULL,	NULL,	NULL, /* Description */	init,	aboutbox,	mpg123_configure,	is_our_file,	NULL,	play_file,	stop,	do_pause,	seek,	mpg123_set_eq,	get_time,	NULL, NULL, NULL,	NULL, NULL, NULL, NULL,	get_song_info,	mpg123_file_info_box,	/* file_info_box */	NULL};InputPlugin *get_iplugin_info(void){	mpg123_ip.description =		g_strdup_printf(_("MPEG Layer 1/2/3 Player %s"), VERSION);	return &mpg123_ip;}

⌨️ 快捷键说明

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