mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 20:05:49 +00:00
Bug 866434 - Part 1: Make it possible to connect an AudioNode to an AudioParam; r=roc
This commit is contained in:
parent
11c6d3c7eb
commit
caeeb616ee
@ -13,14 +13,18 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
static const uint32_t INVALID_PORT = 0xffffffff;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AudioNode, nsDOMEventTargetHelper)
|
||||
tmp->DisconnectFromGraph();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputNodes)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputParams)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AudioNode, nsDOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputNodes)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputParams)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(AudioNode, nsDOMEventTargetHelper)
|
||||
@ -59,6 +63,7 @@ AudioNode::~AudioNode()
|
||||
{
|
||||
MOZ_ASSERT(mInputNodes.IsEmpty());
|
||||
MOZ_ASSERT(mOutputNodes.IsEmpty());
|
||||
MOZ_ASSERT(mOutputParams.IsEmpty());
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
@ -114,6 +119,16 @@ AudioNode::DisconnectFromGraph()
|
||||
output->mInputNodes.RemoveElementAt(inputIndex);
|
||||
}
|
||||
|
||||
while (!mOutputParams.IsEmpty()) {
|
||||
uint32_t i = mOutputParams.Length() - 1;
|
||||
nsRefPtr<AudioParam> output = mOutputParams[i].forget();
|
||||
mOutputParams.RemoveElementAt(i);
|
||||
uint32_t inputIndex = FindIndexOfNode(output->InputNodes(), this);
|
||||
// It doesn't matter which one we remove, since we're going to remove all
|
||||
// entries for this node anyway.
|
||||
output->RemoveInputNode(inputIndex);
|
||||
}
|
||||
|
||||
DestroyMediaStream();
|
||||
}
|
||||
|
||||
@ -159,6 +174,33 @@ AudioNode::Connect(AudioNode& aDestination, uint32_t aOutput,
|
||||
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_SYNTAX_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;
|
||||
}
|
||||
|
||||
void
|
||||
AudioNode::SendDoubleParameterToStream(uint32_t aIndex, double aValue)
|
||||
{
|
||||
@ -224,6 +266,21 @@ AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv)
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
@ -249,5 +306,11 @@ AudioNode::DestroyMediaStream()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioNode::RemoveOutputParam(AudioParam* aParam)
|
||||
{
|
||||
mOutputParams.RemoveElement(aParam);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class AudioParam;
|
||||
struct ThreeDPoint;
|
||||
|
||||
template<class T>
|
||||
@ -108,6 +109,9 @@ public:
|
||||
virtual void Connect(AudioNode& aDestination, uint32_t aOutput,
|
||||
uint32_t aInput, ErrorResult& aRv);
|
||||
|
||||
virtual void Connect(AudioParam& aDestination, uint32_t aOutput,
|
||||
ErrorResult& aRv);
|
||||
|
||||
virtual void Disconnect(uint32_t aOutput, ErrorResult& aRv);
|
||||
|
||||
// The following two virtual methods must be implemented by each node type
|
||||
@ -153,6 +157,7 @@ public:
|
||||
AudioNode* mInputNode;
|
||||
nsRefPtr<MediaInputPort> mStreamPort;
|
||||
// The index of the input port this node feeds into.
|
||||
// This is not used for connections to AudioParams.
|
||||
uint32_t mInputPort;
|
||||
// The index of the output port this node comes out of.
|
||||
uint32_t mOutputPort;
|
||||
@ -165,6 +170,8 @@ public:
|
||||
return mInputNodes;
|
||||
}
|
||||
|
||||
void RemoveOutputParam(AudioParam* aParam);
|
||||
|
||||
private:
|
||||
// This could possibly delete 'this'.
|
||||
void DisconnectFromGraph();
|
||||
@ -197,6 +204,12 @@ private:
|
||||
// exact matching entry, since mOutputNodes doesn't include the port
|
||||
// identifiers and the same node could be connected on multiple ports.
|
||||
nsTArray<nsRefPtr<AudioNode> > mOutputNodes;
|
||||
// For every mOutputParams entry, there is a corresponding entry in
|
||||
// AudioParam::mInputNodes of the mOutputParams entry. We won't necessarily be
|
||||
// able to identify the exact matching entry, since mOutputParams doesn't
|
||||
// include the port identifiers and the same node could be connected on
|
||||
// multiple ports.
|
||||
nsTArray<nsRefPtr<AudioParam> > mOutputParams;
|
||||
uint32_t mChannelCount;
|
||||
ChannelCountMode mChannelCountMode;
|
||||
ChannelInterpretation mChannelInterpretation;
|
||||
|
@ -13,7 +13,30 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(AudioParam, mNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioParam)
|
||||
tmp->DisconnectFromGraph();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioParam)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNode)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(AudioParam)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(AudioParam)
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
AudioParam::Release()
|
||||
{
|
||||
if (mRefCnt.get() == 1) {
|
||||
// We are about to be deleted, disconnect the object from the graph before
|
||||
// the derived type is destroyed.
|
||||
DisconnectFromGraph();
|
||||
}
|
||||
NS_IMPL_CC_NATIVE_RELEASE_BODY(AudioParam)
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AudioParam, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AudioParam, Release)
|
||||
@ -31,6 +54,7 @@ AudioParam::AudioParam(AudioNode* aNode,
|
||||
|
||||
AudioParam::~AudioParam()
|
||||
{
|
||||
MOZ_ASSERT(mInputNodes.IsEmpty());
|
||||
}
|
||||
|
||||
JSObject*
|
||||
@ -39,6 +63,21 @@ AudioParam::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
return AudioParamBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
void
|
||||
AudioParam::DisconnectFromGraph()
|
||||
{
|
||||
// Addref this temporarily so the refcount bumping below doesn't destroy us
|
||||
// prematurely
|
||||
nsRefPtr<AudioParam> kungFuDeathGrip = this;
|
||||
|
||||
while (!mInputNodes.IsEmpty()) {
|
||||
uint32_t i = mInputNodes.Length() - 1;
|
||||
nsRefPtr<AudioNode> input = mInputNodes[i].mInputNode;
|
||||
mInputNodes.RemoveElementAt(i);
|
||||
input->RemoveOutputParam(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,8 @@ public:
|
||||
float aDefaultValue);
|
||||
virtual ~AudioParam();
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AudioParam)
|
||||
NS_IMETHOD_(nsrefcnt) AddRef(void);
|
||||
NS_IMETHOD_(nsrefcnt) Release(void);
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AudioParam)
|
||||
|
||||
AudioContext* GetParentObject() const
|
||||
@ -104,8 +105,32 @@ public:
|
||||
return mDefaultValue;
|
||||
}
|
||||
|
||||
const nsTArray<AudioNode::InputNode>& InputNodes() const
|
||||
{
|
||||
return mInputNodes;
|
||||
}
|
||||
|
||||
void RemoveInputNode(uint32_t aIndex)
|
||||
{
|
||||
mInputNodes.RemoveElementAt(aIndex);
|
||||
}
|
||||
|
||||
AudioNode::InputNode* AppendInputNode()
|
||||
{
|
||||
return mInputNodes.AppendElement();
|
||||
}
|
||||
|
||||
void DisconnectFromGraph();
|
||||
|
||||
protected:
|
||||
nsCycleCollectingAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
private:
|
||||
nsRefPtr<AudioNode> mNode;
|
||||
// For every InputNode, there is a corresponding entry in mOutputParams of the
|
||||
// InputNode's mInputNode.
|
||||
nsTArray<AudioNode::InputNode> mInputNodes;
|
||||
CallbackType mCallback;
|
||||
const float mDefaultValue;
|
||||
};
|
||||
|
@ -46,6 +46,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Connect(AudioParam& aDestination, uint32_t aOutput,
|
||||
ErrorResult& aRv) MOZ_OVERRIDE
|
||||
{
|
||||
AudioNode::Connect(aDestination, aOutput, aRv);
|
||||
if (!aRv.Failed()) {
|
||||
mPlayingRef.Take(this);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Disconnect(uint32_t aOutput, ErrorResult& aRv) MOZ_OVERRIDE
|
||||
{
|
||||
AudioNode::Disconnect(aOutput, aRv);
|
||||
|
@ -26,10 +26,8 @@ interface AudioNode : EventTarget {
|
||||
|
||||
[Throws]
|
||||
void connect(AudioNode destination, optional unsigned long output = 0, optional unsigned long input = 0);
|
||||
|
||||
// [Throws]
|
||||
// void connect(AudioParam destination, optional unsigned long output = 0);
|
||||
|
||||
[Throws]
|
||||
void connect(AudioParam destination, optional unsigned long output = 0);
|
||||
[Throws]
|
||||
void disconnect(optional unsigned long output = 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user