summaryrefslogtreecommitdiffstats
path: root/dom/media/webaudio/AudioDestinationNode.h
blob: df4a9b16ec5ac390bd7e05480d44c876b6835b06 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef AudioDestinationNode_h_
#define AudioDestinationNode_h_

#include "AudioChannelService.h"
#include "AudioNode.h"
#include "AudioChannelAgent.h"
#include "mozilla/TimeStamp.h"

namespace mozilla::dom {

class AudioContext;
class WakeLock;

class AudioDestinationNode final : public AudioNode,
                                   public nsIAudioChannelAgentCallback,
                                   public MainThreadMediaTrackListener {
 public:
  // This node type knows what MediaTrackGraph to use based on
  // whether it's in offline mode.
  AudioDestinationNode(AudioContext* aContext, bool aIsOffline,
                       uint32_t aNumberOfChannels, uint32_t aLength);

  void DestroyMediaTrack() override;

  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioDestinationNode, AudioNode)
  NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK

  JSObject* WrapObject(JSContext* aCx,
                       JS::Handle<JSObject*> aGivenProto) override;

  uint16_t NumberOfOutputs() const final { return 0; }

  uint32_t MaxChannelCount() const;
  void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) override;

  void Init();
  void Close();

  // Returns the track or null after unlink.
  AudioNodeTrack* Track();

  void Mute();
  void Unmute();

  void Suspend();
  void Resume();

  void StartRendering(Promise* aPromise);

  void OfflineShutdown();

  void NotifyMainThreadTrackEnded() override;
  void FireOfflineCompletionEvent();

  const char* NodeType() const override { return "AudioDestinationNode"; }

  size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override;

  void NotifyDataAudibleStateChanged(bool aAudible);
  void ResolvePromise(AudioBuffer* aRenderedBuffer);

  unsigned long Length() {
    MOZ_ASSERT(mIsOffline);
    return mFramesToProduce;
  }

  void NotifyAudioContextStateChanged();

 protected:
  virtual ~AudioDestinationNode();

 private:
  // This would be created for non-offline audio context in order to receive
  // tab's mute/suspend/audio capture state change and update the audible state
  // to the tab.
  void CreateAndStartAudioChannelAgent();
  void DestroyAudioChannelAgentIfExists();
  RefPtr<AudioChannelAgent> mAudioChannelAgent;

  // These members are related to audio capturing. We would start capturing
  // audio if we're starting capturing audio from whole window, and MUST stop
  // capturing explicitly when we don't need to capture audio any more, because
  // we have to release the resource we allocated before.
  bool IsCapturingAudio() const;
  void StartAudioCapturingTrack();
  void StopAudioCapturingTrack();
  RefPtr<MediaInputPort> mCaptureTrackPort;

  // These members are used to determine if the destination node is actual
  // audible and `mFinalAudibleState` represents the final result.
  using AudibleChangedReasons = AudioChannelService::AudibleChangedReasons;
  using AudibleState = AudioChannelService::AudibleState;
  void UpdateFinalAudibleStateIfNeeded(AudibleChangedReasons aReason);
  bool IsAudible() const;
  bool mFinalAudibleState = false;
  bool mIsDataAudible = false;
  float mAudioChannelVolume = 1.0;

  // True if the audio channel disables the track for unvisited tab, and the
  // track will be enabled again when the tab gets first visited, or a user
  // presses the tab play icon.
  bool mAudioChannelDisabled = false;

  // When the destination node is audible, we would request a wakelock to
  // prevent computer from sleeping in order to keep audio playing.
  void CreateAudioWakeLockIfNeeded();
  void ReleaseAudioWakeLockIfExists();
  RefPtr<WakeLock> mWakeLock;

  SelfReference<AudioDestinationNode> mOfflineRenderingRef;
  uint32_t mFramesToProduce;

  RefPtr<Promise> mOfflineRenderingPromise;

  bool mIsOffline;

  // These varaibles are used to know how long AudioContext would become audible
  // since it was created.
  TimeStamp mCreatedTime;
  TimeDuration mDurationBeforeFirstTimeAudible;
};

}  // namespace mozilla::dom

#endif