blob: 95ed3ec0854efb423b8aebb0ca209d213550423d [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;
const MAX_UI_STRING_SIZE uint32 = 256;
// 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.
@for_deprecated_c_bindings
protocol Forwarder {
SendControl(resource struct {
control server_end:Control;
});
SendInput(resource struct {
input server_end:Input;
});
SendOutput(resource struct {
output server_end: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() -> ();
/// Return the number of active input and output virtual devices.
/// This method's callback can be used as a mechanism to synchronize with
/// other asynchronous in-flight virtualaudio FIDL operations.
GetNumDevices() -> (struct {
num_input_devices uint32;
num_output_devices uint32;
});
};
//
// 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.
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() -> (struct {
frames_per_second uint32;
sample_format uint32;
num_channels uint32;
external_delay zx.duration;
});
/// Notify all subscribed listeners when the above format is set or changed.
-> OnSetFormat(struct {
frames_per_second uint32;
sample_format uint32;
num_channels uint32;
external_delay zx.duration;
});
/// 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() -> (struct {
current_mute bool;
current_agc bool;
current_gain_db float32;
});
/// Notify all subscribed listeners when the above gain is set or changed.
-> OnSetGain(struct {
current_mute bool;
current_agc bool;
current_gain_db float32;
});
/// 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() -> (resource struct {
ring_buffer zx.handle:VMO;
num_ring_buffer_frames uint32;
notifications_per_ring uint32;
});
/// Notify all subscribed listeners when the above buffer has been created.
-> OnBufferCreated(resource struct {
ring_buffer zx.handle:VMO;
num_ring_buffer_frames uint32;
notifications_per_ring uint32;
});
/// 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(struct {
notifications_per_ring uint32;
});
/// 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(struct {
start_time zx.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(struct {
stop_time zx.time;
ring_position uint32;
});
/// Return the current position (in bytes) within the ring buffer, along
/// with the time (per MONOTONIC clock) that corresponds with that position.
/// 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() -> (struct {
monotonic_time zx.time;
ring_position uint32;
});
/// 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`. As with a direct call to
/// `GetPosition`, the returned parameters are the current position (in
/// bytes) in the ring buffer, as well as the time (per MONOTONIC clock)
/// that corresponds with that ring buffer position.
-> OnPositionNotify(struct {
monotonic_time zx.time;
ring_position uint32;
});
/// 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(struct {
plug_change_time zx.time;
plugged bool;
});
/// Immediately change the virtual device's clock rate, as expressed in the
/// timing and content of position notifications the driver emits.
/// 'ppm_monotonic' cannot exceed [-1000,+1000]. Each rate change in rate is
/// standalone; i.e. successive rate changes are not cumulative.
AdjustClockRate(struct {
ppm_from_monotonic int32;
});
};
/// 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.
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(struct {
device_name string;
});
/// Set the virtual audio device's manufacturer name. Must be called before
/// `Add()` or after `Remove()`. After device activation, the driver returns
/// this value in response to an `AUDIO_STREAM_CMD_GET_STRING` command of ID
/// `AUDIO_STREAM_STR_ID_MANUFACTURER`. This is exposed to clients via the
/// `fuchsia.media.AudioDeviceEnumerator` protocol, in an `AudioDeviceInfo`
/// struct returned from `GetDevices()` and the `->OnDeviceAdded()` event.
SetManufacturer(struct {
manufacturer_name string:MAX_UI_STRING_SIZE;
});
/// Set the virtual audio device's product name. This must be called before
/// `Add()` or after `Remove()`. After device activation, the driver returns
/// this value in response to an `AUDIO_STREAM_CMD_GET_STRING` command of ID
/// `AUDIO_STREAM_STR_ID_PRODUCT`. This name is exposed to clients via the
/// `fuchsia.media.AudioDeviceEnumerator` protocol, in an `AudioDeviceInfo`
/// struct returned from `GetDevices()` and the `->OnDeviceAdded()` event.
SetProduct(struct {
product_name string:MAX_UI_STRING_SIZE;
});
/// 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(struct {
unique_id array<uint8, 16>;
});
/// 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(struct {
sample_format_flags uint32;
min_frame_rate uint32;
max_frame_rate uint32;
min_channels uint8;
max_channels uint8;
rate_family_flags uint16;
});
/// 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();
@transitional
SetClockDomain(struct {
clock_domain int32;
});
/// Set properties for this virtual device's clock. These include the clock
/// domain and the initial rate difference (in ppm) between its clock and
/// the local monotonic clock. The clock domain is an int32 provided by the
/// clock tree to an audio driver; special values for CLOCK_DOMAIN_MONOTONIC
/// [0], and CLOCK_DOMAIN_EXTERNAL [-1] (not locally controllable) are
/// defined in fuchsia.hardware.audio/stream.fidl. Other than -1, any
/// negative value for clock_domain is invalid and will be ignored. A
/// non-zero value for 'initial_rate_adjustment_ppm' is only valid (and will
/// only be accepted) if the clock_domain is NOT equal to 0. This method
/// must be called before calling `Add()`, or after `Remove()`. Once the
/// device is activated, the clock_domain value is returned by the driver in
/// response to an `AUDIO_STREAM_CMD_GET_CLOCK_DOMAIN` command, and the
/// clock rate is expressed in the timing, and values, of position
/// notifications. Neither clock domain nor position notifications are
/// directly exposed to clients by public APIs, but these are both used in
/// AudioCore's device (or more accurately, domain) clock recovery.
SetClockProperties(struct {
clock_domain int32;
initial_rate_adjustment_ppm int32;
});
/// 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(struct {
fifo_depth_bytes uint32;
});
/// 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(struct {
external_delay zx.duration;
});
/// 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(struct {
min_frames uint32;
max_frames uint32;
modulo_frames uint32;
});
/// 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(struct {
min_gain_db float32;
max_gain_db float32;
gain_step_db float32;
current_gain_db float32;
can_mute bool;
current_mute bool;
can_agc bool;
current_agc bool;
});
/// 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(struct {
plug_change_time zx.time;
plugged bool;
hardwired bool;
can_notify bool;
});
/// 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();
};