Handle play_request_id as an event

This commit is contained in:
Jarkko Lehtoranta 2023-06-13 17:30:56 +03:00
parent 8e43c3f097
commit 46195f18d6
No known key found for this signature in database
GPG key ID: E539048C587D1F09
3 changed files with 25 additions and 13 deletions

View file

@ -663,6 +663,11 @@ impl SpircTask {
} }
fn handle_player_event(&mut self, event: PlayerEvent) -> Result<(), Error> { fn handle_player_event(&mut self, event: PlayerEvent) -> Result<(), Error> {
// update play_request_id
if let PlayerEvent::PlayRequestIdChanged { play_request_id } = event {
self.play_request_id = Some(play_request_id);
return Ok(());
}
// we only process events if the play_request_id matches. If it doesn't, it is // we only process events if the play_request_id matches. If it doesn't, it is
// an event that belongs to a previous track and only arrives now due to a race // an event that belongs to a previous track and only arrives now due to a race
// condition. In this case we have updated the state already and don't want to // condition. In this case we have updated the state already and don't want to
@ -1462,7 +1467,7 @@ impl SpircTask {
Some((track, index)) => { Some((track, index)) => {
self.state.set_playing_track_index(index); self.state.set_playing_track_index(index);
self.play_request_id = Some(self.player.load(track, start_playing, position_ms)); self.player.load(track, start_playing, position_ms);
self.update_state_position(position_ms); self.update_state_position(position_ms);
if start_playing { if start_playing {

View file

@ -55,7 +55,6 @@ pub type PlayerResult = Result<(), Error>;
pub struct Player { pub struct Player {
commands: Option<mpsc::UnboundedSender<PlayerCommand>>, commands: Option<mpsc::UnboundedSender<PlayerCommand>>,
thread_handle: Option<thread::JoinHandle<()>>, thread_handle: Option<thread::JoinHandle<()>>,
play_request_id_generator: SeqGenerator<u64>,
} }
#[derive(PartialEq, Eq, Debug, Clone, Copy)] #[derive(PartialEq, Eq, Debug, Clone, Copy)]
@ -88,6 +87,7 @@ struct PlayerInternal {
auto_normalise_as_album: bool, auto_normalise_as_album: bool,
player_id: usize, player_id: usize,
play_request_id_generator: SeqGenerator<u64>,
} }
static PLAYER_COUNTER: AtomicUsize = AtomicUsize::new(0); static PLAYER_COUNTER: AtomicUsize = AtomicUsize::new(0);
@ -95,7 +95,6 @@ static PLAYER_COUNTER: AtomicUsize = AtomicUsize::new(0);
enum PlayerCommand { enum PlayerCommand {
Load { Load {
track_id: SpotifyId, track_id: SpotifyId,
play_request_id: u64,
play: bool, play: bool,
position_ms: u32, position_ms: u32,
}, },
@ -132,6 +131,10 @@ enum PlayerCommand {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum PlayerEvent { pub enum PlayerEvent {
// Play request id changed
PlayRequestIdChanged {
play_request_id: u64,
},
// Fired when the player is stopped (e.g. by issuing a "stop" command to the player). // Fired when the player is stopped (e.g. by issuing a "stop" command to the player).
Stopped { Stopped {
play_request_id: u64, play_request_id: u64,
@ -475,6 +478,7 @@ impl Player {
auto_normalise_as_album: false, auto_normalise_as_album: false,
player_id, player_id,
play_request_id_generator: SeqGenerator::new(0),
}; };
// While PlayerInternal is written as a future, it still contains blocking code. // While PlayerInternal is written as a future, it still contains blocking code.
@ -488,7 +492,6 @@ impl Player {
Self { Self {
commands: Some(cmd_tx), commands: Some(cmd_tx),
thread_handle: Some(handle), thread_handle: Some(handle),
play_request_id_generator: SeqGenerator::new(0),
} }
} }
@ -500,16 +503,12 @@ impl Player {
} }
} }
pub fn load(&mut self, track_id: SpotifyId, start_playing: bool, position_ms: u32) -> u64 { pub fn load(&self, track_id: SpotifyId, start_playing: bool, position_ms: u32) {
let play_request_id = self.play_request_id_generator.get();
self.command(PlayerCommand::Load { self.command(PlayerCommand::Load {
track_id, track_id,
play_request_id,
play: start_playing, play: start_playing,
position_ms, position_ms,
}); });
play_request_id
} }
pub fn preload(&self, track_id: SpotifyId) { pub fn preload(&self, track_id: SpotifyId) {
@ -1754,10 +1753,15 @@ impl PlayerInternal {
fn handle_command_load( fn handle_command_load(
&mut self, &mut self,
track_id: SpotifyId, track_id: SpotifyId,
play_request_id: u64, play_request_id_option: Option<u64>,
play: bool, play: bool,
position_ms: u32, position_ms: u32,
) -> PlayerResult { ) -> PlayerResult {
let play_request_id =
play_request_id_option.unwrap_or(self.play_request_id_generator.get());
self.send_event(PlayerEvent::PlayRequestIdChanged { play_request_id });
if !self.config.gapless { if !self.config.gapless {
self.ensure_sink_stopped(play); self.ensure_sink_stopped(play);
} }
@ -2010,7 +2014,7 @@ impl PlayerInternal {
{ {
return self.handle_command_load( return self.handle_command_load(
track_id, track_id,
play_request_id, Some(play_request_id),
start_playback, start_playback,
position_ms, position_ms,
); );
@ -2067,10 +2071,9 @@ impl PlayerInternal {
match cmd { match cmd {
PlayerCommand::Load { PlayerCommand::Load {
track_id, track_id,
play_request_id,
play, play,
position_ms, position_ms,
} => self.handle_command_load(track_id, play_request_id, play, position_ms)?, } => self.handle_command_load(track_id, None, play, position_ms)?,
PlayerCommand::Preload { track_id } => self.handle_command_preload(track_id), PlayerCommand::Preload { track_id } => self.handle_command_preload(track_id),

View file

@ -21,6 +21,10 @@ impl EventHandler {
let mut env_vars = HashMap::new(); let mut env_vars = HashMap::new();
match event { match event {
PlayerEvent::PlayRequestIdChanged { play_request_id } => {
env_vars.insert("PLAYER_EVENT", "play_request_id_changed".to_string());
env_vars.insert("PLAY_REQUEST_ID", play_request_id.to_string());
}
PlayerEvent::TrackChanged { audio_item } => { PlayerEvent::TrackChanged { audio_item } => {
match audio_item.track_id.to_base62() { match audio_item.track_id.to_base62() {
Err(e) => { Err(e) => {