use std::ffi::{c_char, c_void, CString};
use mx_remote::{
ActionTransmitRequest, ArcStatus, AudioChangeSource, AudioClip, BayNameChange, BayUid,
DeviceUid, EdidProfileChange, EdidRecord, EdidRequest, EventHandler, FactoryResetRequest,
IrCapture, IrMeta, IrTransmitRequest, KeyTransmitRequest, LinkFeature, MultiviewerCommand,
PowerStatus, RcAction, RcKey, RebootRequest, SetRouteRequest, V2ipBlacklistChange,
V2ipPowerSaveRequest, VideoWallCommand, VolumeMuteStatus,
};
use crate::abi::{bay_or_zero, guard, mxr_bay_uid_t, mxr_tribool_t, mxr_uid_t};
use crate::info::{mxr_arc_status_t, mxr_power_status_t};
pub type mxr_device_cb = Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t)>;
pub type mxr_device_bool_cb =
Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, value: bool)>;
pub type mxr_device_uid_cb =
Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, other: mxr_uid_t)>;
pub type mxr_device_u16_cb =
Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, value: u16)>;
pub type mxr_endpoint_bool_cb =
Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, endpoint: u16, value: bool)>;
pub type mxr_endpoint_u32_cb =
Option<extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, endpoint: u16, value: u32)>;
pub type mxr_system_status_cb = Option<
extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, status: u16, message: *const c_char),
>;
pub type mxr_bay_cb = Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t)>;
pub type mxr_bay_bool_cb =
Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, value: bool)>;
pub type mxr_bay_str_cb =
Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, value: *const c_char)>;
pub type mxr_bay_bay_cb =
Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, other: mxr_bay_uid_t)>;
pub type mxr_bay_u8_cb =
Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, value: u8)>;
pub type mxr_bay_u16_cb =
Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, value: u16)>;
pub type mxr_volume_cb = Option<
extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, volume: u8, muted: mxr_tribool_t),
>;
pub type mxr_power_cb =
Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, power: mxr_power_status_t)>;
pub type mxr_arc_cb =
Option<extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, arc: mxr_arc_status_t)>;
pub type mxr_bay_linked_cb = Option<
extern "C" fn(
userdata: *mut c_void,
bay: mxr_bay_uid_t,
linked_serial: *const c_char,
bay_name: *const c_char,
features: u32,
),
>;
pub type mxr_bay_unlinked_cb = Option<
extern "C" fn(
userdata: *mut c_void,
bay: mxr_bay_uid_t,
linked_serial: *const c_char,
bay_name: *const c_char,
),
>;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_set_route_request_t {
pub serial: *const c_char,
pub sink_bay: u16,
pub source_bay: u16,
pub no_power_on: bool,
pub audio_only: bool,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_edid_request_t {
pub target: mxr_uid_t,
pub output: bool,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_edid_record_t {
pub output: bool,
pub data: *const u8,
pub data_len: usize,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_bay_name_change_t {
pub target: mxr_uid_t,
pub port: u16,
pub name: *const c_char,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_edid_profile_change_t {
pub target: mxr_uid_t,
pub profile: u16,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_factory_reset_request_t {
pub all: bool,
pub target: mxr_uid_t,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_power_save_request_t {
pub target: mxr_uid_t,
pub enabled: bool,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_key_transmit_request_t {
pub target: mxr_uid_t,
pub local_bay: u16,
pub key: u16,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_action_transmit_request_t {
pub target: mxr_uid_t,
pub local_bay: u16,
pub action: u16,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_ir_meta_t {
pub timer_resolution: u16,
pub frequency: u16,
pub nb_timings: u16,
pub repeat_offset: u16,
pub status: u8,
}
impl From<IrMeta> for mxr_ir_meta_t {
fn from(m: IrMeta) -> Self {
Self {
timer_resolution: m.timer_resolution,
frequency: m.frequency,
nb_timings: m.nb_timings,
repeat_offset: m.repeat_offset,
status: m.status,
}
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_ir_capture_t {
pub timestamp: u32,
pub last_change: u32,
pub meta: mxr_ir_meta_t,
pub timings: *const u8,
pub timings_len: usize,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_ir_transmit_request_t {
pub target: mxr_uid_t,
pub local_mode: u8,
pub local_bay: u8,
pub timestamp: u32,
pub meta: mxr_ir_meta_t,
pub timings: *const u8,
pub timings_len: usize,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_blacklist_change_t {
pub target: mxr_uid_t,
pub registered: bool,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_video_wall_command_t {
pub target: mxr_uid_t,
pub pos_x: u16,
pub pos_y: u16,
pub width: u16,
pub height: u16,
pub raster_w: u16,
pub raster_h: u16,
pub op: u8,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_multiviewer_command_t {
pub target: mxr_uid_t,
pub op: u8,
pub params: *const u8,
pub params_len: usize,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_audio_change_source_t {
pub source_uid: mxr_uid_t,
pub source_id: u16,
pub target_uid: mxr_uid_t,
pub target_id: u16,
}
pub type mxr_set_route_cb = Option<
extern "C" fn(
userdata: *mut c_void,
device: mxr_uid_t,
request: *const mxr_set_route_request_t,
),
>;
pub type mxr_edid_request_cb = Option<
extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, request: *const mxr_edid_request_t),
>;
pub type mxr_edid_record_cb = Option<
extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, record: *const mxr_edid_record_t),
>;
pub type mxr_bay_name_change_cb = Option<
extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, change: *const mxr_bay_name_change_t),
>;
pub type mxr_edid_profile_change_cb = Option<
extern "C" fn(
userdata: *mut c_void,
device: mxr_uid_t,
change: *const mxr_edid_profile_change_t,
),
>;
pub type mxr_factory_reset_cb = Option<
extern "C" fn(
userdata: *mut c_void,
device: mxr_uid_t,
request: *const mxr_factory_reset_request_t,
),
>;
pub type mxr_power_save_cb = Option<
extern "C" fn(
userdata: *mut c_void,
device: mxr_uid_t,
request: *const mxr_power_save_request_t,
),
>;
pub type mxr_key_transmit_cb = Option<
extern "C" fn(
userdata: *mut c_void,
device: mxr_uid_t,
request: *const mxr_key_transmit_request_t,
),
>;
pub type mxr_action_transmit_cb = Option<
extern "C" fn(
userdata: *mut c_void,
device: mxr_uid_t,
request: *const mxr_action_transmit_request_t,
),
>;
pub type mxr_ir_transmit_cb = Option<
extern "C" fn(
userdata: *mut c_void,
device: mxr_uid_t,
request: *const mxr_ir_transmit_request_t,
),
>;
pub type mxr_blacklist_cb = Option<
extern "C" fn(userdata: *mut c_void, device: mxr_uid_t, change: *const mxr_blacklist_change_t),
>;
pub type mxr_video_wall_cb = Option<
extern "C" fn(
userdata: *mut c_void,
device: mxr_uid_t,
command: *const mxr_video_wall_command_t,
),
>;
pub type mxr_multiviewer_command_cb = Option<
extern "C" fn(
userdata: *mut c_void,
device: mxr_uid_t,
command: *const mxr_multiviewer_command_t,
),
>;
pub type mxr_audio_select_cb = Option<
extern "C" fn(
userdata: *mut c_void,
device: mxr_uid_t,
change: *const mxr_audio_change_source_t,
),
>;
pub type mxr_ir_capture_cb = Option<
extern "C" fn(userdata: *mut c_void, bay: mxr_bay_uid_t, capture: *const mxr_ir_capture_t),
>;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct mxr_callbacks_t {
pub on_device_update: mxr_device_cb,
pub on_bay_update: mxr_bay_cb,
pub on_device_config_changed: mxr_device_cb,
pub on_device_config_complete: mxr_device_cb,
pub on_device_online_changed: mxr_device_bool_cb,
pub on_device_temperature_changed: mxr_device_cb,
pub on_firmware_version_changed: mxr_device_cb,
pub on_system_status_changed: mxr_system_status_cb,
pub on_network_status_changed: mxr_device_cb,
pub on_v2ip_stats_changed: mxr_device_cb,
pub on_v2ip_sources_changed: mxr_device_cb,
pub on_v2ip_details_changed: mxr_device_cb,
pub on_v2ip_sink_changed: mxr_device_cb,
pub on_multiviewer_status_changed: mxr_device_cb,
pub on_audio_endpoints_changed: mxr_device_cb,
pub on_mesh_master_changed: mxr_device_uid_cb,
pub on_topology_changed: mxr_device_cb,
pub on_amp_dolby_settings_changed: mxr_device_cb,
pub on_setup_status_changed: mxr_device_bool_cb,
pub on_installer_id_changed: mxr_device_u16_cb,
pub on_tiling_changed: mxr_device_cb,
pub on_rc_settings_changed: mxr_device_cb,
pub on_v2ip_link_changed: mxr_device_uid_cb,
pub on_multiviewer_command: mxr_multiviewer_command_cb,
pub on_audio_select_input: mxr_audio_select_cb,
pub on_audio_endpoint_mute: mxr_endpoint_bool_cb,
pub on_audio_endpoint_trigger: mxr_endpoint_bool_cb,
pub on_audio_endpoint_volume: mxr_endpoint_u32_cb,
pub on_discover_request: mxr_device_cb,
pub on_set_route_requested: mxr_set_route_cb,
pub on_edid_requested: mxr_edid_request_cb,
pub on_edid_received: mxr_edid_record_cb,
pub on_bay_name_change_requested: mxr_bay_name_change_cb,
pub on_edid_profile_change_requested: mxr_edid_profile_change_cb,
pub on_reboot_requested: mxr_device_uid_cb,
pub on_factory_reset_requested: mxr_factory_reset_cb,
pub on_monitoring_pulse: mxr_device_cb,
pub on_upgrade_fpga_requested: mxr_device_cb,
pub on_detect_bays_requested: mxr_device_cb,
pub on_power_save_requested: mxr_power_save_cb,
pub on_key_transmit_requested: mxr_key_transmit_cb,
pub on_action_transmit_requested: mxr_action_transmit_cb,
pub on_ir_transmit_requested: mxr_ir_transmit_cb,
pub on_blacklist_changed: mxr_blacklist_cb,
pub on_video_wall_command: mxr_video_wall_cb,
pub on_bay_registered: mxr_bay_cb,
pub on_video_source_changed: mxr_bay_bay_cb,
pub on_audio_source_changed: mxr_bay_bay_cb,
pub on_volume_changed: mxr_volume_cb,
pub on_power_changed: mxr_power_cb,
pub on_name_changed: mxr_bay_str_cb,
pub on_signal_detected_changed: mxr_bay_bool_cb,
pub on_faulty_changed: mxr_bay_bool_cb,
pub on_hidden_changed: mxr_bay_bool_cb,
pub on_poe_powered_changed: mxr_bay_bool_cb,
pub on_hdbt_connected_changed: mxr_bay_bool_cb,
pub on_signal_type_changed: mxr_bay_str_cb,
pub on_hpd_detected_changed: mxr_bay_bool_cb,
pub on_cec_detected_changed: mxr_bay_bool_cb,
pub on_arc_changed: mxr_arc_cb,
pub on_edid_profile_changed: mxr_bay_u16_cb,
pub on_rc_type_changed: mxr_bay_u8_cb,
pub on_key_pressed: mxr_bay_u16_cb,
pub on_action_received: mxr_bay_u16_cb,
pub on_mirror_status_changed: mxr_bay_bay_cb,
pub on_amp_zone_settings_changed: mxr_bay_cb,
pub on_volume_step: mxr_bay_bool_cb,
pub on_audio_clip: mxr_bay_u8_cb,
pub on_ir_captured: mxr_ir_capture_cb,
pub on_filtered_devices_changed: mxr_bay_cb,
pub on_audio_endpoint_changed: mxr_bay_u8_cb,
pub on_encoder_disabled_changed: mxr_bay_bool_cb,
pub on_decoder_disabled_changed: mxr_bay_bool_cb,
pub on_bay_linked: mxr_bay_linked_cb,
pub on_bay_unlinked: mxr_bay_unlinked_cb,
}
struct UserData(*mut c_void);
unsafe impl Send for UserData {}
unsafe impl Sync for UserData {}
pub(crate) struct Bridge {
cb: mxr_callbacks_t,
userdata: UserData,
}
impl Bridge {
pub(crate) fn new(table: &mxr_callbacks_t, userdata: *mut c_void) -> Self {
Self {
cb: *table,
userdata: UserData(userdata),
}
}
fn ud(&self) -> *mut c_void {
self.userdata.0
}
}
macro_rules! forward {
($self:ident.$field:ident( $($arg:expr),* $(,)? )) => {
if let Some(f) = $self.cb.$field {
guard((), || f($self.ud() $(, $arg)*));
}
};
}
fn with_cstr<R>(text: &str, body: impl FnOnce(*const c_char) -> R) -> R {
let owned = CString::new(text).unwrap_or_else(|_| c"".to_owned());
body(owned.as_ptr())
}
fn uid_or_zero(uid: Option<DeviceUid>) -> mxr_uid_t {
uid.unwrap_or(DeviceUid::ZERO).into()
}
impl EventHandler for Bridge {
fn on_device_update(&self, device: DeviceUid) {
forward!(self.on_device_update(device.into()));
}
fn on_bay_update(&self, bay: BayUid) {
forward!(self.on_bay_update(bay.into()));
}
fn on_device_config_changed(&self, device: DeviceUid) {
forward!(self.on_device_config_changed(device.into()));
}
fn on_device_config_complete(&self, device: DeviceUid) {
forward!(self.on_device_config_complete(device.into()));
}
fn on_device_online_changed(&self, device: DeviceUid, online: bool) {
forward!(self.on_device_online_changed(device.into(), online));
}
fn on_device_temperature_changed(&self, device: DeviceUid, _temperatures: Vec<u8>) {
forward!(self.on_device_temperature_changed(device.into()));
}
fn on_firmware_version_changed(&self, device: DeviceUid, _version: mx_remote::FirmwareVersion) {
forward!(self.on_firmware_version_changed(device.into()));
}
fn on_system_status_changed(&self, device: DeviceUid, status: u16, message: String) {
with_cstr(&message, |m| {
forward!(self.on_system_status_changed(device.into(), status, m));
});
}
fn on_network_status_changed(&self, device: DeviceUid, _status: mx_remote::NetworkPortStatus) {
forward!(self.on_network_status_changed(device.into()));
}
fn on_v2ip_stats_changed(&self, device: DeviceUid, _stats: mx_remote::V2ipDeviceStats) {
forward!(self.on_v2ip_stats_changed(device.into()));
}
fn on_v2ip_sources_changed(
&self,
device: DeviceUid,
_sources: Vec<mx_remote::V2ipStreamSources>,
) {
forward!(self.on_v2ip_sources_changed(device.into()));
}
fn on_v2ip_details_changed(&self, device: DeviceUid, _details: mx_remote::DeviceV2ipDetails) {
forward!(self.on_v2ip_details_changed(device.into()));
}
fn on_v2ip_sink_changed(&self, device: DeviceUid, _sink: mx_remote::DeviceV2ipSink) {
forward!(self.on_v2ip_sink_changed(device.into()));
}
fn on_multiviewer_status_changed(
&self,
device: DeviceUid,
_status: mx_remote::MultiviewerStatus,
) {
forward!(self.on_multiviewer_status_changed(device.into()));
}
fn on_audio_endpoints_changed(&self, device: DeviceUid, _endpoints: mx_remote::AudioEndpoints) {
forward!(self.on_audio_endpoints_changed(device.into()));
}
fn on_mesh_master_changed(&self, device: DeviceUid, master: DeviceUid) {
forward!(self.on_mesh_master_changed(device.into(), master.into()));
}
fn on_topology_changed(&self, device: DeviceUid, _topology: Vec<mx_remote::TopologyEntry>) {
forward!(self.on_topology_changed(device.into()));
}
fn on_amp_dolby_settings_changed(
&self,
device: DeviceUid,
_settings: mx_remote::AmpDolbySettings,
) {
forward!(self.on_amp_dolby_settings_changed(device.into()));
}
fn on_setup_status_changed(&self, device: DeviceUid, completed: bool) {
forward!(self.on_setup_status_changed(device.into(), completed));
}
fn on_installer_id_changed(&self, device: DeviceUid, installer_id: u16) {
forward!(self.on_installer_id_changed(device.into(), installer_id));
}
fn on_tiling_changed(&self, device: DeviceUid, _tiling: mx_remote::V2ipTilingConfig) {
forward!(self.on_tiling_changed(device.into()));
}
fn on_rc_settings_changed(&self, device: DeviceUid, _settings: mx_remote::RcSettings) {
forward!(self.on_rc_settings_changed(device.into()));
}
fn on_v2ip_link_changed(&self, device: DeviceUid, target: DeviceUid) {
forward!(self.on_v2ip_link_changed(device.into(), target.into()));
}
fn on_multiviewer_command(&self, device: DeviceUid, command: MultiviewerCommand) {
let payload = mxr_multiviewer_command_t {
target: command.target.into(),
op: command.op,
params: command.params.as_ptr(),
params_len: command.params.len(),
};
forward!(self.on_multiviewer_command(device.into(), &payload));
}
fn on_audio_select_input(&self, device: DeviceUid, change: AudioChangeSource) {
let payload = mxr_audio_change_source_t {
source_uid: change.source_uid.into(),
source_id: change.source_id,
target_uid: change.target_uid.into(),
target_id: change.target_id,
};
forward!(self.on_audio_select_input(device.into(), &payload));
}
fn on_audio_endpoint_mute(&self, device: DeviceUid, endpoint: u16, muted: bool) {
forward!(self.on_audio_endpoint_mute(device.into(), endpoint, muted));
}
fn on_audio_endpoint_trigger(&self, device: DeviceUid, endpoint: u16, active: bool) {
forward!(self.on_audio_endpoint_trigger(device.into(), endpoint, active));
}
fn on_audio_endpoint_volume(&self, device: DeviceUid, endpoint: u16, volume: u32) {
forward!(self.on_audio_endpoint_volume(device.into(), endpoint, volume));
}
fn on_discover_request(&self, device: DeviceUid) {
forward!(self.on_discover_request(device.into()));
}
fn on_set_route_requested(&self, device: DeviceUid, request: SetRouteRequest) {
with_cstr(&request.serial, |serial| {
let payload = mxr_set_route_request_t {
serial,
sink_bay: request.sink_bay,
source_bay: request.source_bay,
no_power_on: request.no_power_on,
audio_only: request.audio_only,
};
forward!(self.on_set_route_requested(device.into(), &payload));
});
}
fn on_edid_requested(&self, device: DeviceUid, request: EdidRequest) {
let payload = mxr_edid_request_t {
target: request.target.into(),
output: request.output,
};
forward!(self.on_edid_requested(device.into(), &payload));
}
fn on_edid_received(&self, device: DeviceUid, edid: EdidRecord) {
let payload = mxr_edid_record_t {
output: edid.output,
data: edid.data.as_ptr(),
data_len: edid.data.len(),
};
forward!(self.on_edid_received(device.into(), &payload));
}
fn on_bay_name_change_requested(&self, device: DeviceUid, change: BayNameChange) {
with_cstr(&change.name, |name| {
let payload = mxr_bay_name_change_t {
target: change.target.into(),
port: change.port,
name,
};
forward!(self.on_bay_name_change_requested(device.into(), &payload));
});
}
fn on_edid_profile_change_requested(&self, device: DeviceUid, change: EdidProfileChange) {
let payload = mxr_edid_profile_change_t {
target: change.target.into(),
profile: change.profile.to_wire(),
};
forward!(self.on_edid_profile_change_requested(device.into(), &payload));
}
fn on_reboot_requested(&self, device: DeviceUid, request: RebootRequest) {
forward!(self.on_reboot_requested(device.into(), request.target.into()));
}
fn on_factory_reset_requested(&self, device: DeviceUid, request: FactoryResetRequest) {
let payload = mxr_factory_reset_request_t {
all: request.all,
target: uid_or_zero(request.target),
};
forward!(self.on_factory_reset_requested(device.into(), &payload));
}
fn on_monitoring_pulse(&self, device: DeviceUid) {
forward!(self.on_monitoring_pulse(device.into()));
}
fn on_upgrade_fpga_requested(&self, device: DeviceUid) {
forward!(self.on_upgrade_fpga_requested(device.into()));
}
fn on_detect_bays_requested(&self, device: DeviceUid) {
forward!(self.on_detect_bays_requested(device.into()));
}
fn on_power_save_requested(&self, device: DeviceUid, request: V2ipPowerSaveRequest) {
let payload = mxr_power_save_request_t {
target: uid_or_zero(request.target),
enabled: request.enabled,
};
forward!(self.on_power_save_requested(device.into(), &payload));
}
fn on_key_transmit_requested(&self, device: DeviceUid, request: KeyTransmitRequest) {
let payload = mxr_key_transmit_request_t {
target: request.target.into(),
local_bay: request.local_bay,
key: request.key.to_wire(),
};
forward!(self.on_key_transmit_requested(device.into(), &payload));
}
fn on_action_transmit_requested(&self, device: DeviceUid, request: ActionTransmitRequest) {
let payload = mxr_action_transmit_request_t {
target: request.target.into(),
local_bay: request.local_bay,
action: request.action.to_wire(),
};
forward!(self.on_action_transmit_requested(device.into(), &payload));
}
fn on_ir_transmit_requested(&self, device: DeviceUid, request: IrTransmitRequest) {
let payload = mxr_ir_transmit_request_t {
target: request.target.into(),
local_mode: request.local_mode,
local_bay: request.local_bay,
timestamp: request.timestamp,
meta: request.meta.into(),
timings: request.timings.as_ptr(),
timings_len: request.timings.len(),
};
forward!(self.on_ir_transmit_requested(device.into(), &payload));
}
fn on_blacklist_changed(&self, device: DeviceUid, change: V2ipBlacklistChange) {
let payload = mxr_blacklist_change_t {
target: change.target.into(),
registered: change.registered,
};
forward!(self.on_blacklist_changed(device.into(), &payload));
}
fn on_video_wall_command(&self, device: DeviceUid, command: VideoWallCommand) {
let payload = mxr_video_wall_command_t {
target: command.target.into(),
pos_x: command.pos_x,
pos_y: command.pos_y,
width: command.width,
height: command.height,
raster_w: command.raster_w,
raster_h: command.raster_h,
op: command.op.to_wire(),
};
forward!(self.on_video_wall_command(device.into(), &payload));
}
fn on_bay_registered(&self, bay: BayUid) {
forward!(self.on_bay_registered(bay.into()));
}
fn on_video_source_changed(&self, bay: BayUid, source: Option<BayUid>) {
forward!(self.on_video_source_changed(bay.into(), bay_or_zero(source)));
}
fn on_audio_source_changed(&self, bay: BayUid, source: Option<BayUid>) {
forward!(self.on_audio_source_changed(bay.into(), bay_or_zero(source)));
}
fn on_volume_changed(&self, bay: BayUid, volume: VolumeMuteStatus) {
forward!(self.on_volume_changed(bay.into(), volume.volume(), volume.muted().into()));
}
fn on_power_changed(&self, bay: BayUid, power: PowerStatus) {
forward!(self.on_power_changed(bay.into(), Some(power).into()));
}
fn on_name_changed(&self, bay: BayUid, name: String) {
with_cstr(&name, |n| forward!(self.on_name_changed(bay.into(), n)));
}
fn on_signal_detected_changed(&self, bay: BayUid, detected: bool) {
forward!(self.on_signal_detected_changed(bay.into(), detected));
}
fn on_faulty_changed(&self, bay: BayUid, faulty: bool) {
forward!(self.on_faulty_changed(bay.into(), faulty));
}
fn on_hidden_changed(&self, bay: BayUid, hidden: bool) {
forward!(self.on_hidden_changed(bay.into(), hidden));
}
fn on_poe_powered_changed(&self, bay: BayUid, powered: bool) {
forward!(self.on_poe_powered_changed(bay.into(), powered));
}
fn on_hdbt_connected_changed(&self, bay: BayUid, connected: bool) {
forward!(self.on_hdbt_connected_changed(bay.into(), connected));
}
fn on_signal_type_changed(&self, bay: BayUid, signal_type: String) {
with_cstr(&signal_type, |s| {
forward!(self.on_signal_type_changed(bay.into(), s))
});
}
fn on_hpd_detected_changed(&self, bay: BayUid, detected: bool) {
forward!(self.on_hpd_detected_changed(bay.into(), detected));
}
fn on_cec_detected_changed(&self, bay: BayUid, detected: bool) {
forward!(self.on_cec_detected_changed(bay.into(), detected));
}
fn on_arc_changed(&self, bay: BayUid, arc: ArcStatus) {
forward!(self.on_arc_changed(bay.into(), arc.into()));
}
fn on_edid_profile_changed(&self, bay: BayUid, profile: mx_remote::EdidProfile) {
forward!(self.on_edid_profile_changed(bay.into(), profile.to_wire()));
}
fn on_rc_type_changed(&self, bay: BayUid, rc_type: mx_remote::RcType) {
forward!(self.on_rc_type_changed(bay.into(), rc_type.to_wire()));
}
fn on_key_pressed(&self, bay: BayUid, key: RcKey) {
forward!(self.on_key_pressed(bay.into(), key.to_wire()));
}
fn on_action_received(&self, bay: BayUid, action: RcAction) {
forward!(self.on_action_received(bay.into(), action.to_wire()));
}
fn on_mirror_status_changed(&self, bay: BayUid, mirror: mx_remote::BayMirrorStatus) {
forward!(self.on_mirror_status_changed(bay.into(), bay_or_zero(mirror.target)));
}
fn on_amp_zone_settings_changed(&self, bay: BayUid, _settings: mx_remote::AmpZoneSettings) {
forward!(self.on_amp_zone_settings_changed(bay.into()));
}
fn on_volume_step(&self, bay: BayUid, up: bool) {
forward!(self.on_volume_step(bay.into(), up));
}
fn on_audio_clip(&self, bay: BayUid, clip: AudioClip) {
forward!(self.on_audio_clip(bay.into(), clip.clip));
}
fn on_ir_captured(&self, bay: BayUid, capture: IrCapture) {
let payload = mxr_ir_capture_t {
timestamp: capture.timestamp,
last_change: capture.last_change,
meta: capture.meta.into(),
timings: capture.timings.as_ptr(),
timings_len: capture.timings.len(),
};
forward!(self.on_ir_captured(bay.into(), &payload));
}
fn on_filtered_devices_changed(&self, bay: BayUid, _filtered: Vec<DeviceUid>) {
forward!(self.on_filtered_devices_changed(bay.into()));
}
fn on_audio_endpoint_changed(&self, bay: BayUid, endpoint: u8) {
forward!(self.on_audio_endpoint_changed(bay.into(), endpoint));
}
fn on_encoder_disabled_changed(&self, bay: BayUid, disabled: bool) {
forward!(self.on_encoder_disabled_changed(bay.into(), disabled));
}
fn on_decoder_disabled_changed(&self, bay: BayUid, disabled: bool) {
forward!(self.on_decoder_disabled_changed(bay.into(), disabled));
}
fn on_bay_linked(
&self,
bay: BayUid,
linked_serial: String,
bay_name: String,
features: LinkFeature,
) {
with_cstr(&linked_serial, |serial| {
with_cstr(&bay_name, |name| {
forward!(self.on_bay_linked(bay.into(), serial, name, features.bits()));
});
});
}
fn on_bay_unlinked(&self, bay: BayUid, linked_serial: String, bay_name: String) {
with_cstr(&linked_serial, |serial| {
with_cstr(&bay_name, |name| {
forward!(self.on_bay_unlinked(bay.into(), serial, name));
});
});
}
}