tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MIDIOutput.cpp (3443B)


      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/MIDIOutput.h"
      8 
      9 #include "mozilla/ErrorResult.h"
     10 #include "mozilla/TimeStamp.h"
     11 #include "mozilla/dom/Document.h"
     12 #include "mozilla/dom/MIDIOutputBinding.h"
     13 #include "mozilla/dom/MIDIPortChild.h"
     14 #include "mozilla/dom/MIDITypes.h"
     15 #include "mozilla/dom/MIDIUtils.h"
     16 #include "mozilla/dom/Performance.h"
     17 #include "nsDOMNavigationTiming.h"
     18 #include "nsGlobalWindowInner.h"
     19 
     20 namespace mozilla::dom {
     21 
     22 MIDIOutput::MIDIOutput(nsPIDOMWindowInner* aWindow) : MIDIPort(aWindow) {}
     23 
     24 // static
     25 RefPtr<MIDIOutput> MIDIOutput::Create(nsPIDOMWindowInner* aWindow,
     26                                      MIDIAccess* aMIDIAccessParent,
     27                                      const MIDIPortInfo& aPortInfo,
     28                                      const bool aSysexEnabled) {
     29  MOZ_ASSERT(static_cast<MIDIPortType>(aPortInfo.type()) ==
     30             MIDIPortType::Output);
     31  RefPtr<MIDIOutput> port = new MIDIOutput(aWindow);
     32  if (NS_WARN_IF(
     33          !port->Initialize(aPortInfo, aSysexEnabled, aMIDIAccessParent))) {
     34    return nullptr;
     35  }
     36  return port;
     37 }
     38 
     39 JSObject* MIDIOutput::WrapObject(JSContext* aCx,
     40                                 JS::Handle<JSObject*> aGivenProto) {
     41  return MIDIOutput_Binding::Wrap(aCx, this, aGivenProto);
     42 }
     43 
     44 void MIDIOutput::Send(const Sequence<uint8_t>& aData,
     45                      const Optional<double>& aTimestamp, ErrorResult& aRv) {
     46  if (Port()->DeviceState() == MIDIPortDeviceState::Disconnected) {
     47    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     48    return;
     49  }
     50  // The timestamp passed to us is a DOMHighResTimestamp, which is in relation
     51  // to the start of navigation timing. This needs to be turned into a
     52  // TimeStamp before it hits the platform specific MIDI service.
     53  //
     54  // If timestamp is either not set or zero, set timestamp to now and send the
     55  // message ASAP.
     56  TimeStamp timestamp;
     57  if (aTimestamp.WasPassed() && aTimestamp.Value() != 0) {
     58    nsCOMPtr<Document> doc = GetOwnerWindow()->GetDoc();
     59    if (!doc) {
     60      aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     61      return;
     62    }
     63    TimeDuration ts_diff = TimeDuration::FromMilliseconds(aTimestamp.Value());
     64    timestamp = GetOwnerWindow()
     65                    ->GetPerformance()
     66                    ->GetDOMTiming()
     67                    ->GetNavigationStartTimeStamp() +
     68                ts_diff;
     69  } else {
     70    timestamp = TimeStamp::Now();
     71  }
     72 
     73  nsTArray<MIDIMessage> msgArray;
     74  bool ret = MIDIUtils::ParseMessages(aData, timestamp, msgArray);
     75  if (!ret) {
     76    aRv.ThrowTypeError("Invalid MIDI message");
     77    return;
     78  }
     79 
     80  if (msgArray.IsEmpty()) {
     81    aRv.ThrowTypeError("Empty message array");
     82    return;
     83  }
     84 
     85  // TODO Move this check back to parse message so we don't have to iterate
     86  // twice.
     87  if (!SysexEnabled()) {
     88    for (auto& msg : msgArray) {
     89      if (MIDIUtils::IsSysexMessage(msg)) {
     90        aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     91        return;
     92      }
     93    }
     94  }
     95  Port()->SendSend(msgArray);
     96 }
     97 
     98 void MIDIOutput::Clear() {
     99  if (Port()->ConnectionState() == MIDIPortConnectionState::Closed) {
    100    return;
    101  }
    102  Port()->SendClear();
    103 }
    104 
    105 }  // namespace mozilla::dom