MIDIInput.cpp (3263B)
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 "mozilla/dom/MIDIInput.h" 8 9 #include "MIDILog.h" 10 #include "mozilla/dom/Document.h" 11 #include "mozilla/dom/MIDIInputBinding.h" 12 #include "mozilla/dom/MIDIMessageEvent.h" 13 #include "mozilla/dom/MIDIMessageEventBinding.h" 14 #include "mozilla/dom/MIDIPortChild.h" 15 #include "nsGlobalWindowInner.h" 16 17 namespace mozilla::dom { 18 19 MIDIInput::MIDIInput(nsPIDOMWindowInner* aWindow) 20 : MIDIPort(aWindow), mKeepAlive(false) {} 21 22 // static 23 RefPtr<MIDIInput> MIDIInput::Create(nsPIDOMWindowInner* aWindow, 24 MIDIAccess* aMIDIAccessParent, 25 const MIDIPortInfo& aPortInfo, 26 const bool aSysexEnabled) { 27 MOZ_ASSERT(static_cast<MIDIPortType>(aPortInfo.type()) == 28 MIDIPortType::Input); 29 RefPtr<MIDIInput> port = new MIDIInput(aWindow); 30 if (!port->Initialize(aPortInfo, aSysexEnabled, aMIDIAccessParent)) { 31 return nullptr; 32 } 33 return port; 34 } 35 36 JSObject* MIDIInput::WrapObject(JSContext* aCx, 37 JS::Handle<JSObject*> aGivenProto) { 38 return MIDIInput_Binding::Wrap(aCx, this, aGivenProto); 39 } 40 41 void MIDIInput::Receive(const nsTArray<MIDIMessage>& aMsgs) { 42 if (!GetOwnerWindow()) { 43 return; // Ignore messages once we've been disconnected from the owner 44 } 45 46 nsCOMPtr<Document> doc = GetOwnerWindow()->GetDoc(); 47 if (!doc) { 48 NS_WARNING("No document available to send MIDIMessageEvent to!"); 49 return; 50 } 51 for (const auto& msg : aMsgs) { 52 RefPtr<MIDIMessageEvent> event( 53 MIDIMessageEvent::Constructor(this, msg.timestamp(), msg.data())); 54 DispatchTrustedEvent(event); 55 } 56 } 57 58 void MIDIInput::StateChange() { 59 if (Port()->ConnectionState() == MIDIPortConnectionState::Open || 60 (Port()->DeviceState() == MIDIPortDeviceState::Connected && 61 Port()->ConnectionState() == MIDIPortConnectionState::Pending)) { 62 KeepAliveOnMidimessage(); 63 } else { 64 DontKeepAliveOnMidimessage(); 65 } 66 } 67 68 void MIDIInput::EventListenerAdded(nsAtom* aType) { 69 if (aType == nsGkAtoms::onmidimessage) { 70 // HACK: the Web MIDI spec states that we should open a port only when 71 // setting the midimessage event handler but Chrome does it even when 72 // adding event listeners hence this. 73 if (Port()->ConnectionState() != MIDIPortConnectionState::Open) { 74 LOG("onmidimessage event listener added, sending implicit Open"); 75 Port()->SendOpen(); 76 } 77 } 78 79 DOMEventTargetHelper::EventListenerAdded(aType); 80 } 81 82 void MIDIInput::DisconnectFromOwner() { 83 DontKeepAliveOnMidimessage(); 84 85 MIDIPort::DisconnectFromOwner(); 86 } 87 88 void MIDIInput::KeepAliveOnMidimessage() { 89 if (!mKeepAlive) { 90 mKeepAlive = true; 91 KeepAliveIfHasListenersFor(nsGkAtoms::onmidimessage); 92 } 93 } 94 95 void MIDIInput::DontKeepAliveOnMidimessage() { 96 if (mKeepAlive) { 97 IgnoreKeepAliveIfHasListenersFor(nsGkAtoms::onmidimessage); 98 mKeepAlive = false; 99 } 100 } 101 102 } // namespace mozilla::dom