track init callback

This commit is contained in:
🪞👃🪞 2024-07-04 19:40:15 +03:00
parent 163ecaaed6
commit c7047327d5
2 changed files with 72 additions and 55 deletions

View file

@ -51,7 +51,7 @@ const KEYMAP: &'static [KeyBinding<App>] = keymap!(App {
Ok(true)
}],
[Char('t'), CONTROL, "add_track", "add a new track", |app: &mut App| {
app.add_track(None)?;
app.add_track(None, None)?;
Ok(true)
}],
[Char('`'), NONE, "switch_mode", "switch the display mode", |app: &mut App| {

View file

@ -40,60 +40,61 @@ pub fn main () -> Usually<()> {
state.scene_cursor = 1;
state.note_start = 12;
state.time_zoom = 12;
state.midi_in = Some(client.register_port("midi-in", MidiIn)?);
state.transport = Some(client.transport());
state.playing = Some(TransportState::Stopped);
state.jack = Some(jack);
state.transport = Some(client.transport());
state.playing = Some(TransportState::Stopped);
state.midi_in = Some(client.register_port("midi-in", MidiIn)?);
state.jack = Some(jack);
let drums = state.add_track(Some("Drums"))?;
drums.add_device(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"),
])))?);
drums.add_device(Plugin::lv2(
"Panagement",
"file:///home/user/.lv2/Auburn Sounds Panagement 2.lv2"
)?);
state.add_track(Some("Drums"), Some(Box::new(move|client, track|{
track.add_device(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"),
])))?);
track.add_device(Plugin::lv2(
"Panagement",
"file:///home/user/.lv2/Auburn Sounds Panagement 2.lv2"
)?);
client.connect_ports(&track.midi_out, &track.devices[0].midi_ins()?[0])?;
track.sequence = Some(1); // FIXME
track.add_phrase("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.add_phrase("D-Beat", ppq * 4, Some(phrase! {
00 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
04 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
08 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
10 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
12 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
}));
track.add_phrase("Garage", ppq * 4, Some(phrase! {
00 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
04 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
11 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
12 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
}));
Ok(())
})))?;
drums.add_phrase("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() },
}));
drums.add_phrase("D-Beat", ppq * 4, Some(phrase! {
00 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
04 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
08 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
10 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
12 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
}));
drums.add_phrase("Garage", ppq * 4, Some(phrase! {
00 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
04 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
11 * ppq/4 => MidiMessage::NoteOn { key: 36.into(), vel: 100.into() },
12 * ppq/4 => MidiMessage::NoteOn { key: 40.into(), vel: 100.into() },
}));
// FIXME:
drums.sequence = Some(1);
let bass = state.add_track(Some("Bass"))?;
bass.add_device(Plugin::lv2("Odin2", "file:///home/user/.lv2/Odin2.lv2")?);
bass.add_phrase("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() },
}));
// FIXME:
bass.sequence = Some(0);
state.add_track(Some("Bass"), Some(Box::new(move|client, track|{
track.add_device(Plugin::lv2("Odin2", "file:///home/user/.lv2/Odin2.lv2")?);
//client.connect_ports(&track.midi_out, &track.devices[0].midi_ins()?[0])?;
track.sequence = Some(0); // FIXME
track.add_phrase("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() },
}));
Ok(())
})))?;
Ok(())
}))
@ -174,6 +175,14 @@ process!(App |self, _client, scope| {
Control::Continue
});
impl App {
pub fn client (&self) -> &Client {
self.jack.as_ref().unwrap().as_client()
}
pub fn connect_ports <A: ::_jack::PortSpec, B: ::_jack::PortSpec> (
&self, a: &Port<A>, b: &Port<B>
) -> Usually<()> {
Ok(self.client().connect_ports(a, b)?)
}
pub fn toggle_play (&mut self) -> Usually<()> {
self.playing = match self.playing.expect("after jack init") {
TransportState::Stopped => {
@ -194,9 +203,17 @@ impl App {
self.scene_cursor = self.scenes.len();
Ok(&mut self.scenes[self.scene_cursor - 1])
}
pub fn add_track (&mut self, name: Option<&str>) -> Usually<&mut Track> {
pub fn add_track (
&mut self,
name: Option<&str>,
init: Option<Box<dyn FnOnce(&Client, &mut Track)->Usually<()>>>,
) -> Usually<&mut Track> {
let name = name.ok_or_else(||format!("Track {}", self.tracks.len() + 1))?;
self.tracks.push(Track::new(&name, self.jack.as_ref().unwrap().as_client(), None, None)?);
let mut track = Track::new(&name, self.client(), None, None)?;
if let Some(init) = init {
init(self.client(), &mut track)?;
}
self.tracks.push(track);
self.track_cursor = self.tracks.len();
Ok(&mut self.tracks[self.track_cursor - 1])
}