Merge pull request #235 from ArtemGr/master
Switching the headset on and off
This commit is contained in:
commit
b82ca1e348
|
@ -20,6 +20,7 @@ use COMMON_SAMPLE_RATES;
|
||||||
use super::check_result;
|
use super::check_result;
|
||||||
use super::com;
|
use super::com;
|
||||||
use super::winapi::Interface;
|
use super::winapi::Interface;
|
||||||
|
use super::winapi::ctypes::c_void;
|
||||||
use super::winapi::shared::devpkey;
|
use super::winapi::shared::devpkey;
|
||||||
use super::winapi::shared::ksmedia;
|
use super::winapi::shared::ksmedia;
|
||||||
use super::winapi::shared::guiddef::{
|
use super::winapi::shared::guiddef::{
|
||||||
|
@ -31,6 +32,9 @@ use super::winapi::shared::minwindef::{
|
||||||
};
|
};
|
||||||
use super::winapi::shared::mmreg;
|
use super::winapi::shared::mmreg;
|
||||||
use super::winapi::shared::wtypes;
|
use super::winapi::shared::wtypes;
|
||||||
|
// https://msdn.microsoft.com/en-us/library/cc230355.aspx
|
||||||
|
use super::winapi::um::winnt::LPWSTR;
|
||||||
|
use super::winapi::um::winnt::WCHAR;
|
||||||
use super::winapi::um::coml2api;
|
use super::winapi::um::coml2api;
|
||||||
use super::winapi::um::audioclient::{
|
use super::winapi::um::audioclient::{
|
||||||
IAudioClient,
|
IAudioClient,
|
||||||
|
@ -532,7 +536,41 @@ impl Device {
|
||||||
impl PartialEq for Device {
|
impl PartialEq for Device {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, other: &Device) -> bool {
|
fn eq(&self, other: &Device) -> bool {
|
||||||
self.device == other.device
|
// Use case: In oder to check whether the default device has changed
|
||||||
|
// the client code might need to compare the previous default device with the current one.
|
||||||
|
// The pointer comparison (`self.device == other.device`) don't work there,
|
||||||
|
// because the pointers are different even when the default device stays the same.
|
||||||
|
//
|
||||||
|
// In this code section we're trying to use the GetId method for the device comparison, cf.
|
||||||
|
// https://docs.microsoft.com/en-us/windows/desktop/api/mmdeviceapi/nf-mmdeviceapi-immdevice-getid
|
||||||
|
unsafe {
|
||||||
|
struct IdRAII (LPWSTR);
|
||||||
|
/// RAII for device IDs.
|
||||||
|
impl Drop for IdRAII {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {CoTaskMemFree(self.0 as *mut c_void)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut id1: LPWSTR = ptr::null_mut();
|
||||||
|
let rc1 = (*self.device).GetId(&mut id1);
|
||||||
|
// GetId only fails with E_OUTOFMEMORY and if it does, we're probably dead already.
|
||||||
|
// Plus it won't do to change the device comparison logic unexpectedly.
|
||||||
|
if rc1 != winerror::S_OK {panic! ("cpal: GetId failure: {}", rc1)}
|
||||||
|
let id1 = IdRAII(id1);
|
||||||
|
let mut id2: LPWSTR = ptr::null_mut();
|
||||||
|
let rc2 = (*other.device).GetId(&mut id2);
|
||||||
|
if rc2 != winerror::S_OK {panic! ("cpal: GetId failure: {}", rc1)}
|
||||||
|
let id2 = IdRAII(id2);
|
||||||
|
// 16-bit null-terminated comparison.
|
||||||
|
let mut offset = 0;
|
||||||
|
loop {
|
||||||
|
let w1: WCHAR = *id1.0.offset(offset);
|
||||||
|
let w2: WCHAR = *id2.0.offset(offset);
|
||||||
|
if w1 == 0 && w2 == 0 {return true}
|
||||||
|
if w1 != w2 {return false}
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -500,6 +500,13 @@ impl EventLoop {
|
||||||
let mut frames_available = {
|
let mut frames_available = {
|
||||||
let mut padding = mem::uninitialized();
|
let mut padding = mem::uninitialized();
|
||||||
let hresult = (*stream.audio_client).GetCurrentPadding(&mut padding);
|
let hresult = (*stream.audio_client).GetCurrentPadding(&mut padding);
|
||||||
|
// Happens when a bluetooth headset was turned off, for example.
|
||||||
|
if hresult == AUDCLNT_E_DEVICE_INVALIDATED {
|
||||||
|
// The client code should switch to a different device eventually.
|
||||||
|
// For now let's just skip the invalidated device.
|
||||||
|
// Would be nice to inform the client code about the invalidation,
|
||||||
|
// but throwing a panic isn't the most ergonomic way to do so.
|
||||||
|
continue}
|
||||||
check_result(hresult).unwrap();
|
check_result(hresult).unwrap();
|
||||||
stream.max_frames_in_buffer - padding
|
stream.max_frames_in_buffer - padding
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue