MediaElementAudioSourceNode.cpp (3706B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "MediaElementAudioSourceNode.h" 8 9 #include "AudioDestinationNode.h" 10 #include "AudioNodeTrack.h" 11 #include "MediaStreamTrack.h" 12 #include "mozilla/dom/MediaElementAudioSourceNodeBinding.h" 13 14 namespace mozilla::dom { 15 16 NS_IMPL_CYCLE_COLLECTION_CLASS(MediaElementAudioSourceNode) 17 18 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaElementAudioSourceNode) 19 tmp->Destroy(); 20 NS_IMPL_CYCLE_COLLECTION_UNLINK(mElement) 21 NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(AudioNode) 22 23 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaElementAudioSourceNode, 24 MediaStreamAudioSourceNode) 25 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mElement) 26 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 27 28 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaElementAudioSourceNode) 29 NS_INTERFACE_MAP_END_INHERITING(MediaStreamAudioSourceNode) 30 31 NS_IMPL_ADDREF_INHERITED(MediaElementAudioSourceNode, 32 MediaStreamAudioSourceNode) 33 NS_IMPL_RELEASE_INHERITED(MediaElementAudioSourceNode, 34 MediaStreamAudioSourceNode) 35 36 MediaElementAudioSourceNode::MediaElementAudioSourceNode( 37 AudioContext* aContext, HTMLMediaElement* aElement) 38 : MediaStreamAudioSourceNode(aContext, TrackChangeBehavior::FollowChanges), 39 mElement(aElement) { 40 MOZ_ASSERT(aElement); 41 } 42 43 /* static */ 44 already_AddRefed<MediaElementAudioSourceNode> 45 MediaElementAudioSourceNode::Create( 46 AudioContext& aAudioContext, const MediaElementAudioSourceOptions& aOptions, 47 ErrorResult& aRv) { 48 // The spec has a pointless check here. See 49 // https://github.com/WebAudio/web-audio-api/issues/2149 50 MOZ_RELEASE_ASSERT(!aAudioContext.IsOffline(), "Bindings messed up?"); 51 52 RefPtr<MediaElementAudioSourceNode> node = 53 new MediaElementAudioSourceNode(&aAudioContext, aOptions.mMediaElement); 54 55 RefPtr<DOMMediaStream> stream = aOptions.mMediaElement->CaptureAudio( 56 aRv, aAudioContext.Destination()->Track()->Graph()); 57 if (aRv.Failed()) { 58 return nullptr; 59 } 60 MOZ_ASSERT(stream, "CaptureAudio should report failure via aRv!"); 61 62 node->Init(*stream, aRv); 63 if (aRv.Failed()) { 64 return nullptr; 65 } 66 67 node->ListenForAllowedToPlay(aOptions); 68 return node.forget(); 69 } 70 71 JSObject* MediaElementAudioSourceNode::WrapObject( 72 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { 73 return MediaElementAudioSourceNode_Binding::Wrap(aCx, this, aGivenProto); 74 } 75 76 void MediaElementAudioSourceNode::ListenForAllowedToPlay( 77 const MediaElementAudioSourceOptions& aOptions) { 78 aOptions.mMediaElement->GetAllowedToPlayPromise() 79 ->Then( 80 AbstractThread::MainThread(), __func__, 81 // Capture by reference to bypass the mozilla-refcounted-inside-lambda 82 // static analysis. We capture a non-owning reference so as to allow 83 // cycle collection of the node. The reference is cleared via 84 // DisconnectIfExists() from Destroy() when the node is collected. 85 [&self = *this]() { 86 self.Context()->StartBlockedAudioContextIfAllowed(); 87 self.mAllowedToPlayRequest.Complete(); 88 }) 89 ->Track(mAllowedToPlayRequest); 90 } 91 92 void MediaElementAudioSourceNode::Destroy() { 93 mAllowedToPlayRequest.DisconnectIfExists(); 94 MediaStreamAudioSourceNode::Destroy(); 95 } 96 97 HTMLMediaElement* MediaElementAudioSourceNode::MediaElement() { 98 return mElement; 99 } 100 101 } // namespace mozilla::dom