use super::song_downloader::InMemSong;
use crate::app::structures::ListSongID;
use crate::async_rodio_sink::rodio::Decoder;
use crate::async_rodio_sink::rodio::decoder::DecoderError;
use crate::async_rodio_sink::{self, AsyncRodio};
use futures::Stream;
use std::io::Cursor;
use std::sync::Arc;
use std::time::Duration;
pub struct DecodedInMemSong(Decoder<Cursor<ArcInMemSong>>);
struct ArcInMemSong(Arc<InMemSong>);
impl std::fmt::Debug for DecodedInMemSong {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("DecodedInMemSong").field(&"..").finish()
}
}
impl AsRef<[u8]> for ArcInMemSong {
fn as_ref(&self) -> &[u8] {
self.0.as_ref().0.as_ref()
}
}
pub struct Player {
rodio_handle: AsyncRodio<Decoder<Cursor<ArcInMemSong>>, ListSongID>,
}
impl Player {
pub fn new() -> Self {
let rodio_handle = AsyncRodio::new();
Self { rodio_handle }
}
pub fn autoplay_song(
&self,
song: DecodedInMemSong,
song_id: ListSongID,
) -> impl Stream<Item = async_rodio_sink::AutoplayUpdate<ListSongID>> + use<> {
self.rodio_handle.autoplay_song(song.0, song_id)
}
pub fn play_song(
&self,
song: DecodedInMemSong,
song_id: ListSongID,
) -> impl Stream<Item = async_rodio_sink::PlayUpdate<ListSongID>> + use<> {
self.rodio_handle.play_song(song.0, song_id)
}
pub fn queue_song(
&self,
song: DecodedInMemSong,
song_id: ListSongID,
) -> impl Stream<Item = async_rodio_sink::QueueUpdate<ListSongID>> + use<> {
self.rodio_handle.queue_song(song.0, song_id)
}
pub async fn seek(
&self,
duration: Duration,
direction: async_rodio_sink::SeekDirection,
) -> Option<async_rodio_sink::ProgressUpdate<ListSongID>> {
self.rodio_handle.seek(duration, direction).await
}
pub async fn seek_to(
&self,
seek_to_pos: Duration,
id: ListSongID,
) -> Option<async_rodio_sink::ProgressUpdate<ListSongID>> {
self.rodio_handle.seek_to(seek_to_pos, id).await
}
pub async fn stop(&self, song_id: ListSongID) -> Option<async_rodio_sink::Stopped<ListSongID>> {
self.rodio_handle.stop(song_id).await
}
pub async fn stop_all(&self) -> Option<async_rodio_sink::AllStopped> {
self.rodio_handle.stop_all().await
}
pub async fn pause_play(
&self,
song_id: ListSongID,
) -> Option<async_rodio_sink::PausePlayResponse<ListSongID>> {
self.rodio_handle.pause_play(song_id).await
}
pub async fn resume(
&self,
song_id: ListSongID,
) -> Option<async_rodio_sink::Resumed<ListSongID>> {
self.rodio_handle.resume(song_id).await
}
pub async fn pause(&self, song_id: ListSongID) -> Option<async_rodio_sink::Paused<ListSongID>> {
self.rodio_handle.pause(song_id).await
}
pub async fn increase_volume(&self, vol_inc: i8) -> Option<async_rodio_sink::VolumeUpdate> {
self.rodio_handle.increase_volume(vol_inc).await
}
pub async fn set_volume(&self, new_vol: u8) -> Option<async_rodio_sink::VolumeUpdate> {
self.rodio_handle.set_volume(new_vol).await
}
pub async fn try_decode(
song: Arc<InMemSong>,
) -> std::result::Result<DecodedInMemSong, DecoderError> {
tokio::task::spawn_blocking(move || try_decode(song))
.await
.expect("Try decode should not panic")
}
}
fn try_decode(song: Arc<InMemSong>) -> std::result::Result<DecodedInMemSong, DecoderError> {
let song = ArcInMemSong(song);
let cur = std::io::Cursor::new(song);
Ok(DecodedInMemSong(async_rodio_sink::rodio::Decoder::new(
cur,
)?))
}