fmod/core/system/device_selection.rs
1// Copyright (c) 2024 Lily Lyons
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use fmod_sys::*;
8use lanyard::Utf8CString;
9use std::{ffi::c_int, mem::MaybeUninit};
10
11use crate::{get_string, Guid, OutputType, SpeakerMode, System};
12
13impl System {
14 #[allow(clippy::doc_markdown)]
15 /// Sets the type of output interface used to run the mixer.
16 ///
17 /// This function is typically used to select between different OS specific audio APIs which may have different features.
18 ///
19 /// It is only necessary to call this function if you want to specifically switch away from the default output mode for the operating system.
20 /// The most optimal mode is selected by default for the operating system.
21 ///
22 /// (Windows, UWP, GameCore, Android, MacOS, iOS, Linux Only) This function can be called from outside the builder.
23 ///
24 /// When using the Studio API, switching to an NRT (non-realtime) output type after FMOD is already initialized
25 /// will not behave correctly unless the Studio API was initialized with [`crate::studio::InitFlags::SYNCHRONOUS_UPDATE`].
26 pub fn set_output(&self, output_type: OutputType) -> Result<()> {
27 unsafe { FMOD_System_SetOutput(self.inner, output_type.into()).to_result() }
28 }
29
30 /// Retrieves the type of output interface used to run the mixer.
31 pub fn get_output_type(&self) -> Result<OutputType> {
32 let mut output_type = 0;
33 unsafe {
34 FMOD_System_GetOutput(self.inner, &mut output_type).to_result()?;
35 }
36 let output_type = output_type.try_into()?;
37 Ok(output_type)
38 }
39
40 /// Retrieves the number of output drivers available for the selected output type.
41 ///
42 /// If [`SystemBuilder::output`]/[`System::set_output`] has not been called,
43 /// this function will return the number of drivers available for the default output type.
44 /// A possible use for this function is to iterate through available sound devices for the current output type,
45 /// and use [`System::get_driver_info`] to get the device's name and other attributes.
46 pub fn get_driver_count(&self) -> Result<c_int> {
47 let mut count = 0;
48 unsafe {
49 FMOD_System_GetNumDrivers(self.inner, &mut count).to_result()?;
50 }
51 Ok(count)
52 }
53
54 /// Retrieves identification information about a sound device specified by its index, and specific to the selected output mode.
55 pub fn get_driver_info(
56 &self,
57 id: c_int,
58 ) -> Result<(Utf8CString, Guid, c_int, SpeakerMode, c_int)> {
59 unsafe {
60 let mut guid = MaybeUninit::zeroed();
61 let mut system_rate = 0;
62 let mut speaker_mode = 0;
63 let mut speaker_mode_channels = 0;
64
65 let name = get_string(|name| {
66 FMOD_System_GetDriverInfo(
67 self.inner,
68 id,
69 name.as_mut_ptr().cast(),
70 name.len() as c_int,
71 guid.as_mut_ptr(),
72 &mut system_rate,
73 &mut speaker_mode,
74 &mut speaker_mode_channels,
75 )
76 })?;
77
78 let guid = guid.assume_init().into();
79 let speaker_mode = speaker_mode.try_into()?;
80
81 Ok((name, guid, system_rate, speaker_mode, speaker_mode_channels))
82 }
83 }
84
85 /// Sets the output driver for the selected output type.
86 ///
87 /// When an output type has more than one driver available, this function can be used to select between them.
88 ///
89 /// When this function is called, the current driver will be shutdown and the newly selected driver will be initialized / started.
90 pub fn set_driver(&self, driver: c_int) -> Result<()> {
91 unsafe { FMOD_System_SetDriver(self.inner, driver).to_result() }
92 }
93
94 /// Retrieves the output driver for the selected output type.
95 pub fn get_driver(&self) -> Result<c_int> {
96 let mut driver = 0;
97 unsafe {
98 FMOD_System_GetDriver(self.inner, &mut driver).to_result()?;
99 }
100 Ok(driver)
101 }
102}