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 mozilla_dom_MIDIAccess_h
8 #define mozilla_dom_MIDIAccess_h
9 
10 #include "mozilla/Attributes.h"
11 #include "mozilla/DOMEventTargetHelper.h"
12 #include "mozilla/ErrorResult.h"
13 #include "mozilla/Observer.h"
14 #include "nsCycleCollectionParticipant.h"
15 #include "nsWrapperCache.h"
16 
17 struct JSContext;
18 
19 namespace mozilla {
20 // Predeclare void_t here, as including IPCMessageUtils brings in windows.h and
21 // causes binding compilation problems.
22 struct void_t;
23 
24 namespace dom {
25 
26 class MIDIAccessManager;
27 class MIDIInputMap;
28 struct MIDIOptions;
29 class MIDIOutputMap;
30 class MIDIPermissionRequest;
31 class MIDIPort;
32 class MIDIPortChangeEvent;
33 class MIDIPortInfo;
34 class MIDIPortList;
35 class Promise;
36 
37 typedef Observer<void_t> MIDIAccessDestructionObserver;
38 
39 /**
40  * MIDIAccess is the DOM object that is handed to the user upon MIDI permissions
41  * being successfully granted. It manages access to MIDI ports, and fires events
42  * for device connection and disconnection.
43  *
44  * New MIDIAccess objects are created every time RequestMIDIAccess is called.
45  * MIDIAccess objects are managed via MIDIAccessManager.
46  */
47 class MIDIAccess final : public DOMEventTargetHelper,
48                          public Observer<MIDIPortList> {
49   // Use the Permission Request class in MIDIAccessManager for creating
50   // MIDIAccess objects.
51   friend class MIDIPermissionRequest;
52   friend class MIDIAccessManager;
53 
54  public:
55   NS_DECL_ISUPPORTS_INHERITED
56   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MIDIAccess,
57                                                          DOMEventTargetHelper)
58  public:
59   virtual JSObject* WrapObject(JSContext* aCx,
60                                JS::Handle<JSObject*> aGivenProto) override;
61 
62   // Return map of MIDI Input Ports
Inputs()63   MIDIInputMap* Inputs() const { return mInputMap; }
64 
65   // Return map of MIDI Output Ports
Outputs()66   MIDIOutputMap* Outputs() const { return mOutputMap; }
67 
68   // Returns true if sysex permissions were given
SysexEnabled()69   bool SysexEnabled() const { return mSysexEnabled; }
70 
71   // Observer implementation for receiving port connection updates
72   void Notify(const MIDIPortList& aEvent) override;
73 
74   // All MIDIPort objects observe destruction of the MIDIAccess object that
75   // created them, as the port object receives disconnection events which then
76   // must be passed up to the MIDIAccess object. If the Port object dies before
77   // the MIDIAccess object, it needs to be removed from the observer list.
78   void RemovePortListener(MIDIAccessDestructionObserver* aPort);
79 
80   // Fires DOM event on port connection/disconnection
81   void FireConnectionEvent(MIDIPort* aPort);
82 
83   // Notify all MIDIPorts that were created by this MIDIAccess and are still
84   // alive, and detach from the MIDIAccessManager.
85   void Shutdown();
86   IMPL_EVENT_HANDLER(statechange);
87 
88  private:
89   MIDIAccess(nsPIDOMWindowInner* aWindow, bool aSysexEnabled,
90              Promise* aAccessPromise);
91   ~MIDIAccess();
92 
93   // On receiving a connection event from MIDIAccessManager, create a
94   // corresponding MIDIPort object if we don't already have one.
95   void MaybeCreateMIDIPort(const MIDIPortInfo& aInfo, ErrorResult& aRv);
96 
97   // Stores all known MIDIInput Ports
98   RefPtr<MIDIInputMap> mInputMap;
99   // Stores all known MIDIOutput Ports
100   RefPtr<MIDIOutputMap> mOutputMap;
101   // List of MIDIPort observers that need to be updated on destruction.
102   ObserverList<void_t> mDestructionObservers;
103   // True if user gave permissions for sysex usage to this object.
104   bool mSysexEnabled;
105   // Promise created by RequestMIDIAccess call, to be resolved after port
106   // populating is finished.
107   RefPtr<Promise> mAccessPromise;
108   // True if shutdown process has started, so we don't try to add more ports.
109   bool mHasShutdown;
110 };
111 
112 }  // namespace dom
113 }  // namespace mozilla
114 
115 #endif  // mozilla_dom_MIDIAccess_h
116