| // Copyright 2015 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "cobalt/audio/audio_node.h" |
| |
| #include "cobalt/audio/audio_context.h" |
| #include "cobalt/dom/dom_exception.h" |
| |
| namespace cobalt { |
| namespace audio { |
| |
| AudioNode::AudioNode(AudioContext* context) |
| : audio_context_(context), |
| audio_lock_(context->audio_lock()), |
| channel_count_(2), |
| channel_count_mode_(kAudioNodeChannelCountModeMax), |
| channel_interpretation_(kAudioNodeChannelInterpretationSpeakers) {} |
| |
| AudioNode::~AudioNode() { |
| AudioLock::AutoLock lock(audio_lock()); |
| |
| RemoveAllInputs(); |
| RemoveAllOutputs(); |
| } |
| |
| scoped_refptr<AudioContext> AudioNode::context() const { |
| return audio_context_; |
| } |
| |
| void AudioNode::set_channel_count(uint32 channel_count, |
| script::ExceptionState* exception_state) { |
| AudioLock::AutoLock lock(audio_lock()); |
| |
| // If this value is set to zero, the implementation MUST throw a |
| // NOT_SUPPORTED_ERR exception. |
| if (channel_count == 0) { |
| dom::DOMException::Raise(dom::DOMException::kNotSupportedErr, |
| "Audio node channel count must be non-zero.", |
| exception_state); |
| return; |
| } |
| |
| // TODO: Check if this AudioNode is destination when setting the |
| // channel count. If it is destination, channel count may be set to any |
| // non-zero value less than or equal to max channel count of the destination. |
| // An INDEX_SIZE_ERR exception MUST be thrown if this value is not within the |
| // valid range. |
| channel_count_ = channel_count; |
| } |
| |
| void AudioNode::set_channel_count_mode( |
| const AudioNodeChannelCountMode& channel_count_mode) { |
| AudioLock::AutoLock lock(audio_lock()); |
| |
| channel_count_mode_ = channel_count_mode; |
| } |
| |
| void AudioNode::set_channel_interpretation( |
| const AudioNodeChannelInterpretation& channel_interpretation) { |
| AudioLock::AutoLock lock(audio_lock()); |
| |
| channel_interpretation_ = channel_interpretation; |
| } |
| |
| void AudioNode::Connect(const scoped_refptr<AudioNode>& destination, |
| uint32 output, uint32 input, |
| script::ExceptionState* exception_state) { |
| AudioLock::AutoLock lock(audio_lock()); |
| |
| // The destination parameter is the AudioNode to connect to. |
| if (!destination) { |
| dom::DOMException::Raise(dom::DOMException::kSyntaxErr, exception_state); |
| return; |
| } |
| // The output parameter is an index describing which output of the AudioNode |
| // from which to connect. If this paremeter is out-of-bound, an INDEX_SIZE_ERR |
| // exception MUST be thrown. |
| if (output >= number_of_outputs()) { |
| dom::DOMException::Raise(dom::DOMException::kIndexSizeErr, exception_state); |
| return; |
| } |
| // The input parameter is an index describing which input of the destination |
| // AudioNode to connect to. If this parameter is out-of-bound, an |
| // INDEX_SIZE_ERR exception MUST be thrown. |
| if (input >= destination->number_of_inputs()) { |
| dom::DOMException::Raise(dom::DOMException::kIndexSizeErr, exception_state); |
| return; |
| } |
| |
| // TODO: Detect if there is a cycle when connecting an AudioNode to |
| // another AudioNode. A cycle is allowed only if there is at least one |
| // DelayNode in the cycle or a NOT_SUPPORTED_ERR exception MUST be thrown. |
| AudioNodeInput* input_node = destination->inputs_[input]; |
| AudioNodeOutput* output_node = outputs_[output]; |
| |
| DCHECK(input_node); |
| DCHECK(output_node); |
| |
| input_node->Connect(output_node); |
| } |
| |
| void AudioNode::Disconnect(uint32 output, |
| script::ExceptionState* exception_state) { |
| AudioLock::AutoLock lock(audio_lock()); |
| |
| // The output parameter is an index describing which output of the AudioNode |
| // to disconnect. If the output parameter is out-of-bounds, an INDEX_SIZE_ERR |
| // exception MUST be thrown. |
| if (output >= number_of_outputs()) { |
| dom::DOMException::Raise(dom::DOMException::kIndexSizeErr, exception_state); |
| return; |
| } |
| |
| scoped_refptr<AudioNodeOutput> output_node = outputs_[output]; |
| |
| DCHECK(output_node); |
| output_node->DisconnectAll(); |
| } |
| |
| void AudioNode::AddInput(const scoped_refptr<AudioNodeInput>& input) { |
| audio_lock()->AssertLocked(); |
| |
| DCHECK(input); |
| |
| inputs_.push_back(input); |
| } |
| |
| void AudioNode::AddOutput(const scoped_refptr<AudioNodeOutput>& output) { |
| audio_lock()->AssertLocked(); |
| |
| DCHECK(output); |
| |
| outputs_.push_back(output); |
| } |
| |
| void AudioNode::RemoveAllInputs() { |
| audio_lock()->AssertLocked(); |
| |
| while (!inputs_.empty()) { |
| scoped_refptr<AudioNodeInput> input = inputs_.back(); |
| input->DisconnectAll(); |
| inputs_.pop_back(); |
| } |
| } |
| |
| void AudioNode::RemoveAllOutputs() { |
| audio_lock()->AssertLocked(); |
| |
| while (!outputs_.empty()) { |
| scoped_refptr<AudioNodeOutput> output = outputs_.back(); |
| output->DisconnectAll(); |
| outputs_.pop_back(); |
| } |
| } |
| |
| AudioNodeInput* AudioNode::Input(int32 index) const { |
| audio_lock()->AssertLocked(); |
| |
| size_t input_index = static_cast<size_t>(index); |
| if (input_index < inputs_.size()) { |
| return inputs_[input_index].get(); |
| } |
| return NULL; |
| } |
| |
| AudioNodeOutput* AudioNode::Output(int32 index) const { |
| audio_lock()->AssertLocked(); |
| |
| size_t output_index = static_cast<size_t>(index); |
| if (output_index < outputs_.size()) { |
| return outputs_[output_index].get(); |
| } |
| return NULL; |
| } |
| |
| } // namespace audio |
| } // namespace cobalt |