Line data Source code
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 "MediaStreamAudioDestinationNode.h"
8 : #include "nsIDocument.h"
9 : #include "mozilla/dom/MediaStreamAudioDestinationNodeBinding.h"
10 : #include "AudioNodeEngine.h"
11 : #include "AudioNodeStream.h"
12 : #include "DOMMediaStream.h"
13 : #include "MediaStreamTrack.h"
14 : #include "TrackUnionStream.h"
15 :
16 : namespace mozilla {
17 : namespace dom {
18 :
19 : class AudioDestinationTrackSource final :
20 : public MediaStreamTrackSource
21 : {
22 : public:
23 : NS_DECL_ISUPPORTS_INHERITED
24 0 : NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioDestinationTrackSource,
25 : MediaStreamTrackSource)
26 :
27 0 : AudioDestinationTrackSource(MediaStreamAudioDestinationNode* aNode,
28 : nsIPrincipal* aPrincipal)
29 0 : : MediaStreamTrackSource(aPrincipal, nsString())
30 0 : , mNode(aNode)
31 : {
32 0 : }
33 :
34 0 : void Destroy() override
35 : {
36 0 : if (mNode) {
37 0 : mNode->DestroyMediaStream();
38 0 : mNode = nullptr;
39 : }
40 0 : }
41 :
42 0 : MediaSourceEnum GetMediaSource() const override
43 : {
44 0 : return MediaSourceEnum::AudioCapture;
45 : }
46 :
47 0 : void Stop() override
48 : {
49 0 : Destroy();
50 0 : }
51 :
52 : private:
53 0 : ~AudioDestinationTrackSource() = default;
54 :
55 : RefPtr<MediaStreamAudioDestinationNode> mNode;
56 : };
57 :
58 0 : NS_IMPL_ADDREF_INHERITED(AudioDestinationTrackSource,
59 : MediaStreamTrackSource)
60 0 : NS_IMPL_RELEASE_INHERITED(AudioDestinationTrackSource,
61 : MediaStreamTrackSource)
62 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioDestinationTrackSource)
63 0 : NS_INTERFACE_MAP_END_INHERITING(MediaStreamTrackSource)
64 0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioDestinationTrackSource,
65 : MediaStreamTrackSource,
66 : mNode)
67 :
68 0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaStreamAudioDestinationNode, AudioNode, mDOMStream)
69 :
70 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaStreamAudioDestinationNode)
71 0 : NS_INTERFACE_MAP_END_INHERITING(AudioNode)
72 :
73 0 : NS_IMPL_ADDREF_INHERITED(MediaStreamAudioDestinationNode, AudioNode)
74 0 : NS_IMPL_RELEASE_INHERITED(MediaStreamAudioDestinationNode, AudioNode)
75 :
76 0 : MediaStreamAudioDestinationNode::MediaStreamAudioDestinationNode(AudioContext* aContext)
77 : : AudioNode(aContext,
78 : 2,
79 : ChannelCountMode::Explicit,
80 : ChannelInterpretation::Speakers)
81 : , mDOMStream(
82 0 : DOMAudioNodeMediaStream::CreateTrackUnionStreamAsInput(GetOwner(),
83 : this,
84 0 : aContext->Graph()))
85 : {
86 : // Ensure an audio track with the correct ID is exposed to JS
87 0 : nsIDocument* doc = aContext->GetParentObject()->GetExtantDoc();
88 : RefPtr<MediaStreamTrackSource> source =
89 0 : new AudioDestinationTrackSource(this, doc->NodePrincipal());
90 : RefPtr<MediaStreamTrack> track =
91 0 : mDOMStream->CreateDOMTrack(AudioNodeStream::AUDIO_TRACK,
92 : MediaSegment::AUDIO, source,
93 0 : MediaTrackConstraints());
94 0 : mDOMStream->AddTrackInternal(track);
95 :
96 0 : ProcessedMediaStream* outputStream = mDOMStream->GetInputStream()->AsProcessedStream();
97 0 : MOZ_ASSERT(!!outputStream);
98 0 : AudioNodeEngine* engine = new AudioNodeEngine(this);
99 0 : mStream = AudioNodeStream::Create(aContext, engine,
100 : AudioNodeStream::EXTERNAL_OUTPUT,
101 0 : aContext->Graph());
102 0 : mPort = outputStream->AllocateInputPort(mStream, AudioNodeStream::AUDIO_TRACK);
103 0 : }
104 :
105 : /* static */ already_AddRefed<MediaStreamAudioDestinationNode>
106 0 : MediaStreamAudioDestinationNode::Create(AudioContext& aAudioContext,
107 : const AudioNodeOptions& aOptions,
108 : ErrorResult& aRv)
109 : {
110 0 : if (aAudioContext.IsOffline()) {
111 0 : aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
112 0 : return nullptr;
113 : }
114 :
115 0 : if (aAudioContext.CheckClosed(aRv)) {
116 0 : return nullptr;
117 : }
118 :
119 : RefPtr<MediaStreamAudioDestinationNode> audioNode =
120 0 : new MediaStreamAudioDestinationNode(&aAudioContext);
121 :
122 0 : audioNode->Initialize(aOptions, aRv);
123 0 : if (NS_WARN_IF(aRv.Failed())) {
124 0 : return nullptr;
125 : }
126 :
127 0 : return audioNode.forget();
128 : }
129 :
130 : size_t
131 0 : MediaStreamAudioDestinationNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
132 : {
133 : // Future:
134 : // - mDOMStream
135 0 : size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
136 0 : amount += mPort->SizeOfIncludingThis(aMallocSizeOf);
137 0 : return amount;
138 : }
139 :
140 : size_t
141 0 : MediaStreamAudioDestinationNode::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
142 : {
143 0 : return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
144 : }
145 :
146 : void
147 0 : MediaStreamAudioDestinationNode::DestroyMediaStream()
148 : {
149 0 : AudioNode::DestroyMediaStream();
150 0 : if (mPort) {
151 0 : mPort->Destroy();
152 0 : mPort = nullptr;
153 : }
154 0 : }
155 :
156 : JSObject*
157 0 : MediaStreamAudioDestinationNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
158 : {
159 0 : return MediaStreamAudioDestinationNodeBinding::Wrap(aCx, this, aGivenProto);
160 : }
161 :
162 : } // namespace dom
163 : } // namespace mozilla
|