Class CompanionApi
- Namespace
- AppleTvControlLibrary.Protocol
- Assembly
- AppleTvControlLibrary.dll
High level implementation of the Companion API: system info, session lifecycle, HID input, media control (volume), attention state, app listing/launching, and account listing/switching.
public sealed class CompanionApi : ICompanionProtocolListener
- Inheritance
-
CompanionApi
- Implements
- Inherited Members
Remarks
Text input is intentionally out of scope for this port (Companion-only, per the porting brief).
Constructors
CompanionApi(CompanionProtocol, HapCredentials, string, string, string, string)
Initializes a new instance of the CompanionApi class.
public CompanionApi(CompanionProtocol protocol, HapCredentials credentials, string stableIdentifier, string deviceId, string model, string name)
Parameters
protocolCompanionProtocolThe underlying Companion protocol instance.
credentialsHapCredentialsThe paired credentials, used to build the
_idsIDsystem info field.stableIdentifierstringA stable, persisted identifier for the
_systemInfo_ifield (typically six random bytes, hex-encoded, generated once at pair time and never regenerated -- see porting brief WP6 notes on_i).deviceIdstringThe device identifier reported as
_pubID.modelstringThe device model string reported in
_systemInfo.namestringThe device name string reported in
_systemInfo.
Properties
CurrentSystemStatus
Gets the most recently known system status (power state), updated by the initial
FetchAttentionState() snapshot taken during Connect() and by
subsequently pushed SystemStatus/TVSystemStatus events.
public SystemStatus CurrentSystemStatus { get; }
Property Value
DeviceId
Gets the device identifier reported as _pubID.
public string DeviceId { get; }
Property Value
IsVolumeControlSupported
Gets a value indicating whether the device currently advertises volume control support
via the _iMC event's _mcF bitmask (Volume).
When this is false, audio is managed outside Companion (e.g. HDMI-CEC)
and GetVolume()/SetVolume(double) must not be used.
public bool IsVolumeControlSupported { get; }
Property Value
Model
Gets the device model string.
public string Model { get; }
Property Value
Name
Gets the device name string.
public string Name { get; }
Property Value
Sid
Gets the combined session id established by SessionStart().
public long Sid { get; }
Property Value
StableIdentifier
Gets the stable identifier used as the _systemInfo _i field.
public string StableIdentifier { get; }
Property Value
TextFocusState
Gets the current keyboard (RTI text input) focus state, as last reported by the
_tiStarted/_tiStopped events or the _tiStart response.
public KeyboardFocusState TextFocusState { get; }
Property Value
Methods
AccountList()
Fetch the list of user accounts that can be switched to on the device, as a mapping of account identifier to display name.
[Obsolete("Use AccountListAsync instead.")]
public Dictionary<string, string> AccountList()
Returns
- Dictionary<string, string>
A mapping of account identifier to display name. Like AppList(), this is not guaranteed to be populated on every device/tvOS combination, so callers must treat an empty (or missing) result as a normal outcome rather than an error.
AccountListAsync()
Asynchronously fetches the list of accounts.
public Task<Dictionary<string, string>> AccountListAsync()
Returns
AccountListRaw()
Diagnostic-only: fetch the raw, untyped _c content of a FetchUserAccountsEvent
response, with no coercion to Dictionary<TKey, TValue> of
string/string. AccountList() silently drops any
entry whose value is not a plain string, which would hide a richer per-account payload
(e.g. a nested dict carrying a "current"/"active" flag) if the device ever sends one. This
exists to let that be checked against real hardware rather than assumed from the pyatv
source, per the brief's rule 2 (do not invent, do not infer past what the source says).
[Obsolete("Use AccountListRawAsync instead.")]
public Dictionary<object, object?> AccountListRaw()
Returns
- Dictionary<object, object>
The raw
_ccontent, or an empty dictionary if missing/malformed.
AccountListRawAsync()
Asynchronously fetches the raw account list response content.
public Task<Dictionary<object, object?>> AccountListRawAsync()
Returns
AppList()
Fetch the list of launchable apps on the device, as a mapping of bundle identifier to display name.
[Obsolete("Use AppListAsync instead.")]
public Dictionary<string, string> AppList()
Returns
- Dictionary<string, string>
A mapping of bundle identifier to display name. This is the only Companion feature with a confirmed history of returning empty on some tvOS point releases, so callers must treat an empty (or missing) result as a normal outcome rather than an error and must not hard-depend on the list being non-empty.
AppListAsync()
Asynchronously fetches the list of launchable apps.
public Task<Dictionary<string, string>> AppListAsync()
Returns
Connect()
Runs the connection bring-up sequence: system info, touch subscription, session start, TV Remote Client session start, and text input session start.
[Obsolete("Use ConnectAsync instead.")]
public void Connect()
ConnectAsync()
Asynchronously runs the connection bring-up sequence.
public Task ConnectAsync()
Returns
FetchAttentionState()
Fetch the current attention state (system status) from the device.
[Obsolete("Use FetchAttentionStateAsync instead.")]
public SystemStatus FetchAttentionState()
Returns
- SystemStatus
The current SystemStatus.
FetchAttentionStateAsync()
Asynchronously fetches the current attention state.
public Task<SystemStatus> FetchAttentionStateAsync()
Returns
GetVolume()
Gets the current volume level, in percent ([0.0-100.0]).
[Obsolete("Use GetVolumeAsync instead.")]
public double GetVolume()
Returns
GetVolumeAsync()
Asynchronously gets the current volume level.
public Task<double> GetVolumeAsync()
Returns
LaunchApp(string)
Launch an app on the device, by bundle identifier or by URL/URL scheme (for deep-linking into content rather than opening an app cold).
[Obsolete("Use LaunchAppAsync instead.")]
public void LaunchApp(string bundleIdOrUrl)
Parameters
bundleIdOrUrlstringA bundle identifier (e.g.
com.apple.TVWatchList), or a URL/URL scheme to open.
LaunchAppAsync(string)
Asynchronously launches an app on the device.
public Task LaunchAppAsync(string bundleIdOrUrl)
Parameters
bundleIdOrUrlstring
Returns
MediaControlCommand(MediaControlCommand, Dictionary<string, object?>?)
Send a media control command to the device.
[Obsolete("Use MediaControlCommandAsync instead.")]
public Dictionary<object, object?> MediaControlCommand(MediaControlCommand command, Dictionary<string, object?>? args = null)
Parameters
commandMediaControlCommandThe media control command to send.
argsDictionary<string, object>Additional command-specific arguments, if any.
Returns
- Dictionary<object, object>
The decoded response content (the message's
_cfield).
MediaControlCommandAsync(MediaControlCommand, Dictionary<string, object?>?)
Asynchronously sends a media control command.
public Task<Dictionary<object, object?>> MediaControlCommandAsync(MediaControlCommand command, Dictionary<string, object?>? args = null)
Parameters
commandMediaControlCommandargsDictionary<string, object>
Returns
SendClick(InputAction)
Send a touch click (tap on the touch surface, distinct from a directional-pad Select press). This is what pyatv's remote-widget "select" gesture actually sends when driven from a touchpad rather than a D-pad: a Select button press/release (button code 6) followed by a touch Click event in the bottom-right corner of the touch surface.
[Obsolete("Use SendClickAsync instead.")]
public void SendClick(InputAction action)
Parameters
actionInputActionThe click gesture: single tap, double tap, or press-and-hold.
SendClickAsync(InputAction)
Asynchronously sends a touch click.
public Task SendClickAsync(InputAction action)
Parameters
actionInputAction
Returns
SendHidCommand(bool, HidCommand)
Send a HID command.
[Obsolete("Use SendHidCommandAsync instead.")]
public void SendHidCommand(bool down, HidCommand command)
Parameters
downboolcommandHidCommandThe button being pressed or released.
SendHidCommandAsync(bool, HidCommand)
Asynchronously sends a HID command.
public Task SendHidCommandAsync(bool down, HidCommand command)
Parameters
downboolcommandHidCommand
Returns
SendHidEvent(int, int, TouchAction)
Send a touch event.
[Obsolete("Use SendHidEventAsync instead.")]
public void SendHidEvent(int x, int y, TouchAction mode)
Parameters
xintThe x coordinate, in the range [0, 1000].
yintThe y coordinate, in the range [0, 1000].
modeTouchActionThe touch phase.
SendHidEventAsync(int, int, TouchAction)
Asynchronously sends a touch event.
public Task SendHidEventAsync(int x, int y, TouchAction mode)
Parameters
xintyintmodeTouchAction
Returns
SessionStart()
Start a Companion session.
[Obsolete("Use SessionStartAsync instead.")]
public void SessionStart()
SessionStartAsync()
Asynchronously starts a Companion session.
public Task SessionStartAsync()
Returns
SessionStop()
Stop the current Companion session.
[Obsolete("Use SessionStopAsync instead.")]
public void SessionStop()
SessionStopAsync()
Asynchronously stops the current Companion session.
public Task SessionStopAsync()
Returns
SetVolume(double)
Sets the current volume level.
[Obsolete("Use SetVolumeAsync instead.")]
public void SetVolume(double level)
Parameters
leveldoubleThe new volume level, in percent ([0.0-100.0]).
SetVolumeAsync(double)
Asynchronously sets the current volume level.
public Task SetVolumeAsync(double level)
Parameters
leveldouble
Returns
SubscribeEvent(string)
Subscribe to updates for an event.
[Obsolete("Use SubscribeEventAsync instead.")]
public void SubscribeEvent(string eventName)
Parameters
eventNamestringThe event identifier to subscribe to.
SubscribeEventAsync(string)
Asynchronously subscribes to updates for an event.
public Task SubscribeEventAsync(string eventName)
Parameters
eventNamestring
Returns
SwitchAccount(string)
Switch the active user account on the device.
[Obsolete("Use SwitchAccountAsync instead.")]
public void SwitchAccount(string accountId)
Parameters
accountIdstringThe account identifier to switch to, as returned by AccountList().
SwitchAccountAsync(string)
Asynchronously switches the active user account.
public Task SwitchAccountAsync(string accountId)
Parameters
accountIdstring
Returns
SystemInfo()
Send system information to the device.
[Obsolete("Use SystemInfoAsync instead.")]
public void SystemInfo()
SystemInfoAsync()
Asynchronously sends system information to the device.
public Task SystemInfoAsync()
Returns
TextAppend(string)
Append text to the virtual keyboard.
[Obsolete("Use TextAppendAsync instead.")]
public void TextAppend(string text)
Parameters
textstringThe text to insert.
TextAppendAsync(string)
Asynchronously appends text to the virtual keyboard.
public Task TextAppendAsync(string text)
Parameters
textstring
Returns
TextClear()
Clear the virtual keyboard text.
[Obsolete("Use TextClearAsync instead.")]
public void TextClear()
TextClearAsync()
Asynchronously clears the virtual keyboard text.
public Task TextClearAsync()
Returns
TextGet()
Get the current virtual keyboard text.
[Obsolete("Use TextGetAsync instead.")]
public string? TextGet()
Returns
TextGetAsync()
Asynchronously gets the current virtual keyboard text.
public Task<string?> TextGetAsync()
Returns
TextInputCommand(string, bool)
Send a text input command: refreshes the RTI session, optionally clears the current text, then optionally inserts new text.
[Obsolete("Use TextInputCommandAsync instead.")]
public string? TextInputCommand(string text, bool clearPreviousInput = false)
Parameters
textstringThe text to insert, or an empty string to insert nothing.
clearPreviousInputboolWhether to clear the existing text before inserting.
Returns
TextInputCommandAsync(string, bool)
Asynchronously sends a text input command.
public Task<string?> TextInputCommandAsync(string text, bool clearPreviousInput = false)
Parameters
Returns
TextInputStart()
Start a text input session.
[Obsolete("Use TextInputStartAsync instead.")]
public Dictionary<object, object?> TextInputStart()
Returns
TextInputStartAsync()
Asynchronously starts a text input session.
public Task<Dictionary<object, object?>> TextInputStartAsync()
Returns
TextInputStop()
Stop the current text input session.
[Obsolete("Use TextInputStopAsync instead.")]
public void TextInputStop()
TextInputStopAsync()
Asynchronously stops the current text input session.
public Task TextInputStopAsync()
Returns
TextSet(string)
Replace the virtual keyboard text.
[Obsolete("Use TextSetAsync instead.")]
public void TextSet(string text)
Parameters
textstringThe new text.
TextSetAsync(string)
Asynchronously replaces the virtual keyboard text.
public Task TextSetAsync(string text)
Parameters
textstring
Returns
ToggleMute()
Toggles mute by saving the current volume and setting it to zero, or restoring the previously saved volume. Requires IsVolumeControlSupported.
[Obsolete("Use ToggleMuteAsync instead.")]
public bool ToggleMute()
Returns
ToggleMuteAsync()
Asynchronously toggles mute.
public Task<bool> ToggleMuteAsync()
Returns
TouchStart()
Subscribe to touch gestures.
[Obsolete("Use TouchStartAsync instead.")]
public void TouchStart()
TouchStartAsync()
Asynchronously subscribes to touch gestures.
public Task TouchStartAsync()
Returns
TouchStop()
Unsubscribe from touch gestures.
[Obsolete("Use TouchStopAsync instead.")]
public void TouchStop()
TouchStopAsync()
Asynchronously unsubscribes from touch gestures.
public Task TouchStopAsync()
Returns
TvRcSessionStart()
Open a TV Remote Client session. tvOS does not answer FetchAttentionState until a
TV Remote Client session is registered with tvremoted; older devices may simply
error on this command, so failures here are intentionally swallowed.
[Obsolete("Use TvRcSessionStartAsync instead.")]
public void TvRcSessionStart()
TvRcSessionStartAsync()
Asynchronously opens a TV Remote Client session.
public Task TvRcSessionStartAsync()
Returns
UnsubscribeEvent(string)
Unsubscribe from updates for an event.
[Obsolete("Use UnsubscribeEventAsync instead.")]
public void UnsubscribeEvent(string eventName)
Parameters
eventNamestringThe event identifier to unsubscribe from.
UnsubscribeEventAsync(string)
Asynchronously unsubscribes from updates for an event.
public Task UnsubscribeEventAsync(string eventName)
Parameters
eventNamestring
Returns
Events
ConnectionClosed
Raised when the connection to the device is closed or lost, whether cleanly (e.g. the remote end closing the socket) or unexpectedly (e.g. a transport, decrypt, or dispatch failure). Inspect Exception to distinguish the two.
public event EventHandler<ConnectionClosedEventArgs>? ConnectionClosed
Event Type
Remarks
Mirrors pyatv's DeviceListener.connection_lost/connection_closed callbacks
(pyatv/interface.py). Unlike pyatv, this port does not implement automatic
reconnection; consumers that want to reconnect must do so themselves in response to this
event.
MediaControlCapabilitiesChanged
Raised whenever an updated _iMC event is received and the device's advertised
media-control capability flags (including IsVolumeControlSupported) may
have changed.
public event EventHandler? MediaControlCapabilitiesChanged
Event Type
SystemStatusChanged
Raised whenever a pushed SystemStatus/TVSystemStatus event changes
CurrentSystemStatus, including transitions between non-Asleep
states (e.g. Awake to Screensaver). Unlike
pyatv, which only notifies on the collapsed on/off boundary, this event fires on every raw state
change; inspect CurrentSystemStatus from the handler for the granular value, or
compare it against Asleep if only on/off matters.
public event EventHandler? SystemStatusChanged
Event Type
TextFocusStateChanged
Raised whenever TextFocusState is updated by a _tiStarted,
_tiStopped event, or a _tiStart response.
public event EventHandler? TextFocusStateChanged