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

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

Issue 2673423002: Web MIDI: add dynamic MidiManager instantiation support for Linux (Closed)
Patch Set: fix check failures 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
« no previous file with comments | « media/midi/midi_manager_alsa.h ('k') | media/midi/midi_manager_android.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/midi_manager_alsa.h" 5 #include "media/midi/midi_manager_alsa.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <poll.h> 8 #include <poll.h>
9 #include <stddef.h> 9 #include <stddef.h>
10 #include <stdlib.h> 10 #include <stdlib.h>
11 11
12 #include <algorithm> 12 #include <algorithm>
13 #include <string> 13 #include <string>
14 #include <utility> 14 #include <utility>
15 15
16 #include "base/bind.h" 16 #include "base/bind.h"
17 #include "base/json/json_string_value_serializer.h" 17 #include "base/json/json_string_value_serializer.h"
18 #include "base/lazy_instance.h"
18 #include "base/logging.h" 19 #include "base/logging.h"
19 #include "base/macros.h" 20 #include "base/macros.h"
20 #include "base/memory/ptr_util.h" 21 #include "base/memory/ptr_util.h"
21 #include "base/message_loop/message_loop.h" 22 #include "base/message_loop/message_loop.h"
22 #include "base/posix/eintr_wrapper.h" 23 #include "base/posix/eintr_wrapper.h"
23 #include "base/posix/safe_strerror.h" 24 #include "base/posix/safe_strerror.h"
24 #include "base/single_thread_task_runner.h" 25 #include "base/single_thread_task_runner.h"
25 #include "base/strings/string_number_conversions.h" 26 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/stringprintf.h" 27 #include "base/strings/stringprintf.h"
27 #include "base/time/time.h" 28 #include "base/time/time.h"
28 #include "crypto/sha2.h" 29 #include "crypto/sha2.h"
29 #include "media/midi/midi_port_info.h" 30 #include "media/midi/midi_port_info.h"
31 #include "media/midi/midi_service.h"
30 32
31 namespace midi { 33 namespace midi {
32 34
33 namespace { 35 namespace {
34 36
35 using mojom::PortState; 37 using mojom::PortState;
36 using mojom::Result; 38 using mojom::Result;
37 39
40 // TODO(toyoshim): use constexpr for following const values.
41 const int kEventTaskRunner = 0;
42 const int kSendTaskRunner = 1;
43
38 // Per-output buffer. This can be smaller, but then large sysex messages 44 // Per-output buffer. This can be smaller, but then large sysex messages
39 // will be (harmlessly) split across multiple seq events. This should 45 // will be (harmlessly) split across multiple seq events. This should
40 // not have any real practical effect, except perhaps to slightly reorder 46 // not have any real practical effect, except perhaps to slightly reorder
41 // realtime messages with respect to sysex. 47 // realtime messages with respect to sysex.
42 const size_t kSendBufferSize = 256; 48 const size_t kSendBufferSize = 256;
43 49
44 // Minimum client id for which we will have ALSA card devices for. When we 50 // Minimum client id for which we will have ALSA card devices for. When we
45 // are searching for card devices (used to get the path, id, and manufacturer), 51 // are searching for card devices (used to get the path, id, and manufacturer),
46 // we don't want to get confused by kernel clients that do not have a card. 52 // we don't want to get confused by kernel clients that do not have a card.
47 // See seq_clientmgr.c in the ALSA code for this. 53 // See seq_clientmgr.c in the ALSA code for this.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 const unsigned int kRequiredOutputPortCaps = 89 const unsigned int kRequiredOutputPortCaps =
84 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; 90 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE;
85 91
86 const unsigned int kCreateOutputPortCaps = 92 const unsigned int kCreateOutputPortCaps =
87 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_NO_EXPORT; 93 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_NO_EXPORT;
88 const unsigned int kCreateInputPortCaps = 94 const unsigned int kCreateInputPortCaps =
89 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_NO_EXPORT; 95 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_NO_EXPORT;
90 const unsigned int kCreatePortType = 96 const unsigned int kCreatePortType =
91 SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION; 97 SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION;
92 98
99 // Global variables to identify MidiManagerAlsa instance.
100 const int kInvalidInstanceId = -1;
101 int g_active_instance_id = kInvalidInstanceId;
102 int g_next_instance_id = 0;
103 base::LazyInstance<base::Lock> g_instance_id_lock = LAZY_INSTANCE_INITIALIZER;
104
105 // Prevent current instance from quiting Finalize() while tasks run on external
106 // TaskRunners.
107 base::LazyInstance<base::Lock> g_event_task_lock = LAZY_INSTANCE_INITIALIZER;
108 base::LazyInstance<base::Lock> g_send_task_lock = LAZY_INSTANCE_INITIALIZER;
109
93 int AddrToInt(int client, int port) { 110 int AddrToInt(int client, int port) {
94 return (client << 8) | port; 111 return (client << 8) | port;
95 } 112 }
96 113
97 // Returns true if this client has an ALSA card associated with it. 114 // Returns true if this client has an ALSA card associated with it.
98 bool IsCardClient(snd_seq_client_type_t type, int client_id) { 115 bool IsCardClient(snd_seq_client_type_t type, int client_id) {
99 return (type == SND_SEQ_KERNEL_CLIENT) && 116 return (type == SND_SEQ_KERNEL_CLIENT) &&
100 (client_id >= kMinimumClientIdForCards); 117 (client_id >= kMinimumClientIdForCards);
101 } 118 }
102 119
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 163
147 void SetStringIfNonEmpty(base::DictionaryValue* value, 164 void SetStringIfNonEmpty(base::DictionaryValue* value,
148 const std::string& path, 165 const std::string& path,
149 const std::string& in_value) { 166 const std::string& in_value) {
150 if (!in_value.empty()) 167 if (!in_value.empty())
151 value->SetString(path, in_value); 168 value->SetString(path, in_value);
152 } 169 }
153 170
154 } // namespace 171 } // namespace
155 172
156 MidiManagerAlsa::MidiManagerAlsa() 173 MidiManagerAlsa::MidiManagerAlsa(MidiService* service) : MidiManager(service) {}
157 : event_thread_("MidiEventThread"), send_thread_("MidiSendThread") {}
158 174
159 MidiManagerAlsa::~MidiManagerAlsa() { 175 MidiManagerAlsa::~MidiManagerAlsa() {
160 // Take lock to ensure that the members initialized on the IO thread 176 // Take lock to ensure that the members initialized on the IO thread
161 // are not destructed here. 177 // are not destructed here.
162 base::AutoLock lock(lazy_init_member_lock_); 178 base::AutoLock lock(lazy_init_member_lock_);
163 179
164 // Extra CHECK to verify all members are already reset. 180 // Extra CHECK to verify all members are already reset.
165 CHECK(!initialization_thread_checker_); 181 CHECK(!initialization_thread_checker_);
166 CHECK(!in_client_); 182 CHECK(!in_client_);
167 CHECK(!out_client_); 183 CHECK(!out_client_);
168 CHECK(!decoder_); 184 CHECK(!decoder_);
169 CHECK(!udev_); 185 CHECK(!udev_);
170 CHECK(!udev_monitor_); 186 CHECK(!udev_monitor_);
171 187
172 CHECK(!send_thread_.IsRunning()); 188 base::AutoLock instance_id_lock(g_instance_id_lock.Get());
173 CHECK(!event_thread_.IsRunning()); 189 CHECK_EQ(kInvalidInstanceId, g_active_instance_id);
174 } 190 }
175 191
176 void MidiManagerAlsa::StartInitialization() { 192 void MidiManagerAlsa::StartInitialization() {
193 {
Takashi Toyoshima 2017/02/08 12:56:13 Since Finalize() is called only when StartInitiali
194 base::AutoLock lock(g_instance_id_lock.Get());
195 CHECK_EQ(kInvalidInstanceId, g_active_instance_id);
196 instance_id_ = g_next_instance_id++;
197 g_active_instance_id = instance_id_;
198 }
199
177 base::AutoLock lock(lazy_init_member_lock_); 200 base::AutoLock lock(lazy_init_member_lock_);
178 201
179 initialization_thread_checker_.reset(new base::ThreadChecker()); 202 initialization_thread_checker_.reset(new base::ThreadChecker());
180 203
181 // Create client handles. 204 // Create client handles.
182 snd_seq_t* tmp_seq = nullptr; 205 snd_seq_t* tmp_seq = nullptr;
183 int err = 206 int err =
184 snd_seq_open(&tmp_seq, kAlsaHw, SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK); 207 snd_seq_open(&tmp_seq, kAlsaHw, SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK);
185 if (err != 0) { 208 if (err != 0) {
186 VLOG(1) << "snd_seq_open fails: " << snd_strerror(err); 209 VLOG(1) << "snd_seq_open fails: " << snd_strerror(err);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 // TODO(agoode): Check the return value for failure. 304 // TODO(agoode): Check the return value for failure.
282 EnumerateAlsaPorts(); 305 EnumerateAlsaPorts();
283 306
284 // Generate hotplug events for existing udev devices. This must be done 307 // Generate hotplug events for existing udev devices. This must be done
285 // after udev_monitor_enable_receiving() is called. See the algorithm 308 // after udev_monitor_enable_receiving() is called. See the algorithm
286 // at http://www.signal11.us/oss/udev/. 309 // at http://www.signal11.us/oss/udev/.
287 EnumerateUdevCards(); 310 EnumerateUdevCards();
288 311
289 // Start processing events. Don't do this before enumeration of both 312 // Start processing events. Don't do this before enumeration of both
290 // ALSA and udev. 313 // ALSA and udev.
291 event_thread_.Start(); 314 service()
292 event_thread_.task_runner()->PostTask( 315 ->GetTaskRunner(kEventTaskRunner)
293 FROM_HERE, 316 ->PostTask(FROM_HERE, base::Bind(&MidiManagerAlsa::EventLoop,
294 base::Bind(&MidiManagerAlsa::ScheduleEventLoop, base::Unretained(this))); 317 base::Unretained(this), instance_id_));
295 send_thread_.Start();
296 318
297 CompleteInitialization(Result::OK); 319 CompleteInitialization(Result::OK);
298 } 320 }
299 321
300 void MidiManagerAlsa::Finalize() { 322 void MidiManagerAlsa::Finalize() {
301 base::AutoLock lock(lazy_init_member_lock_); 323 base::AutoLock lock(lazy_init_member_lock_);
302 DCHECK(initialization_thread_checker_->CalledOnValidThread()); 324 DCHECK(initialization_thread_checker_->CalledOnValidThread());
303 325
304 // Tell the event thread it will soon be time to shut down. This gives 326 // Tell tasks running on TaskRunners it will soon be time to shut down. This
305 // us assurance the thread will stop in case the SND_SEQ_EVENT_CLIENT_EXIT 327 // gives us assurance a task running on kEventTaskRunner will stop in case the
306 // message is lost. 328 // SND_SEQ_EVENT_CLIENT_EXIT message is lost.
307 { 329 {
308 base::AutoLock lock(shutdown_lock_); 330 base::AutoLock lock(g_instance_id_lock.Get());
309 event_thread_shutdown_ = true; 331 CHECK_EQ(instance_id_, g_active_instance_id);
332 g_active_instance_id = kInvalidInstanceId;
310 } 333 }
311 334
312 // Stop the send thread. 335 // Ensure that no tasks run on kSendTaskRunner.
313 send_thread_.Stop(); 336 base::AutoLock send_runner_lock(g_send_task_lock.Get());
314 337
315 // Close the out client. This will trigger the event thread to stop, 338 // Close the out client. This will trigger the event thread to stop,
316 // because of SND_SEQ_EVENT_CLIENT_EXIT. 339 // because of SND_SEQ_EVENT_CLIENT_EXIT.
317 out_client_.reset(); 340 out_client_.reset();
318 341
319 // Wait for the event thread to stop. 342 // Ensure that no tasks run on kEventTaskRunner.
320 event_thread_.Stop(); 343 base::AutoLock event_runner_lock(g_event_task_lock.Get());
321 344
322 // Destruct the other stuff we initialized in StartInitialization(). 345 // Destruct the other stuff we initialized in StartInitialization().
323 udev_monitor_.reset(); 346 udev_monitor_.reset();
324 udev_.reset(); 347 udev_.reset();
325 decoder_.reset(); 348 decoder_.reset();
326 in_client_.reset(); 349 in_client_.reset();
327 initialization_thread_checker_.reset(); 350 initialization_thread_checker_.reset();
328 } 351 }
329 352
330 void MidiManagerAlsa::DispatchSendMidiData(MidiManagerClient* client, 353 void MidiManagerAlsa::DispatchSendMidiData(MidiManagerClient* client,
331 uint32_t port_index, 354 uint32_t port_index,
332 const std::vector<uint8_t>& data, 355 const std::vector<uint8_t>& data,
333 double timestamp) { 356 double timestamp) {
334 base::TimeDelta delay; 357 base::TimeDelta delay;
335 if (timestamp != 0.0) { 358 if (timestamp != 0.0) {
336 base::TimeTicks time_to_send = 359 base::TimeTicks time_to_send =
337 base::TimeTicks() + base::TimeDelta::FromMicroseconds( 360 base::TimeTicks() + base::TimeDelta::FromMicroseconds(
338 timestamp * base::Time::kMicrosecondsPerSecond); 361 timestamp * base::Time::kMicrosecondsPerSecond);
339 delay = std::max(time_to_send - base::TimeTicks::Now(), base::TimeDelta()); 362 delay = std::max(time_to_send - base::TimeTicks::Now(), base::TimeDelta());
340 } 363 }
341 364
342 send_thread_.task_runner()->PostDelayedTask( 365 service()
343 FROM_HERE, base::Bind(&MidiManagerAlsa::SendMidiData, 366 ->GetTaskRunner(kSendTaskRunner)
344 base::Unretained(this), port_index, data), 367 ->PostDelayedTask(
345 delay); 368 FROM_HERE,
346 369 base::Bind(&MidiManagerAlsa::SendMidiData, base::Unretained(this),
347 // Acknowledge send. 370 instance_id_, client, port_index, data),
348 send_thread_.task_runner()->PostTask( 371 delay);
349 FROM_HERE, base::Bind(&MidiManagerAlsa::AccumulateMidiBytesSent,
350 base::Unretained(this), client, data.size()));
351 } 372 }
352 373
353 MidiManagerAlsa::MidiPort::Id::Id() = default; 374 MidiManagerAlsa::MidiPort::Id::Id() = default;
354 375
355 MidiManagerAlsa::MidiPort::Id::Id(const std::string& bus, 376 MidiManagerAlsa::MidiPort::Id::Id(const std::string& bus,
356 const std::string& vendor_id, 377 const std::string& vendor_id,
357 const std::string& model_id, 378 const std::string& model_id,
358 const std::string& usb_interface_num, 379 const std::string& usb_interface_num,
359 const std::string& serial) 380 const std::string& serial)
360 : bus_(bus), 381 : bus_(bus),
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 if (at_index && at_index != std::string::npos) { 878 if (at_index && at_index != std::string::npos) {
858 size_t name_index = alsa_longname.rfind(alsa_name, at_index - 1); 879 size_t name_index = alsa_longname.rfind(alsa_name, at_index - 1);
859 if (name_index && name_index != std::string::npos) 880 if (name_index && name_index != std::string::npos)
860 return alsa_longname.substr(0, name_index - 1); 881 return alsa_longname.substr(0, name_index - 1);
861 } 882 }
862 883
863 // Failure. 884 // Failure.
864 return ""; 885 return "";
865 } 886 }
866 887
867 void MidiManagerAlsa::SendMidiData(uint32_t port_index, 888 void MidiManagerAlsa::SendMidiData(int instance_id,
889 MidiManagerClient* client,
890 uint32_t port_index,
868 const std::vector<uint8_t>& data) { 891 const std::vector<uint8_t>& data) {
869 DCHECK(send_thread_.task_runner()->BelongsToCurrentThread()); 892 DCHECK(service()->GetTaskRunner(kSendTaskRunner)->BelongsToCurrentThread());
893
894 // Obtain the lock so that the instance could not be destructed while this
895 // method is running on the kSendTaskRunner.
896 base::AutoLock lock(g_send_task_lock.Get());
897 {
898 // Check if Finalize() already runs. After this check, we can access |this|
899 // safely on the kEventTaskRunner.
900 base::AutoLock instance_id_lock(g_instance_id_lock.Get());
901 if (instance_id != g_active_instance_id)
902 return;
903 }
870 904
871 snd_midi_event_t* encoder; 905 snd_midi_event_t* encoder;
872 snd_midi_event_new(kSendBufferSize, &encoder); 906 snd_midi_event_new(kSendBufferSize, &encoder);
873 for (const auto datum : data) { 907 for (const auto datum : data) {
874 snd_seq_event_t event; 908 snd_seq_event_t event;
875 int result = snd_midi_event_encode_byte(encoder, datum, &event); 909 int result = snd_midi_event_encode_byte(encoder, datum, &event);
876 if (result == 1) { 910 if (result == 1) {
877 // Full event, send it. 911 // Full event, send it.
878 base::AutoLock lock(out_ports_lock_); 912 base::AutoLock lock(out_ports_lock_);
879 auto it = out_ports_.find(port_index); 913 auto it = out_ports_.find(port_index);
880 if (it != out_ports_.end()) { 914 if (it != out_ports_.end()) {
881 snd_seq_ev_set_source(&event, it->second); 915 snd_seq_ev_set_source(&event, it->second);
882 snd_seq_ev_set_subs(&event); 916 snd_seq_ev_set_subs(&event);
883 snd_seq_ev_set_direct(&event); 917 snd_seq_ev_set_direct(&event);
884 snd_seq_event_output_direct(out_client_.get(), &event); 918 snd_seq_event_output_direct(out_client_.get(), &event);
885 } 919 }
886 } 920 }
887 } 921 }
888 snd_midi_event_free(encoder); 922 snd_midi_event_free(encoder);
923
924 // Acknowledge send.
925 AccumulateMidiBytesSent(client, data.size());
889 } 926 }
890 927
891 void MidiManagerAlsa::ScheduleEventLoop() { 928 void MidiManagerAlsa::EventLoop(int instance_id) {
892 event_thread_.task_runner()->PostTask( 929 // Obtain the lock so that the instance could not be destructed while this
893 FROM_HERE, 930 // method is running on the kEventTaskRunner.
894 base::Bind(&MidiManagerAlsa::EventLoop, base::Unretained(this))); 931 base::AutoLock lock(g_event_task_lock.Get());
895 } 932 {
933 // Check if Finalize() already runs. After this check, we can access |this|
934 // safely on the kEventTaskRunner.
935 base::AutoLock instance_id_lock(g_instance_id_lock.Get());
936 if (instance_id != g_active_instance_id)
937 return;
938 }
896 939
897 void MidiManagerAlsa::EventLoop() {
898 bool loop_again = true; 940 bool loop_again = true;
899 941
900 struct pollfd pfd[2]; 942 struct pollfd pfd[2];
901 snd_seq_poll_descriptors(in_client_.get(), &pfd[0], 1, POLLIN); 943 snd_seq_poll_descriptors(in_client_.get(), &pfd[0], 1, POLLIN);
902 pfd[1].fd = device::udev_monitor_get_fd(udev_monitor_.get()); 944 pfd[1].fd = device::udev_monitor_get_fd(udev_monitor_.get());
903 pfd[1].events = POLLIN; 945 pfd[1].events = POLLIN;
904 946
905 int err = HANDLE_EINTR(poll(pfd, arraysize(pfd), -1)); 947 int err = HANDLE_EINTR(poll(pfd, arraysize(pfd), -1));
906 if (err < 0) { 948 if (err < 0) {
907 VLOG(1) << "poll fails: " << base::safe_strerror(errno); 949 VLOG(1) << "poll fails: " << base::safe_strerror(errno);
908 loop_again = false; 950 loop_again = false;
909 } else { 951 } else {
910 if (pfd[0].revents & POLLIN) { 952 if (pfd[0].revents & POLLIN) {
911 // Read available incoming MIDI data. 953 // Read available incoming MIDI data.
912 int remaining; 954 int remaining;
913 double timestamp = 955 double timestamp =
914 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(); 956 (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
915 do { 957 do {
916 snd_seq_event_t* event; 958 snd_seq_event_t* event;
917 err = snd_seq_event_input(in_client_.get(), &event); 959 err = snd_seq_event_input(in_client_.get(), &event);
918 remaining = snd_seq_event_input_pending(in_client_.get(), 0); 960 remaining = snd_seq_event_input_pending(in_client_.get(), 0);
919 961
920 if (err == -ENOSPC) { 962 if (err == -ENOSPC) {
921 // Handle out of space error. 963 // Handle out of space error.
922 VLOG(1) << "snd_seq_event_input detected buffer overrun"; 964 VLOG(1) << "snd_seq_event_input detected buffer overrun";
923 // We've lost events: check another way to see if we need to shut 965 // We've lost events: check another way to see if we need to shut
924 // down. 966 // down.
925 base::AutoLock lock(shutdown_lock_);
926 if (event_thread_shutdown_)
927 loop_again = false;
928 } else if (err == -EAGAIN) { 967 } else if (err == -EAGAIN) {
929 // We've read all the data. 968 // We've read all the data.
930 } else if (err < 0) { 969 } else if (err < 0) {
931 // Handle other errors. 970 // Handle other errors.
932 VLOG(1) << "snd_seq_event_input fails: " << snd_strerror(err); 971 VLOG(1) << "snd_seq_event_input fails: " << snd_strerror(err);
933 // TODO(agoode): Use RecordAction() or similar to log this. 972 // TODO(agoode): Use RecordAction() or similar to log this.
934 loop_again = false; 973 loop_again = false;
935 } else if (event->source.client == SND_SEQ_CLIENT_SYSTEM && 974 } else if (event->source.client == SND_SEQ_CLIENT_SYSTEM &&
936 event->source.port == SND_SEQ_PORT_SYSTEM_ANNOUNCE) { 975 event->source.port == SND_SEQ_PORT_SYSTEM_ANNOUNCE) {
937 // Handle announce events. 976 // Handle announce events.
(...skipping 28 matching lines...) Expand all
966 device::ScopedUdevDevicePtr dev( 1005 device::ScopedUdevDevicePtr dev(
967 device::udev_monitor_receive_device(udev_monitor_.get())); 1006 device::udev_monitor_receive_device(udev_monitor_.get()));
968 if (dev.get()) 1007 if (dev.get())
969 ProcessUdevEvent(dev.get()); 1008 ProcessUdevEvent(dev.get());
970 else 1009 else
971 VLOG(1) << "udev_monitor_receive_device fails"; 1010 VLOG(1) << "udev_monitor_receive_device fails";
972 } 1011 }
973 } 1012 }
974 1013
975 // Do again. 1014 // Do again.
976 if (loop_again) 1015 if (loop_again) {
977 ScheduleEventLoop(); 1016 service()
1017 ->GetTaskRunner(kEventTaskRunner)
1018 ->PostTask(FROM_HERE, base::Bind(&MidiManagerAlsa::EventLoop,
1019 base::Unretained(this), instance_id));
1020 }
978 } 1021 }
979 1022
980 void MidiManagerAlsa::ProcessSingleEvent(snd_seq_event_t* event, 1023 void MidiManagerAlsa::ProcessSingleEvent(snd_seq_event_t* event,
981 double timestamp) { 1024 double timestamp) {
982 auto source_it = 1025 auto source_it =
983 source_map_.find(AddrToInt(event->source.client, event->source.port)); 1026 source_map_.find(AddrToInt(event->source.client, event->source.port));
984 if (source_it != source_map_.end()) { 1027 if (source_it != source_map_.end()) {
985 uint32_t source = source_it->second; 1028 uint32_t source = source_it->second;
986 if (event->type == SND_SEQ_EVENT_SYSEX) { 1029 if (event->type == SND_SEQ_EVENT_SYSEX) {
987 // Special! Variable-length sysex. 1030 // Special! Variable-length sysex.
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
1394 if (err != 0) { 1437 if (err != 0) {
1395 VLOG(1) << "snd_seq_subscribe_port fails: " << snd_strerror(err); 1438 VLOG(1) << "snd_seq_subscribe_port fails: " << snd_strerror(err);
1396 return false; 1439 return false;
1397 } 1440 }
1398 1441
1399 // Update our map. 1442 // Update our map.
1400 source_map_[AddrToInt(client_id, port_id)] = port_index; 1443 source_map_[AddrToInt(client_id, port_id)] = port_index;
1401 return true; 1444 return true;
1402 } 1445 }
1403 1446
1404 MidiManager* MidiManager::Create() { 1447 MidiManager* MidiManager::Create(MidiService* service) {
1405 return new MidiManagerAlsa(); 1448 return new MidiManagerAlsa(service);
1406 } 1449 }
1407 1450
1408 } // namespace midi 1451 } // namespace midi
OLDNEW
« no previous file with comments | « media/midi/midi_manager_alsa.h ('k') | media/midi/midi_manager_android.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698