already_AddRefed<Promise> AudioContext::Resume(ErrorResult& aRv) { nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(GetParentObject()); RefPtr<Promise> promise; promise = Promise::Create(parentObject, aRv); if (aRv.Failed()) { return nullptr; } if (mIsOffline) { promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return promise.forget(); } if (mAudioContextState == AudioContextState::Closed || mCloseCalled) { promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); return promise.forget(); } if (mAudioContextState == AudioContextState::Running) { promise->MaybeResolve(JS::UndefinedHandleValue); return promise.forget(); } Destination()->Resume(); nsTArray<MediaStream*> streams; // If mSuspendCalled is false then we already resumed all our streams, // so don't resume them again (since suspend(); resume(); resume(); should // be OK). But we still need to do ApplyAudioContextOperation // to ensure our new promise is resolved. if (mSuspendCalled) { streams = GetAllStreams(); } mPromiseGripArray.AppendElement(promise); Graph()->ApplyAudioContextOperation(DestinationStream()->AsAudioNodeStream(), streams, AudioContextOperation::Resume, promise); mSuspendCalled = false; return promise.forget(); }
already_AddRefed<Promise> AudioContext::Close(ErrorResult& aRv) { nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(GetParentObject()); RefPtr<Promise> promise; promise = Promise::Create(parentObject, aRv); if (aRv.Failed()) { return nullptr; } if (mIsOffline) { promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return promise.forget(); } if (mAudioContextState == AudioContextState::Closed) { promise->MaybeResolve(NS_ERROR_DOM_INVALID_STATE_ERR); return promise.forget(); } if (Destination()) { Destination()->DestroyAudioChannelAgent(); } mPromiseGripArray.AppendElement(promise); // This can be called when freeing a document, and the streams are dead at // this point, so we need extra null-checks. MediaStream* ds = DestinationStream(); if (ds) { nsTArray<MediaStream*> streams; // If mSuspendCalled or mCloseCalled are true then we already suspended // all our streams, so don't suspend them again. But we still need to do // ApplyAudioContextOperation to ensure our new promise is resolved. if (!mSuspendCalled && !mCloseCalled) { streams = GetAllStreams(); } Graph()->ApplyAudioContextOperation(ds->AsAudioNodeStream(), streams, AudioContextOperation::Close, promise); } mCloseCalled = true; return promise.forget(); }