| // 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; |
| const MAX_FORMAT_RANGES uint32 = 64; |
| |
| const CONTROL_NODE_NAME string = "/dev/sys/platform/00:00:2f/virtual_audio"; |
| |
| /// This protocol provides methods for adding and removing virtual audio |
| /// devices. This protocol is made available through the device tree via |
| /// `CONTROL_NODE_NAME`. |
| protocol Control { |
| /// Adds an input device to the device tree. |
| /// The device lives until the `Device` FIDL channel is closed. |
| AddInput(resource struct { |
| config Configuration; |
| server server_end:Device; |
| }) -> (struct {}) error Error; |
| |
| /// Adds an output device to the device tree. |
| /// The device lives until the `Device` FIDL channel is closed. |
| AddOutput(resource struct { |
| config Configuration; |
| server server_end:Device; |
| }) -> (struct {}) error Error; |
| |
| /// Returns the number of active input and output virtual devices. |
| GetNumDevices() -> (struct { |
| num_input_devices uint32; |
| num_output_devices uint32; |
| }); |
| |
| /// Synchronously remove all all active input and output devices. |
| RemoveAll() -> (); |
| }; |
| |
| /// Configures a virtual audio device. |
| type Configuration = table { |
| /// Device's name. |
| /// If not specified, a default name is used. |
| 1: device_name string:MAX_UI_STRING_SIZE; |
| |
| /// Device manufacturor's name. |
| /// If not specified, a default manufacturer name is used. |
| 2: manufacturer_name string:MAX_UI_STRING_SIZE; |
| |
| /// Device product's. |
| /// If not specified, a default product name is used. |
| 3: product_name string:MAX_UI_STRING_SIZE; |
| |
| /// Device's unique identifier, a 16 byte string. |
| /// If not specified, a default ID is used. |
| 4: unique_id array<uint8, 16>; |
| |
| /// FIFO depth in bytes. |
| /// If not specified, defaults to an arbitrary amount. |
| 5: fifo_depth_bytes uint32; |
| |
| /// External delay. |
| /// If not specified, defaults to an arbitrary duration. |
| 6: external_delay zx.duration; |
| |
| /// Supported format ranges for this virtual audio device. |
| /// If empty, supports only a 48kHz stereo int16 format by default. |
| 7: supported_formats vector<FormatRange>:MAX_FORMAT_RANGES; |
| |
| /// Configuration for the device's clock. |
| /// If not specified, use the domain of the monotonic clock. |
| 8: clock_properties ClockProperties; |
| |
| /// Constraints on the ring buffer. |
| /// If not specified, there are no constraints. |
| 9: ring_buffer_constraints RingBufferConstraints; |
| |
| /// Configuration of the device gain. |
| /// If not specified, the device has unity gain and cannot mute, enable AGC, |
| /// or change gain. |
| 10: gain_properties GainProperties; |
| |
| /// Configuration of the device's plug state. |
| /// If not specified, the device starts plugged in, with plug notifications |
| /// enabled, and is not hardwired. |
| 11: plug_properties PlugProperties; |
| |
| /// Initial notification frequency. |
| /// This can be changed later with SetNotificationFrequency. |
| 12: initial_notifications_per_ring uint32; |
| }; |
| |
| type FormatRange = struct { |
| /// Has type audio_sample_format_t (see zircon/device/audio.h) |
| sample_format_flags uint32; |
| |
| min_frame_rate uint32; |
| max_frame_rate uint32; |
| min_channels uint8; |
| max_channels uint8; |
| |
| /// Bitfield of `ASF_RANGE_FLAG_FPS_*` flags (see zircon/device/audio.h) |
| rate_family_flags uint16; |
| }; |
| |
| type ClockProperties = struct { |
| /// 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`. Other than -1, any negative value |
| /// for clock_domain is invalid and will be ignored. |
| domain int32; |
| |
| /// Initial rate-adjustment value for this clock. May be non-zero only if |
| /// `clock_domain != 0`. |
| initial_rate_adjustment_ppm int32; |
| }; |
| |
| /// 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. |
| type RingBufferConstraints = struct { |
| /// The ring buffer must have at least this many frames. |
| /// Must be a multiple of `modulo_frames`. |
| min_frames uint32; |
| |
| /// The ring buffer can have at most this many frames. |
| /// Must be a multiple of `modulo_frames`. |
| max_frames uint32; |
| |
| /// The ring buffer must have a multiple of this many frames. |
| /// Cannot be zero. |
| modulo_frames uint32; |
| }; |
| |
| type GainProperties = 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; |
| }; |
| |
| type PlugProperties = struct { |
| plug_change_time zx.time; |
| plugged bool; |
| hardwired bool; |
| can_notify bool; |
| }; |
| |
| /// This protocol represents the base functionality of active audio devices. A |
| /// device is active until this protocol is closed, at which point the device is |
| /// automatically removed. |
| protocol Device { |
| /// Returns the format selected by the client, or `NO_RING_BUFFER` if the |
| /// client has not yet selected a ring buffer format. |
| GetFormat() -> (struct { |
| frames_per_second uint32; |
| sample_format uint32; |
| num_channels uint32; |
| external_delay zx.duration; |
| }) error Error; |
| |
| /// Notifies 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; |
| }); |
| |
| /// Returns the current gain state for this device. |
| GetGain() -> (struct { |
| current_mute bool; |
| current_agc bool; |
| current_gain_db float32; |
| }); |
| |
| /// Notifies all subscribed listeners when the above gain is set or changed. |
| -> OnSetGain(struct { |
| current_mute bool; |
| current_agc bool; |
| current_gain_db float32; |
| }); |
| |
| /// Returns details about the ring buffer. Returns `NO_RING_BUFFER` if the |
| /// client has not yet created the ring buffer. |
| GetBuffer() -> (resource struct { |
| ring_buffer zx.handle:VMO; |
| num_ring_buffer_frames uint32; |
| notifications_per_ring uint32; |
| }) error Error; |
| |
| /// Notifies 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; |
| }); |
| |
| /// Overrides the position notification frequency for this stream. |
| /// This affects the frequency of `OnPositionNotify` events only. It does |
| /// not affect the frequency of notification events sent through the audio |
| /// driver APIs. |
| SetNotificationFrequency(struct { |
| notifications_per_ring uint32; |
| }); |
| |
| /// Notifies 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; |
| }); |
| |
| /// Notifies 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; |
| }); |
| |
| /// Returns 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. Returns |
| /// `NOT_STARTED` if the device has not yet Started streaming. |
| GetPosition() -> (struct { |
| monotonic_time zx.time; |
| ring_position uint32; // position in bytes |
| }) error Error; |
| |
| /// Notifies all subscribed listeners when any position notification is |
| /// issued by the driver. The frequency of these per-stream notifications is |
| /// set by whoever opened the device,, though the frequency can be overriden |
| /// by `SetNotificationFrequency`. |
| -> OnPositionNotify(struct { |
| monotonic_time zx.time; |
| ring_position uint32; // position in bytes |
| }); |
| |
| /// Hot-plugs or hot-unplugs an active virtual device, at the specified |
| /// time. |
| 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; |
| }); |
| }; |
| |
| type Error = flexible enum { |
| /// Unknown internal error occurred. |
| INTERNAL = 1; |
| |
| /// The ring buffer has not been created yet. |
| NO_RING_BUFFER = 2; |
| |
| /// The device has not yet started streaming. |
| NOT_STARTED = 3; |
| }; |