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 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 base::AutoLock lock(lazy_init_member_lock_); | 174 base::AutoLock lock(lazy_init_member_lock_); |
175 | 175 |
176 initialization_thread_checker_.reset(new base::ThreadChecker()); | 176 initialization_thread_checker_.reset(new base::ThreadChecker()); |
177 | 177 |
178 // Create client handles. | 178 // Create client handles. |
179 snd_seq_t* tmp_seq = nullptr; | 179 snd_seq_t* tmp_seq = nullptr; |
180 int err = | 180 int err = |
181 snd_seq_open(&tmp_seq, kAlsaHw, SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK); | 181 snd_seq_open(&tmp_seq, kAlsaHw, SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK); |
182 if (err != 0) { | 182 if (err != 0) { |
183 VLOG(1) << "snd_seq_open fails: " << snd_strerror(err); | 183 VLOG(1) << "snd_seq_open fails: " << snd_strerror(err); |
184 return CompleteInitialization(Result::INITIALIZATION_ERROR); | 184 return CompleteInitialization(mojom::Result::INITIALIZATION_ERROR); |
185 } | 185 } |
186 ScopedSndSeqPtr in_client(tmp_seq); | 186 ScopedSndSeqPtr in_client(tmp_seq); |
187 tmp_seq = nullptr; | 187 tmp_seq = nullptr; |
188 in_client_id_ = snd_seq_client_id(in_client.get()); | 188 in_client_id_ = snd_seq_client_id(in_client.get()); |
189 | 189 |
190 err = snd_seq_open(&tmp_seq, kAlsaHw, SND_SEQ_OPEN_OUTPUT, 0); | 190 err = snd_seq_open(&tmp_seq, kAlsaHw, SND_SEQ_OPEN_OUTPUT, 0); |
191 if (err != 0) { | 191 if (err != 0) { |
192 VLOG(1) << "snd_seq_open fails: " << snd_strerror(err); | 192 VLOG(1) << "snd_seq_open fails: " << snd_strerror(err); |
193 return CompleteInitialization(Result::INITIALIZATION_ERROR); | 193 return CompleteInitialization(mojom::Result::INITIALIZATION_ERROR); |
194 } | 194 } |
195 ScopedSndSeqPtr out_client(tmp_seq); | 195 ScopedSndSeqPtr out_client(tmp_seq); |
196 tmp_seq = nullptr; | 196 tmp_seq = nullptr; |
197 out_client_id_ = snd_seq_client_id(out_client.get()); | 197 out_client_id_ = snd_seq_client_id(out_client.get()); |
198 | 198 |
199 // Name the clients. | 199 // Name the clients. |
200 err = snd_seq_set_client_name(in_client.get(), "Chrome (input)"); | 200 err = snd_seq_set_client_name(in_client.get(), "Chrome (input)"); |
201 if (err != 0) { | 201 if (err != 0) { |
202 VLOG(1) << "snd_seq_set_client_name fails: " << snd_strerror(err); | 202 VLOG(1) << "snd_seq_set_client_name fails: " << snd_strerror(err); |
203 return CompleteInitialization(Result::INITIALIZATION_ERROR); | 203 return CompleteInitialization(mojom::Result::INITIALIZATION_ERROR); |
204 } | 204 } |
205 err = snd_seq_set_client_name(out_client.get(), "Chrome (output)"); | 205 err = snd_seq_set_client_name(out_client.get(), "Chrome (output)"); |
206 if (err != 0) { | 206 if (err != 0) { |
207 VLOG(1) << "snd_seq_set_client_name fails: " << snd_strerror(err); | 207 VLOG(1) << "snd_seq_set_client_name fails: " << snd_strerror(err); |
208 return CompleteInitialization(Result::INITIALIZATION_ERROR); | 208 return CompleteInitialization(mojom::Result::INITIALIZATION_ERROR); |
209 } | 209 } |
210 | 210 |
211 // Create input port. | 211 // Create input port. |
212 in_port_id_ = snd_seq_create_simple_port( | 212 in_port_id_ = snd_seq_create_simple_port( |
213 in_client.get(), NULL, kCreateInputPortCaps, kCreatePortType); | 213 in_client.get(), NULL, kCreateInputPortCaps, kCreatePortType); |
214 if (in_port_id_ < 0) { | 214 if (in_port_id_ < 0) { |
215 VLOG(1) << "snd_seq_create_simple_port fails: " | 215 VLOG(1) << "snd_seq_create_simple_port fails: " |
216 << snd_strerror(in_port_id_); | 216 << snd_strerror(in_port_id_); |
217 return CompleteInitialization(Result::INITIALIZATION_ERROR); | 217 return CompleteInitialization(mojom::Result::INITIALIZATION_ERROR); |
218 } | 218 } |
219 | 219 |
220 // Subscribe to the announce port. | 220 // Subscribe to the announce port. |
221 snd_seq_port_subscribe_t* subs; | 221 snd_seq_port_subscribe_t* subs; |
222 snd_seq_port_subscribe_alloca(&subs); | 222 snd_seq_port_subscribe_alloca(&subs); |
223 snd_seq_addr_t announce_sender; | 223 snd_seq_addr_t announce_sender; |
224 snd_seq_addr_t announce_dest; | 224 snd_seq_addr_t announce_dest; |
225 announce_sender.client = SND_SEQ_CLIENT_SYSTEM; | 225 announce_sender.client = SND_SEQ_CLIENT_SYSTEM; |
226 announce_sender.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE; | 226 announce_sender.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE; |
227 announce_dest.client = in_client_id_; | 227 announce_dest.client = in_client_id_; |
228 announce_dest.port = in_port_id_; | 228 announce_dest.port = in_port_id_; |
229 snd_seq_port_subscribe_set_sender(subs, &announce_sender); | 229 snd_seq_port_subscribe_set_sender(subs, &announce_sender); |
230 snd_seq_port_subscribe_set_dest(subs, &announce_dest); | 230 snd_seq_port_subscribe_set_dest(subs, &announce_dest); |
231 err = snd_seq_subscribe_port(in_client.get(), subs); | 231 err = snd_seq_subscribe_port(in_client.get(), subs); |
232 if (err != 0) { | 232 if (err != 0) { |
233 VLOG(1) << "snd_seq_subscribe_port on the announce port fails: " | 233 VLOG(1) << "snd_seq_subscribe_port on the announce port fails: " |
234 << snd_strerror(err); | 234 << snd_strerror(err); |
235 return CompleteInitialization(Result::INITIALIZATION_ERROR); | 235 return CompleteInitialization(mojom::Result::INITIALIZATION_ERROR); |
236 } | 236 } |
237 | 237 |
238 // Initialize decoder. | 238 // Initialize decoder. |
239 snd_midi_event_t* tmp_decoder = nullptr; | 239 snd_midi_event_t* tmp_decoder = nullptr; |
240 snd_midi_event_new(0, &tmp_decoder); | 240 snd_midi_event_new(0, &tmp_decoder); |
241 ScopedSndMidiEventPtr decoder(tmp_decoder); | 241 ScopedSndMidiEventPtr decoder(tmp_decoder); |
242 tmp_decoder = nullptr; | 242 tmp_decoder = nullptr; |
243 snd_midi_event_no_status(decoder.get(), 1); | 243 snd_midi_event_no_status(decoder.get(), 1); |
244 | 244 |
245 // Initialize udev and monitor. | 245 // Initialize udev and monitor. |
246 device::ScopedUdevPtr udev(device::udev_new()); | 246 device::ScopedUdevPtr udev(device::udev_new()); |
247 device::ScopedUdevMonitorPtr udev_monitor( | 247 device::ScopedUdevMonitorPtr udev_monitor( |
248 device::udev_monitor_new_from_netlink(udev.get(), kUdev)); | 248 device::udev_monitor_new_from_netlink(udev.get(), kUdev)); |
249 if (!udev_monitor.get()) { | 249 if (!udev_monitor.get()) { |
250 VLOG(1) << "udev_monitor_new_from_netlink fails"; | 250 VLOG(1) << "udev_monitor_new_from_netlink fails"; |
251 return CompleteInitialization(Result::INITIALIZATION_ERROR); | 251 return CompleteInitialization(mojom::Result::INITIALIZATION_ERROR); |
252 } | 252 } |
253 err = device::udev_monitor_filter_add_match_subsystem_devtype( | 253 err = device::udev_monitor_filter_add_match_subsystem_devtype( |
254 udev_monitor.get(), kUdevSubsystemSound, nullptr); | 254 udev_monitor.get(), kUdevSubsystemSound, nullptr); |
255 if (err != 0) { | 255 if (err != 0) { |
256 VLOG(1) << "udev_monitor_add_match_subsystem fails: " | 256 VLOG(1) << "udev_monitor_add_match_subsystem fails: " |
257 << base::safe_strerror(-err); | 257 << base::safe_strerror(-err); |
258 return CompleteInitialization(Result::INITIALIZATION_ERROR); | 258 return CompleteInitialization(mojom::Result::INITIALIZATION_ERROR); |
259 } | 259 } |
260 err = device::udev_monitor_enable_receiving(udev_monitor.get()); | 260 err = device::udev_monitor_enable_receiving(udev_monitor.get()); |
261 if (err != 0) { | 261 if (err != 0) { |
262 VLOG(1) << "udev_monitor_enable_receiving fails: " | 262 VLOG(1) << "udev_monitor_enable_receiving fails: " |
263 << base::safe_strerror(-err); | 263 << base::safe_strerror(-err); |
264 return CompleteInitialization(Result::INITIALIZATION_ERROR); | 264 return CompleteInitialization(mojom::Result::INITIALIZATION_ERROR); |
265 } | 265 } |
266 | 266 |
267 // Success! Now, initialize members from the temporaries. Do not | 267 // Success! Now, initialize members from the temporaries. Do not |
268 // initialize these earlier, since they need to be destroyed by the | 268 // initialize these earlier, since they need to be destroyed by the |
269 // thread that calls Finalize(), not the destructor thread (and we | 269 // thread that calls Finalize(), not the destructor thread (and we |
270 // check this in the destructor). | 270 // check this in the destructor). |
271 in_client_.reset(in_client.release()); | 271 in_client_.reset(in_client.release()); |
272 out_client_.reset(out_client.release()); | 272 out_client_.reset(out_client.release()); |
273 decoder_.reset(decoder.release()); | 273 decoder_.reset(decoder.release()); |
274 udev_.reset(udev.release()); | 274 udev_.reset(udev.release()); |
275 udev_monitor_.reset(udev_monitor.release()); | 275 udev_monitor_.reset(udev_monitor.release()); |
276 | 276 |
277 // Generate hotplug events for existing ports. | 277 // Generate hotplug events for existing ports. |
278 // TODO(agoode): Check the return value for failure. | 278 // TODO(agoode): Check the return value for failure. |
279 EnumerateAlsaPorts(); | 279 EnumerateAlsaPorts(); |
280 | 280 |
281 // Generate hotplug events for existing udev devices. This must be done | 281 // Generate hotplug events for existing udev devices. This must be done |
282 // after udev_monitor_enable_receiving() is called. See the algorithm | 282 // after udev_monitor_enable_receiving() is called. See the algorithm |
283 // at http://www.signal11.us/oss/udev/. | 283 // at http://www.signal11.us/oss/udev/. |
284 EnumerateUdevCards(); | 284 EnumerateUdevCards(); |
285 | 285 |
286 // Start processing events. Don't do this before enumeration of both | 286 // Start processing events. Don't do this before enumeration of both |
287 // ALSA and udev. | 287 // ALSA and udev. |
288 event_thread_.Start(); | 288 event_thread_.Start(); |
289 event_thread_.task_runner()->PostTask( | 289 event_thread_.task_runner()->PostTask( |
290 FROM_HERE, | 290 FROM_HERE, |
291 base::Bind(&MidiManagerAlsa::ScheduleEventLoop, base::Unretained(this))); | 291 base::Bind(&MidiManagerAlsa::ScheduleEventLoop, base::Unretained(this))); |
292 send_thread_.Start(); | 292 send_thread_.Start(); |
293 | 293 |
294 CompleteInitialization(Result::OK); | 294 CompleteInitialization(mojom::Result::OK); |
295 } | 295 } |
296 | 296 |
297 void MidiManagerAlsa::Finalize() { | 297 void MidiManagerAlsa::Finalize() { |
298 base::AutoLock lock(lazy_init_member_lock_); | 298 base::AutoLock lock(lazy_init_member_lock_); |
299 DCHECK(initialization_thread_checker_->CalledOnValidThread()); | 299 DCHECK(initialization_thread_checker_->CalledOnValidThread()); |
300 | 300 |
301 // Tell the event thread it will soon be time to shut down. This gives | 301 // Tell the event thread it will soon be time to shut down. This gives |
302 // us assurance the thread will stop in case the SND_SEQ_EVENT_CLIENT_EXIT | 302 // us assurance the thread will stop in case the SND_SEQ_EVENT_CLIENT_EXIT |
303 // message is lost. | 303 // message is lost. |
304 { | 304 { |
(...skipping 1091 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 // Update our map. | 1396 // Update our map. |
1397 source_map_[AddrToInt(client_id, port_id)] = port_index; | 1397 source_map_[AddrToInt(client_id, port_id)] = port_index; |
1398 return true; | 1398 return true; |
1399 } | 1399 } |
1400 | 1400 |
1401 MidiManager* MidiManager::Create() { | 1401 MidiManager* MidiManager::Create() { |
1402 return new MidiManagerAlsa(); | 1402 return new MidiManagerAlsa(); |
1403 } | 1403 } |
1404 | 1404 |
1405 } // namespace midi | 1405 } // namespace midi |
OLD | NEW |