📄 sound_alsa.cxx
字号:
snd_pcm_close (os_handle); os_handle = NULL; return TRUE;}BOOL PSoundChannelALSA::Write (const void *buf, PINDEX len){ long r = 0; char *buf2 = (char *) buf; int pos = 0, max_try = 0; lastWriteCount = 0; PWaitAndSignal m(device_mutex); if (!isInitialised && !Setup() || !len || !os_handle) return FALSE; do { /* the number of frames to read is the buffer length divided by the size of one frame */ r = snd_pcm_writei (os_handle, (char *) &buf2 [pos], len / frame_bytes); if (r > 0) { pos += r * frame_bytes; len -= r * frame_bytes; lastWriteCount += r * frame_bytes; } else { if (r == -EPIPE) { /* under-run */ r = snd_pcm_prepare (os_handle); if (r < 0) PTRACE (1, "ALSA\tCould not prepare device: " << snd_strerror (r)); } else if (r == -ESTRPIPE) { while ((r = snd_pcm_resume (os_handle)) == -EAGAIN) sleep(1); /* wait until the suspend flag is released */ if (r < 0) snd_pcm_prepare (os_handle); } PTRACE (1, "ALSA\tCould not write " << max_try << " " << len << " " << r); max_try++; } } while (len > 0 && max_try < 5); return TRUE;}BOOL PSoundChannelALSA::Read (void * buf, PINDEX len){ long r = 0; char *buf2 = (char *) buf; int pos = 0, max_try = 0; lastReadCount = 0; PWaitAndSignal m(device_mutex); if (!isInitialised && !Setup() || !len || !os_handle) return FALSE; memset ((char *) buf, 0, len); do { /* the number of frames to read is the buffer length divided by the size of one frame */ r = snd_pcm_readi (os_handle, (char *) &buf2 [pos], len / frame_bytes); if (r > 0) { pos += r * frame_bytes; len -= r * frame_bytes; lastReadCount += r * frame_bytes; } else { if (r == -EPIPE) { /* under-run */ snd_pcm_prepare (os_handle); } else if (r == -ESTRPIPE) { while ((r = snd_pcm_resume (os_handle)) == -EAGAIN) sleep(1); /* wait until the suspend flag is released */ if (r < 0) snd_pcm_prepare (os_handle); } PTRACE (1, "ALSA\tCould not read"); max_try++; } } while (len > 0 && max_try < 5); if (len != 0) { memset ((char *) &buf2 [pos], 0, len); lastReadCount += len; PTRACE (1, "ALSA\tRead Error, filling with zeros"); } return TRUE;}BOOL PSoundChannelALSA::SetFormat (unsigned numChannels, unsigned sampleRate, unsigned bitsPerSample){ if (!os_handle) return SetErrorValues(NotOpen, EBADF); /* check parameters */ PAssert((bitsPerSample == 8) || (bitsPerSample == 16), PInvalidParameter); PAssert(numChannels >= 1 && numChannels <= 2, PInvalidParameter); mNumChannels = numChannels; mSampleRate = sampleRate; mBitsPerSample = bitsPerSample; /* mark this channel as uninitialised */ isInitialised = FALSE; return TRUE;}unsigned PSoundChannelALSA::GetChannels() const{ return mNumChannels;}unsigned PSoundChannelALSA::GetSampleRate() const{ return mSampleRate;}unsigned PSoundChannelALSA::GetSampleSize() const{ return mBitsPerSample;}BOOL PSoundChannelALSA::SetBuffers (PINDEX size, PINDEX count){ periods = count; period_size = size / (frame_bytes ? frame_bytes : 2); return TRUE;}BOOL PSoundChannelALSA::GetBuffers(PINDEX & size, PINDEX & count){ size = period_size * (frame_bytes ? frame_bytes : 2); count = periods; return FALSE;}BOOL PSoundChannelALSA::PlaySound(const PSound & sound, BOOL wait){ if (!os_handle) return SetErrorValues(NotOpen, EBADF); if (!Write((const BYTE *)sound, sound.GetSize())) return FALSE; if (wait) return WaitForPlayCompletion(); return TRUE;}BOOL PSoundChannelALSA::PlayFile(const PFilePath & filename, BOOL wait){ BYTE buffer [512]; if (!os_handle) return SetErrorValues(NotOpen, EBADF); PFile file (filename, PFile::ReadOnly); if (!file.IsOpen()) return FALSE; for (;;) { if (!file.Read (buffer, 512)) break; PINDEX len = file.GetLastReadCount(); if (len == 0) break; if (!Write(buffer, len)) break; } file.Close(); if (wait) return WaitForPlayCompletion(); return TRUE;}BOOL PSoundChannelALSA::HasPlayCompleted(){ if (!os_handle) return SetErrorValues(NotOpen, EBADF); return (snd_pcm_state (os_handle) != SND_PCM_STATE_RUNNING);}BOOL PSoundChannelALSA::WaitForPlayCompletion(){ if (!os_handle) return SetErrorValues(NotOpen, EBADF); snd_pcm_drain (os_handle); return TRUE;}BOOL PSoundChannelALSA::RecordSound(PSound & sound){ return FALSE;}BOOL PSoundChannelALSA::RecordFile(const PFilePath & filename){ return FALSE;}BOOL PSoundChannelALSA::StartRecording(){ return FALSE;}BOOL PSoundChannelALSA::IsRecordBufferFull(){ return TRUE;}BOOL PSoundChannelALSA::AreAllRecordBuffersFull(){ return TRUE;}BOOL PSoundChannelALSA::WaitForRecordBufferFull(){ return TRUE;}BOOL PSoundChannelALSA::WaitForAllRecordBuffersFull(){ return FALSE;}BOOL PSoundChannelALSA::Abort(){ int r = 0; if (!os_handle) return FALSE; if ((r = snd_pcm_drain (os_handle)) < 0) { PTRACE (1, "ALSA\tCannot abort" << snd_strerror (r)); return FALSE; } else return TRUE;}BOOL PSoundChannelALSA::SetVolume (unsigned newVal){ unsigned i = 0; return Volume (TRUE, newVal, i);}BOOL PSoundChannelALSA::GetVolume(unsigned &devVol){ return Volume (FALSE, 0, devVol);} BOOL PSoundChannelALSA::IsOpen () const{ return (os_handle != NULL);}BOOL PSoundChannelALSA::Volume (BOOL set, unsigned set_vol, unsigned &get_vol){ int err = 0; snd_mixer_t *handle; snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; const char *play_mix_name = (direction == Player) ? "PCM": "Capture"; PString card_name; long pmin = 0, pmax = 0; long int vol = 0; if (!os_handle) return FALSE; if (card_nr == -2) card_name = "default"; else card_name = "hw:" + PString (card_nr); //allocate simple id snd_mixer_selem_id_alloca (&sid); //sets simple-mixer index and name snd_mixer_selem_id_set_index (sid, 0); snd_mixer_selem_id_set_name (sid, play_mix_name); if ((err = snd_mixer_open (&handle, 0)) < 0) { PTRACE (1, "alsa-control: mixer open error: " << snd_strerror (err)); return FALSE; } if ((err = snd_mixer_attach (handle, card_name)) < 0) { PTRACE (1, "alsa-control: mixer attach " << card_name << " error: " << snd_strerror(err)); snd_mixer_close(handle); return FALSE; } if ((err = snd_mixer_selem_register (handle, NULL, NULL)) < 0) { PTRACE (1, "alsa-control: mixer register error: " << snd_strerror(err)); snd_mixer_close(handle); return FALSE; } err = snd_mixer_load(handle); if (err < 0) { PTRACE (1, "alsa-control: mixer load error: " << snd_strerror(err)); snd_mixer_close(handle); return FALSE; } elem = snd_mixer_find_selem (handle, sid); if (!elem) { PTRACE (1, "alsa-control: unable to find simple control " << snd_mixer_selem_id_get_name(sid) << "," << snd_mixer_selem_id_get_index(sid)); snd_mixer_close(handle); return FALSE; } if (set) { if (direction == Player) { snd_mixer_selem_get_playback_volume_range (elem, &pmin, &pmax); vol = (set_vol * (pmax?pmax:31)) / 100; snd_mixer_selem_set_playback_volume_all (elem, vol); } else { snd_mixer_selem_get_capture_volume_range (elem, &pmin, &pmax); vol = (set_vol * (pmax?pmax:31)) / 100; snd_mixer_selem_set_capture_volume_all (elem, vol); } PTRACE (4, "Set volume to " << vol); } else { if (direction == Player) { snd_mixer_selem_get_playback_volume_range (elem, &pmin, &pmax); snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, &vol); } else { snd_mixer_selem_get_capture_volume_range (elem, &pmin, &pmax); snd_mixer_selem_get_capture_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, &vol); } get_vol = (vol * 100) / (pmax?pmax:31); PTRACE (4, "Got volume " << vol); } snd_mixer_close(handle); return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -