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
- SystemStatus
The most recently known system status (power state), updated by the initial FetchAttentionState() snapshot taken during Connect() and by subsequently pushed
SystemStatus/TVSystemStatusevents.
DeviceId
Gets the device identifier reported as _pubID.
public string DeviceId { get; }
Property Value
- string
The device identifier reported as
_pubID.
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
- bool
A value indicating whether the device currently advertises volume control support via the
_iMCevent's_mcFbitmask (Volume). When this is false, audio is managed outside Companion (e.g. HDMI-CEC) and GetVolume()/SetVolume(double) must not be used.
Model
Gets the device model string.
public string Model { get; }
Property Value
- string
The device model string.
Name
Gets the device name string.
public string Name { get; }
Property Value
- string
The device name string.
Sid
Gets the combined session id established by SessionStart().
public long Sid { get; }
Property Value
- long
The combined session id established by SessionStart().
StableIdentifier
Gets the stable identifier used as the _systemInfo _i field.
public string StableIdentifier { get; }
Property Value
- string
The stable identifier used as the
_systemInfo_ifield.
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
- KeyboardFocusState
The current keyboard (RTI text input) focus state, as last reported by the
_tiStarted/_tiStoppedevents or the_tiStartresponse.
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
- Task<Dictionary<string, string>>
A task containing account display names keyed by account identifier.
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
- Task<Dictionary<object, object>>
A task containing the raw account response content, or an empty dictionary if content is absent.
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
- Task<Dictionary<string, string>>
A task containing launchable application display names keyed by bundle identifier.
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
- Task
A task that completes when the Companion bring-up sequence finishes.
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
- Task<SystemStatus>
A task containing the reported device attention state.
GetVolume()
Gets the current volume level, in percent ([0.0-100.0]).
[Obsolete("Use GetVolumeAsync instead.")]
public double GetVolume()
Returns
- double
The current volume as a percentage from 0 to 100.
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
bundleIdOrUrlstringThe application bundle identifier or absolute URL to launch.
Returns
- Task
A task that completes when the application-launch exchange finishes.
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
commandMediaControlCommandThe HID or media control command to send.
argsDictionary<string, object>Optional command arguments to merge into the request.
Returns
- Task<Dictionary<object, object>>
A task containing the media command response content.
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
actionInputActionThe click action to perform.
Returns
- Task
A task that completes when the requested click sequence has been sent.
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
downboolTrue for a key press; false for a key release.
commandHidCommandThe HID or media control command to send.
Returns
- Task
A task that completes when the HID command exchange finishes.
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
xintThe horizontal touch coordinate, clamped to the touchpad bounds.
yintThe vertical touch coordinate, clamped to the touchpad bounds.
modeTouchActionThe touch action to send.
Returns
- Task
A task that completes when the touch event has been sent.
SessionStart()
Start a Companion session.
[Obsolete("Use SessionStartAsync instead.")]
public void SessionStart()
SessionStartAsync()
Asynchronously starts a Companion session.
public Task SessionStartAsync()
Returns
- Task
A task that completes when the session identifier has been negotiated.
SessionStop()
Stop the current Companion session.
[Obsolete("Use SessionStopAsync instead.")]
public void SessionStop()
SessionStopAsync()
Asynchronously stops the current Companion session.
public Task SessionStopAsync()
Returns
- Task
A task that completes when the session-stop request finishes.
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
leveldoubleThe volume level expressed as a percentage from 0 to 100.
Returns
- Task
A task that completes when the volume command finishes.
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
eventNamestringThe protocol event name to subscribe to or unsubscribe from.
Returns
- Task
A task that completes when the event subscription has been sent or was already registered.
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
accountIdstringThe identifier of the account to activate.
Returns
- Task
A task that completes when the account-switch exchange finishes.
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
- Task
A task that completes when the system-information exchange finishes.
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
textstringThe text to append or set.
Returns
- Task
A task that completes when the text-append operation finishes.
TextClear()
Clear the virtual keyboard text.
[Obsolete("Use TextClearAsync instead.")]
public void TextClear()
TextClearAsync()
Asynchronously clears the virtual keyboard text.
public Task TextClearAsync()
Returns
- Task
A task that completes when the text-clear operation finishes.
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
- Task<string>
A task containing the current virtual keyboard text, or null if no usable text-input session is available.
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
textstringThe text to append or set.
clearPreviousInputboolWhether to clear the existing text before appending the supplied text.
Returns
- Task<string>
A task containing the resulting text, or null if no usable text-input session is available.
TextInputStart()
Start a text input session.
[Obsolete("Use TextInputStartAsync instead.")]
public Dictionary<object, object?> TextInputStart()
Returns
- Dictionary<object, object>
The response to the text-input session start command.
TextInputStartAsync()
Asynchronously starts a text input session.
public Task<Dictionary<object, object?>> TextInputStartAsync()
Returns
- Task<Dictionary<object, object>>
A task containing the response to the text-input session start command.
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
- Task
A task that completes when the text-input stop request finishes.
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
textstringThe text to append or set.
Returns
- Task
A task that completes when the text-replacement operation finishes.
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
- Task<bool>
A task containing true when muted after the operation; false when the previous volume has been restored.
TouchStart()
Subscribe to touch gestures.
[Obsolete("Use TouchStartAsync instead.")]
public void TouchStart()
TouchStartAsync()
Asynchronously subscribes to touch gestures.
public Task TouchStartAsync()
Returns
- Task
A task that completes when the touch subscription request finishes.
TouchStop()
Unsubscribe from touch gestures.
[Obsolete("Use TouchStopAsync instead.")]
public void TouchStop()
TouchStopAsync()
Asynchronously unsubscribes from touch gestures.
public Task TouchStopAsync()
Returns
- Task
A task that completes when the touch unsubscription request finishes.
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
- Task
A task that completes when the TV Remote Client start attempt finishes, including a logged and ignored remote error.
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
eventNamestringThe protocol event name to subscribe to or unsubscribe from.
Returns
- Task
A task that completes when the event unsubscription has been sent or no subscription existed.
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