1use crate::clap::{ClapParameterInfo, ClapPluginInfo};
2#[cfg(all(unix, not(target_os = "macos")))]
3use crate::lv2::Lv2PluginInfo;
4use crate::midi::io::MidiEvent;
5use crate::vst3::Vst3PluginInfo;
6use crate::{kind::Kind, mutex::UnsafeMutex, track::Track};
7use std::sync::{Arc, atomic::AtomicBool};
8use tokio::sync::mpsc::Sender;
9
10#[derive(Clone, Debug)]
11pub struct MidiNoteData {
12 pub start_sample: usize,
13 pub length_samples: usize,
14 pub pitch: u8,
15 pub velocity: u8,
16 pub channel: u8,
17}
18
19#[derive(Clone, Debug)]
20pub struct MidiControllerData {
21 pub sample: usize,
22 pub controller: u8,
23 pub value: u8,
24 pub channel: u8,
25}
26
27#[derive(Debug, Clone)]
28pub struct MidiRawEventData {
29 pub sample: usize,
30 pub data: Vec<u8>,
31}
32
33#[derive(Clone, Debug)]
34pub struct HwMidiEvent {
35 pub device: String,
36 pub event: MidiEvent,
37}
38
39#[derive(Clone, Debug)]
40pub struct OfflineAutomationPoint {
41 pub sample: usize,
42 pub value: f32,
43}
44
45#[derive(Clone, Debug)]
46pub enum OfflineAutomationTarget {
47 Volume,
48 Balance,
49 Mute,
50 #[cfg(all(unix, not(target_os = "macos")))]
51 Lv2Parameter {
52 instance_id: usize,
53 index: u32,
54 min: f32,
55 max: f32,
56 },
57 Vst3Parameter {
58 instance_id: usize,
59 param_id: u32,
60 },
61 ClapParameter {
62 instance_id: usize,
63 param_id: u32,
64 min: f64,
65 max: f64,
66 },
67}
68
69#[derive(Clone, Debug)]
70pub struct OfflineAutomationLane {
71 pub target: OfflineAutomationTarget,
72 pub points: Vec<OfflineAutomationPoint>,
73}
74
75#[derive(Clone, Debug)]
76pub struct OfflineBounceWork {
77 pub state: Arc<UnsafeMutex<crate::state::State>>,
78 pub track_name: String,
79 pub output_path: String,
80 pub start_sample: usize,
81 pub length_samples: usize,
82 pub tempo_bpm: f64,
83 pub tsig_num: u16,
84 pub tsig_denom: u16,
85 pub automation_lanes: Vec<OfflineAutomationLane>,
86 pub cancel: Arc<AtomicBool>,
87}
88
89#[derive(Clone, Debug, Default)]
90pub struct PitchCorrectionPointData {
91 pub start_sample: usize,
92 pub length_samples: usize,
93 pub detected_midi_pitch: f32,
94 pub target_midi_pitch: f32,
95 pub clarity: f32,
96}
97
98#[derive(Clone, Debug)]
99pub struct ClipMoveFrom {
100 pub track_name: String,
101 pub clip_index: usize,
102}
103
104#[derive(Clone, Debug)]
105pub struct ClipMoveTo {
106 pub track_name: String,
107 pub sample_offset: usize,
108 pub input_channel: usize,
109}
110
111#[cfg(unix)]
112#[derive(Clone, Debug, PartialEq, Eq, Hash)]
113pub enum PluginGraphNode {
114 TrackInput,
115 TrackOutput,
116 Lv2PluginInstance(usize),
117 Vst3PluginInstance(usize),
118 ClapPluginInstance(usize),
119}
120
121#[cfg(unix)]
122#[derive(Clone, Debug, PartialEq)]
123pub struct PluginGraphPlugin {
124 pub node: PluginGraphNode,
125 pub instance_id: usize,
126 pub format: String,
127 pub uri: String,
128 pub plugin_id: String,
129 pub name: String,
130 pub main_audio_inputs: usize,
131 pub main_audio_outputs: usize,
132 pub audio_inputs: usize,
133 pub audio_outputs: usize,
134 pub midi_inputs: usize,
135 pub midi_outputs: usize,
136 pub state: Option<Lv2PluginState>,
137}
138
139#[cfg(unix)]
140#[derive(Clone, Debug, PartialEq)]
141pub struct Lv2StatePortValue {
142 pub index: u32,
143 pub value: f32,
144}
145
146#[cfg(unix)]
147#[derive(Clone, Debug, PartialEq, Eq)]
148pub struct Lv2StateProperty {
149 pub key_uri: String,
150 pub type_uri: String,
151 pub flags: u32,
152 pub value: Vec<u8>,
153}
154
155#[cfg(unix)]
156#[derive(Clone, Debug, PartialEq)]
157pub struct Lv2PluginState {
158 pub port_values: Vec<Lv2StatePortValue>,
159 pub properties: Vec<Lv2StateProperty>,
160}
161
162#[cfg(all(unix, not(target_os = "macos")))]
163#[derive(Clone, Debug, PartialEq)]
164pub struct Lv2ControlPortInfo {
165 pub index: u32,
166 pub name: String,
167 pub min: f32,
168 pub max: f32,
169 pub value: f32,
170}
171
172#[cfg(unix)]
173#[derive(Clone, Debug, PartialEq, Eq)]
174pub struct PluginGraphConnection {
175 pub from_node: PluginGraphNode,
176 pub from_port: usize,
177 pub to_node: PluginGraphNode,
178 pub to_port: usize,
179 pub kind: Kind,
180}
181
182#[cfg(unix)]
183pub type PluginGraphSnapshot = (Vec<PluginGraphPlugin>, Vec<PluginGraphConnection>);
184
185#[derive(Clone, Debug, PartialEq, Eq, Hash)]
187pub enum Vst3GraphNode {
188 TrackInput,
189 TrackOutput,
190 PluginInstance(usize),
191}
192
193#[derive(Clone, Debug)]
194pub struct Vst3GraphPlugin {
195 pub instance_id: usize,
196 pub name: String,
197 pub path: String,
198 pub audio_inputs: usize,
199 pub audio_outputs: usize,
200 pub parameters: Vec<crate::vst3::port::ParameterInfo>,
201}
202
203#[derive(Clone, Debug, PartialEq, Eq)]
204pub struct Vst3GraphConnection {
205 pub from_node: Vst3GraphNode,
206 pub from_port: usize,
207 pub to_node: Vst3GraphNode,
208 pub to_port: usize,
209 pub kind: Kind,
210}
211
212#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
213pub struct MidiLearnBinding {
214 pub device: Option<String>,
215 pub channel: u8,
216 pub cc: u8,
217}
218
219#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
220pub enum TrackMidiLearnTarget {
221 Volume,
222 Balance,
223 Mute,
224 Solo,
225 Arm,
226 InputMonitor,
227 DiskMonitor,
228}
229
230#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
231pub enum GlobalMidiLearnTarget {
232 PlayPause,
233 Stop,
234 RecordToggle,
235}
236
237#[derive(Clone, Debug)]
238pub enum Action {
239 Quit,
240 Play,
241 Stop,
242 TransportPosition(usize),
243 SetLoopEnabled(bool),
244 SetLoopRange(Option<(usize, usize)>),
245 SetPunchEnabled(bool),
246 SetPunchRange(Option<(usize, usize)>),
247 SetMetronomeEnabled(bool),
248 SetTempo(f64),
249 SetTimeSignature {
250 numerator: u16,
251 denominator: u16,
252 },
253 SetClipPlaybackEnabled(bool),
254 SetRecordEnabled(bool),
255 SetSessionPath(String),
256 BeginHistoryGroup,
257 EndHistoryGroup,
258 ClearHistory,
259 BeginSessionRestore,
260 EndSessionRestore,
261 AddTrack {
262 name: String,
263 audio_ins: usize,
264 midi_ins: usize,
265 audio_outs: usize,
266 midi_outs: usize,
267 },
268 TrackAddAudioInput(String),
269 TrackAddAudioOutput(String),
270 TrackRemoveAudioInput(String),
271 TrackRemoveAudioOutput(String),
272 AddClip {
273 name: String,
274 track_name: String,
275 start: usize,
276 length: usize,
277 offset: usize,
278 input_channel: usize,
279 muted: bool,
280 kind: Kind,
281 fade_enabled: bool,
282 fade_in_samples: usize,
283 fade_out_samples: usize,
284 source_name: Option<String>,
285 source_offset: Option<usize>,
286 source_length: Option<usize>,
287 preview_name: Option<String>,
288 pitch_correction_points: Vec<PitchCorrectionPointData>,
289 pitch_correction_frame_likeness: Option<f32>,
290 pitch_correction_inertia_ms: Option<u16>,
291 pitch_correction_formant_compensation: Option<bool>,
292 },
293 RemoveClip {
294 track_name: String,
295 kind: Kind,
296 clip_indices: Vec<usize>,
297 },
298 SetClipFade {
299 track_name: String,
300 clip_index: usize,
301 kind: Kind,
302 fade_enabled: bool,
303 fade_in_samples: usize,
304 fade_out_samples: usize,
305 },
306 SetClipBounds {
307 track_name: String,
308 clip_index: usize,
309 kind: Kind,
310 start: usize,
311 length: usize,
312 offset: usize,
313 },
314 SetClipMuted {
315 track_name: String,
316 clip_index: usize,
317 kind: Kind,
318 muted: bool,
319 },
320 SetClipPitchCorrection {
321 track_name: String,
322 clip_index: usize,
323 preview_name: Option<String>,
324 source_name: Option<String>,
325 source_offset: Option<usize>,
326 source_length: Option<usize>,
327 pitch_correction_points: Vec<PitchCorrectionPointData>,
328 pitch_correction_frame_likeness: Option<f32>,
329 pitch_correction_inertia_ms: Option<u16>,
330 pitch_correction_formant_compensation: Option<bool>,
331 },
332 RenameClip {
333 track_name: String,
334 kind: Kind,
335 clip_index: usize,
336 new_name: String,
337 },
338 RenameTrack {
339 old_name: String,
340 new_name: String,
341 },
342 RemoveTrack(String),
343 TrackLevel(String, f32),
344 TrackBalance(String, f32),
345 TrackAutomationLevel(String, f32),
346 TrackAutomationBalance(String, f32),
347 TrackAutomationMute(String, bool),
348 TrackMeters {
349 track_name: String,
350 output_db: Vec<f32>,
351 },
352 RequestMeterSnapshot,
353 MeterSnapshot {
354 hw_out_db: Arc<Vec<f32>>,
355 track_meters: Arc<Vec<(String, Vec<f32>)>>,
356 },
357 TrackToggleArm(String),
358 TrackToggleMute(String),
359 TrackToggleSolo(String),
360 TrackToggleInputMonitor(String),
361 TrackToggleDiskMonitor(String),
362 TrackArmMidiLearn {
363 track_name: String,
364 target: TrackMidiLearnTarget,
365 },
366 GlobalArmMidiLearn {
367 target: GlobalMidiLearnTarget,
368 },
369 TrackSetMidiLearnBinding {
370 track_name: String,
371 target: TrackMidiLearnTarget,
372 binding: Option<MidiLearnBinding>,
373 },
374 SetGlobalMidiLearnBinding {
375 target: GlobalMidiLearnTarget,
376 binding: Option<MidiLearnBinding>,
377 },
378 TrackSetVcaMaster {
379 track_name: String,
380 master_track: Option<String>,
381 },
382 TrackSetMidiLaneChannel {
383 track_name: String,
384 lane: usize,
385 channel: Option<u8>,
386 },
387 TrackSetFrozen {
388 track_name: String,
389 frozen: bool,
390 },
391 TrackOfflineBounce {
392 track_name: String,
393 output_path: String,
394 start_sample: usize,
395 length_samples: usize,
396 automation_lanes: Vec<OfflineAutomationLane>,
397 },
398 TrackOfflineBounceCancel {
399 track_name: String,
400 },
401 TrackOfflineBounceCanceled {
402 track_name: String,
403 },
404 TrackOfflineBounceProgress {
405 track_name: String,
406 progress: f32,
407 operation: Option<String>,
408 },
409 PianoKey {
410 track_name: String,
411 note: u8,
412 velocity: u8,
413 on: bool,
414 },
415 ModifyMidiNotes {
416 track_name: String,
417 clip_index: usize,
418 note_indices: Vec<usize>,
419 new_notes: Vec<MidiNoteData>,
420 old_notes: Vec<MidiNoteData>,
421 },
422 ModifyMidiControllers {
423 track_name: String,
424 clip_index: usize,
425 controller_indices: Vec<usize>,
426 new_controllers: Vec<MidiControllerData>,
427 old_controllers: Vec<MidiControllerData>,
428 },
429 DeleteMidiControllers {
430 track_name: String,
431 clip_index: usize,
432 controller_indices: Vec<usize>,
433 deleted_controllers: Vec<(usize, MidiControllerData)>,
434 },
435 InsertMidiControllers {
436 track_name: String,
437 clip_index: usize,
438 controllers: Vec<(usize, MidiControllerData)>,
439 },
440 DeleteMidiNotes {
441 track_name: String,
442 clip_index: usize,
443 note_indices: Vec<usize>,
444 deleted_notes: Vec<(usize, MidiNoteData)>,
445 },
446 InsertMidiNotes {
447 track_name: String,
448 clip_index: usize,
449 notes: Vec<(usize, MidiNoteData)>,
450 },
451 SetMidiSysExEvents {
452 track_name: String,
453 clip_index: usize,
454 new_sysex_events: Vec<MidiRawEventData>,
455 old_sysex_events: Vec<MidiRawEventData>,
456 },
457 #[cfg(all(unix, not(target_os = "macos")))]
458 TrackLoadLv2Plugin {
459 track_name: String,
460 plugin_uri: String,
461 },
462 TrackClearDefaultPassthrough {
463 track_name: String,
464 },
465 #[cfg(all(unix, not(target_os = "macos")))]
466 TrackSetLv2PluginState {
467 track_name: String,
468 instance_id: usize,
469 state: Lv2PluginState,
470 },
471 #[cfg(all(unix, not(target_os = "macos")))]
472 TrackUnloadLv2PluginInstance {
473 track_name: String,
474 instance_id: usize,
475 },
476 #[cfg(all(unix, not(target_os = "macos")))]
477 TrackGetLv2PluginControls {
478 track_name: String,
479 instance_id: usize,
480 },
481 #[cfg(all(unix, not(target_os = "macos")))]
482 TrackLv2PluginControls {
483 track_name: String,
484 instance_id: usize,
485 controls: Vec<Lv2ControlPortInfo>,
486 instance_access_handle: Option<usize>,
487 },
488 #[cfg(all(unix, not(target_os = "macos")))]
489 TrackGetLv2Midnam {
490 track_name: String,
491 },
492 #[cfg(all(unix, not(target_os = "macos")))]
493 TrackLv2Midnam {
494 track_name: String,
495 note_names: std::collections::HashMap<u8, String>,
496 },
497 #[cfg(all(unix, not(target_os = "macos")))]
498 TrackSetLv2ControlValue {
499 track_name: String,
500 instance_id: usize,
501 index: u32,
502 value: f32,
503 },
504 #[cfg(unix)]
505 TrackGetPluginGraph {
506 track_name: String,
507 },
508 #[cfg(unix)]
509 TrackPluginGraph {
510 track_name: String,
511 plugins: Vec<PluginGraphPlugin>,
512 connections: Vec<PluginGraphConnection>,
513 },
514 #[cfg(unix)]
515 TrackConnectPluginAudio {
516 track_name: String,
517 from_node: PluginGraphNode,
518 from_port: usize,
519 to_node: PluginGraphNode,
520 to_port: usize,
521 },
522 #[cfg(unix)]
523 TrackConnectPluginMidi {
524 track_name: String,
525 from_node: PluginGraphNode,
526 from_port: usize,
527 to_node: PluginGraphNode,
528 to_port: usize,
529 },
530 #[cfg(unix)]
531 TrackDisconnectPluginAudio {
532 track_name: String,
533 from_node: PluginGraphNode,
534 from_port: usize,
535 to_node: PluginGraphNode,
536 to_port: usize,
537 },
538 #[cfg(unix)]
539 TrackDisconnectPluginMidi {
540 track_name: String,
541 from_node: PluginGraphNode,
542 from_port: usize,
543 to_node: PluginGraphNode,
544 to_port: usize,
545 },
546 #[cfg(all(unix, not(target_os = "macos")))]
547 ListLv2Plugins,
548 #[cfg(all(unix, not(target_os = "macos")))]
549 Lv2Plugins(Vec<Lv2PluginInfo>),
550 ListVst3Plugins,
551 Vst3Plugins(Vec<Vst3PluginInfo>),
552 ListClapPlugins,
553 ListClapPluginsWithCapabilities,
554 ClapPlugins(Vec<ClapPluginInfo>),
555 TrackLoadClapPlugin {
556 track_name: String,
557 plugin_path: String,
558 },
559 TrackUnloadClapPlugin {
560 track_name: String,
561 plugin_path: String,
562 },
563 TrackSetClapParameter {
564 track_name: String,
565 instance_id: usize,
566 param_id: u32,
567 value: f64,
568 },
569 TrackSetClapParameterAt {
570 track_name: String,
571 instance_id: usize,
572 param_id: u32,
573 value: f64,
574 frame: u32,
575 },
576 TrackBeginClapParameterEdit {
577 track_name: String,
578 instance_id: usize,
579 param_id: u32,
580 frame: u32,
581 },
582 TrackEndClapParameterEdit {
583 track_name: String,
584 instance_id: usize,
585 param_id: u32,
586 frame: u32,
587 },
588 TrackGetClapParameters {
589 track_name: String,
590 instance_id: usize,
591 },
592 TrackClapParameters {
593 track_name: String,
594 instance_id: usize,
595 parameters: Vec<ClapParameterInfo>,
596 },
597 TrackClapSnapshotState {
598 track_name: String,
599 instance_id: usize,
600 },
601 TrackClapStateSnapshot {
602 track_name: String,
603 instance_id: usize,
604 plugin_path: String,
605 state: crate::clap::ClapPluginState,
606 },
607 TrackClapRestoreState {
608 track_name: String,
609 instance_id: usize,
610 state: crate::clap::ClapPluginState,
611 },
612 TrackSnapshotAllClapStates {
613 track_name: String,
614 },
615 TrackLoadVst3Plugin {
616 track_name: String,
617 plugin_path: String,
618 },
619 TrackUnloadVst3PluginInstance {
620 track_name: String,
621 instance_id: usize,
622 },
623 TrackGetVst3Graph {
624 track_name: String,
625 },
626 TrackVst3Graph {
627 track_name: String,
628 plugins: Vec<Vst3GraphPlugin>,
629 connections: Vec<Vst3GraphConnection>,
630 },
631 TrackSetVst3Parameter {
632 track_name: String,
633 instance_id: usize,
634 param_id: u32,
635 value: f32,
636 },
637 TrackGetVst3Parameters {
638 track_name: String,
639 instance_id: usize,
640 },
641 TrackVst3Parameters {
642 track_name: String,
643 instance_id: usize,
644 parameters: Vec<crate::vst3::port::ParameterInfo>,
645 },
646 TrackVst3SnapshotState {
647 track_name: String,
648 instance_id: usize,
649 },
650 TrackVst3StateSnapshot {
651 track_name: String,
652 instance_id: usize,
653 state: crate::vst3::state::Vst3PluginState,
654 },
655 TrackVst3RestoreState {
656 track_name: String,
657 instance_id: usize,
658 state: crate::vst3::state::Vst3PluginState,
659 },
660 TrackConnectVst3Audio {
661 track_name: String,
662 from_node: Vst3GraphNode,
663 from_port: usize,
664 to_node: Vst3GraphNode,
665 to_port: usize,
666 },
667 TrackDisconnectVst3Audio {
668 track_name: String,
669 from_node: Vst3GraphNode,
670 from_port: usize,
671 to_node: Vst3GraphNode,
672 to_port: usize,
673 },
674 ClipMove {
675 kind: Kind,
676 from: ClipMoveFrom,
677 to: ClipMoveTo,
678 copy: bool,
679 },
680 Connect {
681 from_track: String,
682 from_port: usize,
683 to_track: String,
684 to_port: usize,
685 kind: Kind,
686 },
687 Disconnect {
688 from_track: String,
689 from_port: usize,
690 to_track: String,
691 to_port: usize,
692 kind: Kind,
693 },
694 OpenAudioDevice {
695 device: String,
696 input_device: Option<String>,
697 sample_rate_hz: i32,
698 bits: i32,
699 exclusive: bool,
700 period_frames: usize,
701 nperiods: usize,
702 sync_mode: bool,
703 },
704 OpenMidiInputDevice(String),
705 OpenMidiOutputDevice(String),
706 RequestSessionDiagnostics,
707 RequestMidiLearnMappingsReport,
708 ClearAllMidiLearnBindings,
709 SessionDiagnosticsReport {
710 track_count: usize,
711 frozen_track_count: usize,
712 audio_clip_count: usize,
713 midi_clip_count: usize,
714 #[cfg(all(unix, not(target_os = "macos")))]
715 lv2_instance_count: usize,
716 vst3_instance_count: usize,
717 clap_instance_count: usize,
718 pending_requests: usize,
719 workers_total: usize,
720 workers_ready: usize,
721 pending_hw_midi_events: usize,
722 playing: bool,
723 transport_sample: usize,
724 tempo_bpm: f64,
725 sample_rate_hz: usize,
726 cycle_samples: usize,
727 },
728 MidiLearnMappingsReport {
729 lines: Vec<String>,
730 },
731 HWInfo {
732 channels: usize,
733 rate: usize,
734 input: bool,
735 },
736 Undo,
737 Redo,
738 Panic,
739}
740
741#[derive(Clone, Debug)]
742pub enum Message {
743 Ready(usize),
744 Finished {
745 worker_id: usize,
746 track_name: String,
747 output_linear: Vec<f32>,
748 process_epoch: usize,
749 },
750 TracksFinished,
751
752 ProcessTrack(Arc<UnsafeMutex<Box<Track>>>),
753 ProcessOfflineBounce(OfflineBounceWork),
754 Channel(Sender<Self>),
755
756 Request(Action),
757 Response(Result<Action, String>),
758 HWMidiEvents(Vec<HwMidiEvent>),
759 HWMidiOutEvents(Vec<HwMidiEvent>),
760 ClearHWMidiOutEvents,
761 HWFinished,
762 OfflineBounceFinished {
763 result: Result<Action, String>,
764 },
765}