# HG changeset patch # User Paper # Date 1775370379 14400 # Node ID 26f695129c867351c29d8460f85b30583dd1b35b # Parent 18f743c980fa5e14e20cd59da30995713420a090 *: fixes - seeking is actually relative - added track IDs (yes these weren't implemented yet even though they're required), of the format /org/foobar2000/foobar2000/trackids/(hex encoded file path) - added playlist fetching for a possible implementation of the playlist protocol diff -r 18f743c980fa -r 26f695129c86 Cargo.toml --- a/Cargo.toml Sat Apr 04 17:03:22 2026 -0400 +++ b/Cargo.toml Sun Apr 05 02:26:19 2026 -0400 @@ -17,3 +17,4 @@ uuid = { version = "1.23.0", features = ["v4"] } bytes = "1.11.0" urlencoding = "2.1.3" +hex = "0.4.3" diff -r 18f743c980fa -r 26f695129c86 src/beefweb.rs --- a/src/beefweb.rs Sat Apr 04 17:03:22 2026 -0400 +++ b/src/beefweb.rs Sun Apr 05 02:26:19 2026 -0400 @@ -185,6 +185,24 @@ playlist_items: PlaylistItems, } +#[derive(serde::Serialize, serde::Deserialize, Debug)] +pub struct Playlist { + pub id: String, + pub index: i64, + pub title: String, + #[serde(rename = "isCurrent")] + pub current: bool, + #[serde(rename = "itemCount")] + pub item_count: i64, + #[serde(rename = "totalTime")] + pub total_time: f64, +} + +#[derive(serde::Serialize, serde::Deserialize, Debug)] +pub struct Playlists { + pub playlists: Vec, +} + /* --- NOW, THE ACTUAL BEEFWEB THING */ pub struct Beefweb { @@ -369,6 +387,18 @@ }).await; } + pub async fn seek(&self, position: f64) -> Result<(), anyhow::Error> + { + return self.set_player(&SetPlayer { + volume: None, + relative_volume: None, + muted: None, + position: None, + relative_position: Some(position), + options: None, + }).await; + } + /* TODO -- finish this; need to link between string and enum pub async fn set_playback_order(&self, ) -> Result<(), anyhow::Error> @@ -401,6 +431,17 @@ return self.playlist_items(playlist_id, index, 1, columns).await; } + pub async fn playlists(&self) -> Result, anyhow::Error> + { + return Ok(self.client + .get(format!("{}/playlists", self.base_url)) + .send() + .await? + .json::() + .await? + .playlists); + } + pub async fn artwork(&self, playlist_id: &str, index: i64) -> Result { return Ok(self.client diff -r 18f743c980fa -r 26f695129c86 src/player.rs --- a/src/player.rs Sat Apr 04 17:03:22 2026 -0400 +++ b/src/player.rs Sun Apr 05 02:26:19 2026 -0400 @@ -206,7 +206,7 @@ async fn seek(&self, offset: mpris_server::Time) -> fdo::Result<()> { - let pl = self.bw.set_position(time_to_secs(offset)).await; + let pl = self.bw.seek(time_to_secs(offset)).await; match pl { Err(_) => return Err(fdo::Error::Failed("uhoh".to_string())), @@ -313,6 +313,7 @@ _ => (), }; x.set_album_artist(Some([track.columns.get(5).unwrap()])); + x.set_trackid(format!("/org/foobar2000/foobar2000/trackids/{}", hex::encode(track.columns.get(6).unwrap()))); /* Why is this an i32 ??? It would make more sense as f32 or f64 */ match track.columns.get(7).unwrap().parse::() { Ok(v) => { x.set_audio_bpm(Some(v)) }, @@ -420,16 +421,65 @@ return Ok(mpris_server::PlaybackRate::default()); } - /* WTF is this supposed to do? --paper */ + /* FIXME to implement this we would have to search through each playlist + * for the track, and if it doesn't exist, append it to the current playlist. + * + * THEN we can add it directly into the play queue. */ async fn set_position(&self, track_id: mpris_server::TrackId, position: mpris_server::Time) -> fdo::Result<()> { return Ok(()); } - /* Beefweb doesn't really have this, and it would be - * pointless anyway, unless we used winepath */ + /* TODO: + * + * We can effectively implement this "proper" by detecting a file:// + * path, URL decoding it, and prepending "Z:". */ async fn open_uri(&self, uri: String) -> fdo::Result<()> { return Ok(()); } } + +/* -- unfinished impl, don't mind this + + +impl mpris_server::LocalPlaylistsInterface for BeefwebPlayer { + async fn activate_playlist(&self, playlist_id: mpris_server::PlaylistId) -> fdo::Result<()> + { + return Err(fdo::Error::Failed("uhoh".to_string())); + } + + async fn get_playlists(&self, index: u32, max_count: u32, order: mpris_server::PlaylistOrdering, reverse_order: bool) -> fdo::Result> + { + let mut v: Vec = Vec::new(); + + let playlists = self.bw.playlists().await; + + match playlists { + Ok(ref v) => (), + _ => return Err(fdo::Error::Failed("req failed".to_string())), + } + + for playlist in playlists.unwrap() { + + } + + return Err(fdo::Error::Failed("uhoh".to_string())); + } + + async fn playlist_count(&self) -> fdo::Result + { + return Err(fdo::Error::Failed("unimpl".to_string())); + } + + async fn orderings(&self) -> fdo::Result> + { + todo!() + } + + async fn active_playlist(&self) -> fdo::Result> + { + todo!() + } +} +*/