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.
|
- Changed the emscripten backend to consume less CPU.
|
||||||
- Added improvements to the crate documentation.
|
- Added improvements to the crate documentation.
|
||||||
|
- Implement `pause` and `play` for ALSA backend.
|
||||||
|
|
||||||
# Version 0.5.1 (2017-10-21)
|
# Version 0.5.1 (2017-10-21)
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@ use SupportedFormat;
|
||||||
use UnknownTypeBuffer;
|
use UnknownTypeBuffer;
|
||||||
|
|
||||||
use std::{cmp, ffi, iter, mem, ptr};
|
use std::{cmp, ffi, iter, mem, ptr};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::Mutex;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::vec::IntoIter as VecIntoIter;
|
use std::vec::IntoIter as VecIntoIter;
|
||||||
|
|
||||||
pub type SupportedFormatsIterator = VecIntoIter<SupportedFormat>;
|
pub type SupportedFormatsIterator = VecIntoIter<SupportedFormat>;
|
||||||
|
@ -276,6 +276,8 @@ unsafe impl Sync for EventLoop {
|
||||||
|
|
||||||
enum Command {
|
enum Command {
|
||||||
NewVoice(VoiceInner),
|
NewVoice(VoiceInner),
|
||||||
|
PlayVoice(VoiceId),
|
||||||
|
PauseVoice(VoiceId),
|
||||||
DestroyVoice(VoiceId),
|
DestroyVoice(VoiceId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,8 +311,11 @@ struct VoiceInner {
|
||||||
// Minimum number of samples to put in the buffer.
|
// Minimum number of samples to put in the buffer.
|
||||||
period_len: usize,
|
period_len: usize,
|
||||||
|
|
||||||
// Wherease the sample stream is paused
|
// Whether or not the hardware supports pausing the stream.
|
||||||
is_paused: AtomicBool,
|
can_pause: bool,
|
||||||
|
|
||||||
|
// Whether or not the sample stream is currently paused.
|
||||||
|
is_paused: bool,
|
||||||
|
|
||||||
// A file descriptor opened with `eventfd`.
|
// A file descriptor opened with `eventfd`.
|
||||||
// It is used to wait for resume signal.
|
// It is used to wait for resume signal.
|
||||||
|
@ -367,6 +372,22 @@ impl EventLoop {
|
||||||
Command::DestroyVoice(voice_id) => {
|
Command::DestroyVoice(voice_id) => {
|
||||||
run_context.voices.retain(|v| v.id != 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) => {
|
Command::NewVoice(voice_inner) => {
|
||||||
run_context.voices.push(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))
|
check_errors(alsa::snd_pcm_hw_params(playback_handle, hw_params.0))
|
||||||
.expect("hardware params could not be set");
|
.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
|
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_malloc(&mut sw_params)).unwrap();
|
||||||
check_errors(alsa::snd_pcm_sw_params_current(playback_handle, 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,
|
num_channels: format.channels.len() as u16,
|
||||||
buffer_len: buffer_len,
|
buffer_len: buffer_len,
|
||||||
period_len: period_len,
|
period_len: period_len,
|
||||||
is_paused: AtomicBool::new(true),
|
can_pause: can_pause,
|
||||||
|
is_paused: false,
|
||||||
resume_trigger: Trigger::new(),
|
resume_trigger: Trigger::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.commands
|
self.push_command(Command::NewVoice(voice_inner));
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push(Command::NewVoice(voice_inner));
|
|
||||||
self.pending_trigger.wakeup();
|
|
||||||
Ok(new_voice_id)
|
Ok(new_voice_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn destroy_voice(&self, voice_id: VoiceId) {
|
fn push_command(&self, command: Command) {
|
||||||
self.commands
|
self.commands.lock().unwrap().push(command);
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push(Command::DestroyVoice(voice_id));
|
|
||||||
self.pending_trigger.wakeup();
|
self.pending_trigger.wakeup();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn play(&self, _: VoiceId) {
|
pub fn destroy_voice(&self, voice_id: VoiceId) {
|
||||||
//unimplemented!()
|
self.push_command(Command::DestroyVoice(voice_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pause(&self, _: VoiceId) {
|
pub fn play(&self, voice_id: VoiceId) {
|
||||||
unimplemented!()
|
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