Skip to content

Control RPC (vive_engine.proto)

Index

service VsEngine

The Vive Engine RPC API specification.

Vive Engine is an audio orchestration engine for desktop. It sits between audio applications and the operating system, and lets you inject real-time effects into audio streams, capture audio for recording or analysis, reroute streams between applications and devices, and add live captions.

This service is the public interface to the engine. Its methods let a client open sessions, activate licenses, load custom plugins, configure audio flow and effects, set up captioning, discover devices, and monitor the engine.

From this specification a gRPC client can be generated for any supported language using standard protobuf tooling, exposing the same methods defined in this service. The request and response messages become language-specific structures or DTO classes.

service VsEngine
{

    // / Open a new session.
    rpc OpenSession(VsOpenSessionRequest) returns (VsSessionState);

    // / Renew an existing session.
    rpc RenewSession(VsRenewSessionRequest) returns (VsSessionState);

    // / Close a session.
    rpc CloseSession(VsCloseSessionRequest) returns (VsEmpty);

    // / Query the current license state.
    rpc GetLicense(VsGetLicenseRequest) returns (VsLicenseState);

    // / Activate a license.
    rpc ActivateLicense(VsActivateLicenseRequest) returns (VsLicenseState);

    // / Deactivate the current license.
    rpc DeactivateLicense(VsDeactivateLicenseRequest) returns (VsLicenseState);

    // / List loaded plugins.
    rpc ListPlugins(VsListPluginsRequest) returns (VsPluginList);

    // / Load a plugin.
    rpc LoadPlugin(VsLoadPluginRequest) returns (VsPlugin);

    // / Unload a plugin.
    rpc UnloadPlugin(VsUnloadPluginRequest) returns (VsEmpty);

    // / Send a message to one plugin instance.
    rpc SendMessage(VsSendMessageRequest) returns (VsEmpty);

    // / Broadcast a message to all instances of a plugin.
    rpc BroadcastMessage(VsBroadcastMessageRequest) returns (VsEmpty);

    // / Subscribe to messages from plugins.
    rpc SubscribeMessages(VsSubscribeMessagesRequest) returns (VsSubscription);

    // / Receive messages for a subscription.
    rpc ReceiveMessages(VsReceiveMessagesRequest) returns (stream VsMessage);

    // / Cancel a message subscription.
    rpc UnsubscribeMessages(VsUnsubscribeMessagesRequest) returns (VsEmpty);

    // / Retrieve the current run mode.
    rpc GetRunMode(VsGetModeRequest) returns (VsRunMode);

    // / Set the run mode.
    rpc SetRunMode(VsSetModeRequest) returns (VsRunMode);

    // / Retrieve the configuration of a flow.
    rpc QueryFlow(VsQueryFlowRequest) returns (VsFlowConfig);

    // / Configure a flow.
    rpc ConfigureFlow(VsConfigureFlowRequest) returns (VsFlowConfig);

    // / Retrieve a single effect from a flow.
    rpc QueryEffect(VsQueryEffectRequest) returns (VsEffectConfig);

    // / Insert a single effect into a flow.
    rpc InsertEffect(VsInsertEffectRequest) returns (VsEffectConfig);

    // / Reconfigure a single effect in a flow.
    rpc ConfigureEffect(VsConfigureEffectRequest) returns (VsEffectConfig);

    // / Remove a single effect from a flow.
    rpc DeleteEffect(VsDeleteEffectRequest) returns (VsEmpty);

    // / Select the captioning provider and configure its credentials.
    rpc ConfigureCaptions(VsConfigureCaptionsRequest) returns (VsCaptionsConfig);

    // / Subscribe to captions.
    rpc SubscribeCaptions(VsSubscribeCaptionsRequest) returns (VsSubscription);

    // / Receive captions for a subscription.
    rpc ReceiveCaptions(VsReceiveCaptionsRequest) returns (stream VsCaption);

    // / Cancel a caption subscription.
    rpc UnsubscribeCaptions(VsUnsubscribeCaptionsRequest) returns (VsEmpty);

    // / List the available audio devices.
    rpc ListDevices(VsListDevicesRequest) returns (VsDeviceList);

    // / Subscribe to engine events.
    rpc SubscribeEvents(VsSubscribeEventsRequest) returns (VsSubscription);

    // / Receive events for a subscription.
    rpc ReceiveEvents(VsReceiveEventsRequest) returns (stream VsEvent);

    // / Cancel an event subscription.
    rpc UnsubscribeEvents(VsUnsubscribeEventsRequest) returns (VsEmpty);
}

Sessions

A session is the context in which an engine user makes requests. It must be established before calling any other method, and every request is associated with a specific session through its session_token.

Multiple applications on the computer may use the engine, possibly running under different operating system users. The operating system determines which OS user is currently active, and this can change over time. The engine runs as a single instance and tracks active user change.

An application must report its OS user when opening a session. The engine allows opening sessions only for the currently active OS user. A session opened for another user either blocks until that user becomes active, or fails immediately, depending on open mode.

When the active user changes, the engine closes the sessions of the former user and admits sessions of the new one. An application running in the background under an inactive user therefore either blocks while opening a session, or fails and may retry later.

Typically an application opens one session and uses it for all requests, but any number of sessions may be open in parallel, including from different applications. Sessions of the current active user can all be used in parallel.

A session is not tied to a gRPC connection. It survives gRPC reconnects and may be used from a new connection if its session_token is valid.

rpc OpenSession()

rpc OpenSession(VsOpenSessionRequest) returns (VsSessionState);

Open a new session.

Establishes a session for the OS user given in user_name and returns its VsSessionState. The returned session_token identifies the session and must be carried by every other request.

open_mode selects behavior when the requested user is not the active user: VS_OPEN_MODE_WAIT_USER blocks until that user becomes active, while VS_OPEN_MODE_FAIL_FAST returns an error immediately.

The returned state also carries the session's expiration schedule. A session expires unless renewed in time; see RenewSession.

rpc RenewSession()

rpc RenewSession(VsRenewSessionRequest) returns (VsSessionState);

Renew an existing session.

Resets the session's expiration timer and returns the updated VsSessionState. A session is closed automatically if not renewed in time, so the application must call this method regularly, before expires_at elapses. The recommended period between renewals is reported as renewal_interval in VsSessionState.

The call fails if the session has already been closed, for example because it expired or its OS user is no longer active; in that case a new session must be opened.

rpc CloseSession()

rpc CloseSession(VsCloseSessionRequest) returns (VsEmpty);

Close a session.

Terminates the session identified by session_token and cancels all requests and streams associated with it. Close a session as soon as it is no longer needed, rather than waiting for it to expire.

The call is idempotent: closing an already closed session (including one closed automatically on expiration or an active-user change) has no effect. After closing, the session_token is no longer valid.

message VsOpenSessionRequest

Input argument of OpenSession.

The request names the OS user that the application runs as. The engine tracks which OS user is currently active and, depending on open_mode, admits the session only when that user is active.

message VsOpenSessionRequest
{
    /// Behavior when \c user_name is not the currently active OS user.
    VsOpenMode open_mode = 1;

    /// Login name of the OS user the application runs as. On Linux and macOS
    /// this is the account login name from the user database; on Windows it is
    /// the account name, optionally domain-qualified as \c DOMAIN\\user.
    /// Required.
    string user_name = 2;
}

message VsRenewSessionRequest

Input argument of RenewSession.

message VsRenewSessionRequest
{
    /// Token of the session to renew, as returned by \ref OpenSession.
    string session_token = 1;
}

message VsCloseSessionRequest

Input argument of CloseSession.

message VsCloseSessionRequest
{
    /// Token of the session to close, as returned by \ref OpenSession.
    string session_token = 1;
}

message VsSessionState

Return value of OpenSession and RenewSession.

message VsSessionState
{
    /// Token identifying the session. Returned by \ref OpenSession and carried
    /// by every subsequent request associated with this session.
    string session_token = 1;

    /// Interval at which the engine recommends calling \ref RenewSession to
    /// keep the session from expiring.
    google.protobuf.Duration renewal_interval = 2;

    /// Point in time after which the session expires unless renewed.
    google.protobuf.Timestamp expires_at = 3;
}

enum VsOpenMode

Behavior of OpenSession when the requested OS user is not the currently active one.

enum VsOpenMode
{
    /// Block until the requested user becomes active. This is the default.
    VS_OPEN_MODE_WAIT_USER = 0;

    /// Fail immediately if the requested user is not active.
    VS_OPEN_MODE_FAIL_FAST = 1;
}

Licensing

Licensing controls whether the engine is permitted to run audio processing. Depending on the edition, activation may be required, and the license type determined during activation governs which features are available.

A successful activation is persistent. It remains in effect across restarts until the license expires or is revoked, or the application calls DeactivateLicense.

The engine periodically contacts the licensing service to keep the activation alive and to detect expiration. A license may expire while the engine is running, stopping processing and notifying the application through an event.

rpc GetLicense()

rpc GetLicense(VsGetLicenseRequest) returns (VsLicenseState);

Query the current license state.

Returns the current VsLicenseState without changing it. The state reports the activation_type and, when a license is active, either full or trial activation details.

rpc ActivateLicense()

rpc ActivateLicense(VsActivateLicenseRequest) returns (VsLicenseState);

Activate a license.

Activates the engine using the method selected by activation_type and returns the resulting VsLicenseState.

The call contacts the licensing service and may take noticeably longer than other requests. It fails if the edition does not permit the requested method or if the service rejects the activation.

rpc DeactivateLicense()

rpc DeactivateLicense(VsDeactivateLicenseRequest) returns (VsLicenseState);

Deactivate the current license.

Releases the current activation and returns the updated VsLicenseState. This frees the activation so it can be used on another computer. Once deactivated, the engine stops audio processing until a license is activated again.

message VsGetLicenseRequest

Input argument of GetLicense.

message VsGetLicenseRequest
{
    /// Token returned by \ref OpenSession. Required.
    string session_token = 1;
}

message VsActivateLicenseRequest

Input argument of ActivateLicense.

The activation_type selects how activation is performed and which authentication field, if any, is required. VS_ACTIVATION_TRIAL needs no authentication; VS_ACTIVATION_KEY requires license_key; and VS_ACTIVATION_CREDS requires credentials. VS_ACTIVATION_NONE is not a valid request value.

message VsActivateLicenseRequest
{
    /// Token returned by \ref OpenSession. Required.
    string session_token = 1;

    /// Activation method to perform. Required; must not be
    /// \c VS_ACTIVATION_NONE. Determines which \c authentication field is
    /// required. See \ref VsActivationType.
    VsActivationType activation_type = 2;

    /// Credential for the selected \c activation_type. Must be set for
    /// \c VS_ACTIVATION_KEY and \c VS_ACTIVATION_CREDS, and must be left unset
    /// for \c VS_ACTIVATION_TRIAL.
    oneof authentication
    {
        /// License key. Required when \c activation_type is
        /// \c VS_ACTIVATION_KEY.
        string license_key = 3;

        /// User account credentials. Required when \c activation_type is
        /// \c VS_ACTIVATION_CREDS.
        VsCredentials credentials = 4;
    }
}

message VsDeactivateLicenseRequest

Input argument of DeactivateLicense.

message VsDeactivateLicenseRequest
{
    /// Token returned by \ref OpenSession. Required.
    string session_token = 1;
}

message VsLicenseState

Return value of GetLicense, ActivateLicense, and DeactivateLicense.

The details field is present only when a license is active, and its variant matches activation_type: a trial activation reports trial_activation, a full (key or credentials) activation reports full_activation. When activation_type is VS_ACTIVATION_NONE no license is active and details is unset.

message VsLicenseState
{
    /// Current activation type, or \c VS_ACTIVATION_NONE when no license is
    /// active. See \ref VsActivationType.
    VsActivationType activation_type = 1;

    /// Details of the active license, if any. The variant is selected by
    /// \c activation_type and is unset when \c activation_type is
    /// \c VS_ACTIVATION_NONE.
    oneof details
    {
        /// Details of a full license, set when \c activation_type is
        /// \c VS_ACTIVATION_KEY or \c VS_ACTIVATION_CREDS.
        VsFullActivation full_activation = 2;

        /// Details of a trial license, set when \c activation_type is
        /// \c VS_ACTIVATION_TRIAL.
        VsTrialActivation trial_activation = 3;
    }
}

message VsCredentials

User account credentials for VS_ACTIVATION_CREDS activation, supplied in VsActivateLicenseRequest.

message VsCredentials
{
    /// Email address of the user account. Required.
    string email = 1;

    /// Password of the user account. Required.
    string password = 2;
}

message VsFullActivation

Details of a full (key or credentials) license, reported in the details field of VsLicenseState.

message VsFullActivation
{
    /// Number of activations currently in use across all computers.
    uint64 used_activations = 1;

    /// Total number of activations the license permits.
    uint64 available_activations = 2;

    /// Point in time when the license was issued.
    google.protobuf.Timestamp issue_date = 10;

    /// Point in time when this computer was activated.
    google.protobuf.Timestamp activation_date = 11;

    /// Point in time after which the license expires.
    google.protobuf.Timestamp expiration_date = 12;
}

message VsTrialActivation

Details of a trial license, reported in the details field of VsLicenseState.

message VsTrialActivation
{
    /// Point in time after which the trial expires.
    google.protobuf.Timestamp expiration_date = 1;
}

enum VsActivationType

Activation type, used both to request an activation method in VsActivateLicenseRequest and to report the current one in VsLicenseState.

Which types an engine accepts depends on its edition. During activation the engine contacts the licensing service, which grants or denies the request; a granted activation stays in effect across restarts until it expires or is deactivated. Editions that require no license report VS_ACTIVATION_NONE and run without activation.

enum VsActivationType
{
    /// No license is active. In \ref VsLicenseState this means the engine runs
    /// without activation or has not been activated yet. Not a valid request
    /// value for \ref ActivateLicense.
    VS_ACTIVATION_NONE = 0;

    /// Time-limited trial bound to this computer. Requires no credentials and
    /// expires after a fixed period.
    VS_ACTIVATION_TRIAL = 1;

    /// Full activation using a license key. The activation is granted to this
    /// computer and counts against the license's available activations.
    VS_ACTIVATION_KEY = 2;

    /// Full activation using user account credentials. The activation is
    /// granted to this computer and counts against the license's available
    /// activations.
    VS_ACTIVATION_CREDS = 3;
}

Plugins

Plugins extend the engine with custom audio effects supplied outside the engine. Using a plugin has two stages. First the plugin binary is loaded with LoadPlugin, which assigns it a uid. The plugin can then be used to create instances: an instance is a VsPluginEffect placed into a flow's effect chain, referencing the plugin by uid and addressed within its chain by effect_key. One loaded plugin may back any number of instances across flows.

Loading is persistent. A loaded plugin stays registered in the engine and is loaded again automatically after an engine restart or a reboot, so an application does not need to reload it on every run. The uid is derived from the plugin and is stable: if a plugin is unloaded and then loaded again, it keeps the same uid.

Plugins come in two types, see VsPluginType. A native plugin is loaded directly into the engine's address space. A managed plugin runs in a separate process and exchanges audio with the engine through shared memory. Native plugins offer the lowest overhead, while managed plugins isolate faults and support managed runtimes.

Besides audio, a plugin can exchange out-of-band messages with the application. The application sends messages to plugin instances with SendMessage and BroadcastMessage, and receives messages produced by plugins by subscribing with SubscribeMessages.

The plugin instance configuration (custom_config in VsPluginEffect) and the message payload (message_payload) are arbitrary protobuf messages carried as google.protobuf.Any, opaque to the engine. The plugin developer defines their schema, and the application and the plugin must share it to pack and unpack the payloads.

rpc ListPlugins()

rpc ListPlugins(VsListPluginsRequest) returns (VsPluginList);

List loaded plugins.

Returns a VsPluginList with one VsPlugin per plugin currently loaded in the engine. This lists loaded plugin binaries, not the instances created from them for use as effects.

rpc LoadPlugin()

rpc LoadPlugin(VsLoadPluginRequest) returns (VsPlugin);

Load a plugin.

Loads the plugin binary at location, treating it as the plugin type given in the request, and returns the resulting VsPlugin with its assigned uid. The uid can then be used to create instances of the plugin as VsPluginEffect effects and to address the plugin in messaging calls.

Loading is persistent: the plugin is remembered and loaded again automatically after a restart. The call is idempotent; loading a plugin that is already loaded returns its existing uid without loading it twice. The uid is stable across unload and reload of the same plugin.

rpc UnloadPlugin()

rpc UnloadPlugin(VsUnloadPluginRequest) returns (VsEmpty);

Unload a plugin.

Unloads the plugin identified by plugin_uid and removes it from the persistent set, so it is no longer loaded after a restart. All instances created from the plugin are destroyed and their effects are removed from the flows that contained them.

rpc SendMessage()

rpc SendMessage(VsSendMessageRequest) returns (VsEmpty);

Send a message to one plugin instance.

Delivers message_payload to the single plugin instance selected by target_effect. The payload is an opaque protobuf message understood by the plugin. The message is delivered asynchronously; the call returns once the message is accepted, not once the plugin has processed it.

rpc BroadcastMessage()

rpc BroadcastMessage(VsBroadcastMessageRequest) returns (VsEmpty);

Broadcast a message to all instances of a plugin.

Delivers message_payload to every instance created from the plugin identified by target_plugin_uid. Aside from selecting all instances of a plugin rather than one instance, it behaves like SendMessage.

rpc SubscribeMessages()

rpc SubscribeMessages(VsSubscribeMessagesRequest) returns (VsSubscription);

Subscribe to messages from plugins.

Registers a subscription for messages produced by the plugin selected by source_plugin_uid, optionally narrowed to the instances listed in source_effects, and returns a VsSubscription token. The token is then passed to ReceiveMessages to open the stream and to UnsubscribeMessages to cancel the subscription.

Receiving is split into these three methods rather than a single streaming call so that an application can be sure its subscription is established. After SubscribeMessages succeeds, every matching message is guaranteed to be delivered, including messages from effects created afterwards. A single streaming call gives no such guarantee: gRPC would not signal whether the subscription is ready or still being set up asynchronously, leaving a window in which early messages could be lost.

rpc ReceiveMessages()

rpc ReceiveMessages(VsReceiveMessagesRequest) returns (stream VsMessage);

Receive messages for a subscription.

Opens a stream of VsMessage for the subscription identified by subscription_token, previously obtained from SubscribeMessages. The stream stays open until the subscription is cancelled with UnsubscribeMessages, the session ends, or the call is cancelled.

rpc UnsubscribeMessages()

rpc UnsubscribeMessages(VsUnsubscribeMessagesRequest) returns (VsEmpty);

Cancel a message subscription.

Cancels the subscription identified by subscription_token and closes its ReceiveMessages stream. After this call the subscription_token is no longer valid.

message VsListPluginsRequest

Input argument of ListPlugins.

message VsListPluginsRequest
{
    /// Token returned by \ref OpenSession. Required.
    string session_token = 1;
}

message VsLoadPluginRequest

Input argument of LoadPlugin.

message VsLoadPluginRequest
{
    /// Token returned by \ref OpenSession. Required.
    string session_token = 1;

    /// Kind of plugin binary at \c location. Required. See \ref VsPluginType.
    VsPluginType type = 2;

    /// Filesystem path to the plugin binary on the engine host. Required.
    string location = 3;
}

message VsUnloadPluginRequest

Input argument of UnloadPlugin.

message VsUnloadPluginRequest
{
    /// Token returned by \ref OpenSession. Required.
    string session_token = 1;

    /// Identifier of the plugin to unload, as returned by \ref LoadPlugin.
    /// Required.
    string plugin_uid = 2;
}

message VsPluginList

Return value of ListPlugins.

message VsPluginList
{
    /// Loaded plugins, one entry per plugin binary. Empty if no plugin is
    /// loaded.
    repeated VsPlugin plugins = 1;
}

message VsPlugin

A plugin loaded in the engine.

Returned by LoadPlugin and listed by ListPlugins. This describes a loaded plugin binary, not an instance of it; instances are VsPluginEffect effects placed into flows.

message VsPlugin
{
    /// Identifier of the plugin. Derived from the plugin and stable
    /// across unload and reload, so the same plugin keeps the same \c uid.
    /// Used to create instances and to address the plugin in messaging calls.
    string uid = 1;

    /// Kind of plugin binary. See \ref VsPluginType.
    VsPluginType type = 2;

    /// Filesystem path the plugin was loaded from, as passed to
    /// \ref LoadPlugin.
    string location = 3;

    /// Number of instances currently created from this plugin across all flows.
    uint32 instance_count = 10;
}

message VsSendMessageRequest

Input argument of SendMessage.

message VsSendMessageRequest
{
    /// Token returned by \ref OpenSession. Required.
    string session_token = 1;

    /// Plugin instance to receive the message, addressed by its effect within a
    /// flow. Required. See \ref VsEffectSelector.
    VsEffectSelector target_effect = 2;

    /// Message to deliver. An opaque protobuf message whose schema is defined by
    /// the plugin developer and shared with the application.
    optional google.protobuf.Any message_payload = 10;
}

message VsBroadcastMessageRequest

Input argument of BroadcastMessage.

message VsBroadcastMessageRequest
{
    /// Token returned by \ref OpenSession. Required.
    string session_token = 1;

    /// Plugin whose instances receive the message, as returned by
    /// \ref LoadPlugin. Required. The message is delivered to every instance
    /// created from this plugin.
    string target_plugin_uid = 2;

    /// Message to deliver. An opaque protobuf message whose schema is defined by
    /// the plugin developer and shared with the application.
    optional google.protobuf.Any message_payload = 10;
}

message VsSubscribeMessagesRequest

Input argument of SubscribeMessages.

message VsSubscribeMessagesRequest
{
    /// Token returned by \ref OpenSession. Required.
    string session_token = 1;

    /// Plugin whose messages to receive, as returned by \ref LoadPlugin.
    /// Required.
    string source_plugin_uid = 2;

    /// Instances to narrow the subscription to, each addressed by its effect
    /// within a flow. If empty, messages from all instances of the plugin are
    /// received. See \ref VsEffectSelector.
    repeated VsEffectSelector source_effects = 3;
}

message VsReceiveMessagesRequest

Input argument of ReceiveMessages.

message VsReceiveMessagesRequest
{
    /// Token returned by \ref OpenSession. Required.
    string session_token = 1;

    /// Token returned by the matching subscribe call.
    string subscription_token = 2;
}

message VsUnsubscribeMessagesRequest

Input argument of UnsubscribeMessages.

message VsUnsubscribeMessagesRequest
{
    /// Token returned by \ref OpenSession. Required.
    string session_token = 1;

    /// Token returned by the matching subscribe call.
    string subscription_token = 2;
}

message VsMessage

A message produced by a plugin instance.

Streamed by ReceiveMessages for a subscription created with SubscribeMessages.

message VsMessage
{
    /// Plugin that produced the message, as returned by \ref LoadPlugin.
    string source_plugin_uid = 1;

    /// Instance that produced the message, addressed by its effect within a
    /// flow. See \ref VsEffectSelector.
    optional VsEffectSelector source_effect = 2;

    /// Message payload. An opaque protobuf message whose schema is defined by
    /// the plugin developer and shared with the application.
    optional google.protobuf.Any message_payload = 10;
}

enum VsPluginType

Kind of a plugin binary, selecting how the engine loads and runs it.

enum VsPluginType
{
    /// Unset. Not a valid value in a \ref LoadPlugin request.
    VS_PLUGIN_UNSPECIFIED = 0;

    /// Native plugin, a shared library loaded directly into the engine's
    /// address space for the lowest overhead. The binary at \c location is a
    /// shared library with a platform-specific extension:
    ///
    /// - `.dll` on Windows
    /// - `.so` on Linux and macOS
    VS_PLUGIN_NATIVE = 1;

    /// Managed plugin written in Go using the \c vsplug package. The plugin is
    /// compiled into a regular executable that the engine runs as a separate
    /// process and communicates with over IPC. The binary at \c location is an
    /// executable with a platform-specific extension:
    ///
    /// - `.exe` on Windows
    /// - no extension on Linux and macOS
    VS_PLUGIN_GOLANG = 2;
}

Run mode

Run mode is a master switch that controls whether the engine is active on audio input, output, or both. When a direction is disabled, the engine detaches from the corresponding audio path: neither processing nor routing is applied, and audio flows through the OS as if ViveEngine was not installed.

Input and output can be controlled independently. All configuration (effects, routes) persists while the engine is off and is restored when it is turned on again. Configuration may also be adjusted while the engine is off.

The engine automatically disables itself when there are no open sessions, which serves as a fail-safe measure if the application hangs, crashes, or loses connectivity.

rpc GetRunMode()

rpc GetRunMode(VsGetModeRequest) returns (VsRunMode);

Retrieve the current run mode.

Returns a VsRunMode indicating whether input and output processing are currently enabled or disabled.

rpc SetRunMode()

rpc SetRunMode(VsSetModeRequest) returns (VsRunMode);

Set the run mode.

Enables or disables the engine for input, output, or both. Only the fields present in the request are updated; omitted fields retain their current value. Returns the resulting VsRunMode after the change is applied.

message VsGetModeRequest

Input argument of GetRunMode.

message VsGetModeRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;
}

message VsSetModeRequest

Input argument of SetRunMode.

Only the directions present in the request are changed; omitted fields keep their current value.

message VsSetModeRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Desired state of input processing. If omitted, input processing is
    /// left unchanged.
    optional VsProcessingMode input_processing = 2;

    /// Desired state of output processing. If omitted, output processing is
    /// left unchanged.
    optional VsProcessingMode output_processing = 3;
}

message VsRunMode

Return value of GetRunMode and SetRunMode.

Reports whether the engine is currently active on the input and output audio paths.

message VsRunMode
{
    /// Current state of input processing.
    VsProcessingMode input_processing = 1;

    /// Current state of output processing.
    VsProcessingMode output_processing = 2;
}

message VsProcessingMode

State of the engine for a single audio direction (input or output).

message VsProcessingMode
{
    /// Whether the engine is active on this direction. When \c false, the
    /// engine detaches from the corresponding audio path and audio flows
    /// through the OS unmodified.
    bool enabled = 1;
}

Audio flow

Audio applications and audio devices managed by the engine each have a logical input and output. A flow is the configuration of one such input or output.

A flow is identified by a VsFlowSelector, which includes a scope (whether it is a device, app, or default flow) and a direction (whether it is an input or output flow).

For an application, a flow configures a route, selecting which device is used, and an effect chain, processing the audio. For a device, a flow configures only an effect chain. The default flow applies to applications that have no flow configured of their own.

When an application plays audio to an output device, the audio passes through the effect chains of both the application's flow and the device's flow. The same is true when an application captures from an input device.

An effect chain is an ordered list of effects. Each effect is either built-in, provided by the engine (see VsEffectConfig), or a plugin effect, backed by a loaded plugin (see VsPluginEffect and plugin). Every effect carries a caller-assigned effect_key, unique within the effect chain, used to address the effect.

rpc QueryFlow()

rpc QueryFlow(VsQueryFlowRequest) returns (VsFlowConfig);

Retrieve the configuration of a flow.

Locates the flow by flow_selector and returns its VsFlowConfig, with the current route and effect_chain.

rpc ConfigureFlow()

rpc ConfigureFlow(VsConfigureFlowRequest) returns (VsFlowConfig);

Configure a flow.

Locates the flow by flow_selector and replaces its configuration with flow_config, setting its route and effect_chain in one call. Returns the resulting VsFlowConfig.

If route is omitted, the default route is used. An empty effect_chain means default processing, that is, no processing.

rpc QueryEffect()

rpc QueryEffect(VsQueryEffectRequest) returns (VsEffectConfig);

Retrieve a single effect from a flow.

Locates the effect by flow_selector and effect_key, and returns its VsEffectConfig. Fails if no such effect exists.

rpc InsertEffect()

rpc InsertEffect(VsInsertEffectRequest) returns (VsEffectConfig);

Insert a single effect into a flow.

Locates the flow by flow_selector and inserts effect_config into its effect chain at the zero-based chain_position, shifting later effects toward the end. Returns the resulting VsEffectConfig. Fails if chain_position is past the end of the chain, or if the effect_key is already in use within that chain.

rpc ConfigureEffect()

rpc ConfigureEffect(VsConfigureEffectRequest) returns (VsEffectConfig);

Reconfigure a single effect in a flow.

Locates the effect by flow_selector and the effect_key of effect_config, and replaces it, keeping its position. Returns the resulting VsEffectConfig. Fails if no such effect exists.

rpc DeleteEffect()

rpc DeleteEffect(VsDeleteEffectRequest) returns (VsEmpty);

Remove a single effect from a flow.

Locates the effect by flow_selector and effect_key, and removes it, shifting later effects toward the start. Fails if no such effect exists.

message VsQueryFlowRequest

Input argument of QueryFlow.

message VsQueryFlowRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Flow to query, addressed by its scope and direction. Required. See
    /// \ref VsFlowSelector.
    VsFlowSelector flow_selector = 2;
}

message VsConfigureFlowRequest

Input argument of ConfigureFlow.

message VsConfigureFlowRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Flow to configure, addressed by its scope and direction. Required. See
    /// \ref VsFlowSelector.
    VsFlowSelector flow_selector = 2;

    /// New configuration to install. Required. Replaces the flow's current
    /// \c route and \c effect_chain in full. See \ref VsFlowConfig.
    VsFlowConfig flow_config = 3;
}

message VsQueryEffectRequest

Input argument of QueryEffect.

message VsQueryEffectRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Flow that holds the effect, addressed by its scope and direction.
    /// Required. See \ref VsFlowSelector.
    VsFlowSelector flow_selector = 2;

    /// Key of the effect to query within the flow's effect chain. Required. The
    /// key is an arbitrary number assigned by the caller when the effect is
    /// created; it is unrelated to the effect's position in the chain.
    uint32 effect_key = 3;
}

message VsConfigureEffectRequest

Input argument of ConfigureEffect.

message VsConfigureEffectRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Flow that holds the effect, addressed by its scope and direction.
    /// Required. See \ref VsFlowSelector.
    VsFlowSelector flow_selector = 2;

    /// Replacement configuration. Required. The effect to reconfigure is
    /// identified by the \c effect_key inside \c effect_config; its position in
    /// the chain is preserved. See \ref VsEffectConfig.
    VsEffectConfig effect_config = 3;
}

message VsInsertEffectRequest

Input argument of InsertEffect.

message VsInsertEffectRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Flow to insert the effect into, addressed by its scope and direction.
    /// Required. See \ref VsFlowSelector.
    VsFlowSelector flow_selector = 2;

    /// Effect to insert. Required. Its \c effect_key must not already be in use
    /// within the target chain. See \ref VsEffectConfig.
    VsEffectConfig effect_config = 3;

    /// Zero-based index at which to insert the effect. Required. Later effects
    /// shift toward the end. Effect keys are unaffected by position change. Must
    /// not exceed the current chain length; equal to the length appends to the
    /// end.
    uint32 chain_position = 4;
}

message VsDeleteEffectRequest

Input argument of DeleteEffect.

message VsDeleteEffectRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Flow that holds the effect, addressed by its scope and direction.
    /// Required. See \ref VsFlowSelector.
    VsFlowSelector flow_selector = 2;

    /// Key of the effect to remove within the flow's effect chain. Required.
    uint32 effect_key = 3;
}

message VsFlowSelector

Addresses a single flow by scope and direction.

message VsFlowSelector
{
    /// Which flow the selector refers to. See \ref VsScope.
    VsScope scope = 1;

    /// Whether the input or the output flow is selected. See \ref VsDirection.
    VsDirection direction = 2;
}

message VsEffectSelector

Addresses a single effect within a flow.

Combines a VsFlowSelector with the effect_key of one effect in that flow's effect chain.

message VsEffectSelector
{
    /// Which flow the effect belongs to. See \ref VsScope.
    VsScope scope = 1;

    /// Whether the effect belongs to the input or output flow. See
    /// \ref VsDirection.
    VsDirection direction = 2;

    /// Key of the effect within the flow's effect chain.
    uint32 effect_key = 10;
}

message VsFlowConfig

Configuration of a single flow.

Return value of QueryFlow and ConfigureFlow, and the payload of VsConfigureFlowRequest.

message VsFlowConfig
{
    /// Route that selects the device used by the flow. If omitted, the default
    /// route is used. Only meaningful for application flows; ignored for device
    /// flows. See \ref VsRoute.
    optional VsRoute route = 1;

    /// Ordered list of effects applied to the audio, from first to last. An
    /// empty chain means default processing, that is, no processing. See
    /// \ref VsEffectConfig.
    repeated VsEffectConfig effect_chain = 2;
}

message VsRoute

Route of a flow: the device its audio is bound to.

message VsRoute
{
    /// UID of the device the flow is routed to, as reported by
    /// \ref ListDevices. See \ref VsDevice.
    string device_uid = 1;
}

message VsEffectConfig

Configuration of a single effect within an effect chain.

An effect is either one of the built-in effects provided by the engine or a plugin effect. Exactly one variant of the effect oneof selects the kind of effect and carries its parameters.

message VsEffectConfig
{
    /// Caller-assigned key that identifies the effect within its chain. Must be
    /// unique within the chain. Used to address the effect in \ref QueryEffect,
    /// \ref ConfigureEffect, and \ref DeleteEffect.
    uint32 effect_key = 1;

    /// When \c true, the effect is kept in the chain but bypassed, passing audio
    /// through unchanged. Defaults to \c false (active).
    bool disabled = 2;

    /// The effect kind and its parameters. Exactly one variant must be set.
    oneof effect
    {
        /// Per-channel gain. See \ref VsGainEffect.
        VsGainEffect gain = 10;

        /// Multi-band equalizer. See \ref VsEqualizerEffect.
        VsEqualizerEffect equalizer = 11;

        /// Dynamic range compression. See \ref VsRangeCompressionEffect.
        VsRangeCompressionEffect range_compression = 12;

        /// Noise reduction. See \ref VsNoiseReductionEffect.
        VsNoiseReductionEffect noise_reduction = 13;

        /// Speech captioning. See \ref VsCaptioningEffect.
        VsCaptioningEffect captioning = 14;

        /// Plugin effect. See \ref VsPluginEffect.
        VsPluginEffect plugin = 15;
    }
}

message VsGainEffect

Per-channel gain effect.

Applies a constant gain to each channel independently, in decibels. A positive value amplifies, a negative value attenuates, and 0 leaves the channel unchanged.

message VsGainEffect
{
    /// Gain per channel, in dB. The n-th entry applies to the n-th channel. If
    /// fewer entries are given than there are channels, the last entry applies
    /// to all remaining channels. If empty, a gain of \c 0 dB (unity) is applied
    /// to every channel. Typical range is roughly *-60* to *+30* dB.
    repeated double channel_gains = 1;
}

message VsEqualizerEffect

Multi-band equalizer effect.

Shapes the spectrum by applying an independent gain to each of a series of contiguous frequency bands. band_frequencies and band_gains are parallel arrays and must have the same length: entry i defines band i.

The bands are ordered from low to high frequency. band_frequencies gives the upper edge of each band in ascending order; a band covers from the previous band's edge (or DC for the first band) up to its own edge. The final band extends up to the Nyquist frequency, so its edge only needs to be at or above the highest reproduced frequency.

message VsEqualizerEffect
{
    /// Upper edge frequency of each band, in Hz, in strictly ascending order.
    /// If empty, a default of eight octave-spaced bands is used (from about
    /// \c 177 Hz up to about \c 22627 Hz).
    repeated double band_frequencies = 1;

    /// Gain applied within each band, in dB. Parallel to \c band_frequencies.
    /// A positive value boosts the band, a negative value cuts it, and \c 0
    /// leaves it flat. If empty, all bands default to \c 0 dB (flat response).
    repeated double band_gains = 2;
}

message VsRangeCompressionEffect

Dynamic range compression effect.

A multi-band automatic gain control that raises the level of quiet signals and holds louder signals near a set of per-band target levels, reducing the overall dynamic range and evening out perceived loudness.

message VsRangeCompressionEffect
{
    /// Maximum gain applied to quiet signals, in dB. Bounds how much the effect
    /// may boost signals below the target level. Range \c 0 to \c 40 dB;
    /// recommended default \c 30 dB.
    double boost_level = 1;

    /// Compression ratio applied to signals that exceed the target level,
    /// expressed as the input-to-output ratio (for example \c 10 means 10:1).
    /// A higher ratio makes the level more even; a lower ratio sounds more
    /// natural. Range \c 1 (no compression) to \c 20; recommended default
    /// \c 10.
    double compression_ratio = 2;

    /// Per-band target loudness. If omitted, the default per-band targets are
    /// used. See \ref VsRangeCompressionLevels.
    optional VsRangeCompressionLevels levels = 3;
}

message VsRangeCompressionLevels

Per-band target loudness for VsRangeCompressionEffect.

Each field sets the loudness the compressor aims for in one frequency band, in dBFS (decibels relative to full scale, so 0 is the loudest possible and negative values are quieter). Range for each field is -40 to 0 dBFS.

message VsRangeCompressionLevels
{
    /// Target loudness for the low band, in dBFS. Recommended default
    /// \c -20 dBFS.
    double bass_target_level = 1;

    /// Target loudness for the mid band, in dBFS. Recommended default
    /// \c -8 dBFS.
    double mids_target_level = 2;

    /// Target loudness for the high band, in dBFS. Recommended default
    /// \c -12 dBFS.
    double treble_target_level = 3;
}

message VsNoiseReductionEffect

Noise reduction effect.

Attenuates steady background noise while preserving the desired signal. The mode selects the algorithm. See VsNoiseReductionMode.

message VsNoiseReductionEffect
{
    /// Noise reduction algorithm to use. See \ref VsNoiseReductionMode.
    VsNoiseReductionMode mode = 1;
}

message VsCaptioningEffect

Speech captioning effect.

Adding this effect to a flow's effect chain enables live transcription of speech in that flow. See captioning.

message VsCaptioningEffect
{
    /// BCP-47 language code of the spoken language to transcribe, for example
    /// \c "en-US". If empty, the provider's default language is used.
    string language_code = 1;
}

message VsPluginEffect

Plugin effect.

Runs an instance of a loaded plugin (see plugin) as an effect in the chain.

message VsPluginEffect
{
    /// UID of the plugin to instantiate, as returned by \ref LoadPlugin. The
    /// plugin must be currently loaded.
    string plugin_uid = 1;

    /// Optional plugin-specific configuration passed to the plugin instance
    /// constructor. An opaque protobuf message whose schema is defined by the
    /// plugin developer and shared with the application.
    optional google.protobuf.Any custom_config = 10;
}

enum VsScope

Scope of a flow: which entity it applies to.

enum VsScope
{
    /// The default flow, applied to applications that have no flow of their
    /// own.
    VS_SCOPE_DEFAULT = 0;
}

enum VsDirection

Direction of a flow: capture or playback.

enum VsDirection
{
    /// Input (capture) flow, for audio captured from an input device.
    VS_DIRECTION_INPUT = 0;

    /// Output (playback) flow, for audio played to an output device.
    VS_DIRECTION_OUTPUT = 1;
}

enum VsNoiseReductionMode

Noise reduction algorithm.

enum VsNoiseReductionMode
{
    /// Classic spectral noise reduction. This is the default.
    VS_NOISE_REDUCTION_DSP = 0;

    /// Neural-network noise reduction. More aggressive than \c
    /// VS_NOISE_REDUCTION_DSP and generally more effective on speech.
    VS_NOISE_REDUCTION_RNN = 1;
}

Captioning

Captioning transcribes speech in an audio stream into live text captions.

It is enabled by adding a captioning effect (VsCaptioningEffect) to the effect chain of a flow (see flow), for example the default input flow. Any number of flows may have captioning enabled at the same time.

Captions can be produced by different providers, see VsCaptionsProvider. A built-in provider is available when the license allows it, and requires no further setup. Alternatively, users can supply their own cloud credentials (Bring Your Own Cloud); in that case ConfigureCaptions must be called to configure the keys. The choice of provider also affects which features are available, such as speaker identification.

rpc ConfigureCaptions()

rpc ConfigureCaptions(VsConfigureCaptionsRequest) returns (VsCaptionsConfig);

Select the captioning provider and configure its credentials.

Sets the provider in config (see VsCaptionsProvider) and returns the resulting VsCaptionsConfig. The built-in provider needs no credentials. To use your own cloud account, select the Bring Your Own Cloud provider and supply the keys in byoc_auth.

rpc SubscribeCaptions()

rpc SubscribeCaptions(VsSubscribeCaptionsRequest) returns (VsSubscription);

Subscribe to captions.

Registers a subscription and returns a VsSubscription token. The token is then passed to ReceiveCaptions to open the stream and to UnsubscribeCaptions to cancel the subscription. Receiving is split into three methods for the same reason as SubscribeMessages.

The subscription covers every flow in the session that has captioning enabled.

rpc ReceiveCaptions()

rpc ReceiveCaptions(VsReceiveCaptionsRequest) returns (stream VsCaption);

Receive captions for a subscription.

Opens a stream of VsCaption for the subscription identified by subscription_token, previously obtained from SubscribeCaptions. The stream stays open until the subscription is cancelled with UnsubscribeCaptions, the session ends, or the call is cancelled.

Captions arrive from all flows covered by the subscription; the device_uid of each VsCaption identifies the audio stream it came from.

Captions include both partial and final messages, distinguished by is_partial. While a phrase is being spoken, several partial messages refine the text, followed by one final message when the phrase is complete.

The timecode is the position of the caption within the audio stream, measured from the moment captioning started on that flow.

Some fields depend on the provider. In particular, speaker identification (speaker) is only populated by providers that support it, and is otherwise left empty.

rpc UnsubscribeCaptions()

rpc UnsubscribeCaptions(VsUnsubscribeCaptionsRequest) returns (VsEmpty);

Cancel a caption subscription.

Cancels the subscription identified by subscription_token and closes its ReceiveCaptions stream. After this call the subscription_token is no longer valid.

message VsSubscribeCaptionsRequest

Input argument of SubscribeCaptions.

message VsSubscribeCaptionsRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;
}

message VsReceiveCaptionsRequest

Input argument of ReceiveCaptions.

message VsReceiveCaptionsRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Token returned by the matching subscribe call.
    string subscription_token = 2;
}

message VsUnsubscribeCaptionsRequest

Input argument of UnsubscribeCaptions.

message VsUnsubscribeCaptionsRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Token returned by the matching subscribe call.
    string subscription_token = 2;
}

message VsCaption

A single caption produced by captioning.

Streamed by ReceiveCaptions for a subscription created with SubscribeCaptions.

message VsCaption
{
    /// Device whose audio stream this caption was transcribed from.
    string device_uid = 1;

    /// Position of the caption within the audio stream, measured from the
    /// moment captioning started.
    google.protobuf.Duration timecode = 2;

    /// Label of the detected speaker, when speaker identification is available.
    /// Only populated by providers that support it, and otherwise left empty.
    string speaker = 3;

    /// Whether this is a partial caption. While a phrase is being spoken, it is
    /// delivered as a series of partial captions, each of which may hold an
    /// incomplete phrase, be inaccurate, and change as the speaker continues.
    /// The phrase ends with a single final caption (with \c is_partial set to
    /// \c false) that holds its settled text.
    bool is_partial = 4;

    /// Transcribed text of the caption.
    string text = 5;
}

message VsConfigureCaptionsRequest

Input argument of ConfigureCaptions.

message VsConfigureCaptionsRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Captioning configuration to apply. Required. See \ref VsCaptionsConfig.
    VsCaptionsConfig config = 2;
}

message VsCaptionsConfig

Captioning provider configuration.

Return value of ConfigureCaptions, also carried by its input argument VsConfigureCaptionsRequest. In a return value byoc_auth is never set, because the credentials are write-only.

message VsCaptionsConfig {
    /// Captioning provider to use. See \ref VsCaptionsProvider.
    VsCaptionsProvider provider = 1;

    /// Cloud credentials for the *Bring Your Own Cloud* provider. Required when
    /// \c provider is \c VS_CAPTIONS_PROVIDER_BYOC, and must be omitted
    /// otherwise. See \ref VsCaptionsAuth.
    optional VsCaptionsAuth byoc_auth = 2;
}

message VsCaptionsAuth

Credentials for the Bring Your Own Cloud captioning provider.

Supplies the keys of the user's own AWS account, used to access AWS Transcribe.

message VsCaptionsAuth
{
    /// AWS access key ID. Required and must be non-empty.
    string aws_access_key = 1;

    /// AWS secret access key. Required and must be non-empty.
    string aws_secret_key = 2;
}

enum VsCaptionsProvider

Captioning provider.

enum VsCaptionsProvider
{
    /// Built-in provider billed by ViveSound. Requires no credentials, but is
    /// only available when the license allows it.
    VS_CAPTIONS_PROVIDER_BILLED = 0;

    /// *Bring Your Own Cloud* provider that uses the user's own cloud account.
    /// Requires credentials to be supplied in \ref VsCaptionsConfig.byoc_auth.
    VS_CAPTIONS_PROVIDER_BYOC = 1;
}

Discovery

Devices are the audio endpoints provided by the operating system, such as speakers and microphones, that the engine manages. Input devices (for example microphones) and output devices (for example speakers) are reported separately, so a headset that both captures and plays audio appears as one input device and one output device.

Each device has a uid (see VsDevice) that is specific to the engine. It has a platform-independent format and is stable: the same device always has the same uid, even after it is disconnected and connected again. These UIDs name a device in VsRoute when configuring routes for an audio flow (see flow).

The set of available devices can change while the session is open, as devices are connected and disconnected. The engine reports each such change with a VS_EVENT_DEVICE_LIST_CHANGED event (see monitoring).

rpc ListDevices()

rpc ListDevices(VsListDevicesRequest) returns (VsDeviceList);

List the available audio devices.

Returns a VsDeviceList with the current input and output devices. Each entry is a VsDevice describing one device. Exactly one input device and one output device are marked with VS_DEVICE_FEATURE_DEFAULT, indicating the current system default for that direction.

message VsListDevicesRequest

Input argument of ListDevices.

message VsListDevicesRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;
}

message VsDeviceList

Return value of ListDevices.

Input and output devices are reported in separate lists. A device that both captures and plays audio appears once in each list and gets a different uid in each, because a uid identifies one direction of a device.

message VsDeviceList
{
    /// Input (capture) devices, such as microphones. Exactly one entry is
    /// marked with \c VS_DEVICE_FEATURE_DEFAULT.
    repeated VsDevice input_devices = 1;

    /// Output (playback) devices, such as speakers. Exactly one entry is
    /// marked with \c VS_DEVICE_FEATURE_DEFAULT.
    repeated VsDevice output_devices = 2;
}

message VsDevice

A single audio device.

message VsDevice
{
    /// Stable, engine-specific device identifier.
    ///
    /// This is *not* an operating-system device name. It has a
    /// platform-independent format and is derived by the engine so that the
    /// same physical device always keeps the same \c uid, even after it is
    /// disconnected and connected again. Use it in \ref VsRoute to route a
    /// flow to this device.
    string uid = 1;

    /// Operating-system audio backend that provides the device: Core Audio on
    /// macOS, WASAPI on Windows.
    VsDeviceDriver driver = 2;

    /// Platform-specific device identifier assigned by the operating system.
    ///
    /// On macOS this is the Core Audio device UID; on Windows it is the WASAPI
    /// endpoint ID. Its format is driver-dependent and may contain special
    /// characters. This is a low-level identifier, not a name meant for
    /// display; use \c uid to identify a device and \c display_name to present
    /// it to the user.
    string system_name = 3;

    /// Human-readable, one-line device title suitable for display.
    ///
    /// On macOS it is derived from the Core Audio data source or device name;
    /// on Windows it is the WASAPI endpoint friendly name. Not guaranteed to
    /// be unique.
    string display_name = 4;

    /// Device properties, as a bitwise OR of \ref VsDeviceFeature flags.
    uint64 feature_mask = 5;
}

enum VsDeviceDriver

Operating-system audio backend a device belongs to.

enum VsDeviceDriver
{
    /// Backend is unknown or unspecified.
    VS_DEVICE_DRIVER_UNSPECIFIED = 0;

    /// Core Audio, used on macOS.
    VS_DEVICE_DRIVER_COREAUDIO = 1;

    /// WASAPI, used on Windows.
    VS_DEVICE_DRIVER_WASAPI = 2;
}

enum VsDeviceFeature

Individual flags of VsDevice feature_mask.

The connection and type flags (for example VS_DEVICE_FEATURE_BLUETOOTH or VS_DEVICE_FEATURE_USB) are best-effort hints reported by the operating system.

enum VsDeviceFeature
{
    /// No flags set.
    VS_DEVICE_FEATURE_UNSPECIFIED = 0x000;

    /// Input (capture) device. Set for every device in
    /// \c VsDeviceList.input_devices.
    VS_DEVICE_FEATURE_INPUT = 0x001;

    /// Output (playback) device. Set for every device in
    /// \c VsDeviceList.output_devices.
    VS_DEVICE_FEATURE_OUTPUT = 0x002;

    /// Current system default device for its direction. Set on exactly one
    /// input and one output device.
    VS_DEVICE_FEATURE_DEFAULT = 0x004;

    /// Virtual device not backed by physical hardware.
    VS_DEVICE_FEATURE_VIRTUAL = 0x008;

    /// Microphone or speaker integrated into the computer itself, rather than
    /// an external or removable device.
    VS_DEVICE_FEATURE_BUILTIN = 0x010;

    /// Headphones or a headset. Headphones provide playback only, while a
    /// headset combines headphones with a microphone. May be connected in any
    /// way, such as a wired jack, USB, or Bluetooth.
    VS_DEVICE_FEATURE_HEADSET = 0x020;

    /// Connected via Bluetooth.
    VS_DEVICE_FEATURE_BLUETOOTH = 0x040;

    /// Connected via AirPlay.
    VS_DEVICE_FEATURE_AIRPLAY = 0x080;

    /// Connected via USB. This may be a USB audio device such as a USB headset,
    /// or a USB sound card, in which case the attached hardware (headset,
    /// speakers, and so on) is usually unknown.
    VS_DEVICE_FEATURE_USB = 0x100;

    /// Connected via Thunderbolt.
    VS_DEVICE_FEATURE_THUNDERBOLT = 0x200;

    /// Connected via HDMI.
    VS_DEVICE_FEATURE_HDMI = 0x400;

    /// Connected via DisplayPort.
    VS_DEVICE_FEATURE_DISPLAYPORT = 0x800;
}

Monitoring

An application can observe changes in the engine's state by subscribing to a stream of events.

Events can be initiated either by user actions, such as changing the configuration, or by the operating system, for example when a device is connected or disconnected.

The engine may coalesce several rapid changes of the same kind into a single event, so the number of events need not match the number of underlying changes.

rpc SubscribeEvents()

rpc SubscribeEvents(VsSubscribeEventsRequest) returns (VsSubscription);

Subscribe to engine events.

Registers a subscription and returns a VsSubscription token. The token is then passed to ReceiveEvents to open the stream and to UnsubscribeEvents to cancel the subscription. Receiving is split into three methods for the same reason as SubscribeMessages.

rpc ReceiveEvents()

rpc ReceiveEvents(VsReceiveEventsRequest) returns (stream VsEvent);

Receive events for a subscription.

Opens a stream of VsEvent for the subscription identified by subscription_token, previously obtained from SubscribeEvents. The stream stays open until the subscription is cancelled with UnsubscribeEvents, the session ends, or the call is cancelled.

Each VsEvent reports a single change through its event_code (see VsEventCode); the application then reads the new state through the relevant call.

rpc UnsubscribeEvents()

rpc UnsubscribeEvents(VsUnsubscribeEventsRequest) returns (VsEmpty);

Cancel an event subscription.

Cancels the subscription identified by subscription_token and closes its ReceiveEvents stream. After this call the subscription_token is no longer valid.

message VsSubscribeEventsRequest

Input argument of SubscribeEvents.

message VsSubscribeEventsRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;
}

message VsReceiveEventsRequest

Input argument of ReceiveEvents.

message VsReceiveEventsRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Token returned by the matching subscribe call.
    string subscription_token = 2;
}

message VsUnsubscribeEventsRequest

Input argument of UnsubscribeEvents.

message VsUnsubscribeEventsRequest
{
    /// Token returned by \ref OpenSession.
    string session_token = 1;

    /// Token returned by the matching subscribe call.
    string subscription_token = 2;
}

message VsEvent

A single event reporting a change in the engine's state.

Streamed by ReceiveEvents for a subscription created with SubscribeEvents.

An event carries no payload beyond its event_code and timestamp; it only signals that something changed. Subscribing reports later changes but not the current state.

The recommended flow is to call SubscribeEvents, then read desired state (e.g. device list), then call ReceiveEvents. On every event, re-read state and compare with the previous one for changes. This approach guarantees no event loss and no spurious events.

message VsEvent
{
    /// Point in time at which the engine emitted the event.
    google.protobuf.Timestamp timestamp = 1;

    /// What changed. See \ref VsEventCode.
    VsEventCode event_code = 2;
}

enum VsEventCode

Kind of change reported by a VsEvent.

enum VsEventCode
{
    /// The run mode changed; read the new value with \ref GetRunMode. This can
    /// happen after user interaction, for example a call to \ref SetRunMode, or
    /// on its own, for example when a license expires and the engine disables
    /// itself.
    VS_EVENT_RUN_MODE_CHANGED = 0;

    /// The license state changed; read the new state with \ref GetLicense. This
    /// can happen after user interaction, for example a call to
    /// \ref ActivateLicense, or on its own, for example when a license expires
    /// or the engine re-verifies it in the background.
    VS_EVENT_LICENSE_STATE_CHANGED = 1;

    /// The set of loaded plugins changed; read the new list with
    /// \ref ListPlugins. This can happen after user interaction, for example a
    /// call to \ref LoadPlugin or \ref UnloadPlugin, or on its own, for example
    /// when a plugin fails or its process exits.
    VS_EVENT_PLUGIN_LIST_CHANGED = 2;

    /// The set of available devices changed; read the new list with
    /// \ref ListDevices. This can happen after user interaction, for example
    /// connecting or disconnecting a device, or on its own, for example when
    /// the system default input or output device changes.
    VS_EVENT_DEVICE_LIST_CHANGED = 3;
}

Utility

message VsEmpty

Message that carries no data.

Return value of methods that report only success or failure and produce no other result.

message VsEmpty
{
}

message VsSubscription

Return value of the subscribe methods SubscribeMessages, SubscribeCaptions, and SubscribeEvents.

Identifies the newly created subscription. The token is passed to the matching receive and unsubscribe calls.

message VsSubscription
{
    /// Token identifying the subscription. Passed to the matching receive and
    /// unsubscribe calls.
    string subscription_token = 1;
}