mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-08-28 21:06:56 +02:00
rework command/namespace dispatch
This commit is contained in:
parent
def7a1b210
commit
406aabde6e
15 changed files with 586 additions and 374 deletions
|
|
@ -73,32 +73,32 @@ pub trait HasScene: AsRefOpt<Scene> + AsMutOpt<Scene> {
|
|||
}
|
||||
|
||||
impl<T: HasScene
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Arc<str>>
|
||||
+ for<'a> Namespace<'a, ItemTheme>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Arc<str>>
|
||||
+ Namespace<ItemTheme>
|
||||
> SceneController for T {}
|
||||
|
||||
#[tek_proc::commands(SceneCommand)]
|
||||
pub trait SceneController: HasScene
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Arc<str>>
|
||||
+ for<'a> Namespace<'a, ItemTheme>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Arc<str>>
|
||||
+ Namespace<ItemTheme>
|
||||
{
|
||||
#[command(SetSize = "scene/size")]
|
||||
fn scene_set_size (&mut self, size: usize) -> Perhaps<SceneCommand>
|
||||
where Self: for<'a> Namespace<'a, usize>
|
||||
where Self: Namespace<usize>
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
#[command(SetZoom = "scene/zoom")]
|
||||
fn scene_set_zoom (&mut self, size: usize) -> Perhaps<SceneCommand>
|
||||
where Self: for<'a> Namespace<'a, usize>
|
||||
where Self: Namespace<usize>
|
||||
{
|
||||
todo!()
|
||||
}
|
||||
#[command(SetName = "scene/name")]
|
||||
fn scene_set_name (&mut self, name: Arc<str>) -> Perhaps<SceneCommand>
|
||||
where Self: for<'a> Namespace<'a, Arc<str>>
|
||||
where Self: Namespace<Arc<str>>
|
||||
{
|
||||
Ok(self.scene_mut().map(|scene|swap_value(
|
||||
&mut scene.name,
|
||||
|
|
@ -108,7 +108,7 @@ pub trait SceneController: HasScene
|
|||
}
|
||||
#[command(SetColor = "scene/color")]
|
||||
fn scene_set_color (&mut self, color: ItemTheme) -> Perhaps<SceneCommand>
|
||||
where Self: for<'a> Namespace<'a, ItemTheme>
|
||||
where Self: Namespace<ItemTheme>
|
||||
{
|
||||
Ok(self.scene_mut().map(|scene|swap_value(
|
||||
&mut scene.color,
|
||||
|
|
@ -172,16 +172,16 @@ pub trait HasScenes: AsRef<Vec<Scene>> + AsMut<Vec<Scene>> {
|
|||
}
|
||||
|
||||
impl<T: HasScenes
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Option<ItemTheme>>
|
||||
+ for<'a> Namespace<'a, Option<Arc<str>>>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Option<ItemTheme>>
|
||||
+ Namespace<Option<Arc<str>>>
|
||||
> ScenesController for T {}
|
||||
|
||||
#[tek_proc::commands(ScenesCommand)]
|
||||
pub trait ScenesController: HasScenes
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Option<ItemTheme>>
|
||||
+ for<'a> Namespace<'a, Option<Arc<str>>>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Option<ItemTheme>>
|
||||
+ Namespace<Option<Arc<str>>>
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,18 +85,18 @@ pub trait HasTrack: AsRefOpt<Track> + AsMutOpt<Track> {
|
|||
}
|
||||
|
||||
impl<T: HasTrack
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Arc<str>>
|
||||
+ for<'a> Namespace<'a, ItemTheme>
|
||||
+ for<'a> Namespace<'a, Option<bool>>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Arc<str>>
|
||||
+ Namespace<ItemTheme>
|
||||
+ Namespace<Option<bool>>
|
||||
> TrackController for T {}
|
||||
|
||||
#[tek_proc::commands(TrackCommand)]
|
||||
pub trait TrackController: HasTrack
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Arc<str>>
|
||||
+ for<'a> Namespace<'a, ItemTheme>
|
||||
+ for<'a> Namespace<'a, Option<bool>>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Arc<str>>
|
||||
+ Namespace<ItemTheme>
|
||||
+ Namespace<Option<bool>>
|
||||
{
|
||||
#[command(Stop = "track/stop")]
|
||||
fn track_stop (&mut self) -> Perhaps<TrackCommand> {
|
||||
|
|
@ -259,27 +259,31 @@ pub trait HasTracks: AsRef<Vec<Track>> + AsMut<Vec<Track>> + HasClock + HasTrack
|
|||
}
|
||||
|
||||
impl<T: HasTracks
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Arc<[Connect]>>
|
||||
+ for<'a> Namespace<'a, Option<usize>>
|
||||
+ for<'a> Namespace<'a, Option<Arc<str>>>
|
||||
+ for<'a> Namespace<'a, Option<ItemTheme>>
|
||||
+ for<'a> Namespace<'a, Option<Arc<[Connect]>>>
|
||||
+ for<'a> Namespace<'a, Option<Vec<Option<Arc<RwLock<MidiClip>>>>>>
|
||||
+ HasScenes
|
||||
+ HasJack<'static>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Arc<[Connect]>>
|
||||
+ Namespace<Option<usize>>
|
||||
+ Namespace<Option<Arc<str>>>
|
||||
+ Namespace<Option<ItemTheme>>
|
||||
+ Namespace<Option<Arc<[Connect]>>>
|
||||
+ Namespace<Option<Vec<Option<Arc<RwLock<MidiClip>>>>>>
|
||||
> TracksController for T {}
|
||||
|
||||
#[tek_proc::commands(TracksCommand)]
|
||||
pub trait TracksController: HasTracks
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Arc<[Connect]>>
|
||||
+ for<'a> Namespace<'a, Option<usize>>
|
||||
+ for<'a> Namespace<'a, Option<Arc<str>>>
|
||||
+ for<'a> Namespace<'a, Option<ItemTheme>>
|
||||
+ for<'a> Namespace<'a, Option<Arc<[Connect]>>>
|
||||
+ for<'a> Namespace<'a, Option<Vec<Option<Arc<RwLock<MidiClip>>>>>>
|
||||
+ HasScenes
|
||||
+ HasJack<'static>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Arc<[Connect]>>
|
||||
+ Namespace<Option<usize>>
|
||||
+ Namespace<Option<Arc<str>>>
|
||||
+ Namespace<Option<ItemTheme>>
|
||||
+ Namespace<Option<Arc<[Connect]>>>
|
||||
+ Namespace<Option<Vec<Option<Arc<RwLock<MidiClip>>>>>>
|
||||
{
|
||||
|
||||
#[command(Stop = "tracks/stop")]
|
||||
#[command(Stop = "stop")]
|
||||
/// Stop all playing clips
|
||||
fn tracks_stop_all (&mut self) -> Perhaps<TracksCommand> {
|
||||
for track in self.tracks_mut().iter_mut() {
|
||||
|
|
@ -288,7 +292,7 @@ pub trait TracksController: HasTracks
|
|||
Ok(None)
|
||||
}
|
||||
|
||||
#[command(Launch = "tracks/launch")]
|
||||
#[command(Launch = "launch")]
|
||||
/// Launch multiple clips
|
||||
fn tracks_launch (
|
||||
&mut self, clips: Option<Vec<Option<Arc<RwLock<MidiClip>>>>>
|
||||
|
|
@ -304,6 +308,14 @@ pub trait TracksController: HasTracks
|
|||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[command(Add = "add")]
|
||||
fn tracks_add (&mut self) -> Perhaps<TracksCommand>
|
||||
where Self: HasScenes + HasJack<'static>
|
||||
{
|
||||
let (index, _) = self.tracks_add_one(None, None, [].into(), [].into())?;
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
|
|
|
|||
|
|
@ -11,11 +11,17 @@ impl App {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T:
|
||||
Namespace<usize> +
|
||||
Namespace<PathBuf> +
|
||||
Namespace<Arc<str>>
|
||||
> BrowseController for T {}
|
||||
|
||||
#[tek_proc::commands(BrowseCommand = "browse")]
|
||||
pub trait BrowseController:
|
||||
for<'a> Namespace<'a, usize> +
|
||||
for<'a> Namespace<'a, PathBuf> +
|
||||
for<'a> Namespace<'a, Arc<str>>
|
||||
Namespace<usize> +
|
||||
Namespace<PathBuf> +
|
||||
Namespace<Arc<str>>
|
||||
{
|
||||
/// Toggle visibility of browser
|
||||
#[command(Show = "show")]
|
||||
|
|
|
|||
|
|
@ -66,16 +66,16 @@ pub trait HasClock: AsRef<Clock> + AsMut<Clock> {
|
|||
}
|
||||
|
||||
impl<T: HasClock
|
||||
+ for<'a> Namespace<'a, u32>
|
||||
+ for<'a> Namespace<'a, f64>
|
||||
+ for<'a> Namespace<'a, Option<u32>>
|
||||
+ Namespace<u32>
|
||||
+ Namespace<f64>
|
||||
+ Namespace<Option<u32>>
|
||||
> ClockController for T {}
|
||||
|
||||
#[tek_proc::commands(ClockCommand = "clock")]
|
||||
pub trait ClockController: HasClock
|
||||
+ for<'a> Namespace<'a, u32>
|
||||
+ for<'a> Namespace<'a, f64>
|
||||
+ for<'a> Namespace<'a, Option<u32>>
|
||||
+ Namespace<u32>
|
||||
+ Namespace<f64>
|
||||
+ Namespace<Option<u32>>
|
||||
{
|
||||
#[command(SeekUsec = "usec")]
|
||||
fn seek_usec (&mut self, usec: f64) -> Perhaps<ClockCommand> {
|
||||
|
|
@ -468,3 +468,58 @@ impl_time_unit!(Ppq);
|
|||
impl_time_unit!(Pulse);
|
||||
impl_time_unit!(Bpm);
|
||||
impl_time_unit!(LaunchSync);
|
||||
|
||||
/// ```
|
||||
/// let x = "";
|
||||
/// let _ = tek::view_transport(true, x.as_ref(), x.as_ref(), x.as_ref());
|
||||
/// let _ = tek::view_transport(false, x.as_ref(), x.as_ref(), x.as_ref());
|
||||
/// ```
|
||||
pub fn view_transport (play: bool, bpm: &str, beat: &str, time: &str) -> impl Draw<Tui> {
|
||||
let theme = ItemTheme::G[96];
|
||||
bg(Black, east!(above(
|
||||
button_play_pause(play, false).align_w(),
|
||||
east!(
|
||||
field_h(theme, "BPM", bpm),
|
||||
field_h(theme, "Beat", beat),
|
||||
field_h(theme, "Time", time),
|
||||
).align_e().full_wh()
|
||||
)))
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// let x = "";
|
||||
/// let _ = tek::view_status(None, x.as_ref(), x.as_ref(), x.as_ref());
|
||||
/// let _ = tek::view_status(Some("".into()), x.as_ref(), x.as_ref(), x.as_ref());
|
||||
/// ```
|
||||
pub fn view_status (sel: Option<&str>, sr: &str, buf: &str, lat: &str) -> impl Draw<Tui> {
|
||||
let theme = ItemTheme::G[96];
|
||||
let sr = field_h(theme, "SR", sr);
|
||||
let buf = field_h(theme, "Buf", buf);
|
||||
let lat = field_h(theme, "Lat", lat);
|
||||
bg(Black, east!(above(
|
||||
sel.map(|sel|field_h(theme, "Selected", sel)).align_w().full_wh(),
|
||||
east!(sr, buf, lat).align_e().full_wh(),
|
||||
)))
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// let _ = tek::button_play_pause(true, true);
|
||||
/// let _ = tek::button_play_pause(true, false);
|
||||
/// let _ = tek::button_play_pause(false, true);
|
||||
/// let _ = tek::button_play_pause(false, false);
|
||||
/// ```
|
||||
pub fn button_play_pause (playing: bool, compact: bool) -> impl Draw<Tui> {
|
||||
bg(if playing { Rgb(0, 128, 0) } else { Rgb(128, 64, 0) },
|
||||
either(compact,
|
||||
draw(move|to: &mut Tui|either(playing,
|
||||
fg(Rgb(0, 255, 0), " PLAYING "),
|
||||
fg(Rgb(255, 128, 0), " STOPPED "),
|
||||
).exact_w(9).draw(to)),
|
||||
draw(move|to: &mut Tui|either(playing,
|
||||
fg(Rgb(0, 255, 0), south(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
|
||||
fg(Rgb(255, 128, 0), south(" ▗▄▖ ", " ▝▀▘ ",)),
|
||||
).exact_w(5).draw(to)),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,22 +67,22 @@ pub trait HasEditor: AsRefOpt<MidiEditor> + AsMutOpt<MidiEditor> {
|
|||
impl<T: AsRefOpt<MidiEditor>+AsMutOpt<MidiEditor>> HasEditor for T {}
|
||||
|
||||
impl<T: HasEditor
|
||||
+ for<'a> Namespace<'a, u32>
|
||||
+ for<'a> Namespace<'a, f64>
|
||||
+ for<'a> Namespace<'a, bool>
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Option<u32>>
|
||||
+ for<'a> Namespace<'a, Option<Arc<RwLock<MidiClip>>>>
|
||||
+ Namespace<u32>
|
||||
+ Namespace<f64>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Option<u32>>
|
||||
+ Namespace<Option<Arc<RwLock<MidiClip>>>>
|
||||
> MidiEditController for T {}
|
||||
|
||||
#[tek_proc::commands(MidiEditCommand = "edit")]
|
||||
pub trait MidiEditController: HasEditor
|
||||
+ for<'a> Namespace<'a, u32>
|
||||
+ for<'a> Namespace<'a, f64>
|
||||
+ for<'a> Namespace<'a, bool>
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Option<u32>>
|
||||
+ for<'a> Namespace<'a, Option<Arc<RwLock<MidiClip>>>>
|
||||
+ Namespace<u32>
|
||||
+ Namespace<f64>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Option<u32>>
|
||||
+ Namespace<Option<Arc<RwLock<MidiClip>>>>
|
||||
{
|
||||
#[command(Show = "show")]
|
||||
fn show (&mut self, clip: Option<Arc<RwLock<MidiClip>>>) -> Perhaps<MidiEditCommand> {
|
||||
|
|
|
|||
|
|
@ -70,28 +70,24 @@ pub trait HasPool: AsRef<Pool> + AsMut<Pool> {
|
|||
}
|
||||
|
||||
impl<T: HasPool
|
||||
+ for<'a> Namespace<'a, bool>
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Arc<str>>
|
||||
+ for<'a> Namespace<'a, PathBuf>
|
||||
+ for<'a> Namespace<'a, MidiClip>
|
||||
+ for<'a> Namespace<'a, ItemColor>
|
||||
+ for<'a> Namespace<'a, PoolCommand>
|
||||
+ for<'a> Namespace<'a, PoolCommand>
|
||||
+ for<'a> Namespace<'a, BrowseCommand>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Arc<str>>
|
||||
+ Namespace<PathBuf>
|
||||
+ Namespace<MidiClip>
|
||||
+ Namespace<ItemColor>
|
||||
+ Namespace<BrowseCommand>
|
||||
> PoolController for T {}
|
||||
|
||||
#[tek_proc::commands(PoolCommand = "pool")]
|
||||
pub trait PoolController: HasPool
|
||||
+ for<'a> Namespace<'a, bool>
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ for<'a> Namespace<'a, Arc<str>>
|
||||
+ for<'a> Namespace<'a, PathBuf>
|
||||
+ for<'a> Namespace<'a, MidiClip>
|
||||
+ for<'a> Namespace<'a, ItemColor>
|
||||
+ for<'a> Namespace<'a, PoolCommand>
|
||||
+ for<'a> Namespace<'a, PoolCommand>
|
||||
+ for<'a> Namespace<'a, BrowseCommand>
|
||||
+ Namespace<bool>
|
||||
+ Namespace<usize>
|
||||
+ Namespace<Arc<str>>
|
||||
+ Namespace<PathBuf>
|
||||
+ Namespace<MidiClip>
|
||||
+ Namespace<ItemColor>
|
||||
+ Namespace<BrowseCommand>
|
||||
{
|
||||
|
||||
#[command(Show = "show")]
|
||||
|
|
@ -139,7 +135,7 @@ pub trait PoolController: HasPool
|
|||
for event in events.iter() {
|
||||
clip.notes[event.0 as usize].push(event.2);
|
||||
}
|
||||
Ok(PoolCommand::Add { index, clip }.act(self)?)
|
||||
Ok(PoolCommand::Add { index, clip }.dispatch(self)?)
|
||||
}
|
||||
|
||||
///// Export to file
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ impl<T: AsRef<Sampler> + AsMut<Sampler>> HasSampler for T {}
|
|||
|
||||
#[tek_proc::commands(SamplerCommand = "sampler")]
|
||||
pub trait SamplerController: HasSampler
|
||||
+ for<'a> Namespace<'a, usize>
|
||||
+ Namespace<usize>
|
||||
{
|
||||
|
||||
#[command(RecordToggle = "rec-toggle")]
|
||||
|
|
@ -30,10 +30,10 @@ pub trait SamplerController: HasSampler
|
|||
{
|
||||
let sampler = self.sampler_mut();
|
||||
let recording = sampler.recording.as_ref().map(|x|x.0);
|
||||
let _ = SamplerCommand::RecordFinish.act(self)?;
|
||||
let _ = SamplerCommand::RecordFinish.dispatch(self)?;
|
||||
// autoslice: continue recording at next slot
|
||||
if recording != Some(slot) {
|
||||
SamplerCommand::RecordBegin { slot }.act(self)
|
||||
SamplerCommand::RecordBegin { slot }.dispatch(self)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,15 +245,21 @@ pub trait HasMidiClip {
|
|||
fn clip (&self) -> Option<Arc<RwLock<MidiClip>>>;
|
||||
}
|
||||
|
||||
impl HasMidiClip for App {
|
||||
fn clip (&self) -> Option<Arc<RwLock<MidiClip>>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: HasMidiClip
|
||||
+ for<'a> Namespace<'a, Option<bool>>
|
||||
+ for<'a> Namespace<'a, Option<ItemTheme>>
|
||||
+ Namespace<Option<bool>>
|
||||
+ Namespace<Option<ItemTheme>>
|
||||
> MidiClipController for T {}
|
||||
|
||||
#[tek_proc::commands(MidiClipCommand)]
|
||||
pub trait MidiClipController: HasMidiClip
|
||||
+ for<'a> Namespace<'a, Option<bool>>
|
||||
+ for<'a> Namespace<'a, Option<ItemTheme>>
|
||||
+ Namespace<Option<bool>>
|
||||
+ Namespace<Option<ItemTheme>>
|
||||
{
|
||||
|
||||
#[command(SetColor = "clip/color")]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue