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

Side by Side Diff: media/midi/dynamically_initialized_midi_manager_win.cc

Issue 2701783003: Web MIDI: implement receiving for dynamic manager instantiation on Windows (Closed)
Patch Set: make map non-global/statically initialized object Created 3 years, 10 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
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/midi/dynamically_initialized_midi_manager_win.h" 5 #include "media/midi/dynamically_initialized_midi_manager_win.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include <mmreg.h> 9 #include <mmreg.h>
10 #include <mmsystem.h> 10 #include <mmsystem.h>
11 11
12 #include <algorithm> 12 #include <algorithm>
13 #include <string> 13 #include <string>
14 14
15 #include "base/callback.h" 15 #include "base/callback.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/memory/ptr_util.h" 17 #include "base/memory/ptr_util.h"
18 #include "base/strings/string16.h" 18 #include "base/strings/string16.h"
19 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h" 20 #include "base/strings/utf_string_conversions.h"
21 #include "base/synchronization/lock.h" 21 #include "base/synchronization/lock.h"
22 #include "media/midi/message_util.h"
22 #include "media/midi/midi_port_info.h" 23 #include "media/midi/midi_port_info.h"
23 #include "media/midi/midi_service.h" 24 #include "media/midi/midi_service.h"
24 25
25 namespace midi { 26 namespace midi {
26 27
28 // Forward declaration of PortManager for anonymous functions and internal
29 // classes to use it.
30 class DynamicallyInitializedMidiManagerWin::PortManager {
31 public:
32 // Calculates event time from elapsed time that system provides.
33 base::TimeTicks CalculateInEventTime(size_t index, uint32_t elapsed_ms) const;
34
35 // Registers HMIDIIN handle to resolve port index.
36 void RegisterInHandle(HMIDIIN handle, size_t index);
37
38 // Unregisters HMIDIIN handle.
39 void UnregisterInHandle(HMIDIIN handle);
40
41 // Finds HMIDIIN handle and fullfil |out_index| with the port index.
42 bool FindHandle(HMIDIIN hmi, size_t* out_index);
43
44 // Restores used input buffer for the next data receive.
45 void RestoreInBuffer(size_t index);
46
47 // Ports accessors.
48 std::vector<std::unique_ptr<InPort>>* inputs() { return &input_ports_; }
49 std::vector<std::unique_ptr<OutPort>>* outputs() { return &output_ports_; }
50
51 private:
52 // Holds all MIDI input or output ports connected once.
53 std::vector<std::unique_ptr<InPort>> input_ports_;
54 std::vector<std::unique_ptr<OutPort>> output_ports_;
55
56 // Map to resolve MIDI input port index from HMIDIIN.
57 std::map<HMIDIIN, size_t> hmidiin_to_index_map_;
58 };
59
27 namespace { 60 namespace {
28 61
29 // Assumes that nullptr represents an invalid MIDI handle. 62 // Assumes that nullptr represents an invalid MIDI handle.
30 constexpr HMIDIIN kInvalidInHandle = nullptr; 63 constexpr HMIDIIN kInvalidInHandle = nullptr;
31 constexpr HMIDIOUT kInvalidOutHandle = nullptr; 64 constexpr HMIDIOUT kInvalidOutHandle = nullptr;
32 65
66 // Defines input buffer size.
67 constexpr size_t kBufferLength = 32 * 1024;
68
33 // Global variables to identify MidiManager instance. 69 // Global variables to identify MidiManager instance.
34 constexpr int kInvalidInstanceId = -1; 70 constexpr int kInvalidInstanceId = -1;
35 int g_active_instance_id = kInvalidInstanceId; 71 int g_active_instance_id = kInvalidInstanceId;
36 DynamicallyInitializedMidiManagerWin* g_manager_instance = nullptr; 72 DynamicallyInitializedMidiManagerWin* g_manager_instance = nullptr;
37 73
38 // Obtains base::Lock instance pointer to lock instance_id. 74 // Obtains base::Lock instance pointer to lock instance_id.
39 base::Lock* GetInstanceIdLock() { 75 base::Lock* GetInstanceIdLock() {
40 static base::Lock* lock = new base::Lock; 76 static base::Lock* lock = new base::Lock;
41 return lock; 77 return lock;
42 } 78 }
(...skipping 26 matching lines...) Expand all
69 base::AutoLock lock(*GetInstanceIdLock()); 105 base::AutoLock lock(*GetInstanceIdLock());
70 if (instance_id != g_active_instance_id) 106 if (instance_id != g_active_instance_id)
71 return; 107 return;
72 } 108 }
73 task.Run(); 109 task.Run();
74 } 110 }
75 111
76 // TODO(toyoshim): Factor out TaskRunner related functionaliries above, and 112 // TODO(toyoshim): Factor out TaskRunner related functionaliries above, and
77 // deprecate MidiScheduler. It should be available via MidiManager::scheduler(). 113 // deprecate MidiScheduler. It should be available via MidiManager::scheduler().
78 114
115 // Utility class to handle MIDIHDR struct safely.
116 class MIDIHDRDeleter {
117 public:
118 void operator()(LPMIDIHDR header) {
119 if (!header)
120 return;
121 delete[] static_cast<char*>(header->lpData);
122 delete header;
123 }
124 };
125
126 using ScopedMIDIHDR = std::unique_ptr<MIDIHDR, MIDIHDRDeleter>;
127
128 ScopedMIDIHDR CreateMIDIHDR(size_t size) {
129 ScopedMIDIHDR hdr(new MIDIHDR);
130 ZeroMemory(hdr.get(), sizeof(*hdr));
131 hdr->lpData = new char[size];
132 hdr->dwBufferLength = static_cast<DWORD>(size);
133 return hdr;
134 }
135
136 ScopedMIDIHDR CreateMIDIHDR(const std::vector<uint8_t>& data) {
137 ScopedMIDIHDR hdr(CreateMIDIHDR(data.size()));
138 std::copy(data.begin(), data.end(), hdr->lpData);
139 return hdr;
140 }
141
79 // Helper functions to close MIDI device handles on TaskRunner asynchronously. 142 // Helper functions to close MIDI device handles on TaskRunner asynchronously.
80 void FinalizeInPort(HMIDIIN handle) { 143 void FinalizeInPort(HMIDIIN handle, LPMIDIHDR lphdr) {
144 // Resets the device. This stops receiving messages, and allows to release
Takashi Toyoshima 2017/02/24 08:53:34 Actually, our legacy code of midi_manager_win.cc d
145 // registered buffer headers. Otherwise, midiInUnprepareHeader() and
146 // midiInClose() will fail with MIDIERR_STILLPLAYING.
147 midiInReset(handle);
148
149 // Obtains MIDIHDR ownership to release allocated buffers.
150 ScopedMIDIHDR hdr(lphdr);
151 if (hdr)
152 midiInUnprepareHeader(handle, hdr.get(), sizeof(*hdr));
81 midiInClose(handle); 153 midiInClose(handle);
82 } 154 }
83 155
84 void FinalizeOutPort(HMIDIOUT handle) { 156 void FinalizeOutPort(HMIDIOUT handle) {
85 midiOutClose(handle); 157 midiOutClose(handle);
86 } 158 }
87 159
88 // Handles MIDI input port callbacks that runs on a system provided thread. 160 // Handles MIDI input port callbacks that runs on a system provided thread.
89 void CALLBACK HandleMidiInCallback(HMIDIIN hmi, 161 void CALLBACK HandleMidiInCallback(HMIDIIN hmi,
90 UINT msg, 162 UINT msg,
91 DWORD_PTR instance, 163 DWORD_PTR instance,
92 DWORD_PTR param1, 164 DWORD_PTR param1,
93 DWORD_PTR param2) { 165 DWORD_PTR param2) {
94 // TODO(toyoshim): Following patches will implement actual functions. 166 if (msg != MIM_DATA && msg != MIM_LONGDATA)
167 return;
168 int instance_id = static_cast<int>(instance);
169 DynamicallyInitializedMidiManagerWin* manager = nullptr;
170
171 // Use |g_task_lock| so to ensure the instance can keep alive while running,
172 // and to access member variables that are used on TaskRunner.
173 base::AutoLock task_lock(*GetTaskLock());
174 {
175 base::AutoLock lock(*GetInstanceIdLock());
176 if (instance_id != g_active_instance_id)
177 return;
178 manager = g_manager_instance;
179 }
180
181 size_t index;
182 if (!manager->port_manager()->FindHandle(hmi, &index))
183 return;
184
185 if (msg == MIM_DATA) {
186 const uint8_t status_byte = static_cast<uint8_t>(param1 & 0xff);
Takashi Toyoshima 2017/02/24 08:53:34 Following code through PostReplyTask is same with
187 const uint8_t first_data_byte = static_cast<uint8_t>((param1 >> 8) & 0xff);
188 const uint8_t second_data_byte =
189 static_cast<uint8_t>((param1 >> 16) & 0xff);
190 const size_t len = GetMessageLength(status_byte);
191 const uint8_t kData[] = {status_byte, first_data_byte, second_data_byte};
192 std::vector<uint8_t> data;
193 data.assign(kData, kData + len);
194 manager->PostReplyTask(base::Bind(
195 &DynamicallyInitializedMidiManagerWin::ReceiveMidiData,
196 base::Unretained(manager), index, data,
197 manager->port_manager()->CalculateInEventTime(index, param2)));
198 } else { // msg == MIM_LONGDATA
yhirano 2017/02/24 12:22:58 Is this true? In the old code, the corresponding s
Takashi Toyoshima 2017/02/27 06:44:49 See line 166. But, it would be nicer to have DCHEC
199 LPMIDIHDR hdr = reinterpret_cast<LPMIDIHDR>(param1);
200 if (hdr->dwBytesRecorded > 0) {
201 const uint8_t* src = reinterpret_cast<const uint8_t*>(hdr->lpData);
202 std::vector<uint8_t> data;
203 data.assign(src, src + hdr->dwBytesRecorded);
204 manager->PostReplyTask(base::Bind(
205 &DynamicallyInitializedMidiManagerWin::ReceiveMidiData,
206 base::Unretained(manager), index, data,
207 manager->port_manager()->CalculateInEventTime(index, param2)));
208 }
209 manager->PostTask(base::Bind(
210 &DynamicallyInitializedMidiManagerWin::PortManager::RestoreInBuffer,
211 base::Unretained(manager->port_manager()), index));
212 }
95 } 213 }
96 214
97 // Handles MIDI output port callbacks that runs on a system provided thread. 215 // Handles MIDI output port callbacks that runs on a system provided thread.
98 void CALLBACK HandleMidiOutCallback(HMIDIOUT hmo, 216 void CALLBACK HandleMidiOutCallback(HMIDIOUT hmo,
99 UINT msg, 217 UINT msg,
100 DWORD_PTR instance, 218 DWORD_PTR instance,
101 DWORD_PTR param1, 219 DWORD_PTR param1,
102 DWORD_PTR param2) { 220 DWORD_PTR param2) {
103 // TODO(toyoshim): Following patches will implement actual functions. 221 // TODO(toyoshim): Following patches will implement actual functions.
104 } 222 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 const uint32_t driver_version_; 303 const uint32_t driver_version_;
186 const std::string product_name_; 304 const std::string product_name_;
187 MidiPortInfo info_; 305 MidiPortInfo info_;
188 }; // class Port 306 }; // class Port
189 307
190 } // namespace 308 } // namespace
191 309
192 // TODO(toyoshim): Following patches will implement actual functions. 310 // TODO(toyoshim): Following patches will implement actual functions.
193 class DynamicallyInitializedMidiManagerWin::InPort final : public Port { 311 class DynamicallyInitializedMidiManagerWin::InPort final : public Port {
194 public: 312 public:
195 InPort(UINT device_id, const MIDIINCAPS2W& caps) 313 InPort(DynamicallyInitializedMidiManagerWin* manager,
314 int instance_id,
315 UINT device_id,
316 const MIDIINCAPS2W& caps)
196 : Port("input", 317 : Port("input",
197 device_id, 318 device_id,
198 caps.wMid, 319 caps.wMid,
199 caps.wPid, 320 caps.wPid,
200 caps.vDriverVersion, 321 caps.vDriverVersion,
201 base::WideToUTF8( 322 base::WideToUTF8(
202 base::string16(caps.szPname, wcslen(caps.szPname)))), 323 base::string16(caps.szPname, wcslen(caps.szPname)))),
203 in_handle_(kInvalidInHandle) {} 324 manager_(manager),
325 in_handle_(kInvalidInHandle),
326 instance_id_(instance_id) {}
204 327
205 static std::vector<std::unique_ptr<InPort>> EnumerateActivePorts() { 328 static std::vector<std::unique_ptr<InPort>> EnumerateActivePorts(
329 DynamicallyInitializedMidiManagerWin* manager,
330 int instance_id) {
206 std::vector<std::unique_ptr<InPort>> ports; 331 std::vector<std::unique_ptr<InPort>> ports;
207 const UINT num_devices = midiInGetNumDevs(); 332 const UINT num_devices = midiInGetNumDevs();
208 for (UINT device_id = 0; device_id < num_devices; ++device_id) { 333 for (UINT device_id = 0; device_id < num_devices; ++device_id) {
209 MIDIINCAPS2W caps; 334 MIDIINCAPS2W caps;
210 MMRESULT result = midiInGetDevCaps( 335 MMRESULT result = midiInGetDevCaps(
211 device_id, reinterpret_cast<LPMIDIINCAPSW>(&caps), sizeof(caps)); 336 device_id, reinterpret_cast<LPMIDIINCAPSW>(&caps), sizeof(caps));
212 if (result != MMSYSERR_NOERROR) { 337 if (result != MMSYSERR_NOERROR) {
213 LOG(ERROR) << "midiInGetDevCaps fails on device " << device_id; 338 LOG(ERROR) << "midiInGetDevCaps fails on device " << device_id;
214 continue; 339 continue;
215 } 340 }
216 ports.push_back(base::MakeUnique<InPort>(device_id, caps)); 341 ports.push_back(
342 base::MakeUnique<InPort>(manager, instance_id, device_id, caps));
217 } 343 }
218 return ports; 344 return ports;
219 } 345 }
220 346
221 void Finalize(scoped_refptr<base::SingleThreadTaskRunner> runner) { 347 void Finalize(scoped_refptr<base::SingleThreadTaskRunner> runner) {
222 if (in_handle_ != kInvalidInHandle) { 348 if (in_handle_ != kInvalidInHandle) {
223 runner->PostTask(FROM_HERE, base::Bind(&FinalizeInPort, in_handle_)); 349 runner->PostTask(FROM_HERE,
350 base::Bind(&FinalizeInPort, in_handle_, hdr_.release()));
351 manager_->port_manager()->UnregisterInHandle(in_handle_);
224 in_handle_ = kInvalidInHandle; 352 in_handle_ = kInvalidInHandle;
225 } 353 }
226 } 354 }
227 355
356 base::TimeTicks CalculateInEventTime(uint32_t elapsed_ms) const {
357 return start_time_ + base::TimeDelta::FromMilliseconds(elapsed_ms);
358 }
359
360 void RestoreBuffer() {
361 if (in_handle_ == kInvalidInHandle || !hdr_)
362 return;
363 midiInAddBuffer(in_handle_, hdr_.get(), sizeof(*hdr_));
364 }
365
228 void NotifyPortStateSet(DynamicallyInitializedMidiManagerWin* manager) { 366 void NotifyPortStateSet(DynamicallyInitializedMidiManagerWin* manager) {
229 manager->PostReplyTask( 367 manager->PostReplyTask(
230 base::Bind(&DynamicallyInitializedMidiManagerWin::SetInputPortState, 368 base::Bind(&DynamicallyInitializedMidiManagerWin::SetInputPortState,
231 base::Unretained(manager), index_, info_.state)); 369 base::Unretained(manager), index_, info_.state));
232 } 370 }
233 371
234 void NotifyPortAdded(DynamicallyInitializedMidiManagerWin* manager) { 372 void NotifyPortAdded(DynamicallyInitializedMidiManagerWin* manager) {
235 manager->PostReplyTask( 373 manager->PostReplyTask(
236 base::Bind(&DynamicallyInitializedMidiManagerWin::AddInputPort, 374 base::Bind(&DynamicallyInitializedMidiManagerWin::AddInputPort,
237 base::Unretained(manager), info_)); 375 base::Unretained(manager), info_));
238 } 376 }
239 377
240 // Port overrides: 378 // Port overrides:
241 bool Disconnect() override { 379 bool Disconnect() override {
242 if (in_handle_ != kInvalidInHandle) { 380 if (in_handle_ != kInvalidInHandle) {
243 // Following API call may fail because device was already disconnected. 381 // Following API call may fail because device was already disconnected.
244 // But just in case. 382 // But just in case.
245 midiInClose(in_handle_); 383 midiInClose(in_handle_);
384 manager_->port_manager()->UnregisterInHandle(in_handle_);
246 in_handle_ = kInvalidInHandle; 385 in_handle_ = kInvalidInHandle;
247 } 386 }
248 return Port::Disconnect(); 387 return Port::Disconnect();
249 } 388 }
250 389
251 void Open() override { 390 void Open() override {
252 // TODO(toyoshim): Pass instance_id to implement HandleMidiInCallback.
253 MMRESULT result = 391 MMRESULT result =
254 midiInOpen(&in_handle_, device_id_, 392 midiInOpen(&in_handle_, device_id_,
255 reinterpret_cast<DWORD_PTR>(&HandleMidiInCallback), 0, 393 reinterpret_cast<DWORD_PTR>(&HandleMidiInCallback),
256 CALLBACK_FUNCTION); 394 instance_id_, CALLBACK_FUNCTION);
257 if (result == MMSYSERR_NOERROR) { 395 if (result == MMSYSERR_NOERROR) {
396 hdr_ = CreateMIDIHDR(kBufferLength);
397 result = midiInPrepareHeader(in_handle_, hdr_.get(), sizeof(*hdr_));
398 }
399 if (result != MMSYSERR_NOERROR)
400 in_handle_ = kInvalidInHandle;
401 if (result == MMSYSERR_NOERROR)
402 result = midiInAddBuffer(in_handle_, hdr_.get(), sizeof(*hdr_));
403 if (result == MMSYSERR_NOERROR)
404 result = midiInStart(in_handle_);
405 if (result == MMSYSERR_NOERROR) {
406 start_time_ = base::TimeTicks::Now();
407 manager_->port_manager()->RegisterInHandle(in_handle_, index_);
258 Port::Open(); 408 Port::Open();
259 } else { 409 } else {
260 in_handle_ = kInvalidInHandle; 410 if (in_handle_ != kInvalidInHandle) {
411 midiInUnprepareHeader(in_handle_, hdr_.get(), sizeof(*hdr_));
412 hdr_.reset();
413 midiInClose(in_handle_);
414 in_handle_ = kInvalidInHandle;
415 }
261 Disconnect(); 416 Disconnect();
262 } 417 }
263 } 418 }
264 419
265 private: 420 private:
421 DynamicallyInitializedMidiManagerWin* manager_;
266 HMIDIIN in_handle_; 422 HMIDIIN in_handle_;
423 ScopedMIDIHDR hdr_;
424 base::TimeTicks start_time_;
425 int instance_id_;
267 }; 426 };
268 427
269 // TODO(toyoshim): Following patches will implement actual functions. 428 // TODO(toyoshim): Following patches will implement actual functions.
270 class DynamicallyInitializedMidiManagerWin::OutPort final : public Port { 429 class DynamicallyInitializedMidiManagerWin::OutPort final : public Port {
271 public: 430 public:
272 OutPort(UINT device_id, const MIDIOUTCAPS2W& caps) 431 OutPort(UINT device_id, const MIDIOUTCAPS2W& caps)
273 : Port("output", 432 : Port("output",
274 device_id, 433 device_id,
275 caps.wMid, 434 caps.wMid,
276 caps.wPid, 435 caps.wPid,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 } else { 506 } else {
348 out_handle_ = kInvalidOutHandle; 507 out_handle_ = kInvalidOutHandle;
349 Disconnect(); 508 Disconnect();
350 } 509 }
351 } 510 }
352 511
353 const bool software_; 512 const bool software_;
354 HMIDIOUT out_handle_; 513 HMIDIOUT out_handle_;
355 }; 514 };
356 515
516 base::TimeTicks
517 DynamicallyInitializedMidiManagerWin::PortManager::CalculateInEventTime(
518 size_t index,
519 uint32_t elapsed_ms) const {
520 GetTaskLock()->AssertAcquired();
Takashi Toyoshima 2017/02/24 08:53:34 task lock should be obtained outside this method,
521 CHECK_GT(input_ports_.size(), index);
522 return input_ports_[index]->CalculateInEventTime(elapsed_ms);
523 }
524
525 void DynamicallyInitializedMidiManagerWin::PortManager::RegisterInHandle(
526 HMIDIIN handle,
527 size_t index) {
528 GetTaskLock()->AssertAcquired();
529 hmidiin_to_index_map_[handle] = index;
530 }
531
532 void DynamicallyInitializedMidiManagerWin::PortManager::UnregisterInHandle(
533 HMIDIIN handle) {
534 GetTaskLock()->AssertAcquired();
535 hmidiin_to_index_map_.erase(handle);
536 }
537
538 bool DynamicallyInitializedMidiManagerWin::PortManager::FindHandle(
539 HMIDIIN hmi,
540 size_t* out_index) {
541 GetTaskLock()->AssertAcquired();
542 auto found = hmidiin_to_index_map_.find(hmi);
543 if (found == hmidiin_to_index_map_.end())
544 return false;
545 *out_index = found->second;
546 return true;
547 }
548
549 void DynamicallyInitializedMidiManagerWin::PortManager::RestoreInBuffer(
550 size_t index) {
551 GetTaskLock()->AssertAcquired();
552 CHECK_GT(input_ports_.size(), index);
553 input_ports_[index]->RestoreBuffer();
554 }
555
357 DynamicallyInitializedMidiManagerWin::DynamicallyInitializedMidiManagerWin( 556 DynamicallyInitializedMidiManagerWin::DynamicallyInitializedMidiManagerWin(
358 MidiService* service) 557 MidiService* service)
359 : MidiManager(service), instance_id_(IssueNextInstanceId()) { 558 : MidiManager(service),
559 instance_id_(IssueNextInstanceId()),
560 port_manager_(base::MakeUnique<PortManager>()) {
360 base::AutoLock lock(*GetInstanceIdLock()); 561 base::AutoLock lock(*GetInstanceIdLock());
361 CHECK_EQ(kInvalidInstanceId, g_active_instance_id); 562 CHECK_EQ(kInvalidInstanceId, g_active_instance_id);
362 563
363 // Obtains the task runner for the current thread that hosts this instnace. 564 // Obtains the task runner for the current thread that hosts this instnace.
364 thread_runner_ = base::ThreadTaskRunnerHandle::Get(); 565 thread_runner_ = base::ThreadTaskRunnerHandle::Get();
365 } 566 }
366 567
367 DynamicallyInitializedMidiManagerWin::~DynamicallyInitializedMidiManagerWin() { 568 DynamicallyInitializedMidiManagerWin::~DynamicallyInitializedMidiManagerWin() {
368 base::AutoLock lock(*GetInstanceIdLock()); 569 base::AutoLock lock(*GetInstanceIdLock());
369 CHECK_EQ(kInvalidInstanceId, g_active_instance_id); 570 CHECK_EQ(kInvalidInstanceId, g_active_instance_id);
370 CHECK(thread_runner_->BelongsToCurrentThread()); 571 CHECK(thread_runner_->BelongsToCurrentThread());
371 } 572 }
372 573
574 void DynamicallyInitializedMidiManagerWin::ReceiveMidiData(
575 uint32_t index,
576 const std::vector<uint8_t>& data,
577 base::TimeTicks time) {
578 MidiManager::ReceiveMidiData(index, data.data(), data.size(), time);
579 }
580
581 void DynamicallyInitializedMidiManagerWin::PostTask(const base::Closure& task) {
582 service()
583 ->GetTaskRunner(kTaskRunner)
584 ->PostTask(FROM_HERE, base::Bind(&RunTask, instance_id_, task));
585 }
586
373 void DynamicallyInitializedMidiManagerWin::PostReplyTask( 587 void DynamicallyInitializedMidiManagerWin::PostReplyTask(
374 const base::Closure& task) { 588 const base::Closure& task) {
375 thread_runner_->PostTask(FROM_HERE, base::Bind(&RunTask, instance_id_, task)); 589 thread_runner_->PostTask(FROM_HERE, base::Bind(&RunTask, instance_id_, task));
376 } 590 }
377 591
378 void DynamicallyInitializedMidiManagerWin::StartInitialization() { 592 void DynamicallyInitializedMidiManagerWin::StartInitialization() {
379 { 593 {
380 base::AutoLock lock(*GetInstanceIdLock()); 594 base::AutoLock lock(*GetInstanceIdLock());
381 CHECK_EQ(kInvalidInstanceId, g_active_instance_id); 595 CHECK_EQ(kInvalidInstanceId, g_active_instance_id);
382 g_active_instance_id = instance_id_; 596 g_active_instance_id = instance_id_;
(...skipping 26 matching lines...) Expand all
409 // Tasks that did not started yet will do nothing after invalidate the 623 // Tasks that did not started yet will do nothing after invalidate the
410 // instance ID above. 624 // instance ID above.
411 // Behind the lock below, we can safely access all members for finalization 625 // Behind the lock below, we can safely access all members for finalization
412 // even on the I/O thread. 626 // even on the I/O thread.
413 base::AutoLock lock(*GetTaskLock()); 627 base::AutoLock lock(*GetTaskLock());
414 628
415 // Posts tasks that finalize each device port without MidiManager instance 629 // Posts tasks that finalize each device port without MidiManager instance
416 // on TaskRunner. If another MidiManager instance is created, its 630 // on TaskRunner. If another MidiManager instance is created, its
417 // initialization runs on the same task runner after all tasks posted here 631 // initialization runs on the same task runner after all tasks posted here
418 // finish. 632 // finish.
419 for (const auto& port : input_ports_) 633 for (const auto& port : *port_manager_->inputs())
420 port->Finalize(service()->GetTaskRunner(kTaskRunner)); 634 port->Finalize(service()->GetTaskRunner(kTaskRunner));
421 for (const auto& port : output_ports_) 635 for (const auto& port : *port_manager_->outputs())
422 port->Finalize(service()->GetTaskRunner(kTaskRunner)); 636 port->Finalize(service()->GetTaskRunner(kTaskRunner));
423 } 637 }
424 638
425 void DynamicallyInitializedMidiManagerWin::DispatchSendMidiData( 639 void DynamicallyInitializedMidiManagerWin::DispatchSendMidiData(
426 MidiManagerClient* client, 640 MidiManagerClient* client,
427 uint32_t port_index, 641 uint32_t port_index,
428 const std::vector<uint8_t>& data, 642 const std::vector<uint8_t>& data,
429 double timestamp) { 643 double timestamp) {
430 // TODO(toyoshim): Following patches will implement. 644 // TODO(toyoshim): Following patches will implement.
431 } 645 }
(...skipping 10 matching lines...) Expand all
442 return; 656 return;
443 case base::SystemMonitor::DEVTYPE_UNKNOWN: { 657 case base::SystemMonitor::DEVTYPE_UNKNOWN: {
444 PostTask(base::Bind( 658 PostTask(base::Bind(
445 &DynamicallyInitializedMidiManagerWin::UpdateDeviceListOnTaskRunner, 659 &DynamicallyInitializedMidiManagerWin::UpdateDeviceListOnTaskRunner,
446 base::Unretained(this))); 660 base::Unretained(this)));
447 break; 661 break;
448 } 662 }
449 } 663 }
450 } 664 }
451 665
452 void DynamicallyInitializedMidiManagerWin::PostTask(const base::Closure& task) {
453 service()
454 ->GetTaskRunner(kTaskRunner)
455 ->PostTask(FROM_HERE, base::Bind(&RunTask, instance_id_, task));
456 }
457
458 void DynamicallyInitializedMidiManagerWin::InitializeOnTaskRunner() { 666 void DynamicallyInitializedMidiManagerWin::InitializeOnTaskRunner() {
459 UpdateDeviceListOnTaskRunner(); 667 UpdateDeviceListOnTaskRunner();
460 PostReplyTask( 668 PostReplyTask(
461 base::Bind(&DynamicallyInitializedMidiManagerWin::CompleteInitialization, 669 base::Bind(&DynamicallyInitializedMidiManagerWin::CompleteInitialization,
462 base::Unretained(this), mojom::Result::OK)); 670 base::Unretained(this), mojom::Result::OK));
463 } 671 }
464 672
465 void DynamicallyInitializedMidiManagerWin::UpdateDeviceListOnTaskRunner() { 673 void DynamicallyInitializedMidiManagerWin::UpdateDeviceListOnTaskRunner() {
466 std::vector<std::unique_ptr<InPort>> active_input_ports = 674 std::vector<std::unique_ptr<InPort>> active_input_ports =
467 InPort::EnumerateActivePorts(); 675 InPort::EnumerateActivePorts(this, instance_id_);
468 ReflectActiveDeviceList(this, &input_ports_, &active_input_ports); 676 ReflectActiveDeviceList(this, port_manager_->inputs(), &active_input_ports);
469 677
470 std::vector<std::unique_ptr<OutPort>> active_output_ports = 678 std::vector<std::unique_ptr<OutPort>> active_output_ports =
471 OutPort::EnumerateActivePorts(); 679 OutPort::EnumerateActivePorts();
472 ReflectActiveDeviceList(this, &output_ports_, &active_output_ports); 680 ReflectActiveDeviceList(this, port_manager_->outputs(), &active_output_ports);
473 681
474 // TODO(toyoshim): This method may run before internal MIDI device lists that 682 // TODO(toyoshim): This method may run before internal MIDI device lists that
475 // Windows manages were updated. This may be because MIDI driver may be loaded 683 // Windows manages were updated. This may be because MIDI driver may be loaded
476 // after the raw device list was updated. To avoid this problem, we may want 684 // after the raw device list was updated. To avoid this problem, we may want
477 // to retry device check later if no changes are detected here. 685 // to retry device check later if no changes are detected here.
478 } 686 }
479 687
480 template <typename T> 688 template <typename T>
481 void DynamicallyInitializedMidiManagerWin::ReflectActiveDeviceList( 689 void DynamicallyInitializedMidiManagerWin::ReflectActiveDeviceList(
482 DynamicallyInitializedMidiManagerWin* manager, 690 DynamicallyInitializedMidiManagerWin* manager,
(...skipping 23 matching lines...) Expand all
506 size_t index = known_ports->size(); 714 size_t index = known_ports->size();
507 port->set_index(index); 715 port->set_index(index);
508 known_ports->push_back(std::move(port)); 716 known_ports->push_back(std::move(port));
509 (*known_ports)[index]->Connect(); 717 (*known_ports)[index]->Connect();
510 (*known_ports)[index]->NotifyPortAdded(this); 718 (*known_ports)[index]->NotifyPortAdded(this);
511 } 719 }
512 } 720 }
513 } 721 }
514 722
515 } // namespace midi 723 } // namespace midi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698