mirror of
https://github.com/Dummi26/musicdb.git
synced 2025-09-13 07:06:14 +02:00
155 lines
4.7 KiB
Rust
155 lines
4.7 KiB
Rust
use std::{ffi::OsStr, sync::Arc};
|
|
|
|
use rc_u8_reader::ArcU8Reader;
|
|
use rodio::{decoder::DecoderError, Decoder, OutputStream, Sink, Source};
|
|
|
|
use crate::{
|
|
data::{song::Song, SongId},
|
|
server::{Action, Command},
|
|
};
|
|
|
|
use super::PlayerBackend;
|
|
|
|
pub struct PlayerBackendRodio<T> {
|
|
#[allow(unused)]
|
|
output_stream: OutputStream,
|
|
sink: Sink,
|
|
stopped: bool,
|
|
current: Option<(SongId, Arc<Vec<u8>>, Option<u128>, T)>,
|
|
next: Option<(SongId, Arc<Vec<u8>>, Option<MyDecoder>, T)>,
|
|
command_sender: Option<std::sync::mpsc::Sender<(Command, Option<u64>)>>,
|
|
}
|
|
|
|
impl<T> PlayerBackendRodio<T> {
|
|
pub fn new(
|
|
command_sender: std::sync::mpsc::Sender<(Command, Option<u64>)>,
|
|
) -> Result<Self, Box<dyn std::error::Error>> {
|
|
Self::new_with_optional_command_sending(Some(command_sender))
|
|
}
|
|
pub fn new_without_command_sending() -> Result<Self, Box<dyn std::error::Error>> {
|
|
Self::new_with_optional_command_sending(None)
|
|
}
|
|
pub fn new_with_optional_command_sending(
|
|
command_sender: Option<std::sync::mpsc::Sender<(Command, Option<u64>)>>,
|
|
) -> Result<Self, Box<dyn std::error::Error>> {
|
|
let output_stream =
|
|
rodio::OutputStreamBuilder::from_default_device()?.open_stream_or_fallback()?;
|
|
let sink = Sink::connect_new(&output_stream.mixer());
|
|
Ok(Self {
|
|
output_stream,
|
|
sink,
|
|
stopped: true,
|
|
current: None,
|
|
next: None,
|
|
command_sender,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<T> PlayerBackend<T> for PlayerBackendRodio<T> {
|
|
fn load_next_song(
|
|
&mut self,
|
|
id: SongId,
|
|
_song: &Song,
|
|
_filename: &OsStr,
|
|
bytes: Arc<Vec<u8>>,
|
|
_load_duration: bool,
|
|
custom_data: T,
|
|
) {
|
|
let decoder = decoder_from_bytes(Arc::clone(&bytes));
|
|
if let Err(e) = &decoder {
|
|
if let Some(s) = &self.command_sender {
|
|
s.send((
|
|
Action::ErrorInfo(
|
|
format!("Couldn't decode song #{id}!"),
|
|
format!("Error: '{e}'"),
|
|
)
|
|
.cmd(0xFFu8),
|
|
None,
|
|
))
|
|
.unwrap();
|
|
}
|
|
}
|
|
self.next = Some((id, bytes, decoder.ok(), custom_data));
|
|
}
|
|
fn pause(&mut self) {
|
|
self.sink.pause();
|
|
}
|
|
fn stop(&mut self) {
|
|
if !self.stopped {
|
|
self.sink.clear();
|
|
if let Some((_, bytes, _, _)) = &self.current {
|
|
if let Ok(decoder) = decoder_from_bytes(Arc::clone(bytes)) {
|
|
self.sink.append(decoder);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fn resume(&mut self) {
|
|
self.stopped = false;
|
|
self.sink.play();
|
|
}
|
|
fn next(&mut self, play: bool, load_duration: bool) {
|
|
self.stopped = false;
|
|
self.sink.clear();
|
|
self.current = self
|
|
.next
|
|
.take()
|
|
.map(|(id, bytes, mut decoder, custom_data)| {
|
|
let duration = if let Some(decoder) = decoder.take() {
|
|
let duration = if load_duration {
|
|
dbg!(decoder.total_duration().map(|v| v.as_millis()))
|
|
} else {
|
|
None
|
|
};
|
|
self.sink.append(decoder);
|
|
if play {
|
|
self.sink.play();
|
|
}
|
|
duration
|
|
} else {
|
|
None
|
|
};
|
|
(id, bytes, duration, custom_data)
|
|
});
|
|
}
|
|
fn clear(&mut self) {
|
|
self.sink.clear();
|
|
}
|
|
fn playing(&self) -> bool {
|
|
!(self.sink.is_paused() || self.sink.empty())
|
|
}
|
|
fn current_song(&self) -> Option<(SongId, bool, &T)> {
|
|
self.current.as_ref().map(|(id, _, _, t)| (*id, true, t))
|
|
}
|
|
fn next_song(&self) -> Option<(SongId, bool, &T)> {
|
|
self.next.as_ref().map(|(id, _, _, t)| (*id, true, t))
|
|
}
|
|
fn gen_data_mut(&mut self) -> (Option<&mut T>, Option<&mut T>) {
|
|
(
|
|
self.current.as_mut().map(|(_, _, _, t)| t),
|
|
self.next.as_mut().map(|(_, _, _, t)| t),
|
|
)
|
|
}
|
|
fn song_finished_polling(&self) -> bool {
|
|
true
|
|
}
|
|
fn song_finished(&self) -> bool {
|
|
self.current.is_some() && self.sink.empty()
|
|
}
|
|
fn current_song_duration(&self) -> Option<u64> {
|
|
self.current
|
|
.as_ref()
|
|
.and_then(|(_, _, dur, _)| dur.map(|v| v as _))
|
|
}
|
|
fn current_song_playback_position(&self) -> Option<u64> {
|
|
None
|
|
}
|
|
}
|
|
|
|
type MyDecoder = Decoder<ArcU8Reader<Vec<u8>>>;
|
|
|
|
fn decoder_from_bytes(bytes: Arc<Vec<u8>>) -> Result<MyDecoder, DecoderError> {
|
|
Decoder::new(ArcU8Reader::new(Arc::clone(&bytes))).map(|decoder| decoder)
|
|
}
|