1#[doc(inline)]
8pub use self::platform_impl::*;
9
10macro_rules! impl_platform_host {
36 ($($(#[cfg($feat: meta)])? $HostVariant:ident $host_mod:ident $host_name:literal),*) => {
37 pub const ALL_HOSTS: &'static [HostId] = &[
39 $(
40 $(#[cfg($feat)])?
41 HostId::$HostVariant,
42 )*
43 ];
44
45 pub struct Host(HostInner);
55
56 #[derive(Clone)]
59 pub struct Device(DeviceInner);
60
61 pub struct Devices(DevicesInner);
64
65 #[must_use = "If the stream is not stored it will not play."]
68 pub struct Stream(StreamInner);
69
70 pub struct SupportedInputConfigs(SupportedInputConfigsInner);
73
74 pub struct SupportedOutputConfigs(SupportedOutputConfigsInner);
77
78 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
80 pub enum HostId {
81 $(
82 $(#[cfg($feat)])?
83 $HostVariant,
84 )*
85 }
86
87 #[derive(Clone)]
89 pub enum DeviceInner {
90 $(
91 $(#[cfg($feat)])?
92 $HostVariant(crate::host::$host_mod::Device),
93 )*
94 }
95
96 pub enum DevicesInner {
98 $(
99 $(#[cfg($feat)])?
100 $HostVariant(crate::host::$host_mod::Devices),
101 )*
102 }
103
104 pub enum HostInner {
106 $(
107 $(#[cfg($feat)])?
108 $HostVariant(crate::host::$host_mod::Host),
109 )*
110 }
111
112 pub enum StreamInner {
114 $(
115 $(#[cfg($feat)])?
116 $HostVariant(crate::host::$host_mod::Stream),
117 )*
118 }
119
120 enum SupportedInputConfigsInner {
121 $(
122 $(#[cfg($feat)])?
123 $HostVariant(crate::host::$host_mod::SupportedInputConfigs),
124 )*
125 }
126
127 enum SupportedOutputConfigsInner {
128 $(
129 $(#[cfg($feat)])?
130 $HostVariant(crate::host::$host_mod::SupportedOutputConfigs),
131 )*
132 }
133
134 impl HostId {
135 pub fn name(&self) -> &'static str {
136 match self {
137 $(
138 $(#[cfg($feat)])?
139 HostId::$HostVariant => $host_name,
140 )*
141 }
142 }
143 }
144
145 impl Devices {
146 pub fn as_inner(&self) -> &DevicesInner {
149 &self.0
150 }
151
152 pub fn as_inner_mut(&mut self) -> &mut DevicesInner {
155 &mut self.0
156 }
157
158 pub fn into_inner(self) -> DevicesInner {
160 self.0
161 }
162 }
163
164 impl Device {
165 pub fn as_inner(&self) -> &DeviceInner {
168 &self.0
169 }
170
171 pub fn as_inner_mut(&mut self) -> &mut DeviceInner {
174 &mut self.0
175 }
176
177 pub fn into_inner(self) -> DeviceInner {
179 self.0
180 }
181 }
182
183 impl Host {
184 pub fn id(&self) -> HostId {
186 match self.0 {
187 $(
188 $(#[cfg($feat)])?
189 HostInner::$HostVariant(_) => HostId::$HostVariant,
190 )*
191 }
192 }
193
194 pub fn as_inner(&self) -> &HostInner {
197 &self.0
198 }
199
200 pub fn as_inner_mut(&mut self) -> &mut HostInner {
203 &mut self.0
204 }
205
206 pub fn into_inner(self) -> HostInner {
208 self.0
209 }
210 }
211
212 impl Stream {
213 pub fn as_inner(&self) -> &StreamInner {
216 &self.0
217 }
218
219 pub fn as_inner_mut(&mut self) -> &mut StreamInner {
222 &mut self.0
223 }
224
225 pub fn into_inner(self) -> StreamInner {
227 self.0
228 }
229 }
230
231 impl Iterator for Devices {
232 type Item = Device;
233
234 fn next(&mut self) -> Option<Self::Item> {
235 match self.0 {
236 $(
237 $(#[cfg($feat)])?
238 DevicesInner::$HostVariant(ref mut d) => {
239 d.next().map(DeviceInner::$HostVariant).map(Device::from)
240 }
241 )*
242 }
243 }
244
245 fn size_hint(&self) -> (usize, Option<usize>) {
246 match self.0 {
247 $(
248 $(#[cfg($feat)])?
249 DevicesInner::$HostVariant(ref d) => d.size_hint(),
250 )*
251 }
252 }
253 }
254
255 impl Iterator for SupportedInputConfigs {
256 type Item = crate::SupportedStreamConfigRange;
257
258 fn next(&mut self) -> Option<Self::Item> {
259 match self.0 {
260 $(
261 $(#[cfg($feat)])?
262 SupportedInputConfigsInner::$HostVariant(ref mut s) => s.next(),
263 )*
264 }
265 }
266
267 fn size_hint(&self) -> (usize, Option<usize>) {
268 match self.0 {
269 $(
270 $(#[cfg($feat)])?
271 SupportedInputConfigsInner::$HostVariant(ref d) => d.size_hint(),
272 )*
273 }
274 }
275 }
276
277 impl Iterator for SupportedOutputConfigs {
278 type Item = crate::SupportedStreamConfigRange;
279
280 fn next(&mut self) -> Option<Self::Item> {
281 match self.0 {
282 $(
283 $(#[cfg($feat)])?
284 SupportedOutputConfigsInner::$HostVariant(ref mut s) => s.next(),
285 )*
286 }
287 }
288
289 fn size_hint(&self) -> (usize, Option<usize>) {
290 match self.0 {
291 $(
292 $(#[cfg($feat)])?
293 SupportedOutputConfigsInner::$HostVariant(ref d) => d.size_hint(),
294 )*
295 }
296 }
297 }
298
299 impl crate::traits::DeviceTrait for Device {
300 type SupportedInputConfigs = SupportedInputConfigs;
301 type SupportedOutputConfigs = SupportedOutputConfigs;
302 type Stream = Stream;
303
304 fn name(&self) -> Result<String, crate::DeviceNameError> {
305 match self.0 {
306 $(
307 $(#[cfg($feat)])?
308 DeviceInner::$HostVariant(ref d) => d.name(),
309 )*
310 }
311 }
312
313 fn supports_input(&self) -> bool {
314 match self.0 {
315 $(
316 $(#[cfg($feat)])?
317 DeviceInner::$HostVariant(ref d) => d.supports_input(),
318 )*
319 }
320 }
321
322 fn supports_output(&self) -> bool {
323 match self.0 {
324 $(
325 $(#[cfg($feat)])?
326 DeviceInner::$HostVariant(ref d) => d.supports_output(),
327 )*
328 }
329 }
330
331 fn supported_input_configs(&self) -> Result<Self::SupportedInputConfigs, crate::SupportedStreamConfigsError> {
332 match self.0 {
333 $(
334 $(#[cfg($feat)])?
335 DeviceInner::$HostVariant(ref d) => {
336 d.supported_input_configs()
337 .map(SupportedInputConfigsInner::$HostVariant)
338 .map(SupportedInputConfigs)
339 }
340 )*
341 }
342 }
343
344 fn supported_output_configs(&self) -> Result<Self::SupportedOutputConfigs, crate::SupportedStreamConfigsError> {
345 match self.0 {
346 $(
347 $(#[cfg($feat)])?
348 DeviceInner::$HostVariant(ref d) => {
349 d.supported_output_configs()
350 .map(SupportedOutputConfigsInner::$HostVariant)
351 .map(SupportedOutputConfigs)
352 }
353 )*
354 }
355 }
356
357 fn default_input_config(&self) -> Result<crate::SupportedStreamConfig, crate::DefaultStreamConfigError> {
358 match self.0 {
359 $(
360 $(#[cfg($feat)])?
361 DeviceInner::$HostVariant(ref d) => d.default_input_config(),
362 )*
363 }
364 }
365
366 fn default_output_config(&self) -> Result<crate::SupportedStreamConfig, crate::DefaultStreamConfigError> {
367 match self.0 {
368 $(
369 $(#[cfg($feat)])?
370 DeviceInner::$HostVariant(ref d) => d.default_output_config(),
371 )*
372 }
373 }
374
375 fn build_input_stream_raw<D, E>(
376 &self,
377 config: &crate::StreamConfig,
378 sample_format: crate::SampleFormat,
379 data_callback: D,
380 error_callback: E,
381 timeout: Option<std::time::Duration>,
382 ) -> Result<Self::Stream, crate::BuildStreamError>
383 where
384 D: FnMut(&crate::Data, &crate::InputCallbackInfo) + Send + 'static,
385 E: FnMut(crate::StreamError) + Send + 'static,
386 {
387 match self.0 {
388 $(
389 $(#[cfg($feat)])?
390 DeviceInner::$HostVariant(ref d) => d
391 .build_input_stream_raw(
392 config,
393 sample_format,
394 data_callback,
395 error_callback,
396 timeout,
397 )
398 .map(StreamInner::$HostVariant)
399 .map(Stream::from),
400 )*
401 }
402 }
403
404 fn build_output_stream_raw<D, E>(
405 &self,
406 config: &crate::StreamConfig,
407 sample_format: crate::SampleFormat,
408 data_callback: D,
409 error_callback: E,
410 timeout: Option<std::time::Duration>,
411 ) -> Result<Self::Stream, crate::BuildStreamError>
412 where
413 D: FnMut(&mut crate::Data, &crate::OutputCallbackInfo) + Send + 'static,
414 E: FnMut(crate::StreamError) + Send + 'static,
415 {
416 match self.0 {
417 $(
418 $(#[cfg($feat)])?
419 DeviceInner::$HostVariant(ref d) => d
420 .build_output_stream_raw(
421 config,
422 sample_format,
423 data_callback,
424 error_callback,
425 timeout,
426 )
427 .map(StreamInner::$HostVariant)
428 .map(Stream::from),
429 )*
430 }
431 }
432 }
433
434 impl crate::traits::HostTrait for Host {
435 type Devices = Devices;
436 type Device = Device;
437
438 fn is_available() -> bool {
439 $(
440 $(#[cfg($feat)])?
441 if crate::host::$host_mod::Host::is_available() { return true; }
442 )*
443 false
444 }
445
446 fn devices(&self) -> Result<Self::Devices, crate::DevicesError> {
447 match self.0 {
448 $(
449 $(#[cfg($feat)])?
450 HostInner::$HostVariant(ref h) => {
451 h.devices().map(DevicesInner::$HostVariant).map(Devices::from)
452 }
453 )*
454 }
455 }
456
457 fn default_input_device(&self) -> Option<Self::Device> {
458 match self.0 {
459 $(
460 $(#[cfg($feat)])?
461 HostInner::$HostVariant(ref h) => {
462 h.default_input_device().map(DeviceInner::$HostVariant).map(Device::from)
463 }
464 )*
465 }
466 }
467
468 fn default_output_device(&self) -> Option<Self::Device> {
469 match self.0 {
470 $(
471 $(#[cfg($feat)])?
472 HostInner::$HostVariant(ref h) => {
473 h.default_output_device().map(DeviceInner::$HostVariant).map(Device::from)
474 }
475 )*
476 }
477 }
478 }
479
480 impl crate::traits::StreamTrait for Stream {
481 fn play(&self) -> Result<(), crate::PlayStreamError> {
482 match self.0 {
483 $(
484 $(#[cfg($feat)])?
485 StreamInner::$HostVariant(ref s) => {
486 s.play()
487 }
488 )*
489 }
490 }
491
492 fn pause(&self) -> Result<(), crate::PauseStreamError> {
493 match self.0 {
494 $(
495 $(#[cfg($feat)])?
496 StreamInner::$HostVariant(ref s) => {
497 s.pause()
498 }
499 )*
500 }
501 }
502 }
503
504 impl From<DeviceInner> for Device {
505 fn from(d: DeviceInner) -> Self {
506 Device(d)
507 }
508 }
509
510 impl From<DevicesInner> for Devices {
511 fn from(d: DevicesInner) -> Self {
512 Devices(d)
513 }
514 }
515
516 impl From<HostInner> for Host {
517 fn from(h: HostInner) -> Self {
518 Host(h)
519 }
520 }
521
522 impl From<StreamInner> for Stream {
523 fn from(s: StreamInner) -> Self {
524 Stream(s)
525 }
526 }
527
528 $(
529 $(#[cfg($feat)])?
530 impl From<crate::host::$host_mod::Device> for Device {
531 fn from(h: crate::host::$host_mod::Device) -> Self {
532 DeviceInner::$HostVariant(h).into()
533 }
534 }
535
536 $(#[cfg($feat)])?
537 impl From<crate::host::$host_mod::Devices> for Devices {
538 fn from(h: crate::host::$host_mod::Devices) -> Self {
539 DevicesInner::$HostVariant(h).into()
540 }
541 }
542
543 $(#[cfg($feat)])?
544 impl From<crate::host::$host_mod::Host> for Host {
545 fn from(h: crate::host::$host_mod::Host) -> Self {
546 HostInner::$HostVariant(h).into()
547 }
548 }
549
550 $(#[cfg($feat)])?
551 impl From<crate::host::$host_mod::Stream> for Stream {
552 fn from(h: crate::host::$host_mod::Stream) -> Self {
553 StreamInner::$HostVariant(h).into()
554 }
555 }
556 )*
557
558 pub fn available_hosts() -> Vec<HostId> {
560 let mut host_ids = vec![];
561 $(
562 $(#[cfg($feat)])?
563 if <crate::host::$host_mod::Host as crate::traits::HostTrait>::is_available() {
564 host_ids.push(HostId::$HostVariant);
565 }
566 )*
567 host_ids
568 }
569
570 pub fn host_from_id(id: HostId) -> Result<Host, crate::HostUnavailable> {
572 match id {
573 $(
574 $(#[cfg($feat)])?
575 HostId::$HostVariant => {
576 crate::host::$host_mod::Host::new()
577 .map(HostInner::$HostVariant)
578 .map(Host::from)
579 }
580 )*
581 }
582 }
583
584 impl Default for Host {
585 fn default() -> Host {
586 default_host()
587 }
588 }
589 };
590}
591
592#[cfg(any(
594 target_os = "linux",
595 target_os = "dragonfly",
596 target_os = "freebsd",
597 target_os = "netbsd"
598))]
599mod platform_impl {
600 pub use crate::host::alsa::{
601 Device as AlsaDevice, Devices as AlsaDevices, Host as AlsaHost, Stream as AlsaStream,
602 SupportedInputConfigs as AlsaSupportedInputConfigs,
603 SupportedOutputConfigs as AlsaSupportedOutputConfigs,
604 };
605 #[cfg(feature = "jack")]
606 pub use crate::host::jack::{
607 Device as JackDevice, Devices as JackDevices, Host as JackHost, Stream as JackStream,
608 SupportedInputConfigs as JackSupportedInputConfigs,
609 SupportedOutputConfigs as JackSupportedOutputConfigs,
610 };
611
612 impl_platform_host!(#[cfg(feature = "jack")] Jack jack "JACK", Alsa alsa "ALSA");
613
614 pub fn default_host() -> Host {
616 AlsaHost::new()
617 .expect("the default host should always be available")
618 .into()
619 }
620}
621
622#[cfg(any(target_os = "macos", target_os = "ios"))]
623mod platform_impl {
624 pub use crate::host::coreaudio::{
625 Device as CoreAudioDevice, Devices as CoreAudioDevices, Host as CoreAudioHost,
626 Stream as CoreAudioStream, SupportedInputConfigs as CoreAudioSupportedInputConfigs,
627 SupportedOutputConfigs as CoreAudioSupportedOutputConfigs,
628 };
629
630 impl_platform_host!(CoreAudio coreaudio "CoreAudio");
631
632 pub fn default_host() -> Host {
634 CoreAudioHost::new()
635 .expect("the default host should always be available")
636 .into()
637 }
638}
639
640#[cfg(target_os = "emscripten")]
641mod platform_impl {
642 pub use crate::host::emscripten::{
643 Device as EmscriptenDevice, Devices as EmscriptenDevices, Host as EmscriptenHost,
644 Stream as EmscriptenStream, SupportedInputConfigs as EmscriptenSupportedInputConfigs,
645 SupportedOutputConfigs as EmscriptenSupportedOutputConfigs,
646 };
647
648 impl_platform_host!(Emscripten emscripten "Emscripten");
649
650 pub fn default_host() -> Host {
652 EmscriptenHost::new()
653 .expect("the default host should always be available")
654 .into()
655 }
656}
657
658#[cfg(all(target_arch = "wasm32", feature = "wasm-bindgen"))]
659mod platform_impl {
660 pub use crate::host::webaudio::{
661 Device as WebAudioDevice, Devices as WebAudioDevices, Host as WebAudioHost,
662 Stream as WebAudioStream, SupportedInputConfigs as WebAudioSupportedInputConfigs,
663 SupportedOutputConfigs as WebAudioSupportedOutputConfigs,
664 };
665
666 impl_platform_host!(WebAudio webaudio "WebAudio");
667
668 pub fn default_host() -> Host {
670 WebAudioHost::new()
671 .expect("the default host should always be available")
672 .into()
673 }
674}
675
676#[cfg(windows)]
677mod platform_impl {
678 #[cfg(feature = "asio")]
679 pub use crate::host::asio::{
680 Device as AsioDevice, Devices as AsioDevices, Host as AsioHost, Stream as AsioStream,
681 SupportedInputConfigs as AsioSupportedInputConfigs,
682 SupportedOutputConfigs as AsioSupportedOutputConfigs,
683 };
684 pub use crate::host::wasapi::{
685 Device as WasapiDevice, Devices as WasapiDevices, Host as WasapiHost,
686 Stream as WasapiStream, SupportedInputConfigs as WasapiSupportedInputConfigs,
687 SupportedOutputConfigs as WasapiSupportedOutputConfigs,
688 };
689
690 impl_platform_host!(#[cfg(feature = "asio")] Asio asio "ASIO", Wasapi wasapi "WASAPI");
691
692 pub fn default_host() -> Host {
694 WasapiHost::new()
695 .expect("the default host should always be available")
696 .into()
697 }
698}
699
700#[cfg(target_os = "android")]
701mod platform_impl {
702 pub use crate::host::aaudio::{
703 Device as AAudioDevice, Devices as AAudioDevices, Host as AAudioHost,
704 Stream as AAudioStream, SupportedInputConfigs as AAudioSupportedInputConfigs,
705 SupportedOutputConfigs as AAudioSupportedOutputConfigs,
706 };
707
708 impl_platform_host!(AAudio aaudio "AAudio");
709
710 pub fn default_host() -> Host {
712 AAudioHost::new()
713 .expect("the default host should always be available")
714 .into()
715 }
716}
717
718#[cfg(not(any(
719 windows,
720 target_os = "linux",
721 target_os = "dragonfly",
722 target_os = "freebsd",
723 target_os = "netbsd",
724 target_os = "macos",
725 target_os = "ios",
726 target_os = "emscripten",
727 target_os = "android",
728 all(target_arch = "wasm32", feature = "wasm-bindgen"),
729)))]
730mod platform_impl {
731 pub use crate::host::null::{
732 Device as NullDevice, Devices as NullDevices, Host as NullHost,
733 SupportedInputConfigs as NullSupportedInputConfigs,
734 SupportedOutputConfigs as NullSupportedOutputConfigs,
735 };
736
737 impl_platform_host!(Null null "Null");
738
739 pub fn default_host() -> Host {
741 NullHost::new()
742 .expect("the default host should always be available")
743 .into()
744 }
745}
746
747struct NotSendSyncAcrossAllPlatforms(std::marker::PhantomData<*mut ()>);
756
757impl Default for NotSendSyncAcrossAllPlatforms {
758 fn default() -> Self {
759 NotSendSyncAcrossAllPlatforms(std::marker::PhantomData)
760 }
761}