It works
This commit is contained in:
@@ -265,8 +265,8 @@ impl Actor {
|
||||
.then_some(unix_time_ms()),
|
||||
position_secs: self.state.playback.position_seconds,
|
||||
volume: volume_percent(self.state.playback.volume),
|
||||
shuffle: false,
|
||||
repeat: music_dht::device_sync::PlaybackRepeat::Off,
|
||||
shuffle: self.state.playback.shuffle,
|
||||
repeat: repeat_to_wire(self.state.playback.repeat),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,16 +311,39 @@ impl Actor {
|
||||
start_audio: bool,
|
||||
seek: bool,
|
||||
) {
|
||||
let previous_status = self.state.playback.status;
|
||||
let previous_index = self.state.queue.current_index();
|
||||
let previous_track = self
|
||||
.state
|
||||
.queue
|
||||
.current()
|
||||
.map(|item| item.track.key.clone());
|
||||
let tracks = wire
|
||||
.queue
|
||||
.iter()
|
||||
.filter_map(|track| self.resolve_playback_track(track))
|
||||
.collect::<Vec<_>>();
|
||||
if !tracks.is_empty() {
|
||||
self.state.queue.replace_context(tracks, wire.queue_pos);
|
||||
if wire.shuffle {
|
||||
if !self.state.playback.shuffle {
|
||||
self.state.queue.remember_order();
|
||||
}
|
||||
self.state
|
||||
.queue
|
||||
.replace_shuffled_context(tracks, wire.queue_pos);
|
||||
} else {
|
||||
self.state.queue.replace_context(tracks, wire.queue_pos);
|
||||
}
|
||||
self.resolve_queue_artwork();
|
||||
}
|
||||
let current_changed = previous_index != self.state.queue.current_index()
|
||||
|| previous_track
|
||||
.as_ref()
|
||||
.zip(self.state.queue.current().map(|item| &item.track.key))
|
||||
.is_none_or(|(previous, current)| !previous.matches(current));
|
||||
self.state.playback.volume = f32::from(wire.volume.min(100)) / 100.0;
|
||||
self.state.playback.shuffle = wire.shuffle;
|
||||
self.state.playback.repeat = repeat_from_wire(wire.repeat);
|
||||
self.state.playback.position_seconds = wire.position_secs.max(0.0);
|
||||
self.state.playback.duration_seconds = self
|
||||
.state
|
||||
@@ -338,9 +361,11 @@ impl Actor {
|
||||
if !start_audio {
|
||||
return;
|
||||
}
|
||||
if wire.playing {
|
||||
if !wire.playing {
|
||||
self.audio.stop();
|
||||
} else if previous_status == PlaybackStatus::Stopped || current_changed {
|
||||
self.play_current();
|
||||
if seek || wire.position_secs > 0.0 {
|
||||
if seek {
|
||||
self.audio
|
||||
.seek(Duration::from_secs_f64(wire.position_secs.max(0.0)));
|
||||
self.state.playback.position_seconds = wire.position_secs.max(0.0);
|
||||
@@ -349,8 +374,13 @@ impl Actor {
|
||||
self.audio.pause();
|
||||
self.state.playback.status = PlaybackStatus::Paused;
|
||||
}
|
||||
} else {
|
||||
self.audio.stop();
|
||||
} else if wire.paused {
|
||||
self.audio.pause();
|
||||
} else if previous_status == PlaybackStatus::Paused {
|
||||
self.audio.resume();
|
||||
} else if seek {
|
||||
self.audio
|
||||
.seek(Duration::from_secs_f64(wire.position_secs.max(0.0)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,3 +509,23 @@ impl Actor {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn repeat_to_wire(
|
||||
repeat: furumi_backend_api::PlaybackRepeat,
|
||||
) -> music_dht::device_sync::PlaybackRepeat {
|
||||
match repeat {
|
||||
furumi_backend_api::PlaybackRepeat::Off => music_dht::device_sync::PlaybackRepeat::Off,
|
||||
furumi_backend_api::PlaybackRepeat::One => music_dht::device_sync::PlaybackRepeat::One,
|
||||
furumi_backend_api::PlaybackRepeat::All => music_dht::device_sync::PlaybackRepeat::All,
|
||||
}
|
||||
}
|
||||
|
||||
fn repeat_from_wire(
|
||||
repeat: music_dht::device_sync::PlaybackRepeat,
|
||||
) -> furumi_backend_api::PlaybackRepeat {
|
||||
match repeat {
|
||||
music_dht::device_sync::PlaybackRepeat::Off => furumi_backend_api::PlaybackRepeat::Off,
|
||||
music_dht::device_sync::PlaybackRepeat::One => furumi_backend_api::PlaybackRepeat::One,
|
||||
music_dht::device_sync::PlaybackRepeat::All => furumi_backend_api::PlaybackRepeat::All,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@ use furumi_backend_api::{
|
||||
BackendCommand, BackendSnapshot, BuildInfoSnapshot, ConnectedDeviceSnapshot,
|
||||
ConnectedDevicesSnapshot, DevicePlaybackRole, DevicePresence, DeviceTrust,
|
||||
FederationActivitySnapshot, FederationDebugSnapshot, FederationOperation, LibrarySnapshot,
|
||||
PendingPairingSnapshot, PlaybackStatus, PlaylistSnapshot, RemoteData, RequestId, SearchResults,
|
||||
SearchSnapshot, SearchStats, SendCommandError, SettingsSnapshot, VersionEntrySnapshot,
|
||||
PendingPairingSnapshot, PlaybackRepeat, PlaybackStatus, PlaylistSnapshot, RemoteData,
|
||||
RequestId, SearchResults, SearchSnapshot, SearchStats, SendCommandError, SettingsSnapshot,
|
||||
VersionEntrySnapshot,
|
||||
};
|
||||
use furumi_domain::{
|
||||
Artist, ArtistId, ArtistKey, ArtistRef, Artwork, AudioSource, CatalogSource, ContentId,
|
||||
@@ -688,9 +689,25 @@ impl Actor {
|
||||
}
|
||||
self.publish();
|
||||
}
|
||||
BackendCommand::ToggleShuffle => {
|
||||
self.state.playback.shuffle = !self.state.playback.shuffle;
|
||||
if self.state.playback.shuffle {
|
||||
self.state.queue.shuffle_upcoming();
|
||||
} else {
|
||||
self.state.queue.restore_upcoming_order();
|
||||
}
|
||||
self.send_control_state(false);
|
||||
self.publish();
|
||||
}
|
||||
BackendCommand::CycleRepeat => {
|
||||
self.state.playback.repeat = self.state.playback.repeat.next();
|
||||
self.send_control_state(false);
|
||||
self.publish();
|
||||
}
|
||||
BackendCommand::PlayRelease { release_id, start } => {
|
||||
if let Some(release) = self.release(&release_id).cloned() {
|
||||
self.state.queue.replace_context(release.tracks, start);
|
||||
self.shuffle_new_context();
|
||||
self.resolve_queue_artwork();
|
||||
self.play_current();
|
||||
}
|
||||
@@ -698,6 +715,7 @@ impl Actor {
|
||||
BackendCommand::PlayTrack { track } => {
|
||||
if let Some(track) = self.track(&track).cloned() {
|
||||
self.state.queue.replace_context(vec![track], 0);
|
||||
self.shuffle_new_context();
|
||||
self.resolve_queue_artwork();
|
||||
self.play_current();
|
||||
}
|
||||
@@ -712,6 +730,7 @@ impl Actor {
|
||||
if !tracks.is_empty() {
|
||||
let start = selected_track_position(&tracks, &selected);
|
||||
self.state.queue.replace_context(tracks, start);
|
||||
self.shuffle_new_context();
|
||||
self.resolve_queue_artwork();
|
||||
self.play_current();
|
||||
}
|
||||
@@ -808,7 +827,7 @@ impl Actor {
|
||||
self.select_playback_device(&device_id);
|
||||
}
|
||||
BackendCommand::Next => {
|
||||
if self.state.queue.advance().is_some() {
|
||||
if self.advance_queue(false) {
|
||||
self.play_current();
|
||||
}
|
||||
}
|
||||
@@ -1427,7 +1446,7 @@ impl Actor {
|
||||
}
|
||||
audio::Event::Finished => {
|
||||
self.remove_ephemeral_audio();
|
||||
if self.state.queue.advance().is_some() {
|
||||
if self.advance_queue(true) {
|
||||
self.play_current();
|
||||
} else {
|
||||
self.state.playback.status = PlaybackStatus::Stopped;
|
||||
@@ -1476,6 +1495,23 @@ impl Actor {
|
||||
self.publish();
|
||||
}
|
||||
|
||||
fn shuffle_new_context(&mut self) {
|
||||
if self.state.playback.shuffle {
|
||||
self.state.queue.shuffle_upcoming();
|
||||
}
|
||||
}
|
||||
|
||||
fn advance_queue(&mut self, natural_finish: bool) -> bool {
|
||||
if natural_finish && self.state.playback.repeat == PlaybackRepeat::One {
|
||||
return self.state.queue.current().is_some();
|
||||
}
|
||||
if self.state.queue.advance().is_some() {
|
||||
return true;
|
||||
}
|
||||
self.state.playback.repeat == PlaybackRepeat::All
|
||||
&& self.state.queue.select_index(0).is_some()
|
||||
}
|
||||
|
||||
fn start_federated_playback(&mut self, track: Track, peer_id: String, content_id: ContentId) {
|
||||
let Some(client) = self.federation.clone() else {
|
||||
self.state.playback_error = Some("federation is still starting".into());
|
||||
|
||||
Reference in New Issue
Block a user