OLD | NEW |
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> |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "base/message_loop/message_loop.h" | 21 #include "base/message_loop/message_loop.h" |
22 #include "base/posix/eintr_wrapper.h" | 22 #include "base/posix/eintr_wrapper.h" |
23 #include "base/posix/safe_strerror.h" | 23 #include "base/posix/safe_strerror.h" |
24 #include "base/single_thread_task_runner.h" | 24 #include "base/single_thread_task_runner.h" |
25 #include "base/strings/string_number_conversions.h" | 25 #include "base/strings/string_number_conversions.h" |
26 #include "base/strings/stringprintf.h" | 26 #include "base/strings/stringprintf.h" |
27 #include "base/time/time.h" | 27 #include "base/time/time.h" |
28 #include "crypto/sha2.h" | 28 #include "crypto/sha2.h" |
29 #include "media/midi/midi_port_info.h" | 29 #include "media/midi/midi_port_info.h" |
30 #include "media/midi/midi_service.h" | 30 #include "media/midi/midi_service.h" |
| 31 #include "media/midi/task_service.h" |
31 | 32 |
32 namespace midi { | 33 namespace midi { |
33 | 34 |
34 namespace { | 35 namespace { |
35 | 36 |
36 using mojom::PortState; | 37 using mojom::PortState; |
37 using mojom::Result; | 38 using mojom::Result; |
38 | 39 |
39 // TODO(toyoshim): use constexpr for following const values. | 40 enum { |
40 const int kEventTaskRunner = 0; | 41 kDefaultRunnerNotUsedOnAlsa = TaskService::kDefaultRunnerId, |
41 const int kSendTaskRunner = 1; | 42 kEventTaskRunner, |
| 43 kSendTaskRunner |
| 44 }; |
42 | 45 |
43 // Per-output buffer. This can be smaller, but then large sysex messages | 46 // Per-output buffer. This can be smaller, but then large sysex messages |
44 // will be (harmlessly) split across multiple seq events. This should | 47 // will be (harmlessly) split across multiple seq events. This should |
45 // not have any real practical effect, except perhaps to slightly reorder | 48 // not have any real practical effect, except perhaps to slightly reorder |
46 // realtime messages with respect to sysex. | 49 // realtime messages with respect to sysex. |
47 const size_t kSendBufferSize = 256; | 50 constexpr size_t kSendBufferSize = 256; |
48 | 51 |
49 // Minimum client id for which we will have ALSA card devices for. When we | 52 // Minimum client id for which we will have ALSA card devices for. When we |
50 // are searching for card devices (used to get the path, id, and manufacturer), | 53 // are searching for card devices (used to get the path, id, and manufacturer), |
51 // we don't want to get confused by kernel clients that do not have a card. | 54 // we don't want to get confused by kernel clients that do not have a card. |
52 // See seq_clientmgr.c in the ALSA code for this. | 55 // See seq_clientmgr.c in the ALSA code for this. |
53 // TODO(agoode): Add proper client -> card export from the kernel to avoid | 56 // TODO(agoode): Add proper client -> card export from the kernel to avoid |
54 // hardcoding. | 57 // hardcoding. |
55 const int kMinimumClientIdForCards = 16; | 58 constexpr int kMinimumClientIdForCards = 16; |
56 | 59 |
57 // ALSA constants. | 60 // ALSA constants. |
58 const char kAlsaHw[] = "hw"; | 61 const char kAlsaHw[] = "hw"; |
59 | 62 |
60 // udev constants. | 63 // udev constants. |
61 const char kUdev[] = "udev"; | 64 const char kUdev[] = "udev"; |
62 const char kUdevSubsystemSound[] = "sound"; | 65 const char kUdevSubsystemSound[] = "sound"; |
63 const char kUdevPropertySoundInitialized[] = "SOUND_INITIALIZED"; | 66 const char kUdevPropertySoundInitialized[] = "SOUND_INITIALIZED"; |
64 const char kUdevActionChange[] = "change"; | 67 const char kUdevActionChange[] = "change"; |
65 const char kUdevActionRemove[] = "remove"; | 68 const char kUdevActionRemove[] = "remove"; |
(...skipping 10 matching lines...) Expand all Loading... |
76 | 79 |
77 const char kSysattrVendorName[] = "vendor_name"; | 80 const char kSysattrVendorName[] = "vendor_name"; |
78 const char kSysattrVendor[] = "vendor"; | 81 const char kSysattrVendor[] = "vendor"; |
79 const char kSysattrModel[] = "model"; | 82 const char kSysattrModel[] = "model"; |
80 const char kSysattrGuid[] = "guid"; | 83 const char kSysattrGuid[] = "guid"; |
81 | 84 |
82 const char kCardSyspath[] = "/card"; | 85 const char kCardSyspath[] = "/card"; |
83 | 86 |
84 // Constants for the capabilities we search for in inputs and outputs. | 87 // Constants for the capabilities we search for in inputs and outputs. |
85 // See http://www.alsa-project.org/alsa-doc/alsa-lib/seq.html. | 88 // See http://www.alsa-project.org/alsa-doc/alsa-lib/seq.html. |
86 const unsigned int kRequiredInputPortCaps = | 89 constexpr unsigned int kRequiredInputPortCaps = |
87 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; | 90 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; |
88 const unsigned int kRequiredOutputPortCaps = | 91 constexpr unsigned int kRequiredOutputPortCaps = |
89 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; | 92 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; |
90 | 93 |
91 const unsigned int kCreateOutputPortCaps = | 94 constexpr unsigned int kCreateOutputPortCaps = |
92 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_NO_EXPORT; | 95 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_NO_EXPORT; |
93 const unsigned int kCreateInputPortCaps = | 96 constexpr unsigned int kCreateInputPortCaps = |
94 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_NO_EXPORT; | 97 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_NO_EXPORT; |
95 const unsigned int kCreatePortType = | 98 constexpr unsigned int kCreatePortType = |
96 SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION; | 99 SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION; |
97 | 100 |
98 // Global variables to identify MidiManagerAlsa instance. | |
99 const int kInvalidInstanceId = -1; | |
100 int g_active_instance_id = kInvalidInstanceId; | |
101 int g_next_instance_id = 0; | |
102 | |
103 struct MidiManagerLockHelper { | |
104 base::Lock instance_id_lock; | |
105 | |
106 // Prevent current instance from quiting Finalize() while tasks run on | |
107 // external TaskRunners. | |
108 base::Lock event_task_lock; | |
109 base::Lock send_task_lock; | |
110 }; | |
111 | |
112 MidiManagerLockHelper* GetLockHelper() { | |
113 static MidiManagerLockHelper* lock_helper = new MidiManagerLockHelper(); | |
114 return lock_helper; | |
115 } | |
116 | |
117 int AddrToInt(int client, int port) { | 101 int AddrToInt(int client, int port) { |
118 return (client << 8) | port; | 102 return (client << 8) | port; |
119 } | 103 } |
120 | 104 |
121 // Returns true if this client has an ALSA card associated with it. | 105 // Returns true if this client has an ALSA card associated with it. |
122 bool IsCardClient(snd_seq_client_type_t type, int client_id) { | 106 bool IsCardClient(snd_seq_client_type_t type, int client_id) { |
123 return (type == SND_SEQ_KERNEL_CLIENT) && | 107 return (type == SND_SEQ_KERNEL_CLIENT) && |
124 (client_id >= kMinimumClientIdForCards); | 108 (client_id >= kMinimumClientIdForCards); |
125 } | 109 } |
126 | 110 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 const std::string& in_value) { | 157 const std::string& in_value) { |
174 if (!in_value.empty()) | 158 if (!in_value.empty()) |
175 value->SetString(path, in_value); | 159 value->SetString(path, in_value); |
176 } | 160 } |
177 | 161 |
178 } // namespace | 162 } // namespace |
179 | 163 |
180 MidiManagerAlsa::MidiManagerAlsa(MidiService* service) : MidiManager(service) {} | 164 MidiManagerAlsa::MidiManagerAlsa(MidiService* service) : MidiManager(service) {} |
181 | 165 |
182 MidiManagerAlsa::~MidiManagerAlsa() { | 166 MidiManagerAlsa::~MidiManagerAlsa() { |
183 // Take lock to ensure that the members initialized on the IO thread | |
184 // are not destructed here. | |
185 base::AutoLock lock(lazy_init_member_lock_); | |
186 | |
187 // Extra CHECK to verify all members are already reset. | 167 // Extra CHECK to verify all members are already reset. |
188 CHECK(!initialization_thread_checker_); | |
189 CHECK(!in_client_); | 168 CHECK(!in_client_); |
190 CHECK(!out_client_); | 169 CHECK(!out_client_); |
191 CHECK(!decoder_); | 170 CHECK(!decoder_); |
192 CHECK(!udev_); | 171 CHECK(!udev_); |
193 CHECK(!udev_monitor_); | 172 CHECK(!udev_monitor_); |
194 | |
195 base::AutoLock instance_id_lock(GetLockHelper()->instance_id_lock); | |
196 CHECK_EQ(kInvalidInstanceId, g_active_instance_id); | |
197 } | 173 } |
198 | 174 |
199 void MidiManagerAlsa::StartInitialization() { | 175 void MidiManagerAlsa::StartInitialization() { |
200 { | 176 if (!service()->task_service()->BindInstance()) { |
201 base::AutoLock lock(GetLockHelper()->instance_id_lock); | 177 NOTREACHED(); |
202 CHECK_EQ(kInvalidInstanceId, g_active_instance_id); | 178 return CompleteInitialization(Result::INITIALIZATION_ERROR); |
203 instance_id_ = g_next_instance_id++; | |
204 g_active_instance_id = instance_id_; | |
205 } | 179 } |
206 | 180 |
207 base::AutoLock lock(lazy_init_member_lock_); | |
208 | |
209 initialization_thread_checker_.reset(new base::ThreadChecker()); | |
210 | |
211 // Create client handles. | 181 // Create client handles. |
212 snd_seq_t* tmp_seq = nullptr; | 182 snd_seq_t* tmp_seq = nullptr; |
213 int err = | 183 int err = |
214 snd_seq_open(&tmp_seq, kAlsaHw, SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK); | 184 snd_seq_open(&tmp_seq, kAlsaHw, SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK); |
215 if (err != 0) { | 185 if (err != 0) { |
216 VLOG(1) << "snd_seq_open fails: " << snd_strerror(err); | 186 VLOG(1) << "snd_seq_open fails: " << snd_strerror(err); |
217 return CompleteInitialization(Result::INITIALIZATION_ERROR); | 187 return CompleteInitialization(Result::INITIALIZATION_ERROR); |
218 } | 188 } |
219 ScopedSndSeqPtr in_client(tmp_seq); | 189 ScopedSndSeqPtr in_client(tmp_seq); |
220 tmp_seq = nullptr; | 190 tmp_seq = nullptr; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 // TODO(agoode): Check the return value for failure. | 281 // TODO(agoode): Check the return value for failure. |
312 EnumerateAlsaPorts(); | 282 EnumerateAlsaPorts(); |
313 | 283 |
314 // Generate hotplug events for existing udev devices. This must be done | 284 // Generate hotplug events for existing udev devices. This must be done |
315 // after udev_monitor_enable_receiving() is called. See the algorithm | 285 // after udev_monitor_enable_receiving() is called. See the algorithm |
316 // at http://www.signal11.us/oss/udev/. | 286 // at http://www.signal11.us/oss/udev/. |
317 EnumerateUdevCards(); | 287 EnumerateUdevCards(); |
318 | 288 |
319 // Start processing events. Don't do this before enumeration of both | 289 // Start processing events. Don't do this before enumeration of both |
320 // ALSA and udev. | 290 // ALSA and udev. |
321 service() | 291 service()->task_service()->PostBoundTask( |
322 ->GetTaskRunner(kEventTaskRunner) | 292 kEventTaskRunner, |
323 ->PostTask(FROM_HERE, base::Bind(&MidiManagerAlsa::EventLoop, | 293 base::BindOnce(&MidiManagerAlsa::EventLoop, base::Unretained(this))); |
324 base::Unretained(this), instance_id_)); | |
325 | 294 |
326 CompleteInitialization(Result::OK); | 295 CompleteInitialization(Result::OK); |
327 } | 296 } |
328 | 297 |
329 void MidiManagerAlsa::Finalize() { | 298 void MidiManagerAlsa::Finalize() { |
330 base::AutoLock lock(lazy_init_member_lock_); | |
331 DCHECK(initialization_thread_checker_->CalledOnValidThread()); | |
332 | |
333 // Tell tasks running on TaskRunners it will soon be time to shut down. This | |
334 // gives us assurance a task running on kEventTaskRunner will stop in case the | |
335 // SND_SEQ_EVENT_CLIENT_EXIT message is lost. | |
336 { | |
337 base::AutoLock lock(GetLockHelper()->instance_id_lock); | |
338 CHECK_EQ(instance_id_, g_active_instance_id); | |
339 g_active_instance_id = kInvalidInstanceId; | |
340 } | |
341 | |
342 // Ensure that no tasks run on kSendTaskRunner. | |
343 base::AutoLock send_runner_lock(GetLockHelper()->send_task_lock); | |
344 | |
345 // Close the out client. This will trigger the event thread to stop, | 299 // Close the out client. This will trigger the event thread to stop, |
346 // because of SND_SEQ_EVENT_CLIENT_EXIT. | 300 // because of SND_SEQ_EVENT_CLIENT_EXIT. |
347 out_client_.reset(); | 301 out_client_.reset(); |
348 | 302 |
349 // Ensure that no tasks run on kEventTaskRunner. | 303 // Ensure that no task is running any more. |
350 base::AutoLock event_runner_lock(GetLockHelper()->event_task_lock); | 304 bool result = service()->task_service()->UnbindInstance(); |
| 305 CHECK(result); |
351 | 306 |
352 // Destruct the other stuff we initialized in StartInitialization(). | 307 // Destruct the other stuff we initialized in StartInitialization(). |
353 udev_monitor_.reset(); | 308 udev_monitor_.reset(); |
354 udev_.reset(); | 309 udev_.reset(); |
355 decoder_.reset(); | 310 decoder_.reset(); |
356 in_client_.reset(); | 311 in_client_.reset(); |
357 initialization_thread_checker_.reset(); | |
358 } | 312 } |
359 | 313 |
360 void MidiManagerAlsa::DispatchSendMidiData(MidiManagerClient* client, | 314 void MidiManagerAlsa::DispatchSendMidiData(MidiManagerClient* client, |
361 uint32_t port_index, | 315 uint32_t port_index, |
362 const std::vector<uint8_t>& data, | 316 const std::vector<uint8_t>& data, |
363 double timestamp) { | 317 double timestamp) { |
364 base::TimeDelta delay; | 318 base::TimeDelta delay; |
365 if (timestamp != 0.0) { | 319 if (timestamp != 0.0) { |
366 base::TimeTicks time_to_send = | 320 base::TimeTicks time_to_send = |
367 base::TimeTicks() + base::TimeDelta::FromMicroseconds( | 321 base::TimeTicks() + base::TimeDelta::FromMicroseconds( |
368 timestamp * base::Time::kMicrosecondsPerSecond); | 322 timestamp * base::Time::kMicrosecondsPerSecond); |
369 delay = std::max(time_to_send - base::TimeTicks::Now(), base::TimeDelta()); | 323 delay = std::max(time_to_send - base::TimeTicks::Now(), base::TimeDelta()); |
370 } | 324 } |
371 | 325 |
372 service() | 326 service()->task_service()->PostBoundDelayedTask( |
373 ->GetTaskRunner(kSendTaskRunner) | 327 kSendTaskRunner, |
374 ->PostDelayedTask( | 328 base::BindOnce(&MidiManagerAlsa::SendMidiData, base::Unretained(this), |
375 FROM_HERE, | 329 client, port_index, data), |
376 base::Bind(&MidiManagerAlsa::SendMidiData, base::Unretained(this), | 330 delay); |
377 instance_id_, client, port_index, data), | |
378 delay); | |
379 } | 331 } |
380 | 332 |
381 MidiManagerAlsa::MidiPort::Id::Id() = default; | 333 MidiManagerAlsa::MidiPort::Id::Id() = default; |
382 | 334 |
383 MidiManagerAlsa::MidiPort::Id::Id(const std::string& bus, | 335 MidiManagerAlsa::MidiPort::Id::Id(const std::string& bus, |
384 const std::string& vendor_id, | 336 const std::string& vendor_id, |
385 const std::string& model_id, | 337 const std::string& model_id, |
386 const std::string& usb_interface_num, | 338 const std::string& usb_interface_num, |
387 const std::string& serial) | 339 const std::string& serial) |
388 : bus_(bus), | 340 : bus_(bus), |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 if (at_index && at_index != std::string::npos) { | 837 if (at_index && at_index != std::string::npos) { |
886 size_t name_index = alsa_longname.rfind(alsa_name, at_index - 1); | 838 size_t name_index = alsa_longname.rfind(alsa_name, at_index - 1); |
887 if (name_index && name_index != std::string::npos) | 839 if (name_index && name_index != std::string::npos) |
888 return alsa_longname.substr(0, name_index - 1); | 840 return alsa_longname.substr(0, name_index - 1); |
889 } | 841 } |
890 | 842 |
891 // Failure. | 843 // Failure. |
892 return ""; | 844 return ""; |
893 } | 845 } |
894 | 846 |
895 void MidiManagerAlsa::SendMidiData(int instance_id, | 847 void MidiManagerAlsa::SendMidiData(MidiManagerClient* client, |
896 MidiManagerClient* client, | |
897 uint32_t port_index, | 848 uint32_t port_index, |
898 const std::vector<uint8_t>& data) { | 849 const std::vector<uint8_t>& data) { |
899 DCHECK(service()->GetTaskRunner(kSendTaskRunner)->BelongsToCurrentThread()); | |
900 | |
901 // Obtain the lock so that the instance could not be destructed while this | |
902 // method is running on the kSendTaskRunner. | |
903 base::AutoLock lock(GetLockHelper()->send_task_lock); | |
904 { | |
905 // Check if Finalize() already runs. After this check, we can access |this| | |
906 // safely on the kEventTaskRunner. | |
907 base::AutoLock instance_id_lock(GetLockHelper()->instance_id_lock); | |
908 if (instance_id != g_active_instance_id) | |
909 return; | |
910 } | |
911 | |
912 snd_midi_event_t* encoder; | 850 snd_midi_event_t* encoder; |
913 snd_midi_event_new(kSendBufferSize, &encoder); | 851 snd_midi_event_new(kSendBufferSize, &encoder); |
914 for (const auto datum : data) { | 852 for (const auto datum : data) { |
915 snd_seq_event_t event; | 853 snd_seq_event_t event; |
916 int result = snd_midi_event_encode_byte(encoder, datum, &event); | 854 int result = snd_midi_event_encode_byte(encoder, datum, &event); |
917 if (result == 1) { | 855 if (result == 1) { |
918 // Full event, send it. | 856 // Full event, send it. |
919 base::AutoLock lock(out_ports_lock_); | 857 base::AutoLock lock(out_ports_lock_); |
920 auto it = out_ports_.find(port_index); | 858 auto it = out_ports_.find(port_index); |
921 if (it != out_ports_.end()) { | 859 if (it != out_ports_.end()) { |
922 snd_seq_ev_set_source(&event, it->second); | 860 snd_seq_ev_set_source(&event, it->second); |
923 snd_seq_ev_set_subs(&event); | 861 snd_seq_ev_set_subs(&event); |
924 snd_seq_ev_set_direct(&event); | 862 snd_seq_ev_set_direct(&event); |
925 snd_seq_event_output_direct(out_client_.get(), &event); | 863 snd_seq_event_output_direct(out_client_.get(), &event); |
926 } | 864 } |
927 } | 865 } |
928 } | 866 } |
929 snd_midi_event_free(encoder); | 867 snd_midi_event_free(encoder); |
930 | 868 |
931 // Acknowledge send. | 869 // Acknowledge send. |
932 AccumulateMidiBytesSent(client, data.size()); | 870 AccumulateMidiBytesSent(client, data.size()); |
933 } | 871 } |
934 | 872 |
935 void MidiManagerAlsa::EventLoop(int instance_id) { | 873 void MidiManagerAlsa::EventLoop() { |
936 // Obtain the lock so that the instance could not be destructed while this | |
937 // method is running on the kEventTaskRunner. | |
938 base::AutoLock lock(GetLockHelper()->event_task_lock); | |
939 { | |
940 // Check if Finalize() already runs. After this check, we can access |this| | |
941 // safely on the kEventTaskRunner. | |
942 base::AutoLock instance_id_lock(GetLockHelper()->instance_id_lock); | |
943 if (instance_id != g_active_instance_id) | |
944 return; | |
945 } | |
946 | |
947 bool loop_again = true; | 874 bool loop_again = true; |
948 | 875 |
949 struct pollfd pfd[2]; | 876 struct pollfd pfd[2]; |
950 snd_seq_poll_descriptors(in_client_.get(), &pfd[0], 1, POLLIN); | 877 snd_seq_poll_descriptors(in_client_.get(), &pfd[0], 1, POLLIN); |
951 pfd[1].fd = device::udev_monitor_get_fd(udev_monitor_.get()); | 878 pfd[1].fd = device::udev_monitor_get_fd(udev_monitor_.get()); |
952 pfd[1].events = POLLIN; | 879 pfd[1].events = POLLIN; |
953 | 880 |
954 int err = HANDLE_EINTR(poll(pfd, arraysize(pfd), -1)); | 881 int err = HANDLE_EINTR(poll(pfd, arraysize(pfd), -1)); |
955 if (err < 0) { | 882 if (err < 0) { |
956 VLOG(1) << "poll fails: " << base::safe_strerror(errno); | 883 VLOG(1) << "poll fails: " << base::safe_strerror(errno); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1013 device::udev_monitor_receive_device(udev_monitor_.get())); | 940 device::udev_monitor_receive_device(udev_monitor_.get())); |
1014 if (dev.get()) | 941 if (dev.get()) |
1015 ProcessUdevEvent(dev.get()); | 942 ProcessUdevEvent(dev.get()); |
1016 else | 943 else |
1017 VLOG(1) << "udev_monitor_receive_device fails"; | 944 VLOG(1) << "udev_monitor_receive_device fails"; |
1018 } | 945 } |
1019 } | 946 } |
1020 | 947 |
1021 // Do again. | 948 // Do again. |
1022 if (loop_again) { | 949 if (loop_again) { |
1023 service() | 950 service()->task_service()->PostBoundTask( |
1024 ->GetTaskRunner(kEventTaskRunner) | 951 kEventTaskRunner, |
1025 ->PostTask(FROM_HERE, base::Bind(&MidiManagerAlsa::EventLoop, | 952 base::BindOnce(&MidiManagerAlsa::EventLoop, base::Unretained(this))); |
1026 base::Unretained(this), instance_id)); | |
1027 } | 953 } |
1028 } | 954 } |
1029 | 955 |
1030 void MidiManagerAlsa::ProcessSingleEvent(snd_seq_event_t* event, | 956 void MidiManagerAlsa::ProcessSingleEvent(snd_seq_event_t* event, |
1031 double timestamp) { | 957 double timestamp) { |
1032 auto source_it = | 958 auto source_it = |
1033 source_map_.find(AddrToInt(event->source.client, event->source.port)); | 959 source_map_.find(AddrToInt(event->source.client, event->source.port)); |
1034 if (source_it != source_map_.end()) { | 960 if (source_it != source_map_.end()) { |
1035 uint32_t source = source_it->second; | 961 uint32_t source = source_it->second; |
1036 if (event->type == SND_SEQ_EVENT_SYSEX) { | 962 if (event->type == SND_SEQ_EVENT_SYSEX) { |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1449 // Update our map. | 1375 // Update our map. |
1450 source_map_[AddrToInt(client_id, port_id)] = port_index; | 1376 source_map_[AddrToInt(client_id, port_id)] = port_index; |
1451 return true; | 1377 return true; |
1452 } | 1378 } |
1453 | 1379 |
1454 MidiManager* MidiManager::Create(MidiService* service) { | 1380 MidiManager* MidiManager::Create(MidiService* service) { |
1455 return new MidiManagerAlsa(service); | 1381 return new MidiManagerAlsa(service); |
1456 } | 1382 } |
1457 | 1383 |
1458 } // namespace midi | 1384 } // namespace midi |
OLD | NEW |