📄 oss.cxx
字号:
arg = val = (entry.numChannels == 2) ? 1 : 0; if (ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_STEREO, &arg)) || (arg != val)) { arg = val = entry.sampleRate; if (ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_SPEED, &arg)) || (arg != val)) stat = TRUE; } } } } // 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; if (os_handle == 0) { os_handle = -1; return TRUE; } // the device must be in the dictionary dictMutex.Wait(); SoundHandleEntry * entry; PAssert((entry = handleDict().GetAt(device)) != NULL, "Unknown sound device \"" + device + "\" found"); // 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) { handleDict().RemoveAt(device); dictMutex.Signal(); return PChannel::Close(); } // flag this channel as closed dictMutex.Signal(); os_handle = -1; return TRUE;}BOOL PSoundChannel::Write(const void * buf, PINDEX len){ if (!Setup()) return FALSE; if (os_handle > 0) { while (!ConvertOSError(::write(os_handle, (void *)buf, len))) if (GetErrorCode() != Interrupted) return FALSE; return TRUE; } int index = 0; while (len > 0) { len--; buffer[endptr++] = ((char *)buf)[index++]; if (endptr == LOOPBACK_BUFFER_SIZE) endptr = 0; while (((startptr - 1) == endptr) || ((endptr==LOOPBACK_BUFFER_SIZE - 1) && (startptr==0))) { usleep(5000); } } return TRUE;}BOOL PSoundChannel::Read(void * buf, PINDEX len){ if (!Setup()) return FALSE; if (os_handle > 0) { PTRACE(6, "OSS\tRead start"); int stat; while (!ConvertOSError(stat = ::read(os_handle, (void *)buf, len))) { if (GetErrorCode() != Interrupted) { PTRACE(6, "OSS\tRead failed"); return FALSE; } PTRACE(6, "OSS\tRead interrupted"); } if (stat != len) PTRACE(6, "OSS\tRead completed short - " << stat << " vs " << len); else PTRACE(6, "OSS\tRead completed"); return TRUE; } int index = 0; while (len > 0) { while (startptr == endptr) usleep(5000); len--; ((char *)buf)[index++]=buffer[startptr++]; if (startptr == LOOPBACK_BUFFER_SIZE) startptr = 0; } return TRUE;}BOOL PSoundChannel::SetFormat(unsigned numChannels, unsigned sampleRate, unsigned bitsPerSample){ if (os_handle < 0) { lastError = NotOpen; return FALSE; } // check parameters PAssert((bitsPerSample == 8) || (bitsPerSample == 16), PInvalidParameter); PAssert(numChannels >= 1 && numChannels <= 2, PInvalidParameter); // lock the dictionary PWaitAndSignal mutex(dictMutex); // the device must always be in the dictionary PAssertOS(handleDict().Contains(device)); // get record for the device SoundHandleEntry & entry = handleDict()[device]; if (entry.isInitialised) { if ((numChannels != entry.numChannels) || (sampleRate != entry.sampleRate) || (bitsPerSample != entry.bitsPerSample)) { PTRACE(6, "OSS\tTried to change read/write format without stopping"); return FALSE; } return TRUE; } Abort(); entry.numChannels = numChannels; entry.sampleRate = sampleRate; entry.bitsPerSample = bitsPerSample; entry.isInitialised = FALSE; // mark this channel as uninitialised isInitialised = FALSE; return TRUE;}BOOL PSoundChannel::SetBuffers(PINDEX size, PINDEX count){ if (os_handle < 0) { lastError = NotOpen; return FALSE; } 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; // lock the dictionary PWaitAndSignal mutex(dictMutex); // the device must always be in the dictionary PAssertOS(handleDict().Contains(device)); // get record for the device SoundHandleEntry & entry = handleDict()[device]; if (entry.isInitialised) { if (entry.fragmentValue != (unsigned)arg) { PTRACE(6, "OSS\tTried to change buffers without stopping"); return FALSE; } return TRUE; } Abort(); // set information in the common record entry.fragmentValue = arg; entry.isInitialised = FALSE; // flag this channel as not initialised isInitialised = FALSE; return TRUE;}BOOL PSoundChannel::GetBuffers(PINDEX & size, PINDEX & count){ if (os_handle < 0) { lastError = NotOpen; return FALSE; } // lock the dictionary PWaitAndSignal mutex(dictMutex); // the device must always be in the dictionary PAssertOS(handleDict().Contains(device)); SoundHandleEntry & entry = handleDict()[device]; int arg = entry.fragmentValue; count = arg >> 16; size = 1 << (arg&0xffff); return TRUE;}BOOL PSoundChannel::PlaySound(const PSound & sound, BOOL wait){ if (os_handle < 0) { lastError = NotOpen; return FALSE; } 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) { lastError = NotOpen; return FALSE; } 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) { lastError = NotOpen; return FALSE; } if (os_handle == 0) return BYTESINBUF <= 0; audio_buf_info info; if (!ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_GETOSPACE, &info))) return FALSE; return info.fragments == info.fragstotal;}BOOL PSoundChannel::WaitForPlayCompletion(){ if (os_handle < 0) { lastError = NotOpen; return FALSE; } if (os_handle == 0) { while (BYTESINBUF > 0) usleep(1000); return TRUE; } return ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_SYNC, NULL));}BOOL PSoundChannel::RecordSound(PSound & sound){ if (os_handle < 0) { lastError = NotOpen; return FALSE; } return FALSE;}BOOL PSoundChannel::RecordFile(const PFilePath & filename){ if (os_handle < 0) { lastError = NotOpen; return FALSE; } return FALSE;}BOOL PSoundChannel::StartRecording(){ if (os_handle < 0) { lastError = NotOpen; return FALSE; } if (os_handle == 0) return TRUE; fd_set fds; FD_ZERO(&fds); FD_SET(os_handle, &fds); struct timeval timeout; memset(&timeout, 0, sizeof(timeout)); return ConvertOSError(::select(1, &fds, NULL, NULL, &timeout));}BOOL PSoundChannel::IsRecordBufferFull(){ if (os_handle < 0) { lastError = NotOpen; return FALSE; } if (os_handle == 0) return (BYTESINBUF > 0); audio_buf_info info; if (!ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_GETISPACE, &info))) return FALSE; return info.fragments > 0;}BOOL PSoundChannel::AreAllRecordBuffersFull(){ if (os_handle < 0) { lastError = NotOpen; return FALSE; } if (os_handle == 0) return (BYTESINBUF == LOOPBACK_BUFFER_SIZE); audio_buf_info info; if (!ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_GETISPACE, &info))) return FALSE; return info.fragments == info.fragstotal;}BOOL PSoundChannel::WaitForRecordBufferFull(){ if (os_handle < 0) { lastError = NotOpen; return FALSE; } return PXSetIOBlock(PXReadBlock, readTimeout);}BOOL PSoundChannel::WaitForAllRecordBuffersFull(){ return FALSE;}BOOL PSoundChannel::Abort(){ if (os_handle == 0) { startptr = endptr = 0; return TRUE; } return ConvertOSError(ioctl(os_handle, SNDCTL_DSP_RESET, NULL));}// End of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -