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

📄 audio.c

📁 xmms-1.2.10.tar.gz学习使用的就下吧
💻 C
字号:
/*  XMMS - Cross-platform multimedia player *  Copyright (C) 1998-2001  Peter Alm, Mikael Alm, Olle Hallnas, *                           Thomas Nilsson and 4Front Technologies *  Copyright (C) 1999       Galex Yen *  Copyright (C) 1999-2001  Haavard Kvaalen * *  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. */#include "esdout.h"#include "config.h"static gint fd = 0;static gpointer buffer;static gboolean going = FALSE, paused = FALSE, prebuffer, remove_prebuffer;static gint buffer_size, prebuffer_size, blk_size = 4096;static gint rd_index = 0, wr_index = 0;static gint output_time_offset = 0;static guint64 written = 0, output_bytes = 0;static gint bps, ebps;static gint flush;static gint format, channels, frequency, latency;static esd_format_t esd_format;static gint input_bps, input_format, input_frequency, input_channels;static pthread_t buffer_thread;static gboolean realtime = FALSE;static void *(*esd_translate)(void *, gint);static gint get_latency(void){	int fd, amount = 0;#ifndef HAVE_ESD_GET_LATENCY	esd_server_info_t *info;#endif	fd = esd_open_sound(esd_cfg.hostname);	if (fd == -1)		return 0;#ifdef HAVE_ESD_GET_LATENCY	amount = esd_get_latency(fd);#else	info = esd_get_server_info(fd);	if (info)	{		if (info->format & ESD_STEREO)		{			if (info->format & ESD_BITS16)				amount = (44100 * (ESD_BUF_SIZE + 64)) / info->rate;			else				amount = (44100 * (ESD_BUF_SIZE + 128)) / info->rate;		}		else		{			if (info->format & ESD_BITS16)				amount = (2 * 44100 * (ESD_BUF_SIZE + 128)) / info->rate;			else				amount = (2 * 44100 * (ESD_BUF_SIZE + 256)) / info->rate;		}		free(info);	}	amount += ESD_BUF_SIZE * 2;#endif	esd_close(fd);	return amount;}static void *esd_stou8(void *data, gint length){	int len = length;	unsigned char *dat = (unsigned char *)data;	while (len-- > 0)		*dat++ ^= 0x80;	return data;}static void *esd_utos16sw(void *data, gint length){	int len = length;	short *dat = data;	while ( len > 0 ) {		*dat = GUINT16_SWAP_LE_BE( *dat ) ^ 0x8000;		dat++;		len-=2;	}	return data;}static void *esd_utos16(void *data, gint length){	int len = length;	short *dat = data;	while ( len > 0 ) {		*dat ^= 0x8000;		dat++;		len-=2;	}	return data;}static void *esd_16sw(void *data, gint length){	int len = length;	short *dat = data;	while ( len > 0 ) {		*dat = GUINT16_SWAP_LE_BE( *dat );		dat++;		len-=2;	}	return data;}static void esdout_setup_format(AFormat fmt,gint rate, gint nch){	gboolean swap_sign = FALSE;	gboolean swap_16 = FALSE;	format = fmt;	frequency = rate;	channels = nch;	switch (fmt)	{		case FMT_S8:			swap_sign = TRUE;		case FMT_U8:			esd_format = ESD_BITS8;			break;		case FMT_U16_LE:		case FMT_U16_BE:		case FMT_U16_NE:			swap_sign = TRUE;		case FMT_S16_LE:		case FMT_S16_BE:		case FMT_S16_NE:			esd_format = ESD_BITS16;			break;	}#ifdef WORDS_BIGENDIAN	if (fmt == FMT_U16_LE || fmt == FMT_S16_LE)#else	if (fmt == FMT_U16_BE || fmt == FMT_S16_BE)#endif		swap_16 = TRUE;	esd_translate = (void*(*)())NULL;	if (esd_format == ESD_BITS8) {		if (swap_sign == TRUE)			esd_translate = esd_stou8;	} else {		if (swap_sign == TRUE) {			if (swap_16 == TRUE)				esd_translate = esd_utos16sw;			else				esd_translate = esd_utos16;		} else {			if (swap_16 == TRUE)				esd_translate = esd_16sw;		}	}	bps = rate * nch;	if (esd_format == ESD_BITS16)		bps *= 2;	if(nch == 1)		esd_format |= ESD_MONO;	else		esd_format |= ESD_STEREO;	esd_format |= ESD_STREAM | ESD_PLAY;		latency = ((get_latency() * frequency) / 44100) * channels;	if (format != FMT_U8 && format != FMT_S8)		latency *= 2;}	gint esdout_get_written_time(void){	if (!going)		return 0;	return (gint) ((written * 1000) / input_bps);}gint esdout_get_output_time(void){	guint64 bytes;	if (!fd || !going)		return 0;	bytes = output_bytes;	if (!paused)		bytes -= (bytes < latency ? bytes : latency);		return output_time_offset + (bytes * 1000) / ebps;}gint esdout_used(void){	if (realtime)		return 0;	else	{		if (wr_index >= rd_index)			return wr_index - rd_index;		return buffer_size - (rd_index - wr_index);	}}gint esdout_playing(void){	if (!going)		return FALSE;	if (!esdout_used())		return FALSE;	return TRUE;}gint esdout_free(void){	if (!realtime)	{		if (remove_prebuffer && prebuffer)		{			prebuffer = FALSE;			remove_prebuffer = FALSE;		}		if (prebuffer)			remove_prebuffer = TRUE;		if (rd_index > wr_index)			return (rd_index - wr_index) - 1;		return (buffer_size - (wr_index - rd_index)) - 1;	}	else	{		if (paused)			return 0;		else			return 1000000;	}}static void esdout_write_audio(gpointer data,gint length){	AFormat new_format;	gint new_frequency,new_channels;	EffectPlugin *ep;		new_format = input_format;	new_frequency = input_frequency;	new_channels = input_channels;		ep = get_current_effect_plugin();	if(effects_enabled() && ep && ep->query_format)	{		ep->query_format(&new_format,&new_frequency,&new_channels);	}		if(new_format != format || new_frequency != frequency || new_channels != channels)	{		output_time_offset += (output_bytes * 1000) / ebps;		output_bytes = 0;		esdout_setup_format(new_format, new_frequency, new_channels);		frequency = new_frequency;		channels = new_channels;		esd_close(fd);		esdout_set_audio_params();	}	if(effects_enabled() && ep && ep->mod_samples)		length = ep->mod_samples(&data,length, input_format, input_frequency, input_channels);        if (esd_translate)                output_bytes += write(fd,esd_translate(data,length),length);        else                output_bytes += write(fd,data,length);}void esdout_write(gpointer ptr, gint length){	gint cnt, off = 0;	if (!realtime)	{		remove_prebuffer = FALSE;		written += length;		while (length > 0)		{			cnt = MIN(length, buffer_size - wr_index);			memcpy((gchar *)buffer + wr_index, (gchar *)ptr + off, cnt);			wr_index = (wr_index + cnt) % buffer_size;			length -= cnt;			off += cnt;		}	}	else	{		if (paused)			return;		esdout_write_audio(ptr,length);		written += length;			}}void esdout_close(void){	if (!going)		return;	going = 0;	if (!realtime)		pthread_join(buffer_thread, NULL);	else		esd_close(fd);	wr_index = 0;	rd_index = 0;	g_free(esd_cfg.playername);	esd_cfg.playername = NULL;	esdout_reset_playerid();}void esdout_flush(gint time){	if (!realtime)	{		flush = time;		while (flush != -1)			xmms_usleep(10000);	}	else	{		output_time_offset = time;		written = (guint64)(time / 10) * (guint64)(input_bps / 100);		output_bytes = 0;	}}void esdout_pause(short p){	paused = p;}void *esdout_loop(void *arg){	gint length, cnt;		while (going)	{		if (esdout_used() > prebuffer_size)			prebuffer = FALSE;		if (esdout_used() > 0 && !paused && !prebuffer)		{			length = MIN(blk_size, esdout_used());			while (length > 0)			{				cnt = MIN(length,buffer_size-rd_index);				esdout_write_audio((gchar *)buffer + rd_index, cnt);				rd_index=(rd_index+cnt)%buffer_size;				length-=cnt;							}		}		else			xmms_usleep(10000);		if (flush != -1)		{			output_time_offset = flush;			written = (guint64)(flush / 10) * (guint64)(input_bps / 100);			rd_index = wr_index = output_bytes = 0;			flush = -1;			prebuffer = TRUE;		}	}	esd_close(fd);	g_free(buffer);	pthread_exit(NULL);}void esdout_set_audio_params(void){	fd = esd_play_stream(esd_format, frequency,			     esd_cfg.hostname, esd_cfg.playername);	/* Set the stream's mixer */	if (fd != -1)		esdout_mixer_init();	ebps = frequency * channels;	if (format == FMT_U16_BE || format == FMT_U16_LE ||	    format == FMT_S16_BE || format == FMT_S16_LE ||	    format == FMT_S16_NE || format == FMT_U16_NE)		ebps *= 2;}int esdout_open(AFormat fmt, int rate, int nch){	static unsigned int playercnt = 0;	esdout_setup_format(fmt,rate,nch);		input_format = format;	input_channels = channels;	input_frequency = frequency;	input_bps = bps;	realtime = xmms_check_realtime_priority();		if (!realtime)	{		buffer_size = (esd_cfg.buffer_size * input_bps) / 1000;		if (buffer_size < 8192)			buffer_size = 8192;		prebuffer_size = (buffer_size * esd_cfg.prebuffer) / 100;		if (buffer_size - prebuffer_size < 4096)			prebuffer_size = buffer_size - 4096;		buffer = g_malloc0(buffer_size);	}	flush = -1;	prebuffer = 1;	wr_index = rd_index = output_time_offset = written = output_bytes = 0;	paused = FALSE;	remove_prebuffer = FALSE;	esd_cfg.playername = g_strdup_printf("xmms - plugin (%d-%u)",					     getpid(), playercnt++);	if (esd_cfg.hostname)		g_free(esd_cfg.hostname);	if (esd_cfg.use_remote)		esd_cfg.hostname = g_strdup_printf("%s:%d", esd_cfg.server, esd_cfg.port);	else		esd_cfg.hostname = NULL;		esdout_set_audio_params();	if (fd == -1)	{		g_free(esd_cfg.playername);		esd_cfg.playername = NULL;		g_free(buffer);		return 0;	}	going = 1;	if (!realtime)		pthread_create(&buffer_thread, NULL, esdout_loop, NULL);	return 1;}

⌨️ 快捷键说明

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