From a91eb178c763c35982610d88e7dca9987058e81e Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Thu, 8 Apr 2021 19:56:25 +0200 Subject: [PATCH] Import medium from preview screen --- musicus/src/import/import_screen.rs | 8 +++- musicus/src/import/medium_editor.rs | 33 +++------------ musicus/src/import/medium_preview.rs | 62 +++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/musicus/src/import/import_screen.rs b/musicus/src/import/import_screen.rs index 08176cb..beb9dde 100644 --- a/musicus/src/import/import_screen.rs +++ b/musicus/src/import/import_screen.rs @@ -80,7 +80,9 @@ impl ImportScreen { row.connect_activated(clone!(@weak this => move |_| { let medium = medium.clone(); spawn!(@clone this, async move { - push!(this.handle, MediumPreview, (this.session.clone(), medium.clone())).await; + if let Some(()) = push!(this.handle, MediumPreview, (this.session.clone(), medium.clone())).await { + this.handle.pop(Some(())); + } }); })); @@ -93,7 +95,9 @@ impl ImportScreen { let this = self; spawn!(@clone this, async move { - push!(this.handle, MediumPreview, (this.session.clone(), medium)).await; + if let Some(()) = push!(this.handle, MediumPreview, (this.session.clone(), medium)).await { + this.handle.pop(Some(())); + } }); } } diff --git a/musicus/src/import/medium_editor.rs b/musicus/src/import/medium_editor.rs index c7c1900..419d9ba 100644 --- a/musicus/src/import/medium_editor.rs +++ b/musicus/src/import/medium_editor.rs @@ -131,38 +131,18 @@ impl Screen, Medium> for MediumEditor { } impl MediumEditor { - /// Save the medium and possibly upload it to the server. + /// Create the medium and, if necessary, upload it to the server. async fn save(&self) -> Result { - let name = self.name_entry.get_text().to_string(); - - // Create a new directory in the music library path for the imported medium. - - let mut path = self.handle.backend.get_music_library_path().unwrap().clone(); - path.push(&name); - std::fs::create_dir(&path)?; - // Convert the track set data to real track sets. let mut tracks = Vec::new(); - let import_tracks = self.session.tracks(); for track_set_data in &*self.track_sets.borrow() { for track_data in &track_set_data.tracks { - // Copy the corresponding audio file to the music library. - - let import_track = &import_tracks[track_data.track_source]; - - let mut track_path = path.clone(); - track_path.push(import_track.path.file_name().unwrap()); - - std::fs::copy(&import_track.path, &track_path)?; - - // Create the real track. - let track = Track { recording: track_set_data.recording.clone(), work_parts: track_data.work_parts.clone(), - path: track_path.to_str().unwrap().to_owned(), + path: String::new(), }; tracks.push(track); @@ -181,12 +161,9 @@ impl MediumEditor { self.handle.backend.cl().post_medium(&medium).await?; } - self.handle.backend - .db() - .update_medium(medium.clone()) - .await?; - - self.handle.backend.library_changed(); + // The medium is not added to the database, because the track paths are not known until the + // medium is actually imported into the music library. This step will be handled by the + // medium preview dialog. Ok(medium) } diff --git a/musicus/src/import/medium_preview.rs b/musicus/src/import/medium_preview.rs index 69c817f..8407ce2 100644 --- a/musicus/src/import/medium_preview.rs +++ b/musicus/src/import/medium_preview.rs @@ -1,5 +1,6 @@ use crate::navigator::{NavigationHandle, Screen}; use crate::widgets::Widget; +use anyhow::Result; use gettextrs::gettext; use glib::clone; use gtk::prelude::*; @@ -13,6 +14,7 @@ use std::sync::Arc; pub struct MediumPreview { handle: NavigationHandle<()>, session: Arc, + medium: Medium, widget: gtk::Box, import_button: gtk::Button, done_stack: gtk::Stack, @@ -35,6 +37,7 @@ impl Screen<(Arc, Medium), ()> for MediumPreview { let this = Rc::new(Self { handle, session, + medium, widget, import_button, done_stack, @@ -46,14 +49,21 @@ impl Screen<(Arc, Medium), ()> for MediumPreview { this.handle.pop(None); })); + this.import_button.connect_clicked(clone!(@weak this => move |_| { + spawn!(@clone this, async move { + this.import().await.unwrap(); + this.handle.pop(Some(())); + }); + })); + // Populate the widget - name_label.set_text(&medium.name); + name_label.set_text(&this.medium.name); let mut last_recording_id = ""; let mut last_list = None::; - for track in &medium.tracks { + for track in &this.medium.tracks { if track.recording.id != last_recording_id { last_recording_id = &track.recording.id; @@ -145,6 +155,54 @@ impl MediumPreview { State::Error => todo!("Import error!"), } } + + /// Copy the tracks to the music library and add the medium to the database. + async fn import(&self) -> Result<()> { + // Create a new directory in the music library path for the imported medium. + + let mut path = self.handle.backend.get_music_library_path().unwrap().clone(); + path.push(&self.medium.name); + std::fs::create_dir(&path)?; + + // Copy the tracks to the music library. + + let mut tracks = Vec::new(); + let import_tracks = self.session.tracks(); + + for (index, track) in self.medium.tracks.iter().enumerate() { + let mut track = track.clone(); + + // Set the track path to the new audio file location. + + let import_track = &import_tracks[index]; + let mut track_path = path.clone(); + track_path.push(import_track.path.file_name().unwrap()); + track.path = track_path.to_str().unwrap().to_owned(); + + // Copy the corresponding audio file to the music library. + std::fs::copy(&import_track.path, &track_path)?; + + tracks.push(track); + } + + // Add the modified medium to the database. + + let medium = Medium { + id: self.medium.id.clone(), + name: self.medium.name.clone(), + discid: self.medium.discid.clone(), + tracks, + }; + + self.handle.backend + .db() + .update_medium(medium.clone()) + .await?; + + self.handle.backend.library_changed(); + + Ok(()) + } } impl Widget for MediumPreview {