Skip to content

Commit 090e270

Browse files
committed
feat: update command structure and UI interactions for track and project management
1 parent 044716f commit 090e270

File tree

4 files changed

+353
-48
lines changed

4 files changed

+353
-48
lines changed

apps/egui_ui/src/app.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,7 @@ impl eframe::App for RysynApp {
9090
ui.close_menu();
9191
}
9292
if ui.button("Save Project").clicked() {
93-
self.send_command(Command::SaveProject {
94-
path: "project.rysyn".to_string()
95-
});
93+
self.send_command(Command::SaveProject { path: None });
9694
ui.close_menu();
9795
}
9896
ui.separator();
@@ -114,20 +112,23 @@ impl eframe::App for RysynApp {
114112

115113
ui.menu_button("Track", |ui| {
116114
if ui.button("Add Audio Track").clicked() {
117-
self.send_command(Command::AddTrack {
118-
track_type: rysyn_ffi_bridge::TrackType::Audio
115+
self.send_command(Command::CreateTrack {
116+
name: "Audio".to_string(),
117+
is_midi: false
119118
});
120119
ui.close_menu();
121120
}
122121
if ui.button("Add MIDI Track").clicked() {
123-
self.send_command(Command::AddTrack {
124-
track_type: rysyn_ffi_bridge::TrackType::Midi
122+
self.send_command(Command::CreateTrack {
123+
name: "MIDI".to_string(),
124+
is_midi: true
125125
});
126126
ui.close_menu();
127127
}
128128
if ui.button("Add Instrument Track").clicked() {
129-
self.send_command(Command::AddTrack {
130-
track_type: rysyn_ffi_bridge::TrackType::Instrument
129+
self.send_command(Command::CreateTrack {
130+
name: "Instrument".to_string(),
131+
is_midi: true
131132
});
132133
ui.close_menu();
133134
}
@@ -209,8 +210,7 @@ impl eframe::App for RysynApp {
209210
self.track_list.show(
210211
ui,
211212
&self.state,
212-
|cmd| self.send_command(cmd),
213-
self.timeline_zoom
213+
|cmd| self.send_command(cmd)
214214
);
215215
});
216216

apps/egui_ui/src/theme.rs

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
//! Theme Configuration
2+
//!
3+
//! Custom fonts and dark theme for professional DAW look
4+
5+
use eframe::egui::{self, Color32, FontData, FontDefinitions, FontFamily, Rounding, Style, Visuals};
6+
7+
/// Setup custom fonts for the DAW
8+
pub fn setup_custom_fonts(ctx: &egui::Context) {
9+
let mut fonts = FontDefinitions::default();
10+
11+
// You can add custom fonts here if needed
12+
// For now, we'll use the default fonts with adjusted sizes
13+
14+
// Example of how to add a custom font:
15+
// fonts.font_data.insert(
16+
// "inter".to_owned(),
17+
// FontData::from_static(include_bytes!("../assets/fonts/Inter-Regular.ttf")),
18+
// );
19+
// fonts.families.get_mut(&FontFamily::Proportional).unwrap()
20+
// .insert(0, "inter".to_owned());
21+
22+
ctx.set_fonts(fonts);
23+
}
24+
25+
/// Setup dark theme optimized for DAW workflow
26+
pub fn setup_dark_theme(ctx: &egui::Context) {
27+
let mut style = Style::default();
28+
29+
// Dark background colors
30+
let bg_dark = Color32::from_rgb(25, 25, 28);
31+
let bg_medium = Color32::from_rgb(35, 35, 40);
32+
let bg_light = Color32::from_rgb(45, 45, 50);
33+
let bg_widget = Color32::from_rgb(55, 55, 60);
34+
35+
// Accent colors
36+
let accent = Color32::from_rgb(100, 150, 255);
37+
let accent_hover = Color32::from_rgb(120, 170, 255);
38+
let accent_active = Color32::from_rgb(80, 130, 235);
39+
40+
// Text colors
41+
let text_primary = Color32::from_rgb(230, 230, 230);
42+
let text_secondary = Color32::from_rgb(160, 160, 160);
43+
let text_disabled = Color32::from_rgb(100, 100, 100);
44+
45+
// Configure visuals
46+
let visuals = Visuals {
47+
dark_mode: true,
48+
49+
// Override colors
50+
override_text_color: Some(text_primary),
51+
52+
// Widget visuals
53+
widgets: egui::style::Widgets {
54+
noninteractive: egui::style::WidgetVisuals {
55+
bg_fill: bg_medium,
56+
weak_bg_fill: bg_medium,
57+
bg_stroke: egui::Stroke::new(1.0, Color32::from_rgb(60, 60, 65)),
58+
rounding: Rounding::same(4.0),
59+
fg_stroke: egui::Stroke::new(1.0, text_secondary),
60+
expansion: 0.0,
61+
},
62+
inactive: egui::style::WidgetVisuals {
63+
bg_fill: bg_widget,
64+
weak_bg_fill: bg_widget,
65+
bg_stroke: egui::Stroke::new(1.0, Color32::from_rgb(70, 70, 75)),
66+
rounding: Rounding::same(4.0),
67+
fg_stroke: egui::Stroke::new(1.0, text_primary),
68+
expansion: 0.0,
69+
},
70+
hovered: egui::style::WidgetVisuals {
71+
bg_fill: Color32::from_rgb(65, 65, 70),
72+
weak_bg_fill: Color32::from_rgb(65, 65, 70),
73+
bg_stroke: egui::Stroke::new(1.0, accent_hover),
74+
rounding: Rounding::same(4.0),
75+
fg_stroke: egui::Stroke::new(1.0, text_primary),
76+
expansion: 1.0,
77+
},
78+
active: egui::style::WidgetVisuals {
79+
bg_fill: accent_active,
80+
weak_bg_fill: accent_active,
81+
bg_stroke: egui::Stroke::new(1.0, accent),
82+
rounding: Rounding::same(4.0),
83+
fg_stroke: egui::Stroke::new(2.0, text_primary),
84+
expansion: 1.0,
85+
},
86+
open: egui::style::WidgetVisuals {
87+
bg_fill: bg_light,
88+
weak_bg_fill: bg_light,
89+
bg_stroke: egui::Stroke::new(1.0, Color32::from_rgb(80, 80, 85)),
90+
rounding: Rounding::same(4.0),
91+
fg_stroke: egui::Stroke::new(1.0, text_primary),
92+
expansion: 0.0,
93+
},
94+
},
95+
96+
// Selection
97+
selection: egui::style::Selection {
98+
bg_fill: accent.linear_multiply(0.3),
99+
stroke: egui::Stroke::new(1.0, accent),
100+
},
101+
102+
// Hyperlinks
103+
hyperlink_color: accent,
104+
105+
// Backgrounds
106+
faint_bg_color: bg_dark,
107+
extreme_bg_color: Color32::from_rgb(15, 15, 18),
108+
code_bg_color: bg_medium,
109+
110+
// Warnings
111+
warn_fg_color: Color32::from_rgb(255, 200, 50),
112+
error_fg_color: Color32::from_rgb(255, 80, 80),
113+
114+
// Window
115+
window_rounding: Rounding::same(6.0),
116+
window_shadow: egui::epaint::Shadow {
117+
offset: [0, 4].into(),
118+
blur: 8.0,
119+
spread: 0.0,
120+
color: Color32::from_black_alpha(80),
121+
},
122+
window_fill: bg_medium,
123+
window_stroke: egui::Stroke::new(1.0, Color32::from_rgb(60, 60, 65)),
124+
window_highlight_topmost: true,
125+
126+
// Menu
127+
menu_rounding: Rounding::same(4.0),
128+
129+
// Panel
130+
panel_fill: bg_dark,
131+
132+
// Popup shadow
133+
popup_shadow: egui::epaint::Shadow {
134+
offset: [0, 2].into(),
135+
blur: 6.0,
136+
spread: 0.0,
137+
color: Color32::from_black_alpha(60),
138+
},
139+
140+
// Resize corner
141+
resize_corner_size: 12.0,
142+
143+
// Text cursor
144+
text_cursor: egui::style::TextCursorStyle {
145+
stroke: egui::Stroke::new(2.0, accent),
146+
preview: false,
147+
blink: true,
148+
on_duration: 0.5,
149+
off_duration: 0.5,
150+
},
151+
152+
// Clip rect margin
153+
clip_rect_margin: 3.0,
154+
155+
// Button frame
156+
button_frame: true,
157+
158+
// Collapsing header frame
159+
collapsing_header_frame: true,
160+
161+
// Indent
162+
indent_has_left_vline: true,
163+
164+
// Striped
165+
striped: false,
166+
167+
// Slider trailing fill
168+
slider_trailing_fill: true,
169+
170+
// Handle shape
171+
handle_shape: egui::style::HandleShape::Circle,
172+
173+
// Interact cursor
174+
interact_cursor: None,
175+
176+
// Image loading spinners
177+
image_loading_spinners: true,
178+
179+
// Numeric color space
180+
numeric_color_space: egui::style::NumericColorSpace::GammaByte,
181+
};
182+
183+
style.visuals = visuals;
184+
185+
// Spacing
186+
style.spacing.item_spacing = egui::vec2(8.0, 4.0);
187+
style.spacing.window_margin = egui::Margin::same(8.0);
188+
style.spacing.button_padding = egui::vec2(8.0, 4.0);
189+
style.spacing.indent = 18.0;
190+
style.spacing.slider_width = 100.0;
191+
192+
// Animation
193+
style.animation_time = 0.1;
194+
195+
ctx.set_style(style);
196+
}
197+
198+
/// Color palette for DAW elements
199+
pub struct DawColors;
200+
201+
impl DawColors {
202+
// Track colors (for automatic assignment)
203+
pub const TRACK_COLORS: [Color32; 8] = [
204+
Color32::from_rgb(100, 180, 255), // Blue
205+
Color32::from_rgb(255, 150, 100), // Orange
206+
Color32::from_rgb(150, 255, 150), // Green
207+
Color32::from_rgb(255, 150, 200), // Pink
208+
Color32::from_rgb(200, 150, 255), // Purple
209+
Color32::from_rgb(255, 255, 150), // Yellow
210+
Color32::from_rgb(150, 255, 255), // Cyan
211+
Color32::from_rgb(255, 180, 180), // Salmon
212+
];
213+
214+
// Transport colors
215+
pub const PLAY: Color32 = Color32::from_rgb(100, 200, 100);
216+
pub const STOP: Color32 = Color32::from_rgb(200, 200, 200);
217+
pub const RECORD: Color32 = Color32::from_rgb(255, 80, 80);
218+
pub const LOOP: Color32 = Color32::from_rgb(100, 180, 255);
219+
220+
// Meter colors
221+
pub const METER_GREEN: Color32 = Color32::from_rgb(50, 200, 100);
222+
pub const METER_YELLOW: Color32 = Color32::from_rgb(255, 200, 50);
223+
pub const METER_RED: Color32 = Color32::from_rgb(255, 50, 50);
224+
225+
// Grid colors
226+
pub const GRID_BAR: Color32 = Color32::from_rgb(60, 60, 65);
227+
pub const GRID_BEAT: Color32 = Color32::from_rgb(40, 40, 45);
228+
pub const PLAYHEAD: Color32 = Color32::from_rgb(255, 100, 100);
229+
230+
pub fn track_color(index: usize) -> Color32 {
231+
Self::TRACK_COLORS[index % Self::TRACK_COLORS.len()]
232+
}
233+
234+
pub fn track_color_u32(index: usize) -> u32 {
235+
let c = Self::track_color(index);
236+
((c.r() as u32) << 24) | ((c.g() as u32) << 16) | ((c.b() as u32) << 8) | 0xFF
237+
}
238+
}

crates/ffi_bridge/src/commands.rs

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,53 +15,63 @@ pub enum Command {
1515
ToggleRecord,
1616
ToggleLoop,
1717
SetPlayhead { beats: f64 },
18-
SetBpm { bpm: f64 },
19-
SetTimeSignature { num: u8, denom: u8 },
18+
SetTempo { bpm: f64 },
19+
SetTimeSignature { numerator: u32, denominator: u32 },
2020
SetLoopRegion { start_beats: f64, end_beats: f64 },
2121

2222
// === Project ===
2323
NewProject,
2424
LoadProject { path: String },
25-
SaveProject { path: String },
25+
SaveProject { path: Option<String> },
26+
SetProjectName { name: String },
27+
28+
// === Master ===
29+
SetMasterVolume { volume: f32 },
2630

2731
// === Tracks ===
28-
AddTrack { track_type: TrackType },
29-
RemoveTrack { track_id: u32 },
32+
CreateTrack { name: String, is_midi: bool },
33+
DeleteTrack { track_id: u32 },
34+
DuplicateTrack { track_id: u32 },
3035
RenameTrack { track_id: u32, name: String },
3136
SetTrackVolume { track_id: u32, volume: f32 },
3237
SetTrackPan { track_id: u32, pan: f32 },
33-
SetTrackMute { track_id: u32, mute: bool },
34-
SetTrackSolo { track_id: u32, solo: bool },
35-
SetTrackArmed { track_id: u32, armed: bool },
38+
SetTrackMute { track_id: u32, muted: bool },
39+
SetTrackSolo { track_id: u32, soloed: bool },
40+
SetTrackArm { track_id: u32, armed: bool },
3641
SetTrackColor { track_id: u32, color: u32 },
3742
MoveTrack { track_id: u32, new_index: u32 },
43+
SelectTrack { track_id: u32, exclusive: bool },
3844

3945
// === Clips ===
40-
AddAudioClip { track_id: u32, path: String, start_beats: f64 },
41-
AddMidiClip { track_id: u32, start_beats: f64, length_beats: f64 },
42-
RemoveClip { clip_id: u32 },
43-
MoveClip { clip_id: u32, new_track_id: u32, new_start_beats: f64 },
44-
ResizeClip { clip_id: u32, new_length_beats: f64 },
46+
ImportAudioFile { path: String },
47+
CreateAudioClip { track_id: u32, path: String, start_beats: f64 },
48+
CreateMidiClip { track_id: u32, start_beats: f64, length_beats: f64 },
49+
DeleteClip { clip_id: u32 },
50+
MoveClip { clip_id: u32, start_beats: f64, track_id: Option<u32> },
51+
ResizeClip { clip_id: u32, length_beats: f64 },
52+
RenameClip { clip_id: u32, name: String },
53+
SetClipColor { clip_id: u32, color: u32 },
4554
SplitClip { clip_id: u32, split_beats: f64 },
4655
DuplicateClip { clip_id: u32 },
4756
SelectClip { clip_id: u32, add_to_selection: bool },
4857
DeselectAllClips,
4958

5059
// === MIDI Editing ===
5160
AddMidiNote { clip_id: u32, note: u8, velocity: u8, start_beats: f64, length_beats: f64 },
52-
RemoveMidiNote { clip_id: u32, note_id: u32 },
61+
DeleteMidiNote { clip_id: u32, note_id: u32 },
5362
MoveMidiNote { clip_id: u32, note_id: u32, new_note: u8, new_start_beats: f64 },
5463

5564
// === Plugins (VST3) ===
56-
ScanPlugins,
57-
LoadPlugin { track_id: u32, slot: u32, plugin_id: String },
58-
UnloadPlugin { track_id: u32, slot: u32 },
65+
RescanPlugins,
66+
LoadPlugin { track_id: u32, plugin_id: String, slot: Option<u32> },
67+
RemovePlugin { track_id: u32, slot: u32 },
5968
BypassPlugin { track_id: u32, slot: u32, bypass: bool },
6069
OpenPluginEditor { track_id: u32, slot: u32 },
6170
ClosePluginEditor { track_id: u32, slot: u32 },
6271
SetPluginParameter { track_id: u32, slot: u32, param_id: u32, value: f32 },
6372

6473
// === Audio Settings ===
74+
OpenAudioSettings,
6575
SetAudioDevice { device_name: String },
6676
SetSampleRate { rate: u32 },
6777
SetBufferSize { size: u32 },
@@ -70,9 +80,14 @@ pub enum Command {
7080
RunScript { script: String },
7181
LoadScriptPlugin { path: String },
7282

73-
// === Misc ===
83+
// === Edit ===
7484
Undo,
7585
Redo,
86+
Cut,
87+
Copy,
88+
Paste,
89+
Delete,
90+
SelectAll,
7691
}
7792

7893
/// Track type for creation

0 commit comments

Comments
 (0)