Add some documentation to the winapi implementation
This commit is contained in:
parent
b1add0b12b
commit
bf051dd16f
|
@ -32,10 +32,25 @@ unsafe impl Send for EventLoop {}
|
||||||
unsafe impl Sync for EventLoop {}
|
unsafe impl Sync for EventLoop {}
|
||||||
|
|
||||||
struct EventLoopInner {
|
struct EventLoopInner {
|
||||||
// This event is signalled after elements have been added to `pending_scheduled`.
|
// List of handles that are currently being polled or that are going to be polled. This mutex
|
||||||
pending_scheduled_event: winapi::HANDLE,
|
// is locked for as long as the event loop is running.
|
||||||
|
//
|
||||||
|
// In the `EventLoopScheduled`, the first handle in the list of handles is always
|
||||||
|
// `pending_scheduled_event`. This means that the length of `handles` is always 1 + the length
|
||||||
|
// of `task_handles`.
|
||||||
|
// FIXME: no way to remove elements from that list?
|
||||||
scheduled: Mutex<EventLoopScheduled>,
|
scheduled: Mutex<EventLoopScheduled>,
|
||||||
|
|
||||||
|
// Since the above mutex is locked most of the time, we add new handles to this list instead.
|
||||||
|
// After a new element is added to this list, you should notify `pending_scheduled_event`
|
||||||
|
// so that they get transferred to `scheduled`.
|
||||||
|
//
|
||||||
|
// The length of `handles` and `task_handles` should always be equal.
|
||||||
pending_scheduled: Mutex<EventLoopScheduled>,
|
pending_scheduled: Mutex<EventLoopScheduled>,
|
||||||
|
|
||||||
|
// This event is signalled after elements have been added to `pending_scheduled` in order to
|
||||||
|
// notify that they should be picked up.
|
||||||
|
pending_scheduled_event: winapi::HANDLE,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EventLoopScheduled {
|
struct EventLoopScheduled {
|
||||||
|
@ -44,7 +59,8 @@ struct EventLoopScheduled {
|
||||||
// `WaitForMultipleObjectsEx` on the array without having to perform any conversion.
|
// `WaitForMultipleObjectsEx` on the array without having to perform any conversion.
|
||||||
handles: Vec<winapi::HANDLE>,
|
handles: Vec<winapi::HANDLE>,
|
||||||
|
|
||||||
// List of task handles corresponding to `handles`.
|
// List of task handles corresponding to `handles`. The second element is used to signal
|
||||||
|
// the voice that it has been signaled.
|
||||||
task_handles: Vec<(TaskHandle, Arc<AtomicBool>)>,
|
task_handles: Vec<(TaskHandle, Arc<AtomicBool>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +90,10 @@ impl EventLoop {
|
||||||
let mut scheduled = self.inner.scheduled.lock().unwrap();
|
let mut scheduled = self.inner.scheduled.lock().unwrap();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
debug_assert!(scheduled.handles.len() == 1 + scheduled.task_handles.len());
|
||||||
|
|
||||||
// Creating a voice checks for the MAXIMUM_WAIT_OBJECTS limit.
|
// Creating a voice checks for the MAXIMUM_WAIT_OBJECTS limit.
|
||||||
|
// FIXME: this is not the case ^
|
||||||
debug_assert!(scheduled.handles.len() <= winapi::MAXIMUM_WAIT_OBJECTS as usize);
|
debug_assert!(scheduled.handles.len() <= winapi::MAXIMUM_WAIT_OBJECTS as usize);
|
||||||
|
|
||||||
// Wait for any of the handles to be signalled, which means that the corresponding
|
// Wait for any of the handles to be signalled, which means that the corresponding
|
||||||
|
@ -89,6 +108,8 @@ impl EventLoop {
|
||||||
let handle_id = (result - winapi::WAIT_OBJECT_0) as usize;
|
let handle_id = (result - winapi::WAIT_OBJECT_0) as usize;
|
||||||
|
|
||||||
if handle_id == 0 {
|
if handle_id == 0 {
|
||||||
|
// The `pending_scheduled_event` handle has been notified, which means that we
|
||||||
|
// should pick up the content of `pending_scheduled`.
|
||||||
let mut pending = self.inner.pending_scheduled.lock().unwrap();
|
let mut pending = self.inner.pending_scheduled.lock().unwrap();
|
||||||
scheduled.handles.append(&mut pending.handles);
|
scheduled.handles.append(&mut pending.handles);
|
||||||
scheduled.task_handles.append(&mut pending.task_handles);
|
scheduled.task_handles.append(&mut pending.task_handles);
|
||||||
|
@ -144,18 +165,18 @@ impl Voice {
|
||||||
-> Result<(Voice, SamplesStream), CreationError>
|
-> Result<(Voice, SamplesStream), CreationError>
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
// making sure that COM is initialized
|
// Making sure that COM is initialized.
|
||||||
// it's not actually sure that this is required, but when in doubt do it
|
// It's not actually sure that this is required, but when in doubt do it.
|
||||||
com::com_initialized();
|
com::com_initialized();
|
||||||
|
|
||||||
// obtaining a `IAudioClient`
|
// Obtaining a `IAudioClient`.
|
||||||
let audio_client = match end_point.build_audioclient() {
|
let audio_client = match end_point.build_audioclient() {
|
||||||
Err(ref e) if e.raw_os_error() == Some(winapi::AUDCLNT_E_DEVICE_INVALIDATED) =>
|
Err(ref e) if e.raw_os_error() == Some(winapi::AUDCLNT_E_DEVICE_INVALIDATED) =>
|
||||||
return Err(CreationError::DeviceNotAvailable),
|
return Err(CreationError::DeviceNotAvailable),
|
||||||
e => e.unwrap(),
|
e => e.unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// computing the format and initializing the device
|
// Computing the format and initializing the device.
|
||||||
let format = {
|
let format = {
|
||||||
let format_attempt = try!(format_to_waveformatextensible(format));
|
let format_attempt = try!(format_to_waveformatextensible(format));
|
||||||
let share_mode = winapi::AUDCLNT_SHAREMODE_SHARED;
|
let share_mode = winapi::AUDCLNT_SHAREMODE_SHARED;
|
||||||
|
@ -334,9 +355,10 @@ impl Stream for SamplesStream {
|
||||||
fn poll(&mut self, _: &mut Task) -> Poll<Option<Self::Item>, Self::Error> {
|
fn poll(&mut self, _: &mut Task) -> Poll<Option<Self::Item>, Self::Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if self.ready.swap(false, Ordering::Relaxed) == false {
|
if self.ready.swap(false, Ordering::Relaxed) == false {
|
||||||
|
// Despite its name this function does not block, because we pass `0`.
|
||||||
let result = kernel32::WaitForSingleObject(self.event, 0);
|
let result = kernel32::WaitForSingleObject(self.event, 0);
|
||||||
|
|
||||||
// Returning if timeout.
|
// Returning if the event is not ready.
|
||||||
match result {
|
match result {
|
||||||
winapi::WAIT_OBJECT_0 => (),
|
winapi::WAIT_OBJECT_0 => (),
|
||||||
winapi::WAIT_TIMEOUT => return Poll::NotReady,
|
winapi::WAIT_TIMEOUT => return Poll::NotReady,
|
||||||
|
@ -344,6 +366,8 @@ impl Stream for SamplesStream {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we reach here, that means we're ready to accept new samples.
|
||||||
|
|
||||||
let mut inner = self.inner.lock().unwrap();
|
let mut inner = self.inner.lock().unwrap();
|
||||||
|
|
||||||
// Obtaining the number of frames that are available to be written.
|
// Obtaining the number of frames that are available to be written.
|
||||||
|
|
Loading…
Reference in New Issue