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

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: move methods into private Created 3 years, 9 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
« no previous file with comments | « media/midi/dynamically_initialized_midi_manager_win.h ('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
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 // Handles MIDI input port callbacks that runs on a system provided thread.
52 static void CALLBACK HandleMidiInCallback(HMIDIIN hmi,
53 UINT msg,
54 DWORD_PTR instance,
55 DWORD_PTR param1,
56 DWORD_PTR param2);
57
58 private:
59 // Holds all MIDI input or output ports connected once.
60 std::vector<std::unique_ptr<InPort>> input_ports_;
61 std::vector<std::unique_ptr<OutPort>> output_ports_;
62
63 // Map to resolve MIDI input port index from HMIDIIN.
64 std::map<HMIDIIN, size_t> hmidiin_to_index_map_;
65 };
66
27 namespace { 67 namespace {
28 68
29 // Assumes that nullptr represents an invalid MIDI handle. 69 // Assumes that nullptr represents an invalid MIDI handle.
30 constexpr HMIDIIN kInvalidInHandle = nullptr; 70 constexpr HMIDIIN kInvalidInHandle = nullptr;
31 constexpr HMIDIOUT kInvalidOutHandle = nullptr; 71 constexpr HMIDIOUT kInvalidOutHandle = nullptr;
32 72
73 // Defines input buffer size.
74 constexpr size_t kBufferLength = 32 * 1024;
75
33 // Global variables to identify MidiManager instance. 76 // Global variables to identify MidiManager instance.
34 constexpr int kInvalidInstanceId = -1; 77 constexpr int kInvalidInstanceId = -1;
35 int g_active_instance_id = kInvalidInstanceId; 78 int g_active_instance_id = kInvalidInstanceId;
36 DynamicallyInitializedMidiManagerWin* g_manager_instance = nullptr; 79 DynamicallyInitializedMidiManagerWin* g_manager_instance = nullptr;
37 80
38 // Obtains base::Lock instance pointer to lock instance_id. 81 // Obtains base::Lock instance pointer to lock instance_id.
39 base::Lock* GetInstanceIdLock() { 82 base::Lock* GetInstanceIdLock() {
40 static base::Lock* lock = new base::Lock; 83 static base::Lock* lock = new base::Lock;
41 return lock; 84 return lock;
42 } 85 }
(...skipping 26 matching lines...) Expand all
69 base::AutoLock lock(*GetInstanceIdLock()); 112 base::AutoLock lock(*GetInstanceIdLock());
70 if (instance_id != g_active_instance_id) 113 if (instance_id != g_active_instance_id)
71 return; 114 return;
72 } 115 }
73 task.Run(); 116 task.Run();
74 } 117 }
75 118
76 // TODO(toyoshim): Factor out TaskRunner related functionaliries above, and 119 // TODO(toyoshim): Factor out TaskRunner related functionaliries above, and
77 // deprecate MidiScheduler. It should be available via MidiManager::scheduler(). 120 // deprecate MidiScheduler. It should be available via MidiManager::scheduler().
78 121
122 // Utility class to handle MIDIHDR struct safely.
123 class MIDIHDRDeleter {
124 public:
125 void operator()(LPMIDIHDR header) {
126 if (!header)
127 return;
128 delete[] static_cast<char*>(header->lpData);
129 delete header;
130 }
131 };
132
133 using ScopedMIDIHDR = std::unique_ptr<MIDIHDR, MIDIHDRDeleter>;
134
135 ScopedMIDIHDR CreateMIDIHDR(size_t size) {
136 ScopedMIDIHDR hdr(new MIDIHDR);
137 ZeroMemory(hdr.get(), sizeof(*hdr));
138 hdr->lpData = new char[size];
139 hdr->dwBufferLength = static_cast<DWORD>(size);
140 return hdr;
141 }
142
143 ScopedMIDIHDR CreateMIDIHDR(const std::vector<uint8_t>& data) {
144 ScopedMIDIHDR hdr(CreateMIDIHDR(data.size()));
145 std::copy(data.begin(), data.end(), hdr->lpData);
146 return hdr;
147 }
148
79 // Helper functions to close MIDI device handles on TaskRunner asynchronously. 149 // Helper functions to close MIDI device handles on TaskRunner asynchronously.
80 void FinalizeInPort(HMIDIIN handle) { 150 void FinalizeInPort(HMIDIIN handle, LPMIDIHDR lphdr) {
151 // Resets the device. This stops receiving messages, and allows to release
152 // registered buffer headers. Otherwise, midiInUnprepareHeader() and
153 // midiInClose() will fail with MIDIERR_STILLPLAYING.
154 midiInReset(handle);
155
156 // Obtains MIDIHDR ownership to release allocated buffers.
157 ScopedMIDIHDR hdr(lphdr);
158 if (hdr)
159 midiInUnprepareHeader(handle, hdr.get(), sizeof(*hdr));
81 midiInClose(handle); 160 midiInClose(handle);
82 } 161 }
83 162
84 void FinalizeOutPort(HMIDIOUT handle) { 163 void FinalizeOutPort(HMIDIOUT handle) {
85 midiOutClose(handle); 164 midiOutClose(handle);
86 } 165 }
87 166
88 // Handles MIDI input port callbacks that runs on a system provided thread.
89 void CALLBACK HandleMidiInCallback(HMIDIIN hmi,
90 UINT msg,
91 DWORD_PTR instance,
92 DWORD_PTR param1,
93 DWORD_PTR param2) {
94 // TODO(toyoshim): Following patches will implement actual functions.
95 }
96
97 // Handles MIDI output port callbacks that runs on a system provided thread. 167 // Handles MIDI output port callbacks that runs on a system provided thread.
98 void CALLBACK HandleMidiOutCallback(HMIDIOUT hmo, 168 void CALLBACK HandleMidiOutCallback(HMIDIOUT hmo,
99 UINT msg, 169 UINT msg,
100 DWORD_PTR instance, 170 DWORD_PTR instance,
101 DWORD_PTR param1, 171 DWORD_PTR param1,
102 DWORD_PTR param2) { 172 DWORD_PTR param2) {
103 // TODO(toyoshim): Following patches will implement actual functions. 173 // TODO(toyoshim): Following patches will implement actual functions.
104 } 174 }
105 175
106 // All instances of Port subclasses are always accessed behind a lock of 176 // All instances of Port subclasses are always accessed behind a lock of
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 const uint32_t driver_version_; 255 const uint32_t driver_version_;
186 const std::string product_name_; 256 const std::string product_name_;
187 MidiPortInfo info_; 257 MidiPortInfo info_;
188 }; // class Port 258 }; // class Port
189 259
190 } // namespace 260 } // namespace
191 261
192 // TODO(toyoshim): Following patches will implement actual functions. 262 // TODO(toyoshim): Following patches will implement actual functions.
193 class DynamicallyInitializedMidiManagerWin::InPort final : public Port { 263 class DynamicallyInitializedMidiManagerWin::InPort final : public Port {
194 public: 264 public:
195 InPort(UINT device_id, const MIDIINCAPS2W& caps) 265 InPort(DynamicallyInitializedMidiManagerWin* manager,
266 int instance_id,
267 UINT device_id,
268 const MIDIINCAPS2W& caps)
196 : Port("input", 269 : Port("input",
197 device_id, 270 device_id,
198 caps.wMid, 271 caps.wMid,
199 caps.wPid, 272 caps.wPid,
200 caps.vDriverVersion, 273 caps.vDriverVersion,
201 base::WideToUTF8( 274 base::WideToUTF8(
202 base::string16(caps.szPname, wcslen(caps.szPname)))), 275 base::string16(caps.szPname, wcslen(caps.szPname)))),
203 in_handle_(kInvalidInHandle) {} 276 manager_(manager),
277 in_handle_(kInvalidInHandle),
278 instance_id_(instance_id) {}
204 279
205 static std::vector<std::unique_ptr<InPort>> EnumerateActivePorts() { 280 static std::vector<std::unique_ptr<InPort>> EnumerateActivePorts(
281 DynamicallyInitializedMidiManagerWin* manager,
282 int instance_id) {
206 std::vector<std::unique_ptr<InPort>> ports; 283 std::vector<std::unique_ptr<InPort>> ports;
207 const UINT num_devices = midiInGetNumDevs(); 284 const UINT num_devices = midiInGetNumDevs();
208 for (UINT device_id = 0; device_id < num_devices; ++device_id) { 285 for (UINT device_id = 0; device_id < num_devices; ++device_id) {
209 MIDIINCAPS2W caps; 286 MIDIINCAPS2W caps;
210 MMRESULT result = midiInGetDevCaps( 287 MMRESULT result = midiInGetDevCaps(
211 device_id, reinterpret_cast<LPMIDIINCAPSW>(&caps), sizeof(caps)); 288 device_id, reinterpret_cast<LPMIDIINCAPSW>(&caps), sizeof(caps));
212 if (result != MMSYSERR_NOERROR) { 289 if (result != MMSYSERR_NOERROR) {
213 LOG(ERROR) << "midiInGetDevCaps fails on device " << device_id; 290 LOG(ERROR) << "midiInGetDevCaps fails on device " << device_id;
214 continue; 291 continue;
215 } 292 }
216 ports.push_back(base::MakeUnique<InPort>(device_id, caps)); 293 ports.push_back(
294 base::MakeUnique<InPort>(manager, instance_id, device_id, caps));
217 } 295 }
218 return ports; 296 return ports;
219 } 297 }
220 298
221 void Finalize(scoped_refptr<base::SingleThreadTaskRunner> runner) { 299 void Finalize(scoped_refptr<base::SingleThreadTaskRunner> runner) {
222 if (in_handle_ != kInvalidInHandle) { 300 if (in_handle_ != kInvalidInHandle) {
223 runner->PostTask(FROM_HERE, base::Bind(&FinalizeInPort, in_handle_)); 301 runner->PostTask(FROM_HERE,
302 base::Bind(&FinalizeInPort, in_handle_, hdr_.release()));
yhirano 2017/02/28 11:02:02 Why don't you make FinalizeInPort take ScopedMidiH
Takashi Toyoshima 2017/03/01 01:10:35 Done.
303 manager_->port_manager()->UnregisterInHandle(in_handle_);
224 in_handle_ = kInvalidInHandle; 304 in_handle_ = kInvalidInHandle;
225 } 305 }
226 } 306 }
227 307
308 base::TimeTicks CalculateInEventTime(uint32_t elapsed_ms) const {
309 return start_time_ + base::TimeDelta::FromMilliseconds(elapsed_ms);
310 }
311
312 void RestoreBuffer() {
313 if (in_handle_ == kInvalidInHandle || !hdr_)
314 return;
315 midiInAddBuffer(in_handle_, hdr_.get(), sizeof(*hdr_));
316 }
317
228 void NotifyPortStateSet(DynamicallyInitializedMidiManagerWin* manager) { 318 void NotifyPortStateSet(DynamicallyInitializedMidiManagerWin* manager) {
229 manager->PostReplyTask( 319 manager->PostReplyTask(
230 base::Bind(&DynamicallyInitializedMidiManagerWin::SetInputPortState, 320 base::Bind(&DynamicallyInitializedMidiManagerWin::SetInputPortState,
231 base::Unretained(manager), index_, info_.state)); 321 base::Unretained(manager), index_, info_.state));
232 } 322 }
233 323
234 void NotifyPortAdded(DynamicallyInitializedMidiManagerWin* manager) { 324 void NotifyPortAdded(DynamicallyInitializedMidiManagerWin* manager) {
235 manager->PostReplyTask( 325 manager->PostReplyTask(
236 base::Bind(&DynamicallyInitializedMidiManagerWin::AddInputPort, 326 base::Bind(&DynamicallyInitializedMidiManagerWin::AddInputPort,
237 base::Unretained(manager), info_)); 327 base::Unretained(manager), info_));
238 } 328 }
239 329
240 // Port overrides: 330 // Port overrides:
241 bool Disconnect() override { 331 bool Disconnect() override {
242 if (in_handle_ != kInvalidInHandle) { 332 if (in_handle_ != kInvalidInHandle) {
243 // Following API call may fail because device was already disconnected. 333 // Following API call may fail because device was already disconnected.
244 // But just in case. 334 // But just in case.
245 midiInClose(in_handle_); 335 midiInClose(in_handle_);
336 manager_->port_manager()->UnregisterInHandle(in_handle_);
246 in_handle_ = kInvalidInHandle; 337 in_handle_ = kInvalidInHandle;
247 } 338 }
248 return Port::Disconnect(); 339 return Port::Disconnect();
249 } 340 }
250 341
251 void Open() override { 342 void Open() override {
252 // TODO(toyoshim): Pass instance_id to implement HandleMidiInCallback. 343 MMRESULT result = midiInOpen(
253 MMRESULT result = 344 &in_handle_, device_id_,
254 midiInOpen(&in_handle_, device_id_, 345 reinterpret_cast<DWORD_PTR>(&PortManager::HandleMidiInCallback),
255 reinterpret_cast<DWORD_PTR>(&HandleMidiInCallback), 0, 346 instance_id_, CALLBACK_FUNCTION);
256 CALLBACK_FUNCTION);
257 if (result == MMSYSERR_NOERROR) { 347 if (result == MMSYSERR_NOERROR) {
348 hdr_ = CreateMIDIHDR(kBufferLength);
349 result = midiInPrepareHeader(in_handle_, hdr_.get(), sizeof(*hdr_));
350 }
351 if (result != MMSYSERR_NOERROR)
352 in_handle_ = kInvalidInHandle;
353 if (result == MMSYSERR_NOERROR)
354 result = midiInAddBuffer(in_handle_, hdr_.get(), sizeof(*hdr_));
355 if (result == MMSYSERR_NOERROR)
356 result = midiInStart(in_handle_);
357 if (result == MMSYSERR_NOERROR) {
358 start_time_ = base::TimeTicks::Now();
359 manager_->port_manager()->RegisterInHandle(in_handle_, index_);
258 Port::Open(); 360 Port::Open();
259 } else { 361 } else {
260 in_handle_ = kInvalidInHandle; 362 if (in_handle_ != kInvalidInHandle) {
363 midiInUnprepareHeader(in_handle_, hdr_.get(), sizeof(*hdr_));
364 hdr_.reset();
365 midiInClose(in_handle_);
366 in_handle_ = kInvalidInHandle;
367 }
261 Disconnect(); 368 Disconnect();
262 } 369 }
263 } 370 }
264 371
265 private: 372 private:
373 DynamicallyInitializedMidiManagerWin* manager_;
266 HMIDIIN in_handle_; 374 HMIDIIN in_handle_;
375 ScopedMIDIHDR hdr_;
376 base::TimeTicks start_time_;
377 int instance_id_;
yhirano 2017/02/28 11:02:02 const
Takashi Toyoshima 2017/03/01 01:10:35 Done.
267 }; 378 };
268 379
269 // TODO(toyoshim): Following patches will implement actual functions. 380 // TODO(toyoshim): Following patches will implement actual functions.
270 class DynamicallyInitializedMidiManagerWin::OutPort final : public Port { 381 class DynamicallyInitializedMidiManagerWin::OutPort final : public Port {
271 public: 382 public:
272 OutPort(UINT device_id, const MIDIOUTCAPS2W& caps) 383 OutPort(UINT device_id, const MIDIOUTCAPS2W& caps)
273 : Port("output", 384 : Port("output",
274 device_id, 385 device_id,
275 caps.wMid, 386 caps.wMid,
276 caps.wPid, 387 caps.wPid,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 } else { 458 } else {
348 out_handle_ = kInvalidOutHandle; 459 out_handle_ = kInvalidOutHandle;
349 Disconnect(); 460 Disconnect();
350 } 461 }
351 } 462 }
352 463
353 const bool software_; 464 const bool software_;
354 HMIDIOUT out_handle_; 465 HMIDIOUT out_handle_;
355 }; 466 };
356 467
468 base::TimeTicks
469 DynamicallyInitializedMidiManagerWin::PortManager::CalculateInEventTime(
470 size_t index,
471 uint32_t elapsed_ms) const {
472 GetTaskLock()->AssertAcquired();
473 CHECK_GT(input_ports_.size(), index);
474 return input_ports_[index]->CalculateInEventTime(elapsed_ms);
475 }
476
477 void DynamicallyInitializedMidiManagerWin::PortManager::RegisterInHandle(
478 HMIDIIN handle,
479 size_t index) {
480 GetTaskLock()->AssertAcquired();
481 hmidiin_to_index_map_[handle] = index;
482 }
483
484 void DynamicallyInitializedMidiManagerWin::PortManager::UnregisterInHandle(
485 HMIDIIN handle) {
486 GetTaskLock()->AssertAcquired();
487 hmidiin_to_index_map_.erase(handle);
488 }
489
490 bool DynamicallyInitializedMidiManagerWin::PortManager::FindHandle(
491 HMIDIIN hmi,
492 size_t* out_index) {
493 GetTaskLock()->AssertAcquired();
494 auto found = hmidiin_to_index_map_.find(hmi);
495 if (found == hmidiin_to_index_map_.end())
496 return false;
497 *out_index = found->second;
498 return true;
499 }
500
501 void DynamicallyInitializedMidiManagerWin::PortManager::RestoreInBuffer(
502 size_t index) {
503 GetTaskLock()->AssertAcquired();
504 CHECK_GT(input_ports_.size(), index);
505 input_ports_[index]->RestoreBuffer();
506 }
507
508 void CALLBACK
509 DynamicallyInitializedMidiManagerWin::PortManager::HandleMidiInCallback(
510 HMIDIIN hmi,
511 UINT msg,
512 DWORD_PTR instance,
513 DWORD_PTR param1,
514 DWORD_PTR param2) {
515 if (msg != MIM_DATA && msg != MIM_LONGDATA)
516 return;
517 int instance_id = static_cast<int>(instance);
518 DynamicallyInitializedMidiManagerWin* manager = nullptr;
519
520 // Use |g_task_lock| so to ensure the instance can keep alive while running,
521 // and to access member variables that are used on TaskRunner.
522 base::AutoLock task_lock(*GetTaskLock());
523 {
524 base::AutoLock lock(*GetInstanceIdLock());
525 if (instance_id != g_active_instance_id)
526 return;
527 manager = g_manager_instance;
528 }
529
530 size_t index;
531 if (!manager->port_manager()->FindHandle(hmi, &index))
532 return;
533
534 DCHECK(msg == MIM_DATA || msg == MIM_LONGDATA);
535 if (msg == MIM_DATA) {
536 const uint8_t status_byte = static_cast<uint8_t>(param1 & 0xff);
537 const uint8_t first_data_byte = static_cast<uint8_t>((param1 >> 8) & 0xff);
538 const uint8_t second_data_byte =
539 static_cast<uint8_t>((param1 >> 16) & 0xff);
540 const size_t len = GetMessageLength(status_byte);
541 const uint8_t kData[] = {status_byte, first_data_byte, second_data_byte};
542 std::vector<uint8_t> data;
yhirano 2017/02/28 11:02:02 DCHECK_LE(len, arraysize(kData));
Takashi Toyoshima 2017/03/01 01:10:35 Done. I reordered lines around here a little to cl
543 data.assign(kData, kData + len);
544 manager->PostReplyTask(base::Bind(
545 &DynamicallyInitializedMidiManagerWin::ReceiveMidiData,
546 base::Unretained(manager), index, data,
547 manager->port_manager()->CalculateInEventTime(index, param2)));
548 } else {
549 DCHECK_EQ(static_cast<UINT>(MIM_LONGDATA), msg);
550 LPMIDIHDR hdr = reinterpret_cast<LPMIDIHDR>(param1);
551 if (hdr->dwBytesRecorded > 0) {
552 const uint8_t* src = reinterpret_cast<const uint8_t*>(hdr->lpData);
553 std::vector<uint8_t> data;
554 data.assign(src, src + hdr->dwBytesRecorded);
555 manager->PostReplyTask(base::Bind(
556 &DynamicallyInitializedMidiManagerWin::ReceiveMidiData,
557 base::Unretained(manager), index, data,
558 manager->port_manager()->CalculateInEventTime(index, param2)));
559 }
560 manager->PostTask(base::Bind(
561 &DynamicallyInitializedMidiManagerWin::PortManager::RestoreInBuffer,
562 base::Unretained(manager->port_manager()), index));
563 }
564 }
565
357 DynamicallyInitializedMidiManagerWin::DynamicallyInitializedMidiManagerWin( 566 DynamicallyInitializedMidiManagerWin::DynamicallyInitializedMidiManagerWin(
358 MidiService* service) 567 MidiService* service)
359 : MidiManager(service), instance_id_(IssueNextInstanceId()) { 568 : MidiManager(service),
569 instance_id_(IssueNextInstanceId()),
570 port_manager_(base::MakeUnique<PortManager>()) {
360 base::AutoLock lock(*GetInstanceIdLock()); 571 base::AutoLock lock(*GetInstanceIdLock());
361 CHECK_EQ(kInvalidInstanceId, g_active_instance_id); 572 CHECK_EQ(kInvalidInstanceId, g_active_instance_id);
362 573
363 // Obtains the task runner for the current thread that hosts this instnace. 574 // Obtains the task runner for the current thread that hosts this instnace.
364 thread_runner_ = base::ThreadTaskRunnerHandle::Get(); 575 thread_runner_ = base::ThreadTaskRunnerHandle::Get();
365 } 576 }
366 577
367 DynamicallyInitializedMidiManagerWin::~DynamicallyInitializedMidiManagerWin() { 578 DynamicallyInitializedMidiManagerWin::~DynamicallyInitializedMidiManagerWin() {
368 base::AutoLock lock(*GetInstanceIdLock()); 579 base::AutoLock lock(*GetInstanceIdLock());
369 CHECK_EQ(kInvalidInstanceId, g_active_instance_id); 580 CHECK_EQ(kInvalidInstanceId, g_active_instance_id);
370 CHECK(thread_runner_->BelongsToCurrentThread()); 581 CHECK(thread_runner_->BelongsToCurrentThread());
371 } 582 }
372 583
373 void DynamicallyInitializedMidiManagerWin::PostReplyTask(
374 const base::Closure& task) {
375 thread_runner_->PostTask(FROM_HERE, base::Bind(&RunTask, instance_id_, task));
376 }
377
378 void DynamicallyInitializedMidiManagerWin::StartInitialization() { 584 void DynamicallyInitializedMidiManagerWin::StartInitialization() {
379 { 585 {
380 base::AutoLock lock(*GetInstanceIdLock()); 586 base::AutoLock lock(*GetInstanceIdLock());
381 CHECK_EQ(kInvalidInstanceId, g_active_instance_id); 587 CHECK_EQ(kInvalidInstanceId, g_active_instance_id);
382 g_active_instance_id = instance_id_; 588 g_active_instance_id = instance_id_;
383 CHECK_EQ(nullptr, g_manager_instance); 589 CHECK_EQ(nullptr, g_manager_instance);
384 g_manager_instance = this; 590 g_manager_instance = this;
385 } 591 }
386 // Registers on the I/O thread to be notified on the I/O thread. 592 // Registers on the I/O thread to be notified on the I/O thread.
387 CHECK(thread_runner_->BelongsToCurrentThread()); 593 CHECK(thread_runner_->BelongsToCurrentThread());
(...skipping 21 matching lines...) Expand all
409 // Tasks that did not started yet will do nothing after invalidate the 615 // Tasks that did not started yet will do nothing after invalidate the
410 // instance ID above. 616 // instance ID above.
411 // Behind the lock below, we can safely access all members for finalization 617 // Behind the lock below, we can safely access all members for finalization
412 // even on the I/O thread. 618 // even on the I/O thread.
413 base::AutoLock lock(*GetTaskLock()); 619 base::AutoLock lock(*GetTaskLock());
414 620
415 // Posts tasks that finalize each device port without MidiManager instance 621 // Posts tasks that finalize each device port without MidiManager instance
416 // on TaskRunner. If another MidiManager instance is created, its 622 // on TaskRunner. If another MidiManager instance is created, its
417 // initialization runs on the same task runner after all tasks posted here 623 // initialization runs on the same task runner after all tasks posted here
418 // finish. 624 // finish.
419 for (const auto& port : input_ports_) 625 for (const auto& port : *port_manager_->inputs())
420 port->Finalize(service()->GetTaskRunner(kTaskRunner)); 626 port->Finalize(service()->GetTaskRunner(kTaskRunner));
421 for (const auto& port : output_ports_) 627 for (const auto& port : *port_manager_->outputs())
422 port->Finalize(service()->GetTaskRunner(kTaskRunner)); 628 port->Finalize(service()->GetTaskRunner(kTaskRunner));
423 } 629 }
424 630
425 void DynamicallyInitializedMidiManagerWin::DispatchSendMidiData( 631 void DynamicallyInitializedMidiManagerWin::DispatchSendMidiData(
426 MidiManagerClient* client, 632 MidiManagerClient* client,
427 uint32_t port_index, 633 uint32_t port_index,
428 const std::vector<uint8_t>& data, 634 const std::vector<uint8_t>& data,
429 double timestamp) { 635 double timestamp) {
430 // TODO(toyoshim): Following patches will implement. 636 // TODO(toyoshim): Following patches will implement.
431 } 637 }
(...skipping 10 matching lines...) Expand all
442 return; 648 return;
443 case base::SystemMonitor::DEVTYPE_UNKNOWN: { 649 case base::SystemMonitor::DEVTYPE_UNKNOWN: {
444 PostTask(base::Bind( 650 PostTask(base::Bind(
445 &DynamicallyInitializedMidiManagerWin::UpdateDeviceListOnTaskRunner, 651 &DynamicallyInitializedMidiManagerWin::UpdateDeviceListOnTaskRunner,
446 base::Unretained(this))); 652 base::Unretained(this)));
447 break; 653 break;
448 } 654 }
449 } 655 }
450 } 656 }
451 657
658 void DynamicallyInitializedMidiManagerWin::ReceiveMidiData(
659 uint32_t index,
660 const std::vector<uint8_t>& data,
661 base::TimeTicks time) {
662 MidiManager::ReceiveMidiData(index, data.data(), data.size(), time);
663 }
664
452 void DynamicallyInitializedMidiManagerWin::PostTask(const base::Closure& task) { 665 void DynamicallyInitializedMidiManagerWin::PostTask(const base::Closure& task) {
453 service() 666 service()
454 ->GetTaskRunner(kTaskRunner) 667 ->GetTaskRunner(kTaskRunner)
455 ->PostTask(FROM_HERE, base::Bind(&RunTask, instance_id_, task)); 668 ->PostTask(FROM_HERE, base::Bind(&RunTask, instance_id_, task));
456 } 669 }
457 670
671 void DynamicallyInitializedMidiManagerWin::PostReplyTask(
672 const base::Closure& task) {
673 thread_runner_->PostTask(FROM_HERE, base::Bind(&RunTask, instance_id_, task));
674 }
675
458 void DynamicallyInitializedMidiManagerWin::InitializeOnTaskRunner() { 676 void DynamicallyInitializedMidiManagerWin::InitializeOnTaskRunner() {
459 UpdateDeviceListOnTaskRunner(); 677 UpdateDeviceListOnTaskRunner();
460 PostReplyTask( 678 PostReplyTask(
461 base::Bind(&DynamicallyInitializedMidiManagerWin::CompleteInitialization, 679 base::Bind(&DynamicallyInitializedMidiManagerWin::CompleteInitialization,
462 base::Unretained(this), mojom::Result::OK)); 680 base::Unretained(this), mojom::Result::OK));
463 } 681 }
464 682
465 void DynamicallyInitializedMidiManagerWin::UpdateDeviceListOnTaskRunner() { 683 void DynamicallyInitializedMidiManagerWin::UpdateDeviceListOnTaskRunner() {
466 std::vector<std::unique_ptr<InPort>> active_input_ports = 684 std::vector<std::unique_ptr<InPort>> active_input_ports =
467 InPort::EnumerateActivePorts(); 685 InPort::EnumerateActivePorts(this, instance_id_);
468 ReflectActiveDeviceList(this, &input_ports_, &active_input_ports); 686 ReflectActiveDeviceList(this, port_manager_->inputs(), &active_input_ports);
469 687
470 std::vector<std::unique_ptr<OutPort>> active_output_ports = 688 std::vector<std::unique_ptr<OutPort>> active_output_ports =
471 OutPort::EnumerateActivePorts(); 689 OutPort::EnumerateActivePorts();
472 ReflectActiveDeviceList(this, &output_ports_, &active_output_ports); 690 ReflectActiveDeviceList(this, port_manager_->outputs(), &active_output_ports);
473 691
474 // TODO(toyoshim): This method may run before internal MIDI device lists that 692 // 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 693 // 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 694 // 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. 695 // to retry device check later if no changes are detected here.
478 } 696 }
479 697
480 template <typename T> 698 template <typename T>
481 void DynamicallyInitializedMidiManagerWin::ReflectActiveDeviceList( 699 void DynamicallyInitializedMidiManagerWin::ReflectActiveDeviceList(
482 DynamicallyInitializedMidiManagerWin* manager, 700 DynamicallyInitializedMidiManagerWin* manager,
(...skipping 23 matching lines...) Expand all
506 size_t index = known_ports->size(); 724 size_t index = known_ports->size();
507 port->set_index(index); 725 port->set_index(index);
508 known_ports->push_back(std::move(port)); 726 known_ports->push_back(std::move(port));
509 (*known_ports)[index]->Connect(); 727 (*known_ports)[index]->Connect();
510 (*known_ports)[index]->NotifyPortAdded(this); 728 (*known_ports)[index]->NotifyPortAdded(this);
511 } 729 }
512 } 730 }
513 } 731 }
514 732
515 } // namespace midi 733 } // namespace midi
OLDNEW
« no previous file with comments | « media/midi/dynamically_initialized_midi_manager_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698