1 | //! Platform-specific items. |
2 | //! |
3 | //! This module also contains the implementation of the platform's dynamically dispatched [`Host`] |
4 | //! type and its associated [`Device`], [`Stream`] and other associated types. These |
5 | //! types are useful in the case that users require switching between audio host APIs at runtime. |
6 | |
7 | #[doc (inline)] |
8 | pub use self::platform_impl::*; |
9 | |
10 | /// A macro to assist with implementing a platform's dynamically dispatched [`Host`] type. |
11 | /// |
12 | /// These dynamically dispatched types are necessary to allow for users to switch between hosts at |
13 | /// runtime. |
14 | /// |
15 | /// For example the invocation `impl_platform_host(Wasapi wasapi "WASAPI", Asio asio "ASIO")`, |
16 | /// this macro should expand to: |
17 | /// |
18 | // This sample code block is marked as text because it's not a valid test, |
19 | // it's just illustrative. (see rust issue #96573) |
20 | /// ```text |
21 | /// pub enum HostId { |
22 | /// Wasapi, |
23 | /// Asio, |
24 | /// } |
25 | /// |
26 | /// pub enum Host { |
27 | /// Wasapi(crate::host::wasapi::Host), |
28 | /// Asio(crate::host::asio::Host), |
29 | /// } |
30 | /// ``` |
31 | /// |
32 | /// And so on for Device, Devices, Host, Stream, SupportedInputConfigs, |
33 | /// SupportedOutputConfigs and all their necessary trait implementations. |
34 | /// |
35 | macro_rules! impl_platform_host { |
36 | ($($(#[cfg($feat: meta)])? $HostVariant:ident $host_mod:ident $host_name:literal),*) => { |
37 | /// All hosts supported by CPAL on this platform. |
38 | pub const ALL_HOSTS: &'static [HostId] = &[ |
39 | $( |
40 | $(#[cfg($feat)])? |
41 | HostId::$HostVariant, |
42 | )* |
43 | ]; |
44 | |
45 | /// The platform's dynamically dispatched `Host` type. |
46 | /// |
47 | /// An instance of this `Host` type may represent one of the `Host`s available |
48 | /// on the platform. |
49 | /// |
50 | /// Use this type if you require switching between available hosts at runtime. |
51 | /// |
52 | /// This type may be constructed via the [`host_from_id`] function. [`HostId`]s may |
53 | /// be acquired via the [`ALL_HOSTS`] const, and the [`available_hosts`] function. |
54 | pub struct Host(HostInner); |
55 | |
56 | /// The `Device` implementation associated with the platform's dynamically dispatched |
57 | /// [`Host`] type. |
58 | #[derive(Clone)] |
59 | pub struct Device(DeviceInner); |
60 | |
61 | /// The `Devices` iterator associated with the platform's dynamically dispatched [`Host`] |
62 | /// type. |
63 | pub struct Devices(DevicesInner); |
64 | |
65 | /// The `Stream` implementation associated with the platform's dynamically dispatched |
66 | /// [`Host`] type. |
67 | // Streams cannot be `Send` or `Sync` if we plan to support Android's AAudio API. This is |
68 | // because the stream API is not thread-safe, and the API prohibits calling certain |
69 | // functions within the callback. |
70 | // |
71 | // TODO: Confirm this and add more specific detail and references. |
72 | #[must_use = "If the stream is not stored it will not play." ] |
73 | pub struct Stream(StreamInner, crate::platform::NotSendSyncAcrossAllPlatforms); |
74 | |
75 | /// The `SupportedInputConfigs` iterator associated with the platform's dynamically |
76 | /// dispatched [`Host`] type. |
77 | pub struct SupportedInputConfigs(SupportedInputConfigsInner); |
78 | |
79 | /// The `SupportedOutputConfigs` iterator associated with the platform's dynamically |
80 | /// dispatched [`Host`] type. |
81 | pub struct SupportedOutputConfigs(SupportedOutputConfigsInner); |
82 | |
83 | /// Unique identifier for available hosts on the platform. |
84 | #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] |
85 | pub enum HostId { |
86 | $( |
87 | $(#[cfg($feat)])? |
88 | $HostVariant, |
89 | )* |
90 | } |
91 | |
92 | /// Contains a platform specific [`Device`] implementation. |
93 | #[derive(Clone)] |
94 | pub enum DeviceInner { |
95 | $( |
96 | $(#[cfg($feat)])? |
97 | $HostVariant(crate::host::$host_mod::Device), |
98 | )* |
99 | } |
100 | |
101 | /// Contains a platform specific [`Devices`] implementation. |
102 | pub enum DevicesInner { |
103 | $( |
104 | $(#[cfg($feat)])? |
105 | $HostVariant(crate::host::$host_mod::Devices), |
106 | )* |
107 | } |
108 | |
109 | /// Contains a platform specific [`Host`] implementation. |
110 | pub enum HostInner { |
111 | $( |
112 | $(#[cfg($feat)])? |
113 | $HostVariant(crate::host::$host_mod::Host), |
114 | )* |
115 | } |
116 | |
117 | /// Contains a platform specific [`Stream`] implementation. |
118 | pub enum StreamInner { |
119 | $( |
120 | $(#[cfg($feat)])? |
121 | $HostVariant(crate::host::$host_mod::Stream), |
122 | )* |
123 | } |
124 | |
125 | enum SupportedInputConfigsInner { |
126 | $( |
127 | $(#[cfg($feat)])? |
128 | $HostVariant(crate::host::$host_mod::SupportedInputConfigs), |
129 | )* |
130 | } |
131 | |
132 | enum SupportedOutputConfigsInner { |
133 | $( |
134 | $(#[cfg($feat)])? |
135 | $HostVariant(crate::host::$host_mod::SupportedOutputConfigs), |
136 | )* |
137 | } |
138 | |
139 | impl HostId { |
140 | pub fn name(&self) -> &'static str { |
141 | match self { |
142 | $( |
143 | $(#[cfg($feat)])? |
144 | HostId::$HostVariant => $host_name, |
145 | )* |
146 | } |
147 | } |
148 | } |
149 | |
150 | impl Devices { |
151 | /// Returns a reference to the underlying platform specific implementation of this |
152 | /// `Devices`. |
153 | pub fn as_inner(&self) -> &DevicesInner { |
154 | &self.0 |
155 | } |
156 | |
157 | /// Returns a mutable reference to the underlying platform specific implementation of |
158 | /// this `Devices`. |
159 | pub fn as_inner_mut(&mut self) -> &mut DevicesInner { |
160 | &mut self.0 |
161 | } |
162 | |
163 | /// Returns the underlying platform specific implementation of this `Devices`. |
164 | pub fn into_inner(self) -> DevicesInner { |
165 | self.0 |
166 | } |
167 | } |
168 | |
169 | impl Device { |
170 | /// Returns a reference to the underlying platform specific implementation of this |
171 | /// `Device`. |
172 | pub fn as_inner(&self) -> &DeviceInner { |
173 | &self.0 |
174 | } |
175 | |
176 | /// Returns a mutable reference to the underlying platform specific implementation of |
177 | /// this `Device`. |
178 | pub fn as_inner_mut(&mut self) -> &mut DeviceInner { |
179 | &mut self.0 |
180 | } |
181 | |
182 | /// Returns the underlying platform specific implementation of this `Device`. |
183 | pub fn into_inner(self) -> DeviceInner { |
184 | self.0 |
185 | } |
186 | } |
187 | |
188 | impl Host { |
189 | /// The unique identifier associated with this `Host`. |
190 | pub fn id(&self) -> HostId { |
191 | match self.0 { |
192 | $( |
193 | $(#[cfg($feat)])? |
194 | HostInner::$HostVariant(_) => HostId::$HostVariant, |
195 | )* |
196 | } |
197 | } |
198 | |
199 | /// Returns a reference to the underlying platform specific implementation of this |
200 | /// `Host`. |
201 | pub fn as_inner(&self) -> &HostInner { |
202 | &self.0 |
203 | } |
204 | |
205 | /// Returns a mutable reference to the underlying platform specific implementation of |
206 | /// this `Host`. |
207 | pub fn as_inner_mut(&mut self) -> &mut HostInner { |
208 | &mut self.0 |
209 | } |
210 | |
211 | /// Returns the underlying platform specific implementation of this `Host`. |
212 | pub fn into_inner(self) -> HostInner { |
213 | self.0 |
214 | } |
215 | } |
216 | |
217 | impl Stream { |
218 | /// Returns a reference to the underlying platform specific implementation of this |
219 | /// `Stream`. |
220 | pub fn as_inner(&self) -> &StreamInner { |
221 | &self.0 |
222 | } |
223 | |
224 | /// Returns a mutable reference to the underlying platform specific implementation of |
225 | /// this `Stream`. |
226 | pub fn as_inner_mut(&mut self) -> &mut StreamInner { |
227 | &mut self.0 |
228 | } |
229 | |
230 | /// Returns the underlying platform specific implementation of this `Stream`. |
231 | pub fn into_inner(self) -> StreamInner { |
232 | self.0 |
233 | } |
234 | } |
235 | |
236 | impl Iterator for Devices { |
237 | type Item = Device; |
238 | |
239 | fn next(&mut self) -> Option<Self::Item> { |
240 | match self.0 { |
241 | $( |
242 | $(#[cfg($feat)])? |
243 | DevicesInner::$HostVariant(ref mut d) => { |
244 | d.next().map(DeviceInner::$HostVariant).map(Device::from) |
245 | } |
246 | )* |
247 | } |
248 | } |
249 | |
250 | fn size_hint(&self) -> (usize, Option<usize>) { |
251 | match self.0 { |
252 | $( |
253 | $(#[cfg($feat)])? |
254 | DevicesInner::$HostVariant(ref d) => d.size_hint(), |
255 | )* |
256 | } |
257 | } |
258 | } |
259 | |
260 | impl Iterator for SupportedInputConfigs { |
261 | type Item = crate::SupportedStreamConfigRange; |
262 | |
263 | fn next(&mut self) -> Option<Self::Item> { |
264 | match self.0 { |
265 | $( |
266 | $(#[cfg($feat)])? |
267 | SupportedInputConfigsInner::$HostVariant(ref mut s) => s.next(), |
268 | )* |
269 | } |
270 | } |
271 | |
272 | fn size_hint(&self) -> (usize, Option<usize>) { |
273 | match self.0 { |
274 | $( |
275 | $(#[cfg($feat)])? |
276 | SupportedInputConfigsInner::$HostVariant(ref d) => d.size_hint(), |
277 | )* |
278 | } |
279 | } |
280 | } |
281 | |
282 | impl Iterator for SupportedOutputConfigs { |
283 | type Item = crate::SupportedStreamConfigRange; |
284 | |
285 | fn next(&mut self) -> Option<Self::Item> { |
286 | match self.0 { |
287 | $( |
288 | $(#[cfg($feat)])? |
289 | SupportedOutputConfigsInner::$HostVariant(ref mut s) => s.next(), |
290 | )* |
291 | } |
292 | } |
293 | |
294 | fn size_hint(&self) -> (usize, Option<usize>) { |
295 | match self.0 { |
296 | $( |
297 | $(#[cfg($feat)])? |
298 | SupportedOutputConfigsInner::$HostVariant(ref d) => d.size_hint(), |
299 | )* |
300 | } |
301 | } |
302 | } |
303 | |
304 | impl crate::traits::DeviceTrait for Device { |
305 | type SupportedInputConfigs = SupportedInputConfigs; |
306 | type SupportedOutputConfigs = SupportedOutputConfigs; |
307 | type Stream = Stream; |
308 | |
309 | fn name(&self) -> Result<String, crate::DeviceNameError> { |
310 | match self.0 { |
311 | $( |
312 | $(#[cfg($feat)])? |
313 | DeviceInner::$HostVariant(ref d) => d.name(), |
314 | )* |
315 | } |
316 | } |
317 | |
318 | fn supported_input_configs(&self) -> Result<Self::SupportedInputConfigs, crate::SupportedStreamConfigsError> { |
319 | match self.0 { |
320 | $( |
321 | $(#[cfg($feat)])? |
322 | DeviceInner::$HostVariant(ref d) => { |
323 | d.supported_input_configs() |
324 | .map(SupportedInputConfigsInner::$HostVariant) |
325 | .map(SupportedInputConfigs) |
326 | } |
327 | )* |
328 | } |
329 | } |
330 | |
331 | fn supported_output_configs(&self) -> Result<Self::SupportedOutputConfigs, crate::SupportedStreamConfigsError> { |
332 | match self.0 { |
333 | $( |
334 | $(#[cfg($feat)])? |
335 | DeviceInner::$HostVariant(ref d) => { |
336 | d.supported_output_configs() |
337 | .map(SupportedOutputConfigsInner::$HostVariant) |
338 | .map(SupportedOutputConfigs) |
339 | } |
340 | )* |
341 | } |
342 | } |
343 | |
344 | fn default_input_config(&self) -> Result<crate::SupportedStreamConfig, crate::DefaultStreamConfigError> { |
345 | match self.0 { |
346 | $( |
347 | $(#[cfg($feat)])? |
348 | DeviceInner::$HostVariant(ref d) => d.default_input_config(), |
349 | )* |
350 | } |
351 | } |
352 | |
353 | fn default_output_config(&self) -> Result<crate::SupportedStreamConfig, crate::DefaultStreamConfigError> { |
354 | match self.0 { |
355 | $( |
356 | $(#[cfg($feat)])? |
357 | DeviceInner::$HostVariant(ref d) => d.default_output_config(), |
358 | )* |
359 | } |
360 | } |
361 | |
362 | fn build_input_stream_raw<D, E>( |
363 | &self, |
364 | config: &crate::StreamConfig, |
365 | sample_format: crate::SampleFormat, |
366 | data_callback: D, |
367 | error_callback: E, |
368 | timeout: Option<std::time::Duration>, |
369 | ) -> Result<Self::Stream, crate::BuildStreamError> |
370 | where |
371 | D: FnMut(&crate::Data, &crate::InputCallbackInfo) + Send + 'static, |
372 | E: FnMut(crate::StreamError) + Send + 'static, |
373 | { |
374 | match self.0 { |
375 | $( |
376 | $(#[cfg($feat)])? |
377 | DeviceInner::$HostVariant(ref d) => d |
378 | .build_input_stream_raw( |
379 | config, |
380 | sample_format, |
381 | data_callback, |
382 | error_callback, |
383 | timeout, |
384 | ) |
385 | .map(StreamInner::$HostVariant) |
386 | .map(Stream::from), |
387 | )* |
388 | } |
389 | } |
390 | |
391 | fn build_output_stream_raw<D, E>( |
392 | &self, |
393 | config: &crate::StreamConfig, |
394 | sample_format: crate::SampleFormat, |
395 | data_callback: D, |
396 | error_callback: E, |
397 | timeout: Option<std::time::Duration>, |
398 | ) -> Result<Self::Stream, crate::BuildStreamError> |
399 | where |
400 | D: FnMut(&mut crate::Data, &crate::OutputCallbackInfo) + Send + 'static, |
401 | E: FnMut(crate::StreamError) + Send + 'static, |
402 | { |
403 | match self.0 { |
404 | $( |
405 | $(#[cfg($feat)])? |
406 | DeviceInner::$HostVariant(ref d) => d |
407 | .build_output_stream_raw( |
408 | config, |
409 | sample_format, |
410 | data_callback, |
411 | error_callback, |
412 | timeout, |
413 | ) |
414 | .map(StreamInner::$HostVariant) |
415 | .map(Stream::from), |
416 | )* |
417 | } |
418 | } |
419 | } |
420 | |
421 | impl crate::traits::HostTrait for Host { |
422 | type Devices = Devices; |
423 | type Device = Device; |
424 | |
425 | fn is_available() -> bool { |
426 | $( |
427 | $(#[cfg($feat)])? |
428 | if crate::host::$host_mod::Host::is_available() { return true; } |
429 | )* |
430 | false |
431 | } |
432 | |
433 | fn devices(&self) -> Result<Self::Devices, crate::DevicesError> { |
434 | match self.0 { |
435 | $( |
436 | $(#[cfg($feat)])? |
437 | HostInner::$HostVariant(ref h) => { |
438 | h.devices().map(DevicesInner::$HostVariant).map(Devices::from) |
439 | } |
440 | )* |
441 | } |
442 | } |
443 | |
444 | fn default_input_device(&self) -> Option<Self::Device> { |
445 | match self.0 { |
446 | $( |
447 | $(#[cfg($feat)])? |
448 | HostInner::$HostVariant(ref h) => { |
449 | h.default_input_device().map(DeviceInner::$HostVariant).map(Device::from) |
450 | } |
451 | )* |
452 | } |
453 | } |
454 | |
455 | fn default_output_device(&self) -> Option<Self::Device> { |
456 | match self.0 { |
457 | $( |
458 | $(#[cfg($feat)])? |
459 | HostInner::$HostVariant(ref h) => { |
460 | h.default_output_device().map(DeviceInner::$HostVariant).map(Device::from) |
461 | } |
462 | )* |
463 | } |
464 | } |
465 | } |
466 | |
467 | impl crate::traits::StreamTrait for Stream { |
468 | fn play(&self) -> Result<(), crate::PlayStreamError> { |
469 | match self.0 { |
470 | $( |
471 | $(#[cfg($feat)])? |
472 | StreamInner::$HostVariant(ref s) => { |
473 | s.play() |
474 | } |
475 | )* |
476 | } |
477 | } |
478 | |
479 | fn pause(&self) -> Result<(), crate::PauseStreamError> { |
480 | match self.0 { |
481 | $( |
482 | $(#[cfg($feat)])? |
483 | StreamInner::$HostVariant(ref s) => { |
484 | s.pause() |
485 | } |
486 | )* |
487 | } |
488 | } |
489 | } |
490 | |
491 | impl From<DeviceInner> for Device { |
492 | fn from(d: DeviceInner) -> Self { |
493 | Device(d) |
494 | } |
495 | } |
496 | |
497 | impl From<DevicesInner> for Devices { |
498 | fn from(d: DevicesInner) -> Self { |
499 | Devices(d) |
500 | } |
501 | } |
502 | |
503 | impl From<HostInner> for Host { |
504 | fn from(h: HostInner) -> Self { |
505 | Host(h) |
506 | } |
507 | } |
508 | |
509 | impl From<StreamInner> for Stream { |
510 | fn from(s: StreamInner) -> Self { |
511 | Stream(s, Default::default()) |
512 | } |
513 | } |
514 | |
515 | $( |
516 | $(#[cfg($feat)])? |
517 | impl From<crate::host::$host_mod::Device> for Device { |
518 | fn from(h: crate::host::$host_mod::Device) -> Self { |
519 | DeviceInner::$HostVariant(h).into() |
520 | } |
521 | } |
522 | |
523 | $(#[cfg($feat)])? |
524 | impl From<crate::host::$host_mod::Devices> for Devices { |
525 | fn from(h: crate::host::$host_mod::Devices) -> Self { |
526 | DevicesInner::$HostVariant(h).into() |
527 | } |
528 | } |
529 | |
530 | $(#[cfg($feat)])? |
531 | impl From<crate::host::$host_mod::Host> for Host { |
532 | fn from(h: crate::host::$host_mod::Host) -> Self { |
533 | HostInner::$HostVariant(h).into() |
534 | } |
535 | } |
536 | |
537 | $(#[cfg($feat)])? |
538 | impl From<crate::host::$host_mod::Stream> for Stream { |
539 | fn from(h: crate::host::$host_mod::Stream) -> Self { |
540 | StreamInner::$HostVariant(h).into() |
541 | } |
542 | } |
543 | )* |
544 | |
545 | /// Produces a list of hosts that are currently available on the system. |
546 | pub fn available_hosts() -> Vec<HostId> { |
547 | let mut host_ids = vec![]; |
548 | $( |
549 | $(#[cfg($feat)])? |
550 | if <crate::host::$host_mod::Host as crate::traits::HostTrait>::is_available() { |
551 | host_ids.push(HostId::$HostVariant); |
552 | } |
553 | )* |
554 | host_ids |
555 | } |
556 | |
557 | /// Given a unique host identifier, initialise and produce the host if it is available. |
558 | pub fn host_from_id(id: HostId) -> Result<Host, crate::HostUnavailable> { |
559 | match id { |
560 | $( |
561 | $(#[cfg($feat)])? |
562 | HostId::$HostVariant => { |
563 | crate::host::$host_mod::Host::new() |
564 | .map(HostInner::$HostVariant) |
565 | .map(Host::from) |
566 | } |
567 | )* |
568 | } |
569 | } |
570 | }; |
571 | } |
572 | |
573 | // TODO: Add pulseaudio and jack here eventually. |
574 | #[cfg (any( |
575 | target_os = "linux" , |
576 | target_os = "dragonfly" , |
577 | target_os = "freebsd" , |
578 | target_os = "netbsd" |
579 | ))] |
580 | mod platform_impl { |
581 | pub use crate::host::alsa::{ |
582 | Device as AlsaDevice, Devices as AlsaDevices, Host as AlsaHost, Stream as AlsaStream, |
583 | SupportedInputConfigs as AlsaSupportedInputConfigs, |
584 | SupportedOutputConfigs as AlsaSupportedOutputConfigs, |
585 | }; |
586 | #[cfg (feature = "jack" )] |
587 | pub use crate::host::jack::{ |
588 | Device as JackDevice, Devices as JackDevices, Host as JackHost, Stream as JackStream, |
589 | SupportedInputConfigs as JackSupportedInputConfigs, |
590 | SupportedOutputConfigs as JackSupportedOutputConfigs, |
591 | }; |
592 | |
593 | impl_platform_host!(#[cfg(feature = "jack" )] Jack jack "JACK" , Alsa alsa "ALSA" ); |
594 | |
595 | /// The default host for the current compilation target platform. |
596 | pub fn default_host() -> Host { |
597 | AlsaHostHost::new() |
598 | .expect(msg:"the default host should always be available" ) |
599 | .into() |
600 | } |
601 | } |
602 | |
603 | #[cfg (any(target_os = "macos" , target_os = "ios" ))] |
604 | mod platform_impl { |
605 | pub use crate::host::coreaudio::{ |
606 | Device as CoreAudioDevice, Devices as CoreAudioDevices, Host as CoreAudioHost, |
607 | Stream as CoreAudioStream, SupportedInputConfigs as CoreAudioSupportedInputConfigs, |
608 | SupportedOutputConfigs as CoreAudioSupportedOutputConfigs, |
609 | }; |
610 | |
611 | impl_platform_host!(CoreAudio coreaudio "CoreAudio" ); |
612 | |
613 | /// The default host for the current compilation target platform. |
614 | pub fn default_host() -> Host { |
615 | CoreAudioHost::new() |
616 | .expect("the default host should always be available" ) |
617 | .into() |
618 | } |
619 | } |
620 | |
621 | #[cfg (target_os = "emscripten" )] |
622 | mod platform_impl { |
623 | pub use crate::host::emscripten::{ |
624 | Device as EmscriptenDevice, Devices as EmscriptenDevices, Host as EmscriptenHost, |
625 | Stream as EmscriptenStream, SupportedInputConfigs as EmscriptenSupportedInputConfigs, |
626 | SupportedOutputConfigs as EmscriptenSupportedOutputConfigs, |
627 | }; |
628 | |
629 | impl_platform_host!(Emscripten emscripten "Emscripten" ); |
630 | |
631 | /// The default host for the current compilation target platform. |
632 | pub fn default_host() -> Host { |
633 | EmscriptenHost::new() |
634 | .expect("the default host should always be available" ) |
635 | .into() |
636 | } |
637 | } |
638 | |
639 | #[cfg (all(target_arch = "wasm32" , feature = "wasm-bindgen" ))] |
640 | mod platform_impl { |
641 | pub use crate::host::webaudio::{ |
642 | Device as WebAudioDevice, Devices as WebAudioDevices, Host as WebAudioHost, |
643 | Stream as WebAudioStream, SupportedInputConfigs as WebAudioSupportedInputConfigs, |
644 | SupportedOutputConfigs as WebAudioSupportedOutputConfigs, |
645 | }; |
646 | |
647 | impl_platform_host!(WebAudio webaudio "WebAudio" ); |
648 | |
649 | /// The default host for the current compilation target platform. |
650 | pub fn default_host() -> Host { |
651 | WebAudioHost::new() |
652 | .expect("the default host should always be available" ) |
653 | .into() |
654 | } |
655 | } |
656 | |
657 | #[cfg (windows)] |
658 | mod platform_impl { |
659 | #[cfg (feature = "asio" )] |
660 | pub use crate::host::asio::{ |
661 | Device as AsioDevice, Devices as AsioDevices, Host as AsioHost, Stream as AsioStream, |
662 | SupportedInputConfigs as AsioSupportedInputConfigs, |
663 | SupportedOutputConfigs as AsioSupportedOutputConfigs, |
664 | }; |
665 | pub use crate::host::wasapi::{ |
666 | Device as WasapiDevice, Devices as WasapiDevices, Host as WasapiHost, |
667 | Stream as WasapiStream, SupportedInputConfigs as WasapiSupportedInputConfigs, |
668 | SupportedOutputConfigs as WasapiSupportedOutputConfigs, |
669 | }; |
670 | |
671 | impl_platform_host!(#[cfg(feature = "asio" )] Asio asio "ASIO" , Wasapi wasapi "WASAPI" ); |
672 | |
673 | /// The default host for the current compilation target platform. |
674 | pub fn default_host() -> Host { |
675 | WasapiHost::new() |
676 | .expect("the default host should always be available" ) |
677 | .into() |
678 | } |
679 | } |
680 | |
681 | #[cfg (target_os = "android" )] |
682 | mod platform_impl { |
683 | pub use crate::host::oboe::{ |
684 | Device as OboeDevice, Devices as OboeDevices, Host as OboeHost, Stream as OboeStream, |
685 | SupportedInputConfigs as OboeSupportedInputConfigs, |
686 | SupportedOutputConfigs as OboeSupportedOutputConfigs, |
687 | }; |
688 | |
689 | impl_platform_host!(Oboe oboe "Oboe" ); |
690 | |
691 | /// The default host for the current compilation target platform. |
692 | pub fn default_host() -> Host { |
693 | OboeHost::new() |
694 | .expect("the default host should always be available" ) |
695 | .into() |
696 | } |
697 | } |
698 | |
699 | #[cfg (not(any( |
700 | windows, |
701 | target_os = "linux" , |
702 | target_os = "dragonfly" , |
703 | target_os = "freebsd" , |
704 | target_os = "netbsd" , |
705 | target_os = "macos" , |
706 | target_os = "ios" , |
707 | target_os = "emscripten" , |
708 | target_os = "android" , |
709 | all(target_arch = "wasm32" , feature = "wasm-bindgen" ), |
710 | )))] |
711 | mod platform_impl { |
712 | pub use crate::host::null::{ |
713 | Device as NullDevice, Devices as NullDevices, Host as NullHost, |
714 | SupportedInputConfigs as NullSupportedInputConfigs, |
715 | SupportedOutputConfigs as NullSupportedOutputConfigs, |
716 | }; |
717 | |
718 | impl_platform_host!(Null null "Null" ); |
719 | |
720 | /// The default host for the current compilation target platform. |
721 | pub fn default_host() -> Host { |
722 | NullHost::new() |
723 | .expect("the default host should always be available" ) |
724 | .into() |
725 | } |
726 | } |
727 | |
728 | // The following zero-sized types are for applying Send/Sync restrictions to ensure |
729 | // consistent behaviour across different platforms. These verbosely named types are used |
730 | // (rather than using the markers directly) in the hope of making the compile errors |
731 | // slightly more helpful. |
732 | // |
733 | // TODO: Remove these in favour of using negative trait bounds if they stabilise. |
734 | |
735 | // A marker used to remove the `Send` and `Sync` traits. |
736 | struct NotSendSyncAcrossAllPlatforms(std::marker::PhantomData<*mut ()>); |
737 | |
738 | impl Default for NotSendSyncAcrossAllPlatforms { |
739 | fn default() -> Self { |
740 | NotSendSyncAcrossAllPlatforms(std::marker::PhantomData) |
741 | } |
742 | } |
743 | |