wip: unpetrify, tryna dodge 4000

This commit is contained in:
🪞👃🪞 2024-07-03 15:53:14 +03:00
parent ea529b7734
commit b4fdddc0aa
7 changed files with 161 additions and 78 deletions

View file

@ -31,8 +31,8 @@ pub const KEYMAP: &'static [KeyBinding<Launcher>] = keymap!(Launcher {
[Char('r'), NONE, "record_toggle", "toggle recording", record_toggle],
[Char('d'), NONE, "overdub_toggle", "toggle overdub", overdub_toggle],
[Char('m'), NONE, "monitor_toggle", "toggle input monitoring", monitor_toggle],
[Char('r'), CONTROL, "rename", "rename current element", rename],
[Char('t'), CONTROL, "add_track", "add a new track", add_track],
//[Char('r'), CONTROL, "rename", "rename current element", rename],
//[Char('t'), CONTROL, "add_track", "add a new track", add_track],
//[Char(' '), SHIFT, "play_start", "play from start", play_start],
});
pub const KEYMAP_TRACKS: &'static [KeyBinding<Launcher>] = keymap!(Launcher {
@ -105,16 +105,16 @@ fn activate (_: &mut Launcher) -> Usually<bool> {
Ok(true)
}
fn rename (_: &mut Launcher) -> Usually<bool> {
Ok(true)
}
//fn rename (_: &mut Launcher) -> Usually<bool> {
//Ok(true)
//}
fn add_track (state: &mut Launcher) -> Usually<bool> {
let name = format!("Track {}", state.tracks.len() + 1);
state.tracks.push(Track::new(&name, &state.timebase, None, None)?);
state.cursor.0 = state.tracks.len();
Ok(true)
}
//fn add_track (state: &mut Launcher) -> Usually<bool> {
//let name = format!("Track {}", state.tracks.len() + 1);
//state.tracks.push(Track::new(&name, &state.timebase, None, None)?);
//state.cursor.0 = state.tracks.len();
//Ok(true)
//}
fn delete_track (state: &mut Launcher) -> Usually<bool> {
if state.tracks.len() > 0 && state.cursor.0 >= 1 {

View file

@ -25,27 +25,8 @@ pub const KEYMAP: &'static [KeyBinding<Sequencer>] = keymap!(Sequencer {
[Char('s'), NONE, "stop_and_rewind", "Stop and rewind", stop_and_rewind],
[Char('q'), NONE, "quantize_next", "Next quantize value", quantize_next],
[Char('Q'), SHIFT, "quantize_prev", "Previous quantize value", quantize_prev],
[Char('n'), NONE, "note_axis", "Focus note axis", nop],
[Char('t'), NONE, "time_axis", "Focus time axis", nop],
[Char('v'), NONE, "variations", "Focus variation selector", nop],
[Char('s'), SHIFT, "sync", "Focus sync selector", nop],
[Char('1'), NONE, "seq_1", "Phrase 1", focus_seq(0)],
[Char('2'), NONE, "seq_2", "Phrase 2", focus_seq(1)],
[Char('3'), NONE, "seq_3", "Phrase 3", focus_seq(2)],
[Char('4'), NONE, "seq_4", "Phrase 4", focus_seq(3)],
[Char('5'), NONE, "seq_5", "Phrase 5", focus_seq(4)],
[Char('6'), NONE, "seq_6", "Phrase 6", focus_seq(5)],
[Char('7'), NONE, "seq_7", "Phrase 7", focus_seq(6)],
[Char('8'), NONE, "seq_8", "Phrase 8", focus_seq(7)],
});
const fn focus_seq (i: usize) -> impl Fn(&mut Sequencer)->Usually<bool> {
move |s: &mut Sequencer| {
s.sequence = Some(i);
Ok(true)
}
}
fn nop (_: &mut Sequencer) -> Usually<bool> {
Ok(false)
}

0
src/core/layout.rs Normal file
View file

View file

@ -17,6 +17,15 @@ use crate::core::*;
use crate::model::*;
use crate::view::*;
macro_rules! phrase {
($($t:expr => $msg:expr),* $(,)?) => {{
let mut phrase = BTreeMap::new();
$(phrase.insert($t, vec![]);)*
$(phrase.get_mut(&$t).unwrap().push($msg);)*
phrase
}}
}
pub fn main () -> Usually<()> {
App::default().run(Some(|app: Arc<Mutex<App>>|{
let mut state = app.lock().unwrap();
@ -26,20 +35,50 @@ pub fn main () -> Usually<()> {
state.modal = Some(Box::new(crate::config::SetupModal(Some(xdg.clone()))));
}
state.scenes = vec![
Scene::new("Intro", vec![None, None, None, None]),
Scene::new("Intro", vec![Some(0), Some(0), None, None]),
];
let jack = jack_run("tek", &app)?;
let timebase = &state.timebase;
let ppq = timebase.ppq() as usize;
state.tracks = vec![
Track::new("Drums", &state.timebase, Some(vec![
Track::new("Drums", &jack.as_client(), &timebase, Some(vec![
Sampler::new("Sampler", Some(BTreeMap::from([
sample!(36, "Kick", "/home/user/Lab/Music/pak/kik.wav"),
sample!(40, "Snare", "/home/user/Lab/Music/pak/sna.wav"),
sample!(44, "Hihat", "/home/user/Lab/Music/pak/chh.wav"),
])))?.boxed(),
Plugin::lv2(
"Panagement",
"file:///home/user/.lv2/Auburn Sounds Panagement 2.lv2"
)?.boxed(),
]), Some(vec![
Phrase::new("4 kicks", state.timebase.ppq() as usize * 4, None),
Phrase::new("4 kicks", ppq * 4, Some(phrase! {
00 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
04 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
08 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
12 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
})),
]))?,
Track::new("Bass", &jack.as_client(), &timebase, Some(vec![
]), Some(vec![
Phrase::new("Offbeat", ppq * 4, Some(phrase! {
00 * ppq/4 => MidiMessage::NoteOff { key: 40.into(), vel: 100.into() },
02 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
04 * ppq/4 => MidiMessage::NoteOff { key: 40.into(), vel: 100.into() },
06 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
08 * ppq/4 => MidiMessage::NoteOff { key: 40.into(), vel: 100.into() },
10 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
12 * ppq/4 => MidiMessage::NoteOff { key: 40.into(), vel: 100.into() },
14 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
})),
]))?,
];
state.jack = Some(jack_run("tek", &app)?);
state.jack = Some(jack);
Ok(())
}))
}
@ -48,13 +87,15 @@ pub fn main () -> Usually<()> {
pub struct App {
pub xdg: Option<Arc<XdgApp>>,
pub jack: Option<DynamicAsyncClient>,
pub phrases: Vec<Phrase>,
pub scene: usize,
pub scenes: Vec<Scene>,
pub track_cursor: usize,
pub tracks: Vec<Track>,
pub frame: usize,
pub scene: Vec<usize>,
pub timebase: Arc<Timebase>,
pub modal: Option<Box<dyn Component>>,
pub section: usize,
pub entered: bool,
}
process!(App);
@ -75,23 +116,26 @@ render!(App |self, buf, area| {
buf,
area: Rect { x, y, width, height: height / 3 },
name: "",
focused: true,
focused: self.section == 0,
scenes: &self.scenes,
tracks: &self.tracks,
cursor: &(0, 0)
cursor: &(self.track_cursor, self.scene + 1)
}.draw()?.height;
y = y + ChainView {
focused: true,
chain: Some(&self.tracks[0].chain),
}.render(buf, Rect { x, y, width, height: height / 3 })?.height;
if self.track_cursor > 0 {
let track = self.tracks.get(self.track_cursor - 1);
y = y + ChainView {
focused: self.section == 1,
chain: track.map(|t|&t.chain),
}.render(buf, Rect { x, y, width, height: height / 3 })?.height;
y = y + SequencerView {
focused: true,
ppq: self.timebase.ppq() as usize,
track: Some(&self.tracks[0]),
phrase: Some(&self.tracks[0].sequencer.phrases[0]),
}.render(buf, Rect { x, y, width, height })?.height;
y = y + SequencerView {
focused: self.section == 2,
ppq: self.timebase.ppq() as usize,
track: track,
phrase: track.map(|t|&t.sequencer.phrases[0]),
}.render(buf, Rect { x, y, width, height })?.height;
}
if let Some(ref modal) = self.modal {
for cell in buf.content.iter_mut() {
@ -134,27 +178,90 @@ handle!(App |self, e| {
}))
});
fn increment (_: &mut App) -> Usually<bool> { Ok(true) }
fn decrement (_: &mut App) -> Usually<bool> { Ok(true) }
fn delete (_: &mut App) -> Usually<bool> { Ok(true) }
fn focus_next (app: &mut App) -> Usually<bool> {
if app.section >= 2 {
app.section = 0;
} else {
app.section = app.section + 1;
}
Ok(true)
}
fn focus_prev (app: &mut App) -> Usually<bool> {
if app.section == 0 {
app.section = 2;
} else {
app.section = app.section - 1;
}
Ok(true)
}
fn cursor_up (app: &mut App) -> Usually<bool> {
focus_prev(app)
}
fn cursor_down (app: &mut App) -> Usually<bool> {
focus_next(app)
}
fn cursor_left (app: &mut App) -> Usually<bool> {
match app.section {
0 => {
app.track_cursor = if app.track_cursor == 0 {
app.tracks.len()
} else {
app.track_cursor
} - 1;
Ok(true)
}
_ => Ok(false)
}
}
fn cursor_right (app: &mut App) -> Usually<bool> {
match app.section {
0 => {
app.track_cursor = if app.track_cursor >= app.tracks.len() {
0
} else {
app.track_cursor + 1
};
Ok(true)
},
_ => Ok(false)
}
}
fn increment (app: &mut App) -> Usually<bool> {
match app.section {
0 => clip_next(app),
_ => Ok(false)
}
}
fn decrement (app: &mut App) -> Usually<bool> {
match app.section {
0 => clip_prev(app),
_ => Ok(false)
}
}
fn delete (app: &mut App) -> Usually<bool> {
match app.section {
0 => delete_track(app),
_ => Ok(false)
}
}
fn duplicate (_: &mut App) -> Usually<bool> { Ok(true) }
fn activate (_: &mut App) -> Usually<bool> { Ok(true) }
fn rename (_: &mut App) -> Usually<bool> { Ok(true) }
fn add_track (app: &mut App) -> Usually<bool> {
let name = format!("Track {}", app.tracks.len() + 1);
app.tracks.push(Track::new(&name, &app.timebase, None, None)?);
app.tracks.push(Track::new(&name, app.jack.as_ref().unwrap().as_client(), &app.timebase, None, None)?);
app.track_cursor = app.tracks.len() - 1;
Ok(true)
}
fn delete_track (_: &mut App) -> Usually<bool> {
Ok(true)
fn delete_track (app: &mut App) -> Usually<bool> {
if app.tracks.len() > 0 {
app.tracks.remove(app.track_cursor);
app.track_cursor = app.track_cursor.saturating_sub(1);
return Ok(true)
}
Ok(false)
}
fn cursor_up (_: &mut App) -> Usually<bool> { Ok(true) }
fn cursor_down (_: &mut App) -> Usually<bool> { Ok(true) }
fn cursor_left (_: &mut App) -> Usually<bool> { Ok(true) }
fn cursor_right (_: &mut App) -> Usually<bool> { Ok(true) }
fn toggle_help (_: &mut App) -> Usually<bool> { Ok(true) }
fn focus_next (_: &mut App) -> Usually<bool> { Ok(true) }
fn focus_prev (_: &mut App) -> Usually<bool> { Ok(true) }
fn clip_next (_: &mut App) -> Usually<bool> { Ok(true) }
fn clip_prev (_: &mut App) -> Usually<bool> { Ok(true) }
fn play_toggle (_: &mut App) -> Usually<bool> { Ok(true) }
@ -175,14 +282,6 @@ fn monitor_toggle (_: &mut App) -> Usually<bool> { Ok(true) }
//( $t1 * ppq / 4, vec![ $($msg),* ] )
//}
//}
//macro_rules! phrase {
//($($t:expr => $msg:expr),* $(,)?) => {{
//let mut phrase = BTreeMap::new();
//$(phrase.insert($t, vec![]);)*
//$(phrase.get_mut(&$t).unwrap().push($msg);)*
//phrase
//}}
//}
//Launcher::new("Launcher#0", &timebase,
//Some(vec![

View file

@ -61,7 +61,7 @@ impl Launcher {
cursor: (2, 2),
current_frame: 0,
scenes: scenes.unwrap_or_else(||vec![Scene::new(&"Scene 1", &[None])]),
tracks: if let Some(tracks) = tracks { tracks } else { vec![
tracks: vec![]/*if let Some(tracks) = tracks { tracks } else { vec![
Track::new("Track 1", &timebase, None, Some(vec![
Phrase::new("MIDI Clip 1", ppq * 4, Some(BTreeMap::from([
( ppq * 0, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ),
@ -70,7 +70,7 @@ impl Launcher {
( ppq * 3, vec![MidiMessage::NoteOn { key: 36.into(), vel: 100.into() }] ),
])))
]))?,
] },
] }*/,
show_help: true,
})
}

View file

@ -5,17 +5,20 @@ pub struct Track {
pub name: String,
pub sequencer: Sequencer,
pub chain: Chain,
pub midi_out: Port<MidiOut>,
}
impl Track {
pub fn new (
name: &str,
tempo: &Arc<Timebase>,
devices: Option<Vec<Box<dyn Device>>>,
phrases: Option<Vec<Phrase>>,
name: &str,
jack: &Client,
timebase: &Arc<Timebase>,
devices: Option<Vec<Box<dyn Device>>>,
phrases: Option<Vec<Phrase>>,
) -> Usually<Self> {
let sequencer = Sequencer::new(&name, tempo, phrases)?;
let chain = Chain::new(&name, devices)?;
let sequencer = Sequencer::new(&name, timebase, phrases)?;
let chain = Chain::new(&name, devices)?;
let midi_out = jack.register_port(name, MidiOut)?;
//let (client, _status) = Client::new("init", ClientOptions::NO_START_SERVER)?;
//{
//if let (Some(output), Some(input)) = (
@ -33,7 +36,7 @@ impl Track {
//client.connect_ports_by_name(&output, &input)?;
//}
//}
Ok(Self { name: name.to_string(), sequencer, chain })
Ok(Self { name: name.to_string(), sequencer, chain, midi_out })
}
}

View file

@ -37,7 +37,7 @@ pub fn draw_as_row (
state: &Chain, buf: &mut Buffer, area: Rect, style: Option<Style>
) -> Usually<(Rect, Vec<Rect>)> {
let Rect { mut x, y, width, height } = area;
let mut h = 0u16;
let mut h = 3u16;
let mut frames = vec![];
for (i, device) in state.items.iter().enumerate() {
let x2 = 0u16;