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

📄 qsa.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 2 页
字号:
			return FALSE;
		}
		if (status.status == SND_PCM_STATUS_READY ||
			status.status == SND_PCM_STATUS_UNDERRUN)
		{
			if (snd_pcm_plugin_prepare(entry->pcm_handle, snd_chnmode[direction]) < 0) {
				pthread_rwlock_unlock(&SoundHandleLock);				
				return FALSE;
			}
		}
		if (written < 0)
		  written = 0;
	}	
	pthread_rwlock_unlock(&SoundHandleLock);
	return TRUE;
}

BOOL PSoundChannel::Read(void * buf, PINDEX len)
{
	lastReadCount = 0;

	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);
	
	PTRACE(6, "QSA\tRead start");
	
	lastReadCount = snd_pcm_plugin_read(entry->pcm_handle, buf, len);
	
    if (lastReadCount < len) {
		snd_pcm_channel_status_t status;
		
		memset(&status, 0, sizeof(status));
		status.channel = SND_PCM_CHANNEL_CAPTURE;
		if (snd_pcm_plugin_status(entry->pcm_handle, &status) < 0) {
			pthread_rwlock_unlock(&SoundHandleLock);
			PTRACE(6, "QSA\tRead failed");		  
			return FALSE;
		}
		
		if (status.status == SND_PCM_STATUS_READY ||
			status.status == SND_PCM_STATUS_OVERRUN) {
			if (snd_pcm_plugin_prepare(entry->pcm_handle, SND_PCM_CHANNEL_CAPTURE) < 0) {
				pthread_rwlock_unlock(&SoundHandleLock);
				PTRACE(6, "QSA\tRead failed");		  
				return FALSE;
			}
		}
		PTRACE(6, "QSA\tRead completed short - " << lastReadCount << " vs " << len);
	} else {
		PTRACE(6, "QSA\tRead completed");
	}
	pthread_rwlock_unlock(&SoundHandleLock);
    return TRUE;
}

BOOL PSoundChannel::SetFormat(unsigned numChannels,
                              unsigned sampleRate,
                              unsigned bitsPerSample)
{
	if (os_handle < 0)
	  return SetErrorValues(NotOpen, EBADF);

	// check parameters
	PAssert((bitsPerSample == 8) || (bitsPerSample == 16), PInvalidParameter);
	PAssert(numChannels >= 1 && numChannels <= 2, PInvalidParameter);

	SoundHandleEntry * entry;
	pthread_rwlock_rdlock(&SoundHandleLock);
	for (entry = SoundHandleList; entry && entry->handle != os_handle;
		 entry = entry->next);
	
	if (entry->isInitialised) {
		if ((numChannels   != entry->numChannels) ||
			(sampleRate    != entry->sampleRate) ||
			(bitsPerSample != entry->bitsPerSample)) {
			pthread_rwlock_unlock(&SoundHandleLock);
			PTRACE(6, "OSS\tTried to change read/write format without stopping");
			return FALSE;
		}
		pthread_rwlock_unlock(&SoundHandleLock);
		return TRUE;
	}

	if (direction == Player) {
		snd_pcm_plugin_playback_drain(entry->pcm_handle);
	}

	entry->numChannels   = numChannels;
	entry->sampleRate    = sampleRate;
	entry->bitsPerSample = bitsPerSample;
	entry->isInitialised  = FALSE;
	pthread_rwlock_unlock(&SoundHandleLock);
	
	// mark this channel as uninitialised
	isInitialised = FALSE;
	
	return TRUE;
}

// Get  the number of channels (mono/stereo) in the sound.
unsigned PSoundChannel::GetChannels()   const
{
	return mNumChannels;
}

// Get the sample rate in samples per second.
unsigned PSoundChannel::GetSampleRate() const
{
	return actualSampleRate;
}

// Get the sample size in bits per sample.
unsigned PSoundChannel::GetSampleSize() const
{
	return mBitsPerSample;
}


BOOL PSoundChannel::SetBuffers(PINDEX size, PINDEX count)
{
	if (os_handle < 0)
	  return SetErrorValues(NotOpen, EBADF);

	//PINDEX totalSize = size * count;
	
	//size = 16;
	//count = (totalSize + 15) / 16;
	
	PAssert(size > 0 && count > 0 && count < 65536, PInvalidParameter);
	int arg = 1;
	while (size > (PINDEX)(1 << arg))
	  arg++;
	
	arg |= count << 16;
	
	SoundHandleEntry * entry;
	pthread_rwlock_rdlock(&SoundHandleLock);
	for (entry = SoundHandleList; entry && entry->handle != os_handle;
		 entry = entry->next);
	
	if (entry->isInitialised) {
		if (entry->fragmentValue != (unsigned)arg) {
			pthread_rwlock_unlock(&SoundHandleLock);
			PTRACE(6, "OSS\tTried to change buffers without stopping");
			return FALSE;
		}
		pthread_rwlock_unlock(&SoundHandleLock);
		return TRUE;
	}
	
	if (direction == Player) {
		snd_pcm_plugin_playback_drain(entry->pcm_handle);
	}
	
	// set information in the common record
	entry->fragmentValue = arg;
	entry->isInitialised = FALSE;
	pthread_rwlock_unlock(&SoundHandleLock);
	
	// flag this channel as not initialised
	isInitialised       = FALSE;
	
	return TRUE;
}


BOOL PSoundChannel::GetBuffers(PINDEX & size, PINDEX & count)
{
	if (os_handle < 0)
	  return SetErrorValues(NotOpen, EBADF);
	
	SoundHandleEntry * entry;
	pthread_rwlock_rdlock(&SoundHandleLock);
	for (entry = SoundHandleList; entry && entry->handle != os_handle;
		 entry = entry->next);
	
	int arg = entry->fragmentValue;
	
	count = arg >> 16;
	size = 1 << (arg&0xffff);
	pthread_rwlock_unlock(&SoundHandleLock);
	
	return TRUE;
}


BOOL PSoundChannel::PlaySound(const PSound & sound, BOOL wait)
{
	if (os_handle < 0)
	  return SetErrorValues(NotOpen, EBADF);
	
	Abort();
	
	if (!Write((const BYTE *)sound, sound.GetSize()))
	  return FALSE;
	
	if (wait)
	  return WaitForPlayCompletion();
	
	return TRUE;
}


BOOL PSoundChannel::PlayFile(const PFilePath & filename, BOOL wait)
{
	if (os_handle < 0)
	  return SetErrorValues(NotOpen, EBADF);
	
	PFile file(filename, PFile::ReadOnly);
	if (!file.IsOpen())
	  return FALSE;
	
	for (;;) {
		BYTE buffer[256];
		if (!file.Read(buffer, 256))
		  break;
		PINDEX len = file.GetLastReadCount();
		if (len == 0)
		  break;
		if (!Write(buffer, len))
		  break;
	}
	
	file.Close();
	
	if (wait)
	  return WaitForPlayCompletion();
	
	return TRUE;
}


BOOL PSoundChannel::HasPlayCompleted()
{
	if (os_handle < 0)
	  return SetErrorValues(NotOpen, EBADF);
	
	SoundHandleEntry * entry;
	pthread_rwlock_rdlock(&SoundHandleLock);
	for (entry = SoundHandleList; entry && entry->handle != os_handle;
		 entry = entry->next);
	
	snd_pcm_channel_status_t status;
	memset(&status, 0, sizeof(status));
	status.channel = snd_chnmode[direction];

	if (snd_pcm_plugin_status(entry->pcm_handle, &status) < 0) {
		pthread_rwlock_unlock(&SoundHandleLock);
		return FALSE;
	}

	int ret = (abs(status.free) / (entry->bitsPerSample / 8));
	pthread_rwlock_unlock(&SoundHandleLock);
	return ret;
}

BOOL PSoundChannel::WaitForPlayCompletion()
{
	if (os_handle < 0)
	  return SetErrorValues(NotOpen, EBADF);

	SoundHandleEntry * entry;
	pthread_rwlock_rdlock(&SoundHandleLock);
	for (entry = SoundHandleList; entry && entry->handle != os_handle;
		 entry = entry->next);
	
	if (snd_pcm_playback_flush(entry->pcm_handle) < 0) {
		pthread_rwlock_unlock(&SoundHandleLock);
		return FALSE;
	}
	
	pthread_rwlock_unlock(&SoundHandleLock);
	return TRUE;
}


BOOL PSoundChannel::RecordSound(PSound & sound)
{
  if (os_handle < 0)
    return SetErrorValues(NotOpen, EBADF);

  return FALSE;
}


BOOL PSoundChannel::RecordFile(const PFilePath & filename)
{
  if (os_handle < 0)
    return SetErrorValues(NotOpen, EBADF);

  return FALSE;
}


BOOL PSoundChannel::StartRecording()
{
	if (os_handle < 0)
	  return SetErrorValues(NotOpen, EBADF);

	int fd = os_handle;
	fd_set fds;
	FD_ZERO(&fds);
	FD_SET(fd, &fds);
	struct timeval instant = {0, 0};
	return ConvertOSError(::select(fd + 1, &fds, NULL, NULL, &instant));
}


BOOL PSoundChannel::IsRecordBufferFull()
{
	if (os_handle < 0)
	  return SetErrorValues(NotOpen, EBADF);

	PTRACE(1, "IsRecordBufferFull()\n");
	/* do I suppose to get the status, and check sth ? */
	return TRUE;
}


BOOL PSoundChannel::AreAllRecordBuffersFull()
{
	if (os_handle < 0)
	  return SetErrorValues(NotOpen, EBADF);

	PTRACE(1, "AreAllRecordBuffersFull()\n");
	/* do I suppose to get the status, and check sth ? */
	return TRUE;
}


BOOL PSoundChannel::WaitForRecordBufferFull()
{
	if (os_handle < 0)
	  return SetErrorValues(NotOpen, EBADF);
	
	PTRACE(1, "WaitForRecordBufferFull()\n");
	return PXSetIOBlock(PXReadBlock, readTimeout);
}


BOOL PSoundChannel::WaitForAllRecordBuffersFull()
{
	PTRACE(1, "WaitForAllRecordBuffersFull()\n");
	return FALSE;
}


BOOL PSoundChannel::Abort()
{
	if (direction == Player && os_handle != -1) {
	SoundHandleEntry * entry;
		pthread_rwlock_rdlock(&SoundHandleLock);
		for (entry = SoundHandleList; entry && entry->handle != os_handle;
			 entry = entry->next);
		
		snd_pcm_plugin_playback_drain(entry->pcm_handle);
		pthread_rwlock_unlock(&SoundHandleLock);
	}
	return TRUE;
}


BOOL PSoundChannel::SetVolume(unsigned newVal)
{
	if (os_handle < 0)
	{
		return FALSE;
	}

	SoundHandleEntry *entry;
	pthread_rwlock_rdlock(&SoundHandleLock);
	for (entry = SoundHandleList; entry && entry->handle != os_handle;
		 entry = entry->next);
	
	int ret;
	
	if ((ret = snd_mixer_group_read(entry->mixer_handle, &entry->group)) < 0)
	{
		pthread_rwlock_unlock(&SoundHandleLock);
		cerr << "snd_mixer_group_read: " << strerror(-ret) << endl;
		return FALSE;
	}

	/* QSA treat the newVal as a percentage */
	newVal = (newVal  * (entry->group.max - entry->group.min) / 100) + entry->group.min;
	
	entry->group.volume.names.front_left = newVal;
	entry->group.volume.names.front_right = newVal;
	
	if ((ret = snd_mixer_group_write(entry->mixer_handle, &entry->group)) < 0)
	{
		pthread_rwlock_unlock(&SoundHandleLock);
		cerr << "snd_mixer_group_write: " << strerror(-ret) << endl;
		return FALSE;
	}
	pthread_rwlock_unlock(&SoundHandleLock);	
	return TRUE;
}

BOOL  PSoundChannel::GetVolume(unsigned &devVol)
{
	if (os_handle == 0)
	{
		return FALSE;
	}
  
	SoundHandleEntry *entry;
	pthread_rwlock_rdlock(&SoundHandleLock);
	for (entry = SoundHandleList; entry && entry->handle != os_handle;
		 entry = entry->next);
	
	int ret;
	
	if ((ret = snd_mixer_group_read(entry->mixer_handle, &entry->group)) < 0)
	{
		pthread_rwlock_unlock(&SoundHandleLock);
		return FALSE;
	}
	pthread_rwlock_unlock(&SoundHandleLock);
	
	/* return the percentage */
	devVol = (unsigned)(entry->group.volume.names.front_left - entry->group.min) * 100
	  / (entry->group.max - entry->group.min);

	return TRUE;
}
  


// End of file

⌨️ 快捷键说明

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