Use track set for recording screen

This commit is contained in:
Elias Projahn 2021-01-16 15:08:12 +01:00
parent aa6b5c6ac4
commit f69cb38b57
6 changed files with 108 additions and 106 deletions

View file

@ -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)
}
}

View file

@ -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?
}

View file

@ -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(),

View file

@ -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);

View file

@ -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

View file

@ -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");
}
));