Skip to content

Commit 173b414

Browse files
authored
Added binding for Mix_OpenAudioDevice (#1464)
1 parent e2d5a14 commit 173b414

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ when upgrading from a version of rust-sdl2 to another.
33

44
### Next
55

6+
[PR #1464](https://github.com/Rust-SDL2/rust-sdl2/pull/1464) Added binding for `Mix_OpenAudioDevice`
7+
68
[PR #1451](https://github.com/Rust-SDL2/rust-sdl2/pull/1451) Add `gamma_ramp_arrays` and `calculate_gamma_ramp`.
79

810
[PR #1459](https://github.com/Rust-SDL2/rust-sdl2/pull/1459) Fix image and mixer init flag logic

src/sdl2/mixer/mod.rs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ use libc::{c_double, c_int, c_uint};
2727
use rwops::RWops;
2828
use std::borrow::ToOwned;
2929
use std::convert::TryInto;
30-
use std::default;
3130
use std::ffi::{CStr, CString};
3231
use std::fmt;
3332
use std::marker::PhantomData;
3433
use std::path::Path;
3534
use std::str::from_utf8;
35+
use std::{default, ptr};
3636
use sys;
3737
use sys::mixer;
3838
use version::Version;
@@ -106,6 +106,16 @@ bitflags!(
106106
}
107107
);
108108

109+
bitflags!(
110+
/// Which audio format changes are allowed when opening a device ([`open_audio_device`]).
111+
pub struct AllowChangeFlag: u32 {
112+
const FREQUENCY = sys::SDL_AUDIO_ALLOW_FREQUENCY_CHANGE;
113+
const FORMAT = sys::SDL_AUDIO_ALLOW_FORMAT_CHANGE;
114+
const CHANNELS = sys::SDL_AUDIO_ALLOW_CHANNELS_CHANGE;
115+
const SAMPLES = sys::SDL_AUDIO_ALLOW_SAMPLES_CHANGE;
116+
}
117+
);
118+
109119
impl fmt::Display for InitFlag {
110120
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111121
<Self as fmt::Debug>::fmt(self, f)
@@ -147,7 +157,8 @@ pub fn init(flags: InitFlag) -> Result<Sdl2MixerContext, String> {
147157
}
148158
}
149159

150-
/// Open the mixer with a certain audio format.
160+
/// Opens the default audio device for playback. If you need to select a specific audio device
161+
/// or require more fine-grained control over the device configuration, use [`open_audio_device`].
151162
///
152163
/// * `chunksize`: It is recommended to choose values between 256 and 1024, depending on whether
153164
/// you prefer latency or compatibility. Small values reduce latency but may not
@@ -175,6 +186,60 @@ pub fn open_audio(
175186
}
176187
}
177188

189+
/// Open a specific audio device for playback.
190+
///
191+
/// (A slightly simpler version of this function is available in [`open_audio`], which still might
192+
/// meet most applications' needs.)
193+
///
194+
/// The `allowed_changes` parameter specifies what settings are flexible. These tell `SDL_mixer`
195+
/// that the app doesn't mind if a specific setting changes. For example, the app might need stereo
196+
/// data in [`i16`] format, but if the sample rate or chunk size changes, the app can handle that.
197+
/// In that case, the app would specify `AllowChangeFlag::FORMAT | AllowChangeFlag::SAMPLES`. In
198+
/// this case, if the system's hardware requires something other than the requested format,
199+
/// `SDL_mixer` can select what the hardware demands instead of the app. For a given
200+
/// [`AllowChangeFlag`], If it is not specified, `SDL_mixer` must convert data behind the scenes
201+
/// between what the app demands and what the hardware requires. If your app needs precisely what
202+
/// is requested, specify [`AllowChangeFlag::empty`].
203+
///
204+
/// * `frequency`: The frequency to playback audio at (in Hz).
205+
/// * `format`: Audio format ([`AudioFormat`]).
206+
/// * `channels`: Number of channels (1 is mono, 2 is stereo, etc).
207+
/// * `chunksize`: Audio buffer size in sample FRAMES (total samples divided by channel count).
208+
/// The lower the number, the lower the latency, but you risk dropouts if it gets
209+
/// too low.
210+
/// * `device`: The device name to open, or [`None`] to choose a reasonable default.
211+
/// * `allowed_changes`: Allow change flags ([`AllowChangeFlag`]).
212+
///
213+
pub fn open_audio_device<'a, D>(
214+
frequency: i32,
215+
format: AudioFormat,
216+
channels: i32,
217+
chunksize: i32,
218+
device: D,
219+
allowed_changes: AllowChangeFlag,
220+
) -> Result<(), String>
221+
where
222+
D: Into<Option<&'a str>>,
223+
{
224+
let ret = unsafe {
225+
let device = device.into().map(|device| CString::new(device).unwrap());
226+
let device_ptr = device.as_ref().map_or(ptr::null(), |s| s.as_ptr());
227+
mixer::Mix_OpenAudioDevice(
228+
frequency as c_int,
229+
format,
230+
channels as c_int,
231+
chunksize as c_int,
232+
device_ptr,
233+
allowed_changes.bits() as c_int,
234+
)
235+
};
236+
if ret == 0 {
237+
Ok(())
238+
} else {
239+
Err(get_error())
240+
}
241+
}
242+
178243
/// Shutdown and cleanup the mixer API.
179244
pub fn close_audio() {
180245
unsafe { mixer::Mix_CloseAudio() }

0 commit comments

Comments
 (0)