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

Side by Side 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 unified diff | Download patch
« media/midi/BUILD.gn ('K') | « media/midi/BUILD.gn ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/midi/midi_manager_win.h"
6
7 #include <robuffer.h>
8 #include <windows.devices.enumeration.h>
9 #include <windows.devices.midi.h>
10 #include <wrl/event.h>
11
12 #include <functional>
13
14 #include "base/bind.h"
15 #include "base/containers/hash_tables.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/timer/timer.h"
18 #include "base/win/windows_version.h"
19 #include "media/midi/midi_port_info.h"
20
21 namespace media {
22 namespace midi {
23 namespace {
24
25 using namespace ABI::Windows::Devices::Enumeration;
26 using namespace ABI::Windows::Devices::Midi;
27 using namespace ABI::Windows::Foundation;
28 using namespace ABI::Windows::Storage::Streams;
29 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`.
30 using Microsoft::WRL::ComPtr;
31 using Microsoft::WRL::Wrappers::HStringReference;
32
33 using std::placeholders::_1;
34 using std::placeholders::_2;
35
36 // Singleton helper for accessing WRL static methods.
37 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
38 public:
39 static WrlStatics& GetInstance() {
40 static WrlStatics instance;
41 return instance;
42 }
43
44 auto GetBufferFactory() {
45 return GetStatics(buffer_factory_,
46 RuntimeClass_Windows_Storage_Streams_Buffer);
47 }
48
49 auto GetDeviceInformationStatics() {
50 return GetStatics(
51 device_information_statics_,
52 RuntimeClass_Windows_Devices_Enumeration_DeviceInformation);
53 }
54
55 auto GetMidiInPortStatics() {
56 return GetStatics(midi_in_port_statics_,
57 RuntimeClass_Windows_Devices_Midi_MidiInPort);
58 }
59
60 auto GetMidiOutPortStatics() {
61 return GetStatics(midi_out_port_statics_,
62 RuntimeClass_Windows_Devices_Midi_MidiOutPort);
63 }
64
65 private:
66 WrlStatics() {}
67
68 template <typename T>
69 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.
70 if (com_ptr == nullptr) {
71 HRESULT hr =
72 GetActivationFactory(HStringReference(class_id).Get(), &com_ptr);
73 DCHECK(!FAILED(hr));
74 }
75 return com_ptr.Get();
76 }
77
78 ComPtr<IBufferFactory> buffer_factory_;
79 ComPtr<IDeviceInformationStatics> device_information_statics_;
80 ComPtr<IMidiInPortStatics> midi_in_port_statics_;
81 ComPtr<IMidiOutPortStatics> midi_out_port_statics_;
82
83 DISALLOW_COPY_AND_ASSIGN(WrlStatics);
84 };
85
86 // Helper for setting up DeviceWatcher callbacks.
87 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.
88 public:
89 class CallbackHandler {
90 public:
91 virtual HRESULT OnAdded(IDeviceWatcher* watcher,
92 IDeviceInformation* info) = 0;
93 virtual HRESULT OnEnumerationCompleted(IDeviceWatcher* watcher,
94 IInspectable* insp) = 0;
95 virtual HRESULT OnRemoved(IDeviceWatcher* watcher,
96 IDeviceInformationUpdate* update) = 0;
97 virtual HRESULT OnStopped(IDeviceWatcher* watcher, IInspectable* insp) = 0;
98 virtual HRESULT OnUpdated(IDeviceWatcher* watcher,
99 IDeviceInformationUpdate* update) = 0;
100 };
101
102 DeviceWatcherWrapper() {}
103
104 ~DeviceWatcherWrapper() {
105 watcher_->remove_Added(token_Added_);
106 watcher_->remove_EnumerationCompleted(token_EnumerationCompleted_);
107 watcher_->remove_Removed(token_Removed_);
108 watcher_->remove_Stopped(token_Stopped_);
109 watcher_->remove_Updated(token_Updated_);
110 }
111
112 void Setup(HSTRING selector, CallbackHandler* handler) {
113 HRESULT hr;
114
115 hr = WrlStatics::GetInstance()
116 .GetDeviceInformationStatics()
117 ->CreateWatcherAqsFilter(selector, &watcher_);
118 DCHECK(!FAILED(hr));
119
120 hr = watcher_->add_Added(
121 Callback<ITypedEventHandler<DeviceWatcher*, DeviceInformation*>>(
122 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
123 .Get(),
124 &token_Added_);
125 DCHECK(!FAILED(hr));
126
127 hr = watcher_->add_EnumerationCompleted(
128 Callback<ITypedEventHandler<DeviceWatcher*, IInspectable*>>(
129 std::bind(&CallbackHandler::OnEnumerationCompleted, handler, _1,
130 _2))
131 .Get(),
132 &token_EnumerationCompleted_);
133 DCHECK(!FAILED(hr));
134
135 hr = watcher_->add_Removed(
136 Callback<ITypedEventHandler<DeviceWatcher*, DeviceInformationUpdate*>>(
137 std::bind(&CallbackHandler::OnRemoved, handler, _1, _2))
138 .Get(),
139 &token_Removed_);
140 DCHECK(!FAILED(hr));
141
142 hr = watcher_->add_Stopped(
143 Callback<ITypedEventHandler<DeviceWatcher*, IInspectable*>>(
144 std::bind(&CallbackHandler::OnStopped, handler, _1, _2))
145 .Get(),
146 &token_Stopped_);
147 DCHECK(!FAILED(hr));
148
149 hr = watcher_->add_Updated(
150 Callback<ITypedEventHandler<DeviceWatcher*, DeviceInformationUpdate*>>(
151 std::bind(&CallbackHandler::OnUpdated, handler, _1, _2))
152 .Get(),
153 &token_Updated_);
154 DCHECK(!FAILED(hr));
155
156 hr = watcher_->Start();
157 DCHECK(!FAILED(hr));
158 }
159
160 private:
161 ComPtr<IDeviceWatcher> watcher_;
162 EventRegistrationToken token_Added_, token_EnumerationCompleted_,
163 token_Removed_, token_Stopped_, token_Updated_;
164
165 DISALLOW_COPY_AND_ASSIGN(DeviceWatcherWrapper);
166 };
167
168 template <typename T>
169 inline std::string GetIdString(T obj) {
170 HSTRING hs;
171 HRESULT hr = obj->get_Id(&hs);
172 DCHECK(!FAILED(hr));
173 return base::WideToUTF8(WindowsGetStringRawBuffer(hs, nullptr));
174 }
175
176 template <typename T>
177 inline std::string GetDeviceIdString(T obj) {
178 HSTRING hs;
179 HRESULT hr = obj->get_DeviceId(&hs);
180 DCHECK(!FAILED(hr));
181 return base::WideToUTF8(WindowsGetStringRawBuffer(hs, nullptr));
182 }
183
184 inline std::string GetNameString(IDeviceInformation* info) {
185 HSTRING hs;
186 HRESULT hr = info->get_Name(&hs);
187 DCHECK(!FAILED(hr));
188 return base::WideToUTF8(WindowsGetStringRawBuffer(hs, nullptr));
189 }
190
191 template <typename InterfaceType>
192 struct MidiPort {
193 MidiPort() {}
194
195 uint32_t index;
196 ComPtr<InterfaceType> handle;
197 base::TimeTicks start_time;
198
199 private:
200 DISALLOW_COPY_AND_ASSIGN(MidiPort);
201 };
202
203 template <typename InterfaceType, typename RuntimeType>
204 class MidiPortManager : public DeviceWatcherWrapper::CallbackHandler {
205 public:
206 void SetDelegate(MidiServiceWinDelegate* delegate) { delegate_ = delegate; }
207
208 MidiPort<InterfaceType>* GetPortByDeviceId(std::string dev_id) {
209 base::AutoLock auto_lock(ports_lock_);
210 auto it = ports_.find(dev_id);
211 if (it == ports_.end())
212 return nullptr;
213 return it->second.get();
214 }
215
216 MidiPort<InterfaceType>* GetPortByIndex(uint32_t port_index) {
217 base::AutoLock auto_lock(ports_lock_);
218 auto it = ports_.find(port_ids_[port_index]);
219 if (it == ports_.end())
220 return nullptr;
221 return it->second.get();
222 }
223
224 // DeviceWatcherWrapper::CallbackHandler overrides:
225 HRESULT OnAdded(IDeviceWatcher* watcher, IDeviceInformation* info) override {
226 HSTRING dev_id_hs;
227 HRESULT hr = info->get_Id(&dev_id_hs);
228 DCHECK(!FAILED(hr));
229
230 std::string dev_id =
231 base::WideToUTF8(WindowsGetStringRawBuffer(dev_id_hs, nullptr));
232
233 {
234 base::AutoLock auto_lock(ports_lock_);
235 port_names_[dev_id] = GetNameString(info);
236 }
237
238 ComPtr<IAsyncOperation<RuntimeType*>> async_op;
239
240 RegisterGetPortFromIdAsync(&async_op, dev_id_hs);
241
242 hr = async_op->put_Completed(
243 Callback<IAsyncOperationCompletedHandler<RuntimeType*>>(
244 std::bind(&MidiPortManager::OnCompletedGetPortFromIdAsync, this, _1,
245 _2))
246 .Get());
247 DCHECK(!FAILED(hr));
248
249 {
250 base::AutoLock auto_lock(async_ops_lock_);
251 async_ops_.insert(std::move(async_op));
252 }
253
254 return S_OK;
255 }
256
257 HRESULT OnEnumerationCompleted(IDeviceWatcher* watcher,
258 IInspectable* insp) override {
259 // TODO(shaochuan)
260 return S_OK;
261 }
262
263 HRESULT OnRemoved(IDeviceWatcher* watcher,
264 IDeviceInformationUpdate* update) override {
265 MidiPort<InterfaceType>* port = GetPortByDeviceId(GetIdString(update));
266 DCHECK(port != nullptr);
267
268 SetPortState(port->index, MIDI_PORT_DISCONNECTED);
269
270 port->handle = nullptr;
271
272 return S_OK;
273 }
274
275 HRESULT OnStopped(IDeviceWatcher* watcher, IInspectable* insp) override {
276 // TODO(shaochuan)
277 return S_OK;
278 }
279
280 HRESULT OnUpdated(IDeviceWatcher* watcher,
281 IDeviceInformationUpdate* update) override {
282 // TODO(shaochuan)
283 return S_OK;
284 }
285
286 protected:
287 MidiServiceWinDelegate* delegate_;
288
289 private:
290 HRESULT OnCompletedGetPortFromIdAsync(IAsyncOperation<RuntimeType*>* async_op,
291 AsyncStatus status) {
292 const auto now = base::TimeTicks::Now();
293
294 InterfaceType* handle;
295 HRESULT hr = async_op->GetResults(&handle);
296 DCHECK(!FAILED(hr));
297
298 RegisterOnMessageReceived(handle);
299
300 std::string dev_id = GetDeviceIdString(handle);
301
302 MidiPort<InterfaceType>* port = GetPortByDeviceId(dev_id);
303
304 if (port == nullptr) {
305 base::AutoLock auto_lock(ports_lock_);
306
307 // TODO(shaochuan)
308 AddPort(MidiPortInfo(dev_id, std::string("Manufacturer"),
309 port_names_[dev_id], std::string("DriverVersion"),
310 MIDI_PORT_OPENED));
311
312 port = new MidiPort<InterfaceType>;
313 port->index = static_cast<uint32_t>(port_ids_.size());
314
315 ports_[dev_id].reset(port);
316 port_ids_.push_back(dev_id);
317 } else {
318 SetPortState(port->index, MIDI_PORT_CONNECTED);
319 }
320
321 port->handle = handle;
322 port->start_time = now;
323
324 {
325 base::AutoLock auto_lock(async_ops_lock_);
326 auto it = async_ops_.find(async_op);
327 DCHECK(it != async_ops_.end());
328 async_ops_.erase(it);
329 }
330
331 return S_OK;
332 }
333
334 // Implemented by child classes to call corresponding input/output methods.
335 virtual void RegisterGetPortFromIdAsync(
336 IAsyncOperation<RuntimeType*>** p_async_op,
337 HSTRING dev_id) = 0;
338
339 virtual void RegisterOnMessageReceived(InterfaceType* handle) = 0;
340
341 virtual void AddPort(MidiPortInfo info) = 0;
342
343 virtual void SetPortState(uint32_t port_index, MidiPortState state) = 0;
344
345 base::Lock ports_lock_;
346 base::hash_map<std::string, std::unique_ptr<MidiPort<InterfaceType>>>
347 ports_; // GUARDED_BY(ports_lock_)
348 std::vector<std::string> port_ids_; // GUARDED_BY(ports_lock_)
349 base::hash_map<std::string, std::string>
350 port_names_; // GUARDED_BY(ports_lock_)
351
352 base::Lock async_ops_lock_;
353 std::set<ComPtr<IAsyncOperation<RuntimeType*>>>
354 async_ops_; // GUARDED_BY(async_ops_lock_)
355 };
356
357 class MidiInPortManager final
358 : public MidiPortManager<IMidiInPort, MidiInPort> {
359 public:
360 MidiInPortManager() {}
361
362 private:
363 // MidiPortManager overrides:
364 void RegisterGetPortFromIdAsync(IAsyncOperation<MidiInPort*>** p_async_op,
365 HSTRING dev_id) override {
366 HRESULT hr = WrlStatics::GetInstance().GetMidiInPortStatics()->FromIdAsync(
367 dev_id, p_async_op);
368 DCHECK(!FAILED(hr));
369 }
370
371 void RegisterOnMessageReceived(IMidiInPort* handle) override {
372 base::AutoLock auto_lock(tokens_lock_);
373 EventRegistrationToken& token = tokens_[GetDeviceIdString(handle)];
374
375 handle->add_MessageReceived(
376 Callback<
377 ITypedEventHandler<MidiInPort*, MidiMessageReceivedEventArgs*>>(
378 std::bind(&MidiInPortManager::OnMessageReceived, this, _1, _2))
379 .Get(),
380 &token);
381 }
382
383 void AddPort(MidiPortInfo info) { delegate_->OnAddInputPort(info); }
384
385 void SetPortState(uint32_t port_index, MidiPortState state) {
386 delegate_->OnSetInputPortState(port_index, state);
387 }
388
389 // Callback on receiving MIDI input message.
390 HRESULT OnMessageReceived(IMidiInPort* handle,
391 IMidiMessageReceivedEventArgs* args) {
392 MidiPort<IMidiInPort>* port = GetPortByDeviceId(GetDeviceIdString(handle));
393 DCHECK(port != nullptr);
394
395 ComPtr<IMidiMessage> message;
396 HRESULT hr = args->get_Message(&message);
397 DCHECK(!FAILED(hr));
398
399 ComPtr<IBuffer> buffer;
400 hr = message->get_RawData(&buffer);
401 DCHECK(!FAILED(hr));
402
403 // Use BufferByteAccess object to access buffer memory directly.
404 ComPtr<IInspectable> insp(reinterpret_cast<IInspectable*>(buffer.Get()));
405 ComPtr<Windows::Storage::Streams::IBufferByteAccess> bba;
406 hr = insp.As(&bba);
407 DCHECK(!FAILED(hr));
408
409 uint8_t* data_arr = nullptr;
410 hr = bba->Buffer(reinterpret_cast<byte**>(&data_arr));
411 DCHECK(!FAILED(hr));
412
413 uint32_t len;
414 hr = buffer->get_Length(&len);
415 DCHECK(!FAILED(hr));
416 DCHECK(len != 0);
417
418 std::vector<uint8_t> data(data_arr, data_arr + len);
419
420 // Time since port opened in 100-nanosecond units.
421 TimeSpan time_span;
422 hr = message->get_Timestamp(&time_span);
423 DCHECK(!FAILED(hr));
424
425 delegate_->OnReceiveMidiData(
426 port->index, data, port->start_time + base::TimeDelta::FromMicroseconds(
427 time_span.Duration / 10));
428
429 return S_OK;
430 }
431
432 base::Lock tokens_lock_;
433 base::hash_map<std::string, EventRegistrationToken>
434 tokens_; // GUARDED_BY(tokens_lock_)
435
436 DISALLOW_COPY_AND_ASSIGN(MidiInPortManager);
437 };
438
439 class MidiOutPortManager final
440 : public MidiPortManager<IMidiOutPort, IMidiOutPort> {
441 public:
442 MidiOutPortManager() {}
443
444 private:
445 // MidiPortManager overrides:
446 void RegisterGetPortFromIdAsync(IAsyncOperation<IMidiOutPort*>** p_async_op,
447 HSTRING dev_id) override {
448 HRESULT hr = WrlStatics::GetInstance().GetMidiOutPortStatics()->FromIdAsync(
449 dev_id, p_async_op);
450 DCHECK(!FAILED(hr));
451 }
452
453 void RegisterOnMessageReceived(IMidiOutPort* handle) override {}
454
455 void AddPort(MidiPortInfo info) { delegate_->OnAddOutputPort(info); }
456
457 void SetPortState(uint32_t port_index, MidiPortState state) {
458 delegate_->OnSetOutputPortState(port_index, state);
459 }
460
461 DISALLOW_COPY_AND_ASSIGN(MidiOutPortManager);
462 };
463
464 HSTRING GetMidiInPortSelector() {
465 HSTRING selector = nullptr;
466 HRESULT hr =
467 WrlStatics::GetInstance().GetMidiInPortStatics()->GetDeviceSelector(
468 &selector);
469 DCHECK(!FAILED(hr));
470 return selector;
471 }
472
473 HSTRING GetMidiOutPortSelector() {
474 HSTRING selector = nullptr;
475 HRESULT hr =
476 WrlStatics::GetInstance().GetMidiOutPortStatics()->GetDeviceSelector(
477 &selector);
478 DCHECK(!FAILED(hr));
479 return selector;
480 }
481
482 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.
483 public:
484 MidiServiceWinrtImpl()
485 : delegate_(nullptr),
486 com_thread_("Windows MIDI COM thread"),
487 manager_in_(),
488 manager_out_(),
489 watcher_in_(),
490 watcher_out_() {}
491
492 ~MidiServiceWinrtImpl() final { com_thread_.Stop(); }
493
494 // MidiServiceWin overrides:
495 void InitializeAsync(MidiServiceWinDelegate* delegate) final {
496 delegate_ = delegate;
497
498 com_thread_.init_com_with_mta(true);
499 com_thread_.Start();
500
501 manager_in_.SetDelegate(delegate);
502 manager_out_.SetDelegate(delegate);
503
504 com_thread_.message_loop()->PostTask(
505 FROM_HERE, base::Bind(&MidiServiceWinrtImpl::InitializeOnComThread,
506 base::Unretained(this)));
507
508 delegate_->OnCompleteInitialization(Result::OK);
509 }
510
511 void SendMidiDataAsync(uint32_t port_index,
512 const std::vector<uint8_t>& data,
513 base::TimeTicks time) final {
514 const auto now = base::TimeTicks::Now();
515 if (now < time) {
516 com_thread_.message_loop()->PostDelayedTask(
517 FROM_HERE, base::Bind(&MidiServiceWinrtImpl::SendOnComThread,
518 base::Unretained(this), port_index, data, time),
519 time - now);
520 } else {
521 com_thread_.message_loop()->PostTask(
522 FROM_HERE,
523 base::Bind(&MidiServiceWinrtImpl::SendOnComThread,
524 base::Unretained(this), port_index, data, time));
525 }
526 }
527
528 private:
529 /////////////////////////////////////////////////////////////////////////////
530 // Callbacks on the COM thread.
531 /////////////////////////////////////////////////////////////////////////////
532
533 void AssertOnComThread() {
534 DCHECK_EQ(com_thread_.GetThreadId(), base::PlatformThread::CurrentId());
535 }
536
537 void InitializeOnComThread() {
538 AssertOnComThread();
539
540 watcher_in_.Setup(GetMidiInPortSelector(), &manager_in_);
541 watcher_out_.Setup(GetMidiOutPortSelector(), &manager_out_);
542 }
543
544 void SendOnComThread(uint32_t port_index,
545 const std::vector<uint8_t>& data,
546 base::TimeTicks time) {
547 AssertOnComThread();
548
549 ComPtr<IBuffer> buffer;
550 HRESULT hr = WrlStatics::GetInstance().GetBufferFactory()->Create(
551 static_cast<UINT32>(data.size()), &buffer);
552 DCHECK(!FAILED(hr));
553
554 hr = buffer->put_Length(static_cast<UINT32>(data.size()));
555 DCHECK(!FAILED(hr));
556
557 // Use BufferByteAccess object to access buffer memory directly.
558 ComPtr<IInspectable> insp(reinterpret_cast<IInspectable*>(buffer.Get()));
559 ComPtr<Windows::Storage::Streams::IBufferByteAccess> bba;
560 hr = insp.As(&bba);
561 DCHECK(!FAILED(hr));
562
563 uint8_t* data_arr = nullptr;
564 hr = bba->Buffer(reinterpret_cast<byte**>(&data_arr));
565 DCHECK(!FAILED(hr));
566
567 std::copy(data.begin(), data.end(), data_arr);
568
569 MidiPort<IMidiOutPort>* port = manager_out_.GetPortByIndex(port_index);
570 DCHECK(port != nullptr);
571
572 hr = port->handle->SendBuffer(buffer.Get());
573 DCHECK(!FAILED(hr));
574 }
575
576 /////////////////////////////////////////////////////////////////////////////
577 // Fields:
578 /////////////////////////////////////////////////////////////////////////////
579
580 // Does not take ownership.
581 MidiServiceWinDelegate* delegate_;
582
583 base::Thread com_thread_;
584
585 MidiInPortManager manager_in_;
586 MidiOutPortManager manager_out_;
587 DeviceWatcherWrapper watcher_in_, watcher_out_;
588
589 DISALLOW_COPY_AND_ASSIGN(MidiServiceWinrtImpl);
590 };
591
592 } // namespace
593
594 MidiManagerWin::MidiManagerWin() {}
595
596 MidiManagerWin::~MidiManagerWin() {}
597
598 void MidiManagerWin::StartInitialization() {
599 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
600 midi_service_.reset(new MidiServiceWinrtImpl);
601 midi_service_->InitializeAsync(this);
602 }
603
604 void MidiManagerWin::Finalize() {
605 midi_service_.reset();
606 }
607
608 void MidiManagerWin::DispatchSendMidiData(MidiManagerClient* client,
609 uint32_t port_index,
610 const std::vector<uint8_t>& data,
611 double timestamp) {
612 if (!midi_service_)
613 return;
614
615 base::TimeTicks time_to_send = base::TimeTicks::Now();
616 if (timestamp != 0.0) {
617 time_to_send =
618 base::TimeTicks() + base::TimeDelta::FromMicroseconds(
619 timestamp * base::Time::kMicrosecondsPerSecond);
620 }
621 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
622
623 // TOOD(toyoshim): This calculation should be done when the date is actually
624 // sent.
625 client->AccumulateMidiBytesSent(data.size());
626 }
627
628 void MidiManagerWin::OnCompleteInitialization(Result result) {
629 CompleteInitialization(result);
630 }
631
632 void MidiManagerWin::OnAddInputPort(MidiPortInfo info) {
633 AddInputPort(info);
634 }
635
636 void MidiManagerWin::OnAddOutputPort(MidiPortInfo info) {
637 AddOutputPort(info);
638 }
639
640 void MidiManagerWin::OnSetInputPortState(uint32_t port_index,
641 MidiPortState state) {
642 SetInputPortState(port_index, state);
643 }
644
645 void MidiManagerWin::OnSetOutputPortState(uint32_t port_index,
646 MidiPortState state) {
647 SetOutputPortState(port_index, state);
648 }
649
650 void MidiManagerWin::OnReceiveMidiData(uint32_t port_index,
651 const std::vector<uint8_t>& data,
652 base::TimeTicks time) {
653 ReceiveMidiData(port_index, &data[0], data.size(), time);
654 }
655
656 MidiManager* MidiManager::Create() {
657 return new MidiManagerWin();
658 }
659
660 } // namespace midi
661 } // namespace media
OLDNEW
« 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