mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
This commit is contained in:
parent
b0ef0cfd21
commit
fa73821a0b
29 changed files with 831 additions and 650 deletions
255
crates/device/src/pool/pool_api.rs
Normal file
255
crates/device/src/pool/pool_api.rs
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue