mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-09 05:06:43 +01:00
This commit is contained in:
parent
b0ef0cfd21
commit
fa73821a0b
29 changed files with 831 additions and 650 deletions
|
|
@ -184,44 +184,15 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm
|
|||
}
|
||||
}
|
||||
|
||||
#[tengri_proc::expose] impl MidiPool {
|
||||
fn _todo_bool_stub (&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
fn _todo_path_buf_stub (&self) -> PathBuf {
|
||||
todo!()
|
||||
}
|
||||
fn _todo_arc_str_stub (&self) -> Arc<str> {
|
||||
todo!()
|
||||
}
|
||||
fn clip_new (&self) -> MidiClip {
|
||||
self.new_clip()
|
||||
}
|
||||
fn clip_cloned (&self) -> MidiClip {
|
||||
self.cloned_clip()
|
||||
}
|
||||
fn clip_index_current (&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn clip_index_after (&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn clip_index_previous (&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn clip_index_next (&self) -> usize {
|
||||
0
|
||||
}
|
||||
fn color_random (&self) -> ItemColor {
|
||||
ItemColor::random()
|
||||
}
|
||||
}
|
||||
|
||||
#[tengri_proc::command(App)] impl AppCommand {
|
||||
fn toggle_dialog (app: &mut App, dialog: Dialog) -> Perhaps<Self> {
|
||||
app.toggle_dialog(Some(dialog));
|
||||
Ok(None)
|
||||
}
|
||||
fn cancel_dialog (app: &mut App) -> Perhaps<Self> {
|
||||
app.toggle_dialog(None);
|
||||
Ok(None)
|
||||
}
|
||||
fn toggle_editor (app: &mut App, value: bool) -> Perhaps<Self> {
|
||||
app.toggle_editor(Some(value));
|
||||
Ok(None)
|
||||
|
|
@ -489,275 +460,3 @@ impl<'state> Context<'state, SamplerCommand> for App {
|
|||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[tengri_proc::command(MidiPool)] impl PoolCommand {
|
||||
/// Toggle visibility of pool
|
||||
fn show (pool: &mut MidiPool, visible: bool) -> Perhaps<Self> {
|
||||
pool.visible = visible;
|
||||
Ok(Some(Self::Show { visible: !visible }))
|
||||
}
|
||||
/// Select a clip from the clip pool
|
||||
fn select (pool: &mut MidiPool, index: usize) -> Perhaps<Self> {
|
||||
pool.set_clip_index(index);
|
||||
Ok(None)
|
||||
}
|
||||
/// Rename a clip
|
||||
fn rename (pool: &mut MidiPool, command: ClipRenameCommand) -> Perhaps<Self> {
|
||||
Ok(match command {
|
||||
ClipRenameCommand::Begin => {
|
||||
pool.begin_clip_rename();
|
||||
None
|
||||
},
|
||||
_ => command.delegate(pool, |command|Self::Rename{command})?
|
||||
})
|
||||
}
|
||||
/// Change the length of a clip
|
||||
fn length (pool: &mut MidiPool, command: ClipLengthCommand) -> Perhaps<Self> {
|
||||
Ok(match command {
|
||||
ClipLengthCommand::Begin => {
|
||||
pool.begin_clip_length();
|
||||
None
|
||||
},
|
||||
_ => command.delegate(pool, |command|Self::Length{command})?
|
||||
})
|
||||
}
|
||||
/// Import from file
|
||||
fn import (pool: &mut MidiPool, command: FileBrowserCommand) -> Perhaps<Self> {
|
||||
Ok(match command {
|
||||
FileBrowserCommand::Begin => {
|
||||
pool.begin_import();
|
||||
None
|
||||
},
|
||||
_ => command.delegate(pool, |command|Self::Import{command})?
|
||||
})
|
||||
}
|
||||
/// Export to file
|
||||
fn export (pool: &mut MidiPool, command: FileBrowserCommand) -> Perhaps<Self> {
|
||||
Ok(match command {
|
||||
FileBrowserCommand::Begin => {
|
||||
pool.begin_export();
|
||||
None
|
||||
},
|
||||
_ => command.delegate(pool, |command|Self::Export{command})?
|
||||
})
|
||||
}
|
||||
/// Update the contents of the clip pool
|
||||
fn clip (pool: &mut MidiPool, command: PoolClipCommand) -> Perhaps<Self> {
|
||||
Ok(command.execute(pool)?.map(|command|Self::Clip{command}))
|
||||
}
|
||||
}
|
||||
|
||||
#[tengri_proc::command(MidiPool)] impl PoolClipCommand {
|
||||
fn add (pool: &mut MidiPool, index: usize, clip: MidiClip) -> Perhaps<Self> {
|
||||
let mut index = index;
|
||||
let clip = Arc::new(RwLock::new(clip));
|
||||
let mut clips = pool.clips_mut();
|
||||
if index >= clips.len() {
|
||||
index = clips.len();
|
||||
clips.push(clip)
|
||||
} else {
|
||||
clips.insert(index, clip);
|
||||
}
|
||||
Ok(Some(Self::Delete { index }))
|
||||
}
|
||||
fn delete (pool: &mut MidiPool, index: usize) -> Perhaps<Self> {
|
||||
let clip = pool.clips_mut().remove(index).read().unwrap().clone();
|
||||
Ok(Some(Self::Add { index, clip }))
|
||||
}
|
||||
fn swap (pool: &mut MidiPool, index: usize, other: usize) -> Perhaps<Self> {
|
||||
pool.clips_mut().swap(index, other);
|
||||
Ok(Some(Self::Swap { index, other }))
|
||||
}
|
||||
fn import (pool: &mut MidiPool, index: usize, path: PathBuf) -> Perhaps<Self> {
|
||||
let bytes = std::fs::read(&path)?;
|
||||
let smf = Smf::parse(bytes.as_slice())?;
|
||||
let mut t = 0u32;
|
||||
let mut events = vec![];
|
||||
for track in smf.tracks.iter() {
|
||||
for event in track.iter() {
|
||||
t += event.delta.as_int();
|
||||
if let TrackEventKind::Midi { channel, message } = event.kind {
|
||||
events.push((t, channel.as_int(), message));
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut clip = MidiClip::new("imported", true, t as usize + 1, None, None);
|
||||
for event in events.iter() {
|
||||
clip.notes[event.0 as usize].push(event.2);
|
||||
}
|
||||
Ok(Self::Add { index, clip }.execute(pool)?)
|
||||
}
|
||||
fn export (pool: &mut MidiPool, index: usize, path: PathBuf) -> Perhaps<Self> {
|
||||
todo!("export clip to midi file");
|
||||
}
|
||||
fn set_name (pool: &mut MidiPool, index: usize, name: Arc<str>) -> Perhaps<Self> {
|
||||
let clip = &mut pool.clips_mut()[index];
|
||||
let old_name = clip.read().unwrap().name.clone();
|
||||
clip.write().unwrap().name = name;
|
||||
Ok(Some(Self::SetName { index, name: old_name }))
|
||||
}
|
||||
fn set_length (pool: &mut MidiPool, index: usize, length: usize) -> Perhaps<Self> {
|
||||
let clip = &mut pool.clips_mut()[index];
|
||||
let old_len = clip.read().unwrap().length;
|
||||
clip.write().unwrap().length = length;
|
||||
Ok(Some(Self::SetLength { index, length: old_len }))
|
||||
}
|
||||
fn set_color (pool: &mut MidiPool, index: usize, color: ItemColor) -> Perhaps<Self> {
|
||||
let mut color = ItemTheme::from(color);
|
||||
std::mem::swap(&mut color, &mut pool.clips()[index].write().unwrap().color);
|
||||
Ok(Some(Self::SetColor { index, color: color.base }))
|
||||
}
|
||||
}
|
||||
|
||||
#[tengri_proc::command(MidiPool)] impl ClipRenameCommand {
|
||||
fn begin (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
unreachable!();
|
||||
}
|
||||
fn cancel (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
if let Some(PoolMode::Rename(clip, ref mut old_name)) = pool.mode_mut().clone() {
|
||||
pool.clips()[clip].write().unwrap().name = old_name.clone().into();
|
||||
}
|
||||
return Ok(None)
|
||||
}
|
||||
fn confirm (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
if let Some(PoolMode::Rename(clip, ref mut old_name)) = pool.mode_mut().clone() {
|
||||
let old_name = old_name.clone();
|
||||
*pool.mode_mut() = None;
|
||||
return Ok(Some(Self::Set { value: old_name }))
|
||||
}
|
||||
return Ok(None)
|
||||
}
|
||||
fn set (pool: &mut MidiPool, value: Arc<str>) -> Perhaps<Self> {
|
||||
if let Some(PoolMode::Rename(clip, ref mut old_name)) = pool.mode_mut().clone() {
|
||||
pool.clips()[clip].write().unwrap().name = value;
|
||||
}
|
||||
return Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[tengri_proc::command(MidiPool)] impl ClipLengthCommand {
|
||||
fn begin (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
unreachable!()
|
||||
}
|
||||
fn cancel (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
if let Some(PoolMode::Length(..)) = pool.mode_mut().clone() {
|
||||
*pool.mode_mut() = None;
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
fn set (pool: &mut MidiPool, length: usize) -> Perhaps<Self> {
|
||||
if let Some(PoolMode::Length(clip, ref mut length, ref mut focus))
|
||||
= pool.mode_mut().clone()
|
||||
{
|
||||
let old_length;
|
||||
{
|
||||
let clip = pool.clips()[clip].clone();//.write().unwrap();
|
||||
old_length = Some(clip.read().unwrap().length);
|
||||
clip.write().unwrap().length = *length;
|
||||
}
|
||||
*pool.mode_mut() = None;
|
||||
return Ok(old_length.map(|length|Self::Set { length }))
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
fn next (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
if let Some(PoolMode::Length(clip, ref mut length, ref mut focus))
|
||||
= pool.mode_mut().clone()
|
||||
{
|
||||
focus.next()
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
fn prev (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
if let Some(PoolMode::Length(clip, ref mut length, ref mut focus))
|
||||
= pool.mode_mut().clone()
|
||||
{
|
||||
focus.prev()
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
fn inc (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
if let Some(PoolMode::Length(clip, ref mut length, ref mut focus))
|
||||
= pool.mode_mut().clone()
|
||||
{
|
||||
match focus {
|
||||
ClipLengthFocus::Bar => { *length += 4 * PPQ },
|
||||
ClipLengthFocus::Beat => { *length += PPQ },
|
||||
ClipLengthFocus::Tick => { *length += 1 },
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
fn dec (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
if let Some(PoolMode::Length(clip, ref mut length, ref mut focus))
|
||||
= pool.mode_mut().clone()
|
||||
{
|
||||
match focus {
|
||||
ClipLengthFocus::Bar => { *length = length.saturating_sub(4 * PPQ) },
|
||||
ClipLengthFocus::Beat => { *length = length.saturating_sub(PPQ) },
|
||||
ClipLengthFocus::Tick => { *length = length.saturating_sub(1) },
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[tengri_proc::command(MidiPool)] impl FileBrowserCommand {
|
||||
fn begin (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
unreachable!();
|
||||
}
|
||||
fn cancel (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
pool.mode = None;
|
||||
Ok(None)
|
||||
}
|
||||
fn confirm (pool: &mut MidiPool) -> Perhaps<Self> {
|
||||
Ok(match pool.mode {
|
||||
Some(PoolMode::Import(index, ref mut browser)) => {
|
||||
if browser.is_file() {
|
||||
let path = browser.path();
|
||||
pool.mode = None;
|
||||
let _undo = PoolClipCommand::import(pool, index, path)?;
|
||||
None
|
||||
} else if browser.is_dir() {
|
||||
pool.mode = Some(PoolMode::Import(index, browser.chdir()?));
|
||||
None
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
Some(PoolMode::Export(index, ref mut browser)) => {
|
||||
todo!()
|
||||
},
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
fn select (pool: &mut MidiPool, index: usize) -> Perhaps<Self> {
|
||||
Ok(match pool.mode {
|
||||
Some(PoolMode::Import(index, ref mut browser)) => {
|
||||
browser.index = index;
|
||||
None
|
||||
},
|
||||
Some(PoolMode::Export(index, ref mut browser)) => {
|
||||
browser.index = index;
|
||||
None
|
||||
},
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
fn chdir (pool: &mut MidiPool, dir: PathBuf) -> Perhaps<Self> {
|
||||
Ok(match pool.mode {
|
||||
Some(PoolMode::Import(index, ref mut browser)) => {
|
||||
pool.mode = Some(PoolMode::Import(index, FileBrowser::new(Some(dir))?));
|
||||
None
|
||||
},
|
||||
Some(PoolMode::Export(index, ref mut browser)) => {
|
||||
pool.mode = Some(PoolMode::Export(index, FileBrowser::new(Some(dir))?));
|
||||
None
|
||||
},
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
fn filter (pool: &mut MidiPool, filter: Arc<str>) -> Perhaps<Self> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue