📄 qsa.cxx
字号:
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 + -