diff --git a/Cargo.toml b/Cargo.toml index 896dc81..320e7f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,8 @@ edition = "2018" [dependencies] dirs = "^3.0.1" +eframe = "^0.11.0" +egui = "^0.11.0" gdk = "^0.13.2" gio = "^0" gtk = "^0" diff --git a/src/main.rs b/src/main.rs index 6e816a6..ac81e82 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ #![windows_subsystem = "windows"] -use gio::prelude::*; -use gtk::prelude::*; -use gtk::Orientation; +// use gio::prelude::*; +// use gtk::prelude::*; +// use gtk::Orientation; use rodio::{Sink, Source}; use serde_derive::{Serialize, Deserialize}; use std::env::args; @@ -11,6 +11,8 @@ use std::io::{BufReader, Write, Read}; use std::path::PathBuf; use std::process::Command; +mod ui_egui; + const SPACING: i32 = 16; #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] @@ -77,20 +79,20 @@ fn file_manager() -> &'static str { "xdg-open" } -fn error_popup(message: &str) { - let popup = gtk::Window::new(gtk::WindowType::Toplevel); - popup.set_title("error"); - popup.set_border_width(SPACING as u32); - popup.set_position(gtk::WindowPosition::Center); - popup.set_default_size(256, 64); - popup.set_type_hint(gdk::WindowTypeHint::Dialog); - popup.set_resizable(false); - - let message = gtk::Label::new(Some(message)); - popup.add(&message); - - popup.show_all(); -} +// fn error_popup(message: &str) { +// let popup = gtk::Window::new(gtk::WindowType::Toplevel); +// popup.set_title("error"); +// popup.set_border_width(SPACING as u32); +// popup.set_position(gtk::WindowPosition::Center); +// popup.set_default_size(256, 64); +// popup.set_type_hint(gdk::WindowTypeHint::Dialog); +// popup.set_resizable(false); +// +// let message = gtk::Label::new(Some(message)); +// popup.add(&message); +// +// popup.show_all(); +// } fn get_data_dir() -> PathBuf { let mut data_dir = dirs::data_dir().expect("Couldn't find user data directory"); @@ -104,46 +106,14 @@ fn get_data_dir() -> PathBuf { data_dir } -fn build_ui(application: >k::Application) { - let window = gtk::ApplicationWindow::new(application); +struct Sound { + name: String, + sink: Sink, + volume: f64, +} - window.set_title("lull"); - window.set_border_width(SPACING as u32); - window.set_position(gtk::WindowPosition::Center); - window.set_default_size(256, 128); - - if let Some(config) = load_config() { - window.move_(config.position.0, config.position.1); - window.resize(config.size.0, config.size.1); - } - - let button_manage_sounds = gtk::Button::with_label("manage sounds"); - - button_manage_sounds.connect_clicked(|_| { - let mut file_manager = Command::new(file_manager()); - file_manager.arg(get_data_dir()); - file_manager.output().unwrap(); - }); - - let sounds_manage = gtk::Box::new(Orientation::Vertical, SPACING); - let columns = gtk::Box::new(Orientation::Horizontal, SPACING); - let column_labels = gtk::Box::new(Orientation::Vertical, SPACING); - let column_sliders = gtk::Box::new(Orientation::Vertical, SPACING); - - columns.set_homogeneous(false); - column_labels.set_homogeneous(true); - column_sliders.set_homogeneous(true); - column_labels.set_property_expand(false); - column_sliders.set_property_expand(true); - column_sliders.set_property_width_request(128); - - window.add(&sounds_manage); - sounds_manage.add(&columns); - sounds_manage.add(&button_manage_sounds); - columns.add(&column_labels); - columns.add(&column_sliders); - - let device = rodio::default_output_device().unwrap(); +fn get_sounds(device: &rodio::Device) -> Vec { + let mut sounds = Vec::new(); let mut paths = std::fs::read_dir(get_data_dir()) .expect("Couldn't read lull sounds directory") @@ -154,7 +124,7 @@ fn build_ui(application: >k::Application) { paths.sort(); for path in paths { - let name: &str = path.file_stem().unwrap().to_str().unwrap(); + let name = path.file_stem().unwrap().to_str().unwrap().to_string(); let file = File::open(&path) .expect("Couldn't open audio file"); @@ -163,76 +133,151 @@ fn build_ui(application: >k::Application) { BufReader::new(file) ); - if source.is_err() { - error_popup(&format!( - "Couldn't parse file {}. \n{}.", - path.to_str().unwrap(), - source.err().unwrap() - )); - continue; - } - let source = source.unwrap().repeat_infinite(); - let sink = Sink::new(&device); + let sink = rodio::Sink::new(&device); sink.append(source); sink.pause(); - let label = gtk::Label::new(Some(name)); - label.set_halign(gtk::Align::End); - column_labels.add(&label); - - let adjustment = gtk::Adjustment::new( - 0.0, - 0.0, - 1.0, - 0.0, - 0.0, - 0.0 - ); - - let slider = gtk::Scale::new( - Orientation::Horizontal, - Some(&adjustment) - ); - - slider.set_draw_value(false); - - slider.connect_value_changed(move |scale| { - let volume = scale.get_value(); - - if volume == 0. { - sink.pause(); - } else { - sink.play(); - sink.set_volume(volume as f32); - } - }); - - column_sliders.add(&slider); + sounds.push(Sound { name, sink, volume: 0.0 }); } - window.show_all(); - - window.connect_delete_event(|window, _event| { - save_config(Config { - position: window.get_position(), - size: window.get_size() - }); - - Inhibit(false) - }); + sounds } +// fn build_ui(application: >k::Application) { +// let window = gtk::ApplicationWindow::new(application); +// +// window.set_title("lull"); +// window.set_border_width(SPACING as u32); +// window.set_position(gtk::WindowPosition::Center); +// window.set_default_size(256, 128); +// +// if let Some(config) = load_config() { +// window.move_(config.position.0, config.position.1); +// window.resize(config.size.0, config.size.1); +// } +// +// let button_manage_sounds = gtk::Button::with_label("manage sounds"); +// +// button_manage_sounds.connect_clicked(|_| { +// let mut file_manager = Command::new(file_manager()); +// file_manager.arg(get_data_dir()); +// file_manager.output().unwrap(); +// }); +// +// let sounds_manage = gtk::Box::new(Orientation::Vertical, SPACING); +// let columns = gtk::Box::new(Orientation::Horizontal, SPACING); +// let column_labels = gtk::Box::new(Orientation::Vertical, SPACING); +// let column_sliders = gtk::Box::new(Orientation::Vertical, SPACING); +// +// columns.set_homogeneous(false); +// column_labels.set_homogeneous(true); +// column_sliders.set_homogeneous(true); +// column_labels.set_property_expand(false); +// column_sliders.set_property_expand(true); +// column_sliders.set_property_width_request(128); +// +// window.add(&sounds_manage); +// sounds_manage.add(&columns); +// sounds_manage.add(&button_manage_sounds); +// columns.add(&column_labels); +// columns.add(&column_sliders); +// +// let device = rodio::default_output_device().unwrap(); +// +// let mut paths = std::fs::read_dir(get_data_dir()) +// .expect("Couldn't read lull sounds directory") +// .map(|res| res.map(|e| e.path())) +// .collect::, std::io::Error>>() +// .expect("Couldn't read files from lull sounds directory"); +// +// paths.sort(); +// +// for path in paths { +// let name: &str = path.file_stem().unwrap().to_str().unwrap(); +// +// let file = File::open(&path) +// .expect("Couldn't open audio file"); +// +// let source = rodio::Decoder::new( +// BufReader::new(file) +// ); +// +// if source.is_err() { +// error_popup(&format!( +// "Couldn't parse file {}. \n{}.", +// path.to_str().unwrap(), +// source.err().unwrap() +// )); +// continue; +// } +// +// let source = source.unwrap().repeat_infinite(); +// +// let sink = Sink::new(&device); +// sink.append(source); +// sink.pause(); +// +// let label = gtk::Label::new(Some(name)); +// label.set_halign(gtk::Align::End); +// column_labels.add(&label); +// +// let adjustment = gtk::Adjustment::new( +// 0.0, +// 0.0, +// 1.0, +// 0.0, +// 0.0, +// 0.0 +// ); +// +// let slider = gtk::Scale::new( +// Orientation::Horizontal, +// Some(&adjustment) +// ); +// +// slider.set_draw_value(false); +// +// slider.connect_value_changed(move |scale| { +// let volume = scale.get_value(); +// +// if volume == 0. { +// sink.pause(); +// } else { +// sink.play(); +// sink.set_volume(volume as f32); +// } +// }); +// +// column_sliders.add(&slider); +// } +// +// window.show_all(); +// +// window.connect_delete_event(|window, _event| { +// save_config(Config { +// position: window.get_position(), +// size: window.get_size() +// }); +// +// Inhibit(false) +// }); +// } + +// fn main() { +// let application = gtk::Application::new( +// Some("dev.tinybird.max.lull"), +// Default::default() +// ).expect("Initialization failed..."); +// +// application.connect_activate(|app| { +// build_ui(app); +// }); +// +// application.run(&args().collect::>()); +// } + fn main() { - let application = gtk::Application::new( - Some("dev.tinybird.max.lull"), - Default::default() - ).expect("Initialization failed..."); - - application.connect_activate(|app| { - build_ui(app); - }); - - application.run(&args().collect::>()); + eframe::run_native(Box::new(ui_egui::State::default())); } diff --git a/src/ui_egui.rs b/src/ui_egui.rs new file mode 100644 index 0000000..8bb58af --- /dev/null +++ b/src/ui_egui.rs @@ -0,0 +1,58 @@ +use eframe::{egui, epi}; +use std::process::Command; +use crate::{Sound, file_manager}; + +pub struct State { + device: rodio::Device, + sounds: Vec, +} + +impl Default for State { + fn default() -> Self { + let device = rodio::default_output_device().unwrap(); + let mut sounds = crate::get_sounds(&device); + + Self { device, sounds } + } +} + +impl epi::App for State { + fn update(&mut self, ctx: &egui::CtxRef, _frame: &mut epi::Frame<'_>) { + let State { device: _device, sounds} = self; + + for sound in sounds.into_iter() { + if sound.volume > 0.0 { + sound.sink.set_volume(sound.volume as f32); + sound.sink.play(); + } else { + sound.sink.pause(); + } + } + + egui::CentralPanel::default().show(ctx, |ui| { + for sound in sounds { + ui.separator(); + ui.label(&sound.name); + + ui.add( + egui::Slider::new( + &mut sound.volume, + 0.0..=1.0 + ).show_value(false) + ); + } + + ui.separator(); + + if ui.button("manage sounds").clicked() { + let mut file_manager = Command::new(file_manager()); + file_manager.arg(crate::get_data_dir()); + file_manager.output().unwrap(); + } + }); + } + + fn name(&self) -> &str { + "lull" + } +}