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 { 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 { pool.visible = visible; Ok(Some(Self::Show { visible: !visible })) } /// Select a clip from the clip pool fn select (pool: &mut Pool, index: usize) -> Perhaps { pool.set_clip_index(index); Ok(None) } /// Rename a clip fn rename (pool: &mut Pool, command: RenameCommand) -> Perhaps { Ok(command.delegate(pool, |command|Self::Rename{command})?) } /// Change the length of a clip fn length (pool: &mut Pool, command: CropCommand) -> Perhaps { Ok(command.delegate(pool, |command|Self::Length{command})?) } /// Import from file fn import (pool: &mut Pool, command: BrowserCommand) -> Perhaps { 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 { 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 { Ok(command.execute(pool)?.map(|command|Self::Clip{command})) } } #[tengri_proc::command(Pool)] impl PoolClipCommand { fn add (pool: &mut Pool, index: usize, clip: MidiClip) -> Perhaps { 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 { 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 { pool.clips_mut().swap(index, other); Ok(Some(Self::Swap { index, other })) } fn import (pool: &mut Pool, index: usize, path: PathBuf) -> Perhaps { 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 { todo!("export clip to midi file"); } fn set_name (pool: &mut Pool, index: usize, name: Arc) -> Perhaps { 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 { 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 { 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 { unreachable!(); } fn cancel (pool: &mut Pool) -> Perhaps { 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 { 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) -> Perhaps { 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 { unreachable!() } fn cancel (pool: &mut Pool) -> Perhaps { if let Some(PoolMode::Length(..)) = pool.mode_mut().clone() { *pool.mode_mut() = None; } Ok(None) } fn set (pool: &mut Pool, length: usize) -> Perhaps { 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 { 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 { 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 { 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 { 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) } }