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