mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
wip: bringing it back from the dead once again
Some checks are pending
/ build (push) Waiting to run
Some checks are pending
/ build (push) Waiting to run
This commit is contained in:
parent
45dc05acd6
commit
71c519b711
10 changed files with 530 additions and 371 deletions
603
Cargo.lock
generated
603
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -47,7 +47,7 @@ palette = { version = "0.7.6", features = [ "random" ] }
|
||||||
quanta = { version = "0.12.3" }
|
quanta = { version = "0.12.3" }
|
||||||
rand = { version = "0.8.5" }
|
rand = { version = "0.8.5" }
|
||||||
symphonia = { version = "0.5.4", features = [ "all" ] }
|
symphonia = { version = "0.5.4", features = [ "all" ] }
|
||||||
toml = { version = "0.8.12" }
|
toml = { version = "0.9.2" }
|
||||||
uuid = { version = "1.10.0", features = [ "v4" ] }
|
uuid = { version = "1.10.0", features = [ "v4" ] }
|
||||||
wavers = { version = "1.4.3" }
|
wavers = { version = "1.4.3" }
|
||||||
winit = { version = "0.30.4", features = [ "x11" ] }
|
winit = { version = "0.30.4", features = [ "x11" ] }
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,22 @@
|
||||||
(name "Arranger")
|
(name
|
||||||
|
"Arranger")
|
||||||
(info "A session grid.")
|
(info
|
||||||
|
"A grid of launchable clips arranged by track and scene.")
|
||||||
(keys
|
(keys
|
||||||
(layer-if :focus-editor "./keys_editor.edn")
|
(cond :focus-editor (load "./keys_editor.edn"))
|
||||||
(layer-if :focus-dialog "./keys_dialog.edn")
|
(cond :focus-dialog (load "./keys_dialog.edn"))
|
||||||
(layer-if :focus-message "./keys_message.edn")
|
(cond :focus-message (load "./keys_message.edn"))
|
||||||
(layer-if :focus-device-add "./keys_device_add.edn")
|
(cond :focus-device-add (load "./keys_device_add.edn"))
|
||||||
(layer-if :focus-browser "./keys_browser.edn")
|
(cond :focus-browser (load "./keys_browser.edn"))
|
||||||
(layer-if :focus-pool-rename "./keys_rename.edn")
|
(cond :focus-pool-rename (load "./keys_rename.edn"))
|
||||||
(layer-if :focus-pool-length "./keys_length.edn")
|
(cond :focus-pool-length (load "./keys_length.edn"))
|
||||||
(layer-if :focus-clip "./keys_clip.edn")
|
(cond :focus-clip (load "./keys_clip.edn"))
|
||||||
(layer-if :focus-track "./keys_track.edn")
|
(cond :focus-track (load "./keys_track.edn"))
|
||||||
(layer-if :focus-scene "./keys_scene.edn")
|
(cond :focus-scene (load "./keys_scene.edn"))
|
||||||
(layer-if :focus-mix "./keys_mix.edn")
|
(cond :focus-mix (load "./keys_mix.edn"))
|
||||||
(layer "./keys_clock.edn")
|
(load "./keys_clock.edn")
|
||||||
(layer "./keys_arranger.edn")
|
(load "./keys_arranger.edn")
|
||||||
(layer "./keys_global.edn"))
|
(load "./keys_global.edn"))
|
||||||
|
|
||||||
(view
|
(view
|
||||||
(bsp/a :view-dialog
|
(bsp/a :view-dialog
|
||||||
(bsp/w :view-meters-output
|
(bsp/w :view-meters-output
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ macro_rules! cmd_todo { ($msg:literal) => {{ println!($msg); None }}; }
|
||||||
handle!(TuiIn: |self: App, input|self.handle_tui_key_with_history(input));
|
handle!(TuiIn: |self: App, input|self.handle_tui_key_with_history(input));
|
||||||
impl App {
|
impl App {
|
||||||
fn handle_tui_key_with_history (&mut self, input: &TuiIn) -> Perhaps<bool> {
|
fn handle_tui_key_with_history (&mut self, input: &TuiIn) -> Perhaps<bool> {
|
||||||
Ok(if let Some(command) = self.config.keys.keybind_resolve(self, input)? {
|
Ok(if let Some(command) = self.config.keys.handle(self, input)? {
|
||||||
// FIXME failed commands not persisted in undo history
|
// FIXME failed commands not persisted in undo history
|
||||||
let undo = command.clone().execute(self)?;
|
let undo = command.clone().execute(self)?;
|
||||||
self.history.push((command, undo));
|
self.history.push((command, undo));
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ pub struct App {
|
||||||
/// Performance counter
|
/// Performance counter
|
||||||
pub perf: PerfModel,
|
pub perf: PerfModel,
|
||||||
// View and input definition
|
// View and input definition
|
||||||
pub config: Configuration,
|
pub config: Configuration<Ast>,
|
||||||
/// Contains all recently created clips.
|
/// Contains all recently created clips.
|
||||||
pub pool: Pool,
|
pub pool: Pool,
|
||||||
/// Contains the currently edited musical arrangement
|
/// Contains the currently edited musical arrangement
|
||||||
|
|
@ -42,12 +42,12 @@ maybe_has!(Scene: |self: App|
|
||||||
impl HasSceneScroll for App { fn scene_scroll (&self) -> usize { self.project.scene_scroll() } }
|
impl HasSceneScroll for App { fn scene_scroll (&self) -> usize { self.project.scene_scroll() } }
|
||||||
has_clips!(|self: App|self.pool.clips);
|
has_clips!(|self: App|self.pool.clips);
|
||||||
impl HasClipsSize for App { fn clips_size (&self) -> &Measure<TuiOut> { &self.project.inner_size } }
|
impl HasClipsSize for App { fn clips_size (&self) -> &Measure<TuiOut> { &self.project.inner_size } }
|
||||||
take!(ClockCommand |state: App, iter|Take::take(state.clock(), iter));
|
//take!(ClockCommand |state: App, iter|Take::take(state.clock(), iter));
|
||||||
take!(MidiEditCommand |state: App, iter|Ok(state.editor().map(|x|Take::take(x, iter)).transpose()?.flatten()));
|
//take!(MidiEditCommand |state: App, iter|Ok(state.editor().map(|x|Take::take(x, iter)).transpose()?.flatten()));
|
||||||
take!(PoolCommand |state: App, iter|Take::take(&state.pool, iter));
|
//take!(PoolCommand |state: App, iter|Take::take(&state.pool, iter));
|
||||||
take!(SamplerCommand |state: App, iter|Ok(state.project.sampler().map(|x|Take::take(x, iter)).transpose()?.flatten()));
|
//take!(SamplerCommand |state: App, iter|Ok(state.project.sampler().map(|x|Take::take(x, iter)).transpose()?.flatten()));
|
||||||
take!(ArrangementCommand |state: App, iter|Take::take(&state.project, iter));
|
//take!(ArrangementCommand |state: App, iter|Take::take(&state.project, iter));
|
||||||
take!(DialogCommand |state: App, iter|Take::take(&state.dialog, iter));
|
//take!(DialogCommand |state: App, iter|Take::take(&state.dialog, iter));
|
||||||
//has_editor!(|self: App|{
|
//has_editor!(|self: App|{
|
||||||
//editor = self.editor;
|
//editor = self.editor;
|
||||||
//editor_w = {
|
//editor_w = {
|
||||||
|
|
@ -319,7 +319,7 @@ impl App {
|
||||||
|
|
||||||
/// Configuration
|
/// Configuration
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct Configuration {
|
pub struct Configuration<T: Dsl> {
|
||||||
/// Path of configuration entrypoint
|
/// Path of configuration entrypoint
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
/// Name of configuration
|
/// Name of configuration
|
||||||
|
|
@ -327,149 +327,100 @@ pub struct Configuration {
|
||||||
/// Description of configuration
|
/// Description of configuration
|
||||||
pub info: Option<Arc<str>>,
|
pub info: Option<Arc<str>>,
|
||||||
/// View definition
|
/// View definition
|
||||||
pub view: Cst,
|
pub view: T,
|
||||||
// Input keymap
|
// Input keymap
|
||||||
pub keys: InputMap<App, AppCommand, TuiIn, Cst>,
|
pub keys: EventMap<TuiEvent, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Configuration {
|
impl<T: Dsl> Configuration<T> {
|
||||||
|
pub fn from_path (path: &impl AsRef<Path>, _watch: bool) -> Usually<Self> where T: for<'a> From<&'a str> {
|
||||||
pub fn new (path: &impl AsRef<Path>, _watch: bool) -> Usually<Self> {
|
let mut dsl = T::from(read_and_leak(path.as_ref())?);
|
||||||
let text = read_and_leak(path.as_ref())?;
|
let mut name: Option<T::Exp> = None;
|
||||||
let [name, info, view, keys] = Self::parse(Cst::from(text))?;
|
let mut info: Option<T::Exp> = None;
|
||||||
|
let mut view: Option<T::Exp> = None;
|
||||||
|
let mut keys: Option<T::Exp> = None;
|
||||||
|
dsl.exp_each(|form|Ok(match form.exp_head().dsl() {
|
||||||
|
Val::Key(key) => match key.as_ref() {
|
||||||
|
"name" => name = Some(form.exp_tail()),
|
||||||
|
"info" => info = Some(form.exp_tail()),
|
||||||
|
"keys" => keys = Some(form.exp_tail()),
|
||||||
|
"view" => view = Some(form.exp_tail()),
|
||||||
|
_ => return Err(format!("(e3) unexpected key {key:?} in {form:?}").into())
|
||||||
|
},
|
||||||
|
_ => return Err(format!("(e2) unexpected exp {form :?}").into())
|
||||||
|
}))?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
path: path.as_ref().into(),
|
path: path.as_ref().into(),
|
||||||
info: info.map(Self::parse_info).flatten(),
|
info: info.map(Self::parse_info).flatten(),
|
||||||
name: name.map(Self::parse_name).flatten(),
|
name: name.map(Self::parse_name).flatten(),
|
||||||
view: Self::parse_view(view)?,
|
view: Self::parse_view(view)?.into(),
|
||||||
keys: Self::parse_keys(&path, keys)?,
|
keys: Self::parse_keys(&path, keys)?.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fn parse_name (dsl: T) -> Option<Arc<str>> {
|
||||||
fn parse (iter: Cst) -> Usually<[Option<Cst>;4]> {
|
dsl.str().map(Into::into)
|
||||||
let mut name: Option<Cst> = None;
|
|
||||||
let mut info: Option<Cst> = None;
|
|
||||||
let mut view: Option<Cst> = None;
|
|
||||||
let mut keys: Option<Cst> = None;
|
|
||||||
for token in iter {
|
|
||||||
match token.value {
|
|
||||||
Value::Exp(_, mut exp) => {
|
|
||||||
let next = exp.next();
|
|
||||||
match next {
|
|
||||||
Some(Token { value: Value::Key(sym), .. }) => match sym {
|
|
||||||
"name" => name = Some(exp),
|
|
||||||
"info" => info = Some(exp),
|
|
||||||
"keys" => keys = Some(exp),
|
|
||||||
"view" => view = Some(exp),
|
|
||||||
_ => return Err(
|
|
||||||
format!("(e3) unexpected symbol {sym:?}").into()
|
|
||||||
)
|
|
||||||
},
|
|
||||||
_ => return Err(
|
|
||||||
format!("(e2) unexpected exp {:?}", next.map(|x|x.value)).into()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
t => return Err(
|
|
||||||
format!("(e1) unexpected token {token:?}").into()
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Ok([name, info, view, keys])
|
|
||||||
}
|
}
|
||||||
|
fn parse_info (dsl: T) -> Option<Arc<str>> {
|
||||||
fn parse_info (mut iter: Cst) -> Option<Arc<str>> {
|
dsl.str().map(Into::into)
|
||||||
iter.next().and_then(|x|if let Value::Str(x) = x.value {
|
|
||||||
Some(x.into())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
fn parse_view (dsl: Option<T>) -> Usually<T> {
|
||||||
fn parse_name (mut iter: Cst) -> Option<Arc<str>> {
|
match dsl { Some(view) => Ok(view), _ => Err(format!("missing view definition").into()) }
|
||||||
iter.next().and_then(|x|if let Value::Str(x) = x.value {
|
|
||||||
Some(x.into())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
fn parse_keys (base: &impl AsRef<Path>, dsl: Option<T>) -> Usually<EventMap<TuiIn, T>> {
|
||||||
fn parse_view (iter: Option<Cst>) -> Usually<Cst> {
|
let mut map = EventMap::default();
|
||||||
if let Some(view) = iter {
|
let mut keys = if let Some(keys) = dsl { keys } else {
|
||||||
Ok(view)
|
|
||||||
} else {
|
|
||||||
Err(format!("missing view definition").into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_keys (base: &impl AsRef<Path>, iter: Option<Cst>)
|
|
||||||
-> Usually<InputMap<App, AppCommand, TuiIn, Cst>>
|
|
||||||
{
|
|
||||||
if iter.is_none() {
|
|
||||||
return Err(format!("missing keys definition").into())
|
return Err(format!("missing keys definition").into())
|
||||||
}
|
};
|
||||||
let mut keys = iter.unwrap();
|
keys.exp_each(|form|Ok(match form.exp_head().dsl() {
|
||||||
let mut map = InputMap::default();
|
Val::Sym(s) if s.as_ref() == "layer" =>
|
||||||
while let Some(token) = keys.next() {
|
Self::parse_keys_layer(&mut map, base, form.exp_tail()),
|
||||||
if let Value::Exp(_, mut exp) = token.value {
|
Val::Sym(s) if s.as_ref() == "layer-if" =>
|
||||||
let next = exp.next();
|
Self::parse_keys_layer_if(&mut map, base, form.exp_tail()),
|
||||||
if let Some(Token { value: Value::Key(sym), .. }) = next {
|
x =>
|
||||||
match sym {
|
return Err(format!("(e3) unexpected {x:?} in {form:?}").into())
|
||||||
"layer" => {
|
}))?;
|
||||||
if let Some(Token { value: Value::Str(path), .. }) = exp.peek() {
|
|
||||||
let path = base.as_ref().parent().unwrap().join(unquote(path));
|
|
||||||
if !std::fs::exists(&path)? {
|
|
||||||
return Err(format!("(e5) not found: {path:?}").into())
|
|
||||||
}
|
|
||||||
map.add_layer(read_and_leak(path)?.into());
|
|
||||||
print!("layer:\n path: {:?}...", exp.0.0.trim());
|
|
||||||
println!("ok");
|
|
||||||
} else {
|
|
||||||
return Err(format!("(e4) unexpected non-string {next:?}").into())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"layer-if" => {
|
|
||||||
let mut cond = None;
|
|
||||||
|
|
||||||
if let Some(Token { value: Value::Sym(sym), .. }) = exp.next() {
|
|
||||||
cond = Some(leak(sym));
|
|
||||||
} else {
|
|
||||||
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(Token { value: Value::Str(path), .. }) = exp.peek() {
|
|
||||||
let path = base.as_ref().parent().unwrap().join(unquote(path));
|
|
||||||
if !std::fs::exists(&path)? {
|
|
||||||
return Err(format!("(e5) not found: {path:?}").into())
|
|
||||||
}
|
|
||||||
print!("layer-if:\n cond: {}\n path: {path:?}...",
|
|
||||||
cond.unwrap_or_default());
|
|
||||||
let keys = read_and_leak(path)?.into();
|
|
||||||
let cond = cond.unwrap();
|
|
||||||
println!("ok");
|
|
||||||
map.add_layer_if(
|
|
||||||
Box::new(move |state: &App|Take::take_or_fail(
|
|
||||||
state, exp, ||"missing input layer conditional"
|
|
||||||
)), keys
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_ => return Err(format!("(e3) unexpected symbol {sym:?}").into())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(format!("(e2) unexpected exp {:?}", next.map(|x|x.value)).into())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Err(format!("(e1) unexpected token {token:?}").into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(map)
|
Ok(map)
|
||||||
}
|
}
|
||||||
|
fn parse_keys_layer (map: &mut EventMap<TuiIn, T>, base: &impl AsRef<Path>, exp: &T) {
|
||||||
|
let next = exp.peek().map(|x|x.val());
|
||||||
|
if let Some(Val::Str(path)) = next {
|
||||||
|
let path = base.as_ref().parent().unwrap().join(unquote(path));
|
||||||
|
if !std::fs::exists(&path)? {
|
||||||
|
return Err(format!("(e5) not found: {path:?}").into())
|
||||||
|
}
|
||||||
|
map.add_layer(read_and_leak(path)?.into());
|
||||||
|
print!("layer:\n path: {:?}...", exp.0.0.trim());
|
||||||
|
println!("ok");
|
||||||
|
} else {
|
||||||
|
return Err(format!("(e4) unexpected non-string {next:?}").into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn parse_keys_layer_if (map: &mut EventMap<TuiIn, T>, base: &impl AsRef<Path>, exp: &T) {
|
||||||
|
let next = exp.next().map(|x|x.val());
|
||||||
|
let cond = if let Some(Val::Sym(sym)) = next {
|
||||||
|
leak(sym)
|
||||||
|
} else {
|
||||||
|
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
|
||||||
|
};
|
||||||
|
|
||||||
|
let next = exp.peek().map(|x|x.val());
|
||||||
|
if let Some(Val::Str(path)) = next {
|
||||||
|
let path = base.as_ref().parent().unwrap().join(unquote(path));
|
||||||
|
if !std::fs::exists(&path)? {
|
||||||
|
return Err(format!("(e5) not found: {path:?}").into())
|
||||||
|
}
|
||||||
|
print!("layer-if:\n cond: {cond}\n path: {path:?}...");
|
||||||
|
let keys = read_and_leak(path)?.into();
|
||||||
|
println!("ok");
|
||||||
|
//map.add_layer_if(
|
||||||
|
//Box::new(move |state: &App|Take::take_or_fail(
|
||||||
|
//state, exp, ||"missing input layer conditional"
|
||||||
|
//)), keys
|
||||||
|
//);
|
||||||
|
} else {
|
||||||
|
return Err(format!("(e4) unexpected non-symbol {next:?}").into())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_and_leak (path: impl AsRef<Path>) -> Usually<&'static str> {
|
fn read_and_leak (path: impl AsRef<Path>) -> Usually<&'static str> {
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ impl Cli {
|
||||||
for (index, connect) in midi_tos.iter().enumerate() {
|
for (index, connect) in midi_tos.iter().enumerate() {
|
||||||
midi_outs.push(jack.midi_out(&format!("{index}/M"), &[connect.clone()])?);
|
midi_outs.push(jack.midi_out(&format!("{index}/M"), &[connect.clone()])?);
|
||||||
};
|
};
|
||||||
let config = Configuration::new(&match self.mode {
|
let config = Configuration::from_path(&match self.mode {
|
||||||
LaunchMode::Clock => "config/config_transport.edn",
|
LaunchMode::Clock => "config/config_transport.edn",
|
||||||
LaunchMode::Sequencer => "config/config_sequencer.edn",
|
LaunchMode::Sequencer => "config/config_sequencer.edn",
|
||||||
LaunchMode::Groovebox => "config/config_groovebox.edn",
|
LaunchMode::Groovebox => "config/config_groovebox.edn",
|
||||||
|
|
|
||||||
|
|
@ -58,18 +58,18 @@ maybe_has!(Track: |self: Arrangement|
|
||||||
maybe_has!(Scene: |self: Arrangement|
|
maybe_has!(Scene: |self: Arrangement|
|
||||||
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Scene>>::get(self).get(index)).flatten() };
|
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Scene>>::get(self).get(index)).flatten() };
|
||||||
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Scene>>::get_mut(self).get_mut(index)).flatten() });
|
{ Has::<Selection>::get(self).track().map(|index|Has::<Vec<Scene>>::get_mut(self).get_mut(index)).flatten() });
|
||||||
take!(MidiInputCommand |state: Arrangement, iter|state.selected_midi_in().as_ref()
|
//take!(MidiInputCommand |state: Arrangement, iter|state.selected_midi_in().as_ref()
|
||||||
.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
//.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
||||||
take!(MidiOutputCommand |state: Arrangement, iter|state.selected_midi_out().as_ref()
|
//take!(MidiOutputCommand |state: Arrangement, iter|state.selected_midi_out().as_ref()
|
||||||
.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
//.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
||||||
take!(DeviceCommand|state: Arrangement, iter|state.selected_device().as_ref()
|
//take!(DeviceCommand|state: Arrangement, iter|state.selected_device().as_ref()
|
||||||
.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
//.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
||||||
take!(TrackCommand |state: Arrangement, iter|state.selected_track().as_ref()
|
//take!(TrackCommand |state: Arrangement, iter|state.selected_track().as_ref()
|
||||||
.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
//.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
||||||
take!(SceneCommand |state: Arrangement, iter|state.selected_scene().as_ref()
|
//take!(SceneCommand |state: Arrangement, iter|state.selected_scene().as_ref()
|
||||||
.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
//.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
||||||
take!(ClipCommand |state: Arrangement, iter|state.selected_clip().as_ref()
|
//take!(ClipCommand |state: Arrangement, iter|state.selected_clip().as_ref()
|
||||||
.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
//.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
||||||
#[tengri_proc::expose] impl Arrangement {
|
#[tengri_proc::expose] impl Arrangement {
|
||||||
fn selected_midi_in (&self) -> Option<MidiInput> { todo!() }
|
fn selected_midi_in (&self) -> Option<MidiInput> { todo!() }
|
||||||
fn selected_midi_out (&self) -> Option<MidiOutput> { todo!() }
|
fn selected_midi_out (&self) -> Option<MidiOutput> { todo!() }
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ pub struct Pool {
|
||||||
/// Embedded file browser
|
/// Embedded file browser
|
||||||
pub browser: Option<Browser>,
|
pub browser: Option<Browser>,
|
||||||
}
|
}
|
||||||
take!(BrowserCommand |state: Pool, iter|Ok(state.browser.as_ref()
|
//take!(BrowserCommand |state: Pool, iter|Ok(state.browser.as_ref()
|
||||||
.map(|p|Take::take(p, iter))
|
//.map(|p|Take::take(p, iter))
|
||||||
.transpose()?
|
//.transpose()?
|
||||||
.flatten()));
|
//.flatten()));
|
||||||
impl Default for Pool {
|
impl Default for Pool {
|
||||||
fn default () -> Self {
|
fn default () -> Self {
|
||||||
use PoolMode::*;
|
use PoolMode::*;
|
||||||
|
|
|
||||||
2
deps/tengri
vendored
2
deps/tengri
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 21832453d9554752a77278385446518744baeee8
|
Subproject commit 7b67d29c012f2d39a5d9d2fcd840417c90256503
|
||||||
Loading…
Add table
Add a link
Reference in a new issue