From 4fd50da3dd440afc723d29c4ec3763260a2a75a5 Mon Sep 17 00:00:00 2001 From: kaphula Date: Mon, 9 Jun 2025 20:24:10 +0300 Subject: [PATCH 1/9] Add from_bytes functions to sdl2_mixer's Chunk and Music. --- examples/mixer-demo.rs | 26 +++++++++++++++++---- src/sdl2/mixer/mod.rs | 52 +++++++++++++++++++++++++----------------- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/examples/mixer-demo.rs b/examples/mixer-demo.rs index 52c3fc63e9..956407bde5 100644 --- a/examples/mixer-demo.rs +++ b/examples/mixer-demo.rs @@ -1,9 +1,10 @@ /// Demonstrates the simultaneous mixing of music and sound effects. extern crate sdl2; -use sdl2::mixer::{InitFlag, AUDIO_S16LSB, DEFAULT_CHANNELS}; +use sdl2::mixer::{InitFlag, LoaderRWops, AUDIO_S16LSB, DEFAULT_CHANNELS}; use std::env; use std::path::Path; +use sdl2::rwops::RWops; fn main() -> Result<(), String> { let args: Vec<_> = env::args().collect(); @@ -37,6 +38,7 @@ fn demo(music_file: &Path, sound_file: Option<&Path>) -> Result<(), String> { // simultaneously. sdl2::mixer::allocate_channels(4); + { let n = sdl2::mixer::get_chunk_decoders_number(); println!("available chunk(sample) decoders: {}", n); @@ -109,9 +111,25 @@ fn demo(music_file: &Path, sound_file: Option<&Path>) -> Result<(), String> { music.fade_in_from_pos(1, 10_000, 100.0) ); - timer.delay(5_000); - sdl2::mixer::Music::halt(); - timer.delay(1_000); + timer.delay(5_000); + sdl2::mixer::Music::halt(); + + + println!("playing sound from memory..."); + let sound_as_bytes = include_bytes!("../assets/sine.wav"); + let chunk = sdl2::mixer::Chunk::from_bytes(sound_as_bytes)?; + sdl2::mixer::Channel::all().play(&chunk, 0)?; + timer.delay(1_000); + + println!("playing music from memory..."); + let mus = include_bytes!("../assets/sine.wav"); + let mus = sdl2::mixer::Music::from_bytes(mus)?; + mus.play(-1); + timer.delay(1_000); + + sdl2::mixer::Music::halt(); + + timer.delay(1_000); println!("quitting sdl"); diff --git a/src/sdl2/mixer/mod.rs b/src/sdl2/mixer/mod.rs index be39d3397d..340ddb9db5 100644 --- a/src/sdl2/mixer/mod.rs +++ b/src/sdl2/mixer/mod.rs @@ -299,6 +299,18 @@ impl Drop for Chunk { } impl Chunk { + + /// Load a sample from memory directly. + /// + /// This works the same way as [Chunk::from_file] except with bytes instead of a file path. + /// If you have read your sound files (.wav, .ogg, etc...) from + /// disk to memory as bytes you can use this function + /// to create [Chunk]s from their bytes. + pub fn from_bytes(path: &[u8]) -> Result { + let b = RWops::from_bytes(path)?; + b.load_wav() + } + /// Load file for use as a sample. pub fn from_file>(path: P) -> Result { let raw = unsafe { mixer::Mix_LoadWAV_RW(RWops::from_file(path, "rb")?.raw(), 0) }; @@ -835,27 +847,25 @@ impl<'a> Music<'a> { } } - /// Load music from a static byte buffer. - #[doc(alias = "SDL_RWFromConstMem")] - pub fn from_static_bytes(buf: &'static [u8]) -> Result, String> { - let rw = - unsafe { sys::SDL_RWFromConstMem(buf.as_ptr() as *const c_void, buf.len() as c_int) }; - - if rw.is_null() { - return Err(get_error()); - } - - let raw = unsafe { mixer::Mix_LoadMUS_RW(rw, 0) }; - if raw.is_null() { - Err(get_error()) - } else { - Ok(Music { - raw, - owned: true, - _marker: PhantomData, - }) - } - } + /// Load music from a byte buffer. + #[doc(alias = "SDL_RWFromConstMem")] + pub fn from_bytes(buf: &[u8]) -> Result, String> { + let rw = + unsafe { sys::SDL_RWFromConstMem(buf.as_ptr() as *const c_void, buf.len() as c_int) }; + if rw.is_null() { + return Err(get_error()); + } + let raw = unsafe { mixer::Mix_LoadMUS_RW(rw, 0) }; + if raw.is_null() { + Err(get_error()) + } else { + Ok(Music { + raw, + owned: true, + _marker: PhantomData, + }) + } + } /// The file format encoding of the music. pub fn get_type(&self) -> MusicType { From ee939f69c6b3e12f9edf0e8c203ce6ab08c444f7 Mon Sep 17 00:00:00 2001 From: kaphula Date: Mon, 9 Jun 2025 20:24:36 +0300 Subject: [PATCH 2/9] Run fmt. --- examples/mixer-demo.rs | 32 +++++++++++------------ src/sdl2/mixer/mod.rs | 59 +++++++++++++++++++++--------------------- 2 files changed, 44 insertions(+), 47 deletions(-) diff --git a/examples/mixer-demo.rs b/examples/mixer-demo.rs index 956407bde5..b60e45ebbc 100644 --- a/examples/mixer-demo.rs +++ b/examples/mixer-demo.rs @@ -2,9 +2,9 @@ extern crate sdl2; use sdl2::mixer::{InitFlag, LoaderRWops, AUDIO_S16LSB, DEFAULT_CHANNELS}; +use sdl2::rwops::RWops; use std::env; use std::path::Path; -use sdl2::rwops::RWops; fn main() -> Result<(), String> { let args: Vec<_> = env::args().collect(); @@ -38,7 +38,6 @@ fn demo(music_file: &Path, sound_file: Option<&Path>) -> Result<(), String> { // simultaneously. sdl2::mixer::allocate_channels(4); - { let n = sdl2::mixer::get_chunk_decoders_number(); println!("available chunk(sample) decoders: {}", n); @@ -111,25 +110,24 @@ fn demo(music_file: &Path, sound_file: Option<&Path>) -> Result<(), String> { music.fade_in_from_pos(1, 10_000, 100.0) ); - timer.delay(5_000); - sdl2::mixer::Music::halt(); - + timer.delay(5_000); + sdl2::mixer::Music::halt(); - println!("playing sound from memory..."); - let sound_as_bytes = include_bytes!("../assets/sine.wav"); - let chunk = sdl2::mixer::Chunk::from_bytes(sound_as_bytes)?; - sdl2::mixer::Channel::all().play(&chunk, 0)?; - timer.delay(1_000); + println!("playing sound from memory..."); + let sound_as_bytes = include_bytes!("../assets/sine.wav"); + let chunk = sdl2::mixer::Chunk::from_bytes(sound_as_bytes)?; + sdl2::mixer::Channel::all().play(&chunk, 0)?; + timer.delay(1_000); - println!("playing music from memory..."); - let mus = include_bytes!("../assets/sine.wav"); - let mus = sdl2::mixer::Music::from_bytes(mus)?; - mus.play(-1); - timer.delay(1_000); + println!("playing music from memory..."); + let mus = include_bytes!("../assets/sine.wav"); + let mus = sdl2::mixer::Music::from_bytes(mus)?; + mus.play(-1); + timer.delay(1_000); - sdl2::mixer::Music::halt(); + sdl2::mixer::Music::halt(); - timer.delay(1_000); + timer.delay(1_000); println!("quitting sdl"); diff --git a/src/sdl2/mixer/mod.rs b/src/sdl2/mixer/mod.rs index 340ddb9db5..8b05844f39 100644 --- a/src/sdl2/mixer/mod.rs +++ b/src/sdl2/mixer/mod.rs @@ -299,17 +299,16 @@ impl Drop for Chunk { } impl Chunk { - - /// Load a sample from memory directly. - /// - /// This works the same way as [Chunk::from_file] except with bytes instead of a file path. - /// If you have read your sound files (.wav, .ogg, etc...) from - /// disk to memory as bytes you can use this function - /// to create [Chunk]s from their bytes. - pub fn from_bytes(path: &[u8]) -> Result { - let b = RWops::from_bytes(path)?; - b.load_wav() - } + /// Load a sample from memory directly. + /// + /// This works the same way as [Chunk::from_file] except with bytes instead of a file path. + /// If you have read your sound files (.wav, .ogg, etc...) from + /// disk to memory as bytes you can use this function + /// to create [Chunk]s from their bytes. + pub fn from_bytes(path: &[u8]) -> Result { + let b = RWops::from_bytes(path)?; + b.load_wav() + } /// Load file for use as a sample. pub fn from_file>(path: P) -> Result { @@ -847,25 +846,25 @@ impl<'a> Music<'a> { } } - /// Load music from a byte buffer. - #[doc(alias = "SDL_RWFromConstMem")] - pub fn from_bytes(buf: &[u8]) -> Result, String> { - let rw = - unsafe { sys::SDL_RWFromConstMem(buf.as_ptr() as *const c_void, buf.len() as c_int) }; - if rw.is_null() { - return Err(get_error()); - } - let raw = unsafe { mixer::Mix_LoadMUS_RW(rw, 0) }; - if raw.is_null() { - Err(get_error()) - } else { - Ok(Music { - raw, - owned: true, - _marker: PhantomData, - }) - } - } + /// Load music from a byte buffer. + #[doc(alias = "SDL_RWFromConstMem")] + pub fn from_bytes(buf: &[u8]) -> Result, String> { + let rw = + unsafe { sys::SDL_RWFromConstMem(buf.as_ptr() as *const c_void, buf.len() as c_int) }; + if rw.is_null() { + return Err(get_error()); + } + let raw = unsafe { mixer::Mix_LoadMUS_RW(rw, 0) }; + if raw.is_null() { + Err(get_error()) + } else { + Ok(Music { + raw, + owned: true, + _marker: PhantomData, + }) + } + } /// The file format encoding of the music. pub fn get_type(&self) -> MusicType { From aae6c6eccaaef198a08f25eca34ff6cb413a9ae6 Mon Sep 17 00:00:00 2001 From: kaphula Date: Mon, 9 Jun 2025 20:35:45 +0300 Subject: [PATCH 3/9] Bump version. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5053f7cbec..3cbd5baf48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "sdl2" description = "SDL2 bindings for Rust" repository = "https://github.com/Rust-SDL2/rust-sdl2" documentation = "https://docs.rs/sdl2" -version = "0.37.0" +version = "0.38.0" license = "MIT" authors = [ "Tony Aldridge ", "Cobrand "] keywords = ["SDL", "windowing", "graphics", "api", "engine"] From bd4895816d918b026116f00f84567db9cc860ef3 Mon Sep 17 00:00:00 2001 From: kaphula Date: Mon, 9 Jun 2025 20:37:33 +0300 Subject: [PATCH 4/9] Remove useless imports. --- examples/mixer-demo.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/mixer-demo.rs b/examples/mixer-demo.rs index b60e45ebbc..c23acf86f7 100644 --- a/examples/mixer-demo.rs +++ b/examples/mixer-demo.rs @@ -1,8 +1,7 @@ /// Demonstrates the simultaneous mixing of music and sound effects. extern crate sdl2; -use sdl2::mixer::{InitFlag, LoaderRWops, AUDIO_S16LSB, DEFAULT_CHANNELS}; -use sdl2::rwops::RWops; +use sdl2::mixer::{InitFlag, AUDIO_S16LSB, DEFAULT_CHANNELS}; use std::env; use std::path::Path; From 40c6b4af22edfaed6057b244726a509490dc05f5 Mon Sep 17 00:00:00 2001 From: kaphula Date: Mon, 9 Jun 2025 21:20:59 +0300 Subject: [PATCH 5/9] Bump sdl2-sys version to matching. --- Cargo.toml | 2 +- sdl2-sys/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3cbd5baf48..dde7f2583e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ lazy_static = "1.4.0" [dependencies.sdl2-sys] path = "sdl2-sys" -version = "^0.37.0" +version = "^0.38.0" [dependencies.c_vec] # allow both 1.* and 2.0 versions diff --git a/sdl2-sys/Cargo.toml b/sdl2-sys/Cargo.toml index 4f761fef34..b8e988d3d5 100644 --- a/sdl2-sys/Cargo.toml +++ b/sdl2-sys/Cargo.toml @@ -3,7 +3,7 @@ name = "sdl2-sys" description = "Raw SDL2 bindings for Rust, used internally rust-sdl2" repository = "https://github.com/rust-sdl2/rust-sdl2" -version = "0.37.0" +version = "0.38.0" authors = ["Tony Aldridge ", "Cobrand "] keywords = ["SDL", "windowing", "graphics", "ffi"] categories = ["rendering","external-ffi-bindings","game-engines","multimedia"] From 9439ef7488cb6ff219dfbe4a388ad7853a4d11d0 Mon Sep 17 00:00:00 2001 From: kaphula Date: Tue, 10 Jun 2025 13:24:16 +0300 Subject: [PATCH 6/9] Revamp music functions for various scenarios. --- examples/mixer-demo.rs | 15 ++++++++--- src/sdl2/mixer/mod.rs | 59 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/examples/mixer-demo.rs b/examples/mixer-demo.rs index c23acf86f7..88bd340aa2 100644 --- a/examples/mixer-demo.rs +++ b/examples/mixer-demo.rs @@ -118,9 +118,18 @@ fn demo(music_file: &Path, sound_file: Option<&Path>) -> Result<(), String> { sdl2::mixer::Channel::all().play(&chunk, 0)?; timer.delay(1_000); - println!("playing music from memory..."); - let mus = include_bytes!("../assets/sine.wav"); - let mus = sdl2::mixer::Music::from_bytes(mus)?; + println!("playing music from borrowed memory..."); + let music_as_bytes = include_bytes!("../assets/sine.wav"); + + let mus = sdl2::mixer::Music::from_bytes(music_as_bytes)?; + mus.play(-1); + timer.delay(1_000); + sdl2::mixer::Music::halt(); + timer.delay(0_500); + + println!("playing music from owned memory..."); + + let mus = sdl2::mixer::Music::from_owned_bytes(music_as_bytes.clone().into())?; mus.play(-1); timer.delay(1_000); diff --git a/src/sdl2/mixer/mod.rs b/src/sdl2/mixer/mod.rs index 8b05844f39..fdf8bd1368 100644 --- a/src/sdl2/mixer/mod.rs +++ b/src/sdl2/mixer/mod.rs @@ -374,6 +374,7 @@ impl<'a> LoaderRWops<'a> for RWops<'a> { Ok(Music { raw, owned: true, + owned_data: None, _marker: PhantomData, }) } @@ -810,6 +811,7 @@ extern "C" fn c_music_finished_hook() { pub struct Music<'a> { pub raw: *mut mixer::Mix_Music, pub owned: bool, + pub owned_data: Option>, _marker: PhantomData<&'a ()>, } @@ -830,6 +832,8 @@ impl<'a> fmt::Debug for Music<'a> { impl<'a> Music<'a> { /// Load music file to use. + /// + /// The music is streamed directly from the file when played. pub fn from_file>(path: P) -> Result, String> { let raw = unsafe { let c_path = CString::new(path.as_ref().to_str().unwrap()).unwrap(); @@ -841,14 +845,66 @@ impl<'a> Music<'a> { Ok(Music { raw, owned: true, + owned_data: None, _marker: PhantomData, }) } } /// Load music from a byte buffer. + /// + /// The bytes' lifetime is tied to the returned [Music] instance, + /// so consider using [Music::from_owned_bytes] if that is an issue. + #[doc(alias = "SDL_RWFromConstMem")] + pub fn from_bytes(buf: &'a [u8]) -> Result, String> { + let rw = + unsafe { sys::SDL_RWFromConstMem(buf.as_ptr() as *const c_void, buf.len() as c_int) }; + if rw.is_null() { + return Err(get_error()); + } + let raw = unsafe { mixer::Mix_LoadMUS_RW(rw, 0) }; + if raw.is_null() { + Err(get_error()) + } else { + Ok(Music { + raw, + owned: true, + owned_data: None, + _marker: PhantomData, + }) + } + } + + /// Load music from a static byte buffer. + #[doc(alias = "SDL_RWFromConstMem")] + pub fn from_static_bytes(buf: &'static [u8]) -> Result, String> { + let rw = + unsafe { sys::SDL_RWFromConstMem(buf.as_ptr() as *const c_void, buf.len() as c_int) }; + if rw.is_null() { + return Err(get_error()); + } + let raw = unsafe { mixer::Mix_LoadMUS_RW(rw, 0) }; + if raw.is_null() { + Err(get_error()) + } else { + Ok(Music { + raw, + owned: true, + owned_data: None, + _marker: PhantomData, + }) + } + } + + /// Load music from an owned byte buffer. + /// + /// The returned [Music] instance takes ownership of the given buffer + /// and drops it along with itself. + /// + /// Loading the whole music data to memory can be wasteful if the music can be streamed directly from + /// a file instead. Consider using [Music::from_file] when possible. #[doc(alias = "SDL_RWFromConstMem")] - pub fn from_bytes(buf: &[u8]) -> Result, String> { + pub fn from_owned_bytes(mut buf: Box<[u8]>) -> Result, String> { let rw = unsafe { sys::SDL_RWFromConstMem(buf.as_ptr() as *const c_void, buf.len() as c_int) }; if rw.is_null() { @@ -861,6 +917,7 @@ impl<'a> Music<'a> { Ok(Music { raw, owned: true, + owned_data: Some(buf), _marker: PhantomData, }) } From c1f42d51ba47797092b7615e1fb25a766db0966b Mon Sep 17 00:00:00 2001 From: kaphula Date: Sun, 22 Jun 2025 17:26:53 +0300 Subject: [PATCH 7/9] Remove Music::from_static_bytes. Set version back to 0.37.0 --- Cargo.toml | 2 +- sdl2-sys/Cargo.toml | 2 +- src/sdl2/mixer/mod.rs | 21 --------------------- 3 files changed, 2 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dde7f2583e..e381adca71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "sdl2" description = "SDL2 bindings for Rust" repository = "https://github.com/Rust-SDL2/rust-sdl2" documentation = "https://docs.rs/sdl2" -version = "0.38.0" +version = "0.37.0" license = "MIT" authors = [ "Tony Aldridge ", "Cobrand "] keywords = ["SDL", "windowing", "graphics", "api", "engine"] diff --git a/sdl2-sys/Cargo.toml b/sdl2-sys/Cargo.toml index b8e988d3d5..4f761fef34 100644 --- a/sdl2-sys/Cargo.toml +++ b/sdl2-sys/Cargo.toml @@ -3,7 +3,7 @@ name = "sdl2-sys" description = "Raw SDL2 bindings for Rust, used internally rust-sdl2" repository = "https://github.com/rust-sdl2/rust-sdl2" -version = "0.38.0" +version = "0.37.0" authors = ["Tony Aldridge ", "Cobrand "] keywords = ["SDL", "windowing", "graphics", "ffi"] categories = ["rendering","external-ffi-bindings","game-engines","multimedia"] diff --git a/src/sdl2/mixer/mod.rs b/src/sdl2/mixer/mod.rs index fdf8bd1368..664a9e7bdd 100644 --- a/src/sdl2/mixer/mod.rs +++ b/src/sdl2/mixer/mod.rs @@ -875,27 +875,6 @@ impl<'a> Music<'a> { } } - /// Load music from a static byte buffer. - #[doc(alias = "SDL_RWFromConstMem")] - pub fn from_static_bytes(buf: &'static [u8]) -> Result, String> { - let rw = - unsafe { sys::SDL_RWFromConstMem(buf.as_ptr() as *const c_void, buf.len() as c_int) }; - if rw.is_null() { - return Err(get_error()); - } - let raw = unsafe { mixer::Mix_LoadMUS_RW(rw, 0) }; - if raw.is_null() { - Err(get_error()) - } else { - Ok(Music { - raw, - owned: true, - owned_data: None, - _marker: PhantomData, - }) - } - } - /// Load music from an owned byte buffer. /// /// The returned [Music] instance takes ownership of the given buffer From defc9b8177d82e6ad8c9c77a93581047ccb4116f Mon Sep 17 00:00:00 2001 From: kaphula Date: Sun, 22 Jun 2025 17:29:32 +0300 Subject: [PATCH 8/9] Fix dependency error. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e381adca71..5053f7cbec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ lazy_static = "1.4.0" [dependencies.sdl2-sys] path = "sdl2-sys" -version = "^0.38.0" +version = "^0.37.0" [dependencies.c_vec] # allow both 1.* and 2.0 versions From 10a7bd70257fab62d0874b317ca6ca101cf8f088 Mon Sep 17 00:00:00 2001 From: kaphula Date: Mon, 23 Jun 2025 22:17:49 +0300 Subject: [PATCH 9/9] Remove Music::from_bytes for now, add Music::from_static_bytes back. --- examples/mixer-demo.rs | 4 ++-- src/sdl2/mixer/mod.rs | 33 ++++++++++++++------------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/examples/mixer-demo.rs b/examples/mixer-demo.rs index 88bd340aa2..6711f67a87 100644 --- a/examples/mixer-demo.rs +++ b/examples/mixer-demo.rs @@ -118,10 +118,10 @@ fn demo(music_file: &Path, sound_file: Option<&Path>) -> Result<(), String> { sdl2::mixer::Channel::all().play(&chunk, 0)?; timer.delay(1_000); - println!("playing music from borrowed memory..."); + println!("playing music from static memory..."); let music_as_bytes = include_bytes!("../assets/sine.wav"); - let mus = sdl2::mixer::Music::from_bytes(music_as_bytes)?; + let mus = sdl2::mixer::Music::from_static_bytes(music_as_bytes)?; mus.play(-1); timer.delay(1_000); sdl2::mixer::Music::halt(); diff --git a/src/sdl2/mixer/mod.rs b/src/sdl2/mixer/mod.rs index 664a9e7bdd..ceede51a28 100644 --- a/src/sdl2/mixer/mod.rs +++ b/src/sdl2/mixer/mod.rs @@ -831,14 +831,13 @@ impl<'a> fmt::Debug for Music<'a> { } impl<'a> Music<'a> { - /// Load music file to use. - /// - /// The music is streamed directly from the file when played. - pub fn from_file>(path: P) -> Result, String> { - let raw = unsafe { - let c_path = CString::new(path.as_ref().to_str().unwrap()).unwrap(); - mixer::Mix_LoadMUS(c_path.as_ptr()) - }; + pub fn from_static_bytes(buf: &'static [u8]) -> Result, String> { + let rw = + unsafe { sys::SDL_RWFromConstMem(buf.as_ptr() as *const c_void, buf.len() as c_int) }; + if rw.is_null() { + return Err(get_error()); + } + let raw = unsafe { mixer::Mix_LoadMUS_RW(rw, 0) }; if raw.is_null() { Err(get_error()) } else { @@ -851,18 +850,14 @@ impl<'a> Music<'a> { } } - /// Load music from a byte buffer. + /// Load music file to use. /// - /// The bytes' lifetime is tied to the returned [Music] instance, - /// so consider using [Music::from_owned_bytes] if that is an issue. - #[doc(alias = "SDL_RWFromConstMem")] - pub fn from_bytes(buf: &'a [u8]) -> Result, String> { - let rw = - unsafe { sys::SDL_RWFromConstMem(buf.as_ptr() as *const c_void, buf.len() as c_int) }; - if rw.is_null() { - return Err(get_error()); - } - let raw = unsafe { mixer::Mix_LoadMUS_RW(rw, 0) }; + /// The music is streamed directly from the file when played. + pub fn from_file>(path: P) -> Result, String> { + let raw = unsafe { + let c_path = CString::new(path.as_ref().to_str().unwrap()).unwrap(); + mixer::Mix_LoadMUS(c_path.as_ptr()) + }; if raw.is_null() { Err(get_error()) } else {