// Copyright (c) 2012 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.
//
// THREAD SAFETY
//
// This class is generally not thread safe. Callers should ensure thread safety.
// For instance, the |sink_lock_| in WebAudioSourceProvider synchronizes access
// to this object across the main thread (for WebAudio APIs) and the
// media thread (for HTMLMediaElement APIs).
//
// The one exception is protection for |volume_| via |volume_lock_|. This lock
// prevents races between SetVolume() (called on any thread) and ProvideInput
// (called on audio device thread). See http://crbug.com/588992.

#ifndef MEDIA_BASE_AUDIO_RENDERER_MIXER_INPUT_H_
#define MEDIA_BASE_AUDIO_RENDERER_MIXER_INPUT_H_

#include <string>

#include "base/callback.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "media/base/audio_converter.h"
#include "media/base/audio_latency.h"
#include "media/base/audio_renderer_sink.h"
#include "url/origin.h"

namespace media {

class AudioRendererMixerPool;
class AudioRendererMixer;

class MEDIA_EXPORT AudioRendererMixerInput
    : NON_EXPORTED_BASE(public SwitchableAudioRendererSink),
      public AudioConverter::InputCallback {
 public:
  AudioRendererMixerInput(AudioRendererMixerPool* mixer_pool,
                          int owner_id,
                          const std::string& device_id,
                          const url::Origin& security_origin,
                          AudioLatency::LatencyType latency);

  // SwitchableAudioRendererSink implementation.
  void Start() override;
  void Stop() override;
  void Play() override;
  void Pause() override;
  bool SetVolume(double volume) override;
  OutputDeviceInfo GetOutputDeviceInfo() override;
  void Initialize(const AudioParameters& params,
                  AudioRendererSink::RenderCallback* renderer) override;
  void SwitchOutputDevice(const std::string& device_id,
                          const url::Origin& security_origin,
                          const OutputDeviceStatusCB& callback) override;
  // This is expected to be called on the audio rendering thread. The caller
  // must ensure that this input has been added to a mixer before calling the
  // function, and that it is not removed from the mixer before this function
  // returns.
  bool CurrentThreadIsRenderingThread() override;

  // Called by AudioRendererMixer when an error occurs.
  void OnRenderError();

 protected:
  ~AudioRendererMixerInput() override;

 private:
  friend class AudioRendererMixerInputTest;

  // Pool to obtain mixers from / return them to.
  AudioRendererMixerPool* const mixer_pool_;

  // Protect |volume_|, accessed by separate threads in ProvideInput() and
  // SetVolume().
  base::Lock volume_lock_;

  bool started_;
  bool playing_;
  double volume_;

  // AudioConverter::InputCallback implementation.
  double ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) override;

  // AudioParameters received during Initialize().
  AudioParameters params_;

  const int owner_id_;
  std::string device_id_;  // ID of hardware device to use
  url::Origin security_origin_;
  const AudioLatency::LatencyType latency_;

  // AudioRendererMixer obtained from mixer pool during Initialize(),
  // guaranteed to live (at least) until it is returned to the pool.
  AudioRendererMixer* mixer_;

  // Source of audio data which is provided to the mixer.
  AudioRendererSink::RenderCallback* callback_;

  // Error callback for handing to AudioRendererMixer.
  const base::Closure error_cb_;

  DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerInput);
};

}  // namespace media

#endif  // MEDIA_BASE_AUDIO_RENDERER_MIXER_INPUT_H_
