// Copyright (c) 2010 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.

#ifndef MEDIA_AUDIO_AUDIO_OUTPUT_H_
#define MEDIA_AUDIO_AUDIO_OUTPUT_H_

#include "base/basictypes.h"

// Low-level audio output support. To make sound there are 3 objects involved:
// - AudioSource : produces audio samples on a pull model. Implements
//   the AudioSourceCallback interface.
// - AudioOutputStream : uses the AudioSource to render audio on a given
//   channel, format and sample frequency configuration. Data from the
//   AudioSource is delivered in a 'pull' model.
// - AudioManager : factory for the AudioOutputStream objects, manager
//   of the hardware resources and mixer control.
//
// The number and configuration of AudioOutputStream does not need to match the
// physically available hardware resources. For example you can have:
//
//  MonoPCMSource1 --> MonoPCMStream1 --> |       | --> audio left channel
//  StereoPCMSource -> StereoPCMStream -> | mixer |
//  MonoPCMSource2 --> MonoPCMStream2 --> |       | --> audio right channel
//
// This facility's objective is mix and render audio with low overhead using
// the OS basic audio support, abstracting as much as possible the
// idiosyncrasies of each platform. Non-goals:
// - Positional, 3d audio
// - Dependence on non-default libraries such as DirectX 9, 10, XAudio
// - Digital signal processing or effects
// - Extra features if a specific hardware is installed (EAX, X-fi)
//
// The primary client of this facility is audio coming from several tabs.
// Specifically for this case we avoid supporting complex formats such as MP3
// or WMA. Complex format decoding should be done by the renderers.


// Models an audio stream that gets rendered to the audio hardware output.
// Because we support more audio streams than physically available channels
// a given AudioOutputStream might or might not talk directly to hardware.
class AudioOutputStream {
 public:
  // Audio sources must implement AudioSourceCallback. This interface will be
  // called in a random thread which very likely is a high priority thread. Do
  // not rely on using this thread TLS or make calls that alter the thread
  // itself such as creating Windows or initializing COM.
  class AudioSourceCallback {
   public:
    virtual ~AudioSourceCallback() {}

    // Provide more data by filling |dest| up to |max_size| bytes. The provided
    // buffer size is usually what is specified in Open(). The source
    // will return the number of bytes it filled. The expected structure of
    // |dest| is platform and format specific.
    // |pending_bytes| is the number of bytes will be played before the
    // requested data is played.
    virtual uint32 OnMoreData(AudioOutputStream* stream, void* dest,
                              uint32 max_size, uint32 pending_bytes) = 0;

    // The stream is done with this callback. After this call the audio source
    // can go away or be destroyed.
    virtual void OnClose(AudioOutputStream* stream) = 0;

    // There was an error while playing a buffer. Audio source cannot be
    // destroyed yet. No direct action needed by the AudioStream, but it is
    // a good place to stop accumulating sound data since is is likely that
    // playback will not continue. |code| is an error code that is platform
    // specific.
    virtual void OnError(AudioOutputStream* stream, int code) = 0;
  };

  // Open the stream. |packet_size| is the requested buffer allocation which
  // the audio source thinks it can usually fill without blocking. Internally
  // two or three buffers of |packet_size| size are created, one will be
  // locked for playback and one will be ready to be filled in the call to
  // AudioSourceCallback::OnMoreData().
  // The number of buffers is controlled by AUDIO_PCM_LOW_LATENCY. See more
  // information below.
  //
  // TODO(ajwong): Streams are not reusable, so try to move packet_size into the
  // constructor.
  virtual bool Open(uint32 packet_size) = 0;

  // Starts playing audio and generating AudioSourceCallback::OnMoreData().
  // Since implementor of AudioOutputStream may have internal buffers, right
  // after calling this method initial buffers are fetched.
  //
  // The output stream does not take ownership of this callback.
  virtual void Start(AudioSourceCallback* callback) = 0;

  // Stops playing audio. Effect might not be instantaneous as the hardware
  // might have locked audio data that is processing.
  virtual void Stop() = 0;

  // Sets the relative volume, with range [0.0, 1.0] inclusive.
  virtual void SetVolume(double volume) = 0;

  // Gets the relative volume, with range [0.0, 1.0] inclusive.
  virtual void GetVolume(double* volume) = 0;

  // Close the stream. This also generates AudioSourceCallback::OnClose().
  // After calling this method, the object should not be used anymore.
  virtual void Close() = 0;

 protected:
  virtual ~AudioOutputStream() {}
};

// Manages all audio resources. In particular it owns the AudioOutputStream
// objects. Provides some convenience functions that avoid the need to provide
// iterators over the existing streams.
class AudioManager {
 public:
  enum Format {
    AUDIO_PCM_LINEAR = 0,     // PCM is 'raw' amplitude samples.
    AUDIO_PCM_LOW_LATENCY,    // Linear PCM, low latency requested.
    AUDIO_MOCK,               // Creates a dummy AudioOutputStream object.
    AUDIO_LAST_FORMAT         // Only used for validation of format.
  };

  // Telephone quality sample rate, mostly for speech-only audio.
  static const uint32 kTelephoneSampleRate = 8000;
  // CD sampling rate is 44.1 KHz or conveniently 2x2x3x3x5x5x7x7.
  static const uint32 kAudioCDSampleRate = 44100;
  // Digital Audio Tape sample rate.
  static const uint32 kAudioDATSampleRate = 48000;

  // Returns true if the OS reports existence of audio devices. This does not
  // guarantee that the existing devices support all formats and sample rates.
  virtual bool HasAudioDevices() = 0;

  // Factory for all the supported stream formats. The |channels| can be 1 to 5.
  // The |sample_rate| is in hertz and can be any value supported by the
  // platform. For some future formats the |sample_rate| and |bits_per_sample|
  // can take special values.
  // Returns NULL if the combination of the parameters is not supported, or if
  // we have reached some other platform specific limit.
  //
  // AUDIO_PCM_LOW_LATENCY can be passed to this method and it has two effects:
  // 1- Instead of triple buffered the audio will be double buffered.
  // 2- A low latency driver or alternative audio subsystem will be used when
  //    available.
  //
  // Do not free the returned AudioOutputStream. It is owned by AudioManager.
  virtual AudioOutputStream* MakeAudioStream(Format format, int channels,
                                             int sample_rate,
                                             char bits_per_sample) = 0;

  // Muting continues playback but effectively the volume is set to zero.
  // Un-muting returns the volume to the previous level.
  virtual void MuteAll() = 0;
  virtual void UnMuteAll() = 0;

  // Get AudioManager singleton.
  // TODO(cpu): Define threading requirements for interacting with AudioManager.
  static AudioManager* GetAudioManager();

 protected:
  virtual ~AudioManager() {}
};


#endif  // MEDIA_AUDIO_AUDIO_OUTPUT_H_