/*
 * Copyright (C) 2011, Google Inc. All rights reserved.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``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 APPLE INC. OR ITS CONTRIBUTORS 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 "modules/webaudio/MediaElementAudioSourceNode.h"

#include "core/dom/ExecutionContextTask.h"
#include "core/html/HTMLMediaElement.h"
#include "core/inspector/ConsoleMessage.h"
#include "modules/webaudio/AudioNodeOutput.h"
#include "modules/webaudio/BaseAudioContext.h"
#include "modules/webaudio/MediaElementAudioSourceOptions.h"
#include "platform/audio/AudioUtilities.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "wtf/Locker.h"
#include "wtf/PtrUtil.h"

namespace blink {

MediaElementAudioSourceHandler::MediaElementAudioSourceHandler(
    AudioNode& node,
    HTMLMediaElement& mediaElement)
    : AudioHandler(NodeTypeMediaElementAudioSource,
                   node,
                   node.context()->sampleRate()),
      m_mediaElement(mediaElement),
      m_sourceNumberOfChannels(0),
      m_sourceSampleRate(0),
      m_passesCurrentSrcCORSAccessCheck(
          passesCurrentSrcCORSAccessCheck(mediaElement.currentSrc())),
      m_maybePrintCORSMessage(!m_passesCurrentSrcCORSAccessCheck),
      m_currentSrcString(mediaElement.currentSrc().getString()) {
  DCHECK(isMainThread());
  // Default to stereo. This could change depending on what the media element
  // .src is set to.
  addOutput(2);

  initialize();
}

PassRefPtr<MediaElementAudioSourceHandler>
MediaElementAudioSourceHandler::create(AudioNode& node,
                                       HTMLMediaElement& mediaElement) {
  return adoptRef(new MediaElementAudioSourceHandler(node, mediaElement));
}

MediaElementAudioSourceHandler::~MediaElementAudioSourceHandler() {
  uninitialize();
}

void MediaElementAudioSourceHandler::dispose() {
  m_mediaElement->setAudioSourceNode(nullptr);
  AudioHandler::dispose();
}

void MediaElementAudioSourceHandler::setFormat(size_t numberOfChannels,
                                               float sourceSampleRate) {
  if (numberOfChannels != m_sourceNumberOfChannels ||
      sourceSampleRate != m_sourceSampleRate) {
    if (!numberOfChannels ||
        numberOfChannels > BaseAudioContext::maxNumberOfChannels() ||
        !AudioUtilities::isValidAudioBufferSampleRate(sourceSampleRate)) {
      // process() will generate silence for these uninitialized values.
      DLOG(ERROR) << "setFormat(" << numberOfChannels << ", "
                  << sourceSampleRate << ") - unhandled format change";
      // Synchronize with process().
      Locker<MediaElementAudioSourceHandler> locker(*this);
      m_sourceNumberOfChannels = 0;
      m_sourceSampleRate = 0;
      return;
    }

    // Synchronize with process() to protect m_sourceNumberOfChannels,
    // m_sourceSampleRate, and m_multiChannelResampler.
    Locker<MediaElementAudioSourceHandler> locker(*this);

    m_sourceNumberOfChannels = numberOfChannels;
    m_sourceSampleRate = sourceSampleRate;

    if (sourceSampleRate != sampleRate()) {
      double scaleFactor = sourceSampleRate / sampleRate();
      m_multiChannelResampler =
          wrapUnique(new MultiChannelResampler(scaleFactor, numberOfChannels));
    } else {
      // Bypass resampling.
      m_multiChannelResampler.reset();
    }

    {
      // The context must be locked when changing the number of output channels.
      BaseAudioContext::AutoLocker contextLocker(context());

      // Do any necesssary re-configuration to the output's number of channels.
      output(0).setNumberOfChannels(numberOfChannels);
    }
  }
}

bool MediaElementAudioSourceHandler::passesCORSAccessCheck() {
  DCHECK(mediaElement());

  return (mediaElement()->webMediaPlayer() &&
          mediaElement()->webMediaPlayer()->didPassCORSAccessCheck()) ||
         m_passesCurrentSrcCORSAccessCheck;
}

void MediaElementAudioSourceHandler::onCurrentSrcChanged(
    const KURL& currentSrc) {
  DCHECK(isMainThread());

  // Synchronize with process().
  Locker<MediaElementAudioSourceHandler> locker(*this);

  m_passesCurrentSrcCORSAccessCheck =
      passesCurrentSrcCORSAccessCheck(currentSrc);

  // Make a note if we need to print a console message and save the |curentSrc|
  // for use in the message.  Need to wait until later to print the message in
  // case HTMLMediaElement allows access.
  m_maybePrintCORSMessage = !m_passesCurrentSrcCORSAccessCheck;
  m_currentSrcString = currentSrc.getString();
}

bool MediaElementAudioSourceHandler::passesCurrentSrcCORSAccessCheck(
    const KURL& currentSrc) {
  DCHECK(isMainThread());
  return context()->getSecurityOrigin() &&
         context()->getSecurityOrigin()->canRequest(currentSrc);
}

void MediaElementAudioSourceHandler::printCORSMessage(const String& message) {
  if (context()->getExecutionContext()) {
    context()->getExecutionContext()->addConsoleMessage(
        ConsoleMessage::create(SecurityMessageSource, InfoMessageLevel,
                               "MediaElementAudioSource outputs zeroes due to "
                               "CORS access restrictions for " +
                                   message));
  }
}

void MediaElementAudioSourceHandler::process(size_t numberOfFrames) {
  AudioBus* outputBus = output(0).bus();

  // Use a tryLock() to avoid contention in the real-time audio thread.
  // If we fail to acquire the lock then the HTMLMediaElement must be in the
  // middle of reconfiguring its playback engine, so we output silence in this
  // case.
  MutexTryLocker tryLocker(m_processLock);
  if (tryLocker.locked()) {
    if (!mediaElement() || !m_sourceNumberOfChannels || !m_sourceSampleRate) {
      outputBus->zero();
      return;
    }
    AudioSourceProvider& provider = mediaElement()->getAudioSourceProvider();
    // Grab data from the provider so that the element continues to make
    // progress, even if we're going to output silence anyway.
    if (m_multiChannelResampler.get()) {
      DCHECK_NE(m_sourceSampleRate, sampleRate());
      m_multiChannelResampler->process(&provider, outputBus, numberOfFrames);
    } else {
      // Bypass the resampler completely if the source is at the context's
      // sample-rate.
      DCHECK_EQ(m_sourceSampleRate, sampleRate());
      provider.provideInput(outputBus, numberOfFrames);
    }
    // Output silence if we don't have access to the element.
    if (!passesCORSAccessCheck()) {
      if (m_maybePrintCORSMessage) {
        // Print a CORS message, but just once for each change in the current
        // media element source, and only if we have a document to print to.
        m_maybePrintCORSMessage = false;
        if (context()->getExecutionContext()) {
          context()->getExecutionContext()->postTask(
              BLINK_FROM_HERE,
              createCrossThreadTask(
                  &MediaElementAudioSourceHandler::printCORSMessage,
                  PassRefPtr<MediaElementAudioSourceHandler>(this),
                  m_currentSrcString));
        }
      }
      outputBus->zero();
    }
  } else {
    // We failed to acquire the lock.
    outputBus->zero();
  }
}

void MediaElementAudioSourceHandler::lock() {
  m_processLock.lock();
}

void MediaElementAudioSourceHandler::unlock() {
  m_processLock.unlock();
}

// ----------------------------------------------------------------

MediaElementAudioSourceNode::MediaElementAudioSourceNode(
    BaseAudioContext& context,
    HTMLMediaElement& mediaElement)
    : AudioSourceNode(context) {
  setHandler(MediaElementAudioSourceHandler::create(*this, mediaElement));
}

MediaElementAudioSourceNode* MediaElementAudioSourceNode::create(
    BaseAudioContext& context,
    HTMLMediaElement& mediaElement,
    ExceptionState& exceptionState) {
  DCHECK(isMainThread());

  if (context.isContextClosed()) {
    context.throwExceptionForClosedState(exceptionState);
    return nullptr;
  }

  // First check if this media element already has a source node.
  if (mediaElement.audioSourceNode()) {
    exceptionState.throwDOMException(InvalidStateError,
                                     "HTMLMediaElement already connected "
                                     "previously to a different "
                                     "MediaElementSourceNode.");
    return nullptr;
  }

  MediaElementAudioSourceNode* node =
      new MediaElementAudioSourceNode(context, mediaElement);

  if (node) {
    mediaElement.setAudioSourceNode(node);
    // context keeps reference until node is disconnected
    context.notifySourceNodeStartedProcessing(node);
  }

  return node;
}

MediaElementAudioSourceNode* MediaElementAudioSourceNode::create(
    BaseAudioContext* context,
    const MediaElementAudioSourceOptions& options,
    ExceptionState& exceptionState) {
  if (!options.hasMediaElement()) {
    exceptionState.throwDOMException(NotFoundError,
                                     "mediaElement member is required.");
    return nullptr;
  }

  return create(*context, *options.mediaElement(), exceptionState);
}

DEFINE_TRACE(MediaElementAudioSourceNode) {
  AudioSourceProviderClient::trace(visitor);
  AudioSourceNode::trace(visitor);
}

MediaElementAudioSourceHandler&
MediaElementAudioSourceNode::mediaElementAudioSourceHandler() const {
  return static_cast<MediaElementAudioSourceHandler&>(handler());
}

HTMLMediaElement* MediaElementAudioSourceNode::mediaElement() const {
  return mediaElementAudioSourceHandler().mediaElement();
}

void MediaElementAudioSourceNode::setFormat(size_t numberOfChannels,
                                            float sampleRate) {
  mediaElementAudioSourceHandler().setFormat(numberOfChannels, sampleRate);
}

void MediaElementAudioSourceNode::onCurrentSrcChanged(const KURL& currentSrc) {
  mediaElementAudioSourceHandler().onCurrentSrcChanged(currentSrc);
}

void MediaElementAudioSourceNode::lock() {
  mediaElementAudioSourceHandler().lock();
}

void MediaElementAudioSourceNode::unlock() {
  mediaElementAudioSourceHandler().unlock();
}

}  // namespace blink
