mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
wip: reenable mixer components
This commit is contained in:
parent
2f189c6d7e
commit
1dbc5d1bb7
6 changed files with 87 additions and 16 deletions
|
|
@ -1,15 +1,17 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub struct Mixer<E: Engine> {
|
pub struct Mixer<E: Engine> {
|
||||||
|
/// JACK client handle (needs to not be dropped for standalone mode to work).
|
||||||
|
pub jack: Arc<RwLock<JackClient>>,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub tracks: Vec<Track<E>>,
|
pub tracks: Vec<Track<E>>,
|
||||||
pub selected_track: usize,
|
pub selected_track: usize,
|
||||||
pub selected_column: usize,
|
pub selected_column: usize,
|
||||||
}
|
}
|
||||||
impl<E: Engine> Mixer<E> {
|
impl<E: Engine> Mixer<E> {
|
||||||
pub fn new (name: &str) -> Usually<Self> {
|
pub fn new (jack: &Arc<RwLock<JackClient>>, name: &str) -> Usually<Self> {
|
||||||
let (client, _status) = Client::new(name, ClientOptions::NO_START_SERVER)?;
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
jack: jack.clone(),
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
selected_column: 0,
|
selected_column: 0,
|
||||||
selected_track: 1,
|
selected_track: 1,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
//! Multi-track mixer
|
||||||
|
include!("lib.rs");
|
||||||
|
use tek_core::clap::{self, Parser};
|
||||||
|
pub fn main () -> Usually<()> { MixerCli::parse().run() }
|
||||||
|
#[derive(Debug, Parser)] #[command(version, about, long_about = None)] pub struct MixerCli {
|
||||||
|
/// Name of JACK client
|
||||||
|
#[arg(short, long)] name: Option<String>,
|
||||||
|
/// Number of tracks
|
||||||
|
#[arg(short, long)] channels: Option<usize>,
|
||||||
|
}
|
||||||
|
impl MixerCli {
|
||||||
|
fn run (&self) -> Usually<()> {
|
||||||
|
Tui::run(JackClient::new("tek_mixer")?.activate_with(|jack|{
|
||||||
|
let mut mixer = Mixer::new(jack, self.name.as_ref().map(|x|x.as_str()).unwrap_or("mixer"))?;
|
||||||
|
for channel in 0..self.channels.unwrap_or(8) {
|
||||||
|
mixer.track_add(&format!("Track {}", channel + 1), 1)?;
|
||||||
|
}
|
||||||
|
Ok(mixer)
|
||||||
|
})?)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,8 @@ use crate::*;
|
||||||
/// A plugin device.
|
/// A plugin device.
|
||||||
pub struct Plugin<E> {
|
pub struct Plugin<E> {
|
||||||
_engine: PhantomData<E>,
|
_engine: PhantomData<E>,
|
||||||
|
/// JACK client handle (needs to not be dropped for standalone mode to work).
|
||||||
|
pub jack: Arc<RwLock<JackClient>>,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub path: Option<String>,
|
pub path: Option<String>,
|
||||||
pub plugin: Option<PluginKind>,
|
pub plugin: Option<PluginKind>,
|
||||||
|
|
@ -13,9 +15,13 @@ pub struct Plugin<E> {
|
||||||
|
|
||||||
impl<E> Plugin<E> {
|
impl<E> Plugin<E> {
|
||||||
/// Create a plugin host device.
|
/// Create a plugin host device.
|
||||||
pub fn new (name: &str) -> Usually<Self> {
|
pub fn new (
|
||||||
|
jack: &Arc<RwLock<JackClient>>,
|
||||||
|
name: &str,
|
||||||
|
) -> Usually<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
_engine: Default::default(),
|
_engine: Default::default(),
|
||||||
|
jack: jack.clone(),
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
path: None,
|
path: None,
|
||||||
plugin: None,
|
plugin: None,
|
||||||
|
|
@ -27,11 +33,16 @@ impl<E> Plugin<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Plugin<Tui> {
|
impl Plugin<Tui> {
|
||||||
pub fn new_lv2 (name: &str, path: &str) -> Usually<JackDevice<Tui>> {
|
pub fn new_lv2 (
|
||||||
|
jack: &Arc<RwLock<JackClient>>,
|
||||||
|
name: &str,
|
||||||
|
path: &str,
|
||||||
|
) -> Usually<JackDevice<Tui>> {
|
||||||
let plugin = LV2Plugin::new(path)?;
|
let plugin = LV2Plugin::new(path)?;
|
||||||
jack_from_lv2(name, &plugin.plugin)?
|
jack_from_lv2(name, &plugin.plugin)?
|
||||||
.run(|ports|Box::new(Self {
|
.run(|ports|Box::new(Self {
|
||||||
_engine: Default::default(),
|
_engine: Default::default(),
|
||||||
|
jack: jack.clone(),
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
path: Some(String::from(path)),
|
path: Some(String::from(path)),
|
||||||
plugin: Some(PluginKind::LV2(plugin)),
|
plugin: Some(PluginKind::LV2(plugin)),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,23 @@
|
||||||
//! Plugin host
|
//! Plugin host
|
||||||
include!("lib.rs");
|
include!("lib.rs");
|
||||||
pub fn main () -> Usually<()> {
|
use tek_core::clap::{self, Parser};
|
||||||
Tui::run(Arc::new(RwLock::new(crate::Plugin::new("")?)))?;
|
pub fn main () -> Usually<()> { PluginCli::parse().run() }
|
||||||
Ok(())
|
#[derive(Debug, Parser)] #[command(version, about, long_about = None)] pub struct PluginCli {
|
||||||
|
/// Name of JACK client
|
||||||
|
#[arg(short, long)] name: Option<String>,
|
||||||
|
/// Path to plugin
|
||||||
|
#[arg(short, long)] path: Option<String>,
|
||||||
|
}
|
||||||
|
impl PluginCli {
|
||||||
|
fn run (&self) -> Usually<()> {
|
||||||
|
Tui::run(JackClient::new("tek_plugin")?.activate_with(|jack|{
|
||||||
|
let mut plugin = Plugin::new_lv2(
|
||||||
|
jack,
|
||||||
|
self.name.as_ref().map(|x|x.as_str()).unwrap_or("mixer"),
|
||||||
|
self.path.as_ref().expect("pass --path /to/lv2/plugin.so")
|
||||||
|
)?;
|
||||||
|
Ok(plugin)
|
||||||
|
})?)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
/// The sampler plugin plays sounds.
|
/// The sampler plugin plays sounds.
|
||||||
pub struct Sampler {
|
pub struct Sampler<E: Engine> {
|
||||||
|
_engine: PhantomData<E>,
|
||||||
|
pub jack: Arc<RwLock<JackClient>>,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub cursor: (usize, usize),
|
pub cursor: (usize, usize),
|
||||||
pub editing: Option<Arc<RwLock<Sample>>>,
|
pub editing: Option<Arc<RwLock<Sample>>>,
|
||||||
|
|
@ -14,7 +16,7 @@ pub struct Sampler {
|
||||||
pub output_gain: f32
|
pub output_gain: f32
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sampler {
|
impl<E: Engine> Sampler<E> {
|
||||||
pub fn from_edn <'e> (args: &[Edn<'e>]) -> Usually<JackDevice<Tui>> {
|
pub fn from_edn <'e> (args: &[Edn<'e>]) -> Usually<JackDevice<Tui>> {
|
||||||
let mut name = String::new();
|
let mut name = String::new();
|
||||||
let mut dir = String::new();
|
let mut dir = String::new();
|
||||||
|
|
@ -54,6 +56,7 @@ impl Sampler {
|
||||||
.audio_out("outL")
|
.audio_out("outL")
|
||||||
.audio_out("outR")
|
.audio_out("outR")
|
||||||
.run(|ports|Box::new(Self {
|
.run(|ports|Box::new(Self {
|
||||||
|
_engine: Default::default(),
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
cursor: (0, 0),
|
cursor: (0, 0),
|
||||||
editing: None,
|
editing: None,
|
||||||
|
|
@ -135,7 +138,7 @@ impl Sampler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Audio for Sampler {
|
impl<E: Engine> Audio for Sampler<E> {
|
||||||
fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
||||||
self.process_midi_in(scope);
|
self.process_midi_in(scope);
|
||||||
self.clear_output_buffer();
|
self.clear_output_buffer();
|
||||||
|
|
@ -144,7 +147,7 @@ impl Audio for Sampler {
|
||||||
Control::Continue
|
Control::Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Handle<Tui> for Sampler {
|
impl Handle<Tui> for Sampler<Tui> {
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
match from.event() {
|
match from.event() {
|
||||||
key!(KeyCode::Up) => {
|
key!(KeyCode::Up) => {
|
||||||
|
|
@ -188,7 +191,7 @@ impl Handle<Tui> for Sampler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Sampler {
|
impl Widget for Sampler<Tui> {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> {
|
fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> {
|
||||||
todo!()
|
todo!()
|
||||||
|
|
@ -198,7 +201,7 @@ impl Widget for Sampler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tui_render_sampler (sampler: &Sampler, to: &mut TuiOutput) -> Usually<()> {
|
pub fn tui_render_sampler (sampler: &Sampler<Tui>, to: &mut TuiOutput) -> Usually<()> {
|
||||||
let [x, y, _, height] = to.area();
|
let [x, y, _, height] = to.area();
|
||||||
let style = Style::default().gray();
|
let style = Style::default().gray();
|
||||||
let title = format!(" {} ({})", sampler.name, sampler.voices.read().unwrap().len());
|
let title = format!(" {} ({})", sampler.name, sampler.voices.read().unwrap().len());
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,22 @@
|
||||||
//! Sample player
|
//! Sample player
|
||||||
include!("lib.rs");
|
include!("lib.rs");
|
||||||
pub fn main () -> Usually<()> {
|
use tek_core::clap::{self, Parser};
|
||||||
Tui::run(Arc::new(RwLock::new(crate::Sampler::new("", None)?)))?;
|
pub fn main () -> Usually<()> { SamplerCli::parse().run() }
|
||||||
Ok(())
|
#[derive(Debug, Parser)] #[command(version, about, long_about = None)] pub struct SamplerCli {
|
||||||
|
/// Name of JACK client
|
||||||
|
#[arg(short, long)] name: Option<String>,
|
||||||
|
/// Path to plugin
|
||||||
|
#[arg(short, long)] path: Option<String>,
|
||||||
|
}
|
||||||
|
impl SamplerCli {
|
||||||
|
fn run (&self) -> Usually<()> {
|
||||||
|
Tui::run(JackClient::new("tek_sampler")?.activate_with(|jack|{
|
||||||
|
let mut plugin = Sampler::new(
|
||||||
|
jack,
|
||||||
|
self.name.as_ref().map(|x|x.as_str()).unwrap_or("mixer"),
|
||||||
|
)?;
|
||||||
|
Ok(plugin)
|
||||||
|
})?)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue