Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1007)

Unified Diff: media/midi/midi_manager_winrt.cc

Issue 2243183002: Web MIDI backend for Windows 10 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« media/midi/BUILD.gn ('K') | « media/midi/BUILD.gn ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/midi/midi_manager_winrt.cc
diff --git a/media/midi/midi_manager_winrt.cc b/media/midi/midi_manager_winrt.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d81fb49877d481d6eb0fb0b7a06a388892c0f4d6
--- /dev/null
+++ b/media/midi/midi_manager_winrt.cc
@@ -0,0 +1,661 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/midi/midi_manager_win.h"
+
+#include <robuffer.h>
+#include <windows.devices.enumeration.h>
+#include <windows.devices.midi.h>
+#include <wrl/event.h>
+
+#include <functional>
+
+#include "base/bind.h"
+#include "base/containers/hash_tables.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/timer/timer.h"
+#include "base/win/windows_version.h"
+#include "media/midi/midi_port_info.h"
+
+namespace media {
+namespace midi {
+namespace {
+
+using namespace ABI::Windows::Devices::Enumeration;
+using namespace ABI::Windows::Devices::Midi;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Storage::Streams;
+using Microsoft::WRL::Callback;
Takashi Toyoshima 2016/08/15 08:46:23 To shorten this as Callback is a little confusing
Shao-Chuan Lee 2016/08/16 07:42:25 Now using `namespace WRL = Microsoft::WRL`.
+using Microsoft::WRL::ComPtr;
+using Microsoft::WRL::Wrappers::HStringReference;
+
+using std::placeholders::_1;
+using std::placeholders::_2;
+
+// Singleton helper for accessing WRL static methods.
+class WrlStatics {
Takashi Toyoshima 2016/08/15 08:46:23 Please use base::LazyInstance to implement a singl
Shao-Chuan Lee 2016/08/16 07:42:24 The singleton is now replaced with functions. Alth
+ public:
+ static WrlStatics& GetInstance() {
+ static WrlStatics instance;
+ return instance;
+ }
+
+ auto GetBufferFactory() {
+ return GetStatics(buffer_factory_,
+ RuntimeClass_Windows_Storage_Streams_Buffer);
+ }
+
+ auto GetDeviceInformationStatics() {
+ return GetStatics(
+ device_information_statics_,
+ RuntimeClass_Windows_Devices_Enumeration_DeviceInformation);
+ }
+
+ auto GetMidiInPortStatics() {
+ return GetStatics(midi_in_port_statics_,
+ RuntimeClass_Windows_Devices_Midi_MidiInPort);
+ }
+
+ auto GetMidiOutPortStatics() {
+ return GetStatics(midi_out_port_statics_,
+ RuntimeClass_Windows_Devices_Midi_MidiOutPort);
+ }
+
+ private:
+ WrlStatics() {}
+
+ template <typename T>
+ static T* GetStatics(ComPtr<T>& com_ptr, wchar_t const* class_id) {
Takashi Toyoshima 2016/08/15 08:46:23 Also wchar_t is disallowed in chromium even though
Takashi Toyoshima 2016/08/15 08:46:23 chromium style suggests to use pointers* or const
Shao-Chuan Lee 2016/08/16 07:42:25 Done.
Shao-Chuan Lee 2016/08/16 07:42:25 Done.
+ if (com_ptr == nullptr) {
+ HRESULT hr =
+ GetActivationFactory(HStringReference(class_id).Get(), &com_ptr);
+ DCHECK(!FAILED(hr));
+ }
+ return com_ptr.Get();
+ }
+
+ ComPtr<IBufferFactory> buffer_factory_;
+ ComPtr<IDeviceInformationStatics> device_information_statics_;
+ ComPtr<IMidiInPortStatics> midi_in_port_statics_;
+ ComPtr<IMidiOutPortStatics> midi_out_port_statics_;
+
+ DISALLOW_COPY_AND_ASSIGN(WrlStatics);
+};
+
+// Helper for setting up DeviceWatcher callbacks.
+class DeviceWatcherWrapper {
Takashi Toyoshima 2016/08/15 08:46:24 This looks over-abstracted to me. The midi_manager
Shao-Chuan Lee 2016/08/16 07:42:25 Merged into MidiPortManager.
+ public:
+ class CallbackHandler {
+ public:
+ virtual HRESULT OnAdded(IDeviceWatcher* watcher,
+ IDeviceInformation* info) = 0;
+ virtual HRESULT OnEnumerationCompleted(IDeviceWatcher* watcher,
+ IInspectable* insp) = 0;
+ virtual HRESULT OnRemoved(IDeviceWatcher* watcher,
+ IDeviceInformationUpdate* update) = 0;
+ virtual HRESULT OnStopped(IDeviceWatcher* watcher, IInspectable* insp) = 0;
+ virtual HRESULT OnUpdated(IDeviceWatcher* watcher,
+ IDeviceInformationUpdate* update) = 0;
+ };
+
+ DeviceWatcherWrapper() {}
+
+ ~DeviceWatcherWrapper() {
+ watcher_->remove_Added(token_Added_);
+ watcher_->remove_EnumerationCompleted(token_EnumerationCompleted_);
+ watcher_->remove_Removed(token_Removed_);
+ watcher_->remove_Stopped(token_Stopped_);
+ watcher_->remove_Updated(token_Updated_);
+ }
+
+ void Setup(HSTRING selector, CallbackHandler* handler) {
+ HRESULT hr;
+
+ hr = WrlStatics::GetInstance()
+ .GetDeviceInformationStatics()
+ ->CreateWatcherAqsFilter(selector, &watcher_);
+ DCHECK(!FAILED(hr));
+
+ hr = watcher_->add_Added(
+ Callback<ITypedEventHandler<DeviceWatcher*, DeviceInformation*>>(
+ std::bind(&CallbackHandler::OnAdded, handler, _1, _2))
Takashi Toyoshima 2016/08/15 08:46:23 std::bind is classified to a C++11 features to be
Shao-Chuan Lee 2016/08/16 07:42:25 Acknowledged, will look for advice on this issue (
Shao-Chuan Lee 2016/08/16 09:24:34 Just realized that WRL::Callback supports calling
+ .Get(),
+ &token_Added_);
+ DCHECK(!FAILED(hr));
+
+ hr = watcher_->add_EnumerationCompleted(
+ Callback<ITypedEventHandler<DeviceWatcher*, IInspectable*>>(
+ std::bind(&CallbackHandler::OnEnumerationCompleted, handler, _1,
+ _2))
+ .Get(),
+ &token_EnumerationCompleted_);
+ DCHECK(!FAILED(hr));
+
+ hr = watcher_->add_Removed(
+ Callback<ITypedEventHandler<DeviceWatcher*, DeviceInformationUpdate*>>(
+ std::bind(&CallbackHandler::OnRemoved, handler, _1, _2))
+ .Get(),
+ &token_Removed_);
+ DCHECK(!FAILED(hr));
+
+ hr = watcher_->add_Stopped(
+ Callback<ITypedEventHandler<DeviceWatcher*, IInspectable*>>(
+ std::bind(&CallbackHandler::OnStopped, handler, _1, _2))
+ .Get(),
+ &token_Stopped_);
+ DCHECK(!FAILED(hr));
+
+ hr = watcher_->add_Updated(
+ Callback<ITypedEventHandler<DeviceWatcher*, DeviceInformationUpdate*>>(
+ std::bind(&CallbackHandler::OnUpdated, handler, _1, _2))
+ .Get(),
+ &token_Updated_);
+ DCHECK(!FAILED(hr));
+
+ hr = watcher_->Start();
+ DCHECK(!FAILED(hr));
+ }
+
+ private:
+ ComPtr<IDeviceWatcher> watcher_;
+ EventRegistrationToken token_Added_, token_EnumerationCompleted_,
+ token_Removed_, token_Stopped_, token_Updated_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceWatcherWrapper);
+};
+
+template <typename T>
+inline std::string GetIdString(T obj) {
+ HSTRING hs;
+ HRESULT hr = obj->get_Id(&hs);
+ DCHECK(!FAILED(hr));
+ return base::WideToUTF8(WindowsGetStringRawBuffer(hs, nullptr));
+}
+
+template <typename T>
+inline std::string GetDeviceIdString(T obj) {
+ HSTRING hs;
+ HRESULT hr = obj->get_DeviceId(&hs);
+ DCHECK(!FAILED(hr));
+ return base::WideToUTF8(WindowsGetStringRawBuffer(hs, nullptr));
+}
+
+inline std::string GetNameString(IDeviceInformation* info) {
+ HSTRING hs;
+ HRESULT hr = info->get_Name(&hs);
+ DCHECK(!FAILED(hr));
+ return base::WideToUTF8(WindowsGetStringRawBuffer(hs, nullptr));
+}
+
+template <typename InterfaceType>
+struct MidiPort {
+ MidiPort() {}
+
+ uint32_t index;
+ ComPtr<InterfaceType> handle;
+ base::TimeTicks start_time;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MidiPort);
+};
+
+template <typename InterfaceType, typename RuntimeType>
+class MidiPortManager : public DeviceWatcherWrapper::CallbackHandler {
+ public:
+ void SetDelegate(MidiServiceWinDelegate* delegate) { delegate_ = delegate; }
+
+ MidiPort<InterfaceType>* GetPortByDeviceId(std::string dev_id) {
+ base::AutoLock auto_lock(ports_lock_);
+ auto it = ports_.find(dev_id);
+ if (it == ports_.end())
+ return nullptr;
+ return it->second.get();
+ }
+
+ MidiPort<InterfaceType>* GetPortByIndex(uint32_t port_index) {
+ base::AutoLock auto_lock(ports_lock_);
+ auto it = ports_.find(port_ids_[port_index]);
+ if (it == ports_.end())
+ return nullptr;
+ return it->second.get();
+ }
+
+ // DeviceWatcherWrapper::CallbackHandler overrides:
+ HRESULT OnAdded(IDeviceWatcher* watcher, IDeviceInformation* info) override {
+ HSTRING dev_id_hs;
+ HRESULT hr = info->get_Id(&dev_id_hs);
+ DCHECK(!FAILED(hr));
+
+ std::string dev_id =
+ base::WideToUTF8(WindowsGetStringRawBuffer(dev_id_hs, nullptr));
+
+ {
+ base::AutoLock auto_lock(ports_lock_);
+ port_names_[dev_id] = GetNameString(info);
+ }
+
+ ComPtr<IAsyncOperation<RuntimeType*>> async_op;
+
+ RegisterGetPortFromIdAsync(&async_op, dev_id_hs);
+
+ hr = async_op->put_Completed(
+ Callback<IAsyncOperationCompletedHandler<RuntimeType*>>(
+ std::bind(&MidiPortManager::OnCompletedGetPortFromIdAsync, this, _1,
+ _2))
+ .Get());
+ DCHECK(!FAILED(hr));
+
+ {
+ base::AutoLock auto_lock(async_ops_lock_);
+ async_ops_.insert(std::move(async_op));
+ }
+
+ return S_OK;
+ }
+
+ HRESULT OnEnumerationCompleted(IDeviceWatcher* watcher,
+ IInspectable* insp) override {
+ // TODO(shaochuan)
+ return S_OK;
+ }
+
+ HRESULT OnRemoved(IDeviceWatcher* watcher,
+ IDeviceInformationUpdate* update) override {
+ MidiPort<InterfaceType>* port = GetPortByDeviceId(GetIdString(update));
+ DCHECK(port != nullptr);
+
+ SetPortState(port->index, MIDI_PORT_DISCONNECTED);
+
+ port->handle = nullptr;
+
+ return S_OK;
+ }
+
+ HRESULT OnStopped(IDeviceWatcher* watcher, IInspectable* insp) override {
+ // TODO(shaochuan)
+ return S_OK;
+ }
+
+ HRESULT OnUpdated(IDeviceWatcher* watcher,
+ IDeviceInformationUpdate* update) override {
+ // TODO(shaochuan)
+ return S_OK;
+ }
+
+ protected:
+ MidiServiceWinDelegate* delegate_;
+
+ private:
+ HRESULT OnCompletedGetPortFromIdAsync(IAsyncOperation<RuntimeType*>* async_op,
+ AsyncStatus status) {
+ const auto now = base::TimeTicks::Now();
+
+ InterfaceType* handle;
+ HRESULT hr = async_op->GetResults(&handle);
+ DCHECK(!FAILED(hr));
+
+ RegisterOnMessageReceived(handle);
+
+ std::string dev_id = GetDeviceIdString(handle);
+
+ MidiPort<InterfaceType>* port = GetPortByDeviceId(dev_id);
+
+ if (port == nullptr) {
+ base::AutoLock auto_lock(ports_lock_);
+
+ // TODO(shaochuan)
+ AddPort(MidiPortInfo(dev_id, std::string("Manufacturer"),
+ port_names_[dev_id], std::string("DriverVersion"),
+ MIDI_PORT_OPENED));
+
+ port = new MidiPort<InterfaceType>;
+ port->index = static_cast<uint32_t>(port_ids_.size());
+
+ ports_[dev_id].reset(port);
+ port_ids_.push_back(dev_id);
+ } else {
+ SetPortState(port->index, MIDI_PORT_CONNECTED);
+ }
+
+ port->handle = handle;
+ port->start_time = now;
+
+ {
+ base::AutoLock auto_lock(async_ops_lock_);
+ auto it = async_ops_.find(async_op);
+ DCHECK(it != async_ops_.end());
+ async_ops_.erase(it);
+ }
+
+ return S_OK;
+ }
+
+ // Implemented by child classes to call corresponding input/output methods.
+ virtual void RegisterGetPortFromIdAsync(
+ IAsyncOperation<RuntimeType*>** p_async_op,
+ HSTRING dev_id) = 0;
+
+ virtual void RegisterOnMessageReceived(InterfaceType* handle) = 0;
+
+ virtual void AddPort(MidiPortInfo info) = 0;
+
+ virtual void SetPortState(uint32_t port_index, MidiPortState state) = 0;
+
+ base::Lock ports_lock_;
+ base::hash_map<std::string, std::unique_ptr<MidiPort<InterfaceType>>>
+ ports_; // GUARDED_BY(ports_lock_)
+ std::vector<std::string> port_ids_; // GUARDED_BY(ports_lock_)
+ base::hash_map<std::string, std::string>
+ port_names_; // GUARDED_BY(ports_lock_)
+
+ base::Lock async_ops_lock_;
+ std::set<ComPtr<IAsyncOperation<RuntimeType*>>>
+ async_ops_; // GUARDED_BY(async_ops_lock_)
+};
+
+class MidiInPortManager final
+ : public MidiPortManager<IMidiInPort, MidiInPort> {
+ public:
+ MidiInPortManager() {}
+
+ private:
+ // MidiPortManager overrides:
+ void RegisterGetPortFromIdAsync(IAsyncOperation<MidiInPort*>** p_async_op,
+ HSTRING dev_id) override {
+ HRESULT hr = WrlStatics::GetInstance().GetMidiInPortStatics()->FromIdAsync(
+ dev_id, p_async_op);
+ DCHECK(!FAILED(hr));
+ }
+
+ void RegisterOnMessageReceived(IMidiInPort* handle) override {
+ base::AutoLock auto_lock(tokens_lock_);
+ EventRegistrationToken& token = tokens_[GetDeviceIdString(handle)];
+
+ handle->add_MessageReceived(
+ Callback<
+ ITypedEventHandler<MidiInPort*, MidiMessageReceivedEventArgs*>>(
+ std::bind(&MidiInPortManager::OnMessageReceived, this, _1, _2))
+ .Get(),
+ &token);
+ }
+
+ void AddPort(MidiPortInfo info) { delegate_->OnAddInputPort(info); }
+
+ void SetPortState(uint32_t port_index, MidiPortState state) {
+ delegate_->OnSetInputPortState(port_index, state);
+ }
+
+ // Callback on receiving MIDI input message.
+ HRESULT OnMessageReceived(IMidiInPort* handle,
+ IMidiMessageReceivedEventArgs* args) {
+ MidiPort<IMidiInPort>* port = GetPortByDeviceId(GetDeviceIdString(handle));
+ DCHECK(port != nullptr);
+
+ ComPtr<IMidiMessage> message;
+ HRESULT hr = args->get_Message(&message);
+ DCHECK(!FAILED(hr));
+
+ ComPtr<IBuffer> buffer;
+ hr = message->get_RawData(&buffer);
+ DCHECK(!FAILED(hr));
+
+ // Use BufferByteAccess object to access buffer memory directly.
+ ComPtr<IInspectable> insp(reinterpret_cast<IInspectable*>(buffer.Get()));
+ ComPtr<Windows::Storage::Streams::IBufferByteAccess> bba;
+ hr = insp.As(&bba);
+ DCHECK(!FAILED(hr));
+
+ uint8_t* data_arr = nullptr;
+ hr = bba->Buffer(reinterpret_cast<byte**>(&data_arr));
+ DCHECK(!FAILED(hr));
+
+ uint32_t len;
+ hr = buffer->get_Length(&len);
+ DCHECK(!FAILED(hr));
+ DCHECK(len != 0);
+
+ std::vector<uint8_t> data(data_arr, data_arr + len);
+
+ // Time since port opened in 100-nanosecond units.
+ TimeSpan time_span;
+ hr = message->get_Timestamp(&time_span);
+ DCHECK(!FAILED(hr));
+
+ delegate_->OnReceiveMidiData(
+ port->index, data, port->start_time + base::TimeDelta::FromMicroseconds(
+ time_span.Duration / 10));
+
+ return S_OK;
+ }
+
+ base::Lock tokens_lock_;
+ base::hash_map<std::string, EventRegistrationToken>
+ tokens_; // GUARDED_BY(tokens_lock_)
+
+ DISALLOW_COPY_AND_ASSIGN(MidiInPortManager);
+};
+
+class MidiOutPortManager final
+ : public MidiPortManager<IMidiOutPort, IMidiOutPort> {
+ public:
+ MidiOutPortManager() {}
+
+ private:
+ // MidiPortManager overrides:
+ void RegisterGetPortFromIdAsync(IAsyncOperation<IMidiOutPort*>** p_async_op,
+ HSTRING dev_id) override {
+ HRESULT hr = WrlStatics::GetInstance().GetMidiOutPortStatics()->FromIdAsync(
+ dev_id, p_async_op);
+ DCHECK(!FAILED(hr));
+ }
+
+ void RegisterOnMessageReceived(IMidiOutPort* handle) override {}
+
+ void AddPort(MidiPortInfo info) { delegate_->OnAddOutputPort(info); }
+
+ void SetPortState(uint32_t port_index, MidiPortState state) {
+ delegate_->OnSetOutputPortState(port_index, state);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(MidiOutPortManager);
+};
+
+HSTRING GetMidiInPortSelector() {
+ HSTRING selector = nullptr;
+ HRESULT hr =
+ WrlStatics::GetInstance().GetMidiInPortStatics()->GetDeviceSelector(
+ &selector);
+ DCHECK(!FAILED(hr));
+ return selector;
+}
+
+HSTRING GetMidiOutPortSelector() {
+ HSTRING selector = nullptr;
+ HRESULT hr =
+ WrlStatics::GetInstance().GetMidiOutPortStatics()->GetDeviceSelector(
+ &selector);
+ DCHECK(!FAILED(hr));
+ return selector;
+}
+
+class MidiServiceWinrtImpl : public MidiServiceWin {
Takashi Toyoshima 2016/08/15 08:46:24 Can you remove MidiService* layers and implement d
Shao-Chuan Lee 2016/08/16 07:42:24 Done.
+ public:
+ MidiServiceWinrtImpl()
+ : delegate_(nullptr),
+ com_thread_("Windows MIDI COM thread"),
+ manager_in_(),
+ manager_out_(),
+ watcher_in_(),
+ watcher_out_() {}
+
+ ~MidiServiceWinrtImpl() final { com_thread_.Stop(); }
+
+ // MidiServiceWin overrides:
+ void InitializeAsync(MidiServiceWinDelegate* delegate) final {
+ delegate_ = delegate;
+
+ com_thread_.init_com_with_mta(true);
+ com_thread_.Start();
+
+ manager_in_.SetDelegate(delegate);
+ manager_out_.SetDelegate(delegate);
+
+ com_thread_.message_loop()->PostTask(
+ FROM_HERE, base::Bind(&MidiServiceWinrtImpl::InitializeOnComThread,
+ base::Unretained(this)));
+
+ delegate_->OnCompleteInitialization(Result::OK);
+ }
+
+ void SendMidiDataAsync(uint32_t port_index,
+ const std::vector<uint8_t>& data,
+ base::TimeTicks time) final {
+ const auto now = base::TimeTicks::Now();
+ if (now < time) {
+ com_thread_.message_loop()->PostDelayedTask(
+ FROM_HERE, base::Bind(&MidiServiceWinrtImpl::SendOnComThread,
+ base::Unretained(this), port_index, data, time),
+ time - now);
+ } else {
+ com_thread_.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&MidiServiceWinrtImpl::SendOnComThread,
+ base::Unretained(this), port_index, data, time));
+ }
+ }
+
+ private:
+ /////////////////////////////////////////////////////////////////////////////
+ // Callbacks on the COM thread.
+ /////////////////////////////////////////////////////////////////////////////
+
+ void AssertOnComThread() {
+ DCHECK_EQ(com_thread_.GetThreadId(), base::PlatformThread::CurrentId());
+ }
+
+ void InitializeOnComThread() {
+ AssertOnComThread();
+
+ watcher_in_.Setup(GetMidiInPortSelector(), &manager_in_);
+ watcher_out_.Setup(GetMidiOutPortSelector(), &manager_out_);
+ }
+
+ void SendOnComThread(uint32_t port_index,
+ const std::vector<uint8_t>& data,
+ base::TimeTicks time) {
+ AssertOnComThread();
+
+ ComPtr<IBuffer> buffer;
+ HRESULT hr = WrlStatics::GetInstance().GetBufferFactory()->Create(
+ static_cast<UINT32>(data.size()), &buffer);
+ DCHECK(!FAILED(hr));
+
+ hr = buffer->put_Length(static_cast<UINT32>(data.size()));
+ DCHECK(!FAILED(hr));
+
+ // Use BufferByteAccess object to access buffer memory directly.
+ ComPtr<IInspectable> insp(reinterpret_cast<IInspectable*>(buffer.Get()));
+ ComPtr<Windows::Storage::Streams::IBufferByteAccess> bba;
+ hr = insp.As(&bba);
+ DCHECK(!FAILED(hr));
+
+ uint8_t* data_arr = nullptr;
+ hr = bba->Buffer(reinterpret_cast<byte**>(&data_arr));
+ DCHECK(!FAILED(hr));
+
+ std::copy(data.begin(), data.end(), data_arr);
+
+ MidiPort<IMidiOutPort>* port = manager_out_.GetPortByIndex(port_index);
+ DCHECK(port != nullptr);
+
+ hr = port->handle->SendBuffer(buffer.Get());
+ DCHECK(!FAILED(hr));
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Fields:
+ /////////////////////////////////////////////////////////////////////////////
+
+ // Does not take ownership.
+ MidiServiceWinDelegate* delegate_;
+
+ base::Thread com_thread_;
+
+ MidiInPortManager manager_in_;
+ MidiOutPortManager manager_out_;
+ DeviceWatcherWrapper watcher_in_, watcher_out_;
+
+ DISALLOW_COPY_AND_ASSIGN(MidiServiceWinrtImpl);
+};
+
+} // namespace
+
+MidiManagerWin::MidiManagerWin() {}
+
+MidiManagerWin::~MidiManagerWin() {}
+
+void MidiManagerWin::StartInitialization() {
+ DCHECK(base::win::GetVersion() >= base::win::VERSION_WIN10);
Takashi Toyoshima 2016/08/15 08:46:23 Is this check enough? I mean is 10.0.10240.0 the f
Shao-Chuan Lee 2016/08/16 07:42:25 10.0.10240.0 seems to be the first release of Wind
+ midi_service_.reset(new MidiServiceWinrtImpl);
+ midi_service_->InitializeAsync(this);
+}
+
+void MidiManagerWin::Finalize() {
+ midi_service_.reset();
+}
+
+void MidiManagerWin::DispatchSendMidiData(MidiManagerClient* client,
+ uint32_t port_index,
+ const std::vector<uint8_t>& data,
+ double timestamp) {
+ if (!midi_service_)
+ return;
+
+ base::TimeTicks time_to_send = base::TimeTicks::Now();
+ if (timestamp != 0.0) {
+ time_to_send =
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(
+ timestamp * base::Time::kMicrosecondsPerSecond);
+ }
+ midi_service_->SendMidiDataAsync(port_index, data, time_to_send);
Takashi Toyoshima 2016/08/15 08:46:24 Can you use MidiScheduler here? It would also make
Shao-Chuan Lee 2016/08/16 07:42:24 Using MidiScheduler now, but an extra wrapper is r
+
+ // TOOD(toyoshim): This calculation should be done when the date is actually
+ // sent.
+ client->AccumulateMidiBytesSent(data.size());
+}
+
+void MidiManagerWin::OnCompleteInitialization(Result result) {
+ CompleteInitialization(result);
+}
+
+void MidiManagerWin::OnAddInputPort(MidiPortInfo info) {
+ AddInputPort(info);
+}
+
+void MidiManagerWin::OnAddOutputPort(MidiPortInfo info) {
+ AddOutputPort(info);
+}
+
+void MidiManagerWin::OnSetInputPortState(uint32_t port_index,
+ MidiPortState state) {
+ SetInputPortState(port_index, state);
+}
+
+void MidiManagerWin::OnSetOutputPortState(uint32_t port_index,
+ MidiPortState state) {
+ SetOutputPortState(port_index, state);
+}
+
+void MidiManagerWin::OnReceiveMidiData(uint32_t port_index,
+ const std::vector<uint8_t>& data,
+ base::TimeTicks time) {
+ ReceiveMidiData(port_index, &data[0], data.size(), time);
+}
+
+MidiManager* MidiManager::Create() {
+ return new MidiManagerWin();
+}
+
+} // namespace midi
+} // namespace media
« media/midi/BUILD.gn ('K') | « media/midi/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698