summaryrefslogtreecommitdiffstats
path: root/dom/media/webaudio/MediaStreamAudioSourceNode.h
blob: 82ef67d4b77a605a75f8a0c22736b91184b2802d (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
134
135
136
137
138
139
140
141
142
143
144
145
146
/* -*- 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 MediaStreamAudioSourceNode_h_
#define MediaStreamAudioSourceNode_h_

#include "AudioNode.h"
#include "AudioNodeEngine.h"
#include "DOMMediaStream.h"
#include "PrincipalChangeObserver.h"

namespace mozilla::dom {

class AudioContext;
struct MediaStreamAudioSourceOptions;

class MediaStreamAudioSourceNodeEngine final : public AudioNodeEngine {
 public:
  explicit MediaStreamAudioSourceNodeEngine(AudioNode* aNode)
      : AudioNodeEngine(aNode), mEnabled(false) {}

  bool IsEnabled() const { return mEnabled; }
  enum Parameters { ENABLE };
  void SetInt32Parameter(uint32_t aIndex, int32_t aValue) override {
    switch (aIndex) {
      case ENABLE:
        mEnabled = !!aValue;
        break;
      default:
        NS_ERROR("MediaStreamAudioSourceNodeEngine bad parameter index");
    }
  }

 private:
  bool mEnabled;
};

class MediaStreamAudioSourceNode
    : public AudioNode,
      public PrincipalChangeObserver<MediaStreamTrack> {
 public:
  static already_AddRefed<MediaStreamAudioSourceNode> Create(
      AudioContext& aContext, const MediaStreamAudioSourceOptions& aOptions,
      ErrorResult& aRv);

  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaStreamAudioSourceNode,
                                           AudioNode)

  static already_AddRefed<MediaStreamAudioSourceNode> Constructor(
      const GlobalObject& aGlobal, AudioContext& aAudioContext,
      const MediaStreamAudioSourceOptions& aOptions, ErrorResult& aRv) {
    return Create(aAudioContext, aOptions, aRv);
  }

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

  void DestroyMediaTrack() override;

  uint16_t NumberOfInputs() const override { return 0; }

  DOMMediaStream* GetMediaStream() { return mInputStream; }

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

  virtual const char* CrossOriginErrorString() const {
    return "MediaStreamAudioSourceNodeCrossOrigin";
  }

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

  // Attaches to aTrack so that its audio content will be used as input.
  void AttachToTrack(const RefPtr<MediaStreamTrack>& aTrack, ErrorResult& aRv);

  // Detaches from the currently attached track if there is one.
  void DetachFromTrack();

  // Attaches to the first audio track in the MediaStream, when the tracks are
  // ordered by id.
  void AttachToRightTrack(const RefPtr<DOMMediaStream>& aMediaStream,
                          ErrorResult& aRv);

  // From DOMMediaStream::TrackListener.
  void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack);
  void NotifyTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack);
  void NotifyAudible();

  class TrackListener final : public DOMMediaStream::TrackListener {
   public:
    NS_DECL_ISUPPORTS_INHERITED
    NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TrackListener,
                                             DOMMediaStream::TrackListener)
    explicit TrackListener(MediaStreamAudioSourceNode* aNode) : mNode(aNode) {}
    void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) override {
      mNode->NotifyTrackAdded(aTrack);
    }
    void NotifyTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack) override {
      mNode->NotifyTrackRemoved(aTrack);
    }
    void NotifyAudible() override { mNode->NotifyAudible(); }

   private:
    virtual ~TrackListener() = default;
    RefPtr<MediaStreamAudioSourceNode> mNode;
  };

  // From PrincipalChangeObserver<MediaStreamTrack>.
  void PrincipalChanged(MediaStreamTrack* aMediaStreamTrack) override;

  // This allows implementing the correct behaviour for both
  // MediaElementAudioSourceNode and MediaStreamAudioSourceNode, that have most
  // of their behaviour shared.
  enum TrackChangeBehavior {
    // MediaStreamAudioSourceNode locks on the track it picked, and never
    // changes.
    LockOnTrackPicked,
    // MediaElementAudioSourceNode can change track, depending on what the
    // HTMLMediaElement does.
    FollowChanges
  };

 protected:
  MediaStreamAudioSourceNode(AudioContext* aContext,
                             TrackChangeBehavior aBehavior);
  void Init(DOMMediaStream& aMediaStream, ErrorResult& aRv);
  virtual void Destroy();
  virtual ~MediaStreamAudioSourceNode();

 private:
  const TrackChangeBehavior mBehavior;
  RefPtr<MediaInputPort> mInputPort;
  RefPtr<DOMMediaStream> mInputStream;

  // On construction we set this to the first audio track of mInputStream.
  RefPtr<MediaStreamTrack> mInputTrack;
  RefPtr<TrackListener> mListener;
};

}  // namespace mozilla::dom

#endif