// 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.hardware.audio;

using zx;

table RingBufferProperties {
    /// The driver's best estimate of the external delay (in nanoseconds) present in the
    /// presentation pipeline for the chosen format. When precisely synchronizing presentation
    /// across multiple entities (e.g. devices), the external delay should be taken into account.
    1: zx.duration external_delay;

    /// Size (in bytes) representing a temporary buffer used by the driver in order to consume or
    /// generate the ring buffer contents. The ring buffer contents must be produced and consumed
    /// at the rate specified with the `CreateRingBuffer` command, however some amount of buffering
    /// is required when the data is written into and read from the ring buffer. For playback the
    /// data is consumed by the driver by reading ahead up to `fifo_depth` bytes. For capture the
    /// data is produced by the driver holding up to `fifo_depth` bytes at the time before
    /// committing it to main system memory. Hence `fifo_depth` must be taken into account by the
    /// client when determining either the minimum lead time requirement (for playback) or the
    /// maximum capture delay (for capture).
    ///
    /// To convert `fifo_depth` to the corresponding number of audio frames, use the frame size
    /// returned by `CreateRingBuffer` in the `StreamConfig` protocol, note that the `fifo_depth`
    /// is not necessarily a multiple size of an audio frame.
    ///
    /// The ring buffer data may be directly consumed/generated by hardware, in this case
    /// `fifo_depth` maps directly to the size of a hardware FIFO block, since the hardware FIFO
    /// block determines the amount of data read ahead or held back.
    ///
    /// The ring buffer data may instead be consumed/generated by audio driver software that is
    /// conceptually situated between the ring buffer and the audio hardware. In this case, for
    /// playback the `fifo_depth` read ahead amount is set large enough such that the driver
    /// guarantees no undetected underruns, this assuming the client is generating the data as
    /// determined by the `CreateRingBuffer` and `Start` commands. For capture, the
    /// `fifo_depth` held back amount is set large enough such that the driver guarantees no
    /// undetected underruns when generating the data as determined by the `CreateRingBuffer` and
    /// `Start` commands. The driver must set `fifo_depth` big enough such that the potential
    /// delays added by any software interfacing with the audio hardware do not occur under most
    /// scenarios, and must detect and report underruns. How an underrun is reported is not defined
    /// in this API.
    2: uint32 fifo_depth;

    /// When set to true, indicates that clients need to make sure that their data has been flushed
    /// all the way to physical memory (in the case of playback) or that their view of the ring
    /// buffer will need to be invalidated before read (in the case of capture).
    3: bool needs_cache_flush_or_invalidate;
};

struct RingBufferPositionInfo {
    /// The driver's best estimate of the time at which the playback/capture pointer reached the
    /// position indicated by `position`.
    /// external_delay impact should not be incorporated into 'timestamp'.
    zx.time timestamp;

    /// The playback/capture pointer position (in bytes) in the ring buffer at time
    /// `timestamp` as estimated by the driver.
    uint32 position;
};

enum GetVmoError {
    /// The ring buffer setup failed due to an invalid argument, e.g. min_frames is too big.
    INVALID_ARGS = 1;

    /// The ring buffer setup failed due to an internal error.
    INTERNAL_ERROR = 2;
};

/// For an overview see
/// [Audio Driver Streaming Interface](//docs/concepts/drivers/driver_interfaces/audio_streaming.md)
protocol RingBuffer {
    /// Accessor for top level static properties.
    GetProperties() -> (RingBufferProperties properties);

    /// Gets the ring buffer current position via a hanging get. The driver must respond to a
    /// client's first `WatchClockRecoveryPositionInfo` call, but will not respond to subsequent
    /// client calls until the position information has changed from what was most recently
    /// provided to that client. The driver must not respond to a
    /// `WatchClockRecoveryPositionInfo` until after it has replied to the `Start` command. If
    /// `clock_recovery_notifications_per_ring` is not zero, the driver will reply with its
    /// estimated position to be used for clock recovery at most at
    /// `clock_recovery_notifications_per_ring` frequency.
    /// `WatchClockRecoveryPositionInfo` may only be called after `GetVmo` was called, hence a
    /// `clock_recovery_notifications_per_ring` was specified.
    /// Must be delivered with timestamps that are monotonically increasing.
    WatchClockRecoveryPositionInfo() -> (RingBufferPositionInfo position_info);

    /// Requests a shared buffer to be used for moving bulk audio data. Requests the buffer size to
    /// fit at least `min_frames`, and returns the actual `num_frames` allocated in
    /// `ring_buffer`.
    ///
    /// If `clock_recovery_notifications_per_ring` is non-zero, the driver will send replies to
    /// `WatchClockRecoveryPositionInfo` client requests at most at
    /// `clock_recovery_notifications_per_ring` frequency. These notifications are meant to be used
    /// for clock recovery.
    ///
    GetVmo(uint32 min_frames, uint32 clock_recovery_notifications_per_ring)
        -> (uint32 num_frames, zx.handle:VMO ring_buffer)
        error GetVmoError;

    /// Start the ring buffer. The `start_time` value (in the CLOCK_MONOTONIC timeline) indicates
    /// when position began moving, starting at the beginning of the ring buffer.
    /// external_delay impact should not be incorporated into 'start_time'.
    Start() -> (zx.time start_time);

    /// Stop the ring buffer. Once this call's response is received, no further position
    /// notifications will be sent until `Start` is called again.
    // TODO(fxbug.dev/39494): Add timestamp parameter.
    Stop() -> ();
};
