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 #ifndef AudioDestinationNode_h_
8 #define AudioDestinationNode_h_
9 
10 #include "AudioChannelService.h"
11 #include "AudioNode.h"
12 #include "AudioChannelAgent.h"
13 #include "mozilla/TimeStamp.h"
14 
15 namespace mozilla {
16 namespace dom {
17 
18 class AudioContext;
19 class WakeLock;
20 
21 class AudioDestinationNode final : public AudioNode,
22                                    public nsIAudioChannelAgentCallback,
23                                    public MainThreadMediaTrackListener {
24  public:
25   // This node type knows what MediaTrackGraph to use based on
26   // whether it's in offline mode.
27   AudioDestinationNode(AudioContext* aContext, bool aIsOffline,
28                        uint32_t aNumberOfChannels, uint32_t aLength);
29 
30   void DestroyMediaTrack() override;
31 
32   NS_DECL_ISUPPORTS_INHERITED
33   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioDestinationNode, AudioNode)
34   NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK
35 
36   JSObject* WrapObject(JSContext* aCx,
37                        JS::Handle<JSObject*> aGivenProto) override;
38 
NumberOfOutputs()39   uint16_t NumberOfOutputs() const final { return 0; }
40 
41   uint32_t MaxChannelCount() const;
42   void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) override;
43 
44   void Init();
45   void Close();
46 
47   // Returns the track or null after unlink.
48   AudioNodeTrack* Track();
49 
50   void Mute();
51   void Unmute();
52 
53   void Suspend();
54   void Resume();
55 
56   void StartRendering(Promise* aPromise);
57 
58   void OfflineShutdown();
59 
60   void NotifyMainThreadTrackEnded() override;
61   void FireOfflineCompletionEvent();
62 
NodeType()63   const char* NodeType() const override { return "AudioDestinationNode"; }
64 
65   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
66   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;
67 
68   void NotifyDataAudibleStateChanged(bool aAudible);
69   void ResolvePromise(AudioBuffer* aRenderedBuffer);
70 
Length()71   unsigned long Length() {
72     MOZ_ASSERT(mIsOffline);
73     return mFramesToProduce;
74   }
75 
76   void NotifyAudioContextStateChanged();
77 
78  protected:
79   virtual ~AudioDestinationNode();
80 
81  private:
82   // This would be created for non-offline audio context in order to receive
83   // tab's mute/suspend/audio capture state change and update the audible state
84   // to the tab.
85   void CreateAndStartAudioChannelAgent();
86   void DestroyAudioChannelAgentIfExists();
87   RefPtr<AudioChannelAgent> mAudioChannelAgent;
88 
89   // These members are related to audio capturing. We would start capturing
90   // audio if we're starting capturing audio from whole window, and MUST stop
91   // capturing explicitly when we don't need to capture audio any more, because
92   // we have to release the resource we allocated before.
93   bool IsCapturingAudio() const;
94   void StartAudioCapturingTrack();
95   void StopAudioCapturingTrack();
96   RefPtr<MediaInputPort> mCaptureTrackPort;
97 
98   // These members are used to determine if the destination node is actual
99   // audible and `mFinalAudibleState` represents the final result.
100   using AudibleChangedReasons = AudioChannelService::AudibleChangedReasons;
101   using AudibleState = AudioChannelService::AudibleState;
102   void UpdateFinalAudibleStateIfNeeded(AudibleChangedReasons aReason);
103   bool IsAudible() const;
104   bool mFinalAudibleState = false;
105   bool mIsDataAudible = false;
106   float mAudioChannelVolume = 1.0;
107 
108   // True if the audio channel disables the track for unvisited tab, and the
109   // track will be enabled again when the tab gets first visited, or a user
110   // presses the tab play icon.
111   bool mAudioChannelDisabled = false;
112 
113   // When the destination node is audible, we would request a wakelock to
114   // prevent computer from sleeping in order to keep audio playing.
115   void CreateAudioWakeLockIfNeeded();
116   void ReleaseAudioWakeLockIfExists();
117   RefPtr<WakeLock> mWakeLock;
118 
119   SelfReference<AudioDestinationNode> mOfflineRenderingRef;
120   uint32_t mFramesToProduce;
121 
122   RefPtr<Promise> mOfflineRenderingPromise;
123 
124   bool mIsOffline;
125 
126   // These varaibles are used to know how long AudioContext would become audible
127   // since it was created.
128   TimeStamp mCreatedTime;
129   TimeDuration mDurationBeforeFirstTimeAudible;
130 };
131 
132 }  // namespace dom
133 }  // namespace mozilla
134 
135 #endif
136