Skip to content

Commit

Permalink
fix playlist issues
Browse files Browse the repository at this point in the history
  • Loading branch information
kamiyaa committed Sep 5, 2024
1 parent 4fbd62b commit 6dfbdbe
Show file tree
Hide file tree
Showing 16 changed files with 246 additions and 136 deletions.
18 changes: 9 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/bin/client/ui/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl AppBackend {
W: Widget,
{
let _ = self.terminal_mut().draw(|frame| {
let rect = frame.size();
let rect = frame.area();
frame.render_widget(widget, rect);
});
}
Expand Down
32 changes: 13 additions & 19 deletions src/bin/server/audio/symphonia/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,6 @@ impl Iterator for PacketReader {
Err(_) => return None,
};

// Consume any new metadata that has been read since the last packet.
while !self.format.metadata().is_latest() {
// Pop the old head of the metadata queue.
self.format.metadata().pop();

// Consume the new metadata at the head of the metadata queue.
}

// If the packet does not belong to the selected track, skip over it.
if packet.track_id() != self.track_id {
continue;
Expand Down Expand Up @@ -131,28 +123,30 @@ where
+ symphonia::core::conv::FromSample<symphonia::core::sample::i24>
+ symphonia::core::conv::FromSample<symphonia::core::sample::u24>,
{
let err_fn = |err| eprintln!("A playback error has occured! {}", err);

let (playback_loop_tx, playback_loop_rx) = mpsc::channel();
let err_fn = |err| {
tracing::error!("A playback error has occured! {}", err);
};

let time_base = TimeBase {
numer: 1,
denom: config.sample_rate.0 * config.channels as u32,
};

let _ = stream_tx.send(StreamEvent::Progress(Duration::from_secs(0)));

// if stream_tx is None, then we've already sent a StreamEnded message
// and we don't need to send another one
let mut stream_tx = Some(stream_tx);

let samples_count = samples.len();

// all vars that the stream will update while its streaming
let frame_index = Arc::new(RwLock::new(0_usize));
let volume = Arc::new(RwLock::new(volume));
let playback_duration = Arc::new(RwLock::new(0));

let _ = stream_tx.send(StreamEvent::Progress(Duration::from_secs(0)));

// if stream_tx is None, then we've already sent a StreamEnded message
// and we don't need to send another one
let mut stream_tx = Some(stream_tx);

let (playback_loop_tx, playback_loop_rx) = mpsc::channel();

let stream = device.build_output_stream(
config,
move |data: &mut [T], _: &cpal::OutputCallbackInfo| {
Expand Down Expand Up @@ -183,7 +177,7 @@ where
process_message(msg);
}

// if sample_offsetcurrent_volume is greater than samples_count, then we've reached the end
// if sample_offset is greater than samples_count, then we've reached the end
let sample_offset = { *frame_index.read().unwrap() };
if sample_offset >= samples_count {
if let Some(stream_tx) = stream_tx.take() {
Expand All @@ -194,7 +188,7 @@ where

let current_volume = { *volume.read().unwrap() };
let mut i = 0;
for d in data {
for d in data.iter_mut() {
if sample_offset + i >= samples_count {
let mut offset = frame_index.write().unwrap();
*offset = samples_count + 1;
Expand Down
77 changes: 38 additions & 39 deletions src/bin/server/audio/symphonia/player/impl_audio_player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use dizi::song::DiziAudioFile;
use dizi::song::DiziSongEntry;

use crate::audio::request::PlayerRequest;
use crate::context::PlaylistContext;
use crate::playlist::DiziPlaylist;
use crate::traits::{AudioPlayer, DiziPlaylistTrait};
use crate::util::mimetype::{get_mimetype, is_mimetype_audio, is_mimetype_video};
Expand All @@ -17,7 +18,8 @@ use super::SymphoniaPlayer;
impl AudioPlayer for SymphoniaPlayer {
fn player_state(&self) -> PlayerState {
let mut state = self.state.clone();
state.playlist = self.playlist.to_file_playlist();
state.playlist = self.playlist_context.file_playlist.to_file_playlist();
state.playlist_status = self.playlist_context.current_playlist_type;
state
}

Expand Down Expand Up @@ -47,42 +49,36 @@ impl AudioPlayer for SymphoniaPlayer {
playlist.shuffle();
}

let order_index = playlist.order_index.ok_or_else(|| {
let error_msg = "Order index is None";
tracing::error!("{error_msg}");
DiziError::new(DiziErrorKind::Server, error_msg.to_string())
})?;

let entry = playlist.contents[order_index].clone();
// lazily load metadata before playing
let audio_file = entry.load_metadata()?;
self.play(&audio_file)?;
playlist.contents[order_index] = DiziSongEntry::Loaded(audio_file);
playlist.load_current_entry_metadata()?;
if let Some(entry) = playlist.current_entry() {
if let DiziSongEntry::Loaded(audio_file) = entry.entry {
self.play(&audio_file)?;
}
}

self.playlist = playlist;
self.state.playlist_status = PlaylistType::DirectoryListing;
self.playlist_context.directory_playlist = playlist;
self.set_playlist_type(PlaylistType::DirectoryListing);
}
Ok(())
}

fn play_from_playlist(&mut self, index: usize) -> DiziResult {
let shuffle_enabled = self.shuffle_enabled();
let playlist = &mut self.playlist;

let playlist = &mut self.playlist_context.file_playlist;
// unshuffle the playlist before choosing setting the new index
playlist.order_index = Some(index);
// reshuffle playlist upon playing new file
if shuffle_enabled {
playlist.shuffle();
}

let entry = playlist.contents[index].clone();
// lazily load metadata before playing
let audio_file = entry.load_metadata()?;
playlist.contents[index] = DiziSongEntry::Loaded(audio_file.clone());
self.state.playlist_status = PlaylistType::PlaylistFile;

self.play(&audio_file)?;
playlist.load_current_entry_metadata()?;
if let Some(entry) = playlist.current_entry() {
if let DiziSongEntry::Loaded(audio_file) = entry.entry {
self.play(&audio_file)?;
}
}
self.set_playlist_type(PlaylistType::PlaylistFile);

Ok(())
}
Expand All @@ -92,34 +88,36 @@ impl AudioPlayer for SymphoniaPlayer {
}

fn play_next(&mut self) -> DiziResult {
let playlist = &mut self.playlist;
let playlist = self.playlist_context.current_playlist_mut();

let song_entry = playlist.next_song_peak().ok_or_else(|| {
DiziError::new(DiziErrorKind::ParseError, "Playlist error".to_string())
})?;
playlist.order_index = Some(song_entry.order_index);

let entry_index = playlist.order[song_entry.order_index];
let audio_file = song_entry.entry.load_metadata()?;
playlist.contents[entry_index] = DiziSongEntry::Loaded(audio_file.clone());

self.play(&audio_file)?;
playlist.load_current_entry_metadata()?;
if let Some(entry) = playlist.current_entry() {
if let DiziSongEntry::Loaded(audio_file) = entry.entry {
self.play(&audio_file)?;
}
}
Ok(())
}

fn play_previous(&mut self) -> DiziResult {
let playlist = &mut self.playlist;
let playlist = self.playlist_context.current_playlist_mut();

let song_entry = playlist.previous_song_peak().ok_or_else(|| {
DiziError::new(DiziErrorKind::ParseError, "Playlist error".to_string())
})?;
playlist.order_index = Some(song_entry.order_index);

let entry_index = playlist.order[song_entry.order_index];
let audio_file = song_entry.entry.load_metadata()?;
playlist.contents[entry_index] = DiziSongEntry::Loaded(audio_file.clone());

self.play(&audio_file)?;
playlist.load_current_entry_metadata()?;
if let Some(entry) = playlist.current_entry() {
if let DiziSongEntry::Loaded(audio_file) = entry.entry {
self.play(&audio_file)?;
}
}
Ok(())
}

Expand Down Expand Up @@ -201,10 +199,11 @@ impl AudioPlayer for SymphoniaPlayer {
}
fn set_shuffle(&mut self, shuffle: bool) {
self.state.shuffle = shuffle;

if self.shuffle_enabled() {
self.playlist.shuffle();
self.playlist_context.current_playlist_mut().shuffle();
} else {
self.playlist.unshuffle();
self.playlist_context.current_playlist_mut().unshuffle();
}
}

Expand All @@ -215,7 +214,7 @@ impl AudioPlayer for SymphoniaPlayer {
fn current_song_ref(&self) -> Option<&DiziAudioFile> {
self.state.song.as_ref()
}
fn playlist_mut(&mut self) -> &mut DiziPlaylist {
&mut self.playlist
fn playlist_context_mut(&mut self) -> &mut PlaylistContext {
&mut self.playlist_context
}
}
22 changes: 18 additions & 4 deletions src/bin/server/audio/symphonia/player/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@ use cpal::traits::HostTrait;

use dizi::error::{DiziError, DiziErrorKind, DiziResult};
use dizi::player::{PlayerState, PlayerStatus};
use dizi::playlist::PlaylistType;
use dizi::song::DiziAudioFile;

use crate::audio::device::get_default_host;
use crate::audio::request::PlayerRequest;
use crate::audio::symphonia::stream::PlayerStream;
use crate::config;
use crate::context::PlaylistContext;
use crate::events::ServerEventSender;
use crate::playlist::DiziPlaylist;
use crate::traits::AudioPlayer;

#[derive(Debug)]
pub struct SymphoniaPlayer {
pub state: PlayerState,
pub playlist: DiziPlaylist,
pub playlist_context: PlaylistContext,

pub player_req_tx: mpsc::Sender<PlayerRequest>,
pub player_res_rx: mpsc::Receiver<DiziResult>,
Expand All @@ -43,15 +45,22 @@ impl SymphoniaPlayer {

let stream_handle: JoinHandle<DiziResult> = thread::spawn(move || {
let mut stream =
PlayerStream::new(event_tx, player_res_tx, player_req_rx, audio_device);
PlayerStream::new(event_tx, player_res_tx, player_req_rx, audio_device)?;
stream.listen_for_events()?;
Ok(())
});

let server_config = config_t.server_ref();
let player_config = server_config.player_ref();

let playlist = DiziPlaylist::from_file(&PathBuf::from("/"), server_config.playlist_ref())?;
let playlist_context = PlaylistContext {
file_playlist: DiziPlaylist::from_file(
&PathBuf::from("/"),
server_config.playlist_ref(),
)
.unwrap_or_default(),
..Default::default()
};
let state = PlayerState {
next: player_config.next,
repeat: player_config.repeat,
Expand All @@ -63,7 +72,7 @@ impl SymphoniaPlayer {

Ok(Self {
state,
playlist,
playlist_context,
player_req_tx,
player_res_rx,
_stream_handle: stream_handle,
Expand Down Expand Up @@ -91,4 +100,9 @@ impl SymphoniaPlayer {
self.state.song = Some(song.clone());
Ok(())
}

fn set_playlist_type(&mut self, playlist_type: PlaylistType) {
self.playlist_context.current_playlist_type = playlist_type;
self.state.playlist_status = playlist_type;
}
}
Loading

0 comments on commit 6dfbdbe

Please sign in to comment.