Hello,
I think it is maybe a global Rust philosophy question. I'm trying to use rodio crate which give this example to play a sound:
use std::fs::File;
use std::io::BufReader;
use rodio::{Decoder, OutputStream, source::Source};
// Get a output stream handle to the default physical sound device
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
// Load a sound from a file, using a path relative to Cargo.toml
let file = BufReader::new(File::open("examples/music.ogg").unwrap());
// Decode that sound file into a source
let source = Decoder::new(file).unwrap();
// Play the sound directly on the device
stream_handle.play_raw(source.convert_samples());
// The sound plays in a separate audio thread,
// so we need to keep the main thread alive while it's playing.
std::thread::sleep(std::time::Duration::from_secs(5));
For my project, I want to play the same song often. So I want to design a struct like this:
use rodio::source::{SamplesConverter, SineWave};
use rodio::{Decoder, OutputStream, OutputStreamHandle, source::Source};
use std::fs::File;
use std::io::BufReader;
use std::path::Path;
type SoundSource = Decoder<BufReader<File>>;
pub struct Audio {
stream_handle: OutputStreamHandle,
garand_m1_single_shot: SoundSource,
}
fn source(sound_file_string_path: &str) -> SoundSource {
let file = BufReader::new(File::open(sound_file_string_path).unwrap());
Decoder::new(file).unwrap()
}
impl Audio {
pub fn new() -> Self {
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
let garand_m1_single_shot = source("resources/audio/lmg_fire01.mp3");
Self {
stream_handle,
garand_m1_single_shot,
}
}
pub fn shot(&self) {
self.stream_handle.play_raw(self.garand_m1_single_shot.convert_samples());
}
}
But this produce the following error:
error[E0507]: cannot move out of `self.garand_m1_single_shot` which is behind a shared reference
--> src/audio/mod.rs:74:37
|
74 | self.stream_handle.play_raw(self.garand_m1_single_shot.convert_samples());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because `self.garand_m1_single_shot` has type `Decoder<BufReader<std::fs::File>>`, which does not implement the `Copy` trait
I understand .play_raw don't want a reference but take the ownership of parameter. But, if I have to give ownership, I have to build BufReader then Decoder etc each times ? How can I design code to prepare the Decoder<BufReader<File>> once per sound ?