getting there

This commit is contained in:
Josh Jeppson 2024-11-14 09:16:24 -07:00
parent 3234c4dae2
commit 2629a52be0
2 changed files with 61 additions and 9 deletions

View file

@ -7,4 +7,5 @@ edition = "2021"
clap = { version = "4.5.20", features = ["derive"] } clap = { version = "4.5.20", features = ["derive"] }
eframe = "0.29.1" eframe = "0.29.1"
egui = "0.29.1" egui = "0.29.1"
egui_flex = "0.1.1"
jack = "0.13.0" jack = "0.13.0"

View file

@ -2,13 +2,19 @@
use clap::Parser; use clap::Parser;
use eframe::egui::*; use eframe::egui::*;
use egui_flex::{item, Flex, FlexAlignContent};
use std::sync::{Arc, Mutex};
fn main() -> eframe::Result { fn main() -> eframe::Result {
let args = Args::parse(); let args = Args::parse();
let eq_box = Box::<FslcMix>::new(FslcMix::new(args.channels)); let shared_mix = Arc::new(Mutex::new(FslcMix::new(args.channels)));
let app = MixApp {
mix : shared_mix.clone(),
};
let options = eframe::NativeOptions { let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default() viewport: egui::ViewportBuilder::default()
.with_inner_size([eq_box.ui_size[0], eq_box.ui_size[1]]), .with_inner_size([500.0, 325.0]),
..Default::default() ..Default::default()
}; };
eframe::run_native( eframe::run_native(
@ -18,11 +24,46 @@ fn main() -> eframe::Result {
// Dark theme // Dark theme
cc.egui_ctx.set_theme(egui::Theme::Dark); cc.egui_ctx.set_theme(egui::Theme::Dark);
// egui_extras::install_image_loaders(&cc.egui_ctx); // egui_extras::install_image_loaders(&cc.egui_ctx);
Ok(eq_box) Ok(Box::new(app))
}), }),
) )
} }
fn start_jack(mixer: Arc<Mutex<FslcMix>>) {
let unlocked_mixer = mixer.lock().unwrap();
let (client, _status) = jack::Client::new("fslcmix", jack::ClientOptions::default()).unwrap();
let in_ports = unlocked_mixer.channels.iter().map(
|channel| channel.declare_jack_port(&client)).collect::<Vec<_>>();
let mut out_port = client.register_port("Master Out", jack::AudioOut::default()).unwrap();
let process_callback = {
let mixer = Arc::clone(&mixer);
move |_: &jack::Client, ps: &jack::ProcessScope| -> jack::Control {
let ins = in_ports.iter().map(|port| port.as_slice(ps)).collect::<Vec<_>>();
let out = out_port.as_mut_slice(ps);
if let Ok(mut owned_mixer) = mixer.lock() {
owned_mixer.mix(ins, out);
} else {
}
jack::Control::Continue
}
};
// Create process and activate the client
let process = jack::contrib::ClosureProcessHandler::new(process_callback);
client.activate_async((), process).unwrap();
}
struct MixApp {
mix: Arc<Mutex<FslcMix>>,
}
impl eframe::App for MixApp {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
let mut owned_mix = self.mix.lock().unwrap();
owned_mix.update(ctx, frame);
}
}
/// A mixer that supports an arbitrary number of channels. /// A mixer that supports an arbitrary number of channels.
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(version, about, long_about = None)] #[command(version, about, long_about = None)]
@ -102,11 +143,14 @@ impl FslcMix {
} }
self.master.last = output[output.len() - 1]; self.master.last = output[output.len() - 1];
} }
}
impl eframe::App for FslcMix {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
// }
// impl eframe::App for FslcMix {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
//egui::Window::new("Mixer (FSLCMix)") //egui::Window::new("Mixer (FSLCMix)")
// .default_pos([100.0, 100.0]) // .default_pos([100.0, 100.0])
// .title_bar(true) // .title_bar(true)
@ -174,7 +218,10 @@ impl MixChannel {
ui.label(format!("Peak: {} dB", self.max.log10())); ui.label(format!("Peak: {} dB", self.max.log10()));
}); });
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.add(egui::Slider::new(&mut self.gain, 0.0..=1.2).text("Gain").vertical()); ui.spacing_mut().slider_width = 175.0;
ui.add(egui::Slider::new(&mut self.gain, 0.0..=1.2)
//.text("Gain")
.vertical());
self.levels_bar(ui, self.last); self.levels_bar(ui, self.last);
}); });
@ -198,11 +245,15 @@ impl MixChannel {
let filled_rect = Rect::from_min_max(rect.min, rect.min + vec2(rect.width(), filled_height)); let filled_rect = Rect::from_min_max(rect.min, rect.min + vec2(rect.width(), filled_height));
let remaining_rect = Rect::from_min_max(filled_rect.max, rect.max); let remaining_rect = Rect::from_min_max(filled_rect.max, rect.max);
painter.rect_filled(filled_rect, 0.0, Color32::from_rgb(0, 200, 0)); painter.rect_filled(filled_rect, 0.0, Color32::from_rgb(0, 200, 0));
painter.rect_filled(remaining_rect, 0.0, Color32::from_rgb(200, 0, 0)); painter.rect_filled(remaining_rect, 0.0, Color32::from_rgb(200, 0, 0));
painter.rect_stroke(rect, 0.0, (1.0, Color32::GRAY)); painter.rect_stroke(rect, 0.0, (1.0, Color32::DARK_GRAY));
response.on_hover_cursor(egui::CursorIcon::PointingHand) response.on_hover_cursor(egui::CursorIcon::PointingHand)
.on_hover_text(format!("{:.1} db", value.log10())); .on_hover_text(format!("{:.1} db", value.log10()));
} }
fn declare_jack_port(&self, client : &jack::Client) -> jack::Port<jack::AudioIn> {
client.register_port(&self.channel_name, jack::AudioIn::default()).unwrap()
}
} }
impl Default for MixChannel { impl Default for MixChannel {