| 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 |