1use std::ffi::{c_char, c_void, CString};
26
27use mx_remote::{
28 ActionTransmitRequest, ArcStatus, AudioChangeSource, AudioClip, BayNameChange, BayUid,
29 DeviceUid, EdidProfileChange, EdidRecord, EdidRequest, EventHandler, FactoryResetRequest,
30 IrCapture, IrMeta, IrTransmitRequest, KeyTransmitRequest, LinkFeature, MultiviewerCommand,
31 PowerStatus, RcAction, RcKey, RebootRequest, SetRouteRequest, V2ipBlacklistChange,
32 V2ipPowerSaveRequest, VideoWallCommand, VolumeMuteStatus,
33};
34
35use crate::abi::{bay_or_zero, guard, mxr_bay_uid_t, mxr_tribool_t, mxr_uid_t};
36use crate::info::{mxr_arc_status_t, mxr_power_status_t};
37
38pub type mxr_device_cb = Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t)>;
42pub type mxr_device_bool_cb =
44 Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, value: bool)>;
45pub type mxr_device_uid_cb =
47 Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, other: mxr_uid_t)>;
48pub type mxr_device_u16_cb =
50 Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, value: u16)>;
51pub type mxr_endpoint_bool_cb =
53 Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, endpoint: u16, value: bool)>;
54pub type mxr_endpoint_u32_cb =
56 Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, endpoint: u16, value: u32)>;
57pub type mxr_system_status_cb = Option<
59 extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, status: u16, message: *const c_char),
60>;
61
62pub type mxr_bay_cb = Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t)>;
64pub type mxr_bay_bool_cb =
66 Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, value: bool)>;
67pub type mxr_bay_str_cb =
69 Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, value: *const c_char)>;
70pub type mxr_bay_bay_cb =
72 Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, other: mxr_bay_uid_t)>;
73pub type mxr_bay_u8_cb =
75 Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, value: u8)>;
76pub type mxr_bay_u16_cb =
78 Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, value: u16)>;
79pub type mxr_volume_cb = Option<
81 extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, volume: u8, muted: mxr_tribool_t),
82>;
83pub type mxr_power_cb =
85 Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, power: mxr_power_status_t)>;
86pub type mxr_arc_cb =
88 Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, arc: mxr_arc_status_t)>;
89pub type mxr_bay_linked_cb = Option<
91 extern "C" fn(
92 userdata: *mut c_void,
93 bay: mxr_bay_uid_t,
94 linked_serial: *const c_char,
95 bay_name: *const c_char,
96 features: u32,
97 ),
98>;
99pub type mxr_bay_unlinked_cb = Option<
101 extern "C" fn(
102 userdata: *mut c_void,
103 bay: mxr_bay_uid_t,
104 linked_serial: *const c_char,
105 bay_name: *const c_char,
106 ),
107>;
108
109#[repr(C)]
113#[derive(Clone, Copy)]
114pub struct mxr_set_route_request_t {
115 pub serial: *const c_char,
117 pub sink_bay: u16,
119 pub source_bay: u16,
121 pub no_power_on: bool,
123 pub audio_only: bool,
125}
126
127#[repr(C)]
129#[derive(Clone, Copy)]
130pub struct mxr_edid_request_t {
131 pub target: mxr_uid_t,
133 pub output: bool,
135}
136
137#[repr(C)]
139#[derive(Clone, Copy)]
140pub struct mxr_edid_record_t {
141 pub output: bool,
143 pub data: *const u8,
145 pub data_len: usize,
147}
148
149#[repr(C)]
151#[derive(Clone, Copy)]
152pub struct mxr_bay_name_change_t {
153 pub target: mxr_uid_t,
155 pub port: u16,
157 pub name: *const c_char,
159}
160
161#[repr(C)]
163#[derive(Clone, Copy)]
164pub struct mxr_edid_profile_change_t {
165 pub target: mxr_uid_t,
167 pub profile: u16,
169}
170
171#[repr(C)]
173#[derive(Clone, Copy)]
174pub struct mxr_factory_reset_request_t {
175 pub all: bool,
177 pub target: mxr_uid_t,
180}
181
182#[repr(C)]
184#[derive(Clone, Copy)]
185pub struct mxr_power_save_request_t {
186 pub target: mxr_uid_t,
188 pub enabled: bool,
190}
191
192#[repr(C)]
194#[derive(Clone, Copy)]
195pub struct mxr_key_transmit_request_t {
196 pub target: mxr_uid_t,
198 pub local_bay: u16,
200 pub key: u16,
202}
203
204#[repr(C)]
206#[derive(Clone, Copy)]
207pub struct mxr_action_transmit_request_t {
208 pub target: mxr_uid_t,
210 pub local_bay: u16,
212 pub action: u16,
214}
215
216#[repr(C)]
218#[derive(Clone, Copy)]
219pub struct mxr_ir_meta_t {
220 pub timer_resolution: u16,
222 pub frequency: u16,
224 pub nb_timings: u16,
226 pub repeat_offset: u16,
228 pub status: u8,
230}
231
232impl From<IrMeta> for mxr_ir_meta_t {
233 fn from(m: IrMeta) -> Self {
234 Self {
235 timer_resolution: m.timer_resolution,
236 frequency: m.frequency,
237 nb_timings: m.nb_timings,
238 repeat_offset: m.repeat_offset,
239 status: m.status,
240 }
241 }
242}
243
244#[repr(C)]
246#[derive(Clone, Copy)]
247pub struct mxr_ir_capture_t {
248 pub timestamp: u32,
250 pub last_change: u32,
252 pub meta: mxr_ir_meta_t,
254 pub timings: *const u8,
256 pub timings_len: usize,
258}
259
260#[repr(C)]
262#[derive(Clone, Copy)]
263pub struct mxr_ir_transmit_request_t {
264 pub target: mxr_uid_t,
266 pub local_mode: u8,
268 pub local_bay: u8,
270 pub timestamp: u32,
272 pub meta: mxr_ir_meta_t,
274 pub timings: *const u8,
276 pub timings_len: usize,
278}
279
280#[repr(C)]
282#[derive(Clone, Copy)]
283pub struct mxr_blacklist_change_t {
284 pub target: mxr_uid_t,
286 pub registered: bool,
288}
289
290#[repr(C)]
296#[derive(Clone, Copy)]
297pub struct mxr_video_wall_command_t {
298 pub target: mxr_uid_t,
300 pub pos_x: u16,
302 pub pos_y: u16,
304 pub width: u16,
306 pub height: u16,
308 pub raster_w: u16,
310 pub raster_h: u16,
312 pub op: u8,
314}
315
316#[repr(C)]
322#[derive(Clone, Copy)]
323pub struct mxr_multiviewer_command_t {
324 pub target: mxr_uid_t,
326 pub op: u8,
328 pub params: *const u8,
330 pub params_len: usize,
332}
333
334#[repr(C)]
336#[derive(Clone, Copy)]
337pub struct mxr_audio_change_source_t {
338 pub source_uid: mxr_uid_t,
340 pub source_id: u16,
342 pub target_uid: mxr_uid_t,
344 pub target_id: u16,
346}
347
348pub type mxr_set_route_cb = Option<
350 extern "C" fn(
351 userdata: *mut c_void,
352 device: mxr_uid_t,
353 request: *const mxr_set_route_request_t,
354 ),
355>;
356pub type mxr_edid_request_cb = Option<
358 extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, request: *const mxr_edid_request_t),
359>;
360pub type mxr_edid_record_cb = Option<
362 extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, record: *const mxr_edid_record_t),
363>;
364pub type mxr_bay_name_change_cb = Option<
366 extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, change: *const mxr_bay_name_change_t),
367>;
368pub type mxr_edid_profile_change_cb = Option<
370 extern "C" fn(
371 userdata: *mut c_void,
372 device: mxr_uid_t,
373 change: *const mxr_edid_profile_change_t,
374 ),
375>;
376pub type mxr_factory_reset_cb = Option<
378 extern "C" fn(
379 userdata: *mut c_void,
380 device: mxr_uid_t,
381 request: *const mxr_factory_reset_request_t,
382 ),
383>;
384pub type mxr_power_save_cb = Option<
386 extern "C" fn(
387 userdata: *mut c_void,
388 device: mxr_uid_t,
389 request: *const mxr_power_save_request_t,
390 ),
391>;
392pub type mxr_key_transmit_cb = Option<
394 extern "C" fn(
395 userdata: *mut c_void,
396 device: mxr_uid_t,
397 request: *const mxr_key_transmit_request_t,
398 ),
399>;
400pub type mxr_action_transmit_cb = Option<
402 extern "C" fn(
403 userdata: *mut c_void,
404 device: mxr_uid_t,
405 request: *const mxr_action_transmit_request_t,
406 ),
407>;
408pub type mxr_ir_transmit_cb = Option<
410 extern "C" fn(
411 userdata: *mut c_void,
412 device: mxr_uid_t,
413 request: *const mxr_ir_transmit_request_t,
414 ),
415>;
416pub type mxr_blacklist_cb = Option<
418 extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, change: *const mxr_blacklist_change_t),
419>;
420pub type mxr_video_wall_cb = Option<
422 extern "C" fn(
423 userdata: *mut c_void,
424 device: mxr_uid_t,
425 command: *const mxr_video_wall_command_t,
426 ),
427>;
428pub type mxr_multiviewer_command_cb = Option<
430 extern "C" fn(
431 userdata: *mut c_void,
432 device: mxr_uid_t,
433 command: *const mxr_multiviewer_command_t,
434 ),
435>;
436pub type mxr_audio_select_cb = Option<
438 extern "C" fn(
439 userdata: *mut c_void,
440 device: mxr_uid_t,
441 change: *const mxr_audio_change_source_t,
442 ),
443>;
444pub type mxr_ir_capture_cb = Option<
446 extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, capture: *const mxr_ir_capture_t),
447>;
448
449#[repr(C)]
455#[derive(Clone, Copy)]
456pub struct mxr_callbacks_t {
457 pub on_device_update: mxr_device_cb,
459 pub on_bay_update: mxr_bay_cb,
461
462 pub on_device_config_changed: mxr_device_cb,
464 pub on_device_config_complete: mxr_device_cb,
466 pub on_device_online_changed: mxr_device_bool_cb,
468 pub on_device_temperature_changed: mxr_device_cb,
471 pub on_firmware_version_changed: mxr_device_cb,
474 pub on_system_status_changed: mxr_system_status_cb,
476 pub on_network_status_changed: mxr_device_cb,
479 pub on_v2ip_stats_changed: mxr_device_cb,
482 pub on_v2ip_sources_changed: mxr_device_cb,
485 pub on_v2ip_details_changed: mxr_device_cb,
488 pub on_v2ip_sink_changed: mxr_device_cb,
491 pub on_multiviewer_status_changed: mxr_device_cb,
494 pub on_audio_endpoints_changed: mxr_device_cb,
497 pub on_mesh_master_changed: mxr_device_uid_cb,
499 pub on_topology_changed: mxr_device_cb,
502 pub on_amp_dolby_settings_changed: mxr_device_cb,
505 pub on_pdu_state_changed: mxr_device_cb,
508 pub on_setup_status_changed: mxr_device_bool_cb,
510 pub on_installer_id_changed: mxr_device_u16_cb,
512 pub on_tiling_changed: mxr_device_cb,
515 pub on_rc_settings_changed: mxr_device_cb,
518 pub on_v2ip_link_changed: mxr_device_uid_cb,
520 pub on_multiviewer_command: mxr_multiviewer_command_cb,
522 pub on_audio_select_input: mxr_audio_select_cb,
524 pub on_audio_endpoint_mute: mxr_endpoint_bool_cb,
526 pub on_audio_endpoint_trigger: mxr_endpoint_bool_cb,
528 pub on_audio_endpoint_volume: mxr_endpoint_u32_cb,
530 pub on_discover_request: mxr_device_cb,
532 pub on_set_route_requested: mxr_set_route_cb,
534 pub on_edid_requested: mxr_edid_request_cb,
536 pub on_edid_received: mxr_edid_record_cb,
538 pub on_bay_name_change_requested: mxr_bay_name_change_cb,
540 pub on_edid_profile_change_requested: mxr_edid_profile_change_cb,
542 pub on_reboot_requested: mxr_device_uid_cb,
545 pub on_factory_reset_requested: mxr_factory_reset_cb,
547 pub on_monitoring_pulse: mxr_device_cb,
549 pub on_upgrade_fpga_requested: mxr_device_cb,
551 pub on_detect_bays_requested: mxr_device_cb,
553 pub on_power_save_requested: mxr_power_save_cb,
555 pub on_key_transmit_requested: mxr_key_transmit_cb,
557 pub on_action_transmit_requested: mxr_action_transmit_cb,
559 pub on_ir_transmit_requested: mxr_ir_transmit_cb,
561 pub on_blacklist_changed: mxr_blacklist_cb,
563 pub on_video_wall_command: mxr_video_wall_cb,
565
566 pub on_bay_registered: mxr_bay_cb,
568 pub on_video_source_changed: mxr_bay_bay_cb,
570 pub on_audio_source_changed: mxr_bay_bay_cb,
572 pub on_volume_changed: mxr_volume_cb,
574 pub on_power_changed: mxr_power_cb,
576 pub on_name_changed: mxr_bay_str_cb,
578 pub on_signal_detected_changed: mxr_bay_bool_cb,
580 pub on_faulty_changed: mxr_bay_bool_cb,
582 pub on_hidden_changed: mxr_bay_bool_cb,
584 pub on_poe_powered_changed: mxr_bay_bool_cb,
586 pub on_hdbt_connected_changed: mxr_bay_bool_cb,
588 pub on_signal_type_changed: mxr_bay_str_cb,
590 pub on_hpd_detected_changed: mxr_bay_bool_cb,
592 pub on_cec_detected_changed: mxr_bay_bool_cb,
594 pub on_arc_changed: mxr_arc_cb,
596 pub on_edid_profile_changed: mxr_bay_u16_cb,
598 pub on_rc_type_changed: mxr_bay_u8_cb,
600 pub on_key_pressed: mxr_bay_u16_cb,
602 pub on_action_received: mxr_bay_u16_cb,
604 pub on_mirror_status_changed: mxr_bay_bay_cb,
607 pub on_amp_zone_settings_changed: mxr_bay_cb,
610 pub on_volume_step: mxr_bay_bool_cb,
612 pub on_audio_clip: mxr_bay_u8_cb,
614 pub on_ir_captured: mxr_ir_capture_cb,
616 pub on_filtered_devices_changed: mxr_bay_cb,
619 pub on_audio_endpoint_changed: mxr_bay_u8_cb,
621 pub on_encoder_disabled_changed: mxr_bay_bool_cb,
623 pub on_decoder_disabled_changed: mxr_bay_bool_cb,
625
626 pub on_bay_linked: mxr_bay_linked_cb,
631 pub on_bay_unlinked: mxr_bay_unlinked_cb,
634}
635
636struct UserData(*mut c_void);
645
646unsafe impl Send for UserData {}
649unsafe impl Sync for UserData {}
651
652pub(crate) struct Bridge {
654 cb: mxr_callbacks_t,
655 userdata: UserData,
656}
657
658impl Bridge {
659 pub(crate) fn new(table: &mxr_callbacks_t, userdata: *mut c_void) -> Self {
661 Self {
662 cb: *table,
663 userdata: UserData(userdata),
664 }
665 }
666
667 fn ud(&self) -> *mut c_void {
668 self.userdata.0
669 }
670}
671
672macro_rules! forward {
678 ($self:ident.$field:ident( $($arg:expr),* $(,)? )) => {
679 if let Some(f) = $self.cb.$field {
680 guard((), || f($self.ud() $(, $arg)*));
681 }
682 };
683}
684
685fn with_cstr<R>(text: &str, body: impl FnOnce(*const c_char) -> R) -> R {
687 let owned = CString::new(text).unwrap_or_else(|_| c"".to_owned());
690 body(owned.as_ptr())
691}
692
693fn uid_or_zero(uid: Option<DeviceUid>) -> mxr_uid_t {
696 uid.unwrap_or(DeviceUid::ZERO).into()
697}
698
699impl EventHandler for Bridge {
700 fn on_device_update(&self, device: DeviceUid) {
701 forward!(self.on_device_update(device.into()));
702 }
703
704 fn on_bay_update(&self, bay: BayUid) {
705 forward!(self.on_bay_update(bay.into()));
706 }
707
708 fn on_device_config_changed(&self, device: DeviceUid) {
711 forward!(self.on_device_config_changed(device.into()));
712 }
713
714 fn on_device_config_complete(&self, device: DeviceUid) {
715 forward!(self.on_device_config_complete(device.into()));
716 }
717
718 fn on_device_online_changed(&self, device: DeviceUid, online: bool) {
719 forward!(self.on_device_online_changed(device.into(), online));
720 }
721
722 fn on_device_temperature_changed(&self, device: DeviceUid, _temperatures: Vec<u8>) {
723 forward!(self.on_device_temperature_changed(device.into()));
724 }
725
726 fn on_firmware_version_changed(&self, device: DeviceUid, _version: mx_remote::FirmwareVersion) {
727 forward!(self.on_firmware_version_changed(device.into()));
728 }
729
730 fn on_system_status_changed(&self, device: DeviceUid, status: u16, message: String) {
731 with_cstr(&message, |m| {
732 forward!(self.on_system_status_changed(device.into(), status, m));
733 });
734 }
735
736 fn on_network_status_changed(&self, device: DeviceUid, _status: mx_remote::NetworkPortStatus) {
737 forward!(self.on_network_status_changed(device.into()));
738 }
739
740 fn on_v2ip_stats_changed(&self, device: DeviceUid, _stats: mx_remote::V2ipDeviceStats) {
741 forward!(self.on_v2ip_stats_changed(device.into()));
742 }
743
744 fn on_v2ip_sources_changed(
745 &self,
746 device: DeviceUid,
747 _sources: Vec<mx_remote::V2ipStreamSources>,
748 ) {
749 forward!(self.on_v2ip_sources_changed(device.into()));
750 }
751
752 fn on_v2ip_details_changed(&self, device: DeviceUid, _details: mx_remote::DeviceV2ipDetails) {
753 forward!(self.on_v2ip_details_changed(device.into()));
754 }
755
756 fn on_v2ip_sink_changed(&self, device: DeviceUid, _sink: mx_remote::DeviceV2ipSink) {
757 forward!(self.on_v2ip_sink_changed(device.into()));
758 }
759
760 fn on_multiviewer_status_changed(
761 &self,
762 device: DeviceUid,
763 _status: mx_remote::MultiviewerStatus,
764 ) {
765 forward!(self.on_multiviewer_status_changed(device.into()));
766 }
767
768 fn on_audio_endpoints_changed(&self, device: DeviceUid, _endpoints: mx_remote::AudioEndpoints) {
769 forward!(self.on_audio_endpoints_changed(device.into()));
770 }
771
772 fn on_mesh_master_changed(&self, device: DeviceUid, master: DeviceUid) {
773 forward!(self.on_mesh_master_changed(device.into(), master.into()));
774 }
775
776 fn on_topology_changed(&self, device: DeviceUid, _topology: Vec<mx_remote::TopologyEntry>) {
777 forward!(self.on_topology_changed(device.into()));
778 }
779
780 fn on_amp_dolby_settings_changed(
781 &self,
782 device: DeviceUid,
783 _settings: mx_remote::AmpDolbySettings,
784 ) {
785 forward!(self.on_amp_dolby_settings_changed(device.into()));
786 }
787
788 fn on_pdu_state_changed(&self, device: DeviceUid, _state: mx_remote::PduState) {
789 forward!(self.on_pdu_state_changed(device.into()));
790 }
791
792 fn on_setup_status_changed(&self, device: DeviceUid, completed: bool) {
793 forward!(self.on_setup_status_changed(device.into(), completed));
794 }
795
796 fn on_installer_id_changed(&self, device: DeviceUid, installer_id: u16) {
797 forward!(self.on_installer_id_changed(device.into(), installer_id));
798 }
799
800 fn on_tiling_changed(&self, device: DeviceUid, _tiling: mx_remote::V2ipTilingConfig) {
801 forward!(self.on_tiling_changed(device.into()));
802 }
803
804 fn on_rc_settings_changed(&self, device: DeviceUid, _settings: mx_remote::RcSettings) {
805 forward!(self.on_rc_settings_changed(device.into()));
806 }
807
808 fn on_v2ip_link_changed(&self, device: DeviceUid, target: DeviceUid) {
809 forward!(self.on_v2ip_link_changed(device.into(), target.into()));
810 }
811
812 fn on_multiviewer_command(&self, device: DeviceUid, command: MultiviewerCommand) {
813 let payload = mxr_multiviewer_command_t {
814 target: command.target.into(),
815 op: command.op,
816 params: command.params.as_ptr(),
817 params_len: command.params.len(),
818 };
819 forward!(self.on_multiviewer_command(device.into(), &payload));
820 }
821
822 fn on_audio_select_input(&self, device: DeviceUid, change: AudioChangeSource) {
823 let payload = mxr_audio_change_source_t {
824 source_uid: change.source_uid.into(),
825 source_id: change.source_id,
826 target_uid: change.target_uid.into(),
827 target_id: change.target_id,
828 };
829 forward!(self.on_audio_select_input(device.into(), &payload));
830 }
831
832 fn on_audio_endpoint_mute(&self, device: DeviceUid, endpoint: u16, muted: bool) {
833 forward!(self.on_audio_endpoint_mute(device.into(), endpoint, muted));
834 }
835
836 fn on_audio_endpoint_trigger(&self, device: DeviceUid, endpoint: u16, active: bool) {
837 forward!(self.on_audio_endpoint_trigger(device.into(), endpoint, active));
838 }
839
840 fn on_audio_endpoint_volume(&self, device: DeviceUid, endpoint: u16, volume: u32) {
841 forward!(self.on_audio_endpoint_volume(device.into(), endpoint, volume));
842 }
843
844 fn on_discover_request(&self, device: DeviceUid) {
845 forward!(self.on_discover_request(device.into()));
846 }
847
848 fn on_set_route_requested(&self, device: DeviceUid, request: SetRouteRequest) {
849 with_cstr(&request.serial, |serial| {
850 let payload = mxr_set_route_request_t {
851 serial,
852 sink_bay: request.sink_bay,
853 source_bay: request.source_bay,
854 no_power_on: request.no_power_on,
855 audio_only: request.audio_only,
856 };
857 forward!(self.on_set_route_requested(device.into(), &payload));
858 });
859 }
860
861 fn on_edid_requested(&self, device: DeviceUid, request: EdidRequest) {
862 let payload = mxr_edid_request_t {
863 target: request.target.into(),
864 output: request.output,
865 };
866 forward!(self.on_edid_requested(device.into(), &payload));
867 }
868
869 fn on_edid_received(&self, device: DeviceUid, edid: EdidRecord) {
870 let payload = mxr_edid_record_t {
871 output: edid.output,
872 data: edid.data.as_ptr(),
873 data_len: edid.data.len(),
874 };
875 forward!(self.on_edid_received(device.into(), &payload));
876 }
877
878 fn on_bay_name_change_requested(&self, device: DeviceUid, change: BayNameChange) {
879 with_cstr(&change.name, |name| {
880 let payload = mxr_bay_name_change_t {
881 target: change.target.into(),
882 port: change.port,
883 name,
884 };
885 forward!(self.on_bay_name_change_requested(device.into(), &payload));
886 });
887 }
888
889 fn on_edid_profile_change_requested(&self, device: DeviceUid, change: EdidProfileChange) {
890 let payload = mxr_edid_profile_change_t {
891 target: change.target.into(),
892 profile: change.profile.to_wire(),
893 };
894 forward!(self.on_edid_profile_change_requested(device.into(), &payload));
895 }
896
897 fn on_reboot_requested(&self, device: DeviceUid, request: RebootRequest) {
898 forward!(self.on_reboot_requested(device.into(), request.target.into()));
899 }
900
901 fn on_factory_reset_requested(&self, device: DeviceUid, request: FactoryResetRequest) {
902 let payload = mxr_factory_reset_request_t {
903 all: request.all,
904 target: uid_or_zero(request.target),
905 };
906 forward!(self.on_factory_reset_requested(device.into(), &payload));
907 }
908
909 fn on_monitoring_pulse(&self, device: DeviceUid) {
910 forward!(self.on_monitoring_pulse(device.into()));
911 }
912
913 fn on_upgrade_fpga_requested(&self, device: DeviceUid) {
914 forward!(self.on_upgrade_fpga_requested(device.into()));
915 }
916
917 fn on_detect_bays_requested(&self, device: DeviceUid) {
918 forward!(self.on_detect_bays_requested(device.into()));
919 }
920
921 fn on_power_save_requested(&self, device: DeviceUid, request: V2ipPowerSaveRequest) {
922 let payload = mxr_power_save_request_t {
923 target: uid_or_zero(request.target),
924 enabled: request.enabled,
925 };
926 forward!(self.on_power_save_requested(device.into(), &payload));
927 }
928
929 fn on_key_transmit_requested(&self, device: DeviceUid, request: KeyTransmitRequest) {
930 let payload = mxr_key_transmit_request_t {
931 target: request.target.into(),
932 local_bay: request.local_bay,
933 key: request.key.to_wire(),
934 };
935 forward!(self.on_key_transmit_requested(device.into(), &payload));
936 }
937
938 fn on_action_transmit_requested(&self, device: DeviceUid, request: ActionTransmitRequest) {
939 let payload = mxr_action_transmit_request_t {
940 target: request.target.into(),
941 local_bay: request.local_bay,
942 action: request.action.to_wire(),
943 };
944 forward!(self.on_action_transmit_requested(device.into(), &payload));
945 }
946
947 fn on_ir_transmit_requested(&self, device: DeviceUid, request: IrTransmitRequest) {
948 let payload = mxr_ir_transmit_request_t {
949 target: request.target.into(),
950 local_mode: request.local_mode,
951 local_bay: request.local_bay,
952 timestamp: request.timestamp,
953 meta: request.meta.into(),
954 timings: request.timings.as_ptr(),
955 timings_len: request.timings.len(),
956 };
957 forward!(self.on_ir_transmit_requested(device.into(), &payload));
958 }
959
960 fn on_blacklist_changed(&self, device: DeviceUid, change: V2ipBlacklistChange) {
961 let payload = mxr_blacklist_change_t {
962 target: change.target.into(),
963 registered: change.registered,
964 };
965 forward!(self.on_blacklist_changed(device.into(), &payload));
966 }
967
968 fn on_video_wall_command(&self, device: DeviceUid, command: VideoWallCommand) {
969 let payload = mxr_video_wall_command_t {
970 target: command.target.into(),
971 pos_x: command.pos_x,
972 pos_y: command.pos_y,
973 width: command.width,
974 height: command.height,
975 raster_w: command.raster_w,
976 raster_h: command.raster_h,
977 op: command.op.to_wire(),
978 };
979 forward!(self.on_video_wall_command(device.into(), &payload));
980 }
981
982 fn on_bay_registered(&self, bay: BayUid) {
985 forward!(self.on_bay_registered(bay.into()));
986 }
987
988 fn on_video_source_changed(&self, bay: BayUid, source: Option<BayUid>) {
989 forward!(self.on_video_source_changed(bay.into(), bay_or_zero(source)));
990 }
991
992 fn on_audio_source_changed(&self, bay: BayUid, source: Option<BayUid>) {
993 forward!(self.on_audio_source_changed(bay.into(), bay_or_zero(source)));
994 }
995
996 fn on_volume_changed(&self, bay: BayUid, volume: VolumeMuteStatus) {
997 forward!(self.on_volume_changed(bay.into(), volume.volume(), volume.muted().into()));
998 }
999
1000 fn on_power_changed(&self, bay: BayUid, power: PowerStatus) {
1001 forward!(self.on_power_changed(bay.into(), Some(power).into()));
1002 }
1003
1004 fn on_name_changed(&self, bay: BayUid, name: String) {
1005 with_cstr(&name, |n| forward!(self.on_name_changed(bay.into(), n)));
1006 }
1007
1008 fn on_signal_detected_changed(&self, bay: BayUid, detected: bool) {
1009 forward!(self.on_signal_detected_changed(bay.into(), detected));
1010 }
1011
1012 fn on_faulty_changed(&self, bay: BayUid, faulty: bool) {
1013 forward!(self.on_faulty_changed(bay.into(), faulty));
1014 }
1015
1016 fn on_hidden_changed(&self, bay: BayUid, hidden: bool) {
1017 forward!(self.on_hidden_changed(bay.into(), hidden));
1018 }
1019
1020 fn on_poe_powered_changed(&self, bay: BayUid, powered: bool) {
1021 forward!(self.on_poe_powered_changed(bay.into(), powered));
1022 }
1023
1024 fn on_hdbt_connected_changed(&self, bay: BayUid, connected: bool) {
1025 forward!(self.on_hdbt_connected_changed(bay.into(), connected));
1026 }
1027
1028 fn on_signal_type_changed(&self, bay: BayUid, signal_type: String) {
1029 with_cstr(&signal_type, |s| {
1030 forward!(self.on_signal_type_changed(bay.into(), s))
1031 });
1032 }
1033
1034 fn on_hpd_detected_changed(&self, bay: BayUid, detected: bool) {
1035 forward!(self.on_hpd_detected_changed(bay.into(), detected));
1036 }
1037
1038 fn on_cec_detected_changed(&self, bay: BayUid, detected: bool) {
1039 forward!(self.on_cec_detected_changed(bay.into(), detected));
1040 }
1041
1042 fn on_arc_changed(&self, bay: BayUid, arc: ArcStatus) {
1043 forward!(self.on_arc_changed(bay.into(), arc.into()));
1044 }
1045
1046 fn on_edid_profile_changed(&self, bay: BayUid, profile: mx_remote::EdidProfile) {
1047 forward!(self.on_edid_profile_changed(bay.into(), profile.to_wire()));
1048 }
1049
1050 fn on_rc_type_changed(&self, bay: BayUid, rc_type: mx_remote::RcType) {
1051 forward!(self.on_rc_type_changed(bay.into(), rc_type.to_wire()));
1052 }
1053
1054 fn on_key_pressed(&self, bay: BayUid, key: RcKey) {
1055 forward!(self.on_key_pressed(bay.into(), key.to_wire()));
1056 }
1057
1058 fn on_action_received(&self, bay: BayUid, action: RcAction) {
1059 forward!(self.on_action_received(bay.into(), action.to_wire()));
1060 }
1061
1062 fn on_mirror_status_changed(&self, bay: BayUid, mirror: mx_remote::BayMirrorStatus) {
1063 forward!(self.on_mirror_status_changed(bay.into(), bay_or_zero(mirror.target)));
1064 }
1065
1066 fn on_amp_zone_settings_changed(&self, bay: BayUid, _settings: mx_remote::AmpZoneSettings) {
1067 forward!(self.on_amp_zone_settings_changed(bay.into()));
1068 }
1069
1070 fn on_volume_step(&self, bay: BayUid, up: bool) {
1071 forward!(self.on_volume_step(bay.into(), up));
1072 }
1073
1074 fn on_audio_clip(&self, bay: BayUid, clip: AudioClip) {
1075 forward!(self.on_audio_clip(bay.into(), clip.clip));
1076 }
1077
1078 fn on_ir_captured(&self, bay: BayUid, capture: IrCapture) {
1079 let payload = mxr_ir_capture_t {
1080 timestamp: capture.timestamp,
1081 last_change: capture.last_change,
1082 meta: capture.meta.into(),
1083 timings: capture.timings.as_ptr(),
1084 timings_len: capture.timings.len(),
1085 };
1086 forward!(self.on_ir_captured(bay.into(), &payload));
1087 }
1088
1089 fn on_filtered_devices_changed(&self, bay: BayUid, _filtered: Vec<DeviceUid>) {
1090 forward!(self.on_filtered_devices_changed(bay.into()));
1091 }
1092
1093 fn on_audio_endpoint_changed(&self, bay: BayUid, endpoint: u8) {
1094 forward!(self.on_audio_endpoint_changed(bay.into(), endpoint));
1095 }
1096
1097 fn on_encoder_disabled_changed(&self, bay: BayUid, disabled: bool) {
1098 forward!(self.on_encoder_disabled_changed(bay.into(), disabled));
1099 }
1100
1101 fn on_decoder_disabled_changed(&self, bay: BayUid, disabled: bool) {
1102 forward!(self.on_decoder_disabled_changed(bay.into(), disabled));
1103 }
1104
1105 fn on_bay_linked(
1108 &self,
1109 bay: BayUid,
1110 linked_serial: String,
1111 bay_name: String,
1112 features: LinkFeature,
1113 ) {
1114 with_cstr(&linked_serial, |serial| {
1115 with_cstr(&bay_name, |name| {
1116 forward!(self.on_bay_linked(bay.into(), serial, name, features.bits()));
1117 });
1118 });
1119 }
1120
1121 fn on_bay_unlinked(&self, bay: BayUid, linked_serial: String, bay_name: String) {
1122 with_cstr(&linked_serial, |serial| {
1123 with_cstr(&bay_name, |name| {
1124 forward!(self.on_bay_unlinked(bay.into(), serial, name));
1125 });
1126 });
1127 }
1128}