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,
179}
180
181#[repr(C)]
183#[derive(Clone, Copy)]
184pub struct mxr_power_save_request_t {
185 pub target: mxr_uid_t,
187 pub enabled: bool,
189}
190
191#[repr(C)]
193#[derive(Clone, Copy)]
194pub struct mxr_key_transmit_request_t {
195 pub target: mxr_uid_t,
197 pub local_bay: u16,
199 pub key: u16,
201}
202
203#[repr(C)]
205#[derive(Clone, Copy)]
206pub struct mxr_action_transmit_request_t {
207 pub target: mxr_uid_t,
209 pub local_bay: u16,
211 pub action: u16,
213}
214
215#[repr(C)]
217#[derive(Clone, Copy)]
218pub struct mxr_ir_meta_t {
219 pub timer_resolution: u16,
221 pub frequency: u16,
223 pub nb_timings: u16,
225 pub repeat_offset: u16,
227 pub status: u8,
229}
230
231impl From<IrMeta> for mxr_ir_meta_t {
232 fn from(m: IrMeta) -> Self {
233 Self {
234 timer_resolution: m.timer_resolution,
235 frequency: m.frequency,
236 nb_timings: m.nb_timings,
237 repeat_offset: m.repeat_offset,
238 status: m.status,
239 }
240 }
241}
242
243#[repr(C)]
245#[derive(Clone, Copy)]
246pub struct mxr_ir_capture_t {
247 pub timestamp: u32,
249 pub last_change: u32,
251 pub meta: mxr_ir_meta_t,
253 pub timings: *const u8,
255 pub timings_len: usize,
257}
258
259#[repr(C)]
261#[derive(Clone, Copy)]
262pub struct mxr_ir_transmit_request_t {
263 pub target: mxr_uid_t,
265 pub local_mode: u8,
267 pub local_bay: u8,
269 pub timestamp: u32,
271 pub meta: mxr_ir_meta_t,
273 pub timings: *const u8,
275 pub timings_len: usize,
277}
278
279#[repr(C)]
282#[derive(Clone, Copy)]
283pub struct mxr_blacklist_change_t {
284 pub groups: *const u8,
286 pub groups_len: usize,
288 pub registered: bool,
290}
291
292#[repr(C)]
298#[derive(Clone, Copy)]
299pub struct mxr_video_wall_command_t {
300 pub target: mxr_uid_t,
302 pub pos_x: u16,
304 pub pos_y: u16,
306 pub width: u16,
308 pub height: u16,
310 pub raster_w: u16,
312 pub raster_h: u16,
314 pub op: u8,
316}
317
318#[repr(C)]
324#[derive(Clone, Copy)]
325pub struct mxr_multiviewer_command_t {
326 pub target: mxr_uid_t,
328 pub op: u8,
330 pub params: *const u8,
332 pub params_len: usize,
334}
335
336#[repr(C)]
338#[derive(Clone, Copy)]
339pub struct mxr_audio_change_source_t {
340 pub source_uid: mxr_uid_t,
342 pub source_id: u16,
344 pub target_uid: mxr_uid_t,
346 pub target_id: u16,
348}
349
350pub type mxr_set_route_cb = Option<
352 extern "C" fn(
353 userdata: *mut c_void,
354 device: mxr_uid_t,
355 request: *const mxr_set_route_request_t,
356 ),
357>;
358pub type mxr_edid_request_cb = Option<
360 extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, request: *const mxr_edid_request_t),
361>;
362pub type mxr_edid_record_cb = Option<
364 extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, record: *const mxr_edid_record_t),
365>;
366pub type mxr_bay_name_change_cb = Option<
368 extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, change: *const mxr_bay_name_change_t),
369>;
370pub type mxr_edid_profile_change_cb = Option<
372 extern "C" fn(
373 userdata: *mut c_void,
374 device: mxr_uid_t,
375 change: *const mxr_edid_profile_change_t,
376 ),
377>;
378pub type mxr_factory_reset_cb = Option<
380 extern "C" fn(
381 userdata: *mut c_void,
382 device: mxr_uid_t,
383 request: *const mxr_factory_reset_request_t,
384 ),
385>;
386pub type mxr_power_save_cb = Option<
388 extern "C" fn(
389 userdata: *mut c_void,
390 device: mxr_uid_t,
391 request: *const mxr_power_save_request_t,
392 ),
393>;
394pub type mxr_key_transmit_cb = Option<
396 extern "C" fn(
397 userdata: *mut c_void,
398 device: mxr_uid_t,
399 request: *const mxr_key_transmit_request_t,
400 ),
401>;
402pub type mxr_action_transmit_cb = Option<
404 extern "C" fn(
405 userdata: *mut c_void,
406 device: mxr_uid_t,
407 request: *const mxr_action_transmit_request_t,
408 ),
409>;
410pub type mxr_ir_transmit_cb = Option<
412 extern "C" fn(
413 userdata: *mut c_void,
414 device: mxr_uid_t,
415 request: *const mxr_ir_transmit_request_t,
416 ),
417>;
418pub type mxr_blacklist_cb = Option<
420 extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, change: *const mxr_blacklist_change_t),
421>;
422pub type mxr_video_wall_cb = Option<
424 extern "C" fn(
425 userdata: *mut c_void,
426 device: mxr_uid_t,
427 command: *const mxr_video_wall_command_t,
428 ),
429>;
430pub type mxr_multiviewer_command_cb = Option<
432 extern "C" fn(
433 userdata: *mut c_void,
434 device: mxr_uid_t,
435 command: *const mxr_multiviewer_command_t,
436 ),
437>;
438pub type mxr_audio_select_cb = Option<
440 extern "C" fn(
441 userdata: *mut c_void,
442 device: mxr_uid_t,
443 change: *const mxr_audio_change_source_t,
444 ),
445>;
446pub type mxr_ir_capture_cb = Option<
448 extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, capture: *const mxr_ir_capture_t),
449>;
450
451#[repr(C)]
457#[derive(Clone, Copy)]
458pub struct mxr_callbacks_t {
459 pub on_device_update: mxr_device_cb,
461 pub on_bay_update: mxr_bay_cb,
463
464 pub on_device_config_changed: mxr_device_cb,
466 pub on_device_config_complete: mxr_device_cb,
468 pub on_device_online_changed: mxr_device_bool_cb,
470 pub on_device_temperature_changed: mxr_device_cb,
473 pub on_firmware_version_changed: mxr_device_cb,
476 pub on_system_status_changed: mxr_system_status_cb,
478 pub on_network_status_changed: mxr_device_cb,
481 pub on_v2ip_stats_changed: mxr_device_cb,
484 pub on_v2ip_sources_changed: mxr_device_cb,
487 pub on_v2ip_details_changed: mxr_device_cb,
490 pub on_v2ip_sink_changed: mxr_device_cb,
498 pub on_multiviewer_status_changed: mxr_device_cb,
501 pub on_audio_endpoints_changed: mxr_device_cb,
504 pub on_mesh_master_changed: mxr_device_uid_cb,
506 pub on_topology_changed: mxr_device_cb,
509 pub on_amp_dolby_settings_changed: mxr_device_cb,
512 pub on_setup_status_changed: mxr_device_bool_cb,
514 pub on_installer_id_changed: mxr_device_u16_cb,
516 pub on_tiling_changed: mxr_device_cb,
519 pub on_v2ip_features_changed: mxr_device_cb,
522 pub on_rc_settings_changed: mxr_device_cb,
525 pub on_v2ip_link_changed: mxr_device_uid_cb,
527 pub on_multiviewer_command: mxr_multiviewer_command_cb,
529 pub on_audio_select_input: mxr_audio_select_cb,
532 pub on_audio_endpoint_mute: mxr_endpoint_bool_cb,
534 pub on_audio_endpoint_trigger: mxr_endpoint_bool_cb,
536 pub on_audio_endpoint_volume: mxr_endpoint_u32_cb,
539 pub on_discover_request: mxr_device_cb,
541 pub on_set_route_requested: mxr_set_route_cb,
543 pub on_edid_requested: mxr_edid_request_cb,
545 pub on_edid_received: mxr_edid_record_cb,
547 pub on_bay_name_change_requested: mxr_bay_name_change_cb,
549 pub on_edid_profile_change_requested: mxr_edid_profile_change_cb,
551 pub on_reboot_requested: mxr_device_uid_cb,
555 pub on_factory_reset_requested: mxr_factory_reset_cb,
557 pub on_monitoring_pulse: mxr_device_cb,
559 pub on_upgrade_fpga_requested: mxr_device_cb,
561 pub on_detect_bays_requested: mxr_device_cb,
563 pub on_power_save_requested: mxr_power_save_cb,
565 pub on_key_transmit_requested: mxr_key_transmit_cb,
567 pub on_action_transmit_requested: mxr_action_transmit_cb,
569 pub on_ir_transmit_requested: mxr_ir_transmit_cb,
571 pub on_blacklist_changed: mxr_blacklist_cb,
574 pub on_video_wall_command: mxr_video_wall_cb,
576
577 pub on_bay_registered: mxr_bay_cb,
579 pub on_video_source_changed: mxr_bay_bay_cb,
581 pub on_audio_source_changed: mxr_bay_bay_cb,
583 pub on_volume_changed: mxr_volume_cb,
585 pub on_power_changed: mxr_power_cb,
587 pub on_name_changed: mxr_bay_str_cb,
589 pub on_signal_detected_changed: mxr_bay_bool_cb,
591 pub on_faulty_changed: mxr_bay_bool_cb,
593 pub on_hidden_changed: mxr_bay_bool_cb,
595 pub on_zone_powered_changed: mxr_bay_bool_cb,
597 pub on_hdbt_connected_changed: mxr_bay_bool_cb,
599 pub on_signal_type_changed: mxr_bay_str_cb,
601 pub on_hpd_detected_changed: mxr_bay_bool_cb,
603 pub on_cec_detected_changed: mxr_bay_bool_cb,
605 pub on_arc_changed: mxr_arc_cb,
607 pub on_edid_profile_changed: mxr_bay_u16_cb,
609 pub on_rc_type_changed: mxr_bay_u8_cb,
611 pub on_key_pressed: mxr_bay_u16_cb,
613 pub on_action_received: mxr_bay_u16_cb,
615 pub on_mirror_status_changed: mxr_bay_bay_cb,
618 pub on_amp_zone_settings_changed: mxr_bay_cb,
621 pub on_volume_step: mxr_bay_bool_cb,
623 pub on_audio_clip: mxr_bay_u8_cb,
625 pub on_ir_captured: mxr_ir_capture_cb,
627 pub on_filtered_devices_changed: mxr_bay_cb,
630 pub on_audio_endpoint_changed: mxr_bay_u8_cb,
632 pub on_encoder_disabled_changed: mxr_bay_bool_cb,
634 pub on_decoder_disabled_changed: mxr_bay_bool_cb,
636
637 pub on_bay_linked: mxr_bay_linked_cb,
642 pub on_bay_unlinked: mxr_bay_unlinked_cb,
645}
646
647struct UserData(*mut c_void);
656
657unsafe impl Send for UserData {}
660unsafe impl Sync for UserData {}
662
663pub(crate) struct Bridge {
665 cb: mxr_callbacks_t,
666 userdata: UserData,
667}
668
669impl Bridge {
670 pub(crate) fn new(table: &mxr_callbacks_t, userdata: *mut c_void) -> Self {
672 Self {
673 cb: *table,
674 userdata: UserData(userdata),
675 }
676 }
677
678 fn ud(&self) -> *mut c_void {
679 self.userdata.0
680 }
681}
682
683macro_rules! forward {
689 ($self:ident.$field:ident( $($arg:expr),* $(,)? )) => {
690 if let Some(f) = $self.cb.$field {
691 guard((), || f($self.ud() $(, $arg)*));
692 }
693 };
694}
695
696fn with_cstr<R>(text: &str, body: impl FnOnce(*const c_char) -> R) -> R {
698 let owned = CString::new(text).unwrap_or_else(|_| c"".to_owned());
701 body(owned.as_ptr())
702}
703
704fn uid_or_zero(uid: Option<DeviceUid>) -> mxr_uid_t {
707 uid.unwrap_or(DeviceUid::ZERO).into()
708}
709
710impl EventHandler for Bridge {
711 fn on_device_update(&self, device: DeviceUid) {
712 forward!(self.on_device_update(device.into()));
713 }
714
715 fn on_bay_update(&self, bay: BayUid) {
716 forward!(self.on_bay_update(bay.into()));
717 }
718
719 fn on_device_config_changed(&self, device: DeviceUid) {
722 forward!(self.on_device_config_changed(device.into()));
723 }
724
725 fn on_device_config_complete(&self, device: DeviceUid) {
726 forward!(self.on_device_config_complete(device.into()));
727 }
728
729 fn on_device_online_changed(&self, device: DeviceUid, online: bool) {
730 forward!(self.on_device_online_changed(device.into(), online));
731 }
732
733 fn on_device_temperature_changed(&self, device: DeviceUid, _temperatures: Vec<i8>) {
734 forward!(self.on_device_temperature_changed(device.into()));
735 }
736
737 fn on_firmware_version_changed(&self, device: DeviceUid, _version: mx_remote::FirmwareVersion) {
738 forward!(self.on_firmware_version_changed(device.into()));
739 }
740
741 fn on_system_status_changed(&self, device: DeviceUid, status: u16, message: String) {
742 with_cstr(&message, |m| {
743 forward!(self.on_system_status_changed(device.into(), status, m));
744 });
745 }
746
747 fn on_network_status_changed(&self, device: DeviceUid, _status: mx_remote::NetworkPortStatus) {
748 forward!(self.on_network_status_changed(device.into()));
749 }
750
751 fn on_v2ip_stats_changed(&self, device: DeviceUid, _stats: mx_remote::V2ipDeviceStats) {
752 forward!(self.on_v2ip_stats_changed(device.into()));
753 }
754
755 fn on_v2ip_sources_changed(
756 &self,
757 device: DeviceUid,
758 _sources: Vec<mx_remote::V2ipStreamSources>,
759 ) {
760 forward!(self.on_v2ip_sources_changed(device.into()));
761 }
762
763 fn on_v2ip_details_changed(&self, device: DeviceUid, _details: mx_remote::DeviceV2ipDetails) {
764 forward!(self.on_v2ip_details_changed(device.into()));
765 }
766
767 fn on_v2ip_sink_changed(&self, device: DeviceUid, _sink: mx_remote::DeviceV2ipSink) {
768 forward!(self.on_v2ip_sink_changed(device.into()));
769 }
770
771 fn on_multiviewer_status_changed(
772 &self,
773 device: DeviceUid,
774 _status: mx_remote::MultiviewerStatus,
775 ) {
776 forward!(self.on_multiviewer_status_changed(device.into()));
777 }
778
779 fn on_audio_endpoints_changed(&self, device: DeviceUid, _endpoints: mx_remote::AudioEndpoints) {
780 forward!(self.on_audio_endpoints_changed(device.into()));
781 }
782
783 fn on_mesh_master_changed(&self, device: DeviceUid, master: DeviceUid) {
784 forward!(self.on_mesh_master_changed(device.into(), master.into()));
785 }
786
787 fn on_topology_changed(&self, device: DeviceUid, _topology: Vec<mx_remote::TopologyEntry>) {
788 forward!(self.on_topology_changed(device.into()));
789 }
790
791 fn on_amp_dolby_settings_changed(
792 &self,
793 device: DeviceUid,
794 _settings: mx_remote::AmpDolbySettings,
795 ) {
796 forward!(self.on_amp_dolby_settings_changed(device.into()));
797 }
798
799 fn on_setup_status_changed(&self, device: DeviceUid, completed: bool) {
800 forward!(self.on_setup_status_changed(device.into(), completed));
801 }
802
803 fn on_installer_id_changed(&self, device: DeviceUid, installer_id: u16) {
804 forward!(self.on_installer_id_changed(device.into(), installer_id));
805 }
806
807 fn on_tiling_changed(&self, device: DeviceUid, _tiling: mx_remote::V2ipTilingConfig) {
808 forward!(self.on_tiling_changed(device.into()));
809 }
810
811 fn on_v2ip_features_changed(&self, device: DeviceUid, _features: mx_remote::V2ipFpgaFeature) {
812 forward!(self.on_v2ip_features_changed(device.into()));
813 }
814
815 fn on_rc_settings_changed(&self, device: DeviceUid, _settings: mx_remote::RcSettings) {
816 forward!(self.on_rc_settings_changed(device.into()));
817 }
818
819 fn on_v2ip_link_changed(&self, device: DeviceUid, target: DeviceUid) {
820 forward!(self.on_v2ip_link_changed(device.into(), target.into()));
821 }
822
823 fn on_multiviewer_command(&self, device: DeviceUid, command: MultiviewerCommand) {
824 let payload = mxr_multiviewer_command_t {
825 target: command.target.into(),
826 op: command.op,
827 params: command.params.as_ptr(),
828 params_len: command.params.len(),
829 };
830 forward!(self.on_multiviewer_command(device.into(), &payload));
831 }
832
833 fn on_audio_select_input(&self, device: DeviceUid, change: AudioChangeSource) {
834 let payload = mxr_audio_change_source_t {
835 source_uid: change.source_uid.into(),
836 source_id: change.source_id,
837 target_uid: change.target_uid.into(),
838 target_id: change.target_id,
839 };
840 forward!(self.on_audio_select_input(device.into(), &payload));
841 }
842
843 fn on_audio_endpoint_mute(&self, device: DeviceUid, endpoint: u16, muted: bool) {
844 forward!(self.on_audio_endpoint_mute(device.into(), endpoint, muted));
845 }
846
847 fn on_audio_endpoint_trigger(&self, device: DeviceUid, endpoint: u16, active: bool) {
848 forward!(self.on_audio_endpoint_trigger(device.into(), endpoint, active));
849 }
850
851 fn on_audio_endpoint_volume(&self, device: DeviceUid, endpoint: u16, volume: u32) {
852 forward!(self.on_audio_endpoint_volume(device.into(), endpoint, volume));
853 }
854
855 fn on_discover_request(&self, device: DeviceUid) {
856 forward!(self.on_discover_request(device.into()));
857 }
858
859 fn on_set_route_requested(&self, device: DeviceUid, request: SetRouteRequest) {
860 with_cstr(&request.serial, |serial| {
861 let payload = mxr_set_route_request_t {
862 serial,
863 sink_bay: request.sink_bay,
864 source_bay: request.source_bay,
865 no_power_on: request.no_power_on,
866 audio_only: request.audio_only,
867 };
868 forward!(self.on_set_route_requested(device.into(), &payload));
869 });
870 }
871
872 fn on_edid_requested(&self, device: DeviceUid, request: EdidRequest) {
873 let payload = mxr_edid_request_t {
874 target: request.target.into(),
875 output: request.output,
876 };
877 forward!(self.on_edid_requested(device.into(), &payload));
878 }
879
880 fn on_edid_received(&self, device: DeviceUid, edid: EdidRecord) {
881 let payload = mxr_edid_record_t {
882 output: edid.output,
883 data: edid.data.as_ptr(),
884 data_len: edid.data.len(),
885 };
886 forward!(self.on_edid_received(device.into(), &payload));
887 }
888
889 fn on_bay_name_change_requested(&self, device: DeviceUid, change: BayNameChange) {
890 with_cstr(&change.name, |name| {
891 let payload = mxr_bay_name_change_t {
892 target: change.target.into(),
893 port: change.port,
894 name,
895 };
896 forward!(self.on_bay_name_change_requested(device.into(), &payload));
897 });
898 }
899
900 fn on_edid_profile_change_requested(&self, device: DeviceUid, change: EdidProfileChange) {
901 let payload = mxr_edid_profile_change_t {
902 target: change.target.into(),
903 profile: change.profile.to_wire(),
904 };
905 forward!(self.on_edid_profile_change_requested(device.into(), &payload));
906 }
907
908 fn on_reboot_requested(&self, device: DeviceUid, request: RebootRequest) {
909 forward!(self.on_reboot_requested(device.into(), uid_or_zero(request.target)));
910 }
911
912 fn on_factory_reset_requested(&self, device: DeviceUid, request: FactoryResetRequest) {
913 let payload = mxr_factory_reset_request_t {
914 all: request.all,
915 target: uid_or_zero(request.target),
916 };
917 forward!(self.on_factory_reset_requested(device.into(), &payload));
918 }
919
920 fn on_monitoring_pulse(&self, device: DeviceUid) {
921 forward!(self.on_monitoring_pulse(device.into()));
922 }
923
924 fn on_upgrade_fpga_requested(&self, device: DeviceUid) {
925 forward!(self.on_upgrade_fpga_requested(device.into()));
926 }
927
928 fn on_detect_bays_requested(&self, device: DeviceUid) {
929 forward!(self.on_detect_bays_requested(device.into()));
930 }
931
932 fn on_power_save_requested(&self, device: DeviceUid, request: V2ipPowerSaveRequest) {
933 let payload = mxr_power_save_request_t {
934 target: uid_or_zero(request.target),
935 enabled: request.enabled,
936 };
937 forward!(self.on_power_save_requested(device.into(), &payload));
938 }
939
940 fn on_key_transmit_requested(&self, device: DeviceUid, request: KeyTransmitRequest) {
941 let payload = mxr_key_transmit_request_t {
942 target: request.target.into(),
943 local_bay: request.local_bay,
944 key: request.key.to_wire(),
945 };
946 forward!(self.on_key_transmit_requested(device.into(), &payload));
947 }
948
949 fn on_action_transmit_requested(&self, device: DeviceUid, request: ActionTransmitRequest) {
950 let payload = mxr_action_transmit_request_t {
951 target: request.target.into(),
952 local_bay: request.local_bay,
953 action: request.action.to_wire(),
954 };
955 forward!(self.on_action_transmit_requested(device.into(), &payload));
956 }
957
958 fn on_ir_transmit_requested(&self, device: DeviceUid, request: IrTransmitRequest) {
959 let payload = mxr_ir_transmit_request_t {
960 target: request.target.into(),
961 local_mode: request.local_mode,
962 local_bay: request.local_bay,
963 timestamp: request.timestamp,
964 meta: request.meta.into(),
965 timings: request.timings.as_ptr(),
966 timings_len: request.timings.len(),
967 };
968 forward!(self.on_ir_transmit_requested(device.into(), &payload));
969 }
970
971 fn on_blacklist_changed(&self, device: DeviceUid, change: V2ipBlacklistChange) {
972 let groups: Vec<u8> = change.groups.iter().flat_map(|g| g.octets()).collect();
973 let payload = mxr_blacklist_change_t {
974 groups: groups.as_ptr(),
975 groups_len: change.groups.len(),
976 registered: change.registered,
977 };
978 forward!(self.on_blacklist_changed(device.into(), &payload));
979 }
980
981 fn on_video_wall_command(&self, device: DeviceUid, command: VideoWallCommand) {
982 let payload = mxr_video_wall_command_t {
983 target: command.target.into(),
984 pos_x: command.pos_x,
985 pos_y: command.pos_y,
986 width: command.width,
987 height: command.height,
988 raster_w: command.raster_w,
989 raster_h: command.raster_h,
990 op: command.op.to_wire(),
991 };
992 forward!(self.on_video_wall_command(device.into(), &payload));
993 }
994
995 fn on_bay_registered(&self, bay: BayUid) {
998 forward!(self.on_bay_registered(bay.into()));
999 }
1000
1001 fn on_video_source_changed(&self, bay: BayUid, source: Option<BayUid>) {
1002 forward!(self.on_video_source_changed(bay.into(), bay_or_zero(source)));
1003 }
1004
1005 fn on_audio_source_changed(&self, bay: BayUid, source: Option<BayUid>) {
1006 forward!(self.on_audio_source_changed(bay.into(), bay_or_zero(source)));
1007 }
1008
1009 fn on_volume_changed(&self, bay: BayUid, volume: VolumeMuteStatus) {
1010 forward!(self.on_volume_changed(bay.into(), volume.volume(), volume.muted().into()));
1011 }
1012
1013 fn on_power_changed(&self, bay: BayUid, power: PowerStatus) {
1014 forward!(self.on_power_changed(bay.into(), Some(power).into()));
1015 }
1016
1017 fn on_name_changed(&self, bay: BayUid, name: String) {
1018 with_cstr(&name, |n| forward!(self.on_name_changed(bay.into(), n)));
1019 }
1020
1021 fn on_signal_detected_changed(&self, bay: BayUid, detected: bool) {
1022 forward!(self.on_signal_detected_changed(bay.into(), detected));
1023 }
1024
1025 fn on_faulty_changed(&self, bay: BayUid, faulty: bool) {
1026 forward!(self.on_faulty_changed(bay.into(), faulty));
1027 }
1028
1029 fn on_hidden_changed(&self, bay: BayUid, hidden: bool) {
1030 forward!(self.on_hidden_changed(bay.into(), hidden));
1031 }
1032
1033 fn on_zone_powered_changed(&self, bay: BayUid, powered: bool) {
1034 forward!(self.on_zone_powered_changed(bay.into(), powered));
1035 }
1036
1037 fn on_hdbt_connected_changed(&self, bay: BayUid, connected: bool) {
1038 forward!(self.on_hdbt_connected_changed(bay.into(), connected));
1039 }
1040
1041 fn on_signal_type_changed(&self, bay: BayUid, signal_type: String) {
1042 with_cstr(&signal_type, |s| {
1043 forward!(self.on_signal_type_changed(bay.into(), s))
1044 });
1045 }
1046
1047 fn on_hpd_detected_changed(&self, bay: BayUid, detected: bool) {
1048 forward!(self.on_hpd_detected_changed(bay.into(), detected));
1049 }
1050
1051 fn on_cec_detected_changed(&self, bay: BayUid, detected: bool) {
1052 forward!(self.on_cec_detected_changed(bay.into(), detected));
1053 }
1054
1055 fn on_arc_changed(&self, bay: BayUid, arc: ArcStatus) {
1056 forward!(self.on_arc_changed(bay.into(), arc.into()));
1057 }
1058
1059 fn on_edid_profile_changed(&self, bay: BayUid, profile: mx_remote::EdidProfile) {
1060 forward!(self.on_edid_profile_changed(bay.into(), profile.to_wire()));
1061 }
1062
1063 fn on_rc_type_changed(&self, bay: BayUid, rc_type: mx_remote::RcType) {
1064 forward!(self.on_rc_type_changed(bay.into(), rc_type.to_wire()));
1065 }
1066
1067 fn on_key_pressed(&self, bay: BayUid, key: RcKey) {
1068 forward!(self.on_key_pressed(bay.into(), key.to_wire()));
1069 }
1070
1071 fn on_action_received(&self, bay: BayUid, action: RcAction) {
1072 forward!(self.on_action_received(bay.into(), action.to_wire()));
1073 }
1074
1075 fn on_mirror_status_changed(&self, bay: BayUid, mirror: mx_remote::BayMirrorStatus) {
1076 forward!(self.on_mirror_status_changed(bay.into(), bay_or_zero(mirror.target)));
1077 }
1078
1079 fn on_amp_zone_settings_changed(&self, bay: BayUid, _settings: mx_remote::AmpZoneSettings) {
1080 forward!(self.on_amp_zone_settings_changed(bay.into()));
1081 }
1082
1083 fn on_volume_step(&self, bay: BayUid, up: bool) {
1084 forward!(self.on_volume_step(bay.into(), up));
1085 }
1086
1087 fn on_audio_clip(&self, bay: BayUid, clip: AudioClip) {
1088 forward!(self.on_audio_clip(bay.into(), clip.clip));
1089 }
1090
1091 fn on_ir_captured(&self, bay: BayUid, capture: IrCapture) {
1092 let payload = mxr_ir_capture_t {
1093 timestamp: capture.timestamp,
1094 last_change: capture.last_change,
1095 meta: capture.meta.into(),
1096 timings: capture.timings.as_ptr(),
1097 timings_len: capture.timings.len(),
1098 };
1099 forward!(self.on_ir_captured(bay.into(), &payload));
1100 }
1101
1102 fn on_filtered_devices_changed(&self, bay: BayUid, _filtered: Vec<DeviceUid>) {
1103 forward!(self.on_filtered_devices_changed(bay.into()));
1104 }
1105
1106 fn on_audio_endpoint_changed(&self, bay: BayUid, endpoint: u8) {
1107 forward!(self.on_audio_endpoint_changed(bay.into(), endpoint));
1108 }
1109
1110 fn on_encoder_disabled_changed(&self, bay: BayUid, disabled: bool) {
1111 forward!(self.on_encoder_disabled_changed(bay.into(), disabled));
1112 }
1113
1114 fn on_decoder_disabled_changed(&self, bay: BayUid, disabled: bool) {
1115 forward!(self.on_decoder_disabled_changed(bay.into(), disabled));
1116 }
1117
1118 fn on_bay_linked(
1121 &self,
1122 bay: BayUid,
1123 linked_serial: String,
1124 bay_name: String,
1125 features: LinkFeature,
1126 ) {
1127 with_cstr(&linked_serial, |serial| {
1128 with_cstr(&bay_name, |name| {
1129 forward!(self.on_bay_linked(bay.into(), serial, name, features.bits()));
1130 });
1131 });
1132 }
1133
1134 fn on_bay_unlinked(&self, bay: BayUid, linked_serial: String, bay_name: String) {
1135 with_cstr(&linked_serial, |serial| {
1136 with_cstr(&bay_name, |name| {
1137 forward!(self.on_bay_unlinked(bay.into(), serial, name));
1138 });
1139 });
1140 }
1141}