diff --git a/Cargo.toml b/Cargo.toml index cb740a2..e03733c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ wmidi = "4.0.8" # rodio = { git = "https://github.com/PetrGlad/rodio.git", branch = "configurable-buffer-size" } # https://docs.rs/alsa/latest/alsa/ +# apt install libasound2-dev # alsa = "0.8.1" # see also https://github.com/RustAudio/cpal diff --git a/README.md b/README.md index f0a58f5..adadd42 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,8 @@ revamps. In case you get "No package 'freetype2' found" on Linux `apt install libxft-dev`. -ALSA wrapper dependency -`apt install libasound2-dev`. - As an VST synth plugin you can use `amsynth`, for example. -I personally use Pianoteq, but that is a commercial product. +I use Pianoteq, but that is a commercial product. ## TODO diff --git a/src/stave.rs b/src/stave.rs index f69edfd..38a5cf0 100644 --- a/src/stave.rs +++ b/src/stave.rs @@ -1,9 +1,3 @@ -use std::cell::RefCell; -use std::collections::btree_set::Iter; -use std::collections::{BTreeMap, BTreeSet, HashSet}; -use std::ops::Range; -use std::path::PathBuf; - use eframe::egui::{ self, Color32, Context, Frame, Margin, Modifiers, Painter, PointerButton, Pos2, Rangef, Rect, Rounding, Sense, Stroke, Ui, @@ -11,6 +5,11 @@ use eframe::egui::{ use egui::Rgba; use ordered_float::OrderedFloat; use serde::{Deserialize, Serialize}; +use std::cell::RefCell; +use std::collections::{BTreeMap, HashSet}; +use std::ops::Range; +use std::path::PathBuf; +use std::slice::Iter; use crate::changeset::{Changeset, EventActionsList}; use crate::common::Time; @@ -23,7 +22,7 @@ use crate::track_edit::{ stretch_selected_notes, tape_delete, tape_insert, transpose_selected_notes, AppliedCommand, EditCommandId, }; -use crate::track_history::TrackHistory; +use crate::track_history::{CommandApplication, TrackHistory}; use crate::{util, Pix}; // Tone 60 is C3, tones start at C-2 (21). @@ -86,27 +85,43 @@ pub struct Bookmark { #[derive(Debug, Deserialize, Serialize)] pub struct Bookmarks { - // Maybe bookmarks should also be events in the track. - pub list: BTreeSet, + // (refactoring) Maybe bookmarks should also be events in the track. The logic is about the same. + pub list: Vec, file_path: PathBuf, } impl Bookmarks { pub fn new(file_path: &PathBuf) -> Bookmarks { Bookmarks { - list: BTreeSet::default(), + list: vec![], file_path: file_path.to_owned(), } } pub fn set(&mut self, at: Time) { - self.list.insert(Bookmark { at }); - self.store_to(&self.file_path); + let bm = Bookmark { at }; + let idx = self.list.binary_search(&bm); + if let Err(idx) = idx { + self.list.insert(idx, bm); + self.store_to(&self.file_path); + } } pub fn remove(&mut self, at: &Time) { - self.list.remove(&Bookmark { at: *at }); - self.store_to(&self.file_path); + let bm = Bookmark { at: at.clone() }; + let idx = self.list.binary_search(&bm); + if let Ok(idx) = idx { + self.list.remove(idx); + self.store_to(&self.file_path); + } + } + + pub fn shift(&mut self, after: Time, delta: Time) { + for m in self.list.iter_mut() { + if m.at >= after { + m.at += delta; + } + } } pub fn previous(&self, here: &Time) -> Option