diff --git a/connect/src/spirc.rs b/connect/src/spirc.rs index 874b3fd0..a4145c10 100644 --- a/connect/src/spirc.rs +++ b/connect/src/spirc.rs @@ -126,6 +126,7 @@ enum SpircCommand { RepeatTrack(bool), Disconnect { pause: bool }, SetPosition(u32), + SeekOffset(i32), SetVolume(u16), Activate, Load(LoadRequest), @@ -385,6 +386,13 @@ impl Spirc { Ok(self.commands.send(SpircCommand::Load(command))?) } + /// Seek to given offset. + /// + /// Does nothing if we are not the active device. + pub fn seek_offset(&self, offset_ms: i32) -> Result<(), Error> { + Ok(self.commands.send(SpircCommand::SeekOffset(offset_ms))?) + } + /// Disconnects the current device and pauses the playback according the value. /// /// Does nothing if we are not the active device. @@ -651,6 +659,7 @@ impl SpircTask { SpircCommand::Repeat(repeat) => self.handle_repeat_context(repeat)?, SpircCommand::RepeatTrack(repeat) => self.handle_repeat_track(repeat), SpircCommand::SetPosition(position) => self.handle_seek(position), + SpircCommand::SeekOffset(offset) => self.handle_seek_offset(offset), SpircCommand::SetVolume(volume) => self.set_volume(volume), SpircCommand::Load(command) => self.handle_load(command, None).await?, }; @@ -1461,6 +1470,25 @@ impl SpircTask { }; } + fn handle_seek_offset(&mut self, offset_ms: i32) { + let position_ms = match self.play_status { + SpircPlayStatus::Stopped => return, + SpircPlayStatus::LoadingPause { position_ms } + | SpircPlayStatus::LoadingPlay { position_ms } + | SpircPlayStatus::Paused { position_ms, .. } => position_ms, + SpircPlayStatus::Playing { + nominal_start_time, .. + } => { + let now = self.now_ms(); + (now - nominal_start_time) as u32 + } + }; + + let position_ms = ((position_ms as i32) + offset_ms).max(0) as u32; + + self.handle_seek(position_ms); + } + fn handle_shuffle(&mut self, shuffle: bool) -> Result<(), Error> { self.player.emit_shuffle_changed_event(shuffle); self.connect_state.handle_shuffle(shuffle)