mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 03:47:23 +01:00
Store tracks from tracks editor
This commit is contained in:
parent
543f5ed1fd
commit
54e743b876
9 changed files with 126 additions and 11 deletions
|
|
@ -16,4 +16,6 @@ DROP TABLE ensembles;
|
|||
|
||||
DROP TABLE recordings;
|
||||
|
||||
DROP TABLE performances;
|
||||
DROP TABLE performances;
|
||||
|
||||
DROP TABLE tracks;
|
||||
|
|
@ -59,4 +59,12 @@ CREATE TABLE performances (
|
|||
person BIGINT REFERENCES persons(id),
|
||||
ensemble BIGINT REFERENCES ensembles(id),
|
||||
role BIGINT REFERENCES instruments(id)
|
||||
);
|
||||
|
||||
CREATE TABLE tracks (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
file_name TEXT NOT NULL,
|
||||
recording BIGINT NOT NULL REFERENCES recordings(id) ON DELETE CASCADE,
|
||||
track_index INTEGER NOT NULL,
|
||||
work_parts TEXT NOT NULL
|
||||
);
|
||||
|
|
@ -34,6 +34,8 @@ enum BackendAction {
|
|||
GetRecordingsForPerson(i64, Sender<Result<Vec<RecordingDescription>>>),
|
||||
GetRecordingsForEnsemble(i64, Sender<Result<Vec<RecordingDescription>>>),
|
||||
GetRecordingsForWork(i64, Sender<Result<Vec<RecordingDescription>>>),
|
||||
AddTracks(i64, Vec<TrackDescription>, Sender<Result<()>>),
|
||||
GetTracks(i64, Sender<Result<Vec<TrackDescription>>>),
|
||||
Stop,
|
||||
}
|
||||
|
||||
|
|
@ -212,6 +214,20 @@ impl Backend {
|
|||
receiver.await?
|
||||
}
|
||||
|
||||
pub async fn add_tracks(&self, recording_id: i64, tracks: Vec<TrackDescription>) -> Result<()> {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
self.unwrap_action_sender()?
|
||||
.send(AddTracks(recording_id, tracks, sender))?;
|
||||
receiver.await?
|
||||
}
|
||||
|
||||
pub async fn get_tracks(&self, recording_id: i64) -> Result<Vec<TrackDescription>> {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
self.unwrap_action_sender()?
|
||||
.send(GetTracks(recording_id, sender))?;
|
||||
receiver.await?
|
||||
}
|
||||
|
||||
pub async fn set_music_library_path(&self, path: PathBuf) -> Result<()> {
|
||||
self.music_library_path.replace(Some(path.clone()));
|
||||
self.set_state(BackendState::Loading);
|
||||
|
|
@ -369,6 +385,16 @@ impl Backend {
|
|||
.send(db.get_recordings_for_work(id))
|
||||
.expect("Failed to send result from database thread!");
|
||||
}
|
||||
AddTracks(recording_id, tracks, sender) => {
|
||||
sender
|
||||
.send(db.add_tracks(recording_id, tracks))
|
||||
.expect("Failed to send result from database thread!");
|
||||
}
|
||||
GetTracks(recording_id, sender) => {
|
||||
sender
|
||||
.send(db.get_tracks(recording_id))
|
||||
.expect("Failed to send result from database thread!");
|
||||
}
|
||||
Stop => {
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use super::schema::*;
|
|||
use super::tables::*;
|
||||
use anyhow::{anyhow, Error, Result};
|
||||
use diesel::prelude::*;
|
||||
use std::convert::TryInto;
|
||||
|
||||
embed_migrations!();
|
||||
|
||||
|
|
@ -399,6 +400,38 @@ impl Database {
|
|||
Ok(recordings)
|
||||
}
|
||||
|
||||
pub fn add_tracks(&self, recording_id: i64, tracks: Vec<TrackDescription>) -> Result<()> {
|
||||
for (index, track_description) in tracks.iter().enumerate() {
|
||||
let track = Track {
|
||||
id: rand::random(),
|
||||
file_name: track_description.file_name.clone(),
|
||||
recording: recording_id,
|
||||
track_index: index.try_into().unwrap(),
|
||||
work_parts: track_description
|
||||
.work_parts
|
||||
.iter()
|
||||
.map(|i| i.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(","),
|
||||
};
|
||||
|
||||
diesel::insert_into(tracks::table)
|
||||
.values(track)
|
||||
.execute(&self.c)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_tracks(&self, recording_id: i64) -> Result<Vec<TrackDescription>> {
|
||||
let tracks = tracks::table
|
||||
.filter(tracks::recording.eq(recording_id))
|
||||
.order_by(tracks::track_index)
|
||||
.load::<Track>(&self.c)?;
|
||||
|
||||
Ok(tracks.iter().map(|track| track.clone().into()).collect())
|
||||
}
|
||||
|
||||
fn defer_foreign_keys(&self) {
|
||||
diesel::sql_query("PRAGMA defer_foreign_keys = ON;")
|
||||
.execute(&self.c)
|
||||
|
|
|
|||
|
|
@ -183,7 +183,21 @@ impl From<RecordingDescription> for RecordingInsertion {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Track {
|
||||
pub struct TrackDescription {
|
||||
pub work_parts: Vec<usize>,
|
||||
pub file_name: String,
|
||||
}
|
||||
|
||||
impl From<Track> for TrackDescription {
|
||||
fn from(track: Track) -> Self {
|
||||
let mut work_parts = Vec::<usize>::new();
|
||||
for part in track.work_parts.split(",") {
|
||||
work_parts.push(part.parse().unwrap());
|
||||
}
|
||||
|
||||
TrackDescription {
|
||||
work_parts,
|
||||
file_name: track.file_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,16 @@ table! {
|
|||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
tracks (id) {
|
||||
id -> BigInt,
|
||||
file_name -> Text,
|
||||
recording -> BigInt,
|
||||
track_index -> Integer,
|
||||
work_parts -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
work_parts (id) {
|
||||
id -> BigInt,
|
||||
|
|
@ -90,6 +100,7 @@ joinable!(performances -> instruments (role));
|
|||
joinable!(performances -> persons (person));
|
||||
joinable!(performances -> recordings (recording));
|
||||
joinable!(recordings -> works (work));
|
||||
joinable!(tracks -> recordings (recording));
|
||||
joinable!(work_parts -> persons (composer));
|
||||
joinable!(work_parts -> works (work));
|
||||
joinable!(work_sections -> works (work));
|
||||
|
|
@ -103,6 +114,7 @@ allow_tables_to_appear_in_same_query!(
|
|||
performances,
|
||||
persons,
|
||||
recordings,
|
||||
tracks,
|
||||
work_parts,
|
||||
work_sections,
|
||||
works,
|
||||
|
|
|
|||
|
|
@ -83,3 +83,12 @@ pub struct Performance {
|
|||
pub ensemble: Option<i64>,
|
||||
pub role: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Insertable, Queryable, Debug, Clone)]
|
||||
pub struct Track {
|
||||
pub id: i64,
|
||||
pub file_name: String,
|
||||
pub recording: i64,
|
||||
pub track_index: i32,
|
||||
pub work_parts: String,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ pub struct TrackEditor {
|
|||
}
|
||||
|
||||
impl TrackEditor {
|
||||
pub fn new<W, F>(parent: &W, track: Track, work: WorkDescription, callback: F) -> Self
|
||||
pub fn new<W, F>(parent: &W, track: TrackDescription, work: WorkDescription, callback: F) -> Self
|
||||
where
|
||||
W: IsA<gtk::Window>,
|
||||
F: Fn(Track) -> () + 'static,
|
||||
F: Fn(TrackDescription) -> () + 'static,
|
||||
{
|
||||
let builder = gtk::Builder::from_resource("/de/johrpan/musicus_editor/ui/track_editor.ui");
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ impl TrackEditor {
|
|||
let mut work_parts = work_parts.borrow_mut();
|
||||
work_parts.sort();
|
||||
|
||||
callback(Track {
|
||||
callback(TrackDescription {
|
||||
work_parts: work_parts.clone(),
|
||||
file_name: file_name.clone(),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -41,10 +41,10 @@ impl TracksEditor {
|
|||
}));
|
||||
|
||||
let recording = Rc::new(RefCell::new(None::<RecordingDescription>));
|
||||
let tracks = Rc::new(RefCell::new(Vec::<Track>::new()));
|
||||
let tracks = Rc::new(RefCell::new(Vec::<TrackDescription>::new()));
|
||||
|
||||
let track_list = List::new(
|
||||
clone!(@strong recording => move |track: &Track| {
|
||||
clone!(@strong recording => move |track: &TrackDescription| {
|
||||
let mut title_parts = Vec::<String>::new();
|
||||
for part in &track.work_parts {
|
||||
if let Some(recording) = &*recording.borrow() {
|
||||
|
|
@ -122,9 +122,20 @@ impl TracksEditor {
|
|||
}
|
||||
));
|
||||
|
||||
save_button.connect_clicked(clone!(@strong window => move |_| {
|
||||
window.close();
|
||||
callback();
|
||||
let callback = Rc::new(callback);
|
||||
save_button.connect_clicked(clone!(@strong window, @strong backend, @strong recording, @strong tracks, @strong callback => move |_| {
|
||||
let context = glib::MainContext::default();
|
||||
let window = window.clone();
|
||||
let backend = backend.clone();
|
||||
let recording = recording.clone();
|
||||
let tracks = tracks.clone();
|
||||
let callback = callback.clone();
|
||||
context.spawn_local(async move {
|
||||
backend.add_tracks(recording.borrow().as_ref().unwrap().id, tracks.borrow().clone()).await.unwrap();
|
||||
callback();
|
||||
window.close();
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
add_track_button.connect_clicked(clone!(@strong window, @strong tracks, @strong track_list, @strong autofill_parts => move |_| {
|
||||
|
|
@ -144,7 +155,7 @@ impl TracksEditor {
|
|||
let mut tracks = tracks.borrow_mut();
|
||||
for file_name in dialog.get_filenames() {
|
||||
let file_name = file_name.strip_prefix(&music_library_path).unwrap();
|
||||
tracks.insert(index, Track {
|
||||
tracks.insert(index, TrackDescription {
|
||||
work_parts: Vec::new(),
|
||||
file_name: String::from(file_name.to_str().unwrap()),
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue