Chromium Code Reviews| 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 |