// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// The <code>chrome.audio</code> API is provided to allow users to
// get information about and control the audio devices attached to the
// system. This API is currently only implemented for ChromeOS.
namespace audio {

  // Type of stream an audio device provides.
  enum StreamType {
    INPUT,
    OUTPUT
  };

  // Available audio device types.
  enum DeviceType {
    HEADPHONE,
    MIC,
    USB,
    BLUETOOTH,
    HDMI,
    INTERNAL_SPEAKER,
    INTERNAL_MIC,
    FRONT_MIC,
    REAR_MIC,
    KEYBOARD_MIC,
    HOTWORD,
    LINEOUT,
    POST_MIX_LOOPBACK,
    POST_DSP_LOOPBACK,
    OTHER
  };

  [nodoc, deprecated = "Used only with the deprecated $(ref:getInfo)."]
  dictionary OutputDeviceInfo {
    // The unique identifier of the audio output device.
    DOMString id;
    // The user-friendly name (e.g. "Bose Amplifier").
    DOMString name;
    // True if this is the current active device.
    boolean isActive;
    // True if this is muted.
    boolean isMuted;
    // The output volume ranging from 0.0 to 100.0.
    double volume;
  };

  [nodoc, deprecated = "Used only with the deprecated $(ref:getInfo)."]
  dictionary InputDeviceInfo {
    // The unique identifier of the audio input device.
    DOMString id;
    // The user-friendly name (e.g. "USB Microphone").
    DOMString name;
    // True if this is the current active device.
    boolean isActive;
    // True if this is muted.
    boolean isMuted;
    // The input gain ranging from 0.0 to 100.0.
    double gain;
  };

  dictionary AudioDeviceInfo {
    // The unique identifier of the audio device.
    DOMString id;
    // Stream type associated with this device.
    StreamType streamType;
    // Type of the device.
    DeviceType deviceType;
    // The user-friendly name (e.g. "USB Microphone").
    DOMString displayName;
    // Device name.
    DOMString deviceName;
    // True if this is the current active device.
    boolean isActive;
    // The sound level of the device, volume for output, gain for input.
    long level;
    // The stable/persisted device id string when available.
    DOMString? stableDeviceId;
  };

  dictionary DeviceFilter {
    // If set, only audio devices whose stream type is included in this list
    // will satisfy the filter.
    StreamType[]? streamTypes;

    // If set, only audio devices whose active state matches this value will
    // satisfy the filter.
    boolean? isActive;
  };

  dictionary DeviceProperties {
    // True if this is muted.
    [nodoc, deprecated="Use $(ref:setMute) to set mute state."]
    boolean? isMuted;

    // If this is an output device then this field indicates the output volume.
    // If this is an input device then this field is ignored.
    [nodoc, deprecated="Use |level| to set output volume."] double? volume;

    // If this is an input device then this field indicates the input gain.
    // If this is an output device then this field is ignored.
    [nodoc, deprecated="Use |level| to set input gain."] double? gain;
 
    // <p>
    //   The audio device's desired sound level. Defaults to the device's
    //   current sound level.
    // </p> 
    // <p>If used with audio input device, represents audio device gain.</p>
    // <p>If used with audio output device, represents audio device volume.</p>
    long? level;
  };

  dictionary DeviceIdLists {
    // <p>List of input devices specified by their ID.</p>
    // <p>To indicate input devices should be unaffected, leave this property
    //   unset.</p>
    DOMString[]? input;

    // <p>List of output devices specified by their ID.</p>
    // <p>To indicate output devices should be unaffected, leave this property
    //   unset.</p>
    DOMString[]? output;
  };

  dictionary MuteChangedEvent {
    // The type of the stream for which the mute value changed. The updated mute
    // value applies to all devices with this stream type.
    StreamType streamType;

    // Whether or not the stream is now muted.
    boolean isMuted;
  };

  dictionary LevelChangedEvent {
    // ID of device whose sound level has changed.
    DOMString deviceId;

    // The device's new sound level.
    long level;
  };

  callback GetInfoCallback = void(OutputDeviceInfo[] outputInfo,
                                  InputDeviceInfo[] inputInfo);
  callback GetDevicesCallback = void(AudioDeviceInfo[] devices);
  callback GetMuteCallback = void(boolean value);
  callback EmptyCallback = void();

  interface Functions {
    // Gets a list of audio devices filtered based on |filter|.
    // |filter|: Device properties by which to filter the list of returned
    //     audio devices. If the filter is not set or set to <code>{}</code>,
    //     returned device list will contain all available audio devices.
    // |callback|: Reports the requested list of audio devices. 
    static void getDevices(optional DeviceFilter filter,
                           GetDevicesCallback callback);

    // Sets lists of active input and/or output devices.
    // |ids|: <p>Specifies IDs of devices that should be active. If either the
    //     input or output list is not set, devices in that category are
    //     unaffected.
    //     </p>
    //     <p>It is an error to pass in a non-existent device ID.</p>
    //     <p><b>NOTE:</b> While the method signature allows device IDs to be
    //     passed as a list of strings, this method of setting active devices
    //     is deprecated and should not be relied upon to work. Please use
    //     $(ref:DeviceIdLists) instead.
    //     </p>
    static void setActiveDevices((DeviceIdLists or DOMString[]) ids,
                                 EmptyCallback callback);

    // Sets the properties for the input or output device.
    static void setProperties(DOMString id,
                              DeviceProperties properties,
                              EmptyCallback callback);

    // Gets the system-wide mute state for the specified stream type.
    // |streamType|: Stream type for which mute state should be fetched.
    // |callback|: Callback reporting whether mute is set or not for specified
    // stream type.
    static void getMute(StreamType streamType, GetMuteCallback callback);

    // Sets mute state for a stream type. The mute state will apply to all audio
    // devices with the specified audio stream type.
    // |streamType|: Stream type for which mute state should be set.
    // |isMuted|: New mute value.
    static void setMute(StreamType streamType,
                        boolean isMuted,
                        optional EmptyCallback callback);

    // Gets the information of all audio output and input devices.
    [nodoc, deprecated="Use $(ref:getDevices) instead."]
    static void getInfo(GetInfoCallback callback);
  };

  interface Events {
    // Fired when sound level changes for an active audio device.
    static void onLevelChanged(LevelChangedEvent event);

    // Fired when the mute state of the audio input or output changes.
    // Note that mute state is system-wide and the new value applies to every
    // audio device with specified stream type.
    static void onMuteChanged(MuteChangedEvent event);

    // Fired when audio devices change, either new devices being added, or
    // existing devices being removed.
    // |devices|: List of all present audio devices after the change.
    static void onDeviceListChanged(AudioDeviceInfo[] devices);

    // Fired when anything changes to the audio device configuration.
    [nodoc, deprecated="Use more granular $(ref:onLevelChanged),
         $(ref:onMuteChanged) and $(ref:onDeviceListChanged) instead."]
    static void onDeviceChanged();
  };
};
