Mercurial > beefweb_mpris
comparison src/player.rs @ 5:8f71820abe71
player: use winepath for URLs
this is optional, and it will be automagically disabled if winepath
got something invalid or whatever
| author | Paper <paper@tflc.us> |
|---|---|
| date | Sun, 05 Apr 2026 11:40:21 -0400 |
| parents | 26f695129c86 |
| children |
comparison
equal
deleted
inserted
replaced
| 4:26f695129c86 | 5:8f71820abe71 |
|---|---|
| 16 * You should have received a copy of the GNU General Public License | 16 * You should have received a copy of the GNU General Public License |
| 17 * along with this program; if not, see | 17 * along with this program; if not, see |
| 18 * <https://www.gnu.org/licenses/>. | 18 * <https://www.gnu.org/licenses/>. |
| 19 */ | 19 */ |
| 20 | 20 |
| 21 /* Fuck off, I don't care. */ | |
| 22 #![allow(nonstandard_style)] | |
| 23 #![allow(unused_variables)] | |
| 24 | |
| 21 use crate::beefweb; | 25 use crate::beefweb; |
| 22 | 26 |
| 23 use zbus::fdo; | 27 use zbus::fdo; |
| 24 use zbus::Result; | 28 use zbus::Result; |
| 25 use std::collections::HashMap; | 29 use std::collections::HashMap; |
| 27 use std::cell::RefCell; | 31 use std::cell::RefCell; |
| 28 | 32 |
| 29 /* teehee */ | 33 /* teehee */ |
| 30 pub struct BeefwebPlayer { | 34 pub struct BeefwebPlayer { |
| 31 bw: beefweb::Beefweb, | 35 bw: beefweb::Beefweb, |
| 36 wc: Option<winepath::WineConfig>, | |
| 32 artcache: String, | 37 artcache: String, |
| 33 /* artmap | 38 /* artmap |
| 34 * key: %path% column from beefweb | 39 * key: %path% column from beefweb |
| 35 * value: local path of the artwork | 40 * value: local path of the artwork |
| 36 * also LOL RUST FUCK */ | 41 * also LOL RUST FUCK */ |
| 40 impl BeefwebPlayer { | 45 impl BeefwebPlayer { |
| 41 pub fn new(base: &str, artcache: &str) -> BeefwebPlayer | 46 pub fn new(base: &str, artcache: &str) -> BeefwebPlayer |
| 42 { | 47 { |
| 43 return BeefwebPlayer { | 48 return BeefwebPlayer { |
| 44 bw: beefweb::Beefweb::new(base), | 49 bw: beefweb::Beefweb::new(base), |
| 50 /* teehee */ | |
| 51 wc: winepath::WineConfig::from_env().ok(), | |
| 45 artcache: artcache.to_string(), | 52 artcache: artcache.to_string(), |
| 46 artmap: RefCell::new(HashMap::new()), | 53 artmap: RefCell::new(HashMap::new()), |
| 47 }; | 54 }; |
| 48 } | 55 } |
| 49 | 56 |
| 83 self.artmap.borrow_mut().insert(path.to_string(), artpath.to_string()); | 90 self.artmap.borrow_mut().insert(path.to_string(), artpath.to_string()); |
| 84 | 91 |
| 85 return Ok(artpath); | 92 return Ok(artpath); |
| 86 } | 93 } |
| 87 */ | 94 */ |
| 95 | |
| 96 fn win32_path_to_file_url(&self, p: &str) -> fdo::Result<String> | |
| 97 { | |
| 98 match &(self.wc) { | |
| 99 Some(_) => (), | |
| 100 _ => { return Err(fdo::Error::Failed("Wine environment not loaded?".into())) }, | |
| 101 }; | |
| 102 | |
| 103 let nps = self.wc.as_ref().unwrap(); | |
| 104 | |
| 105 println!("{:?}", nps.prefix()); | |
| 106 | |
| 107 match nps.to_native_path(p) { | |
| 108 Ok(v) => { | |
| 109 match v.to_str() { | |
| 110 /* hax: don't kill slashes */ | |
| 111 Some(vv) => return Ok(format!("file://{}", urlencoding::encode(vv).replace("%2F", "/"))), | |
| 112 _ => (), | |
| 113 }; | |
| 114 }, | |
| 115 /* TODO detect if this is a unix path and use it as such */ | |
| 116 Err(x) => { println!("{}", x); }, | |
| 117 }; | |
| 118 | |
| 119 return Err(fdo::Error::Failed("Converting to unix path failed...".into())); | |
| 120 } | |
| 88 } | 121 } |
| 89 | 122 |
| 90 fn secs_to_time(x: f64) -> mpris_server::Time | 123 fn secs_to_time(x: f64) -> mpris_server::Time |
| 91 { | 124 { |
| 92 return mpris_server::Time::from_micros((x * 1000000.0).round() as i64); | 125 return mpris_server::Time::from_micros((x * 1000000.0).round() as i64); |
| 298 | 331 |
| 299 let mut x = mpris_server::Metadata::new(); | 332 let mut x = mpris_server::Metadata::new(); |
| 300 | 333 |
| 301 x.set_length(Some(secs_to_time(p.active_item.duration))); | 334 x.set_length(Some(secs_to_time(p.active_item.duration))); |
| 302 if track.columns.len() >= 13 { | 335 if track.columns.len() >= 13 { |
| 336 let path = track.columns.get(6).unwrap(); | |
| 337 | |
| 303 x.set_title(Some(track.columns.get(0).unwrap())); | 338 x.set_title(Some(track.columns.get(0).unwrap())); |
| 304 /* XXX musicbrainz has %artists% we can use for a proper list */ | 339 /* XXX musicbrainz has %artists% we can use for a proper list */ |
| 305 x.set_artist(Some([track.columns.get(1).unwrap()])); | 340 x.set_artist(Some([track.columns.get(1).unwrap()])); |
| 306 x.set_album(Some(track.columns.get(2).unwrap())); | 341 x.set_album(Some(track.columns.get(2).unwrap())); |
| 307 match track.columns.get(3).unwrap().parse::<i32>() { | 342 match track.columns.get(3).unwrap().parse::<i32>() { |
| 311 match track.columns.get(4).unwrap().parse::<i32>() { | 346 match track.columns.get(4).unwrap().parse::<i32>() { |
| 312 Ok(v) => { x.set_track_number(Some(v)); }, | 347 Ok(v) => { x.set_track_number(Some(v)); }, |
| 313 _ => (), | 348 _ => (), |
| 314 }; | 349 }; |
| 315 x.set_album_artist(Some([track.columns.get(5).unwrap()])); | 350 x.set_album_artist(Some([track.columns.get(5).unwrap()])); |
| 316 x.set_trackid(format!("/org/foobar2000/foobar2000/trackids/{}", hex::encode(track.columns.get(6).unwrap()))); | 351 x.set_trackid(Some(mpris_server::TrackId::from(zbus::zvariant::ObjectPath::from_string_unchecked(format!("/org/foobar2000/foobar2000/trackids/{}", hex::encode(path)))))); |
| 317 /* Why is this an i32 ??? It would make more sense as f32 or f64 */ | 352 /* Why is this an i32 ??? It would make more sense as f32 or f64 */ |
| 318 match track.columns.get(7).unwrap().parse::<i32>() { | 353 match track.columns.get(7).unwrap().parse::<i32>() { |
| 319 Ok(v) => { x.set_audio_bpm(Some(v)) }, | 354 Ok(v) => { x.set_audio_bpm(Some(v)) }, |
| 320 _ => (), | 355 _ => (), |
| 321 }; | 356 }; |
| 322 x.set_composer(Some([track.columns.get(8).unwrap()])); | 357 x.set_composer(Some([track.columns.get(8).unwrap()])); |
| 323 x.set_comment(Some([track.columns.get(9).unwrap()])); | 358 x.set_comment(Some([track.columns.get(9).unwrap()])); |
| 324 x.set_content_created(Some(track.columns.get(10).unwrap())); | 359 x.set_content_created(Some(track.columns.get(10).unwrap())); |
| 325 x.set_genre(Some(track.columns.get(11).unwrap().split(";"))); | 360 x.set_genre(Some(track.columns.get(11).unwrap().split(";"))); |
| 326 x.set_lyricist(Some([track.columns.get(12).unwrap()])); | 361 x.set_lyricist(Some([track.columns.get(12).unwrap()])); |
| 362 | |
| 363 /* add file:// URI */ | |
| 364 match self.win32_path_to_file_url(path) { | |
| 365 Ok(a) => { x.set_url(Some(a)); }, | |
| 366 /* If it failed, it's more than likely a URL already, | |
| 367 * pointing to a stream */ | |
| 368 Err(_) => { x.set_url(Some(path)); }, | |
| 369 }; | |
| 327 } | 370 } |
| 328 | 371 |
| 329 /* | 372 /* |
| 330 return match artwork.await { | 373 return match artwork.await { |
| 331 Ok(x) => Ok(builder.art_url(urlencoding::encode(format!("file://{}", x).as_str())).build()), | 374 Ok(x) => Ok(builder.art_url(urlencoding::encode(format!("file://{}", x).as_str())).build()), |
