I need to play audio after crawling them from the site. I am using crate rodio to play audios. How can I get the iterator of variable audio: Vec<Decoder<std::io::BufReader<std::fs::File>>> in the following code?
let audios: Vec<Decoder<_>> = Vec::new();
let aud_mutex: Arc<Mutex<Vec<_>>> = Arc::new(Mutex::new(audios));
// I grab data from the web and write audio bufs into aud_mutex
let (_stream, stream_handle) = rodio::OutputStream::try_default().unwrap();
let audios = aud_mutex.lock().unwrap();
for source in audios {
stream_handle.play_raw(source.convert_samples());
}
The above code produces the following error.
error[E0277]: `std::sync::MutexGuard<'_, Vec<Decoder<std::io::BufReader<std::fs::File>>>>` is not an iterator
--> src\entries.rs:179:23
|
179 | for source in audios {
| ^^^^^^ `std::sync::MutexGuard<'_, Vec<Decoder<std::io::BufReader<std::fs::File>>>>` is not an iterator
|
= help: the trait `Iterator` is not implemented for `std::sync::MutexGuard<'_, Vec<Decoder<std::io::BufReader<std::fs::File>>>>`
= note: required for `std::sync::MutexGuard<'_, Vec<Decoder<std::io::BufReader<std::fs::File>>>>` to implement `IntoIterator`
TL;DR change for source in audios to for source in &audios or for source in audios.iter() (they are the same thing in this case because of the way that Vec is implemented).
The MutexGuard types uses a Deref implementation, which means that you can't move it - you have to use it by ref. The for _ in _ language construct uses IntoIterator (the trait), and that trait is not implemented for MutexGuard. IntoIterator isn't implemented for &MutexGuard either, but because it is behind a reference the compiler does 'automatic deref' using the Deref trait (it runs the Deref::deref method then sees if there is an IntoIterator on the target type, in this case &Vec). There is an impl of IntoIterator for &Vec, so that is used.
However, another error occurs when I modify the code as follows. I would like to take the ownership of individual elements. How can I do that?
let audios = aud_mutex.lock().unwrap();
let (_stream, stream_handle) = rodio::OutputStream::try_default().unwrap();
for source in audios.iter() {
stream_handle.play_raw(source.convert_samples());
}
error[E0507]: cannot move out of `*source` which is behind a shared reference
--> src\entries.rs:181:36
|
181 | stream_handle.play_raw(source.convert_samples());
| ^^^^^^^-----------------
| | |
| | `*source` moved due to this method call
| move occurs because `*source` has type `Decoder<std::io::BufReader<std::fs::File>>`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves `*source`
--> D:\Scoop\persist\rustup-msvc\.cargo\registry\src\github.com-1ecc6299db9ec823\rodio-0.16.0\src\source\mod.rs:292:27
|
292 | fn convert_samples<D>(self) -> SamplesConverter<Self, D>
| ^^^^
For more information about this error, try `rustc --explain E0507`.