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

📄 qsa.cxx

📁 安装 H323需要的pwlib库
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* * qsa.cxx * * QNX Sound Architecture */#pragma implementation "sound.h"#include <ptlib.h>#include <stdio.h>#include <sys/asoundlib.h>typedef struct _SoundHandleEntry {	struct _SoundHandleEntry *next;		int handle;	int direction;	unsigned numChannels;	unsigned sampleRate;	unsigned bitsPerSample;	unsigned fragmentValue;	BOOL isInitialised;		snd_pcm_t   *pcm_handle;	int         card;	int         dev;	snd_mixer_t *mixer_handle;	snd_mixer_group_t group;} SoundHandleEntry;static SoundHandleEntry *SoundHandleList;static pthread_rwlock_t SoundHandleLock = PTHREAD_RWLOCK_INITIALIZER;static int snd_openmode[2] = {SND_PCM_OPEN_CAPTURE, SND_PCM_OPEN_PLAYBACK};static int snd_chnmode[2]  = {SND_PCM_CHANNEL_CAPTURE, SND_PCM_CHANNEL_PLAYBACK};PSound::PSound(unsigned channels,               unsigned samplesPerSecond,               unsigned bitsPerSample,               PINDEX   bufferSize,               const BYTE * buffer){	encoding = 0;	numChannels = channels;	sampleRate = samplesPerSecond;	sampleSize = bitsPerSample;	SetSize(bufferSize);	if (buffer != NULL)	  memcpy(GetPointer(), buffer, bufferSize);}PSound::PSound(const PFilePath & filename){	encoding = 0;	numChannels = 1;	sampleRate = 8000;	sampleSize = 16;	Load(filename);}PSound & PSound::operator=(const PBYTEArray & data){	PBYTEArray::operator=(data);	return *this;}void PSound::SetFormat(unsigned channels,                       unsigned samplesPerSecond,                       unsigned bitsPerSample){	encoding = 0;	numChannels = channels;	sampleRate = samplesPerSecond;	sampleSize = bitsPerSample;	formatInfo.SetSize(0);}BOOL PSound::Load(const PFilePath & /*filename*/){	return FALSE;}BOOL PSound::Save(const PFilePath & /*filename*/){	return FALSE;}BOOL PSound::Play(){	PSoundChannel channel(PSoundChannel::GetDefaultDevice(PSoundChannel::Player),						  PSoundChannel::Player);	if (!channel.IsOpen())	  return FALSE;		return channel.PlaySound(*this, TRUE);}BOOL PSound::PlayFile(const PFilePath & file, BOOL wait){	PSoundChannel channel(PSoundChannel::GetDefaultDevice(PSoundChannel::Player),						  PSoundChannel::Player);	if (!channel.IsOpen())	  return FALSE;		return channel.PlayFile(file, wait);}PSoundChannel::PSoundChannel(){	Construct();}PSoundChannel::PSoundChannel(const PString & device,                             Directions dir,                             unsigned numChannels,                             unsigned sampleRate,                             unsigned bitsPerSample){	Construct();	Open(device, dir, numChannels, sampleRate, bitsPerSample);}void PSoundChannel::Construct(){	os_handle = -1;}PSoundChannel::~PSoundChannel(){	Close();}PStringArray PSoundChannel::GetDeviceNames(Directions dir){	PStringList devices;	PDirectory  devdir = "/dev/snd";		if (!devdir.Open())	  return NULL;	do {		PString filename = devdir.GetEntryName();		PString devname = devdir + filename;		if ((filename.GetLength() > 3) && (filename.Left(3) == "pcm") &&			(filename.Right(1) == (dir == Recorder ? "r" : "p")))		{			int fd = ::open(filename, O_RDONLY);			if (fd >= 0) {				devices.AppendString(filename);				::close(fd);			}		}	} while (devdir.Next());	return devices;}PString PSoundChannel::GetDefaultDevice(Directions dir){	PString filename;		if (dir == Player)	  filename = "/dev/snd/pcmPreferredp";	else	  filename = "/dev/snd/pcmPreferredc";		int fd = ::open(filename, O_RDONLY);//	PTRACE(1, "GetDefaultDevice; fd = " << fd << ", filename ='" << filename <<"'\n");	if (fd >=0) {		::close (fd);		return filename;	} else {		return (filename = "/dev/null");	}}BOOL PSoundChannel::Open(const PString & _device,						 Directions _dir,						 unsigned _numChannels,						 unsigned _sampleRate,						 unsigned _bitsPerSample){	Close();		// make the direction value 1 or 2	int dir = _dir + 1;	SoundHandleEntry *entry;		pthread_rwlock_wrlock(&SoundHandleLock);	for (entry = SoundHandleList; entry && entry->handle != os_handle; entry = entry->next);		if (entry) {		PTRACE(6, "OSS\tOpen occured for existing entry");				// see if the sound channel is already open in this direction		if ((entry->direction & dir) != 0) {			pthread_rwlock_unlock(&SoundHandleLock);			return FALSE;		}				// flag this entry as open in this direction		entry->direction |= dir;		os_handle = entry->handle;	} else {				PTRACE(6, "OSS\tOpen occured for new entry");				SoundHandleEntry *entry = (SoundHandleEntry *)::malloc(sizeof(*entry));				if (!entry) {			pthread_rwlock_unlock(&SoundHandleLock);			return FALSE;		}		// this is the first time this device has been used		// open the device in read/write mode always		if (((_dir == Player) && _device == "/dev/snd/pcmPreferredp") ||			((_dir == Recorder) && _device == "/dev/snd/pcmPreferredc"))		{			os_handle = snd_pcm_open_preferred(&entry->pcm_handle, &entry->card, &entry->dev, snd_openmode[_dir]);		} else {			if (sscanf(_device, "/dev/snd/pcmC%iD%i", &entry->card, &entry->dev) != 2) {				errno = ESRCH;				return ConvertOSError(os_handle);			}			os_handle = snd_pcm_open(&entry->pcm_handle, entry->card, entry->dev, snd_openmode[_dir]);		}				if (os_handle < 0) {			errno = -os_handle;			os_handle = 0;			return ConvertOSError(os_handle);		}		if (snd_pcm_plugin_set_disable(entry->pcm_handle, PLUGIN_DISABLE_MMAP) < 0)		  return FALSE;			// save the information into the dictionary entry		os_handle            = snd_pcm_file_descriptor(entry->pcm_handle, snd_chnmode[_dir]);		entry->handle        = os_handle;		entry->direction     = dir;		entry->numChannels   = mNumChannels     = _numChannels;		entry->sampleRate    = actualSampleRate = mSampleRate    = _sampleRate;		entry->bitsPerSample = mBitsPerSample   = _bitsPerSample;		entry->isInitialised = FALSE;		entry->fragmentValue = 0x7fff0008;		entry->mixer_handle  = 0;				entry->next          = SoundHandleList;		SoundHandleList      = entry;	}	pthread_rwlock_unlock(&SoundHandleLock);		// save the direction and device	direction     = _dir;	device        = _device;	isInitialised = FALSE;		return TRUE;}BOOL PSoundChannel::Setup(){	if (os_handle < 0) {		PTRACE(6, "OSS\tSkipping setup of " << device << " as not open");		return FALSE;	}		if (isInitialised) {		PTRACE(6, "OSS\tSkipping setup of " << device << " as instance already initialised");		return TRUE;	}	SoundHandleEntry *entry;	pthread_rwlock_rdlock(&SoundHandleLock);	for (entry = SoundHandleList; entry && entry->handle != os_handle;		 entry = entry->next);		// set default return status	BOOL stat = TRUE;		// do not re-initialise initialised devices	if (entry->isInitialised) {		pthread_rwlock_unlock(&SoundHandleLock);		PTRACE(6, "OSS\tSkipping setup for " << device << " as already initialised");		return stat;	}		PTRACE(6, "OSS\tInitialising " << device << "(" << (void *)(&entry) << ")");    stat = FALSE;		mBitsPerSample = entry->bitsPerSample;	mNumChannels = entry->numChannels;	mSampleRate = entry->sampleRate;	snd_pcm_channel_params_t pp;	memset(&pp, 0, sizeof(pp));	pp.channel = snd_chnmode[direction];	pp.mode = SND_PCM_MODE_BLOCK;	pp.start_mode = (direction == Player) ? SND_PCM_START_FULL : SND_PCM_START_DATA;	pp.stop_mode = SND_PCM_STOP_STOP;	pp.buf.block.frags_min = 1;	pp.buf.block.frag_size = 1 << (entry->fragmentValue & 0xffff);	pp.buf.block.frags_max = ((unsigned)entry->fragmentValue >> 16) & 0x7fff;	if (pp.buf.block.frags_max == 0)	  pp.buf.block.frags_max = 65536;			pp.format.interleave = 1;	pp.format.rate = entry->sampleRate;	pp.format.voices = entry->numChannels;		#if PBYTE_ORDER == PLITTLE_ENDIAN	pp.format.format = (entry->bitsPerSample == 16) ? SND_PCM_SFMT_S16_LE : SND_PCM_SFMT_U8;#else	pp.format.format = (entry->bitsPerSample == 16) ? SND_PCM_SFMT_S16_BE : SND_PCM_SFMT_U8;#endif		if (snd_pcm_plugin_params(entry->pcm_handle, &pp) < 0) {		pthread_rwlock_unlock(&SoundHandleLock);		return stat;	}		if (snd_pcm_plugin_prepare(entry->pcm_handle, snd_chnmode[direction]) < 0) {		pthread_rwlock_unlock(&SoundHandleLock);		return stat;	}		/* also open the mixer */	snd_pcm_channel_setup_t setup;		memset(&setup, 0, sizeof(setup));	memset(&entry->group, 0, sizeof(entry->group));	setup.channel = snd_chnmode[direction];	setup.mixer_gid = &entry->group.gid;		if (snd_pcm_plugin_setup(entry->pcm_handle, &setup) < 0) {		pthread_rwlock_unlock(&SoundHandleLock);		return FALSE;	}			if (snd_mixer_open(&entry->mixer_handle, entry->card, setup.mixer_device) < 0) {		pthread_rwlock_unlock(&SoundHandleLock);		return FALSE;	}		actualSampleRate = setup.format.rate;	stat = TRUE;#if PTRACING	PTRACE(4, "QSA: Frag Size = " << setup.buf.block.frag_size			   << ", Rate = " << setup.format.rate		       << ", Mixer Pcm Group [" << entry->group.gid.name << "]\n");#endif	pthread_rwlock_unlock(&SoundHandleLock);	// ensure device is marked as initialised	isInitialised        = TRUE;	entry->isInitialised = TRUE;		return stat;}BOOL PSoundChannel::Close(){	// if the channel isn't open, do nothing	if (os_handle < 0)	  return TRUE;		SoundHandleEntry *entry, **entryp;		pthread_rwlock_wrlock(&SoundHandleLock);	for (entryp = &SoundHandleList, entry = *entryp; entry && entry->handle != os_handle;		 entryp = &entry->next, entry = *entryp);	  	if (!entry) {		pthread_rwlock_unlock(&SoundHandleLock);		return TRUE;	}		// modify the directions bit mask in the dictionary	entry->direction ^= (direction+1);		// if this is the last usage of this entry, then remove it	if (entry->direction == 0) {		snd_mixer_close(entry->mixer_handle);		snd_pcm_plugin_flush(entry->pcm_handle, snd_chnmode[direction]);		snd_pcm_close(entry->pcm_handle);		*entryp = entry->next;		::free(entry);		os_handle = -1;		pthread_rwlock_unlock(&SoundHandleLock);		return PChannel::Close();	}		// flag this channel as closed	pthread_rwlock_unlock(&SoundHandleLock);	return TRUE;}BOOL PSoundChannel::Write(const void * buf, PINDEX len){	if (!Setup())	  return FALSE;		if (os_handle < 0)	  return FALSE;		SoundHandleEntry * entry;	pthread_rwlock_rdlock(&SoundHandleLock);	for (entry = SoundHandleList; entry && entry->handle != os_handle;		 entry = entry->next);		snd_pcm_channel_status_t status;	int written = 0;		while ((written += snd_pcm_plugin_write(entry->pcm_handle, buf, len)) < len)	{		memset(&status, 0, sizeof(status));		status.channel = SND_PCM_CHANNEL_PLAYBACK;		if (snd_pcm_plugin_status(entry->pcm_handle, &status) < 0) {			pthread_rwlock_unlock(&SoundHandleLock);

⌨️ 快捷键说明

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