📄 sound_oss.cxx
字号:
PINDEX total = 0; while (total < len) { PINDEX bytes = 0; while (!ConvertOSError(bytes = ::read(os_handle, (void *)(((unsigned int)buf) + total), len-total))) { if (GetErrorCode() != Interrupted) { PTRACE(6, "OSS\tRead failed"); return FALSE; } PTRACE(6, "OSS\tRead interrupted"); } total += bytes; if (total != len) PTRACE(6, "OSS\tRead completed short - " << total << " vs " << len << ". Reading more data"); } lastReadCount = total;#else while (!ConvertOSError(lastReadCount = ::read(os_handle, (void *)buf, len))) { if (GetErrorCode() != Interrupted) { PTRACE(6, "OSS\tRead failed"); return FALSE; } PTRACE(6, "OSS\tRead interrupted"); }#endif if (lastReadCount != len) PTRACE(6, "OSS\tRead completed short - " << lastReadCount << " vs " << len); else PTRACE(6, "OSS\tRead completed"); return TRUE;}BOOL PSoundChannelOSS::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); // 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;}// Get the number of channels (mono/stereo) in the sound.unsigned PSoundChannelOSS::GetChannels() const{ return mNumChannels;}// Get the sample rate in samples per second.unsigned PSoundChannelOSS::GetSampleRate() const{ return actualSampleRate;}// Get the sample size in bits per sample.unsigned PSoundChannelOSS::GetSampleSize() const{ return mBitsPerSample;}BOOL PSoundChannelOSS::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; // 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 PSoundChannelOSS::GetBuffers(PINDEX & size, PINDEX & count){ if (os_handle < 0) return SetErrorValues(NotOpen, EBADF); // 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 PSoundChannelOSS::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 PSoundChannelOSS::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 PSoundChannelOSS::HasPlayCompleted(){ if (os_handle < 0) return SetErrorValues(NotOpen, EBADF); audio_buf_info info; if (!ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_GETOSPACE, &info))) return FALSE; return info.fragments == info.fragstotal;}BOOL PSoundChannelOSS::WaitForPlayCompletion(){ if (os_handle < 0) return SetErrorValues(NotOpen, EBADF); return ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_SYNC, NULL));}BOOL PSoundChannelOSS::RecordSound(PSound & sound){ if (os_handle < 0) return SetErrorValues(NotOpen, EBADF); return FALSE;}BOOL PSoundChannelOSS::RecordFile(const PFilePath & filename){ if (os_handle < 0) return SetErrorValues(NotOpen, EBADF); return FALSE;}BOOL PSoundChannelOSS::StartRecording(){ if (os_handle < 0) return SetErrorValues(NotOpen, EBADF); if (os_handle == 0) return TRUE; P_fd_set fds = os_handle; P_timeval instant; return ConvertOSError(::select(1, fds, NULL, NULL, instant));}BOOL PSoundChannelOSS::IsRecordBufferFull(){ if (os_handle < 0) return SetErrorValues(NotOpen, EBADF); audio_buf_info info; if (!ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_GETISPACE, &info))) return FALSE; return info.fragments > 0;}BOOL PSoundChannelOSS::AreAllRecordBuffersFull(){ if (os_handle < 0) return SetErrorValues(NotOpen, EBADF); audio_buf_info info; if (!ConvertOSError(::ioctl(os_handle, SNDCTL_DSP_GETISPACE, &info))) return FALSE; return info.fragments == info.fragstotal;}BOOL PSoundChannelOSS::WaitForRecordBufferFull(){ if (os_handle < 0) return SetErrorValues(NotOpen, EBADF); return PXSetIOBlock(PXReadBlock, readTimeout);}BOOL PSoundChannelOSS::WaitForAllRecordBuffersFull(){ return FALSE;}BOOL PSoundChannelOSS::Abort(){ return ConvertOSError(ioctl(os_handle, SNDCTL_DSP_RESET, NULL));}BOOL PSoundChannelOSS::SetVolume(unsigned newVal){ if (os_handle <= 0) //CAnnot set volume in loop back mode. return FALSE; int rc, deviceVol = (newVal << 8) | newVal; if (direction == Player) rc = ::ioctl(os_handle, MIXER_WRITE(SOUND_MIXER_VOLUME), &deviceVol); else rc = ::ioctl(os_handle, MIXER_WRITE(SOUND_MIXER_MIC), &deviceVol); if (rc < 0) { PTRACE(1, "PSoundChannelOSS::SetVolume failed : " << ::strerror(errno)); return FALSE; } return TRUE;}BOOL PSoundChannelOSS::GetVolume(unsigned &devVol){ if (os_handle <= 0) //CAnnot get volume in loop back mode. return FALSE; int vol, rc; if (direction == Player) rc = ::ioctl(os_handle, MIXER_READ(SOUND_MIXER_VOLUME), &vol); else rc = ::ioctl(os_handle, MIXER_READ(SOUND_MIXER_MIC), &vol); if (rc < 0) { PTRACE(1, "PSoundChannelOSS::GetVolume failed : " << ::strerror(errno)) ; return FALSE; } devVol = vol & 0xff; return TRUE;} // End of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -