/*
 * libjingle
 * Copyright 2004 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/session/media/channelmanager.h"

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <algorithm>

#include "talk/app/webrtc/mediacontroller.h"
#include "talk/media/base/capturemanager.h"
#include "talk/media/base/hybriddataengine.h"
#include "talk/media/base/rtpdataengine.h"
#include "talk/media/base/videocapturer.h"
#include "talk/media/devices/devicemanager.h"
#ifdef HAVE_SCTP
#include "talk/media/sctp/sctpdataengine.h"
#endif
#include "talk/session/media/srtpfilter.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/common.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/sigslotrepeater.h"
#include "webrtc/base/stringencode.h"
#include "webrtc/base/stringutils.h"

namespace cricket {

enum {
  MSG_VIDEOCAPTURESTATE = 1,
};

using rtc::Bind;

static const int kNotSetOutputVolume = -1;

struct CaptureStateParams : public rtc::MessageData {
  CaptureStateParams(cricket::VideoCapturer* c, cricket::CaptureState s)
      : capturer(c),
        state(s) {}
  cricket::VideoCapturer* capturer;
  cricket::CaptureState state;
};

static DataEngineInterface* ConstructDataEngine() {
#ifdef HAVE_SCTP
  return new HybridDataEngine(new RtpDataEngine(), new SctpDataEngine());
#else
  return new RtpDataEngine();
#endif
}

ChannelManager::ChannelManager(MediaEngineInterface* me,
                               DataEngineInterface* dme,
                               DeviceManagerInterface* dm,
                               CaptureManager* cm,
                               rtc::Thread* worker_thread) {
  Construct(me, dme, dm, cm, worker_thread);
}

ChannelManager::ChannelManager(MediaEngineInterface* me,
                               DeviceManagerInterface* dm,
                               rtc::Thread* worker_thread) {
  Construct(me,
            ConstructDataEngine(),
            dm,
            new CaptureManager(),
            worker_thread);
}

void ChannelManager::Construct(MediaEngineInterface* me,
                               DataEngineInterface* dme,
                               DeviceManagerInterface* dm,
                               CaptureManager* cm,
                               rtc::Thread* worker_thread) {
  media_engine_.reset(me);
  data_media_engine_.reset(dme);
  device_manager_.reset(dm);
  capture_manager_.reset(cm);
  initialized_ = false;
  main_thread_ = rtc::Thread::Current();
  worker_thread_ = worker_thread;
  // Get the default audio options from the media engine.
  audio_options_ = media_engine_->GetAudioOptions();
  audio_in_device_ = DeviceManagerInterface::kDefaultDeviceName;
  audio_out_device_ = DeviceManagerInterface::kDefaultDeviceName;
  audio_delay_offset_ = kDefaultAudioDelayOffset;
  audio_output_volume_ = kNotSetOutputVolume;
  local_renderer_ = NULL;
  capturing_ = false;
  monitoring_ = false;
  enable_rtx_ = false;

  // Init the device manager immediately, and set up our default video device.
  SignalDevicesChange.repeat(device_manager_->SignalDevicesChange);
  device_manager_->Init();

  capture_manager_->SignalCapturerStateChange.connect(
      this, &ChannelManager::OnVideoCaptureStateChange);
}

ChannelManager::~ChannelManager() {
  if (initialized_) {
    Terminate();
    // If srtp is initialized (done by the Channel) then we must call
    // srtp_shutdown to free all crypto kernel lists. But we need to make sure
    // shutdown always called at the end, after channels are destroyed.
    // ChannelManager d'tor is always called last, it's safe place to call
    // shutdown.
    ShutdownSrtp();
  }
  // Some deletes need to be on the worker thread for thread safe destruction,
  // this includes the media engine and capture manager.
  worker_thread_->Invoke<void>(Bind(
      &ChannelManager::DestructorDeletes_w, this));
}

bool ChannelManager::SetVideoRtxEnabled(bool enable) {
  // To be safe, this call is only allowed before initialization. Apps like
  // Flute only have a singleton ChannelManager and we don't want this flag to
  // be toggled between calls or when there's concurrent calls. We expect apps
  // to enable this at startup and retain that setting for the lifetime of the
  // app.
  if (!initialized_) {
    enable_rtx_ = enable;
    return true;
  } else {
    LOG(LS_WARNING) << "Cannot toggle rtx after initialization!";
    return false;
  }
}

int ChannelManager::GetCapabilities() {
  return media_engine_->GetCapabilities() & device_manager_->GetCapabilities();
}

void ChannelManager::GetSupportedAudioCodecs(
    std::vector<AudioCodec>* codecs) const {
  codecs->clear();

  for (std::vector<AudioCodec>::const_iterator it =
           media_engine_->audio_codecs().begin();
      it != media_engine_->audio_codecs().end(); ++it) {
    codecs->push_back(*it);
  }
}

void ChannelManager::GetSupportedAudioRtpHeaderExtensions(
    RtpHeaderExtensions* ext) const {
  *ext = media_engine_->audio_rtp_header_extensions();
}

void ChannelManager::GetSupportedVideoCodecs(
    std::vector<VideoCodec>* codecs) const {
  codecs->clear();

  std::vector<VideoCodec>::const_iterator it;
  for (it = media_engine_->video_codecs().begin();
      it != media_engine_->video_codecs().end(); ++it) {
    if (!enable_rtx_ && _stricmp(kRtxCodecName, it->name.c_str()) == 0) {
      continue;
    }
    codecs->push_back(*it);
  }
}

void ChannelManager::GetSupportedVideoRtpHeaderExtensions(
    RtpHeaderExtensions* ext) const {
  *ext = media_engine_->video_rtp_header_extensions();
}

void ChannelManager::GetSupportedDataCodecs(
    std::vector<DataCodec>* codecs) const {
  *codecs = data_media_engine_->data_codecs();
}

bool ChannelManager::Init() {
  ASSERT(!initialized_);
  if (initialized_) {
    return false;
  }
  ASSERT(worker_thread_ != NULL);
  if (!worker_thread_) {
    return false;
  }
  if (worker_thread_ != rtc::Thread::Current()) {
    // Do not allow invoking calls to other threads on the worker thread.
    worker_thread_->Invoke<bool>(rtc::Bind(
        &rtc::Thread::SetAllowBlockingCalls, worker_thread_, false));
  }

  initialized_ = worker_thread_->Invoke<bool>(Bind(
      &ChannelManager::InitMediaEngine_w, this));
  ASSERT(initialized_);
  if (!initialized_) {
    return false;
  }

  // Now that we're initialized, apply any stored preferences. A preferred
  // device might have been unplugged. In this case, we fallback to the
  // default device but keep the user preferences. The preferences are
  // changed only when the Javascript FE changes them.
  const std::string preferred_audio_in_device = audio_in_device_;
  const std::string preferred_audio_out_device = audio_out_device_;
  const std::string preferred_camera_device = camera_device_;
  Device device;
  if (!device_manager_->GetAudioInputDevice(audio_in_device_, &device)) {
    LOG(LS_WARNING) << "The preferred microphone '" << audio_in_device_
                    << "' is unavailable. Fall back to the default.";
    audio_in_device_ = DeviceManagerInterface::kDefaultDeviceName;
  }
  if (!device_manager_->GetAudioOutputDevice(audio_out_device_, &device)) {
    LOG(LS_WARNING) << "The preferred speaker '" << audio_out_device_
                    << "' is unavailable. Fall back to the default.";
    audio_out_device_ = DeviceManagerInterface::kDefaultDeviceName;
  }
  if (!device_manager_->GetVideoCaptureDevice(camera_device_, &device)) {
    if (!camera_device_.empty()) {
      LOG(LS_WARNING) << "The preferred camera '" << camera_device_
                      << "' is unavailable. Fall back to the default.";
    }
    camera_device_ = DeviceManagerInterface::kDefaultDeviceName;
  }

  if (!SetAudioOptions(audio_in_device_, audio_out_device_,
                       audio_options_, audio_delay_offset_)) {
    LOG(LS_WARNING) << "Failed to SetAudioOptions with"
                    << " microphone: " << audio_in_device_
                    << " speaker: " << audio_out_device_
                    << " options: " << audio_options_.ToString()
                    << " delay: " << audio_delay_offset_;
  }

  // If audio_output_volume_ has been set via SetOutputVolume(), set the
  // audio output volume of the engine.
  if (kNotSetOutputVolume != audio_output_volume_ &&
      !SetOutputVolume(audio_output_volume_)) {
    LOG(LS_WARNING) << "Failed to SetOutputVolume to "
                    << audio_output_volume_;
  }
  if (!SetCaptureDevice(camera_device_) && !camera_device_.empty()) {
    LOG(LS_WARNING) << "Failed to SetCaptureDevice with camera: "
                    << camera_device_;
  }

  // Restore the user preferences.
  audio_in_device_ = preferred_audio_in_device;
  audio_out_device_ = preferred_audio_out_device;
  camera_device_ = preferred_camera_device;

  // Now apply the default video codec that has been set earlier.
  if (default_video_encoder_config_.max_codec.id != 0) {
    SetDefaultVideoEncoderConfig(default_video_encoder_config_);
  }

  return initialized_;
}

bool ChannelManager::InitMediaEngine_w() {
  ASSERT(worker_thread_ == rtc::Thread::Current());
  return (media_engine_->Init(worker_thread_));
}

void ChannelManager::Terminate() {
  ASSERT(initialized_);
  if (!initialized_) {
    return;
  }
  worker_thread_->Invoke<void>(Bind(&ChannelManager::Terminate_w, this));
  initialized_ = false;
}

void ChannelManager::DestructorDeletes_w() {
  ASSERT(worker_thread_ == rtc::Thread::Current());
  media_engine_.reset(NULL);
  capture_manager_.reset(NULL);
}

void ChannelManager::Terminate_w() {
  ASSERT(worker_thread_ == rtc::Thread::Current());
  // Need to destroy the voice/video channels
  while (!video_channels_.empty()) {
    DestroyVideoChannel_w(video_channels_.back());
  }
  while (!voice_channels_.empty()) {
    DestroyVoiceChannel_w(voice_channels_.back());
  }
  if (!SetCaptureDevice_w(NULL)) {
    LOG(LS_WARNING) << "failed to delete video capturer";
  }
  media_engine_->Terminate();
}

VoiceChannel* ChannelManager::CreateVoiceChannel(
    webrtc::MediaControllerInterface* media_controller,
    BaseSession* session,
    const std::string& content_name,
    bool rtcp,
    const AudioOptions& options) {
  return worker_thread_->Invoke<VoiceChannel*>(
      Bind(&ChannelManager::CreateVoiceChannel_w,
          this,
          media_controller,
          session,
          content_name,
          rtcp,
          options));
}

VoiceChannel* ChannelManager::CreateVoiceChannel_w(
    webrtc::MediaControllerInterface* media_controller,
    BaseSession* session,
    const std::string& content_name,
    bool rtcp,
    const AudioOptions& options) {
  ASSERT(initialized_);
  ASSERT(worker_thread_ == rtc::Thread::Current());
  ASSERT(nullptr != media_controller);
  VoiceMediaChannel* media_channel =
      media_engine_->CreateChannel(media_controller->call_w(), options);
  if (!media_channel)
    return nullptr;

  VoiceChannel* voice_channel = new VoiceChannel(
      worker_thread_, media_engine_.get(), media_channel,
      session, content_name, rtcp);
  if (!voice_channel->Init()) {
    delete voice_channel;
    return nullptr;
  }
  voice_channels_.push_back(voice_channel);
  return voice_channel;
}

void ChannelManager::DestroyVoiceChannel(VoiceChannel* voice_channel) {
  if (voice_channel) {
    worker_thread_->Invoke<void>(
        Bind(&ChannelManager::DestroyVoiceChannel_w, this, voice_channel));
  }
}

void ChannelManager::DestroyVoiceChannel_w(VoiceChannel* voice_channel) {
  // Destroy voice channel.
  ASSERT(initialized_);
  ASSERT(worker_thread_ == rtc::Thread::Current());
  VoiceChannels::iterator it = std::find(voice_channels_.begin(),
      voice_channels_.end(), voice_channel);
  ASSERT(it != voice_channels_.end());
  if (it == voice_channels_.end())
    return;
  voice_channels_.erase(it);
  delete voice_channel;
}

VideoChannel* ChannelManager::CreateVideoChannel(
    webrtc::MediaControllerInterface* media_controller,
    BaseSession* session,
    const std::string& content_name,
    bool rtcp,
    const VideoOptions& options) {
  return worker_thread_->Invoke<VideoChannel*>(
      Bind(&ChannelManager::CreateVideoChannel_w,
           this,
           media_controller,
           session,
           content_name,
           rtcp,
           options));
}

VideoChannel* ChannelManager::CreateVideoChannel_w(
    webrtc::MediaControllerInterface* media_controller,
    BaseSession* session,
    const std::string& content_name,
    bool rtcp,
    const VideoOptions& options) {
  ASSERT(initialized_);
  ASSERT(worker_thread_ == rtc::Thread::Current());
  ASSERT(nullptr != media_controller);
  VideoMediaChannel* media_channel =
      media_engine_->CreateVideoChannel(media_controller->call_w(), options);
  if (media_channel == NULL)
    return NULL;

  VideoChannel* video_channel = new VideoChannel(
      worker_thread_, media_channel,
      session, content_name, rtcp);
  if (!video_channel->Init()) {
    delete video_channel;
    return NULL;
  }
  video_channels_.push_back(video_channel);
  return video_channel;
}

void ChannelManager::DestroyVideoChannel(VideoChannel* video_channel) {
  if (video_channel) {
    worker_thread_->Invoke<void>(
        Bind(&ChannelManager::DestroyVideoChannel_w, this, video_channel));
  }
}

void ChannelManager::DestroyVideoChannel_w(VideoChannel* video_channel) {
  // Destroy video channel.
  ASSERT(initialized_);
  ASSERT(worker_thread_ == rtc::Thread::Current());
  VideoChannels::iterator it = std::find(video_channels_.begin(),
      video_channels_.end(), video_channel);
  ASSERT(it != video_channels_.end());
  if (it == video_channels_.end())
    return;

  video_channels_.erase(it);
  delete video_channel;
}

DataChannel* ChannelManager::CreateDataChannel(
    BaseSession* session, const std::string& content_name,
    bool rtcp, DataChannelType channel_type) {
  return worker_thread_->Invoke<DataChannel*>(
      Bind(&ChannelManager::CreateDataChannel_w, this, session, content_name,
           rtcp, channel_type));
}

DataChannel* ChannelManager::CreateDataChannel_w(
    BaseSession* session, const std::string& content_name,
    bool rtcp, DataChannelType data_channel_type) {
  // This is ok to alloc from a thread other than the worker thread.
  ASSERT(initialized_);
  DataMediaChannel* media_channel = data_media_engine_->CreateChannel(
      data_channel_type);
  if (!media_channel) {
    LOG(LS_WARNING) << "Failed to create data channel of type "
                    << data_channel_type;
    return NULL;
  }

  DataChannel* data_channel = new DataChannel(
      worker_thread_, media_channel,
      session, content_name, rtcp);
  if (!data_channel->Init()) {
    LOG(LS_WARNING) << "Failed to init data channel.";
    delete data_channel;
    return NULL;
  }
  data_channels_.push_back(data_channel);
  return data_channel;
}

void ChannelManager::DestroyDataChannel(DataChannel* data_channel) {
  if (data_channel) {
    worker_thread_->Invoke<void>(
        Bind(&ChannelManager::DestroyDataChannel_w, this, data_channel));
  }
}

void ChannelManager::DestroyDataChannel_w(DataChannel* data_channel) {
  // Destroy data channel.
  ASSERT(initialized_);
  DataChannels::iterator it = std::find(data_channels_.begin(),
      data_channels_.end(), data_channel);
  ASSERT(it != data_channels_.end());
  if (it == data_channels_.end())
    return;

  data_channels_.erase(it);
  delete data_channel;
}

bool ChannelManager::GetAudioOptions(std::string* in_name,
                                     std::string* out_name,
                                     AudioOptions* options) {
  if (in_name)
    *in_name = audio_in_device_;
  if (out_name)
    *out_name = audio_out_device_;
  if (options)
    *options = audio_options_;
  return true;
}

bool ChannelManager::SetAudioOptions(const std::string& in_name,
                                     const std::string& out_name,
                                     const AudioOptions& options) {
  return SetAudioOptions(in_name, out_name, options, audio_delay_offset_);
}

bool ChannelManager::SetAudioOptions(const std::string& in_name,
                                     const std::string& out_name,
                                     const AudioOptions& options,
                                     int delay_offset) {
  // Get device ids from DeviceManager.
  Device in_dev, out_dev;
  if (!device_manager_->GetAudioInputDevice(in_name, &in_dev)) {
    LOG(LS_WARNING) << "Failed to GetAudioInputDevice: " << in_name;
    return false;
  }
  if (!device_manager_->GetAudioOutputDevice(out_name, &out_dev)) {
    LOG(LS_WARNING) << "Failed to GetAudioOutputDevice: " << out_name;
    return false;
  }

  // If we're initialized, pass the settings to the media engine.
  bool ret = true;
  if (initialized_) {
    ret = worker_thread_->Invoke<bool>(
        Bind(&ChannelManager::SetAudioOptions_w, this,
             options, delay_offset, &in_dev, &out_dev));
  }

  // If all worked well, save the values for use in GetAudioOptions.
  if (ret) {
    audio_options_ = options;
    audio_in_device_ = in_name;
    audio_out_device_ = out_name;
    audio_delay_offset_ = delay_offset;
  }
  return ret;
}

bool ChannelManager::SetAudioOptions_w(
    const AudioOptions& options, int delay_offset,
    const Device* in_dev, const Device* out_dev) {
  ASSERT(worker_thread_ == rtc::Thread::Current());
  ASSERT(initialized_);

  // Set audio options
  bool ret = media_engine_->SetAudioOptions(options);

  if (ret) {
    ret = media_engine_->SetAudioDelayOffset(delay_offset);
  }

  // Set the audio devices
  if (ret) {
    ret = media_engine_->SetSoundDevices(in_dev, out_dev);
  }

  return ret;
}

bool ChannelManager::GetOutputVolume(int* level) {
  if (!initialized_) {
    return false;
  }
  return worker_thread_->Invoke<bool>(
      Bind(&MediaEngineInterface::GetOutputVolume, media_engine_.get(), level));
}

bool ChannelManager::SetOutputVolume(int level) {
  bool ret = level >= 0 && level <= 255;
  if (initialized_) {
    ret &= worker_thread_->Invoke<bool>(
        Bind(&MediaEngineInterface::SetOutputVolume,
             media_engine_.get(), level));
  }

  if (ret) {
    audio_output_volume_ = level;
  }

  return ret;
}

bool ChannelManager::IsSameCapturer(const std::string& capturer_name,
                                    VideoCapturer* capturer) {
  if (capturer == NULL) {
    return false;
  }
  Device device;
  if (!device_manager_->GetVideoCaptureDevice(capturer_name, &device)) {
    return false;
  }
  return capturer->GetId() == device.id;
}

bool ChannelManager::GetVideoCaptureDevice(Device* device) {
  std::string device_name;
  if (!GetCaptureDevice(&device_name)) {
    return false;
  }
  return device_manager_->GetVideoCaptureDevice(device_name, device);
}

bool ChannelManager::GetCaptureDevice(std::string* cam_name) {
  if (camera_device_.empty()) {
    // Initialize camera_device_ with default.
    Device device;
    if (!device_manager_->GetVideoCaptureDevice(
        DeviceManagerInterface::kDefaultDeviceName, &device)) {
      LOG(LS_WARNING) << "Device manager can't find default camera: " <<
          DeviceManagerInterface::kDefaultDeviceName;
      return false;
    }
    camera_device_ = device.name;
  }
  *cam_name = camera_device_;
  return true;
}

bool ChannelManager::SetCaptureDevice(const std::string& cam_name) {
  Device device;
  bool ret = true;
  if (!device_manager_->GetVideoCaptureDevice(cam_name, &device)) {
    if (!cam_name.empty()) {
      LOG(LS_WARNING) << "Device manager can't find camera: " << cam_name;
    }
    ret = false;
  }

  // If we're running, tell the media engine about it.
  if (initialized_ && ret) {
    ret = worker_thread_->Invoke<bool>(
        Bind(&ChannelManager::SetCaptureDevice_w, this, &device));
  }

  // If everything worked, retain the name of the selected camera.
  if (ret) {
    camera_device_ = device.name;
  } else if (camera_device_.empty()) {
    // When video option setting fails, we still want camera_device_ to be in a
    // good state, so we initialize it with default if it's empty.
    Device default_device;
    if (!device_manager_->GetVideoCaptureDevice(
        DeviceManagerInterface::kDefaultDeviceName, &default_device)) {
      LOG(LS_WARNING) << "Device manager can't find default camera: " <<
          DeviceManagerInterface::kDefaultDeviceName;
    }
    camera_device_ = default_device.name;
  }

  return ret;
}

VideoCapturer* ChannelManager::CreateVideoCapturer() {
  Device device;
  if (!device_manager_->GetVideoCaptureDevice(camera_device_, &device)) {
    if (!camera_device_.empty()) {
      LOG(LS_WARNING) << "Device manager can't find camera: " << camera_device_;
    }
    return NULL;
  }
  VideoCapturer* capturer = device_manager_->CreateVideoCapturer(device);
  if (capturer && default_video_encoder_config_.max_codec.id != 0) {
    // For now, use the aspect ratio of the default_video_encoder_config_,
    // which may be different than the native aspect ratio of the start
    // format the camera may use.
    capturer->UpdateAspectRatio(
        default_video_encoder_config_.max_codec.width,
        default_video_encoder_config_.max_codec.height);
  }
  return capturer;
}

VideoCapturer* ChannelManager::CreateScreenCapturer(
    const ScreencastId& screenid) {
  return device_manager_->CreateScreenCapturer(screenid);
}

bool ChannelManager::SetCaptureDevice_w(const Device* cam_device) {
  ASSERT(worker_thread_ == rtc::Thread::Current());
  ASSERT(initialized_);

  if (!cam_device) {
    video_device_name_.clear();
    return true;
  }
  video_device_name_ = cam_device->name;
  return true;
}

bool ChannelManager::SetDefaultVideoEncoderConfig(const VideoEncoderConfig& c) {
  bool ret = true;
  if (initialized_) {
    ret = worker_thread_->Invoke<bool>(
        Bind(&MediaEngineInterface::SetDefaultVideoEncoderConfig,
             media_engine_.get(), c));
  }
  if (ret) {
    default_video_encoder_config_ = c;
  }
  return ret;
}

bool ChannelManager::SetLocalMonitor(bool enable) {
  bool ret = initialized_ && worker_thread_->Invoke<bool>(
      Bind(&MediaEngineInterface::SetLocalMonitor,
           media_engine_.get(), enable));
  if (ret) {
    monitoring_ = enable;
  }
  return ret;
}

void ChannelManager::SetVoiceLogging(int level, const char* filter) {
  if (initialized_) {
    worker_thread_->Invoke<void>(
        Bind(&MediaEngineInterface::SetVoiceLogging,
             media_engine_.get(), level, filter));
  } else {
    media_engine_->SetVoiceLogging(level, filter);
  }
}

void ChannelManager::SetVideoLogging(int level, const char* filter) {
  if (initialized_) {
    worker_thread_->Invoke<void>(
        Bind(&MediaEngineInterface::SetVideoLogging,
             media_engine_.get(), level, filter));
  } else {
    media_engine_->SetVideoLogging(level, filter);
  }
}

std::vector<cricket::VideoFormat> ChannelManager::GetSupportedFormats(
    VideoCapturer* capturer) const {
  ASSERT(capturer != NULL);
  std::vector<VideoFormat> formats;
  worker_thread_->Invoke<void>(rtc::Bind(&ChannelManager::GetSupportedFormats_w,
                                         this, capturer, &formats));
  return formats;
}

void ChannelManager::GetSupportedFormats_w(
    VideoCapturer* capturer,
    std::vector<cricket::VideoFormat>* out_formats) const {
  const std::vector<VideoFormat>* formats = capturer->GetSupportedFormats();
  if (formats != NULL)
    *out_formats = *formats;
}

bool ChannelManager::RegisterVoiceProcessor(
    uint32 ssrc,
    VoiceProcessor* processor,
    MediaProcessorDirection direction) {
  return initialized_ && worker_thread_->Invoke<bool>(
      Bind(&MediaEngineInterface::RegisterVoiceProcessor, media_engine_.get(),
           ssrc, processor, direction));
}

bool ChannelManager::UnregisterVoiceProcessor(
    uint32 ssrc,
    VoiceProcessor* processor,
    MediaProcessorDirection direction) {
  return initialized_ && worker_thread_->Invoke<bool>(
      Bind(&MediaEngineInterface::UnregisterVoiceProcessor,
           media_engine_.get(), ssrc, processor, direction));
}

// The following are done in the new "CaptureManager" style that
// all local video capturers, processors, and managers should move
// to.
// TODO(pthatcher): Add more of the CaptureManager interface.
bool ChannelManager::StartVideoCapture(
    VideoCapturer* capturer, const VideoFormat& video_format) {
  return initialized_ && worker_thread_->Invoke<bool>(
      Bind(&CaptureManager::StartVideoCapture,
           capture_manager_.get(), capturer, video_format));
}

bool ChannelManager::MuteToBlackThenPause(
    VideoCapturer* video_capturer, bool muted) {
  if (!initialized_) {
    return false;
  }
  worker_thread_->Invoke<void>(
      Bind(&VideoCapturer::MuteToBlackThenPause, video_capturer, muted));
  return true;
}

bool ChannelManager::StopVideoCapture(
    VideoCapturer* capturer, const VideoFormat& video_format) {
  return initialized_ && worker_thread_->Invoke<bool>(
      Bind(&CaptureManager::StopVideoCapture,
           capture_manager_.get(), capturer, video_format));
}

bool ChannelManager::RestartVideoCapture(
    VideoCapturer* video_capturer,
    const VideoFormat& previous_format,
    const VideoFormat& desired_format,
    CaptureManager::RestartOptions options) {
  return initialized_ && worker_thread_->Invoke<bool>(
      Bind(&CaptureManager::RestartVideoCapture, capture_manager_.get(),
           video_capturer, previous_format, desired_format, options));
}

bool ChannelManager::AddVideoRenderer(
    VideoCapturer* capturer, VideoRenderer* renderer) {
  return initialized_ && worker_thread_->Invoke<bool>(
      Bind(&CaptureManager::AddVideoRenderer,
           capture_manager_.get(), capturer, renderer));
}

bool ChannelManager::RemoveVideoRenderer(
    VideoCapturer* capturer, VideoRenderer* renderer) {
  return initialized_ && worker_thread_->Invoke<bool>(
      Bind(&CaptureManager::RemoveVideoRenderer,
           capture_manager_.get(), capturer, renderer));
}

bool ChannelManager::IsScreencastRunning() const {
  return initialized_ && worker_thread_->Invoke<bool>(
      Bind(&ChannelManager::IsScreencastRunning_w, this));
}

bool ChannelManager::IsScreencastRunning_w() const {
  VideoChannels::const_iterator it = video_channels_.begin();
  for ( ; it != video_channels_.end(); ++it) {
    if ((*it) && (*it)->IsScreencasting()) {
      return true;
    }
  }
  return false;
}

void ChannelManager::OnVideoCaptureStateChange(VideoCapturer* capturer,
                                               CaptureState result) {
  // TODO(whyuan): Check capturer and signal failure only for camera video, not
  // screencast.
  capturing_ = result == CS_RUNNING;
  main_thread_->Post(this, MSG_VIDEOCAPTURESTATE,
                     new CaptureStateParams(capturer, result));
}

void ChannelManager::OnMessage(rtc::Message* message) {
  switch (message->message_id) {
    case MSG_VIDEOCAPTURESTATE: {
      CaptureStateParams* data =
          static_cast<CaptureStateParams*>(message->pdata);
      SignalVideoCaptureStateChange(data->capturer, data->state);
      delete data;
      break;
    }
  }
}


static void GetDeviceNames(const std::vector<Device>& devs,
                           std::vector<std::string>* names) {
  names->clear();
  for (size_t i = 0; i < devs.size(); ++i) {
    names->push_back(devs[i].name);
  }
}

bool ChannelManager::GetAudioInputDevices(std::vector<std::string>* names) {
  names->clear();
  std::vector<Device> devs;
  bool ret = device_manager_->GetAudioInputDevices(&devs);
  if (ret)
    GetDeviceNames(devs, names);

  return ret;
}

bool ChannelManager::GetAudioOutputDevices(std::vector<std::string>* names) {
  names->clear();
  std::vector<Device> devs;
  bool ret = device_manager_->GetAudioOutputDevices(&devs);
  if (ret)
    GetDeviceNames(devs, names);

  return ret;
}

bool ChannelManager::GetVideoCaptureDevices(std::vector<std::string>* names) {
  names->clear();
  std::vector<Device> devs;
  bool ret = device_manager_->GetVideoCaptureDevices(&devs);
  if (ret)
    GetDeviceNames(devs, names);

  return ret;
}

void ChannelManager::SetVideoCaptureDeviceMaxFormat(
    const std::string& usb_id,
    const VideoFormat& max_format) {
  device_manager_->SetVideoCaptureDeviceMaxFormat(usb_id, max_format);
}

bool ChannelManager::StartAecDump(rtc::PlatformFile file) {
  return worker_thread_->Invoke<bool>(
      Bind(&MediaEngineInterface::StartAecDump, media_engine_.get(), file));
}

}  // namespace cricket
