Skip to main content

cpal/platform/
mod.rs

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)]
8pub use self::platform_impl::*;
9
10#[cfg(feature = "custom")]
11pub use crate::host::custom::{Device as CustomDevice, Host as CustomHost, Stream as CustomStream};
12
13/// A macro to assist with implementing a platform's dynamically dispatched [`Host`] type.
14///
15/// These dynamically dispatched types are necessary to allow for users to switch between hosts at
16/// runtime.
17///
18/// For example the invocation `impl_platform_host(Wasapi wasapi "WASAPI", Asio asio "ASIO")`,
19/// this macro should expand to:
20///
21// This sample code block is marked as text because it's not a valid test,
22// it's just illustrative. (see rust issue #96573)
23/// ```text
24/// pub enum HostId {
25///     Wasapi,
26///     Asio,
27/// }
28///
29/// pub enum Host {
30///     Wasapi(crate::host::wasapi::Host),
31///     Asio(crate::host::asio::Host),
32/// }
33/// ```
34///
35/// And so on for Device, Devices, Host, Stream, SupportedInputConfigs,
36/// SupportedOutputConfigs and all their necessary trait implementations.
37///
38macro_rules! impl_platform_host {
39    ($($(#[cfg($feat: meta)])? $HostVariant:ident => $Host:ty),* $(,)?) => {
40        /// All hosts supported by CPAL on this platform.
41        pub const ALL_HOSTS: &'static [HostId] = &[
42            $(
43                $(#[cfg($feat)])?
44                HostId::$HostVariant,
45            )*
46        ];
47
48        /// The platform's dynamically dispatched `Host` type.
49        ///
50        /// An instance of this `Host` type may represent one of the `Host`s available
51        /// on the platform.
52        ///
53        /// Use this type if you require switching between available hosts at runtime.
54        ///
55        /// This type may be constructed via the [`host_from_id`] function. [`HostId`]s may
56        /// be acquired via the [`ALL_HOSTS`] const, and the [`available_hosts`] function.
57        pub struct Host(HostInner);
58
59        /// The `Device` implementation associated with the platform's dynamically dispatched
60        /// [`Host`] type.
61        #[derive(Clone)]
62        pub struct Device(DeviceInner);
63
64        /// The `Devices` iterator associated with the platform's dynamically dispatched [`Host`]
65        /// type.
66        pub struct Devices(DevicesInner);
67
68        /// The `Stream` implementation associated with the platform's dynamically dispatched
69        /// [`Host`] type.
70        #[must_use = "If the stream is not stored it will not play."]
71        pub struct Stream(StreamInner);
72
73        /// The `SupportedInputConfigs` iterator associated with the platform's dynamically
74        /// dispatched [`Host`] type.
75        #[derive(Clone)]
76        pub struct SupportedInputConfigs(SupportedInputConfigsInner);
77
78        /// The `SupportedOutputConfigs` iterator associated with the platform's dynamically
79        /// dispatched [`Host`] type.
80        #[derive(Clone)]
81        pub struct SupportedOutputConfigs(SupportedOutputConfigsInner);
82
83        /// Unique identifier for available hosts on the platform.
84        ///
85        /// Only the hosts supported by the current platform are available as enum variants.
86        /// For cross-platform code that needs to handle hosts from other platforms,
87        /// use the string representation via [`std::fmt::Display`]/[`std::str::FromStr`].
88        ///
89        /// # Available Host Strings
90        ///
91        /// For cross-platform matching, these host strings are available:
92        ///
93        /// - `"aaudio"` - Android Audio
94        /// - `"alsa"` - Advanced Linux Sound Architecture
95        /// - `"asio"` - ASIO
96        /// - `"coreaudio"` - CoreAudio
97        /// - `"custom"` - Custom host (requires `custom` feature)
98        /// - `"emscripten"` - Emscripten
99        /// - `"jack"` - JACK Audio Connection Kit
100        /// - `"null"` - Null host
101        /// - `"wasapi"` - Windows Audio Session API
102        /// - `"webaudio"` - Web Audio API
103        /// - `"audioworklet"` - Audio Worklet
104        ///
105        /// # Cross-Platform Example
106        ///
107        /// ```
108        /// use cpal::HostId;
109        /// use std::str::FromStr;
110        ///
111        /// fn handle_host_string(host_string: &str) {
112        ///     // String matching works on all platforms
113        ///     match host_string {
114        ///         "alsa" => println!("ALSA host"),
115        ///         "coreaudio" => println!("CoreAudio host"),
116        ///         "jack" => println!("JACK host"),
117        ///         "wasapi" => println!("WASAPI host"),
118        ///         "asio" => println!("ASIO host"),
119        ///         "aaudio" => println!("AAudio host"),
120        ///         _ => println!("Other host"),
121        ///     }
122        ///
123        ///     // Parse host string (may fail if host is not available on this platform)
124        ///     if let Ok(host_id) = HostId::from_str(host_string) {
125        ///         println!("Successfully parsed: {}", host_id);
126        ///     }
127        /// }
128        /// ```
129        #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
130        pub enum HostId {
131            $(
132                $(#[cfg($feat)])?
133                $(#[cfg_attr(docsrs, doc(cfg($feat)))])?
134                $HostVariant,
135            )*
136        }
137
138        /// Contains a platform specific [`Device`] implementation.
139        #[derive(Clone)]
140        pub enum DeviceInner {
141            $(
142                $(#[cfg($feat)])?
143                $HostVariant(<$Host as crate::traits::HostTrait>::Device),
144            )*
145        }
146
147        /// Contains a platform specific [`Devices`] implementation.
148        pub enum DevicesInner {
149            $(
150                $(#[cfg($feat)])?
151                $HostVariant(<$Host as crate::traits::HostTrait>::Devices),
152            )*
153        }
154
155        /// Contains a platform specific [`Host`] implementation.
156        pub enum HostInner {
157            $(
158                $(#[cfg($feat)])?
159                $HostVariant($Host),
160            )*
161        }
162
163        /// Contains a platform specific [`Stream`] implementation.
164        pub enum StreamInner {
165            $(
166                $(#[cfg($feat)])?
167                $HostVariant(<<$Host as crate::traits::HostTrait>::Device as crate::traits::DeviceTrait>::Stream),
168            )*
169        }
170
171        #[derive(Clone)]
172        enum SupportedInputConfigsInner {
173            $(
174                $(#[cfg($feat)])?
175                $HostVariant(<<$Host as crate::traits::HostTrait>::Device as crate::traits::DeviceTrait>::SupportedInputConfigs),
176            )*
177        }
178
179        #[derive(Clone)]
180        enum SupportedOutputConfigsInner {
181            $(
182                $(#[cfg($feat)])?
183                $HostVariant(<<$Host as crate::traits::HostTrait>::Device as crate::traits::DeviceTrait>::SupportedOutputConfigs),
184            )*
185        }
186
187        impl HostId {
188            pub fn name(&self) -> &'static str {
189                match self {
190                    $(
191                        $(#[cfg($feat)])?
192                        HostId::$HostVariant => stringify!($HostVariant),
193                    )*
194                }
195            }
196        }
197
198        impl std::fmt::Display for HostId {
199            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200                write!(f, "{}", self.name().to_lowercase())
201            }
202        }
203
204        impl std::str::FromStr for HostId {
205            type Err = crate::HostUnavailable;
206
207            fn from_str(s: &str) -> Result<Self, Self::Err> {
208                $(
209                    $(#[cfg($feat)])?
210                    if stringify!($HostVariant).eq_ignore_ascii_case(s) {
211                        return Ok(HostId::$HostVariant);
212                    }
213                )*
214                Err(crate::HostUnavailable)
215            }
216        }
217
218        impl Devices {
219            /// Returns a reference to the underlying platform specific implementation of this
220            /// `Devices`.
221            pub fn as_inner(&self) -> &DevicesInner {
222                &self.0
223            }
224
225            /// Returns a mutable reference to the underlying platform specific implementation of
226            /// this `Devices`.
227            pub fn as_inner_mut(&mut self) -> &mut DevicesInner {
228                &mut self.0
229            }
230
231            /// Returns the underlying platform specific implementation of this `Devices`.
232            pub fn into_inner(self) -> DevicesInner {
233                self.0
234            }
235        }
236
237        impl Device {
238            /// Returns a reference to the underlying platform specific implementation of this
239            /// `Device`.
240            pub fn as_inner(&self) -> &DeviceInner {
241                &self.0
242            }
243
244            /// Returns a mutable reference to the underlying platform specific implementation of
245            /// this `Device`.
246            pub fn as_inner_mut(&mut self) -> &mut DeviceInner {
247                &mut self.0
248            }
249
250            /// Returns the underlying platform specific implementation of this `Device`.
251            pub fn into_inner(self) -> DeviceInner {
252                self.0
253            }
254        }
255
256        impl Host {
257            /// The unique identifier associated with this `Host`.
258            pub fn id(&self) -> HostId {
259                match self.0 {
260                    $(
261                        $(#[cfg($feat)])?
262                        HostInner::$HostVariant(_) => HostId::$HostVariant,
263                    )*
264                }
265            }
266
267            /// Returns a reference to the underlying platform specific implementation of this
268            /// `Host`.
269            pub fn as_inner(&self) -> &HostInner {
270                &self.0
271            }
272
273            /// Returns a mutable reference to the underlying platform specific implementation of
274            /// this `Host`.
275            pub fn as_inner_mut(&mut self) -> &mut HostInner {
276                &mut self.0
277            }
278
279            /// Returns the underlying platform specific implementation of this `Host`.
280            pub fn into_inner(self) -> HostInner {
281                self.0
282            }
283        }
284
285        impl Stream {
286            /// Returns a reference to the underlying platform specific implementation of this
287            /// `Stream`.
288            pub fn as_inner(&self) -> &StreamInner {
289                &self.0
290            }
291
292            /// Returns a mutable reference to the underlying platform specific implementation of
293            /// this `Stream`.
294            pub fn as_inner_mut(&mut self) -> &mut StreamInner {
295                &mut self.0
296            }
297
298            /// Returns the underlying platform specific implementation of this `Stream`.
299            pub fn into_inner(self) -> StreamInner {
300                self.0
301            }
302        }
303
304        impl Iterator for Devices {
305            type Item = Device;
306
307            fn next(&mut self) -> Option<Self::Item> {
308                match self.0 {
309                    $(
310                        $(#[cfg($feat)])?
311                        DevicesInner::$HostVariant(ref mut d) => {
312                            d.next().map(DeviceInner::$HostVariant).map(Device::from)
313                        }
314                    )*
315                }
316            }
317
318            fn size_hint(&self) -> (usize, Option<usize>) {
319                match self.0 {
320                    $(
321                        $(#[cfg($feat)])?
322                        DevicesInner::$HostVariant(ref d) => d.size_hint(),
323                    )*
324                }
325            }
326        }
327
328        impl Iterator for SupportedInputConfigs {
329            type Item = crate::SupportedStreamConfigRange;
330
331            fn next(&mut self) -> Option<Self::Item> {
332                match self.0 {
333                    $(
334                        $(#[cfg($feat)])?
335                        SupportedInputConfigsInner::$HostVariant(ref mut s) => s.next(),
336                    )*
337                }
338            }
339
340            fn size_hint(&self) -> (usize, Option<usize>) {
341                match self.0 {
342                    $(
343                        $(#[cfg($feat)])?
344                        SupportedInputConfigsInner::$HostVariant(ref d) => d.size_hint(),
345                    )*
346                }
347            }
348        }
349
350        impl Iterator for SupportedOutputConfigs {
351            type Item = crate::SupportedStreamConfigRange;
352
353            fn next(&mut self) -> Option<Self::Item> {
354                match self.0 {
355                    $(
356                        $(#[cfg($feat)])?
357                        SupportedOutputConfigsInner::$HostVariant(ref mut s) => s.next(),
358                    )*
359                }
360            }
361
362            fn size_hint(&self) -> (usize, Option<usize>) {
363                match self.0 {
364                    $(
365                        $(#[cfg($feat)])?
366                        SupportedOutputConfigsInner::$HostVariant(ref d) => d.size_hint(),
367                    )*
368                }
369            }
370        }
371
372        impl crate::traits::DeviceTrait for Device {
373            type SupportedInputConfigs = SupportedInputConfigs;
374            type SupportedOutputConfigs = SupportedOutputConfigs;
375            type Stream = Stream;
376
377            #[allow(deprecated)]
378            fn name(&self) -> Result<String, crate::DeviceNameError> {
379                match self.0 {
380                    $(
381                        $(#[cfg($feat)])?
382                        DeviceInner::$HostVariant(ref d) => d.name(),
383                    )*
384                }
385            }
386
387            fn description(&self) -> Result<crate::DeviceDescription, crate::DeviceNameError> {
388                match self.0 {
389                    $(
390                        $(#[cfg($feat)])?
391                        DeviceInner::$HostVariant(ref d) => d.description(),
392                    )*
393                }
394            }
395
396            fn id(&self) -> Result<crate::DeviceId, crate::DeviceIdError> {
397                match self.0 {
398                    $(
399                        $(#[cfg($feat)])?
400                        DeviceInner::$HostVariant(ref d) => d.id(),
401                    )*
402                }
403            }
404
405            fn supports_input(&self) -> bool {
406                match self.0 {
407                    $(
408                        $(#[cfg($feat)])?
409                        DeviceInner::$HostVariant(ref d) => d.supports_input(),
410                    )*
411                }
412            }
413
414            fn supports_output(&self) -> bool {
415                match self.0 {
416                    $(
417                        $(#[cfg($feat)])?
418                        DeviceInner::$HostVariant(ref d) => d.supports_output(),
419                    )*
420                }
421            }
422
423            fn supported_input_configs(&self) -> Result<Self::SupportedInputConfigs, crate::SupportedStreamConfigsError> {
424                match self.0 {
425                    $(
426                        $(#[cfg($feat)])?
427                        DeviceInner::$HostVariant(ref d) => {
428                            d.supported_input_configs()
429                                .map(SupportedInputConfigsInner::$HostVariant)
430                                .map(SupportedInputConfigs)
431                        }
432                    )*
433                }
434            }
435
436            fn supported_output_configs(&self) -> Result<Self::SupportedOutputConfigs, crate::SupportedStreamConfigsError> {
437                match self.0 {
438                    $(
439                        $(#[cfg($feat)])?
440                        DeviceInner::$HostVariant(ref d) => {
441                            d.supported_output_configs()
442                                .map(SupportedOutputConfigsInner::$HostVariant)
443                                .map(SupportedOutputConfigs)
444                        }
445                    )*
446                }
447            }
448
449            fn default_input_config(&self) -> Result<crate::SupportedStreamConfig, crate::DefaultStreamConfigError> {
450                match self.0 {
451                    $(
452                        $(#[cfg($feat)])?
453                        DeviceInner::$HostVariant(ref d) => d.default_input_config(),
454                    )*
455                }
456            }
457
458            fn default_output_config(&self) -> Result<crate::SupportedStreamConfig, crate::DefaultStreamConfigError> {
459                match self.0 {
460                    $(
461                        $(#[cfg($feat)])?
462                        DeviceInner::$HostVariant(ref d) => d.default_output_config(),
463                    )*
464                }
465            }
466
467            fn build_input_stream_raw<D, E>(
468                &self,
469                config: &crate::StreamConfig,
470                sample_format: crate::SampleFormat,
471                data_callback: D,
472                error_callback: E,
473                timeout: Option<std::time::Duration>,
474            ) -> Result<Self::Stream, crate::BuildStreamError>
475            where
476                D: FnMut(&crate::Data, &crate::InputCallbackInfo) + Send + 'static,
477                E: FnMut(crate::StreamError) + Send + 'static,
478            {
479                match self.0 {
480                    $(
481                        $(#[cfg($feat)])?
482                        DeviceInner::$HostVariant(ref d) => d
483                            .build_input_stream_raw(
484                                config,
485                                sample_format,
486                                data_callback,
487                                error_callback,
488                                timeout,
489                            )
490                            .map(StreamInner::$HostVariant)
491                            .map(Stream::from),
492                    )*
493                }
494            }
495
496            fn build_output_stream_raw<D, E>(
497                &self,
498                config: &crate::StreamConfig,
499                sample_format: crate::SampleFormat,
500                data_callback: D,
501                error_callback: E,
502                timeout: Option<std::time::Duration>,
503            ) -> Result<Self::Stream, crate::BuildStreamError>
504            where
505                D: FnMut(&mut crate::Data, &crate::OutputCallbackInfo) + Send + 'static,
506                E: FnMut(crate::StreamError) + Send + 'static,
507            {
508                match self.0 {
509                    $(
510                        $(#[cfg($feat)])?
511                        DeviceInner::$HostVariant(ref d) => d
512                            .build_output_stream_raw(
513                                config,
514                                sample_format,
515                                data_callback,
516                                error_callback,
517                                timeout,
518                            )
519                            .map(StreamInner::$HostVariant)
520                            .map(Stream::from),
521                    )*
522                }
523            }
524        }
525
526        impl crate::traits::HostTrait for Host {
527            type Devices = Devices;
528            type Device = Device;
529
530            fn is_available() -> bool {
531                $(
532                    $(#[cfg($feat)])?
533                    if <$Host>::is_available() { return true; }
534                )*
535                false
536            }
537
538            fn devices(&self) -> Result<Self::Devices, crate::DevicesError> {
539                match self.0 {
540                    $(
541                        $(#[cfg($feat)])?
542                        HostInner::$HostVariant(ref h) => {
543                            h.devices().map(DevicesInner::$HostVariant).map(Devices::from)
544                        }
545                    )*
546                }
547            }
548
549            fn default_input_device(&self) -> Option<Self::Device> {
550                match self.0 {
551                    $(
552                        $(#[cfg($feat)])?
553                        HostInner::$HostVariant(ref h) => {
554                            h.default_input_device().map(DeviceInner::$HostVariant).map(Device::from)
555                        }
556                    )*
557                }
558            }
559
560            fn default_output_device(&self) -> Option<Self::Device> {
561                match self.0 {
562                    $(
563                        $(#[cfg($feat)])?
564                        HostInner::$HostVariant(ref h) => {
565                            h.default_output_device().map(DeviceInner::$HostVariant).map(Device::from)
566                        }
567                    )*
568                }
569            }
570        }
571
572        impl crate::traits::StreamTrait for Stream {
573            fn play(&self) -> Result<(), crate::PlayStreamError> {
574                match self.0 {
575                    $(
576                        $(#[cfg($feat)])?
577                        StreamInner::$HostVariant(ref s) => {
578                            s.play()
579                        }
580                    )*
581                }
582            }
583
584            fn pause(&self) -> Result<(), crate::PauseStreamError> {
585                match self.0 {
586                    $(
587                        $(#[cfg($feat)])?
588                        StreamInner::$HostVariant(ref s) => {
589                            s.pause()
590                        }
591                    )*
592                }
593            }
594        }
595
596        impl From<DeviceInner> for Device {
597            fn from(d: DeviceInner) -> Self {
598                Device(d)
599            }
600        }
601
602        impl From<DevicesInner> for Devices {
603            fn from(d: DevicesInner) -> Self {
604                Devices(d)
605            }
606        }
607
608        impl From<HostInner> for Host {
609            fn from(h: HostInner) -> Self {
610                Host(h)
611            }
612        }
613
614        impl From<StreamInner> for Stream {
615            fn from(s: StreamInner) -> Self {
616                Stream(s)
617            }
618        }
619
620        $(
621            $(#[cfg($feat)])?
622            impl From<<$Host as crate::traits::HostTrait>::Device> for Device {
623                fn from(h: <$Host as crate::traits::HostTrait>::Device) -> Self {
624                    DeviceInner::$HostVariant(h).into()
625                }
626            }
627
628            $(#[cfg($feat)])?
629            impl From<<$Host as crate::traits::HostTrait>::Devices> for Devices {
630                fn from(h: <$Host as crate::traits::HostTrait>::Devices) -> Self {
631                    DevicesInner::$HostVariant(h).into()
632                }
633            }
634
635            $(#[cfg($feat)])?
636            impl From<$Host> for Host {
637                fn from(h: $Host) -> Self {
638                    HostInner::$HostVariant(h).into()
639                }
640            }
641
642            $(#[cfg($feat)])?
643            impl From<<<$Host as crate::traits::HostTrait>::Device as crate::traits::DeviceTrait>::Stream> for Stream {
644                fn from(h: <<$Host as crate::traits::HostTrait>::Device as crate::traits::DeviceTrait>::Stream) -> Self {
645                    StreamInner::$HostVariant(h).into()
646                }
647            }
648        )*
649
650        /// Produces a list of hosts that are currently available on the system.
651        pub fn available_hosts() -> Vec<HostId> {
652            let mut host_ids = vec![];
653            $(
654                $(#[cfg($feat)])?
655                if <$Host as crate::traits::HostTrait>::is_available() {
656                    host_ids.push(HostId::$HostVariant);
657                }
658            )*
659            host_ids
660        }
661
662        /// Given a unique host identifier, initialise and produce the host if it is available.
663        pub fn host_from_id(id: HostId) -> Result<Host, crate::HostUnavailable> {
664            match id {
665                $(
666                    $(#[cfg($feat)])?
667                    HostId::$HostVariant => {
668                        <$Host>::new()
669                            .map(HostInner::$HostVariant)
670                            .map(Host::from)
671                    }
672                )*
673            }
674        }
675
676        impl Default for Host {
677            fn default() -> Host {
678                default_host()
679            }
680        }
681    };
682}
683
684// TODO: Add pulseaudio here eventually.
685#[cfg(any(
686    target_os = "linux",
687    target_os = "dragonfly",
688    target_os = "freebsd",
689    target_os = "netbsd"
690))]
691mod platform_impl {
692    #[cfg_attr(
693        docsrs,
694        doc(cfg(any(
695            target_os = "linux",
696            target_os = "dragonfly",
697            target_os = "freebsd",
698            target_os = "netbsd"
699        )))
700    )]
701    pub use crate::host::alsa::Host as AlsaHost;
702    #[cfg(feature = "jack")]
703    #[cfg_attr(
704        docsrs,
705        doc(cfg(all(
706            any(
707                target_os = "linux",
708                target_os = "dragonfly",
709                target_os = "freebsd",
710                target_os = "netbsd"
711            ),
712            feature = "jack"
713        )))
714    )]
715    pub use crate::host::jack::Host as JackHost;
716
717    impl_platform_host!(
718        #[cfg(feature = "jack")] Jack => JackHost,
719        Alsa => AlsaHost,
720        #[cfg(feature = "custom")] Custom => super::CustomHost
721    );
722
723    /// The default host for the current compilation target platform.
724    pub fn default_host() -> Host {
725        AlsaHost::new()
726            .expect("the default host should always be available")
727            .into()
728    }
729}
730
731#[cfg(any(target_os = "macos", target_os = "ios"))]
732mod platform_impl {
733    #[cfg_attr(docsrs, doc(cfg(any(target_os = "macos", target_os = "ios"))))]
734    pub use crate::host::coreaudio::Host as CoreAudioHost;
735    #[cfg(all(feature = "jack", target_os = "macos"))]
736    #[cfg_attr(docsrs, doc(cfg(all(feature = "jack", target_os = "macos"))))]
737    pub use crate::host::jack::Host as JackHost;
738
739    impl_platform_host!(
740        CoreAudio => CoreAudioHost,
741        #[cfg(all(feature = "jack", target_os = "macos"))] Jack => JackHost,
742        #[cfg(feature = "custom")] Custom => super::CustomHost
743    );
744
745    /// The default host for the current compilation target platform.
746    pub fn default_host() -> Host {
747        CoreAudioHost::new()
748            .expect("the default host should always be available")
749            .into()
750    }
751}
752
753#[cfg(target_os = "emscripten")]
754mod platform_impl {
755    #[cfg_attr(docsrs, doc(cfg(target_os = "emscripten")))]
756    pub use crate::host::emscripten::Host as EmscriptenHost;
757    impl_platform_host!(
758        Emscripten => EmscriptenHost,
759        #[cfg(feature = "custom")] Custom => super::CustomHost
760    );
761
762    /// The default host for the current compilation target platform.
763    pub fn default_host() -> Host {
764        EmscriptenHost::new()
765            .expect("the default host should always be available")
766            .into()
767    }
768}
769
770#[cfg(all(target_arch = "wasm32", feature = "wasm-bindgen"))]
771mod platform_impl {
772    #[cfg_attr(
773        docsrs,
774        doc(cfg(all(target_arch = "wasm32", feature = "wasm-bindgen")))
775    )]
776    pub use crate::host::webaudio::Host as WebAudioHost;
777
778    #[cfg(feature = "audioworklet")]
779    #[cfg_attr(
780        docsrs,
781        doc(cfg(all(
782            target_arch = "wasm32",
783            feature = "wasm-bindgen",
784            feature = "audioworklet"
785        )))
786    )]
787    pub use crate::host::audioworklet::Host as AudioWorkletHost;
788
789    impl_platform_host!(
790        WebAudio => WebAudioHost,
791        #[cfg(feature = "audioworklet")] AudioWorklet => AudioWorkletHost,
792        #[cfg(feature = "custom")] Custom => super::CustomHost
793    );
794
795    /// The default host for the current compilation target platform.
796    pub fn default_host() -> Host {
797        WebAudioHost::new()
798            .expect("the default host should always be available")
799            .into()
800    }
801}
802
803#[cfg(windows)]
804mod platform_impl {
805    #[cfg(feature = "asio")]
806    #[cfg_attr(docsrs, doc(cfg(all(windows, feature = "asio"))))]
807    pub use crate::host::asio::Host as AsioHost;
808    #[cfg(feature = "jack")]
809    #[cfg_attr(docsrs, doc(cfg(all(windows, feature = "jack"))))]
810    pub use crate::host::jack::Host as JackHost;
811    #[cfg_attr(docsrs, doc(cfg(windows)))]
812    pub use crate::host::wasapi::Host as WasapiHost;
813
814    impl_platform_host!(
815        #[cfg(feature = "asio")] Asio => AsioHost,
816        Wasapi => WasapiHost,
817        #[cfg(feature = "jack")] Jack => JackHost,
818        #[cfg(feature = "custom")] Custom => super::CustomHost,
819    );
820
821    /// The default host for the current compilation target platform.
822    pub fn default_host() -> Host {
823        WasapiHost::new()
824            .expect("the default host should always be available")
825            .into()
826    }
827}
828
829#[cfg(target_os = "android")]
830mod platform_impl {
831    #[cfg_attr(docsrs, doc(cfg(target_os = "android")))]
832    pub use crate::host::aaudio::Host as AAudioHost;
833    impl_platform_host!(
834        AAudio => AAudioHost,
835        #[cfg(feature = "custom")] Custom => super::CustomHost
836    );
837
838    /// The default host for the current compilation target platform.
839    pub fn default_host() -> Host {
840        AAudioHost::new()
841            .expect("the default host should always be available")
842            .into()
843    }
844}
845
846#[cfg(not(any(
847    windows,
848    target_os = "linux",
849    target_os = "dragonfly",
850    target_os = "freebsd",
851    target_os = "netbsd",
852    target_os = "macos",
853    target_os = "ios",
854    target_os = "emscripten",
855    target_os = "android",
856    all(target_arch = "wasm32", feature = "wasm-bindgen"),
857)))]
858mod platform_impl {
859    #[cfg_attr(
860        docsrs,
861        doc(cfg(not(any(
862            windows,
863            target_os = "linux",
864            target_os = "dragonfly",
865            target_os = "freebsd",
866            target_os = "netbsd",
867            target_os = "macos",
868            target_os = "ios",
869            target_os = "emscripten",
870            target_os = "android",
871            all(target_arch = "wasm32", feature = "wasm-bindgen")
872        ))))
873    )]
874    pub use crate::host::null::Host as NullHost;
875
876    impl_platform_host!(
877        Null => NullHost,
878        #[cfg(feature = "custom")] Custom => super::CustomHost,
879    );
880
881    /// The default host for the current compilation target platform.
882    pub fn default_host() -> Host {
883        NullHost::new()
884            .expect("the default host should always be available")
885            .into()
886    }
887}