Commit 9990e648 authored by tzik's avatar tzik Committed by Commit Bot

Refactor MIDIOutput

This CL contains:
 - Convert MIDIOutput::pending_data_ to contain DOMUint8Array instead of
   Vector, so that we don't need an extra copy on the lazy open case.
 - Take care null or non-Document ExecutionContext.
 - Misc clean up.

Change-Id: I33862de0aa39ddd68dc9ee5e4a594caf1e8f7437
Reviewed-on: https://chromium-review.googlesource.com/895129
Commit-Queue: Taiju Tsuiki <tzik@chromium.org>
Reviewed-by: default avatarTakashi Toyoshima <toyoshim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#533254}
parent 1101e069
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#include "core/frame/UseCounter.h" #include "core/frame/UseCounter.h"
#include "core/timing/DOMWindowPerformance.h" #include "core/timing/DOMWindowPerformance.h"
#include "core/timing/Performance.h" #include "core/timing/Performance.h"
#include "core/timing/WorkerGlobalScopePerformance.h"
#include "core/workers/WorkerGlobalScope.h"
#include "media/midi/midi_service.mojom-blink.h" #include "media/midi/midi_service.mojom-blink.h"
#include "modules/webmidi/MIDIAccess.h" #include "modules/webmidi/MIDIAccess.h"
...@@ -47,11 +49,36 @@ namespace blink { ...@@ -47,11 +49,36 @@ namespace blink {
namespace { namespace {
double Now(ExecutionContext* context) { DOMUint8Array* ConvertUnsignedDataToUint8Array(
LocalDOMWindow* window = context ? context->ExecutingWindow() : nullptr; Vector<unsigned> unsigned_data,
Performance* performance = ExceptionState& exception_state) {
window ? DOMWindowPerformance::performance(*window) : nullptr; DOMUint8Array* array = DOMUint8Array::Create(unsigned_data.size());
return performance ? performance->now() : 0.0; DOMUint8Array::ValueType* array_data = array->Data();
for (size_t i = 0; i < unsigned_data.size(); ++i) {
if (unsigned_data[i] > 0xff) {
exception_state.ThrowTypeError("The value at index " + String::Number(i) +
" (" + String::Number(unsigned_data[i]) +
") is greater than 0xFF.");
return nullptr;
}
array_data[i] = unsigned_data[i];
}
return array;
}
double GetTimeOrigin(ExecutionContext* context) {
DCHECK(context);
PerformanceBase* performance = nullptr;
if (LocalDOMWindow* window = context->ExecutingWindow()) {
performance = DOMWindowPerformance::performance(*window);
} else {
DCHECK(context->IsWorkerGlobalScope());
performance = WorkerGlobalScopePerformance::performance(
*static_cast<WorkerGlobalScope*>(context));
}
DCHECK(performance);
return performance->timeOrigin();
} }
class MessageValidator { class MessageValidator {
...@@ -224,81 +251,103 @@ MIDIOutput::MIDIOutput(MIDIAccess* access, ...@@ -224,81 +251,103 @@ MIDIOutput::MIDIOutput(MIDIAccess* access,
MIDIOutput::~MIDIOutput() = default; MIDIOutput::~MIDIOutput() = default;
void MIDIOutput::send(NotShared<DOMUint8Array> array, void MIDIOutput::send(NotShared<DOMUint8Array> array,
double timestamp, double timestamp_in_milliseconds,
ExceptionState& exception_state) { ExceptionState& exception_state) {
DCHECK(array); ExecutionContext* context = GetExecutionContext();
if (!context)
if (timestamp == 0.0) return;
timestamp = Now(GetExecutionContext());
double timestamp;
UseCounter::Count(*ToDocument(GetExecutionContext()), if (timestamp_in_milliseconds == 0.0) {
WebFeature::kMIDIOutputSend); timestamp = CurrentTimeTicksInMilliseconds();
} else {
// Implicit open. It does nothing if the port is already opened. timestamp = GetTimeOrigin(context) + timestamp_in_milliseconds;
// This should be performed even if |array| is invalid.
open();
if (MessageValidator::Validate(array.View(), exception_state,
midiAccess()->sysexEnabled())) {
if (IsOpening()) {
pending_data_.push_back(std::make_pair(Vector<uint8_t>(), timestamp));
pending_data_.back().first.Append(array.View()->Data(),
array.View()->length());
} else {
midiAccess()->SendMIDIData(port_index_, array.View()->Data(),
array.View()->length(), timestamp);
}
} }
SendInternal(array.View(), timestamp, exception_state);
} }
void MIDIOutput::send(Vector<unsigned> unsigned_data, void MIDIOutput::send(Vector<unsigned> unsigned_data,
double timestamp, double timestamp_in_milliseconds,
ExceptionState& exception_state) { ExceptionState& exception_state) {
if (timestamp == 0.0) if (!GetExecutionContext())
timestamp = Now(GetExecutionContext()); return;
DOMUint8Array* array = DOMUint8Array::Create(unsigned_data.size()); DOMUint8Array* array = ConvertUnsignedDataToUint8Array(
DOMUint8Array::ValueType* const array_data = array->Data(); std::move(unsigned_data), exception_state);
const uint32_t array_length = array->length(); if (!array) {
DCHECK(exception_state.HadException());
for (size_t i = 0; i < unsigned_data.size(); ++i) { return;
if (unsigned_data[i] > 0xff) {
exception_state.ThrowTypeError("The value at index " + String::Number(i) +
" (" + String::Number(unsigned_data[i]) +
") is greater than 0xFF.");
return;
}
if (i < array_length)
array_data[i] = unsigned_data[i] & 0xff;
} }
send(NotShared<DOMUint8Array>(array), timestamp, exception_state); send(NotShared<DOMUint8Array>(array), timestamp_in_milliseconds,
exception_state);
} }
void MIDIOutput::send(NotShared<DOMUint8Array> data, void MIDIOutput::send(NotShared<DOMUint8Array> data,
ExceptionState& exception_state) { ExceptionState& exception_state) {
if (!GetExecutionContext())
return;
DCHECK(data); DCHECK(data);
send(data, 0.0, exception_state); SendInternal(data.View(), CurrentTimeTicksInMilliseconds(), exception_state);
} }
void MIDIOutput::send(Vector<unsigned> unsigned_data, void MIDIOutput::send(Vector<unsigned> unsigned_data,
ExceptionState& exception_state) { ExceptionState& exception_state) {
send(unsigned_data, 0.0, exception_state); if (!GetExecutionContext())
return;
DOMUint8Array* array = ConvertUnsignedDataToUint8Array(
std::move(unsigned_data), exception_state);
if (!array) {
DCHECK(exception_state.HadException());
return;
}
SendInternal(array, CurrentTimeTicksInMilliseconds(), exception_state);
} }
void MIDIOutput::DidOpen(bool opened) { void MIDIOutput::DidOpen(bool opened) {
if (!opened) {
pending_data_.clear();
return;
}
while (!pending_data_.empty()) { while (!pending_data_.empty()) {
if (opened) { auto& front = pending_data_.front();
auto& front = pending_data_.front(); midiAccess()->SendMIDIData(port_index_, front.first->Data(),
midiAccess()->SendMIDIData(port_index_, front.first.data(), front.first->length(), front.second);
front.first.size(), front.second);
}
pending_data_.TakeFirst(); pending_data_.TakeFirst();
} }
} }
void MIDIOutput::Trace(blink::Visitor* visitor) { void MIDIOutput::Trace(blink::Visitor* visitor) {
MIDIPort::Trace(visitor); MIDIPort::Trace(visitor);
visitor->Trace(pending_data_);
}
void MIDIOutput::SendInternal(DOMUint8Array* array,
double platform_timestamp,
ExceptionState& exception_state) {
DCHECK(GetExecutionContext());
DCHECK(array);
DCHECK_NE(0.0, platform_timestamp);
UseCounter::Count(GetExecutionContext(), WebFeature::kMIDIOutputSend);
// Implicit open. It does nothing if the port is already opened.
// This should be performed even if |array| is invalid.
open();
if (!MessageValidator::Validate(array, exception_state,
midiAccess()->sysexEnabled()))
return;
if (IsOpening()) {
pending_data_.emplace_back(array, platform_timestamp);
} else {
midiAccess()->SendMIDIData(port_index_, array->Data(), array->length(),
platform_timestamp);
}
} }
} // namespace blink } // namespace blink
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "core/typed_arrays/ArrayBufferViewHelpers.h" #include "core/typed_arrays/ArrayBufferViewHelpers.h"
#include "core/typed_arrays/DOMTypedArray.h" #include "core/typed_arrays/DOMTypedArray.h"
#include "modules/webmidi/MIDIPort.h" #include "modules/webmidi/MIDIPort.h"
#include "platform/heap/HeapAllocator.h"
namespace blink { namespace blink {
...@@ -73,9 +74,10 @@ class MIDIOutput final : public MIDIPort { ...@@ -73,9 +74,10 @@ class MIDIOutput final : public MIDIPort {
midi::mojom::PortState); midi::mojom::PortState);
void DidOpen(bool opened) override; void DidOpen(bool opened) override;
void SendInternal(DOMUint8Array*, double platform_timestamp, ExceptionState&);
unsigned port_index_; unsigned port_index_;
Deque<std::pair<Vector<uint8_t>, double>> pending_data_; HeapDeque<std::pair<Member<DOMUint8Array>, double>> pending_data_;
}; };
} // namespace blink } // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment