mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 11:47:25 +01:00
Use track set for recording screen
This commit is contained in:
parent
aa6b5c6ac4
commit
f69cb38b57
6 changed files with 108 additions and 106 deletions
|
|
@ -175,33 +175,22 @@ impl Database {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Get all tracks for a recording.
|
||||
pub fn get_tracks(&self, recording_id: &str) -> Result<Vec<Track>> {
|
||||
let mut tracks: Vec<Track> = Vec::new();
|
||||
/// Get all available track sets for a recording.
|
||||
pub fn get_track_sets(&self, recording_id: &str) -> Result<Vec<TrackSet>> {
|
||||
let mut track_sets: Vec<TrackSet> = 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::<TrackRow>(&self.connection)?;
|
||||
.select(track_sets::table::all_columns())
|
||||
.load::<TrackSetRow>(&self.connection)?;
|
||||
|
||||
for row in rows {
|
||||
let work_parts = row
|
||||
.work_parts
|
||||
.split(',')
|
||||
.map(|part_index| Ok(str::parse(part_index)?))
|
||||
.collect::<Result<Vec<usize>>>()?;
|
||||
|
||||
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::<TrackRow>(&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::<Result<Vec<usize>>>()?;
|
||||
|
||||
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<TrackSet> {
|
||||
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::<TrackRow>(&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::<Result<Vec<usize>>>()?;
|
||||
|
||||
let track = Track {
|
||||
work_parts,
|
||||
path: track_row.path,
|
||||
};
|
||||
|
||||
tracks.push(track);
|
||||
}
|
||||
|
||||
let track_set = TrackSet { recording, tracks };
|
||||
|
||||
Ok(track_set)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ enum Action {
|
|||
UpdateMedium(Medium, Sender<Result<()>>),
|
||||
GetMedium(String, Sender<Result<Option<Medium>>>),
|
||||
DeleteMedium(String, Sender<Result<()>>),
|
||||
GetTracks(String, Sender<Result<Vec<Track>>>),
|
||||
GetTrackSets(String, Sender<Result<Vec<TrackSet>>>),
|
||||
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<Vec<Track>> {
|
||||
/// Get all track sets for a recording.
|
||||
pub async fn get_track_sets(&self, recording_id: &str) -> Result<Vec<TrackSet>> {
|
||||
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?
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ use std::rc::Rc;
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct PlaylistItem {
|
||||
pub tracks: TrackSet,
|
||||
pub file_names: Vec<String>,
|
||||
pub track_set: TrackSet,
|
||||
pub indices: Vec<usize>,
|
||||
}
|
||||
|
||||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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::<String>::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::<String>::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);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ pub struct RecordingScreen {
|
|||
recording: Recording,
|
||||
widget: gtk::Box,
|
||||
stack: gtk::Stack,
|
||||
tracks: RefCell<Vec<Track>>,
|
||||
track_sets: RefCell<Vec<TrackSet>>,
|
||||
navigator: RefCell<Option<Rc<Navigator>>>,
|
||||
}
|
||||
|
||||
|
|
@ -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::<String>::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::<String>::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
|
||||
|
|
|
|||
|
|
@ -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::<String>::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");
|
||||
}
|
||||
));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue