void AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv) { if (aOutput >= NumberOfOutputs()) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } for (int32_t outputIndex = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) { AudioNode* dest = mOutputNodes[outputIndex]; for (int32_t inputIndex = dest->mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) { InputNode& input = dest->mInputNodes[inputIndex]; if (input.mOutputPort == aOutput) { DisconnectFromOutputIfConnected(*dest, outputIndex, inputIndex); } } } for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) { AudioParam* dest = mOutputParams[outputIndex]; for (int32_t inputIndex = dest->InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) { const InputNode& input = dest->InputNodes()[inputIndex]; if (input.mOutputPort == aOutput) { DisconnectFromParamIfConnected(*dest, outputIndex, inputIndex); } } } // This disconnection may have disconnected a panner and a source. Context()->UpdatePannerSource(); }
static void valueAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { INC_STATS("DOM.AudioParam.value._set"); AudioParam* imp = V8AudioParam::toNative(info.Holder()); float v = static_cast<float>(value->NumberValue()); imp->setValue(v); return; }
static v8::Handle<v8::Value> cancelScheduledValuesCallback(const v8::Arguments& args) { INC_STATS("DOM.AudioParam.cancelScheduledValues"); if (args.Length() < 1) return throwError("Not enough arguments", V8Proxy::TypeError); AudioParam* imp = V8AudioParam::toNative(args.Holder()); EXCEPTION_BLOCK(float, startTime, static_cast<float>(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined)->NumberValue())); imp->cancelScheduledValues(startTime); return v8::Handle<v8::Value>(); }
void AudioNodeOutput::disconnectAllParams() { ASSERT(context()->isGraphOwner()); // AudioParam::disconnect() changes m_params by calling removeParam(). while (m_params.size()) { AudioParam* param = *m_params.begin(); param->disconnect(this); } }
static v8::Handle<v8::Value> exponentialRampToValueAtTimeCallback(const v8::Arguments& args) { INC_STATS("DOM.AudioParam.exponentialRampToValueAtTime"); if (args.Length() < 2) return throwError("Not enough arguments", V8Proxy::TypeError); AudioParam* imp = V8AudioParam::toNative(args.Holder()); EXCEPTION_BLOCK(float, value, static_cast<float>(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined)->NumberValue())); EXCEPTION_BLOCK(float, time, static_cast<float>(MAYBE_MISSING_PARAMETER(args, 1, MissingIsUndefined)->NumberValue())); imp->exponentialRampToValueAtTime(value, time); return v8::Handle<v8::Value>(); }
static v8::Handle<v8::Value> setValueCurveAtTimeCallback(const v8::Arguments& args) { INC_STATS("DOM.AudioParam.setValueCurveAtTime"); if (args.Length() < 3) return throwError("Not enough arguments", V8Proxy::TypeError); AudioParam* imp = V8AudioParam::toNative(args.Holder()); EXCEPTION_BLOCK(Float32Array*, values, V8Float32Array::HasInstance(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined)) ? V8Float32Array::toNative(v8::Handle<v8::Object>::Cast(MAYBE_MISSING_PARAMETER(args, 0, MissingIsUndefined))) : 0); EXCEPTION_BLOCK(float, time, static_cast<float>(MAYBE_MISSING_PARAMETER(args, 1, MissingIsUndefined)->NumberValue())); EXCEPTION_BLOCK(float, duration, static_cast<float>(MAYBE_MISSING_PARAMETER(args, 2, MissingIsUndefined)->NumberValue())); imp->setValueCurveAtTime(values, time, duration); return v8::Handle<v8::Value>(); }
bool AudioNode::DisconnectFromParamIfConnected(AudioParam& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex) { MOZ_ASSERT(aOutputIndex < mOutputParams.Length()); MOZ_ASSERT(aInputIndex < aDestination.InputNodes().Length()); const InputNode& input = aDestination.InputNodes()[aInputIndex]; if (input.mInputNode != this) { return false; } aDestination.RemoveInputNode(aInputIndex); // Remove one instance of 'dest' from mOutputParams. There could be // others, and it's not correct to remove them all since some of them // could be for different output ports. mOutputParams.RemoveElementAt(aOutputIndex); return true; }
void AudioNode::Disconnect(ErrorResult& aRv) { for (int32_t outputIndex = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) { AudioNode* dest = mOutputNodes[outputIndex]; for (int32_t inputIndex = dest->mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) { DisconnectFromOutputIfConnected(*dest, outputIndex, inputIndex); } } for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) { AudioParam* dest = mOutputParams[outputIndex]; for (int32_t inputIndex = dest->InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) { DisconnectFromParamIfConnected(*dest, outputIndex, inputIndex); } } // This disconnection may have disconnected a panner and a source. Context()->UpdatePannerSource(); }
void AudioNode::Connect(AudioParam& aDestination, uint32_t aOutput, ErrorResult& aRv) { if (aOutput >= NumberOfOutputs()) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } if (Context() != aDestination.GetParentObject()) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return; } if (FindIndexOfNodeWithPorts(aDestination.InputNodes(), this, INVALID_PORT, aOutput) != nsTArray<AudioNode::InputNode>::NoIndex) { // connection already exists. return; } mOutputParams.AppendElement(&aDestination); InputNode* input = aDestination.AppendInputNode(); input->mInputNode = this; input->mInputPort = INVALID_PORT; input->mOutputPort = aOutput; MediaStream* stream = aDestination.Stream(); MOZ_ASSERT(stream->AsProcessedStream()); ProcessedMediaStream* ps = static_cast<ProcessedMediaStream*>(stream); if (mStream) { // Setup our stream as an input to the AudioParam's stream MOZ_ASSERT(aOutput <= UINT16_MAX, "Unexpected large output port number"); input->mStreamPort = ps->AllocateInputPort(mStream, AudioNodeStream::AUDIO_TRACK, TRACK_ANY, 0, static_cast<uint16_t>(aOutput)); } }
void AudioNode::Disconnect(AudioParam& aDestination, uint32_t aOutput, ErrorResult& aRv) { if (aOutput >= NumberOfOutputs()) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } bool wasConnected = false; for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) { for (int32_t inputIndex = aDestination.InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) { const InputNode& input = aDestination.InputNodes()[inputIndex]; if (input.mOutputPort == aOutput) { wasConnected |= DisconnectFromParamIfConnected(aDestination, outputIndex, inputIndex); } } } if (!wasConnected) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return; } }
void AudioNode::Disconnect(AudioParam& aDestination, ErrorResult& aRv) { bool wasConnected = false; for (int32_t outputIndex = mOutputParams.Length() - 1; outputIndex >= 0; --outputIndex) { for (int32_t inputIndex = aDestination.InputNodes().Length() - 1; inputIndex >= 0; --inputIndex) { wasConnected |= DisconnectFromParamIfConnected(aDestination, outputIndex, inputIndex); } } if (!wasConnected) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return; } }
void AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv) { if (aOutput >= NumberOfOutputs()) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } // An upstream node may be starting to play on the graph thread, and the // engine for a downstream node may be sending a PlayingRefChangeHandler // ADDREF message to this (main) thread. Wait for a round trip before // releasing nodes, to give engines receiving sound now time to keep their // nodes alive. class RunnableRelease final : public nsRunnable { public: explicit RunnableRelease(already_AddRefed<AudioNode> aNode) : mNode(aNode) {} NS_IMETHODIMP Run() override { mNode = nullptr; return NS_OK; } private: nsRefPtr<AudioNode> mNode; }; for (int32_t i = mOutputNodes.Length() - 1; i >= 0; --i) { AudioNode* dest = mOutputNodes[i]; for (int32_t j = dest->mInputNodes.Length() - 1; j >= 0; --j) { InputNode& input = dest->mInputNodes[j]; if (input.mInputNode == this && input.mOutputPort == aOutput) { // Destroying the InputNode here sends a message to the graph thread // to disconnect the streams, which should be sent before the // RunAfterPendingUpdates() call below. dest->mInputNodes.RemoveElementAt(j); // Remove one instance of 'dest' from mOutputNodes. There could be // others, and it's not correct to remove them all since some of them // could be for different output ports. nsRefPtr<AudioNode> output = mOutputNodes[i].forget(); mOutputNodes.RemoveElementAt(i); output->NotifyInputsChanged(); if (mStream) { nsRefPtr<nsIRunnable> runnable = new RunnableRelease(output.forget()); mStream->RunAfterPendingUpdates(runnable.forget()); } break; } } } for (int32_t i = mOutputParams.Length() - 1; i >= 0; --i) { AudioParam* dest = mOutputParams[i]; for (int32_t j = dest->InputNodes().Length() - 1; j >= 0; --j) { const InputNode& input = dest->InputNodes()[j]; if (input.mInputNode == this && input.mOutputPort == aOutput) { dest->RemoveInputNode(j); // Remove one instance of 'dest' from mOutputParams. There could be // others, and it's not correct to remove them all since some of them // could be for different output ports. mOutputParams.RemoveElementAt(i); break; } } } // This disconnection may have disconnected a panner and a source. Context()->UpdatePannerSource(); }
static v8::Handle<v8::Value> unitsAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.AudioParam.units._get"); AudioParam* imp = V8AudioParam::toNative(info.Holder()); return v8::Integer::New(imp->units()); }
static v8::Handle<v8::Value> nameAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { INC_STATS("DOM.AudioParam.name._get"); AudioParam* imp = V8AudioParam::toNative(info.Holder()); return v8String(imp->name()); }