зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1130010: Implement the new AudioNode.disconnect methods. r=dminor,ehsan
Initial patch by Thomas Escalon <tesc.bugzilla@gmail.com>. MozReview-Commit-ID: KDnmKIGWYL
This commit is contained in:
Родитель
fc8ba03399
Коммит
5056af1d5d
|
@ -291,14 +291,9 @@ AudioNode::SendChannelMixingParametersToStream()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv)
|
||||
bool
|
||||
AudioNode::DisconnectFromOutputIfConnected(AudioNode& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex)
|
||||
{
|
||||
if (aOutput >= NumberOfOutputs()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
WEB_AUDIO_API_LOG("%f: %s %u Disconnect()", Context()->CurrentTime(),
|
||||
NodeType(), Id());
|
||||
|
||||
|
@ -322,41 +317,91 @@ AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv)
|
|||
RefPtr<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.
|
||||
RefPtr<AudioNode> output = mOutputNodes[i].forget();
|
||||
mOutputNodes.RemoveElementAt(i);
|
||||
output->NotifyInputsChanged();
|
||||
if (mStream) {
|
||||
RefPtr<nsIRunnable> runnable = new RunnableRelease(output.forget());
|
||||
mStream->RunAfterPendingUpdates(runnable.forget());
|
||||
}
|
||||
break;
|
||||
InputNode& input = aDestination.mInputNodes[aInputIndex];
|
||||
if (input.mInputNode != this) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Destroying the InputNode here sends a message to the graph thread
|
||||
// to disconnect the streams, which should be sent before the
|
||||
// RunAfterPendingUpdates() call below.
|
||||
aDestination.mInputNodes.RemoveElementAt(aInputIndex);
|
||||
// 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.
|
||||
RefPtr<AudioNode> output = mOutputNodes[aOutputIndex].forget();
|
||||
mOutputNodes.RemoveElementAt(aOutputIndex);
|
||||
output->NotifyInputsChanged();
|
||||
if (mStream) {
|
||||
nsCOMPtr<nsIRunnable> runnable = new RunnableRelease(output.forget());
|
||||
mStream->RunAfterPendingUpdates(runnable.forget());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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::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 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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -365,6 +410,133 @@ AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv)
|
|||
Context()->UpdatePannerSource();
|
||||
}
|
||||
|
||||
void
|
||||
AudioNode::Disconnect(AudioNode& aDestination, ErrorResult& aRv)
|
||||
{
|
||||
bool wasConnected = false;
|
||||
|
||||
size_t outputIndex = mOutputNodes.IndexOf(&aDestination);
|
||||
if (outputIndex == nsTArray<InputNode>::NoIndex) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
for (int32_t inputIndex = aDestination.mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) {
|
||||
wasConnected |= DisconnectFromOutputIfConnected(aDestination, outputIndex, inputIndex);
|
||||
}
|
||||
|
||||
if (!wasConnected) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// This disconnection may have disconnected a panner and a source.
|
||||
Context()->UpdatePannerSource();
|
||||
}
|
||||
|
||||
void
|
||||
AudioNode::Disconnect(AudioNode& 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 = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) {
|
||||
for (int32_t inputIndex = aDestination.mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) {
|
||||
InputNode& input = aDestination.mInputNodes[inputIndex];
|
||||
if (input.mOutputPort == aOutput) {
|
||||
wasConnected |= DisconnectFromOutputIfConnected(aDestination, outputIndex, inputIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!wasConnected) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// This disconnection may have disconnected a panner and a source.
|
||||
Context()->UpdatePannerSource();
|
||||
}
|
||||
|
||||
void
|
||||
AudioNode::Disconnect(AudioNode& aDestination, uint32_t aOutput, uint32_t aInput, ErrorResult& aRv)
|
||||
{
|
||||
if (aOutput >= NumberOfOutputs()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aInput >= aDestination.NumberOfInputs()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
bool wasConnected = false;
|
||||
|
||||
for (int32_t outputIndex = mOutputNodes.Length() - 1; outputIndex >= 0; --outputIndex) {
|
||||
for (int32_t inputIndex = aDestination.mInputNodes.Length() - 1; inputIndex >= 0; --inputIndex) {
|
||||
InputNode& input = aDestination.mInputNodes[inputIndex];
|
||||
if (input.mOutputPort == aOutput && input.mInputPort == aInput) {
|
||||
wasConnected |= DisconnectFromOutputIfConnected(aDestination, outputIndex, inputIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!wasConnected) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// This disconnection may have disconnected a panner and a source.
|
||||
Context()->UpdatePannerSource();
|
||||
}
|
||||
|
||||
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(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::DestroyMediaStream()
|
||||
{
|
||||
|
|
|
@ -94,7 +94,17 @@ public:
|
|||
virtual void Connect(AudioParam& aDestination, uint32_t aOutput,
|
||||
ErrorResult& aRv);
|
||||
|
||||
virtual void Disconnect(ErrorResult& aRv);
|
||||
virtual void Disconnect(uint32_t aOutput, ErrorResult& aRv);
|
||||
virtual void Disconnect(AudioNode& aDestination, ErrorResult& aRv);
|
||||
virtual void Disconnect(AudioNode& aDestination, uint32_t aOutput,
|
||||
ErrorResult& aRv);
|
||||
virtual void Disconnect(AudioNode& aDestination,
|
||||
uint32_t aOutput, uint32_t aInput,
|
||||
ErrorResult& aRv);
|
||||
virtual void Disconnect(AudioParam& aDestination, ErrorResult& aRv);
|
||||
virtual void Disconnect(AudioParam& aDestination, uint32_t aOutput,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// Called after input nodes have been explicitly added or removed through
|
||||
// the Connect() or Disconnect() methods.
|
||||
|
@ -220,6 +230,8 @@ private:
|
|||
}
|
||||
// Callers must hold a reference to 'this'.
|
||||
void DisconnectFromGraph();
|
||||
bool DisconnectFromOutputIfConnected(AudioNode& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex);
|
||||
bool DisconnectFromParamIfConnected(AudioParam& aDestination, uint32_t aOutputIndex, uint32_t aInputIndex);
|
||||
|
||||
protected:
|
||||
// Helpers for sending different value types to streams
|
||||
|
|
|
@ -50,13 +50,15 @@ public:
|
|||
UpdateConnectedStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void Disconnect(ErrorResult& aRv) override
|
||||
{
|
||||
AudioNode::Disconnect(aRv);
|
||||
UpdateConnectedStatus();
|
||||
}
|
||||
void Disconnect(uint32_t aOutput, ErrorResult& aRv) override
|
||||
{
|
||||
AudioNode::Disconnect(aOutput, aRv);
|
||||
if (!aRv.Failed()) {
|
||||
UpdateConnectedStatus();
|
||||
}
|
||||
UpdateConnectedStatus();
|
||||
}
|
||||
void NotifyInputsChanged() override
|
||||
{
|
||||
|
@ -68,7 +70,31 @@ public:
|
|||
// No need to UpdateConnectedStatus() because there was previously an
|
||||
// input in InputNodes().
|
||||
}
|
||||
|
||||
void Disconnect(AudioNode& aDestination, ErrorResult& aRv) override
|
||||
{
|
||||
AudioNode::Disconnect(aDestination, aRv);
|
||||
UpdateConnectedStatus();
|
||||
}
|
||||
void Disconnect(AudioNode& aDestination, uint32_t aOutput, ErrorResult& aRv) override
|
||||
{
|
||||
AudioNode::Disconnect(aDestination, aOutput, aRv);
|
||||
UpdateConnectedStatus();
|
||||
}
|
||||
void Disconnect(AudioNode& aDestination, uint32_t aOutput, uint32_t aInput, ErrorResult& aRv) override
|
||||
{
|
||||
AudioNode::Disconnect(aDestination, aOutput, aInput, aRv);
|
||||
UpdateConnectedStatus();
|
||||
}
|
||||
void Disconnect(AudioParam& aDestination, ErrorResult& aRv) override
|
||||
{
|
||||
AudioNode::Disconnect(aDestination, aRv);
|
||||
UpdateConnectedStatus();
|
||||
}
|
||||
void Disconnect(AudioParam& aDestination, uint32_t aOutput, ErrorResult& aRv) override
|
||||
{
|
||||
AudioNode::Disconnect(aDestination, aOutput, aRv);
|
||||
UpdateConnectedStatus();
|
||||
}
|
||||
void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) override
|
||||
{
|
||||
if (aChannelCount != ChannelCount()) {
|
||||
|
|
|
@ -29,7 +29,19 @@ interface AudioNode : EventTarget {
|
|||
[Throws]
|
||||
void connect(AudioParam destination, optional unsigned long output = 0);
|
||||
[Throws]
|
||||
void disconnect(optional unsigned long output = 0);
|
||||
void disconnect();
|
||||
[Throws]
|
||||
void disconnect(unsigned long output);
|
||||
[Throws]
|
||||
void disconnect(AudioNode destination);
|
||||
[Throws]
|
||||
void disconnect(AudioNode destination, unsigned long output);
|
||||
[Throws]
|
||||
void disconnect(AudioNode destination, unsigned long output, unsigned long input);
|
||||
[Throws]
|
||||
void disconnect(AudioParam destination);
|
||||
[Throws]
|
||||
void disconnect(AudioParam destination, unsigned long output);
|
||||
|
||||
readonly attribute AudioContext context;
|
||||
readonly attribute unsigned long numberOfInputs;
|
||||
|
|
Загрузка…
Ссылка в новой задаче