diff --git a/musicus/src/database/medium.rs b/musicus/src/database/medium.rs index f145ccf..0512c22 100644 --- a/musicus/src/database/medium.rs +++ b/musicus/src/database/medium.rs @@ -175,33 +175,22 @@ impl Database { Ok(()) } - /// Get all tracks for a recording. - pub fn get_tracks(&self, recording_id: &str) -> Result> { - let mut tracks: Vec = Vec::new(); + /// Get all available track sets for a recording. + pub fn get_track_sets(&self, recording_id: &str) -> Result> { + let mut track_sets: Vec = Vec::new(); - let rows = tracks::table - .inner_join(track_sets::table.on(track_sets::id.eq(tracks::track_set))) + let rows = track_sets::table .inner_join(recordings::table.on(recordings::id.eq(track_sets::recording))) .filter(recordings::id.eq(recording_id)) - .select(tracks::table::all_columns()) - .load::(&self.connection)?; + .select(track_sets::table::all_columns()) + .load::(&self.connection)?; for row in rows { - let work_parts = row - .work_parts - .split(',') - .map(|part_index| Ok(str::parse(part_index)?)) - .collect::>>()?; - - let track = Track { - work_parts, - path: row.path.clone(), - }; - - tracks.push(track); + let track_set = self.get_track_set_from_row(row)?; + track_sets.push(track_set); } - Ok(tracks) + Ok(track_sets) } /// Retrieve all available information on a medium from related tables. @@ -214,36 +203,7 @@ impl Database { let mut track_sets = Vec::new(); for track_set_row in track_set_rows { - let recording_id = &track_set_row.recording; - - let recording = self - .get_recording(recording_id)? - .ok_or_else(|| anyhow!("No recording with ID: {}", recording_id))?; - - let track_rows = tracks::table - .filter(tracks::id.eq(&track_set_row.id)) - .order_by(tracks::index) - .load::(&self.connection)?; - - let mut tracks = Vec::new(); - - for track_row in track_rows { - let work_parts = track_row - .work_parts - .split(',') - .map(|part_index| Ok(str::parse(part_index)?)) - .collect::>>()?; - - let track = Track { - work_parts, - path: track_row.path.clone(), - }; - - tracks.push(track); - } - - let track_set = TrackSet { recording, tracks }; - + let track_set = self.get_track_set_from_row(track_set_row)?; track_sets.push(track_set); } @@ -256,4 +216,39 @@ impl Database { Ok(medium) } + + /// Convert a track set row from the database to an actual track set. + fn get_track_set_from_row(&self, row: TrackSetRow) -> Result { + let recording_id = row.recording; + + let recording = self + .get_recording(&recording_id)? + .ok_or_else(|| anyhow!("No recording with ID: {}", recording_id))?; + + let track_rows = tracks::table + .filter(tracks::track_set.eq(row.id)) + .order_by(tracks::index) + .load::(&self.connection)?; + + let mut tracks = Vec::new(); + + for track_row in track_rows { + let work_parts = track_row + .work_parts + .split(',') + .map(|part_index| Ok(str::parse(part_index)?)) + .collect::>>()?; + + let track = Track { + work_parts, + path: track_row.path, + }; + + tracks.push(track); + } + + let track_set = TrackSet { recording, tracks }; + + Ok(track_set) + } } diff --git a/musicus/src/database/thread.rs b/musicus/src/database/thread.rs index 23955e8..2ce86fe 100644 --- a/musicus/src/database/thread.rs +++ b/musicus/src/database/thread.rs @@ -31,7 +31,7 @@ enum Action { UpdateMedium(Medium, Sender>), GetMedium(String, Sender>>), DeleteMedium(String, Sender>), - GetTracks(String, Sender>>), + GetTrackSets(String, Sender>>), Stop(Sender<()>), } @@ -134,8 +134,8 @@ impl DbThread { DeleteMedium(id, sender) => { sender.send(db.delete_medium(&id)).unwrap(); } - GetTracks(recording_id, sender) => { - sender.send(db.get_tracks(&recording_id)).unwrap(); + GetTrackSets(recording_id, sender) => { + sender.send(db.get_track_sets(&recording_id)).unwrap(); } Stop(sender) => { sender.send(()).unwrap(); @@ -339,10 +339,10 @@ impl DbThread { receiver.await? } - /// Get all tracks for a recording. - pub async fn get_tracks(&self, recording_id: &str) -> Result> { + /// Get all track sets for a recording. + pub async fn get_track_sets(&self, recording_id: &str) -> Result> { let (sender, receiver) = oneshot::channel(); - self.action_sender.send(GetTracks(recording_id.to_owned(), sender))?; + self.action_sender.send(GetTrackSets(recording_id.to_owned(), sender))?; receiver.await? } diff --git a/musicus/src/player.rs b/musicus/src/player.rs index f59371b..31ba92e 100644 --- a/musicus/src/player.rs +++ b/musicus/src/player.rs @@ -8,8 +8,7 @@ use std::rc::Rc; #[derive(Clone)] pub struct PlaylistItem { - pub tracks: TrackSet, - pub file_names: Vec, + pub track_set: TrackSet, pub indices: Vec, } @@ -249,7 +248,7 @@ impl Player { "file://{}", self.music_library_path .join( - self.playlist.borrow()[current_item].file_names[current_track].clone(), + self.playlist.borrow()[current_item].track_set.tracks[current_track].path.clone(), ) .to_str() .unwrap(), diff --git a/musicus/src/screens/player_screen.rs b/musicus/src/screens/player_screen.rs index 8a258e2..fe3ae81 100644 --- a/musicus/src/screens/player_screen.rs +++ b/musicus/src/screens/player_screen.rs @@ -215,17 +215,17 @@ impl PlayerScreen { elements.push(PlaylistElement { item: item_index, track: 0, - title: item.tracks.recording.work.get_title(), - subtitle: Some(item.tracks.recording.get_performers()), + title: item.track_set.recording.work.get_title(), + subtitle: Some(item.track_set.recording.get_performers()), playable: false, }); for track_index in &item.indices { - let track = &item.tracks.tracks[*track_index]; + let track = &item.track_set.tracks[*track_index]; let mut parts = Vec::::new(); for part in &track.work_parts { - parts.push(item.tracks.recording.work.parts[*part].title.clone()); + parts.push(item.track_set.recording.work.parts[*part].title.clone()); } let title = if parts.is_empty() { @@ -264,20 +264,20 @@ impl PlayerScreen { next_button.set_sensitive(player.has_next()); let item = &playlist.borrow()[current_item]; - let track = &item.tracks.tracks[current_track]; + let track = &item.track_set.tracks[current_track]; let mut parts = Vec::::new(); for part in &track.work_parts { - parts.push(item.tracks.recording.work.parts[*part].title.clone()); + parts.push(item.track_set.recording.work.parts[*part].title.clone()); } - let mut title = item.tracks.recording.work.get_title(); + let mut title = item.track_set.recording.work.get_title(); if !parts.is_empty() { title = format!("{}: {}", title, parts.join(", ")); } title_label.set_text(&title); - subtitle_label.set_text(&item.tracks.recording.get_performers()); + subtitle_label.set_text(&item.track_set.recording.get_performers()); position_label.set_text("0:00"); self_item.replace(current_item); diff --git a/musicus/src/screens/recording_screen.rs b/musicus/src/screens/recording_screen.rs index 18540fb..4d33aa9 100644 --- a/musicus/src/screens/recording_screen.rs +++ b/musicus/src/screens/recording_screen.rs @@ -17,7 +17,7 @@ pub struct RecordingScreen { recording: Recording, widget: gtk::Box, stack: gtk::Stack, - tracks: RefCell>, + track_sets: RefCell>, navigator: RefCell>>, } @@ -56,35 +56,43 @@ impl RecordingScreen { recording, widget, stack, - tracks: RefCell::new(Vec::new()), + track_sets: RefCell::new(Vec::new()), navigator: RefCell::new(None), }); - list.set_make_widget(clone!(@strong result => move |track: &Track| { - let mut title_parts = Vec::::new(); - for part in &track.work_parts { - title_parts.push(result.recording.work.parts[*part].title.clone()); - } - - let title = if title_parts.is_empty() { - gettext("Unknown") - } else { - title_parts.join(", ") - }; - - let title_label = gtk::Label::new(Some(&title)); - title_label.set_ellipsize(pango::EllipsizeMode::End); - title_label.set_halign(gtk::Align::Start); - - let file_name_label = gtk::Label::new(Some(&track.path)); - file_name_label.set_ellipsize(pango::EllipsizeMode::End); - file_name_label.set_opacity(0.5); - file_name_label.set_halign(gtk::Align::Start); - + list.set_make_widget(clone!(@strong result => move |track_set: &TrackSet| { let vbox = gtk::Box::new(gtk::Orientation::Vertical, 0); vbox.set_border_width(6); - vbox.add(&title_label); - vbox.add(&file_name_label); + vbox.set_spacing(6); + + for track in &track_set.tracks { + let track_box = gtk::Box::new(gtk::Orientation::Vertical, 0); + + let mut title_parts = Vec::::new(); + for part in &track.work_parts { + title_parts.push(result.recording.work.parts[*part].title.clone()); + } + + let title = if title_parts.is_empty() { + gettext("Unknown") + } else { + title_parts.join(", ") + }; + + let title_label = gtk::Label::new(Some(&title)); + title_label.set_ellipsize(pango::EllipsizeMode::End); + title_label.set_halign(gtk::Align::Start); + + let file_name_label = gtk::Label::new(Some(&track.path)); + file_name_label.set_ellipsize(pango::EllipsizeMode::End); + file_name_label.set_opacity(0.5); + file_name_label.set_halign(gtk::Align::Start); + + track_box.add(&title_label); + track_box.add(&file_name_label); + + vbox.add(&track_box); + } vbox.upcast() })); @@ -97,12 +105,12 @@ impl RecordingScreen { })); add_to_playlist_button.connect_clicked(clone!(@strong result => move |_| { - if let Some(player) = result.backend.get_player() { - // player.add_item(PlaylistItem { - // recording: result.recording.clone(), - // tracks: result.tracks.borrow().clone(), - // }).unwrap(); - } + // if let Some(player) = result.backend.get_player() { + // player.add_item(PlaylistItem { + // track_set: result.track_sets.get(0).unwrap().clone(), + // indices: result.tracks.borrow().clone(), + // }).unwrap(); + // } })); edit_action.connect_activate(clone!(@strong result => move |_, _| { @@ -138,16 +146,16 @@ impl RecordingScreen { let context = glib::MainContext::default(); let clone = result.clone(); context.spawn_local(async move { - let tracks = clone + let track_sets = clone .backend .db() - .get_tracks(&clone.recording.id) + .get_track_sets(&clone.recording.id) .await .unwrap(); - list.show_items(tracks.clone()); + list.show_items(track_sets.clone()); clone.stack.set_visible_child_name("content"); - clone.tracks.replace(tracks); + clone.track_sets.replace(track_sets); }); result diff --git a/musicus/src/widgets/player_bar.rs b/musicus/src/widgets/player_bar.rs index c84d11b..1e61df6 100644 --- a/musicus/src/widgets/player_bar.rs +++ b/musicus/src/widgets/player_bar.rs @@ -112,20 +112,20 @@ impl PlayerBar { next_button.set_sensitive(player.has_next()); let item = &playlist.borrow()[current_item]; - let track = &item.tracks.tracks[current_track]; + let track = &item.track_set.tracks[current_track]; let mut parts = Vec::::new(); for part in &track.work_parts { - parts.push(item.tracks.recording.work.parts[*part].title.clone()); + parts.push(item.track_set.recording.work.parts[*part].title.clone()); } - let mut title = item.tracks.recording.work.get_title(); + let mut title = item.track_set.recording.work.get_title(); if !parts.is_empty() { title = format!("{}: {}", title, parts.join(", ")); } title_label.set_text(&title); - subtitle_label.set_text(&item.tracks.recording.get_performers()); + subtitle_label.set_text(&item.track_set.recording.get_performers()); position_label.set_text("0:00"); } ));