pub struct Remote { /* private fields */ }Expand description
A client on the MX Remote network.
Create one with Remote::new, then Remote::start it. Discovery runs
on threads this client owns until Remote::close, or until the Remote
is dropped.
Implementations§
Source§impl Remote
impl Remote
Sourcepub fn select_video_source(
&self,
sink: BayUid,
source_port: u16,
) -> Result<(), ControlError>
pub fn select_video_source( &self, sink: BayUid, source_port: u16, ) -> Result<(), ControlError>
Routes this OneIP sink’s video to the stream a source port advertises.
The sink’s audio then follows the video: a separate audio route is dropped, so route audio after video to keep them apart. A unit below protocol 0x27 is routed the source’s audio stream instead, as some of those route no audio for “follow the video”.
Sourcepub fn select_audio_source(
&self,
sink: BayUid,
source_port: u16,
) -> Result<(), ControlError>
pub fn select_audio_source( &self, sink: BayUid, source_port: u16, ) -> Result<(), ControlError>
Routes this OneIP sink’s audio to the stream a source port advertises.
Sourcepub fn select_video_source_by_name(
&self,
sink: BayUid,
name: &str,
) -> Result<(), ControlError>
pub fn select_video_source_by_name( &self, sink: BayUid, name: &str, ) -> Result<(), ControlError>
Routes this OneIP sink’s video to the input bay with the given user-assigned name.
Sourcepub fn select_audio_source_addr(
&self,
sink: BayUid,
audio_ip: Ipv4Addr,
audio_port: Option<u16>,
format: Option<V2ipAudioFormat>,
) -> Result<(), ControlError>
pub fn select_audio_source_addr( &self, sink: BayUid, audio_ip: Ipv4Addr, audio_port: Option<u16>, format: Option<V2ipAudioFormat>, ) -> Result<(), ControlError>
Routes this OneIP sink’s audio to a multicast address directly, leaving its video and ancillary streams alone.
An unset port is the standard OneIP audio port. A format overrides the sample rate and channel count the receiver would otherwise assume.
Sourcepub fn select_source_addr(
&self,
sink: BayUid,
route: V2ipRoute,
format: Option<V2ipAudioFormat>,
) -> Result<(), ControlError>
pub fn select_source_addr( &self, sink: BayUid, route: V2ipRoute, format: Option<V2ipAudioFormat>, ) -> Result<(), ControlError>
Routes this OneIP sink’s video, audio and ancillary streams to multicast groups the caller names.
This is the only way to reach a stream no device on the mesh advertises, such as one the host is transmitting itself; a route by source port can only name a stream some bay has announced.
Set all three groups. The firmware decides whether a sink has a manual route by looking at the video and ancillary groups, so a route that leaves either unset does not register as one and the sink falls back to the audio source its mesh picks.
An unset format sends V2ipAudioFormat::STANDARD rather than
omitting the trailer. The firmware stores whatever this frame carries
and hands it to the FPGA unexamined, so a frame without one leaves a
zero rate and zero channel count there, which the FPGA rejects and
which takes the switch down with it.
Sourcepub fn select_audio_source_by_name(
&self,
sink: BayUid,
name: &str,
format: Option<V2ipAudioFormat>,
) -> Result<(), ControlError>
pub fn select_audio_source_by_name( &self, sink: BayUid, name: &str, format: Option<V2ipAudioFormat>, ) -> Result<(), ControlError>
Routes this OneIP sink’s audio from the input bay with the given user-assigned name.
A format is carried on the manual switch frame, which is the only form that can override the receiver’s sample rate and channel count.
Sourcepub fn set_bay_name(&self, bay: BayUid, name: &str) -> Result<(), ControlError>
pub fn set_bay_name(&self, bay: BayUid, name: &str) -> Result<(), ControlError>
Renames a bay.
Hides a bay from the pickers that list it, or shows it again.
Sourcepub fn select_edid_profile(
&self,
bay: BayUid,
profile: EdidProfile,
) -> Result<(), ControlError>
pub fn select_edid_profile( &self, bay: BayUid, profile: EdidProfile, ) -> Result<(), ControlError>
Sets the EDID profile an input presents to the source attached to it.
Sourcepub fn send_action(
&self,
bay: BayUid,
action: RcAction,
) -> Result<(), ControlError>
pub fn send_action( &self, bay: BayUid, action: RcAction, ) -> Result<(), ControlError>
Sends a remote-control action to whatever is attached to a bay.
Sourcepub fn send_key(&self, bay: BayUid, key: RcKey) -> Result<(), ControlError>
pub fn send_key(&self, bay: BayUid, key: RcKey) -> Result<(), ControlError>
Sends a remote-control key press to whatever is attached to a bay.
The device forwards it over CEC, infrared or IP, whichever that bay is
configured for; the caller does not choose. An action from
Remote::send_action names an outcome instead, and the device
decides which keys reach it.
Sourcepub fn power_on(&self, bay: BayUid) -> Result<(), ControlError>
pub fn power_on(&self, bay: BayUid) -> Result<(), ControlError>
Powers on the device attached to a bay.
Sourcepub fn power_off(&self, bay: BayUid) -> Result<(), ControlError>
pub fn power_off(&self, bay: BayUid) -> Result<(), ControlError>
Powers off the device attached to a bay.
Sourcepub fn set_volume(
&self,
bay: BayUid,
volume: u8,
muted: Option<bool>,
) -> Result<(), ControlError>
pub fn set_volume( &self, bay: BayUid, volume: u8, muted: Option<bool>, ) -> Result<(), ControlError>
Sets a bay’s volume, as a percentage, and optionally its mute state.
Both channels are set together: the wire carries them separately, but nothing on this surface splits them.
A bay with no volume control of its own is set through its
linked_bay, so an output wired to an
amplifier zone reaches that zone. volume_up,
volume_down and set_muted
follow the same link, and read the volume they step from through it.
Sourcepub fn volume_up(&self, bay: BayUid) -> Result<(), ControlError>
pub fn volume_up(&self, bay: BayUid) -> Result<(), ControlError>
Raises a bay’s volume by one percent.
The step carries the mute state the bay last reported rather than “unchanged”, which an older matrix reads as mute.
Sourcepub fn volume_down(&self, bay: BayUid) -> Result<(), ControlError>
pub fn volume_down(&self, bay: BayUid) -> Result<(), ControlError>
Lowers a bay’s volume by one percent, as Remote::volume_up does.
Sourcepub fn set_muted(&self, bay: BayUid, muted: bool) -> Result<(), ControlError>
pub fn set_muted(&self, bay: BayUid, muted: bool) -> Result<(), ControlError>
Mutes or unmutes a bay, keeping the volume it is set to.
Sourcepub fn set_amp_zone_settings(
&self,
bay: BayUid,
settings: AmpZoneSettings,
) -> Result<(), ControlError>
pub fn set_amp_zone_settings( &self, bay: BayUid, settings: AmpZoneSettings, ) -> Result<(), ControlError>
Applies amplifier settings to a zone.
Sourcepub fn set_audio_endpoint_muted(
&self,
device: DeviceUid,
endpoint: u16,
muted: bool,
) -> Result<(), ControlError>
pub fn set_audio_endpoint_muted( &self, device: DeviceUid, endpoint: u16, muted: bool, ) -> Result<(), ControlError>
Mutes or unmutes an audio endpoint.
Refused unless the endpoint reports AudioFeatures::MUTE: a unit
changes nothing for one that does not.
Sourcepub fn set_audio_endpoint_trigger(
&self,
device: DeviceUid,
endpoint: u16,
active: bool,
) -> Result<(), ControlError>
pub fn set_audio_endpoint_trigger( &self, device: DeviceUid, endpoint: u16, active: bool, ) -> Result<(), ControlError>
Sets an audio endpoint’s trigger output.
Refused unless the endpoint reports AudioFeatures::TRIGGER: a unit
changes nothing for one that does not.
Sourcepub fn set_audio_endpoint_locked(
&self,
device: DeviceUid,
endpoint: u8,
locked: bool,
) -> Result<(), ControlError>
pub fn set_audio_endpoint_locked( &self, device: DeviceUid, endpoint: u8, locked: bool, ) -> Result<(), ControlError>
Locks or unlocks the audio source of an audio endpoint: while it is locked, a video route change leaves the endpoint’s audio source alone.
Refused unless the endpoint reports
AudioFeatures::AUDIO_LOCK, which
is the only one the device acts on. The device reports its endpoints
again once the lock has changed;
AudioEndpoints::status reads it.
Sourcepub fn set_audio_endpoint_volume(
&self,
_device: DeviceUid,
_endpoint: u16,
_volume: u32,
) -> Result<(), ControlError>
pub fn set_audio_endpoint_volume( &self, _device: DeviceUid, _endpoint: u16, _volume: u32, ) -> Result<(), ControlError>
Sets an audio endpoint’s volume. Always refused.
No unit acts on the command: the audio module defines it but neither sends nor handles it, and a unit on released firmware reads the same sub-opcode as a request to select an output.
Sourcepub fn select_audio_endpoint_input(
&self,
sink: DeviceUid,
sink_endpoint: u16,
source: DeviceUid,
source_endpoint: u16,
) -> Result<(), ControlError>
pub fn select_audio_endpoint_input( &self, sink: DeviceUid, sink_endpoint: u16, source: DeviceUid, source_endpoint: u16, ) -> Result<(), ControlError>
Routes a source endpoint on one device to a sink endpoint on another.
A unit on released firmware up to 4.4.2 routes only between its own endpoints, so a route from another unit to one is refused.
Sourcepub fn subscribe_v2ip_stats(
&self,
device: DeviceUid,
subscribe: bool,
) -> Result<(), ControlError>
pub fn subscribe_v2ip_stats( &self, device: DeviceUid, subscribe: bool, ) -> Result<(), ControlError>
Starts or stops a OneIP device reporting its transport statistics.
There is no free-running mode: a device reports only while a subscription is live, at 1Hz, and the subscription lapses after a minute. A caller that wants a continuous feed re-sends inside the minute; nothing here re-arms it.
Reports reach crate::EventHandler::on_v2ip_stats_changed and read
back through Remote::v2ip_stats. A device new enough to send it also
carries what the sink’s decoder recovered, in
crate::V2ipDeviceStats::decoder.
Sourcepub fn request_edid(
&self,
device: DeviceUid,
output: bool,
) -> Result<(), ControlError>
pub fn request_edid( &self, device: DeviceUid, output: bool, ) -> Result<(), ControlError>
Asks a device for an EDID: the one the display on its output publishes, or the one it presents to the source on its input.
The device answers with a frame the receive path decodes, so the bytes
arrive at crate::EventHandler::on_edid_received and stay readable
through Remote::edid.
Only OneIP hardware handles this opcode. A matrix or an amplifier accepts the frame and answers nothing, at any protocol version, so the silence that follows is permanent rather than a reply still to come. This call cannot tell the two apart and does not try: it reports what was sent, and a caller polling for an EDID should ask a device that can answer rather than wait on one that cannot.
Sourcepub fn request_signal_status(
&self,
device: Option<DeviceUid>,
) -> Result<(), ControlError>
pub fn request_signal_status( &self, device: Option<DeviceUid>, ) -> Result<(), ControlError>
Asks for a detailed signal report from every bay of one device, or - with no device named - from every bay on the network.
Devices report on their own when a signal changes, so this is what a client that has just started needs: without it, a bay that has been showing the same picture for an hour says nothing until it changes.
Sourcepub fn reboot(&self, device: DeviceUid) -> Result<(), ControlError>
pub fn reboot(&self, device: DeviceUid) -> Result<(), ControlError>
Reboots a device.
The device is marked as rebooting once the frame is away, so the silence that follows does not read as one that went offline. A device on protocol 0x2C or later takes it only from its mesh controller or a management application, which this client announces itself as.
Sourcepub fn ping(&self, device: DeviceUid) -> Result<(), ControlError>
pub fn ping(&self, device: DeviceUid) -> Result<(), ControlError>
Asks a device to announce itself now.
Its hello marks it online again, so a device suspected to be gone is confirmed or ruled out within a second or two rather than at the end of its silence window. A device that stays silent is not taken offline here: that remains the silence window’s call.
Sourcepub fn auto_assign_v2ip_source_addresses(
&self,
device: DeviceUid,
) -> Result<(), ControlError>
pub fn auto_assign_v2ip_source_addresses( &self, device: DeviceUid, ) -> Result<(), ControlError>
Hands a OneIP source’s stream addresses back to automatic assignment, undoing addresses that were set on it by hand.
The device takes this only from management, which this client
announces itself as. Nothing acknowledges it: the device’s next
configuration report carries the addresses it ends up with, and
Remote::v2ip_details reads them.
Refused for a device that is not a OneIP source, and for one below protocol 0x2B, which predates the operation and ignores it.
Sourcepub fn play_v2ip_sdp(
&self,
device: DeviceUid,
sdp: &str,
) -> Result<(), ControlError>
pub fn play_v2ip_sdp( &self, device: DeviceUid, sdp: &str, ) -> Result<(), ControlError>
Has a OneIP output play the stream a session description describes.
The description goes out in pages of up to 1 KB, and the output plays
it once the last page is in. It takes them only from its mesh
controller or a management application, which this client announces
itself as. Nothing acknowledges the pages: Remote::v2ip_sink_sdp
reads what the output reports next. Refused for an empty description
or one longer than V2IP_SDP_MAX bytes, for a
device that is not a OneIP output, and for one below protocol 0x2E.
Sourcepub fn stop_v2ip_sdp(&self, device: DeviceUid) -> Result<(), ControlError>
pub fn stop_v2ip_sdp(&self, device: DeviceUid) -> Result<(), ControlError>
Stops the stream a OneIP output plays from a session description. As
Remote::play_v2ip_sdp.
Sourcepub fn set_v2ip_sdp_screen(
&self,
device: DeviceUid,
screen: u8,
) -> Result<(), ControlError>
pub fn set_v2ip_sdp_screen( &self, device: DeviceUid, screen: u8, ) -> Result<(), ControlError>
Sets what a OneIP output shows while it plays audio alone, as the wire
value. As Remote::play_v2ip_sdp.
Sourcepub fn request_v2ip_sink_sdp(
&self,
device: DeviceUid,
) -> Result<(), ControlError>
pub fn request_v2ip_sink_sdp( &self, device: DeviceUid, ) -> Result<(), ControlError>
Asks a OneIP output what it plays from a session description now,
rather than at its next report, which comes at least once a minute.
As Remote::play_v2ip_sdp.
Sourcepub fn request_v2ip_privacy(
&self,
device: DeviceUid,
) -> Result<(), ControlError>
pub fn request_v2ip_privacy( &self, device: DeviceUid, ) -> Result<(), ControlError>
Asks a OneIP source unit how its streams are encrypted now, rather than
at its next report, which comes at least once a minute and whenever
they change. Remote::v2ip_privacy reads the answer.
Refused for a device that is not a OneIP source, and for one below protocol 0x30, which predates the report.
Sourcepub fn request_osd_message(&self, device: DeviceUid) -> Result<(), ControlError>
pub fn request_osd_message(&self, device: DeviceUid) -> Result<(), ControlError>
Asks a unit for the message on its output, which
Remote::osd_message reads once the unit answers.
Refused for a device that is not a OneIP output.
Sourcepub fn show_osd_message(
&self,
device: DeviceUid,
logo: i8,
priority: OsdMessagePriority,
text: &str,
) -> Result<(), ControlError>
pub fn show_osd_message( &self, device: DeviceUid, logo: i8, priority: OsdMessagePriority, text: &str, ) -> Result<(), ControlError>
Shows a message on a unit’s output, in place of any it has.
logo is shown with it: 0 the built-in logo, -1 none, 1 to 5 a logo
slot. text is markup of at most
OSD_MESSAGE_TEXT_MAX bytes, with no
control character; empty, the logo shows alone.
The unit takes it from management, which this client announces itself
as, and holds it until it restarts. It answers with the message it
then has, which Remote::osd_message reads, flagged
REFUSED when its video processor has no
message layer. Refused here for a device that is not a OneIP output,
and for a logo, priority or text the unit would refuse.
Sourcepub fn clear_osd_message(&self, device: DeviceUid) -> Result<(), ControlError>
pub fn clear_osd_message(&self, device: DeviceUid) -> Result<(), ControlError>
Takes the message down from a unit’s output. As
Remote::show_osd_message.
Sourcepub fn request_all_v2ip_privacy(&self) -> Result<(), ControlError>
pub fn request_all_v2ip_privacy(&self) -> Result<(), ControlError>
Asks every OneIP source unit of the mesh how its streams are encrypted,
as Remote::request_v2ip_privacy asks one. A unit below protocol
0x30 ignores it.
Sourcepub fn clear_unit_status(&self, device: DeviceUid) -> Result<(), ControlError>
pub fn clear_unit_status(&self, device: DeviceUid) -> Result<(), ControlError>
Clears a unit’s current system status.
The terms of Remote::upgrade_unit_fpga apply.
Sourcepub fn upgrade_unit_fpga(
&self,
device: DeviceUid,
force: bool,
) -> Result<(), ControlError>
pub fn upgrade_unit_fpga( &self, device: DeviceUid, force: bool, ) -> Result<(), ControlError>
Upgrades a unit’s video processor to the latest image it holds, or
flashes that image again when force is set and it already runs it.
The unit takes a command only from its mesh controller or a management
application, which this client announces itself as. Nothing
acknowledges it: Remote::unit_status reads what the unit reports
next. Refused for a device that is not a OneIP unit, and for one below
protocol 0x2C, which predates the command.
Sourcepub fn set_unit_dhcp(&self, device: DeviceUid) -> Result<(), ControlError>
pub fn set_unit_dhcp(&self, device: DeviceUid) -> Result<(), ControlError>
Switches a unit to an IP configuration from DHCP.
The terms of Remote::set_unit_network apply.
Sourcepub fn set_unit_network(
&self,
device: DeviceUid,
network: UnitNetConfig,
) -> Result<(), ControlError>
pub fn set_unit_network( &self, device: DeviceUid, network: UnitNetConfig, ) -> Result<(), ControlError>
Gives a unit a static IP configuration.
The address must be one a unit can hold and the netmask a run of ones from the top; anything else is refused before it is sent.
The unit applies the change at once and reverts it unless its mesh
controller, hearing the unit report it, confirms it in time.
UnitStatus::network_pending says
whether it still waits, and
Remote::confirm_unit_network confirms it. Otherwise as
Remote::upgrade_unit_fpga.
Sourcepub fn confirm_unit_network(
&self,
device: DeviceUid,
) -> Result<(), ControlError>
pub fn confirm_unit_network( &self, device: DeviceUid, ) -> Result<(), ControlError>
Keeps a unit’s pending IP configuration, as its mesh controller does when it hears the unit at its new address.
The terms of Remote::upgrade_unit_fpga apply.
Sourcepub fn set_mesh_time_zone(
&self,
zone: &str,
rule: &str,
) -> Result<(), ControlError>
pub fn set_mesh_time_zone( &self, zone: &str, rule: &str, ) -> Result<(), ControlError>
Sets the time zone of every device that hears it.
zone is an IANA name such as Europe/Amsterdam and rule the POSIX
TZ rule the devices keep time by, such as CET-1CEST,M3.5.0,M10.5.0/3.
A device applies the rule and shows the name.
Neither may be empty, hold a NUL, or be longer than its field on the
wire leaves room for; Remote::clear_mesh_time_zone sends both empty.
The mesh controller takes it too, and announces it from then on with every periodic broadcast. A device takes it only from a management application or the controller, and this client announces itself as a management application.
Sourcepub fn clear_mesh_time_zone(&self) -> Result<(), ControlError>
pub fn clear_mesh_time_zone(&self) -> Result<(), ControlError>
Clears the time zone of every device that hears it, which then keeps
UTC. Sent, received and announced as Remote::set_mesh_time_zone
with an empty name and rule.
Sourcepub fn set_mesh_time(&self, time: SystemTime) -> Result<(), ControlError>
pub fn set_mesh_time(&self, time: SystemTime) -> Result<(), ControlError>
Sets the clock of every device that hears it to time.
A device keeps its own clock where that is within 2s of time. It takes
the time only from a management application or the controller; see
Remote::set_mesh_time_zone. A time before 1970 or past what 32 bits
of seconds hold, in 2106, is refused.
Sourcepub fn send_monitoring_pulse(&self) -> Result<(), ControlError>
pub fn send_monitoring_pulse(&self) -> Result<(), ControlError>
Tells every unit to check its update server for new firmware now.
Sourcepub fn set_v2ip_auto_scaling(
&self,
device: DeviceUid,
enabled: bool,
) -> Result<(), ControlError>
pub fn set_v2ip_auto_scaling( &self, device: DeviceUid, enabled: bool, ) -> Result<(), ControlError>
Turns a OneIP sink’s automatic scaling on or off.
Refused for a unit below protocol 0x2F: released firmware drops a scaling write from management.
Automatic scaling and a configured output mode are separate reasons for
a sink to scale, and this moves only the first: a sink with a mode
configured goes on scaling to it with automatic scaling off. Turning
both off is this call plus Remote::clear_v2ip_output_mode.
Nothing acknowledges the frame. Read the sink back through
Remote::v2ip_details to learn what it did, and treat the block as
meaningful only where crate::DeviceInfo::config_initialised is set.
Read any route you still need before writing. The sink rebuilds
and rebroadcasts its subscription in response, and that report can
arrive empty for up to a minute; crate::DeviceV2ipSink says when
and why.
Sourcepub fn set_v2ip_output_mode(
&self,
device: DeviceUid,
mode: V2ipOutputMode,
) -> Result<(), ControlError>
pub fn set_v2ip_output_mode( &self, device: DeviceUid, mode: V2ipOutputMode, ) -> Result<(), ControlError>
Sets the output format a OneIP sink scales to.
Refused for a unit below protocol 0x2F: released firmware drops a scaling write from management.
The mode is checked here and nothing is sent if it fails, because every value a sink refuses it refuses in silence. Passing that check is not a guarantee: the sink also weighs the format against the display’s EDID and against what its own output stage can produce.
Turn automatic scaling off first if it is on. A sink refuses a mode whose format the attached display does not list while it is scaling automatically, and refuses it silently. Setting a mode and then turning automatic scaling back on is the order that survives, because the mode is checked while automatic scaling is still off.
Configuring a mode is itself a reason to scale, so a sink with one scales whether or not automatic scaling is on.
Pass a descriptor and a refresh rate that agree. A sink stores both
halves and, with its match-source setting on as it ships, reports back
the descriptor matching the refresh it holds: a 60Hz descriptor written
with a refresh of 50 reads back as that descriptor’s 50Hz sibling, once,
and stays there. A sink with match-source off reports the descriptor it
was given. Either way a pair that agrees reads back unchanged, and the
format driven is the same - so this costs a caller nothing except a
descriptor it did not write. That substitution shows up on the sink’s
next report rather than immediately, because
crate::V2ipScalingSettings holds what was written until then.
A mode read from the sink’s own web interface is not interchangeable
with this pair. That interface reports the descriptor’s 60Hz sibling and
carries the refresh in a field of its own, so writing back what it shows
as the mode, on its own, changes the setting rather than restoring it.
Read any route you still need before writing. The sink rebuilds
and rebroadcasts its subscription in response, and that report can
arrive empty for up to a minute; crate::DeviceV2ipSink says when
and why.
Sourcepub fn clear_v2ip_output_mode(
&self,
device: DeviceUid,
) -> Result<(), ControlError>
pub fn clear_v2ip_output_mode( &self, device: DeviceUid, ) -> Result<(), ControlError>
Clears the output format a OneIP sink is configured to scale to.
Refused for a unit below protocol 0x2F: released firmware drops a scaling write from management.
The sink stops scaling for that reason and keeps its automatic scaling
setting, so a sink scaling for both reasons goes on scaling until
Remote::set_v2ip_auto_scaling turns the other one off.
This is the only way to express “no mode configured”, and it is what a
caller restoring a sink that had none has to send: a sink reports no
mode by leaving the mode’s valid bit clear, which is not something a
write can say.
Read any route you still need before writing. The sink rebuilds
and rebroadcasts its subscription in response, and that report can
arrive empty for up to a minute; crate::DeviceV2ipSink says when
and why.
Sourcepub fn set_v2ip_device_setting(
&self,
device: DeviceUid,
setting: V2ipDeviceSetting,
enabled: bool,
) -> Result<(), ControlError>
pub fn set_v2ip_device_setting( &self, device: DeviceUid, setting: V2ipDeviceSetting, enabled: bool, ) -> Result<(), ControlError>
Switches on/off settings of a OneIP device, all to the same value.
setting names one or more of V2ipDeviceSetting::SWITCHES, and
each must be one the device has reported: a device ignores a setting it
does not have, so a write for one would read back as applied here and
change nothing there.
Nothing acknowledges the frame. The device answers by reporting its
settings, and until then Remote::v2ip_device_settings reads back
what was written.
Sourcepub fn set_v2ip_ir_profile(
&self,
device: DeviceUid,
profile: i8,
) -> Result<(), ControlError>
pub fn set_v2ip_ir_profile( &self, device: DeviceUid, profile: i8, ) -> Result<(), ControlError>
Sets the infrared profile of a OneIP device’s global infrared port.
profile is below V2IP_IR_PROFILE_MAX, and is checked here because
a device ignores one out of range. The terms of
Remote::set_v2ip_device_setting apply.
Sourcepub fn set_v2ip_sink_ir_profile(
&self,
device: DeviceUid,
profile: i8,
) -> Result<(), ControlError>
pub fn set_v2ip_sink_ir_profile( &self, device: DeviceUid, profile: i8, ) -> Result<(), ControlError>
Sets the infrared profile of a OneIP device’s output infrared port.
V2IP_IR_PROFILE_NOT_SET makes the port follow the global one.
Otherwise as Remote::set_v2ip_ir_profile.
Sourcepub fn set_v2ip_auto_power_save(
&self,
device: DeviceUid,
minutes: u16,
) -> Result<(), ControlError>
pub fn set_v2ip_auto_power_save( &self, device: DeviceUid, minutes: u16, ) -> Result<(), ControlError>
Sets how many idle minutes a OneIP device waits before it powers down by
itself, 0 for never. The terms of Remote::set_v2ip_device_setting
apply.
Sourcepub fn set_v2ip_power_save_schedule(
&self,
device: DeviceUid,
schedule: V2ipPowerSaveSchedule,
) -> Result<(), ControlError>
pub fn set_v2ip_power_save_schedule( &self, device: DeviceUid, schedule: V2ipPowerSaveSchedule, ) -> Result<(), ControlError>
Sets a OneIP device’s daily power save windows.
Every time is below V2IP_MINUTES_PER_DAY,
and is checked here.
The windows are kept in the device’s own time zone. The terms of
Remote::set_v2ip_device_setting apply.
Sourcepub fn set_v2ip_power_save_level(
&self,
device: DeviceUid,
level: V2ipPowerSaveLevel,
) -> Result<(), ControlError>
pub fn set_v2ip_power_save_level( &self, device: DeviceUid, level: V2ipPowerSaveLevel, ) -> Result<(), ControlError>
Sets the level a OneIP device powers down to in power save. A level the
unit does not offer is one its UnitStatus
reports without SUPPORTED. It also
switches POWER_SAVE_DISABLED
off. The terms of Remote::set_v2ip_device_setting apply.
Sourcepub fn set_v2ip_ptp_messages(
&self,
device: DeviceUid,
which: V2ipDeviceSetting,
messages: V2ipPtpMessages,
) -> Result<(), ControlError>
pub fn set_v2ip_ptp_messages( &self, device: DeviceUid, which: V2ipDeviceSetting, messages: V2ipPtpMessages, ) -> Result<(), ControlError>
Sets how a OneIP device paces its PTP messages, its SAP timings, its
streams’ TTL and its output’s rotation: the values of messages behind
the bits of which, each one of
SETTINGS_BLOCK. A DSCP above
V2IP_DSCP_MAX, a stream TTL of 0 and a
rotation that is not 0 or a multiple of the step the device reports
are refused. The terms of Remote::set_v2ip_device_setting apply.
Sourcepub fn set_v2ip_downmix(
&self,
device: DeviceUid,
downmix: V2ipDownmix,
) -> Result<(), ControlError>
pub fn set_v2ip_downmix( &self, device: DeviceUid, downmix: V2ipDownmix, ) -> Result<(), ControlError>
Sets how a OneIP device’s output mixes 5.1 and 7.1 PCM down to stereo:
the mode, level and LFE percent of downmix, which the device applies
together. Its state and channels are the device’s to report, and are
not sent.
Refused before anything is sent for a mode, level or LFE percent out of range, and unless the device reports a downmix, which one whose output cannot mix down never does. The new downmix is cached once the frame is sent, and the device’s next report replaces it.
Sourcepub fn set_v2ip_ptp_mode(
&self,
device: DeviceUid,
mode: V2ipPtpMode,
) -> Result<(), ControlError>
pub fn set_v2ip_ptp_mode( &self, device: DeviceUid, mode: V2ipPtpMode, ) -> Result<(), ControlError>
Sets the PTP mode a OneIP device runs. The terms of
Remote::set_v2ip_device_setting apply.
Sourcepub fn set_v2ip_ptp_domain(
&self,
device: DeviceUid,
domain: u8,
) -> Result<(), ControlError>
pub fn set_v2ip_ptp_domain( &self, device: DeviceUid, domain: u8, ) -> Result<(), ControlError>
Sets the PTP domain a OneIP device runs in, at most
V2IP_PTP_DOMAIN_MAX. The terms of
Remote::set_v2ip_device_setting apply.
Sourcepub fn set_v2ip_ptp_priority1(
&self,
device: DeviceUid,
priority1: u8,
) -> Result<(), ControlError>
pub fn set_v2ip_ptp_priority1( &self, device: DeviceUid, priority1: u8, ) -> Result<(), ControlError>
Sets the priority1 a OneIP device announces as a PTP grandmaster, lower
winning. The terms of Remote::set_v2ip_device_setting apply.
Sourcepub fn set_all_v2ip_device_settings(
&self,
settings: V2ipDeviceSettings,
) -> Result<(), ControlError>
pub fn set_all_v2ip_device_settings( &self, settings: V2ipDeviceSettings, ) -> Result<(), ControlError>
Changes settings on every OneIP device of the mesh with one frame.
settings carries the settings behind their bits in
valid, as a device reports them. Each
device applies those it has and ignores the rest, and none that
predates the frame applies any. A setting only a device reports about
itself, a profile, PTP mode, PTP domain, power save level or PTP DSCP
out of range, a stream TTL of 0, a rotation above
V2IP_SINK_ROTATION_MAX and a
schedule time that is not a time of day are refused here, since every
device would ignore them. Each device takes a rotation only by its own
step.
Nothing is cached: each device that applies a change reports its
settings, and Remote::v2ip_device_settings reads that.
Sourcepub fn set_v2ip_vlan(
&self,
device: DeviceUid,
vlan: V2ipVlan,
) -> Result<(), ControlError>
pub fn set_v2ip_vlan( &self, device: DeviceUid, vlan: V2ipVlan, ) -> Result<(), ControlError>
Changes a OneIP device’s VLAN configuration.
Writes the VLAN ids, the pinned uplink and the
TRUNK flag of vlan; its other flags and the
fields only the device reports are not sent. Refused before anything is
sent unless the device announces DeviceFeature::VLAN and has
reported its configuration, every id is at most
V2IP_VLAN_ID_MAX, and the uplink is
detected or names a port the device has.
The device applies the change at once and reverts it unless the mesh
controller, hearing the device report it, confirms it. Nothing is
cached here: Remote::v2ip_vlan reads what the device reports, and
V2ipVlan::is_pending whether it is still to be confirmed.
Sourcepub fn request_v2ip_testcard(
&self,
device: DeviceUid,
) -> Result<(), ControlError>
pub fn request_v2ip_testcard( &self, device: DeviceUid, ) -> Result<(), ControlError>
Asks a OneIP sink for its test card, which it reports straight back;
Remote::v2ip_testcard reads it.
Refused unless the sink’s video processor has reported
SINK_TEST_PATTERN. A sink with
that feature but without the module that draws the test card does not
answer.
Sourcepub fn set_v2ip_test_pattern(
&self,
device: DeviceUid,
pattern: V2ipTestPattern,
colour: u32,
) -> Result<(), ControlError>
pub fn set_v2ip_test_pattern( &self, device: DeviceUid, pattern: V2ipTestPattern, colour: u32, ) -> Result<(), ControlError>
Shows a test pattern on a OneIP sink’s output, or none for
V2ipTestPattern::OFF. colour is 0xRRGGBB, used by
V2ipTestPattern::FLAT.
A pattern runs until it is turned off, and holds the output on while it
does. The sink reports its test card in answer. Refused as
Remote::request_v2ip_testcard is, and for a pattern this library
does not name or a colour above 0xFFFFFF.
Sourcepub fn set_v2ip_test_tone(
&self,
device: DeviceUid,
tone: V2ipTestTone,
) -> Result<(), ControlError>
pub fn set_v2ip_test_tone( &self, device: DeviceUid, tone: V2ipTestTone, ) -> Result<(), ControlError>
Plays a test tone on a OneIP sink’s output.
Every value is checked here, as the sink ignores a tone that is not
V2ipTestTone::is_valid; V2ipToneMode::OFF stops it whatever the
rest holds, and the sink keeps those values as its last ones. Otherwise
as Remote::set_v2ip_test_pattern.
Sourcepub fn set_v2ip_test_sync(
&self,
device: DeviceUid,
sync: V2ipTestSync,
) -> Result<(), ControlError>
pub fn set_v2ip_test_sync( &self, device: DeviceUid, sync: V2ipTestSync, ) -> Result<(), ControlError>
Sets a OneIP sink’s lip-sync flash.
Checked here as V2ipTestSync::is_valid, since the sink ignores
settings that are not. Otherwise as Remote::set_v2ip_test_pattern.
Sourcepub fn preview_video_wall(
&self,
sink: DeviceUid,
window: VideoWallWindow,
) -> Result<(), ControlError>
pub fn preview_video_wall( &self, sink: DeviceUid, window: VideoWallWindow, ) -> Result<(), ControlError>
Shows a window on a sink’s video wall without persisting it.
The window survives until the sink is told otherwise or restarts.
Remote::revert_video_wall puts back whatever was stored.
Pass crate::VIDEO_WALL_CLEARED to show the whole frame again.
Sourcepub fn store_video_wall(
&self,
sink: DeviceUid,
window: VideoWallWindow,
) -> Result<(), ControlError>
pub fn store_video_wall( &self, sink: DeviceUid, window: VideoWallWindow, ) -> Result<(), ControlError>
Persists a window as a sink’s video wall.
The geometry is checked here, before anything is sent, because the sink is not guaranteed to check it. A sink running a video-wall module older than 2026083100 writes the window to its configuration before asking its video processor to apply it, and the processor’s refusal does not undo that write - so an out-of-spec window survives a reboot and is re-offered on every stream restart until something else replaces it. A power cycle does not clear it.
Nothing acknowledges this frame either way, so an Ok says only that
it was sent. Read the sink’s state back to learn what it did.
Pass crate::VIDEO_WALL_CLEARED to store “show the whole frame”.
Sourcepub fn revert_video_wall(&self, sink: DeviceUid) -> Result<(), ControlError>
pub fn revert_video_wall(&self, sink: DeviceUid) -> Result<(), ControlError>
Restores the window a sink has stored, discarding a preview.
Carries no window of its own: the sink already holds the one this puts back.
Sourcepub fn set_multiviewer_view_mode(
&self,
device: DeviceUid,
mode: MultiviewerViewMode,
) -> Result<(), ControlError>
pub fn set_multiviewer_view_mode( &self, device: DeviceUid, mode: MultiviewerViewMode, ) -> Result<(), ControlError>
Sets the window layout.
Sourcepub fn set_multiviewer_video_source(
&self,
device: DeviceUid,
screen: u8,
source: MultiviewerSource,
) -> Result<(), ControlError>
pub fn set_multiviewer_video_source( &self, device: DeviceUid, screen: u8, source: MultiviewerSource, ) -> Result<(), ControlError>
Assigns a source to one window, counting windows from zero.
A window index the multiviewer is not currently showing is refused rather than sent: firmware accepts an index one past the last window and writes through the end of the array it indexes, so the frame that would carry it is the one frame this library must never put on the wire. The bound comes from the layout in the multiviewer’s last status report, so a multiviewer that has reported none can only be given window zero, which every layout has.
Sourcepub fn set_multiviewer_audio_source(
&self,
device: DeviceUid,
source: MultiviewerSource,
) -> Result<(), ControlError>
pub fn set_multiviewer_audio_source( &self, device: DeviceUid, source: MultiviewerSource, ) -> Result<(), ControlError>
Selects which window’s audio is output.
Sourcepub fn set_multiviewer_audio_volume(
&self,
device: DeviceUid,
volume: u8,
muted: bool,
) -> Result<(), ControlError>
pub fn set_multiviewer_audio_volume( &self, device: DeviceUid, volume: u8, muted: bool, ) -> Result<(), ControlError>
Sets the output volume, as a percentage, and the mute state.
A volume above 100 is refused rather than sent. What a multiviewer does with one depends on its module version: from 2026083100 it drops the whole frame, and before that it dropped the volume alone and still acted on the mute beside it. Neither is what the caller asked for, and neither is reported back.
Sourcepub fn set_multiviewer_edid_template(
&self,
device: DeviceUid,
template: MultiviewerEdidTemplate,
) -> Result<(), ControlError>
pub fn set_multiviewer_edid_template( &self, device: DeviceUid, template: MultiviewerEdidTemplate, ) -> Result<(), ControlError>
Sets the EDID template presented to the sources.
Sourcepub fn set_multiviewer_remote_control(
&self,
device: DeviceUid,
source: MultiviewerSource,
) -> Result<(), ControlError>
pub fn set_multiviewer_remote_control( &self, device: DeviceUid, source: MultiviewerSource, ) -> Result<(), ControlError>
Selects which window receives remote-control passthrough.
Sourcepub fn set_multiviewer_pip_size(
&self,
device: DeviceUid,
size: MultiviewerPipSize,
) -> Result<(), ControlError>
pub fn set_multiviewer_pip_size( &self, device: DeviceUid, size: MultiviewerPipSize, ) -> Result<(), ControlError>
Sets how large the picture-in-picture window is.
Sourcepub fn set_multiviewer_pip_position(
&self,
device: DeviceUid,
position: MultiviewerPipPosition,
) -> Result<(), ControlError>
pub fn set_multiviewer_pip_position( &self, device: DeviceUid, position: MultiviewerPipPosition, ) -> Result<(), ControlError>
Sets which corner the picture-in-picture window sits in.
Sourcepub fn set_multiviewer_aspect_ratio(
&self,
device: DeviceUid,
aspect: MultiviewerAspectRatio,
) -> Result<(), ControlError>
pub fn set_multiviewer_aspect_ratio( &self, device: DeviceUid, aspect: MultiviewerAspectRatio, ) -> Result<(), ControlError>
Sets the aspect ratio the windows are scaled to.
Sourcepub fn set_multiviewer_auto_switch(
&self,
device: DeviceUid,
enable: bool,
) -> Result<(), ControlError>
pub fn set_multiviewer_auto_switch( &self, device: DeviceUid, enable: bool, ) -> Result<(), ControlError>
Enables or disables switching windows on its own.
Sourcepub fn set_multiviewer_output_mode(
&self,
device: DeviceUid,
mode: MultiviewerOutputMode,
) -> Result<(), ControlError>
pub fn set_multiviewer_output_mode( &self, device: DeviceUid, mode: MultiviewerOutputMode, ) -> Result<(), ControlError>
Sets the output resolution and refresh rate.
Sourcepub fn set_multiviewer_output_itc(
&self,
device: DeviceUid,
mode: MultiviewerItcMode,
) -> Result<(), ControlError>
pub fn set_multiviewer_output_itc( &self, device: DeviceUid, mode: MultiviewerItcMode, ) -> Result<(), ControlError>
Sets the IT-content flag on the output.
Sourcepub fn set_multiviewer_hdcp_mode(
&self,
device: DeviceUid,
mode: MultiviewerHdcpMode,
) -> Result<(), ControlError>
pub fn set_multiviewer_hdcp_mode( &self, device: DeviceUid, mode: MultiviewerHdcpMode, ) -> Result<(), ControlError>
Sets the HDCP version negotiated on the output.
Sourcepub fn set_multiviewer_input_source(
&self,
device: DeviceUid,
input: u8,
source: DeviceUid,
) -> Result<(), ControlError>
pub fn set_multiviewer_input_source( &self, device: DeviceUid, input: u8, source: DeviceUid, ) -> Result<(), ControlError>
Maps a source device onto one of the multiviewer’s inputs, counting inputs from zero.
DeviceUid::ZERO clears the mapping on a multiviewer running module
version 2026083100 or newer, and is stored as a mapping like any other
on anything older. No version checks that a mapping names a device on
the mesh.
Which of the two happened shows in mappings on a later status report,
where a cleared input reads as DeviceUid::ZERO only from that same
version. It will not be the next frame this multiviewer sends: this is
one of the two settings that schedule no status broadcast of their own,
so the answer arrives whenever something else prompts one.
Sourcepub fn multiviewer_auto_route(
&self,
device: DeviceUid,
) -> Result<(), ControlError>
pub fn multiviewer_auto_route( &self, device: DeviceUid, ) -> Result<(), ControlError>
Asks the multiviewer to route its sources itself.
Source§impl Remote
impl Remote
Sourcepub fn send_osd_sync(
&self,
content: OsdSyncContent,
) -> Result<u16, ControlError>
pub fn send_osd_sync( &self, content: OsdSyncContent, ) -> Result<u16, ControlError>
Has every unit copy content, and keeps it in place, returning the
sync’s number.
Units take a sync from the mesh controller or a management
application, which this client announces itself as. Each unit
fetches the images from a server this client runs, then asks for the
settings, which this client answers until the content is replaced or
Remote::clear_osd_sync. Meanwhile it announces itself as the
mesh’s overlay sync manager, so a unit waking from power save takes
this content too, rather than the controller’s. The controller can
still send its own over it; the last sync a unit took is what it
shows. Each unit’s
Remote::osd_sync_report says how it went.
Refused for content copying nothing, with more than
OSD_SYNC_RECORDS_MAX settings, a caption font over
OSD_SYNC_FONT_MAX or text over OSD_SYNC_TEXT_MAX bytes, a logo
other than -1 to 4, or an image that is not a PNG within
OSD_SYNC_IMAGE_MAX bytes and OSD_SYNC_IMAGE_WIDTH_MAX by
OSD_SYNC_IMAGE_HEIGHT_MAX pixels, shown at over
OSD_SYNC_PERCENT_MAX percent. Refused content leaves the held sync
as it was; content that fails to go out leaves none held.
Sourcepub fn resend_osd_sync(&self, device: DeviceUid) -> Result<u16, ControlError>
pub fn resend_osd_sync(&self, device: DeviceUid) -> Result<u16, ControlError>
Has one unit copy the sync this client holds again, returning the
new sync’s number. As Remote::send_osd_sync.
Refused while no sync is held, and for a unit that does not announce
OSD_SYNC, as one that does not take
overlay syncs.
Sourcepub fn clear_osd_sync(&self)
pub fn clear_osd_sync(&self)
Stops holding the sync this client sent, and hands the overlay sync manager’s part back to the controller.
Units keep what they took. One still taking it fails, as its requests go unanswered.
Source§impl Remote
impl Remote
Sourcepub fn new(config: Config, handler: Arc<dyn EventHandler>) -> Result<Self>
pub fn new(config: Config, handler: Arc<dyn EventHandler>) -> Result<Self>
Builds a client, loading or generating its identifier.
Nothing is sent and no socket is opened until Remote::start.
Examples found in repository?
59fn main() -> std::io::Result<()> {
60 let mut config = Config::default();
61 config.name = Some("discover".to_owned());
62 if let Some(address) = std::env::args().nth(1) {
63 config.local_ip = Some(address.parse().map_err(|_| {
64 std::io::Error::new(std::io::ErrorKind::InvalidInput, "not an IPv4 address")
65 })?);
66 }
67
68 let remote = Arc::new(Remote::new(config, Arc::new(Printer))?);
69 let _ = CLIENT.set(Arc::clone(&remote));
70 remote.start()?;
71
72 if let Some(target) = remote.target() {
73 println!("listening, sending to {target}. Ctrl-C to stop.");
74 }
75
76 let running = Arc::new(AtomicBool::new(true));
77 let stop = Arc::clone(&running);
78 ctrl_c(move || stop.store(false, Ordering::Relaxed));
79 while running.load(Ordering::Relaxed) {
80 std::thread::sleep(Duration::from_millis(200));
81 }
82
83 let devices = remote.devices();
84 println!("\n{} device(s):", devices.len());
85 for device in devices {
86 Printer.on_device_update(device);
87 }
88
89 remote.close();
90 Ok(())
91}Sourcepub fn start(&self) -> Result<()>
pub fn start(&self) -> Result<()>
Opens the socket, announces this client and begins discovery.
Returns once the receive thread is running; discovery continues in the background.
Examples found in repository?
59fn main() -> std::io::Result<()> {
60 let mut config = Config::default();
61 config.name = Some("discover".to_owned());
62 if let Some(address) = std::env::args().nth(1) {
63 config.local_ip = Some(address.parse().map_err(|_| {
64 std::io::Error::new(std::io::ErrorKind::InvalidInput, "not an IPv4 address")
65 })?);
66 }
67
68 let remote = Arc::new(Remote::new(config, Arc::new(Printer))?);
69 let _ = CLIENT.set(Arc::clone(&remote));
70 remote.start()?;
71
72 if let Some(target) = remote.target() {
73 println!("listening, sending to {target}. Ctrl-C to stop.");
74 }
75
76 let running = Arc::new(AtomicBool::new(true));
77 let stop = Arc::clone(&running);
78 ctrl_c(move || stop.store(false, Ordering::Relaxed));
79 while running.load(Ordering::Relaxed) {
80 std::thread::sleep(Duration::from_millis(200));
81 }
82
83 let devices = remote.devices();
84 println!("\n{} device(s):", devices.len());
85 for device in devices {
86 Printer.on_device_update(device);
87 }
88
89 remote.close();
90 Ok(())
91}Sourcepub fn close(&self)
pub fn close(&self)
Stops discovery, closes the socket and waits for the threads to finish.
Calling it more than once, or before Remote::start, does nothing.
Examples found in repository?
59fn main() -> std::io::Result<()> {
60 let mut config = Config::default();
61 config.name = Some("discover".to_owned());
62 if let Some(address) = std::env::args().nth(1) {
63 config.local_ip = Some(address.parse().map_err(|_| {
64 std::io::Error::new(std::io::ErrorKind::InvalidInput, "not an IPv4 address")
65 })?);
66 }
67
68 let remote = Arc::new(Remote::new(config, Arc::new(Printer))?);
69 let _ = CLIENT.set(Arc::clone(&remote));
70 remote.start()?;
71
72 if let Some(target) = remote.target() {
73 println!("listening, sending to {target}. Ctrl-C to stop.");
74 }
75
76 let running = Arc::new(AtomicBool::new(true));
77 let stop = Arc::clone(&running);
78 ctrl_c(move || stop.store(false, Ordering::Relaxed));
79 while running.load(Ordering::Relaxed) {
80 std::thread::sleep(Duration::from_millis(200));
81 }
82
83 let devices = remote.devices();
84 println!("\n{} device(s):", devices.len());
85 for device in devices {
86 Printer.on_device_update(device);
87 }
88
89 remote.close();
90 Ok(())
91}Sourcepub fn target(&self) -> Option<SocketAddrV4>
pub fn target(&self) -> Option<SocketAddrV4>
The address frames are being sent to, once started.
Examples found in repository?
59fn main() -> std::io::Result<()> {
60 let mut config = Config::default();
61 config.name = Some("discover".to_owned());
62 if let Some(address) = std::env::args().nth(1) {
63 config.local_ip = Some(address.parse().map_err(|_| {
64 std::io::Error::new(std::io::ErrorKind::InvalidInput, "not an IPv4 address")
65 })?);
66 }
67
68 let remote = Arc::new(Remote::new(config, Arc::new(Printer))?);
69 let _ = CLIENT.set(Arc::clone(&remote));
70 remote.start()?;
71
72 if let Some(target) = remote.target() {
73 println!("listening, sending to {target}. Ctrl-C to stop.");
74 }
75
76 let running = Arc::new(AtomicBool::new(true));
77 let stop = Arc::clone(&running);
78 ctrl_c(move || stop.store(false, Ordering::Relaxed));
79 while running.load(Ordering::Relaxed) {
80 std::thread::sleep(Duration::from_millis(200));
81 }
82
83 let devices = remote.devices();
84 println!("\n{} device(s):", devices.len());
85 for device in devices {
86 Printer.on_device_update(device);
87 }
88
89 remote.close();
90 Ok(())
91}Sourcepub fn devices(&self) -> Vec<DeviceUid>
pub fn devices(&self) -> Vec<DeviceUid>
Every device heard from, in no particular order.
Examples found in repository?
59fn main() -> std::io::Result<()> {
60 let mut config = Config::default();
61 config.name = Some("discover".to_owned());
62 if let Some(address) = std::env::args().nth(1) {
63 config.local_ip = Some(address.parse().map_err(|_| {
64 std::io::Error::new(std::io::ErrorKind::InvalidInput, "not an IPv4 address")
65 })?);
66 }
67
68 let remote = Arc::new(Remote::new(config, Arc::new(Printer))?);
69 let _ = CLIENT.set(Arc::clone(&remote));
70 remote.start()?;
71
72 if let Some(target) = remote.target() {
73 println!("listening, sending to {target}. Ctrl-C to stop.");
74 }
75
76 let running = Arc::new(AtomicBool::new(true));
77 let stop = Arc::clone(&running);
78 ctrl_c(move || stop.store(false, Ordering::Relaxed));
79 while running.load(Ordering::Relaxed) {
80 std::thread::sleep(Duration::from_millis(200));
81 }
82
83 let devices = remote.devices();
84 println!("\n{} device(s):", devices.len());
85 for device in devices {
86 Printer.on_device_update(device);
87 }
88
89 remote.close();
90 Ok(())
91}Sourcepub fn device(&self, uid: DeviceUid) -> Option<DeviceInfo>
pub fn device(&self, uid: DeviceUid) -> Option<DeviceInfo>
A snapshot of one device.
Examples found in repository?
28 fn on_device_update(&self, device: DeviceUid) {
29 let Some(remote) = CLIENT.get() else { return };
30 let Some(info) = remote.device(device) else {
31 return;
32 };
33 println!(
34 " {device} {:<16} {:<12} {:<16} protocol {:#04x}, {} bays{}",
35 info.model,
36 info.serial,
37 info.name,
38 info.supported_protocol,
39 info.bays.len(),
40 if info.online { "" } else { " (offline)" },
41 );
42 }Sourcepub fn device_by_serial(&self, serial: &str) -> Option<DeviceUid>
pub fn device_by_serial(&self, serial: &str) -> Option<DeviceUid>
The device with the given serial number.
Sourcepub fn resolve_device(&self, name: &str) -> Option<DeviceUid>
pub fn resolve_device(&self, name: &str) -> Option<DeviceUid>
Resolves a device from its dotted-hex identifier, falling back to a serial-number match.
Sourcepub fn bay(&self, uid: BayUid) -> Option<BayInfo>
pub fn bay(&self, uid: BayUid) -> Option<BayInfo>
A snapshot of one bay.
Examples found in repository?
44 fn on_bay_update(&self, bay: BayUid) {
45 let Some(remote) = CLIENT.get() else { return };
46 let Some(info) = remote.bay(bay) else { return };
47 println!(
48 " bay {} {:<16} {}",
49 bay.port,
50 info.user_name,
51 match info.signal_detected {
52 Some(true) => "signal",
53 _ => "no signal",
54 },
55 );
56 }Sourcepub fn bay_by_name(&self, device: DeviceUid, port_name: &str) -> Option<BayUid>
pub fn bay_by_name(&self, device: DeviceUid, port_name: &str) -> Option<BayUid>
The bay on device with the given port name, such as Output 1.
Sourcepub fn bay_by_stream_ip(&self, ip: Ipv4Addr, audio: bool) -> Option<BayUid>
pub fn bay_by_stream_ip(&self, ip: Ipv4Addr, audio: bool) -> Option<BayUid>
The source bay advertising the given multicast group, for the video or the audio stream.
Sourcepub fn v2ip_sources(&self, uid: DeviceUid) -> Option<Vec<V2ipStreamSources>>
pub fn v2ip_sources(&self, uid: DeviceUid) -> Option<Vec<V2ipStreamSources>>
The OneIP streams a device advertises.
Sourcepub fn v2ip_details(&self, uid: DeviceUid) -> Option<DeviceV2ipDetails>
pub fn v2ip_details(&self, uid: DeviceUid) -> Option<DeviceV2ipDetails>
A OneIP device’s own encoder configuration.
Sourcepub fn v2ip_sink(&self, uid: DeviceUid) -> Option<DeviceV2ipSink>
pub fn v2ip_sink(&self, uid: DeviceUid) -> Option<DeviceV2ipSink>
The streams a OneIP sink is subscribed to.
Sourcepub fn v2ip_stats(&self, uid: DeviceUid) -> Option<V2ipDeviceStats>
pub fn v2ip_stats(&self, uid: DeviceUid) -> Option<V2ipDeviceStats>
Transport statistics a OneIP device reports.
Sourcepub fn v2ip_features(&self, uid: DeviceUid) -> Option<V2ipFpgaFeature>
pub fn v2ip_features(&self, uid: DeviceUid) -> Option<V2ipFpgaFeature>
What a OneIP device’s video processor supports.
None until the device has reported a non-empty mask about itself.
A device reports nothing at all while its processor has yet to answer,
and an older processor answers with none of the optional commands, so
“no features” and “not yet known” are the same bytes on the wire and
both read as None here. A mask that has arrived only gains bits.
Sourcepub fn v2ip_device_settings(&self, uid: DeviceUid) -> Option<V2ipDeviceSettings>
pub fn v2ip_device_settings(&self, uid: DeviceUid) -> Option<V2ipDeviceSettings>
A OneIP device’s settings, None until it has reported any.
A device reports only the settings it has, so one missing from
V2ipDeviceSettings::valid once the rest have arrived is one the
device does not have.
Sourcepub fn v2ip_downmix(&self, uid: DeviceUid) -> Option<V2ipDownmix>
pub fn v2ip_downmix(&self, uid: DeviceUid) -> Option<V2ipDownmix>
How a OneIP device’s output mixes down to stereo, as it last reported,
None while it reports no downmix: until its video processor has
answered for it, and always for one whose output cannot mix down.
Sourcepub fn v2ip_vlan(&self, uid: DeviceUid) -> Option<V2ipVlan>
pub fn v2ip_vlan(&self, uid: DeviceUid) -> Option<V2ipVlan>
The VLAN configuration a OneIP device last reported about itself,
None until it has reported one.
Sourcepub fn v2ip_sink_sdp(&self, uid: DeviceUid) -> Option<V2ipSinkSdp>
pub fn v2ip_sink_sdp(&self, uid: DeviceUid) -> Option<V2ipSinkSdp>
What a OneIP output last reported playing from a session description,
None until it has reported.
Sourcepub fn v2ip_privacy(&self, uid: DeviceUid) -> Option<V2ipPrivacy>
pub fn v2ip_privacy(&self, uid: DeviceUid) -> Option<V2ipPrivacy>
How a OneIP source unit’s streams are encrypted, as it last reported
it, None until it has reported.
Sourcepub fn osd_sync(&self, uid: DeviceUid) -> Option<OsdSync>
pub fn osd_sync(&self, uid: DeviceUid) -> Option<OsdSync>
The overlay sync a management unit last sent, None until it has
sent one.
Sourcepub fn osd_sync_report(&self, uid: DeviceUid) -> Option<OsdSyncReport>
pub fn osd_sync_report(&self, uid: DeviceUid) -> Option<OsdSyncReport>
How a unit last reported getting on with an overlay sync, None until
it has reported. Match it to the sync by seq and the sync’s source.
Sourcepub fn osd_message(&self, uid: DeviceUid) -> Option<OsdMessage>
pub fn osd_message(&self, uid: DeviceUid) -> Option<OsdMessage>
The message on a unit’s output, as the unit last reported it to this
client, None until it has. A unit reports it only when asked, or
when this client writes it.
Sourcepub fn unit_status(&self, uid: DeviceUid) -> Option<UnitStatus>
pub fn unit_status(&self, uid: DeviceUid) -> Option<UnitStatus>
The health and IP configuration a unit last reported, None until it
has reported them.
Sourcepub fn v2ip_ptp(&self, uid: DeviceUid) -> Option<V2ipPtpState>
pub fn v2ip_ptp(&self, uid: DeviceUid) -> Option<V2ipPtpState>
The PTP state a OneIP device last reported about itself, None until
it has reported one, and while it has no PTP to report: none on its
video processor, or in power save.
Sourcepub fn v2ip_testcard(&self, uid: DeviceUid) -> Option<V2ipTestcard>
pub fn v2ip_testcard(&self, uid: DeviceUid) -> Option<V2ipTestcard>
The test card a OneIP sink last reported, None until it has answered
Remote::request_v2ip_testcard or a change.
Sourcepub fn time_zone(&self, uid: DeviceUid) -> Option<TimeZone>
pub fn time_zone(&self, uid: DeviceUid) -> Option<TimeZone>
The time zone a device announced for its mesh, None until it has.
The mesh controller announces it with every periodic broadcast, empty when it has none.
Sourcepub fn device_clock(&self, uid: DeviceUid) -> Option<SystemTime>
pub fn device_clock(&self, uid: DeviceUid) -> Option<SystemTime>
A device’s clock as of now: the time it last announced, advanced by
how long ago that arrived. None until it has announced one.
The mesh controller announces its clock with every periodic broadcast, and only once it has been set.
Sourcepub fn v2ip_tiling(&self, uid: DeviceUid) -> Option<V2ipTilingConfig>
pub fn v2ip_tiling(&self, uid: DeviceUid) -> Option<V2ipTilingConfig>
The video-wall tiling a OneIP device is configured for.
Sourcepub fn audio_endpoints(&self, uid: DeviceUid) -> Option<AudioEndpoints>
pub fn audio_endpoints(&self, uid: DeviceUid) -> Option<AudioEndpoints>
The audio endpoint tree a device exposes.
Sourcepub fn multiviewer_status(&self, uid: DeviceUid) -> Option<MultiviewerStatus>
pub fn multiviewer_status(&self, uid: DeviceUid) -> Option<MultiviewerStatus>
The multiviewer layout a device is showing.
Sourcepub fn dolby_settings(&self, uid: DeviceUid) -> Option<AmpDolbySettings>
pub fn dolby_settings(&self, uid: DeviceUid) -> Option<AmpDolbySettings>
An amplifier’s Dolby decoder settings.
Sourcepub fn rc_settings(&self, uid: DeviceUid) -> Option<RcSettings>
pub fn rc_settings(&self, uid: DeviceUid) -> Option<RcSettings>
A device’s remote-control settings.
Sourcepub fn network_status(&self, uid: DeviceUid) -> Vec<NetworkPortStatus>
pub fn network_status(&self, uid: DeviceUid) -> Vec<NetworkPortStatus>
Every network port a device reports, in port order.
Sourcepub fn topology(&self, uid: DeviceUid) -> Vec<TopologyEntry>
pub fn topology(&self, uid: DeviceUid) -> Vec<TopologyEntry>
The mesh topology a device reports.
Sourcepub fn edid(&self, uid: DeviceUid, output: bool) -> Option<Vec<u8>>
pub fn edid(&self, uid: DeviceUid, output: bool) -> Option<Vec<u8>>
The EDID a device last reported: the display on its output, or the one it presents to the source on its input.
Filled in by a device’s answer to Remote::request_edid, and by any
answer to a peer’s request that this client happened to hear.
Sourcepub fn frames_received(&self) -> u64
pub fn frames_received(&self) -> u64
How many frames from other senders have parsed since this client started.
It separates a mesh with nothing on it from an interface nothing is on:
a client that has discovered no device but is counting frames is
hearing traffic it cannot get answers from, which on a multi-homed host
is what a wrong Config::local_ip looks like. Frames this client
sent are not counted, because the host loops its own multicast back
whichever interface was selected.
Sourcepub fn firmware(&self, uid: DeviceUid) -> Vec<(FirmwareType, FirmwareVersion)>
pub fn firmware(&self, uid: DeviceUid) -> Vec<(FirmwareType, FirmwareVersion)>
Every firmware image a device reports a version for.