mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-10-08 18:56:42 +02:00
collect tek_view, tek_ctrl
This commit is contained in:
parent
c5d6ce24b2
commit
186b81f29c
47 changed files with 2665 additions and 2893 deletions
212
src/device.rs
212
src/device.rs
|
|
@ -1,212 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
impl App {
|
||||
/// FIXME: generalize. Set picked device in device pick dialog.
|
||||
///
|
||||
/// ```
|
||||
/// tek::App::default().device_pick(0);
|
||||
/// ```
|
||||
pub fn device_pick (&mut self, index: usize) {
|
||||
self.dialog = Dialog::Device(index);
|
||||
}
|
||||
|
||||
/// FIXME: generalize. Add device to current track.
|
||||
pub fn add_device (&mut self, index: usize) -> Usually<()> {
|
||||
match index {
|
||||
0 => {
|
||||
let name = self.jack.with_client(|c|c.name().to_string());
|
||||
let midi = self.project.track().expect("no active track").sequencer.midi_outs[0].port_name();
|
||||
let track = self.track().expect("no active track");
|
||||
let port = format!("{}/Sampler", &track.name);
|
||||
let connect = Connect::exact(format!("{name}:{midi}"));
|
||||
let sampler = if let Ok(sampler) = Sampler::new(
|
||||
&self.jack, &port, &[connect], &[&[], &[]], &[&[], &[]]
|
||||
) {
|
||||
self.dialog = Dialog::None;
|
||||
Device::Sampler(sampler)
|
||||
} else {
|
||||
self.dialog = Dialog::Message("Failed to add device.".into());
|
||||
return Err("failed to add device".into())
|
||||
};
|
||||
let track = self.track_mut().expect("no active track");
|
||||
track.devices.push(sampler);
|
||||
Ok(())
|
||||
},
|
||||
1 => {
|
||||
todo!();
|
||||
//Ok(())
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasJack<'static> for App {
|
||||
fn jack (&self) -> &Jack<'static> {
|
||||
&self.jack
|
||||
}
|
||||
}
|
||||
|
||||
impl_audio!(App: tek_jack_process, tek_jack_event);
|
||||
|
||||
fn tek_jack_process (state: &mut App, client: &Client, scope: &ProcessScope) -> Control {
|
||||
let t0 = state.perf.get_t0();
|
||||
state.clock().update_from_scope(scope).unwrap();
|
||||
let midi_in = state.project.midi_input_collect(scope);
|
||||
if let Some(editor) = &state.editor() {
|
||||
let mut pitch: Option<u7> = None;
|
||||
for port in midi_in.iter() {
|
||||
for event in port.iter() {
|
||||
if let (_, Ok(LiveEvent::Midi {message: MidiMessage::NoteOn {key, ..}, ..}))
|
||||
= event
|
||||
{
|
||||
pitch = Some(key.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(pitch) = pitch {
|
||||
editor.set_note_pos(pitch.as_int() as usize);
|
||||
}
|
||||
}
|
||||
let result = state.project.tracks_jack_process(client, scope);
|
||||
state.perf.update_from_jack_scope(t0, scope);
|
||||
result
|
||||
}
|
||||
|
||||
fn tek_jack_event (state: &mut App, event: JackEvent) {
|
||||
use JackEvent::*;
|
||||
match event {
|
||||
SampleRate(sr) => { state.clock().timebase.sr.set(sr as f64); },
|
||||
PortRegistration(_id, true) => {
|
||||
//let port = self.jack().port_by_id(id);
|
||||
//println!("\rport add: {id} {port:?}");
|
||||
//println!("\rport add: {id}");
|
||||
},
|
||||
PortRegistration(_id, false) => {
|
||||
/*println!("\rport del: {id}")*/
|
||||
},
|
||||
PortsConnected(_a, _b, true) => { /*println!("\rport conn: {a} {b}")*/ },
|
||||
PortsConnected(_a, _b, false) => { /*println!("\rport disc: {a} {b}")*/ },
|
||||
ClientRegistration(_id, true) => {},
|
||||
ClientRegistration(_id, false) => {},
|
||||
ThreadInit => {},
|
||||
XRun => {},
|
||||
GraphReorder => {},
|
||||
_ => { panic!("{event:?}"); }
|
||||
}
|
||||
}
|
||||
|
||||
#[tek_proc::command(Device)]
|
||||
#[tek_proc::keyword(Device)]
|
||||
#[derive(Debug)]
|
||||
pub enum DeviceCommand {}
|
||||
|
||||
impl Device {
|
||||
pub fn name (&self) -> &str {
|
||||
match self {
|
||||
Self::Sampler(sampler) => sampler.name.as_ref(),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
pub fn midi_ins (&self) -> &[MidiInput] {
|
||||
match self {
|
||||
//Self::Sampler(Sampler { midi_in, .. }) => &[midi_in],
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
pub fn midi_outs (&self) -> &[MidiOutput] {
|
||||
match self {
|
||||
Self::Sampler(_) => &[],
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
pub fn audio_ins (&self) -> &[AudioInput] {
|
||||
match self {
|
||||
Self::Sampler(Sampler { audio_ins, .. }) => audio_ins.as_slice(),
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
pub fn audio_outs (&self) -> &[AudioOutput] {
|
||||
match self {
|
||||
Self::Sampler(Sampler { audio_outs, .. }) => audio_outs.as_slice(),
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A device that can be plugged into the chain.
|
||||
///
|
||||
/// ```
|
||||
/// let device = tek::Device::default();
|
||||
/// ```
|
||||
#[derive(Debug, Default)] pub enum Device {
|
||||
#[default]
|
||||
Bypass,
|
||||
Mute,
|
||||
#[cfg(feature = "sampler")]
|
||||
Sampler(Sampler),
|
||||
#[cfg(feature = "lv2")] // TODO
|
||||
Lv2(Lv2),
|
||||
#[cfg(feature = "vst2")] // TODO
|
||||
Vst2,
|
||||
#[cfg(feature = "vst3")] // TODO
|
||||
Vst3,
|
||||
#[cfg(feature = "clap")] // TODO
|
||||
Clap,
|
||||
#[cfg(feature = "sf2")] // TODO
|
||||
Sf2,
|
||||
}
|
||||
|
||||
/// Some sort of wrapper?
|
||||
pub struct DeviceAudio<'a>(pub &'a mut Device);
|
||||
|
||||
impl_audio!(|self: DeviceAudio<'a>, client, scope|{
|
||||
use Device::*;
|
||||
match self.0 {
|
||||
Mute => { Control::Continue },
|
||||
Bypass => { /*TODO*/ Control::Continue },
|
||||
#[cfg(feature = "sampler")] Sampler(sampler) => sampler.process(client, scope),
|
||||
#[cfg(feature = "lv2")] Lv2(lv2) => lv2.process(client, scope),
|
||||
#[cfg(feature = "vst2")] Vst2 => { todo!() }, // TODO
|
||||
#[cfg(feature = "vst3")] Vst3 => { todo!() }, // TODO
|
||||
#[cfg(feature = "clap")] Clap => { todo!() }, // TODO
|
||||
#[cfg(feature = "sf2")] Sf2 => { todo!() }, // TODO
|
||||
}
|
||||
});
|
||||
|
||||
pub fn device_kinds () -> &'static [&'static str] {
|
||||
&[
|
||||
#[cfg(feature = "sampler")] "Sampler",
|
||||
#[cfg(feature = "lv2")] "Plugin (LV2)",
|
||||
]
|
||||
}
|
||||
|
||||
impl<T: AsRef<Vec<Device>> + AsMut<Vec<Device>>> HasDevices for T {
|
||||
fn devices (&self) -> &Vec<Device> {
|
||||
self.as_ref()
|
||||
}
|
||||
fn devices_mut (&mut self) -> &mut Vec<Device> {
|
||||
self.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasDevices: AsRef<Vec<Device>> + AsMut<Vec<Device>> {
|
||||
fn devices (&self) -> &Vec<Device> {
|
||||
self.as_ref()
|
||||
}
|
||||
fn devices_mut (&mut self) -> &mut Vec<Device> {
|
||||
self.as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn view_device <'a> (state: &'a App) -> impl Draw<Tui> {
|
||||
let selected = state.dialog.device_kind().unwrap();
|
||||
south(
|
||||
bold(true, "Add device"),
|
||||
iter_south(move||device_kinds().iter().enumerate().map(move|(i, _label)|{
|
||||
let b = if i == selected { Rgb(64,128,32) } else { Rgb(0,0,0) };
|
||||
let l = if i == selected { "[ " } else { " " };
|
||||
let r = if i == selected { " ]" } else { " " };
|
||||
bg(b, east(l, west(r, "FIXME device name"))).full_w()
|
||||
})))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue