1use std::mem;
3use std::os::raw::{c_int, c_void};
4
5use crate::host::{GetName, Host};
6use crate::plugin;
7use crate::{
8 intptr_t, AsRawPtr, FlMessage, MessageBoxFlags, MessageBoxResult, NameColor, Note, Notes,
9 ParamMenuEntry, SongTime, TNameColor, TParamMenuEntry, Tag, Time, TimeFormat, ValuePtr,
10};
11
12pub trait Message {
15 type Return;
17
18 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return;
20}
21
22macro_rules! impl_message {
23 ($message: ident) => {
24 impl Message for $message {
25 type Return = ();
26
27 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return {
28 unsafe {
29 host_on_message(*host.host_ptr.get_mut(), tag.0, self.into());
30 }
31 }
32 }
33 };
34}
35
36macro_rules! impl_message_ty {
37 ($message: ident, $res: ty) => {
38 impl Message for $message {
39 type Return = $res;
40
41 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return {
42 ValuePtr(unsafe { host_on_message(*host.host_ptr.get_mut(), tag.0, self.into()) })
43 .get::<$res>()
44 }
45 }
46 };
47}
48
49extern "C" {
50 fn host_on_message(host: *mut c_void, plugin_tag: Tag, message: FlMessage) -> intptr_t;
51}
52
53#[derive(Debug)]
59pub struct ParamMenu(pub usize, pub usize);
60
61impl_message!(ParamMenu);
62
63impl From<ParamMenu> for FlMessage {
64 fn from(message: ParamMenu) -> Self {
65 FlMessage {
66 id: 0,
67 index: message.0.as_raw_ptr(),
68 value: message.1.as_raw_ptr(),
69 }
70 }
71}
72
73#[derive(Debug)]
75pub struct EditorResized;
76
77impl_message!(EditorResized);
78
79impl From<EditorResized> for FlMessage {
80 fn from(_message: EditorResized) -> Self {
81 FlMessage {
82 id: 2,
83 index: 0,
84 value: 0,
85 }
86 }
87}
88
89#[derive(Debug)]
92pub struct NamesChanged(pub GetName);
93
94impl_message!(NamesChanged);
95
96impl From<NamesChanged> for FlMessage {
97 fn from(message: NamesChanged) -> Self {
98 FlMessage {
99 id: 3,
100 index: 0,
101 value: Option::<FlMessage>::from(message.0)
102 .map(|msg| msg.id)
103 .unwrap_or_default(),
104 }
105 }
106}
107
108#[derive(Debug)]
111pub struct ActivateMidi;
112
113impl_message!(ActivateMidi);
114
115impl From<ActivateMidi> for FlMessage {
116 fn from(_: ActivateMidi) -> Self {
117 FlMessage {
118 id: 4,
119 index: 0,
120 value: 0,
121 }
122 }
123}
124
125#[derive(Debug)]
131pub struct WantMidiInput(pub bool);
132
133impl_message!(WantMidiInput);
134
135impl From<WantMidiInput> for FlMessage {
136 fn from(message: WantMidiInput) -> Self {
137 FlMessage {
138 id: 5,
139 index: 0,
140 value: message.0.as_raw_ptr(),
141 }
142 }
143}
144
145#[derive(Debug)]
154pub struct KillAutomation(pub usize, pub usize);
155
156impl_message!(KillAutomation);
157
158impl From<KillAutomation> for FlMessage {
159 fn from(message: KillAutomation) -> Self {
160 FlMessage {
161 id: 8,
162 index: message.0.as_raw_ptr(),
163 value: message.1.as_raw_ptr(),
164 }
165 }
166}
167
168#[derive(Debug)]
173pub struct SetNumPresets(pub usize);
174
175impl_message!(SetNumPresets);
176
177impl From<SetNumPresets> for FlMessage {
178 fn from(message: SetNumPresets) -> Self {
179 FlMessage {
180 id: 9,
181 index: 0,
182 value: message.0.as_raw_ptr(),
183 }
184 }
185}
186
187#[derive(Debug)]
191pub struct SetNewName(pub String);
192
193impl_message!(SetNewName);
194
195impl From<SetNewName> for FlMessage {
196 fn from(message: SetNewName) -> Self {
197 FlMessage {
198 id: 10,
199 index: 0,
200 value: message.0.as_raw_ptr(),
201 }
202 }
203}
204
205#[derive(Debug)]
207pub struct VstiIdle;
208
209impl_message!(VstiIdle);
210
211impl From<VstiIdle> for FlMessage {
212 fn from(_message: VstiIdle) -> Self {
213 FlMessage {
214 id: 11,
215 index: 0,
216 value: 0,
217 }
218 }
219}
220
221#[derive(Debug)]
229pub enum WantIdle {
230 Disabled,
232 EnabledVisible,
234 EnabledAlways,
236}
237
238impl_message!(WantIdle);
239
240impl From<WantIdle> for FlMessage {
241 fn from(message: WantIdle) -> Self {
242 FlMessage {
243 id: 13,
244 index: 0,
245 value: message.into(),
246 }
247 }
248}
249
250impl From<WantIdle> for intptr_t {
251 fn from(message: WantIdle) -> Self {
252 match message {
253 WantIdle::Disabled => 0,
254 WantIdle::EnabledVisible => 1,
255 WantIdle::EnabledAlways => 2,
256 }
257 }
258}
259
260#[derive(Debug)]
266pub struct LocateDataFile(pub String);
267
268impl_message_ty!(LocateDataFile, String);
269
270impl From<LocateDataFile> for FlMessage {
271 fn from(message: LocateDataFile) -> Self {
272 FlMessage {
273 id: 14,
274 index: 0,
275 value: message.0.as_raw_ptr(),
276 }
277 }
278}
279
280#[derive(Debug)]
286pub struct TicksToTime(pub u32);
287
288impl Message for TicksToTime {
289 type Return = SongTime;
290
291 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return {
292 let message = FlMessage::from(self);
293 let time_ptr = message.index;
294 unsafe { host_on_message(*host.host_ptr.get_mut(), tag.0, message) };
295 ValuePtr(time_ptr).get::<Self::Return>()
296 }
297}
298
299impl From<TicksToTime> for FlMessage {
300 fn from(message: TicksToTime) -> Self {
301 let time = SongTime::default();
302 FlMessage {
303 id: 16,
304 index: (Box::into_raw(Box::new(time)) as *mut c_void).as_raw_ptr(),
305 value: message.0.as_raw_ptr(),
306 }
307 }
308}
309
310#[derive(Debug)]
312pub struct AddToPianoRoll(pub Notes);
313
314impl_message!(AddToPianoRoll);
315
316impl From<AddToPianoRoll> for FlMessage {
317 fn from(mut message: AddToPianoRoll) -> Self {
318 message.0.notes.shrink_to_fit();
319 let notes_ptr = message.0.notes.as_mut_ptr();
320 let len = message.0.notes.len();
321
322 let p_notes_params = unsafe {
323 init_p_notes_params(
324 1,
325 message.0.flags.bits() as c_int,
326 message.0.channel.map(|v| v as c_int).unwrap_or(-1),
327 message.0.pattern.map(|v| v as c_int).unwrap_or(-1),
328 notes_ptr,
329 len as c_int,
330 )
331 };
332
333 FlMessage {
334 id: 17,
335 index: 0,
336 value: p_notes_params,
337 }
338 }
339}
340
341extern "C" {
342 fn init_p_notes_params(
347 target: c_int,
348 flags: c_int,
349 ch_num: c_int,
350 pat_num: c_int,
351 notes: *mut Note,
352 count: c_int,
353 ) -> intptr_t;
354}
355
356#[derive(Debug)]
365pub struct GetParamMenuEntry(pub usize, pub usize);
366
367impl Message for GetParamMenuEntry {
368 type Return = Option<ParamMenuEntry>;
369
370 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return {
371 let message = FlMessage::from(self);
372 let result = unsafe { host_on_message(*host.host_ptr.get_mut(), tag.0, message) };
373
374 if (result as *mut c_void).is_null() {
375 return None;
376 }
377
378 Some(ParamMenuEntry::from_ffi(
379 result as *mut c_void as *mut TParamMenuEntry,
380 ))
381 }
382}
383
384impl From<GetParamMenuEntry> for FlMessage {
385 fn from(message: GetParamMenuEntry) -> Self {
386 FlMessage {
387 id: 18,
388 index: message.0.as_raw_ptr(),
389 value: message.1.as_raw_ptr(),
390 }
391 }
392}
393
394#[derive(Debug)]
404pub struct MessageBox(pub String, pub String, pub MessageBoxFlags);
405
406impl_message_ty!(MessageBox, MessageBoxResult);
407
408impl From<MessageBox> for FlMessage {
409 fn from(message: MessageBox) -> Self {
410 FlMessage {
411 id: 19,
412 index: format!("{}|{}", message.0, message.1).as_raw_ptr(),
413 value: message.2.as_raw_ptr(),
414 }
415 }
416}
417
418#[derive(Debug)]
426pub struct NoteOn(pub u8, pub u8, pub u8);
427
428impl_message!(NoteOn);
429
430impl From<NoteOn> for FlMessage {
431 fn from(message: NoteOn) -> Self {
432 FlMessage {
433 id: 20,
434 index: dword_from_note_and_ch(message.0, message.1).as_raw_ptr(),
435 value: message.2.as_raw_ptr(),
436 }
437 }
438}
439
440#[derive(Debug)]
444pub struct NoteOff(pub u8);
445
446impl_message!(NoteOff);
447
448impl From<NoteOff> for FlMessage {
449 fn from(message: NoteOff) -> Self {
450 FlMessage {
451 id: 21,
452 index: message.0.as_raw_ptr(),
453 value: 0,
454 }
455 }
456}
457
458#[derive(Debug)]
463pub struct OnHintDirect(pub String);
464
465impl_message!(OnHintDirect);
466
467impl From<OnHintDirect> for FlMessage {
468 fn from(message: OnHintDirect) -> Self {
469 FlMessage {
470 id: 22,
471 index: 0,
472 value: message.0.as_raw_ptr(),
473 }
474 }
475}
476
477#[derive(Debug)]
483pub struct SetNewColor(pub u8);
484
485impl_message!(SetNewColor);
486
487impl From<SetNewColor> for FlMessage {
488 fn from(message: SetNewColor) -> Self {
489 FlMessage {
490 id: 23,
491 index: 0,
492 value: message.0.as_raw_ptr(),
493 }
494 }
495}
496
497#[derive(Debug)]
519pub struct KillIntCtrl(pub usize, pub usize);
520
521impl_message!(KillIntCtrl);
522
523impl From<KillIntCtrl> for FlMessage {
524 fn from(message: KillIntCtrl) -> Self {
525 FlMessage {
526 id: 25,
527 index: message.0.as_raw_ptr(),
528 value: message.1.as_raw_ptr(),
529 }
530 }
531}
532
533#[derive(Debug)]
538pub struct SetNumParams(pub usize);
539
540impl_message!(SetNumParams);
541
542impl From<SetNumParams> for FlMessage {
543 fn from(message: SetNumParams) -> Self {
544 FlMessage {
545 id: 27,
546 index: 0,
547 value: message.0.as_raw_ptr(),
548 }
549 }
550}
551
552#[derive(Debug)]
559pub struct PackDataFile(pub String);
560
561impl_message_ty!(PackDataFile, String);
562
563impl From<PackDataFile> for FlMessage {
564 fn from(message: PackDataFile) -> Self {
565 FlMessage {
566 id: 28,
567 index: 0,
568 value: message.0.as_raw_ptr(),
569 }
570 }
571}
572
573#[derive(Debug)]
578pub struct GetProgPath;
579
580impl_message_ty!(GetProgPath, String);
581
582impl From<GetProgPath> for FlMessage {
583 fn from(_: GetProgPath) -> Self {
584 FlMessage {
585 id: 29,
586 index: 0,
587 value: 0,
588 }
589 }
590}
591
592#[derive(Debug)]
596pub struct SetLatency(pub u32);
597
598impl_message!(SetLatency);
599
600impl From<SetLatency> for FlMessage {
601 fn from(message: SetLatency) -> Self {
602 FlMessage {
603 id: 30,
604 index: 0,
605 value: message.0.as_raw_ptr(),
606 }
607 }
608}
609
610#[derive(Debug)]
612pub struct CallDownloader;
613
614impl_message!(CallDownloader);
615
616impl From<CallDownloader> for FlMessage {
617 fn from(_: CallDownloader) -> Self {
618 FlMessage {
619 id: 31,
620 index: 0,
621 value: 0,
622 }
623 }
624}
625
626#[derive(Debug)]
633pub struct EditSample(pub String, pub bool);
634
635impl_message!(EditSample);
636
637impl From<EditSample> for FlMessage {
638 fn from(message: EditSample) -> Self {
639 FlMessage {
640 id: 32,
641 index: message.1.as_raw_ptr(),
642 value: message.0.as_raw_ptr(),
643 }
644 }
645}
646
647#[derive(Debug)]
655pub struct SetThreadSafe(pub bool);
656
657impl_message!(SetThreadSafe);
658
659impl From<SetThreadSafe> for FlMessage {
660 fn from(message: SetThreadSafe) -> Self {
661 FlMessage {
662 id: 33,
663 index: 0,
664 value: message.0.as_raw_ptr(),
665 }
666 }
667}
668
669#[derive(Debug)]
674pub struct SmartDisable(pub bool);
675
676impl_message!(SmartDisable);
677
678impl From<SmartDisable> for FlMessage {
679 fn from(message: SmartDisable) -> Self {
680 FlMessage {
681 id: 34,
682 index: 0,
683 value: message.0.as_raw_ptr(),
684 }
685 }
686}
687
688#[derive(Debug)]
693pub struct SetUid(pub String);
694
695impl_message!(SetUid);
696
697impl From<SetUid> for FlMessage {
698 fn from(message: SetUid) -> Self {
699 FlMessage {
700 id: 35,
701 index: 0,
702 value: message.0.as_raw_ptr(),
703 }
704 }
705}
706
707#[derive(Debug)]
715pub struct GetMixingTime(pub TimeFormat, pub u64);
716
717impl Message for GetMixingTime {
718 type Return = Time;
719
720 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return {
721 get_time_send(self, tag, host)
722 }
723}
724
725fn get_time_send<T: Into<FlMessage>>(msg: T, tag: plugin::Tag, host: &mut Host) -> Time {
726 let message: FlMessage = msg.into();
727 let time_ptr = message.value;
728 unsafe { host_on_message(*host.host_ptr.get_mut(), tag.0, message) };
729 ValuePtr(time_ptr).get::<Time>()
730}
731
732impl From<GetMixingTime> for FlMessage {
733 fn from(message: GetMixingTime) -> Self {
734 get_time_ffi(36, message.0, message.1)
735 }
736}
737
738fn get_time_ffi(id: intptr_t, format: TimeFormat, offset: u64) -> FlMessage {
739 let time = Time(offset as f64, offset as f64);
740 FlMessage {
741 id,
742 index: u8::from(format).as_raw_ptr(),
743 value: (Box::into_raw(Box::new(time)) as *mut c_void).as_raw_ptr(),
744 }
745}
746
747#[derive(Debug)]
749pub struct GetPlaybackTime(pub TimeFormat, pub u64);
750
751impl Message for GetPlaybackTime {
752 type Return = Time;
753
754 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return {
755 get_time_send(self, tag, host)
756 }
757}
758
759impl From<GetPlaybackTime> for FlMessage {
760 fn from(message: GetPlaybackTime) -> Self {
761 get_time_ffi(37, message.0, message.1)
762 }
763}
764
765#[derive(Debug)]
772pub struct GetSelTime(pub TimeFormat);
773
774impl Message for GetSelTime {
775 type Return = Time;
776
777 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return {
778 get_time_send(self, tag, host)
779 }
780}
781
782impl From<GetSelTime> for FlMessage {
783 fn from(message: GetSelTime) -> Self {
784 get_time_ffi(38, message.0, 0)
785 }
786}
787
788#[derive(Debug)]
793pub struct GetTimeMul;
794
795impl_message_ty!(GetTimeMul, f32);
796
797impl From<GetTimeMul> for FlMessage {
798 fn from(_: GetTimeMul) -> Self {
799 FlMessage {
800 id: 39,
801 index: 0,
802 value: 0,
803 }
804 }
805}
806
807#[derive(Debug)]
811pub struct Captionize(pub bool);
812
813impl_message!(Captionize);
814
815impl From<Captionize> for FlMessage {
816 fn from(message: Captionize) -> Self {
817 FlMessage {
818 id: 40,
819 index: 0,
820 value: message.0.as_raw_ptr(),
821 }
822 }
823}
824
825#[derive(Debug)]
831pub struct SendSysEx<'a>(pub usize, pub &'a [u8]);
832
833impl Message for SendSysEx<'_> {
834 type Return = ();
835
836 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return {
837 unsafe {
838 host_on_message(*host.host_ptr.get_mut(), tag.0, self.into());
839 }
840 }
841}
842
843impl From<SendSysEx<'_>> for FlMessage {
844 fn from(message: SendSysEx<'_>) -> Self {
845 let len = message.1.len() as i32;
846 let len_bytes: [u8; mem::size_of::<i32>()] = unsafe { mem::transmute(len) };
847 let mut final_data = [&len_bytes, message.1].concat();
848 let data_ptr = final_data.as_mut_ptr();
849 mem::forget(final_data);
850
851 FlMessage {
852 id: 41,
853 index: message.0.as_raw_ptr(),
854 value: (data_ptr as *mut c_void).as_raw_ptr(),
855 }
856 }
857}
858
859#[derive(Debug)]
864pub struct LoadAudioClip(pub String);
865
866impl_message!(LoadAudioClip);
867
868impl From<LoadAudioClip> for FlMessage {
869 fn from(message: LoadAudioClip) -> Self {
870 FlMessage {
871 id: 42,
872 index: 0,
873 value: message.0.as_raw_ptr(),
874 }
875 }
876}
877
878#[derive(Debug)]
882pub struct LoadInChannel(pub String);
883
884impl_message!(LoadInChannel);
885
886impl From<LoadInChannel> for FlMessage {
887 fn from(message: LoadInChannel) -> Self {
888 FlMessage {
889 id: 43,
890 index: 0,
891 value: message.0.as_raw_ptr(),
892 }
893 }
894}
895
896#[derive(Debug)]
901pub struct ShowInBrowser(pub String);
902
903impl_message!(ShowInBrowser);
904
905impl From<ShowInBrowser> for FlMessage {
906 fn from(message: ShowInBrowser) -> Self {
907 FlMessage {
908 id: 44,
909 index: 0,
910 value: message.0.as_raw_ptr(),
911 }
912 }
913}
914
915#[derive(Debug)]
919pub struct DebugLogMsg(pub String);
920
921impl_message!(DebugLogMsg);
922
923impl From<DebugLogMsg> for FlMessage {
924 fn from(message: DebugLogMsg) -> Self {
925 FlMessage {
926 id: 45,
927 index: 0,
928 value: message.0.as_raw_ptr(),
929 }
930 }
931}
932
933#[derive(Debug)]
937pub struct GetMainFormHandle;
938
939impl Message for GetMainFormHandle {
940 type Return = Option<*mut c_void>;
941
942 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return {
943 let message = FlMessage::from(self);
944 let result_ptr = message.value;
945 unsafe { host_on_message(*host.host_ptr.get_mut(), tag.0, message) };
946
947 if result_ptr == 0 {
948 None
949 } else {
950 Some(result_ptr as *mut c_void)
951 }
952 }
953}
954
955impl From<GetMainFormHandle> for FlMessage {
956 fn from(_: GetMainFormHandle) -> Self {
957 FlMessage {
958 id: 46,
959 index: 0,
960 value: 0,
961 }
962 }
963}
964
965#[derive(Debug)]
969pub struct GetProjDataPath;
970
971impl_message_ty!(GetProjDataPath, String);
972
973impl From<GetProjDataPath> for FlMessage {
974 fn from(_message: GetProjDataPath) -> Self {
975 FlMessage {
976 id: 47,
977 index: 0,
978 value: 0,
979 }
980 }
981}
982
983#[derive(Debug)]
986pub struct SetDirty;
987
988impl_message!(SetDirty);
989
990impl From<SetDirty> for FlMessage {
991 fn from(_message: SetDirty) -> Self {
992 FlMessage {
993 id: 48,
994 index: 0,
995 value: 0,
996 }
997 }
998}
999
1000#[derive(Debug)]
1004pub struct AddToRecent(pub String);
1005
1006impl_message!(AddToRecent);
1007
1008impl From<AddToRecent> for FlMessage {
1009 fn from(message: AddToRecent) -> Self {
1010 FlMessage {
1011 id: 49,
1012 index: 0,
1013 value: message.0.as_raw_ptr(),
1014 }
1015 }
1016}
1017
1018#[derive(Debug)]
1023pub enum GetNumInOut {
1024 Inputs,
1026 Outputs,
1028}
1029
1030impl_message_ty!(GetNumInOut, usize);
1031
1032impl From<GetNumInOut> for FlMessage {
1033 fn from(message: GetNumInOut) -> Self {
1034 FlMessage {
1035 id: 50,
1036 index: message.into(),
1037 value: 0,
1038 }
1039 }
1040}
1041
1042impl From<GetNumInOut> for intptr_t {
1043 fn from(message: GetNumInOut) -> Self {
1044 match message {
1045 GetNumInOut::Inputs => 0,
1046 GetNumInOut::Outputs => 1,
1047 }
1048 }
1049}
1050
1051#[derive(Debug)]
1059pub struct GetInName(pub usize);
1060
1061impl Message for GetInName {
1062 type Return = Option<NameColor>;
1063
1064 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return {
1065 get_name_dispatcher(self, tag, host)
1066 }
1067}
1068
1069fn get_name_dispatcher<T: Into<FlMessage>>(
1070 msg: T,
1071 tag: plugin::Tag,
1072 host: &mut Host,
1073) -> Option<NameColor> {
1074 let message: FlMessage = msg.into();
1075 let result_ptr = message.value;
1076 let result = unsafe { host_on_message(*host.host_ptr.get_mut(), tag.0, message) };
1077
1078 if result == 0 || (result_ptr as *mut c_void).is_null() {
1079 return None;
1080 }
1081
1082 Some(ValuePtr(result_ptr).get::<TNameColor>().into())
1083}
1084
1085impl From<GetInName> for FlMessage {
1086 fn from(message: GetInName) -> Self {
1087 get_name_ffi(51, message.0)
1088 }
1089}
1090
1091fn get_name_ffi(id: intptr_t, index: usize) -> FlMessage {
1092 let name_color = TNameColor {
1093 name: [0; 256],
1094 vis_name: [0; 256],
1095 color: 0,
1096 index: index as c_int,
1097 };
1098 FlMessage {
1099 id,
1100 index: index.as_raw_ptr(),
1101 value: (Box::into_raw(Box::new(name_color)) as *mut c_void).as_raw_ptr(),
1102 }
1103}
1104
1105#[derive(Debug)]
1113pub struct GetOutName(pub usize);
1114
1115impl Message for GetOutName {
1116 type Return = Option<NameColor>;
1117
1118 fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return {
1119 get_name_dispatcher(self, tag, host)
1120 }
1121}
1122
1123impl From<GetOutName> for FlMessage {
1124 fn from(message: GetOutName) -> Self {
1125 get_name_ffi(52, message.0)
1126 }
1127}
1128
1129#[derive(Debug)]
1131pub enum ShowEditor {
1132 Show,
1134 Hide,
1136 Toggle,
1138}
1139
1140impl_message!(ShowEditor);
1141
1142impl From<ShowEditor> for FlMessage {
1143 fn from(message: ShowEditor) -> Self {
1144 FlMessage {
1145 id: 53,
1146 index: 0,
1147 value: message.into(),
1148 }
1149 }
1150}
1151
1152impl From<ShowEditor> for intptr_t {
1153 fn from(message: ShowEditor) -> Self {
1154 match message {
1155 ShowEditor::Show => 1,
1156 ShowEditor::Hide => 0,
1157 ShowEditor::Toggle => -1,
1158 }
1159 }
1160}
1161
1162#[derive(Debug)]
1165pub struct FloatAutomation(pub usize, pub usize);
1166
1167impl_message!(FloatAutomation);
1168
1169impl From<FloatAutomation> for FlMessage {
1170 fn from(message: FloatAutomation) -> Self {
1171 FlMessage {
1172 id: 54,
1173 index: message.0.as_raw_ptr(),
1174 value: message.1.as_raw_ptr(),
1175 }
1176 }
1177}
1178
1179#[derive(Debug)]
1187pub struct ShowSettings(pub bool);
1188
1189impl_message!(ShowSettings);
1190
1191impl From<ShowSettings> for FlMessage {
1192 fn from(message: ShowSettings) -> Self {
1193 FlMessage {
1194 id: 55,
1195 index: 0,
1196 value: message.0.as_raw_ptr(),
1197 }
1198 }
1199}
1200
1201#[derive(Debug)]
1209pub struct NoteOnOff(pub u8, pub u8, pub u8);
1210
1211impl_message!(NoteOnOff);
1212
1213impl From<NoteOnOff> for FlMessage {
1214 fn from(message: NoteOnOff) -> Self {
1215 FlMessage {
1216 id: 56,
1217 index: dword_from_note_and_ch(message.0, message.1).as_raw_ptr(),
1218 value: message.2.as_raw_ptr(),
1219 }
1220 }
1221}
1222
1223#[derive(Debug)]
1225pub enum ShowPicker {
1226 Plugins(PickerFilter),
1228 Project(PickerFilter),
1230}
1231
1232impl_message!(ShowPicker);
1233
1234#[derive(Debug)]
1236pub enum PickerFilter {
1237 Generators,
1239 Effects,
1241 GeneratorsEffects,
1243 Patcher,
1245}
1246
1247impl From<ShowPicker> for FlMessage {
1248 fn from(message: ShowPicker) -> Self {
1249 let (index, value): (intptr_t, intptr_t) = message.into();
1250 FlMessage {
1251 id: 57,
1252 index,
1253 value,
1254 }
1255 }
1256}
1257
1258impl From<ShowPicker> for (intptr_t, intptr_t) {
1259 fn from(message: ShowPicker) -> Self {
1260 match message {
1261 ShowPicker::Plugins(filter) => (0, filter.into()),
1262 ShowPicker::Project(filter) => (1, filter.into()),
1263 }
1264 }
1265}
1266
1267impl From<PickerFilter> for intptr_t {
1268 fn from(filter: PickerFilter) -> Self {
1269 match filter {
1270 PickerFilter::Generators => 0,
1271 PickerFilter::Effects => 1,
1272 PickerFilter::GeneratorsEffects => -1,
1273 PickerFilter::Patcher => -2,
1274 }
1275 }
1276}
1277
1278#[derive(Debug)]
1281pub struct GetIdleOverflow;
1282
1283impl_message!(GetIdleOverflow);
1284
1285impl From<GetIdleOverflow> for FlMessage {
1286 fn from(_: GetIdleOverflow) -> Self {
1287 FlMessage {
1288 id: 58,
1289 index: 0,
1290 value: 0,
1291 }
1292 }
1293}
1294
1295#[derive(Debug)]
1297pub struct ModalIdle;
1298
1299impl_message!(ModalIdle);
1300
1301impl From<ModalIdle> for FlMessage {
1302 fn from(_: ModalIdle) -> Self {
1303 FlMessage {
1304 id: 59,
1305 index: 0,
1306 value: 0,
1307 }
1308 }
1309}
1310
1311#[derive(Debug)]
1313pub struct RenderProject;
1314
1315impl_message!(RenderProject);
1316
1317impl From<RenderProject> for FlMessage {
1318 fn from(_: RenderProject) -> Self {
1319 FlMessage {
1320 id: 60,
1321 index: 0,
1322 value: 0,
1323 }
1324 }
1325}
1326
1327#[derive(Debug)]
1331pub enum GetProjectInfo {
1332 Title,
1334 Author,
1336 Comments,
1338 Url,
1340}
1341
1342impl_message_ty!(GetProjectInfo, String);
1343
1344impl From<GetProjectInfo> for FlMessage {
1345 fn from(message: GetProjectInfo) -> Self {
1346 FlMessage {
1347 id: 61,
1348 index: message.into(),
1349 value: 0,
1350 }
1351 }
1352}
1353
1354impl From<GetProjectInfo> for intptr_t {
1355 fn from(value: GetProjectInfo) -> Self {
1356 match value {
1357 GetProjectInfo::Title => 0,
1358 GetProjectInfo::Author => 1,
1359 GetProjectInfo::Comments => 2,
1360 GetProjectInfo::Url => 3,
1361 }
1362 }
1363}
1364
1365fn dword_from_note_and_ch(note: u8, channel: u8) -> u32 {
1366 (note as u32) | ((channel as u32) << 16)
1367}
1368
1369#[cfg(test)]
1370mod tests {
1371 use super::*;
1372
1373 #[test]
1374 fn test_dword() {
1375 let value = dword_from_note_and_ch(60, 15);
1376 assert_eq!(60, value & 0xff);
1377 assert_eq!(15, (value >> 16) & 0xff);
1378 }
1379}