mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
255 lines
8.3 KiB
Rust
255 lines
8.3 KiB
Rust
use crate::*;
|
|
|
|
#[tengri_proc::expose]
|
|
impl Pool {
|
|
fn _todo_usize_ (&self) -> usize { todo!() }
|
|
fn _todo_bool_ (&self) -> bool { todo!() }
|
|
fn _todo_clip_ (&self) -> MidiClip { todo!() }
|
|
fn _todo_path_ (&self) -> PathBuf { todo!() }
|
|
fn _todo_color_ (&self) -> ItemColor { todo!() }
|
|
fn _todo_str_ (&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(Pool)]
|
|
impl PoolCommand {
|
|
|
|
/// Toggle visibility of pool
|
|
fn show (pool: &mut Pool, visible: bool) -> Perhaps<Self> {
|
|
pool.visible = visible;
|
|
Ok(Some(Self::Show { visible: !visible }))
|
|
}
|
|
|
|
/// Select a clip from the clip pool
|
|
fn select (pool: &mut Pool, index: usize) -> Perhaps<Self> {
|
|
pool.set_clip_index(index);
|
|
Ok(None)
|
|
}
|
|
|
|
/// Rename a clip
|
|
fn rename (pool: &mut Pool, command: RenameCommand) -> Perhaps<Self> {
|
|
Ok(command.delegate(pool, |command|Self::Rename{command})?)
|
|
}
|
|
|
|
/// Change the length of a clip
|
|
fn length (pool: &mut Pool, command: CropCommand) -> Perhaps<Self> {
|
|
Ok(command.delegate(pool, |command|Self::Length{command})?)
|
|
}
|
|
|
|
/// Import from file
|
|
fn import (pool: &mut Pool, command: BrowserCommand) -> Perhaps<Self> {
|
|
Ok(if let Some(browser) = pool.browser.as_mut() {
|
|
command.delegate(browser, |command|Self::Import{command})?
|
|
} else {
|
|
None
|
|
})
|
|
}
|
|
|
|
/// Export to file
|
|
fn export (pool: &mut Pool, command: BrowserCommand) -> Perhaps<Self> {
|
|
Ok(if let Some(browser) = pool.browser.as_mut() {
|
|
command.delegate(browser, |command|Self::Export{command})?
|
|
} else {
|
|
None
|
|
})
|
|
}
|
|
|
|
/// Update the contents of the clip pool
|
|
fn clip (pool: &mut Pool, command: PoolClipCommand) -> Perhaps<Self> {
|
|
Ok(command.execute(pool)?.map(|command|Self::Clip{command}))
|
|
}
|
|
|
|
}
|
|
|
|
impl<'state> Context<'state, BrowserCommand> for Pool {
|
|
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<BrowserCommand> {
|
|
self.browser.as_ref().map(|p|Context::get(p, iter)).flatten()
|
|
}
|
|
}
|
|
|
|
#[tengri_proc::command(Pool)]
|
|
impl PoolClipCommand {
|
|
|
|
fn add (pool: &mut Pool, 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 Pool, index: usize) -> Perhaps<Self> {
|
|
let clip = pool.clips_mut().remove(index).read().unwrap().clone();
|
|
Ok(Some(Self::Add { index, clip }))
|
|
}
|
|
|
|
fn swap (pool: &mut Pool, index: usize, other: usize) -> Perhaps<Self> {
|
|
pool.clips_mut().swap(index, other);
|
|
Ok(Some(Self::Swap { index, other }))
|
|
}
|
|
|
|
fn import (pool: &mut Pool, 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 Pool, index: usize, path: PathBuf) -> Perhaps<Self> {
|
|
todo!("export clip to midi file");
|
|
}
|
|
|
|
fn set_name (pool: &mut Pool, 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 Pool, 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 Pool, 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(Pool)]
|
|
impl RenameCommand {
|
|
fn begin (pool: &mut Pool) -> Perhaps<Self> {
|
|
unreachable!();
|
|
}
|
|
fn cancel (pool: &mut Pool) -> 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 Pool) -> 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 Pool, 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(Pool)]
|
|
impl CropCommand {
|
|
fn begin (pool: &mut Pool) -> Perhaps<Self> {
|
|
unreachable!()
|
|
}
|
|
fn cancel (pool: &mut Pool) -> Perhaps<Self> {
|
|
if let Some(PoolMode::Length(..)) = pool.mode_mut().clone() {
|
|
*pool.mode_mut() = None;
|
|
}
|
|
Ok(None)
|
|
}
|
|
fn set (pool: &mut Pool, 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 Pool) -> 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 Pool) -> 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 Pool) -> 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 Pool) -> 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)
|
|
}
|
|
}
|