/*
 * Copyright (C) 2010, 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/ChannelSplitterNode.h"
#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
#include "modules/webaudio/AudioNodeInput.h"
#include "modules/webaudio/AudioNodeOutput.h"
#include "modules/webaudio/BaseAudioContext.h"
#include "modules/webaudio/ChannelSplitterOptions.h"

namespace blink {

ChannelSplitterHandler::ChannelSplitterHandler(AudioNode& node,
                                               float sample_rate,
                                               unsigned number_of_outputs)
    : AudioHandler(kNodeTypeChannelSplitter, node, sample_rate) {
  // These properties are fixed and cannot be changed by the user.
  channel_count_ = number_of_outputs;
  SetInternalChannelCountMode(kExplicit);
  SetInternalChannelInterpretation(AudioBus::kDiscrete);
  AddInput();

  // Create a fixed number of outputs (able to handle the maximum number of
  // channels fed to an input).
  for (unsigned i = 0; i < number_of_outputs; ++i)
    AddOutput(1);

  Initialize();
}

scoped_refptr<ChannelSplitterHandler> ChannelSplitterHandler::Create(
    AudioNode& node,
    float sample_rate,
    unsigned number_of_outputs) {
  return base::AdoptRef(
      new ChannelSplitterHandler(node, sample_rate, number_of_outputs));
}

void ChannelSplitterHandler::Process(size_t frames_to_process) {
  AudioBus* source = Input(0).Bus();
  DCHECK(source);
  DCHECK_EQ(frames_to_process, source->length());

  unsigned number_of_source_channels = source->NumberOfChannels();

  for (unsigned i = 0; i < NumberOfOutputs(); ++i) {
    AudioBus* destination = Output(i).Bus();
    DCHECK(destination);

    if (i < number_of_source_channels) {
      // Split the channel out if it exists in the source.
      // It would be nice to avoid the copy and simply pass along pointers, but
      // this becomes extremely difficult with fanout and fanin.
      destination->Channel(0)->CopyFrom(source->Channel(i));
    } else if (Output(i).RenderingFanOutCount() > 0) {
      // Only bother zeroing out the destination if it's connected to anything
      destination->Zero();
    }
  }
}

void ChannelSplitterHandler::SetChannelCount(unsigned long channel_count,
                                             ExceptionState& exception_state) {
  DCHECK(IsMainThread());
  BaseAudioContext::GraphAutoLocker locker(Context());

  // channelCount cannot be changed from the number of outputs.
  if (channel_count != NumberOfOutputs()) {
    exception_state.ThrowDOMException(
        kInvalidStateError,
        "ChannelSplitter: channelCount cannot be changed from " +
            String::Number(NumberOfOutputs()));
  }
}

void ChannelSplitterHandler::SetChannelCountMode(
    const String& mode,
    ExceptionState& exception_state) {
  DCHECK(IsMainThread());
  BaseAudioContext::GraphAutoLocker locker(Context());

  // channcelCountMode must be 'explicit'.
  if (mode != "explicit") {
    exception_state.ThrowDOMException(
        kInvalidStateError,
        "ChannelSplitter: channelCountMode cannot be changed from 'explicit'");
  }
}

void ChannelSplitterHandler::SetChannelInterpretation(
    const String& mode,
    ExceptionState& exception_state) {
  DCHECK(IsMainThread());
  BaseAudioContext::GraphAutoLocker locker(Context());

  // channelInterpretation must be "discrete"
  if (mode != "discrete") {
    exception_state.ThrowDOMException(kInvalidStateError,
                                      "ChannelSplitter: channelInterpretation "
                                      "cannot be changed from 'discrete'");
  }
}

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

ChannelSplitterNode::ChannelSplitterNode(BaseAudioContext& context,
                                         unsigned number_of_outputs)
    : AudioNode(context) {
  SetHandler(ChannelSplitterHandler::Create(*this, context.sampleRate(),
                                            number_of_outputs));
}

ChannelSplitterNode* ChannelSplitterNode::Create(
    BaseAudioContext& context,
    ExceptionState& exception_state) {
  DCHECK(IsMainThread());

  // Default number of outputs for the splitter node is 6.
  return Create(context, 6, exception_state);
}

ChannelSplitterNode* ChannelSplitterNode::Create(
    BaseAudioContext& context,
    unsigned number_of_outputs,
    ExceptionState& exception_state) {
  DCHECK(IsMainThread());

  if (context.IsContextClosed()) {
    context.ThrowExceptionForClosedState(exception_state);
    return nullptr;
  }

  if (!number_of_outputs ||
      number_of_outputs > BaseAudioContext::MaxNumberOfChannels()) {
    exception_state.ThrowDOMException(
        kIndexSizeError, ExceptionMessages::IndexOutsideRange<size_t>(
                             "number of outputs", number_of_outputs, 1,
                             ExceptionMessages::kInclusiveBound,
                             BaseAudioContext::MaxNumberOfChannels(),
                             ExceptionMessages::kInclusiveBound));
    return nullptr;
  }

  return new ChannelSplitterNode(context, number_of_outputs);
}

ChannelSplitterNode* ChannelSplitterNode::Create(
    BaseAudioContext* context,
    const ChannelSplitterOptions& options,
    ExceptionState& exception_state) {
  ChannelSplitterNode* node =
      Create(*context, options.numberOfOutputs(), exception_state);

  if (!node)
    return nullptr;

  node->HandleChannelOptions(options, exception_state);

  return node;
}

}  // namespace blink
