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

📄 sdl_pulseaudio.c

📁 SDL库 在进行视频显示程序spcaview安装时必须的库文件
💻 C
字号:
/*    SDL - Simple DirectMedia Layer    Copyright (C) 1997-2007 Sam Lantinga    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Lesser General Public    License as published by the Free Software Foundation; either    version 2.1 of the License, or (at your option) any later version.    This library 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    Lesser General Public License for more details.    You should have received a copy of the GNU Lesser General Public    License along with this library; if not, write to the Free Software    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA    Stéphan Kochen    stephan@kochen.nl        Based on parts of the ALSA and ESounD output drivers.*/#include "SDL_config.h"/* Allow access to an PulseAudio network stream mixing buffer */#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <errno.h>#include <pulse/simple.h>#include "SDL_timer.h"#include "SDL_audio.h"#include "../SDL_audiomem.h"#include "../SDL_audio_c.h"#include "../SDL_audiodev_c.h"#include "SDL_pulseaudio.h"#ifdef SDL_AUDIO_DRIVER_PULSE_DYNAMIC#include "SDL_name.h"#include "SDL_loadso.h"#else#define SDL_NAME(X)	X#endif/* The tag name used by the driver */#define PULSE_DRIVER_NAME	"pulse"/* Audio driver functions */static int PULSE_OpenAudio(_THIS, SDL_AudioSpec *spec);static void PULSE_WaitAudio(_THIS);static void PULSE_PlayAudio(_THIS);static Uint8 *PULSE_GetAudioBuf(_THIS);static void PULSE_CloseAudio(_THIS);#ifdef SDL_AUDIO_DRIVER_PULSE_DYNAMICstatic const char *pulse_library = SDL_AUDIO_DRIVER_PULSE_DYNAMIC;static void *pulse_handle = NULL;static int pulse_loaded = 0;static pa_simple* (*SDL_NAME(pa_simple_new))(	const char *server,	const char *name,	pa_stream_direction_t dir,	const char *dev,	const char *stream_name,	const pa_sample_spec *ss,	const pa_channel_map *map,	const pa_buffer_attr *attr,	int *error);static void (*SDL_NAME(pa_simple_free))(pa_simple *s);static int (*SDL_NAME(pa_simple_drain))(pa_simple *s, int *error);static int (*SDL_NAME(pa_simple_write))(	pa_simple *s,	const void *data,	size_t length,	int *error );static pa_channel_map* (*SDL_NAME(pa_channel_map_init_auto))(	pa_channel_map *m,	unsigned channels,	pa_channel_map_def_t def);	static struct {	const char *name;	void **func;} pulse_functions[] = {	{ "pa_simple_new",		(void **)&SDL_NAME(pa_simple_new)		},	{ "pa_simple_free",		(void **)&SDL_NAME(pa_simple_free)		},	{ "pa_simple_drain",		(void **)&SDL_NAME(pa_simple_drain)		},	{ "pa_simple_write",		(void **)&SDL_NAME(pa_simple_write)		},	{ "pa_channel_map_init_auto",		(void **)&SDL_NAME(pa_channel_map_init_auto)	},};static void UnloadPulseLibrary(){	if ( pulse_loaded ) {		SDL_UnloadObject(pulse_handle);		pulse_handle = NULL;		pulse_loaded = 0;	}}static int LoadPulseLibrary(void){	int i, retval = -1;	pulse_handle = SDL_LoadObject(pulse_library);	if ( pulse_handle ) {		pulse_loaded = 1;		retval = 0;		for ( i=0; i<SDL_arraysize(pulse_functions); ++i ) {			*pulse_functions[i].func = SDL_LoadFunction(pulse_handle, pulse_functions[i].name);			if ( !*pulse_functions[i].func ) {				retval = -1;				UnloadPulseLibrary();				break;			}		}	}	return retval;}#elsestatic void UnloadPulseLibrary(){	return;}static int LoadPulseLibrary(void){	return 0;}#endif /* SDL_AUDIO_DRIVER_PULSE_DYNAMIC *//* Audio driver bootstrap functions */static int Audio_Available(void){	pa_sample_spec paspec;	pa_simple *connection;	int available;	available = 0;	if ( LoadPulseLibrary() < 0 ) {		return available;	}		/* Connect with a dummy format. */	paspec.format = PA_SAMPLE_U8;	paspec.rate = 11025;	paspec.channels = 1;	connection = SDL_NAME(pa_simple_new)(		SDL_getenv("PASERVER"),      /* server */		"Test stream",               /* application name */		PA_STREAM_PLAYBACK,          /* playback mode */		SDL_getenv("PADEVICE"),      /* device on the server */		"Simple DirectMedia Layer",  /* stream description */		&paspec,                     /* sample format spec */		NULL,                        /* channel map */		NULL,                        /* buffering attributes */		NULL                         /* error code */	);	if ( connection != NULL ) {		available = 1;		SDL_NAME(pa_simple_free)(connection);	}		UnloadPulseLibrary();	return(available);}static void Audio_DeleteDevice(SDL_AudioDevice *device){	SDL_free(device->hidden);	SDL_free(device);	UnloadPulseLibrary();}static SDL_AudioDevice *Audio_CreateDevice(int devindex){	SDL_AudioDevice *this;	/* Initialize all variables that we clean on shutdown */	LoadPulseLibrary();	this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice));	if ( this ) {		SDL_memset(this, 0, (sizeof *this));		this->hidden = (struct SDL_PrivateAudioData *)				SDL_malloc((sizeof *this->hidden));	}	if ( (this == NULL) || (this->hidden == NULL) ) {		SDL_OutOfMemory();		if ( this ) {			SDL_free(this);		}		return(0);	}	SDL_memset(this->hidden, 0, (sizeof *this->hidden));	/* Set the function pointers */	this->OpenAudio = PULSE_OpenAudio;	this->WaitAudio = PULSE_WaitAudio;	this->PlayAudio = PULSE_PlayAudio;	this->GetAudioBuf = PULSE_GetAudioBuf;	this->CloseAudio = PULSE_CloseAudio;	this->free = Audio_DeleteDevice;	return this;}AudioBootStrap PULSE_bootstrap = {	PULSE_DRIVER_NAME, "PulseAudio",	Audio_Available, Audio_CreateDevice};/* This function waits until it is possible to write a full sound buffer */static void PULSE_WaitAudio(_THIS){	/* Check to see if the thread-parent process is still alive */	{ static int cnt = 0;		/* Note that this only works with thread implementations 		   that use a different process id for each thread.		*/		if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */			if ( kill(parent, 0) < 0 ) {				this->enabled = 0;			}		}	}}static void PULSE_PlayAudio(_THIS){	/* Write the audio data */	if ( SDL_NAME(pa_simple_write)(stream, mixbuf, mixlen, NULL) != 0 )	{		this->enabled = 0;	}}static Uint8 *PULSE_GetAudioBuf(_THIS){	return(mixbuf);}static void PULSE_CloseAudio(_THIS){	if ( mixbuf != NULL ) {		SDL_FreeAudioMem(mixbuf);		mixbuf = NULL;	}	if ( stream != NULL ) {		SDL_NAME(pa_simple_drain)(stream, NULL);		SDL_NAME(pa_simple_free)(stream);		stream = NULL;	}}/* Try to get the name of the program */static char *get_progname(void){	char *progname = NULL;#ifdef __LINUX__	FILE *fp;	static char temp[BUFSIZ];	SDL_snprintf(temp, SDL_arraysize(temp), "/proc/%d/cmdline", getpid());	fp = fopen(temp, "r");	if ( fp != NULL ) {		if ( fgets(temp, sizeof(temp)-1, fp) ) {			progname = SDL_strrchr(temp, '/');			if ( progname == NULL ) {				progname = temp;			} else {				progname = progname+1;			}		}		fclose(fp);	}#endif	return(progname);}static int PULSE_OpenAudio(_THIS, SDL_AudioSpec *spec){	Uint16          test_format;	pa_sample_spec  paspec;	pa_buffer_attr  paattr;	pa_channel_map  pacmap;		paspec.format = PA_SAMPLE_INVALID;	for ( test_format = SDL_FirstAudioFormat(spec->format); test_format; ) {		switch ( test_format ) {			case AUDIO_U8:				paspec.format = PA_SAMPLE_U8;				break;			case AUDIO_S16LSB:				paspec.format = PA_SAMPLE_S16LE;				break;			case AUDIO_S16MSB:				paspec.format = PA_SAMPLE_S16BE;				break;		}		if ( paspec.format != PA_SAMPLE_INVALID )			break;	}	if (paspec.format == PA_SAMPLE_INVALID ) {		SDL_SetError("Couldn't find any suitable audio formats");		return(-1);	}	spec->format = test_format;		paspec.channels = spec->channels;	paspec.rate = spec->freq;	/* Calculate the final parameters for this audio specification */	SDL_CalculateAudioSpec(spec);	/* Allocate mixing buffer */	mixlen = spec->size;	mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen);	if ( mixbuf == NULL ) {		return(-1);	}	SDL_memset(mixbuf, spec->silence, spec->size);		/* Reduced prebuffering compared to the defaults. */	paattr.tlength = mixlen;	paattr.minreq = mixlen;	paattr.fragsize = mixlen;	paattr.prebuf = mixlen;	paattr.maxlength = mixlen * 4;		/* The SDL ALSA output hints us that we use Windows' channel mapping */	/* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */	SDL_NAME(pa_channel_map_init_auto)(		&pacmap, spec->channels, PA_CHANNEL_MAP_WAVEEX);		/* Connect to the PulseAudio server */	stream = SDL_NAME(pa_simple_new)(		SDL_getenv("PASERVER"),      /* server */		get_progname(),              /* application name */		PA_STREAM_PLAYBACK,          /* playback mode */		SDL_getenv("PADEVICE"),      /* device on the server */		"Simple DirectMedia Layer",  /* stream description */		&paspec,                     /* sample format spec */		&pacmap,                     /* channel map */		&paattr,                     /* buffering attributes */		NULL                         /* error code */	);	if ( stream == NULL ) {		PULSE_CloseAudio(this);		SDL_SetError("Could not connect to PulseAudio");		return(-1);	}	/* Get the parent process id (we're the parent of the audio thread) */	parent = getpid();		return(0);}

⌨️ 快捷键说明

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