// Copyright 2018 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.media;

using fuchsia.hardware.audio;

type AudioGainInfoFlags = strict bits : uint32 {
    MUTE = 0x01;
    AGC_SUPPORTED = 0x02;
    AGC_ENABLED = 0x04;
};

type AudioGainInfo = struct {
    gain_db float32;
    flags AudioGainInfoFlags;
};

type AudioDeviceInfo = struct {
    name string;
    unique_id string;
    token_id uint64;
    is_input bool;

    // We include these during device enumeration to reduce server round-trip
    // calls, and to simplify a user's state machine when determining current
    // device state during initial enumeration.
    gain_info AudioGainInfo;
    is_default bool;
};

type AudioGainValidFlags = strict bits : uint32 {
    GAIN_VALID = 0x01;
    MUTE_VALID = 0x02;
    AGC_VALID = 0x04;
};

@discoverable
protocol AudioDeviceEnumerator {
    /// Obtain the list of currently active audio devices.
    GetDevices() -> (struct {
        devices vector<AudioDeviceInfo>;
    });

    /// Events sent when devices are added or removed, or when properties of a
    /// device change.
    //
    // TODO(mpuryear): Should we have a set of filters which control which of
    // these events a user receives?
    //
    // Pro: Having filters like this removes the need for the server to send
    // messages to clients who don't care. In particular, it seems likely that a
    // client who just called SetDeviceGain will not care about the
    // OnDeviceGainChanged event being fired.
    //
    // Con: Having filters like this means that the server needs to maintain a
    // bit more per-client state.
    -> OnDeviceAdded(struct {
        device AudioDeviceInfo;
    });
    -> OnDeviceRemoved(struct {
        device_token uint64;
    });
    -> OnDeviceGainChanged(struct {
        device_token uint64;
        gain_info AudioGainInfo;
    });
    @deprecated
    -> OnDefaultDeviceChanged(struct {
        old_default_token uint64;
        new_default_token uint64;
    });

    /// Gain/Mute/AGC control
    ///
    /// Note that each of these operations requires a device_token in order to
    /// target the proper input/output.
    ///
    /// The Get command returns the device_token of the device whose gain is
    /// being reported, or `ZX_KOID_INVALID` in the case that the requested
    /// device_token was invalid or the device had been removed from the system
    /// before the Get command could be processed.
    ///
    /// Set commands which are given an invalid device token are ignored and
    /// have no effect on the system. In addition, users do not need to control
    /// all of the gain settings for an audio device with each call. Only the
    /// settings with a corresponding flag set in the set_flags parameter will
    /// be affected. For example, passing SetAudioGainFlag_MuteValid will cause
    /// a SetDeviceGain call to care only about the mute setting in the
    /// gain_info structure, while passing (SetAudioGainFlag_GainValid |
    /// SetAudioGainFlag_MuteValid) will cause both the mute and the gain
    /// status to be changed simultaneously.
    GetDeviceGain(struct {
        device_token uint64;
    }) -> (struct {
        device_token uint64;
        gain_info AudioGainInfo;
    });
    SetDeviceGain(struct {
        device_token uint64;
        gain_info AudioGainInfo;
        valid_flags AudioGainValidFlags;
    });

    //
    // TODO(mpuryear): solidify the concept of "default" device. Right now, it
    // basically means the device which would be chosen as the destination of an
    // AudioRenderer stream (or the source for an AudioCapturer stream), in the
    // absence of...
    //
    // 1) Any manual routing configuration imposed by the user.
    // 2) Any property based routing decision made by the audio service.
    //
    // Currently, this translates to "the default inputs/output will be the last
    // plugged input/output". As the human level logic which drives the audio
    // routing policy evolves and becomes more complicated, this will probably
    // change.
    /// Default Device
    ///
    /// Fetch the device ID of the current default input or output device, or
    /// `ZX_KOID_INVALID` if no such device exists.
    @deprecated
    @transitional
    GetDefaultInputDevice() -> (struct {
        device_token uint64;
    });
    @deprecated
    @transitional
    GetDefaultOutputDevice() -> (struct {
        device_token uint64;
    });

    AddDeviceByChannel(resource struct {
        device_name string:256;
        is_input bool;
        channel client_end:fuchsia.hardware.audio.StreamConfig;
    });
};
