Implement `pause` and `play` for ALSA backend (#176)
* Implement `pause` and `play` for ALSA backend This commit also ensures that the Voice is initially paused when returned to remain consistent with the rest of the CPAL backends. Related to #175. * Remove ineffective pause from end of build_voice method * ALSA - Change `is_paused` flag from `AtomicBool` to `bool` * Add pause and play ALSA addition to CHANGELOG
This commit is contained in:
parent
743e4e3526
commit
019b27350f
|
@ -2,6 +2,7 @@
|
|||
|
||||
- Changed the emscripten backend to consume less CPU.
|
||||
- Added improvements to the crate documentation.
|
||||
- Implement `pause` and `play` for ALSA backend.
|
||||
|
||||
# Version 0.5.1 (2017-10-21)
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ use SupportedFormat;
|
|||
use UnknownTypeBuffer;
|
||||
|
||||
use std::{cmp, ffi, iter, mem, ptr};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::Mutex;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::vec::IntoIter as VecIntoIter;
|
||||
|
||||
pub type SupportedFormatsIterator = VecIntoIter<SupportedFormat>;
|
||||
|
@ -276,6 +276,8 @@ unsafe impl Sync for EventLoop {
|
|||
|
||||
enum Command {
|
||||
NewVoice(VoiceInner),
|
||||
PlayVoice(VoiceId),
|
||||
PauseVoice(VoiceId),
|
||||
DestroyVoice(VoiceId),
|
||||
}
|
||||
|
||||
|
@ -309,8 +311,11 @@ struct VoiceInner {
|
|||
// Minimum number of samples to put in the buffer.
|
||||
period_len: usize,
|
||||
|
||||
// Wherease the sample stream is paused
|
||||
is_paused: AtomicBool,
|
||||
// Whether or not the hardware supports pausing the stream.
|
||||
can_pause: bool,
|
||||
|
||||
// Whether or not the sample stream is currently paused.
|
||||
is_paused: bool,
|
||||
|
||||
// A file descriptor opened with `eventfd`.
|
||||
// It is used to wait for resume signal.
|
||||
|
@ -367,6 +372,22 @@ impl EventLoop {
|
|||
Command::DestroyVoice(voice_id) => {
|
||||
run_context.voices.retain(|v| v.id != voice_id);
|
||||
},
|
||||
Command::PlayVoice(voice_id) => {
|
||||
if let Some(voice) = run_context.voices.iter_mut()
|
||||
.find(|voice| voice.can_pause && voice.id == voice_id)
|
||||
{
|
||||
alsa::snd_pcm_pause(voice.channel, 0);
|
||||
voice.is_paused = false;
|
||||
}
|
||||
},
|
||||
Command::PauseVoice(voice_id) => {
|
||||
if let Some(voice) = run_context.voices.iter_mut()
|
||||
.find(|voice| voice.can_pause && voice.id == voice_id)
|
||||
{
|
||||
alsa::snd_pcm_pause(voice.channel, 1);
|
||||
voice.is_paused = true;
|
||||
}
|
||||
},
|
||||
Command::NewVoice(voice_inner) => {
|
||||
run_context.voices.push(voice_inner);
|
||||
},
|
||||
|
@ -561,6 +582,8 @@ impl EventLoop {
|
|||
check_errors(alsa::snd_pcm_hw_params(playback_handle, hw_params.0))
|
||||
.expect("hardware params could not be set");
|
||||
|
||||
let can_pause = alsa::snd_pcm_hw_params_can_pause(hw_params.0) == 1;
|
||||
|
||||
let mut sw_params = mem::uninitialized(); // TODO: RAII
|
||||
check_errors(alsa::snd_pcm_sw_params_malloc(&mut sw_params)).unwrap();
|
||||
check_errors(alsa::snd_pcm_sw_params_current(playback_handle, sw_params)).unwrap();
|
||||
|
@ -605,36 +628,35 @@ impl EventLoop {
|
|||
num_channels: format.channels.len() as u16,
|
||||
buffer_len: buffer_len,
|
||||
period_len: period_len,
|
||||
is_paused: AtomicBool::new(true),
|
||||
can_pause: can_pause,
|
||||
is_paused: false,
|
||||
resume_trigger: Trigger::new(),
|
||||
};
|
||||
|
||||
self.commands
|
||||
.lock()
|
||||
.unwrap()
|
||||
.push(Command::NewVoice(voice_inner));
|
||||
self.pending_trigger.wakeup();
|
||||
self.push_command(Command::NewVoice(voice_inner));
|
||||
Ok(new_voice_id)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn destroy_voice(&self, voice_id: VoiceId) {
|
||||
self.commands
|
||||
.lock()
|
||||
.unwrap()
|
||||
.push(Command::DestroyVoice(voice_id));
|
||||
fn push_command(&self, command: Command) {
|
||||
self.commands.lock().unwrap().push(command);
|
||||
self.pending_trigger.wakeup();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn play(&self, _: VoiceId) {
|
||||
//unimplemented!()
|
||||
pub fn destroy_voice(&self, voice_id: VoiceId) {
|
||||
self.push_command(Command::DestroyVoice(voice_id));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pause(&self, _: VoiceId) {
|
||||
unimplemented!()
|
||||
pub fn play(&self, voice_id: VoiceId) {
|
||||
self.push_command(Command::PlayVoice(voice_id));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pause(&self, voice_id: VoiceId) {
|
||||
self.push_command(Command::PauseVoice(voice_id));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue