blob: 5b15cd9b657d30f134a1973893f228b74f03f3d6 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.virtualaudio;
using zx;
// fuchsia.virtualaudio.Forwarder
//
/// Using this Simple Layout (C-bound) protocol, an intermediary (such as the
/// virtual audio service) forwards FIDL protocol requests to the virtual audio
/// driver, which enables clients to use more full-featured (C++ based) bindings
/// with this driver -- specifically the Control, Input and Output protocols.
[Layout = "Simple"]
protocol Forwarder {
SendControl(request<Control> control);
SendInput(request<Input> input);
SendOutput(request<Output> output);
};
// fuchsia.virtualaudio.Control
//
/// This protocol provides the caller a high-level ON/OFF switch for overall
/// virtual audio functionality at the system level. When virtualaudio is
/// disabled, device configurations can be created and changed, but no devices
/// can be added. When virtualaudio is enabled, device configurations can again
/// be converted into devices by calling `Add()`.
[Discoverable]
protocol Control {
/// Allow inputs and outputs to be activated, but do not automatically
/// reactivate those previously deactivated by `Disable()`. Does not affect
/// existing Configs. By default, virtualaudio is enabled on system startup.
/// This method's callback can be used as a mechanism to synchronize with
/// other asynchronous in-flight virtualaudio FIDL operations.
Enable() -> ();
/// Deactivate all active inputs/outputs; disallow subsequent activations.
/// This method's callback can be used as a mechanism to synchronize with
/// other asynchronous in-flight virtualaudio FIDL operations.
Disable() -> ();
};
///
/// The Input and Output protocols closely correspond to the capabilities
/// exposed by the Audio Driver Streaming Interface, fully documented at
/// driver-interfaces/audio.md and declared at device/audio.h.
///
// fuchsia.virtualaudio.Input
//
/// This protocol represents an active virtual audio input device. It inherits
/// the parent protocols Device and Configuration. This protocol, as well as the
/// contents of Device, represent actions that can be taken by an active input
/// device -- actions that should be immediately detected and reacted upon by
/// the audio subsystem.
[Discoverable]
protocol Input {
compose Device;
// TODO(mpuryear): `SetCaptureSignal()` -- indicate what to "capture".
// E.g. sinusoid, constant, square, ramp, saw, noise. Can differ by channel.
// TODO(mpuryear): `PairWithOutput()` -- client passes an output (server)
// binding; input device returns as captured data the streamed output data.
};
// fuchsia.virtualaudio.Output
//
/// This protocol represents an active virtual audio output device. It inherits
/// the parent protocols Device and Configuration. This protocol, as well as the
/// contents of Device, represent actions that can be taken by an active output
/// device -- actions that should be immediately detected and reacted upon by
/// the audio subsystem.
[Discoverable]
protocol Output {
compose Device;
// TODO(mpuryear): any render-specific configuration or runtime triggers.
};
/// This protocol represents the base functionality of active Input and Output
/// audio devices -- methods that are common to both protocols. This protocol,
/// as well as the contents of Output and Input, represent actions that can be
/// taken by an active device -- actions that should be immediately detected and
/// reacted upon by the audio subsystem.
[FragileBase]
protocol Device {
compose Configuration;
/// Activate (`DdkAdd`) the virtual audio device as currently configured. A
/// device node will be published and detected by the AudioDeviceManager,
/// and a driver for the virtual device will be loaded and queried. Device
/// arrivals are exposed to clients by the
/// `fuchsia.media.AudioDeviceEnumerator` protocol, in `GetDevices()` and
/// the `->OnDeviceAdded()` event.
Add();
/// Deactivate (`DdkRemove`) the active virtual audio device, but retain its
/// configuration for future activation. The driver for the virtual device
/// will be unloaded, and the device node closed. Device removals are
/// exposed to clients by `fuchsia.media.AudioDeviceEnumerator`, in
/// `GetDevices()` and `->OnDeviceRemoved()`.
Remove();
/// Return the format selected by the client, when that client issued an
/// `AUDIO_STREAM_CMD_SET_FORMAT` command. This can only occur after a
/// device has been added, and is only allowed to occur before the device's
/// ring buffer has been returned (i.e., before an
/// `AUDIO_RB_CMD_GET_BUFFER` command).
GetFormat() -> (uint32 frames_per_second, uint32 sample_format,
uint32 num_channels, zx.duration external_delay);
/// Notify all subscribed listeners when the above format is set or changed.
-> OnSetFormat(uint32 frames_per_second, uint32 sample_format,
uint32 num_channels, zx.duration external_delay);
/// Return the current gain state for this device. After a device has been
/// added, a client can call this at any time -- even before the ring buffer
/// has been established, or before the format has been set.
GetGain() -> (bool current_mute, bool current_agc, float32 current_gain_db);
/// Notify all subscribed listeners when the above gain is set or changed.
-> OnSetGain(bool current_mute, bool current_agc, float32 current_gain_db);
/// Return details about the ring buffer that was established in response
/// to a client `AUDIO_RB_CMD_GET_BUFFER` command. This will only occur
/// after the client sets the format and retrieves other driver information.
GetBuffer() -> (handle<vmo> ring_buffer, uint32 num_ring_buffer_frames,
uint32 notifications_per_ring);
/// Notify all subscribed listeners when the above buffer has been created.
-> OnBufferCreated(handle<vmo> ring_buffer, uint32 num_ring_buffer_frames,
uint32 notifications_per_ring);
/// Override the position notification frequency set by AudioCore for this
/// stream, with the given value. Although this method can be called at any
/// time (including before this Input|Output is added, or after it is
/// started), logically it makes most sense to call this immediately after
/// receiving details about the just-created ring buffer, via `GetBuffer` or
/// the `->OnBufferCreated` event.
SetNotificationFrequency(uint32 notifications_per_ring);
/// Notify all subscribed listeners when the device is commanded to Start
/// streaming. This can only occur after a device is fully configured
/// (format is set; ring buffer is established and fetched).
-> OnStart(zx.time start_time);
/// Notify all subscribed listeners when the device is commanded to Stop
/// streaming. This can only occur when the device is already Started. Stop
/// returns the device to a fully-configured state. Upon this command, the
/// already-set format and ring buffer are retained without change, but
/// position will re-begin at 0, if the device is again Started.
-> OnStop(zx.time stop_time, uint32 ring_position);
/// Return the current position (in bytes) within the ring buffer. This can
/// only be called after the ring buffer is established. If the device has
/// not yet Started streaming, then zero will always be returned.
GetPosition() -> (uint32 ring_position, zx.time clock_time);
/// Notify all subscribed listeners, when any `AUDIO_RB_POSITION_NOTIFY`
/// position notification is issued by the driver. The frequency of these
/// per-stream notifications is set by AudioCore, reported to VAD clients
/// via `GetBuffer` or the `->OnBufferCreated` event. VirtualAudioDevice
/// clients can enable an alternate notification frequency for a given
/// stream by calling `SetNotificationFrequency`.
-> OnPositionNotify(uint32 ring_position, zx.time clock_time);
/// Hot-plug or hot-unplug an active virtual device, at the specified time.
/// For devices marked as capable of asynchronously notifying the system of
/// plug changes, the driver will now send the values using
/// `AUDIO_STREAM_PLUG_DETECT_NOTIFY`. Else, values will be reflected when
/// the driver is next sent an `AUDIO_STREAM_CMD_PLUG_DETECT` command. This
/// information is used by the system when determining which device is
/// default. This, in turn, is exposed to clients by the
/// `fuchsia.media.AudioDeviceEnumerator` protocol: in `GetDevices()`,
/// `GetDefaultInputDevice()`/`GetDefaultOutputDevice()` and the
/// `->OnDefaultDeviceChanged()` event.
ChangePlugState(zx.time plug_change_time, bool plugged);
// TODO(mpuryear): `TweakClockRate(uint64 numerator, uint64 denominator)` --
// emulating a device clock, advance position at given ratio of MONOTONIC.
};
/// This protocol is conceptually a base protocol to Device. It exposes the
/// methods used to specify the properties of a virtual audio device (its
/// configuration), before the virtual device is instantiated by the call to
/// `Add()`. Although the non-Add methods on this protocol can be called after
/// calling `Add()` (i.e., after Configuration has been converted into active
/// Device), this only changes how future Devices will be created; it has no
/// effect on already-created Devices.
[FragileBase]
protocol Configuration {
/// Set the virtual audio device's name. This corresponds to the value
/// associated with the device node for this virtual device. This must be
/// called before calling `Add()`, or after `Remove()`.
SetDeviceName(string device_name);
/// Set the virtual audio device's manufacturer name. This must be called
/// before calling `Add()`, or after `Remove()`. Once a device is activated,
/// this value is returned by the driver in response to an
/// `AUDIO_STREAM_CMD_GET_STRING` command of string ID
/// `AUDIO_STREAM_STR_ID_MANUFACTURER`. This information is exposed to
/// clients by the `fuchsia.media.AudioDeviceEnumerator` protocol: returned
/// in an `AudioDeviceInfo` struct by `GetDevices()` and the
/// `->OnDeviceAdded()` event.
SetManufacturer(string manufacturer_name);
/// Set the virtual audio device's product name. This must be called before
/// calling `Add()`, or after `Remove()`. Once the device is activated, this
/// value is returned by the driver in response to an
/// `AUDIO_STREAM_CMD_GET_STRING` command of string ID
/// `AUDIO_STREAM_STR_ID_PRODUCT`. This information is exposed to clients by
/// the `fuchsia.media.AudioDeviceEnumerator` protocol: returned in an
/// `AudioDeviceInfo` struct by `GetDevices()` and the `->OnDeviceAdded()`
/// event.
SetProduct(string product_name);
/// Set the virtual audio device's unique ID, a 16-character string. This
/// must be called before calling `Add()`, or after `Remove()`. Once the
/// device is activated, this value is returned by the driver in response
/// to an `AUDIO_STREAM_CMD_GET_UNIQUE_ID` command. This value is exposed
/// to clients by the `fuchsia.media.AudioDeviceEnumerator` protocol:
/// returned in an `AudioDeviceInfo` struct by `GetDevices()` or
/// `->OnDeviceAdded()`.
SetUniqueId(array<uint8>:16 unique_id);
/// Add a supported format range for this audio device. This must be called
/// before calling `Add()`, or after `Remove()`. Once the device is
/// activated, format ranges are returned by the driver in response to an
/// `AUDIO_STREAM_CMD_GET_FORMATS` command. sample_format_flags is of type
/// audio_sample_format_t, and rate_family_flags is a bit field of possible
/// constants beginning with ASF_RANGE_FLAG_FPS_. See audio.h for details.
AddFormatRange(uint32 sample_format_flags, uint32 min_frame_rate,
uint32 max_frame_rate, uint8 min_channels,
uint8 max_channels, uint16 rate_family_flags);
/// Remove the minimal format range that is added by default to all
/// configurations. As with `AddFormatRange()`, this method must be called
/// before calling `Add()`, or after `Remove()`.
ClearFormatRanges();
/// Set the virtual audio device's fifo depth, in bytes. This must be called
/// before calling `Add()`, or after `Remove()`. Once the device is
/// activated, the depth of its FIFO is returned by the driver in response
/// to an `AUDIO_RB_CMD_GET_FIFO_DEPTH` command on the ring buffer channel.
SetFifoDepth(uint32 fifo_depth_bytes);
/// Set the virtual audio device's external delay, in nanoseconds. This must
/// be called before calling `Add()`, or after `Remove()`. Once the device
/// is activated, this value is returned by the driver in response to an
/// `AUDIO_STREAM_CMD_SET_FORMAT` command.
//
// Treating this as a static property is inadequate, considering that the
// delay is intended to be calculated from the format that was just set.
SetExternalDelay(zx.duration external_delay);
/// Set restrictions for the device ring buffer. This must be called before
/// calling `Add()`, or after `Remove()`. Once the device is activated, the
/// ring buffer and its size are returned by the driver in response to an
/// `AUDIO_RB_CMD_GET_BUFFER` command on the ring buffer channel.
/// Note: both min_frames and max_frames must be multiples of modulo_frames.
SetRingBufferRestrictions(uint32 min_frames, uint32 max_frames,
uint32 modulo_frames);
/// Set gain properties for this virtual device. This must be called before
/// calling `Add()`, or after `Remove()`. Once the device is activated, gain
/// information is returned by the driver in an
/// `audio_stream_cmd_get_gain_resp` struct, in response to an
/// `AUDIO_STREAM_CMD_GET_GAIN` command. This information is exposed to
/// clients by the `fuchsia.media.AudioDeviceEnumerator` protocol: returned
/// in an `AudioGainInfo` struct by `GetDeviceGain()` and the
/// `->OnDeviceGainChanged()` event.
SetGainProperties(float32 min_gain_db, float32 max_gain_db,
float32 gain_step_db, float32 current_gain_db,
bool can_mute, bool current_mute,
bool can_agc, bool current_agc);
/// Set plug properties for this virtual device. This must be called before
/// calling `Add()`, or after `Remove()`. Once the device is activated, plug
/// information is returned by the driver in response to an
/// `AUDIO_STREAM_CMD_PLUG_DETECT `command. This information is used by the
/// system when determining which device is default. This in turn is exposed
/// to clients by the `fuchsia.media.AudioDeviceEnumerator` protocol: in
/// `GetDevices()`, `GetDefaultInputDevice()`/`GetDefaultOutputDevice()` and
/// the `->OnDefaultDeviceChanged()` event.
SetPlugProperties(zx.time plug_change_time, bool plugged, bool hardwired,
bool can_notify);
/// Return a configuration to its default settings. This call has no effect
/// on active devices. In other words, it must be called before calling
/// `Add()`, or after `Remove()`.
ResetConfiguration();
};