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."]
73 pub struct Stream(StreamInner, crate::platform::NotSendSyncAcrossAllPlatforms);
74
75 pub struct SupportedInputConfigs(SupportedInputConfigsInner);
78
79 pub struct SupportedOutputConfigs(SupportedOutputConfigsInner);
82
83 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
85 pub enum HostId {
86 $(
87 $(#[cfg($feat)])?
88 $HostVariant,
89 )*
90 }
91
92 #[derive(Clone)]
94 pub enum DeviceInner {
95 $(
96 $(#[cfg($feat)])?
97 $HostVariant(crate::host::$host_mod::Device),
98 )*
99 }
100
101 pub enum DevicesInner {
103 $(
104 $(#[cfg($feat)])?
105 $HostVariant(crate::host::$host_mod::Devices),
106 )*
107 }
108
109 pub enum HostInner {
111 $(
112 $(#[cfg($feat)])?
113 $HostVariant(crate::host::$host_mod::Host),
114 )*
115 }
116
117 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 pub fn as_inner(&self) -> &DevicesInner {
154 &self.0
155 }
156
157 pub fn as_inner_mut(&mut self) -> &mut DevicesInner {
160 &mut self.0
161 }
162
163 pub fn into_inner(self) -> DevicesInner {
165 self.0
166 }
167 }
168
169 impl Device {
170 pub fn as_inner(&self) -> &DeviceInner {
173 &self.0
174 }
175
176 pub fn as_inner_mut(&mut self) -> &mut DeviceInner {
179 &mut self.0
180 }
181
182 pub fn into_inner(self) -> DeviceInner {
184 self.0
185 }
186 }
187
188 impl Host {
189 pub fn id(&self) -> HostId {
191 match self.0 {
192 $(
193 $(#[cfg($feat)])?
194 HostInner::$HostVariant(_) => HostId::$HostVariant,
195 )*
196 }
197 }
198
199 pub fn as_inner(&self) -> &HostInner {
202 &self.0
203 }
204
205 pub fn as_inner_mut(&mut self) -> &mut HostInner {
208 &mut self.0
209 }
210
211 pub fn into_inner(self) -> HostInner {
213 self.0
214 }
215 }
216
217 impl Stream {
218 pub fn as_inner(&self) -> &StreamInner {
221 &self.0
222 }
223
224 pub fn as_inner_mut(&mut self) -> &mut StreamInner {
227 &mut self.0
228 }
229
230 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 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 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#[cfg(any(
575 target_os = "linux",
576 target_os = "dragonfly",
577 target_os = "freebsd",
578 target_os = "netbsd"
579))]
580mod 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 pub fn default_host() -> Host {
597 AlsaHost::new()
598 .expect("the default host should always be available")
599 .into()
600 }
601}
602
603#[cfg(any(target_os = "macos", target_os = "ios"))]
604mod 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 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")]
622mod 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 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"))]
640mod 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 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)]
658mod 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 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")]
682mod 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 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)))]
711mod 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 pub fn default_host() -> Host {
722 NullHost::new()
723 .expect("the default host should always be available")
724 .into()
725 }
726}
727
728struct NotSendSyncAcrossAllPlatforms(std::marker::PhantomData<*mut ()>);
737
738impl Default for NotSendSyncAcrossAllPlatforms {
739 fn default() -> Self {
740 NotSendSyncAcrossAllPlatforms(std::marker::PhantomData)
741 }
742}