diff --git a/src/model/album.rs b/src/model/album.rs new file mode 100644 index 0000000..1f05598 --- /dev/null +++ b/src/model/album.rs @@ -0,0 +1,74 @@ +mod imp { + use adw::prelude::*; + use gtk::subclass::prelude::*; + use gtk::{gdk, glib}; + use std::cell::{Cell, RefCell}; + + #[derive(glib::Properties, Default)] + #[properties(wrapper_type = super::Album)] + pub struct Album { + #[property(get, set)] + id: RefCell, + #[property(get, set)] + name: RefCell, + #[property(get, set)] + artist: RefCell>, + } + + #[glib::object_subclass] + impl ObjectSubclass for Album { + const NAME: &'static str = "AudreyModelAlbum"; + type Type = super::Album; + } +} + +use crate::subsonic; +use adw::{prelude::*, subclass::prelude::*}; +use glib::Object; +use gtk::{gdk, glib}; +use std::rc::Rc; + +glib::wrapper! { + pub struct Album(ObjectSubclass); +} + +impl Album { + pub fn from_api( + album: &subsonic::schema::Child, + load_thumbnail: bool, + ) -> Self { + let album: Album = Object::builder() + .property("id", &album.id) + .property("title", &album.title) + .property("artist", &album.artist) + .property("album", &album.album) + .property("genre", &album.genre) + .property("duration", album.duration as i64) + .property("track", album.track.map(i64::from).unwrap_or(-1)) + .property("stream-url", api.stream_url(&album.id).as_str()) + .build(); + + if load_thumbnail { + let api = Rc::clone(&api); + let id = album.id(); + let album_weak = album.downgrade(); + album.imp() + .thumbnail_loading + .replace(Some(glib::spawn_future_local(async move { + let bytes = api + .cover_art(&id, Some(50)) // TODO: WidgetExt::scale_factor + .await + .unwrap(); + let album = match album_weak.upgrade() { + None => return, + Some(album) => album, + }; + album.set_thumbnail( + gdk::Texture::from_bytes(&glib::Bytes::from_owned(bytes)).unwrap(), + ); + }))); + } + + album + } +} diff --git a/src/model/song.rs b/src/model/song.rs index b32fe22..8cfa8a3 100644 --- a/src/model/song.rs +++ b/src/model/song.rs @@ -53,7 +53,9 @@ mod imp { impl Drop for Song { fn drop(&mut self) { - self.thumbnail_loading.take().map(|handle| handle.abort()); + if let Some(handle) = self.thumbnail_loading.take() { + handle.abort(); + } } } } @@ -86,7 +88,7 @@ impl Song { .build(); if load_thumbnail { - let api = Rc::clone(&api); + let api = Rc::clone(api); let id = song.id(); let song_weak = song.downgrade(); song.imp() diff --git a/src/mpris/player.rs b/src/mpris/player.rs index 75aaec6..a56d741 100644 --- a/src/mpris/player.rs +++ b/src/mpris/player.rs @@ -131,9 +131,9 @@ impl Player { object_server.at("/org/mpris/MediaPlayer2", player).await?; - Ok(object_server + object_server .interface::<_, Self>("/org/mpris/MediaPlayer2") - .await?) + .await /* playbin.connect_new_track(glib::clone!( @@ -339,7 +339,7 @@ impl Player { #[zbus(property(emits_changed_signal = "false"))] fn position(&self) -> i64 { - (self.window().time_pos() * MICROSECONDS as f64) as i64 + (self.window().time_pos() * MICROSECONDS) as i64 } #[zbus(property)] diff --git a/src/subsonic/album_list.rs b/src/subsonic/album_list.rs index 670500b..1d28c56 100644 --- a/src/subsonic/album_list.rs +++ b/src/subsonic/album_list.rs @@ -36,10 +36,7 @@ impl Client { _ => todo!("{type_:?}"), } - .map(|response| match response.album_list2.album { - Some(albums) => albums, - None => vec![], - }) + .map(|response| response.album_list2.album.unwrap_or_default()) } pub fn album_list_full( @@ -50,7 +47,7 @@ impl Client { let type_ = type_.clone(); async move { match self.album_list(&type_, 500, offset as u32).await { - Ok(albums) if albums.len() == 0 => Ok(None), + Ok(albums) if albums.is_empty() => Ok(None), Ok(albums) => { let next_offset = offset + albums.len(); Ok(Some(( diff --git a/src/ui/window.rs b/src/ui/window.rs index b339653..ab6e45f 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -291,15 +291,11 @@ mod imp { } fn volume(&self) -> i64 { - self.mpv - .get_property::("volume") - .unwrap() - .try_into() - .unwrap() + self.mpv.get_property("volume").unwrap() } fn set_volume(&self, volume: i64) { - self.mpv.set_property("volume", volume as i64).unwrap(); + self.mpv.set_property("volume", volume).unwrap(); } fn mute(&self) -> bool { @@ -365,11 +361,7 @@ mod imp { } fn playlist_count(&self) -> i64 { - self.mpv - .get_property::("playlist-count") - .unwrap() - .try_into() - .unwrap() + self.mpv.get_property::("playlist-count").unwrap() } fn song(&self) -> Option { @@ -389,28 +381,30 @@ mod imp { fn buffering_start(&self) { let started_buffering = std::time::Instant::now(); let window = self.obj().downgrade(); - self.buffering_timeout - .replace(Some(glib::timeout_add_local( - std::time::Duration::from_millis(100), - move || { - match window.upgrade() { - None => glib::ControlFlow::Break, - Some(window) => { - // 3 second period from gnome hig - if started_buffering.elapsed() > std::time::Duration::from_secs(3) { - window.imp().playbar.set_show_pulse_bar(true); - window.imp().playbar.pulse_bar().pulse(); - } - glib::ControlFlow::Continue + if let Some(source) = self.buffering_timeout.replace(Some(glib::timeout_add_local( + std::time::Duration::from_millis(100), + move || { + match window.upgrade() { + None => glib::ControlFlow::Break, + Some(window) => { + // 3 second period from gnome hig + if started_buffering.elapsed() > std::time::Duration::from_secs(3) { + window.imp().playbar.set_show_pulse_bar(true); + window.imp().playbar.pulse_bar().pulse(); } + glib::ControlFlow::Continue } - }, - ))) - .map(|source| source.remove()); + } + }, + ))) { + source.remove() + } } fn buffering_end(&self) { - self.buffering_timeout.take().map(|source| source.remove()); + if let Some(source) = self.buffering_timeout.take() { + source.remove(); + } self.playbar.set_show_pulse_bar(false); } @@ -459,7 +453,7 @@ mod imp { assert_eq!(path, self.obj().song().unwrap().stream_url()) } Err(err) if err.is_property_unavailable() => {} - Err(err) => Err(err).unwrap(), + Err(err) => panic!("{err:?}"), } } @@ -474,7 +468,8 @@ mod imp { let window = self.obj().clone(); let song_id = window.song().unwrap().id(); - self.loading_cover_handle + if let Some(handle) = self + .loading_cover_handle .replace(Some(glib::spawn_future_local(async move { let api = window.imp().api.borrow().as_ref().unwrap().clone(); let bytes = api @@ -496,7 +491,9 @@ mod imp { } } }))) - .map(|handle| handle.abort()); + { + handle.abort(); + } // make sure this is reported as 0 self.obj().notify("time-pos"); @@ -589,10 +586,12 @@ mod imp { self.mpv_event_loop_handle.take().unwrap().abort(); self.zbus_executor_loop_handle.take().unwrap().abort(); - self.time_pos_notify_timeout - .take() - .map(|source| source.remove()); - self.buffering_timeout.take().map(|source| source.remove()); + if let Some(source) = self.time_pos_notify_timeout.take() { + source.remove(); + } + if let Some(source) = self.buffering_timeout.take() { + source.remove(); + } } } } @@ -664,7 +663,7 @@ impl Window { let mut count = 0; let mut albums = std::pin::pin!(api.album_list_full(crate::subsonic::AlbumListType::Newest)); - while let Some(_) = albums.try_next().await.unwrap() { + while albums.try_next().await.unwrap().is_some() { count += 1; } println!("gathered {count} albums"); @@ -705,27 +704,32 @@ impl Window { .command(["playlist-move", &from.to_string(), &to.to_string()]) .unwrap(); - if from < to { - // F1234T -> 1234FT - let mut spliced = Vec::with_capacity((to - from) as usize); - for i in from + 1..to { - spliced.push(self.playlist_model().item(i).unwrap()); - } - spliced.push(self.playlist_model().item(from).unwrap()); + use std::cmp::Ordering; + match from.cmp(&to) { + Ordering::Less => { + // F1234T -> 1234FT + let mut spliced = Vec::with_capacity((to - from) as usize); + for i in from + 1..to { + spliced.push(self.playlist_model().item(i).unwrap()); + } + spliced.push(self.playlist_model().item(from).unwrap()); - self.playlist_model() - .splice(from, spliced.len() as u32, &spliced); - } else if to < from { - // T1234F -> FT1234 - let mut spliced = Vec::with_capacity((from - to + 1) as usize); - spliced.push(self.playlist_model().item(from).unwrap()); - spliced.push(self.playlist_model().item(to).unwrap()); - for i in to + 1..from { - spliced.push(self.playlist_model().item(i).unwrap()); + self.playlist_model() + .splice(from, spliced.len() as u32, &spliced); } + Ordering::Greater => { + // T1234F -> FT1234 + let mut spliced = Vec::with_capacity((from - to + 1) as usize); + spliced.push(self.playlist_model().item(from).unwrap()); + spliced.push(self.playlist_model().item(to).unwrap()); + for i in to + 1..from { + spliced.push(self.playlist_model().item(i).unwrap()); + } - self.playlist_model() - .splice(to, spliced.len() as u32, &spliced); + self.playlist_model() + .splice(to, spliced.len() as u32, &spliced); + } + Ordering::Equal => {} } } }