sbz_switch/soundcore/
event.rs1use futures::channel::mpsc;
2use futures::sink::SinkExt;
3use futures::{executor, Stream};
4
5use std::clone::Clone;
6use std::mem;
7use std::pin::Pin;
8use std::task::{Context, Poll};
9
10use slog::Logger;
11
12use winapi::shared::winerror::E_ABORT;
13
14use crate::com::event::ComEventIterator;
15use crate::com::ComObject;
16use crate::ctsndcr::{EventInfo, ICallback, IEventNotify, ISoundCore, Param};
17use crate::hresult::{check, Win32Error};
18
19use super::{SoundCoreFeature, SoundCoreParameter};
20
21pub(crate) struct SoundCoreEvents {
22 event_notify: ComObject<IEventNotify>,
23 events: mpsc::UnboundedReceiver<EventInfo>,
24 logger: Logger,
25 core: ComObject<ISoundCore>,
26}
27
28impl SoundCoreEvents {
29 pub fn new(
30 event_notify: ComObject<IEventNotify>,
31 core: ComObject<ISoundCore>,
32 logger: Logger,
33 ) -> Result<Self, Win32Error> {
34 let (mut tx, rx) = mpsc::unbounded();
35
36 unsafe {
37 let callback = ICallback::new(move |e| match executor::block_on(tx.send(*e)) {
38 Ok(()) => Ok(()),
39 Err(_) => Err(Win32Error::new(E_ABORT)),
40 });
41
42 let result = check((*event_notify).RegisterEventCallback(0xff, callback));
43 (*callback).Release();
44 result?;
45 }
46
47 Ok(Self {
48 event_notify,
49 events: rx,
50 core,
51 logger,
52 })
53 }
54}
55
56impl Stream for SoundCoreEvents {
57 type Item = Result<SoundCoreEvent, Win32Error>;
58
59 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
60 match Pin::new(&mut self.events).poll_next(cx) {
61 Poll::Ready(Some(e)) => Poll::Ready(Some(match e.event {
62 2 => unsafe {
63 let mut feature = mem::zeroed();
64 let feature = check(self.core.GetFeatureInfo(
65 0,
66 e.data_or_feature_id,
67 &mut feature,
68 ))
69 .map(|_| feature);
70 match feature {
71 Ok(feature) => {
72 let feature = SoundCoreFeature::new(
73 self.core.clone(),
74 self.logger.clone(),
75 0,
76 &feature,
77 );
78 let mut param = mem::zeroed();
79 let param = check(self.core.GetParamInfo(
80 Param {
81 param: e.param_id,
82 feature: e.data_or_feature_id,
83 context: 0,
84 },
85 &mut param,
86 ))
87 .map(|_| param);
88 match param {
89 Ok(param) => {
90 let param = SoundCoreParameter::new(
91 self.core.clone(),
92 feature.description.clone(),
93 self.logger.clone(),
94 ¶m,
95 );
96 Ok(SoundCoreEvent::ParamChange {
97 feature,
98 parameter: param,
99 })
100 }
101 Err(error) => Err(error),
102 }
103 }
104 Err(error) => Err(error),
105 }
106 },
107 _ => Ok(SoundCoreEvent::Unknown(e)),
108 })),
109 Poll::Ready(None) => Poll::Ready(None),
110 Poll::Pending => Poll::Pending,
111 }
112 }
113}
114
115impl Drop for SoundCoreEvents {
116 fn drop(&mut self) {
117 unsafe {
118 self.event_notify.UnregisterEventCallback();
119 }
120 }
121}
122
123pub struct SoundCoreEventIterator {
130 inner: ComEventIterator<SoundCoreEvents>,
131}
132
133impl SoundCoreEventIterator {
134 pub(crate) fn new(stream: SoundCoreEvents) -> Self {
135 SoundCoreEventIterator {
136 inner: ComEventIterator::new(stream),
137 }
138 }
139}
140
141impl Iterator for SoundCoreEventIterator {
142 type Item = Result<SoundCoreEvent, Win32Error>;
143
144 fn next(&mut self) -> Option<Result<SoundCoreEvent, Win32Error>> {
145 self.inner.next()
146 }
147}
148
149#[derive(Debug)]
151pub enum SoundCoreEvent {
152 Unknown(EventInfo),
156 ParamChange {
158 feature: SoundCoreFeature,
160 parameter: SoundCoreParameter,
162 },
163}