Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Side by Side Diff: media/midi/midi_manager_alsa.cc

Issue 1025163002: Rename AlsaRawmidi to AlsaCard and include the count of midi devices instead of duplicating (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@h4
Patch Set: Rebase Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/midi/midi_manager_alsa.h ('k') | media/midi/midi_manager_alsa_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <alsa/asoundlib.h> 7 #include <alsa/asoundlib.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <algorithm> 9 #include <algorithm>
10 #include <string> 10 #include <string>
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 FROM_HERE, base::Bind(&MidiManagerAlsa::SendMidiData, 236 FROM_HERE, base::Bind(&MidiManagerAlsa::SendMidiData,
237 base::Unretained(this), port_index, data), 237 base::Unretained(this), port_index, data),
238 delay); 238 delay);
239 239
240 // Acknowledge send. 240 // Acknowledge send.
241 send_thread_.message_loop()->PostTask( 241 send_thread_.message_loop()->PostTask(
242 FROM_HERE, base::Bind(&MidiManagerClient::AccumulateMidiBytesSent, 242 FROM_HERE, base::Bind(&MidiManagerClient::AccumulateMidiBytesSent,
243 base::Unretained(client), data.size())); 243 base::Unretained(client), data.size()));
244 } 244 }
245 245
246 MidiManagerAlsa::AlsaRawmidi::AlsaRawmidi(const MidiManagerAlsa* outer, 246 MidiManagerAlsa::AlsaCard::AlsaCard(const MidiManagerAlsa* outer,
247 const std::string& alsa_name, 247 const std::string& alsa_name,
248 const std::string& alsa_longname, 248 const std::string& alsa_longname,
249 const std::string& alsa_driver, 249 const std::string& alsa_driver,
250 int card_index) 250 int card_index,
251 int midi_count)
251 : alsa_name_(alsa_name), 252 : alsa_name_(alsa_name),
252 alsa_longname_(alsa_longname), 253 alsa_longname_(alsa_longname),
253 alsa_driver_(alsa_driver) { 254 alsa_driver_(alsa_driver),
255 midi_count_(midi_count) {
254 // Get udev properties if available. 256 // Get udev properties if available.
255 std::string vendor; 257 std::string vendor;
256 std::string vendor_from_database; 258 std::string vendor_from_database;
257 259
258 #if defined(USE_UDEV) 260 #if defined(USE_UDEV)
259 const std::string sysname = base::StringPrintf("card%i", card_index); 261 const std::string sysname = base::StringPrintf("card%i", card_index);
260 device::ScopedUdevDevicePtr udev_device( 262 device::ScopedUdevDevicePtr udev_device(
261 device::udev_device_new_from_subsystem_sysname( 263 device::udev_device_new_from_subsystem_sysname(
262 outer->udev_.get(), kSoundClass, sysname.c_str())); 264 outer->udev_.get(), kSoundClass, sysname.c_str()));
263 265
(...skipping 26 matching lines...) Expand all
290 292
291 // Get the usb interface number. 293 // Get the usb interface number.
292 usb_interface_num_ = 294 usb_interface_num_ =
293 device::UdevDeviceGetPropertyValue(udev_device.get(), kUsbInterfaceNum); 295 device::UdevDeviceGetPropertyValue(udev_device.get(), kUsbInterfaceNum);
294 #endif // defined(USE_UDEV) 296 #endif // defined(USE_UDEV)
295 297
296 manufacturer_ = ExtractManufacturerString( 298 manufacturer_ = ExtractManufacturerString(
297 vendor, vendor_id_, vendor_from_database, alsa_name, alsa_longname); 299 vendor, vendor_id_, vendor_from_database, alsa_name, alsa_longname);
298 } 300 }
299 301
300 MidiManagerAlsa::AlsaRawmidi::~AlsaRawmidi() { 302 MidiManagerAlsa::AlsaCard::~AlsaCard() {
301 } 303 }
302 304
303 const std::string MidiManagerAlsa::AlsaRawmidi::alsa_name() const { 305 const std::string MidiManagerAlsa::AlsaCard::alsa_name() const {
304 return alsa_name_; 306 return alsa_name_;
305 } 307 }
306 308
307 const std::string MidiManagerAlsa::AlsaRawmidi::alsa_longname() const { 309 const std::string MidiManagerAlsa::AlsaCard::alsa_longname() const {
308 return alsa_longname_; 310 return alsa_longname_;
309 } 311 }
310 312
311 const std::string MidiManagerAlsa::AlsaRawmidi::manufacturer() const { 313 const std::string MidiManagerAlsa::AlsaCard::manufacturer() const {
312 return manufacturer_; 314 return manufacturer_;
313 } 315 }
314 316
315 const std::string MidiManagerAlsa::AlsaRawmidi::alsa_driver() const { 317 const std::string MidiManagerAlsa::AlsaCard::alsa_driver() const {
316 return alsa_driver_; 318 return alsa_driver_;
317 } 319 }
318 320
319 const std::string MidiManagerAlsa::AlsaRawmidi::path() const { 321 const std::string MidiManagerAlsa::AlsaCard::path() const {
320 return path_; 322 return path_;
321 } 323 }
322 324
323 const std::string MidiManagerAlsa::AlsaRawmidi::bus() const { 325 const std::string MidiManagerAlsa::AlsaCard::bus() const {
324 return bus_; 326 return bus_;
325 } 327 }
326 328
327 const std::string MidiManagerAlsa::AlsaRawmidi::vendor_id() const { 329 const std::string MidiManagerAlsa::AlsaCard::vendor_id() const {
328 return vendor_id_; 330 return vendor_id_;
329 } 331 }
330 332
331 const std::string MidiManagerAlsa::AlsaRawmidi::id() const { 333 const std::string MidiManagerAlsa::AlsaCard::id() const {
332 std::string id = vendor_id_; 334 std::string id = vendor_id_;
333 if (!model_id_.empty()) 335 if (!model_id_.empty())
334 id += ":" + model_id_; 336 id += ":" + model_id_;
335 if (!usb_interface_num_.empty()) 337 if (!usb_interface_num_.empty())
336 id += ":" + usb_interface_num_; 338 id += ":" + usb_interface_num_;
337 return id; 339 return id;
338 } 340 }
339 341
342 const int MidiManagerAlsa::AlsaCard::midi_count() const {
343 return midi_count_;
344 }
345
340 // static 346 // static
341 std::string MidiManagerAlsa::AlsaRawmidi::ExtractManufacturerString( 347 std::string MidiManagerAlsa::AlsaCard::ExtractManufacturerString(
342 const std::string& udev_id_vendor, 348 const std::string& udev_id_vendor,
343 const std::string& udev_id_vendor_id, 349 const std::string& udev_id_vendor_id,
344 const std::string& udev_id_vendor_from_database, 350 const std::string& udev_id_vendor_from_database,
345 const std::string& alsa_name, 351 const std::string& alsa_name,
346 const std::string& alsa_longname) { 352 const std::string& alsa_longname) {
347 // Let's try to determine the manufacturer. Here is the ordered preference 353 // Let's try to determine the manufacturer. Here is the ordered preference
348 // in extraction: 354 // in extraction:
349 // 1. Vendor name from the hardware device string, from udev properties 355 // 1. Vendor name from the hardware device string, from udev properties
350 // or sysattrs. 356 // or sysattrs.
351 // 2. Vendor name from the udev database (property ID_VENDOR_FROM_DATABASE). 357 // 2. Vendor name from the udev database (property ID_VENDOR_FROM_DATABASE).
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 // mapping and just use a UUID or other random string. 444 // mapping and just use a UUID or other random string.
439 // http://crbug.com/465320 445 // http://crbug.com/465320
440 std::string MidiManagerAlsa::AlsaPortMetadata::OpaqueKey() const { 446 std::string MidiManagerAlsa::AlsaPortMetadata::OpaqueKey() const {
441 uint8 hash[crypto::kSHA256Length]; 447 uint8 hash[crypto::kSHA256Length];
442 crypto::SHA256HashString(JSONValue(), &hash, sizeof(hash)); 448 crypto::SHA256HashString(JSONValue(), &hash, sizeof(hash));
443 return base::HexEncode(&hash, sizeof(hash)); 449 return base::HexEncode(&hash, sizeof(hash));
444 } 450 }
445 451
446 // TODO(agoode): Add a client->card/rawmidi mapping to the kernel to avoid 452 // TODO(agoode): Add a client->card/rawmidi mapping to the kernel to avoid
447 // needing to probe in this way. 453 // needing to probe in this way.
448 ScopedVector<MidiManagerAlsa::AlsaRawmidi> MidiManagerAlsa::AllAlsaRawmidis() { 454 ScopedVector<MidiManagerAlsa::AlsaCard> MidiManagerAlsa::AllMidiCards() {
449 ScopedVector<AlsaRawmidi> devices; 455 ScopedVector<AlsaCard> devices;
450 snd_ctl_card_info_t* card; 456 snd_ctl_card_info_t* card;
451 snd_hwdep_info_t* hwdep; 457 snd_hwdep_info_t* hwdep;
452 snd_ctl_card_info_alloca(&card); 458 snd_ctl_card_info_alloca(&card);
453 snd_hwdep_info_alloca(&hwdep); 459 snd_hwdep_info_alloca(&hwdep);
454 for (int card_index = -1; !snd_card_next(&card_index) && card_index >= 0;) { 460 for (int card_index = -1; !snd_card_next(&card_index) && card_index >= 0;) {
461 int midi_count = 0;
455 const std::string id = base::StringPrintf("hw:CARD=%i", card_index); 462 const std::string id = base::StringPrintf("hw:CARD=%i", card_index);
456 snd_ctl_t* handle; 463 snd_ctl_t* handle;
457 int err = snd_ctl_open(&handle, id.c_str(), 0); 464 int err = snd_ctl_open(&handle, id.c_str(), 0);
458 if (err != 0) { 465 if (err != 0) {
459 VLOG(1) << "snd_ctl_open fails: " << snd_strerror(err); 466 VLOG(1) << "snd_ctl_open fails: " << snd_strerror(err);
460 continue; 467 continue;
461 } 468 }
462 err = snd_ctl_card_info(handle, card); 469 err = snd_ctl_card_info(handle, card);
463 if (err != 0) { 470 if (err != 0) {
464 VLOG(1) << "snd_ctl_card_info fails: " << snd_strerror(err); 471 VLOG(1) << "snd_ctl_card_info fails: " << snd_strerror(err);
465 snd_ctl_close(handle); 472 snd_ctl_close(handle);
466 continue; 473 continue;
467 } 474 }
468 std::string name = snd_ctl_card_info_get_name(card); 475 std::string name = snd_ctl_card_info_get_name(card);
469 std::string longname = snd_ctl_card_info_get_longname(card); 476 std::string longname = snd_ctl_card_info_get_longname(card);
470 std::string driver = snd_ctl_card_info_get_driver(card); 477 std::string driver = snd_ctl_card_info_get_driver(card);
471 478
472 // Count rawmidi devices (not subdevices). 479 // Count rawmidi devices (not subdevices).
473 for (int device = -1; 480 for (int device = -1;
474 !snd_ctl_rawmidi_next_device(handle, &device) && device >= 0;) { 481 !snd_ctl_rawmidi_next_device(handle, &device) && device >= 0;)
475 devices.push_back( 482 ++midi_count;
476 new AlsaRawmidi(this, name, longname, driver, card_index));
477 }
478 483
479 // Count any hwdep synths that become MIDI devices. 484 // Count any hwdep synths that become MIDI devices outside of rawmidi.
480 // 485 //
481 // Explanation: 486 // Explanation:
482 // Any kernel driver can create an ALSA client (visible to us). 487 // Any kernel driver can create an ALSA client (visible to us).
483 // With modern hardware, only rawmidi devices do this. Kernel 488 // With modern hardware, only rawmidi devices do this. Kernel
484 // drivers create rawmidi devices and the rawmidi subsystem makes 489 // drivers create rawmidi devices and the rawmidi subsystem makes
485 // the seq clients. But the OPL3 driver is special, it does not 490 // the seq clients. But the OPL3 driver is special, it does not
486 // make a rawmidi device but a seq client directly. (This is the 491 // make a rawmidi device but a seq client directly. (This is the
487 // only one to worry about in the kernel code, as of 2015-03-23.) 492 // only one to worry about in the kernel code, as of 2015-03-23.)
488 // 493 //
489 // OPL3 is very old (but still possible to get in new 494 // OPL3 is very old (but still possible to get in new
490 // hardware). It is unlikely that new drivers would not use 495 // hardware). It is unlikely that new drivers would not use
491 // rawmidi and defeat our heuristic. 496 // rawmidi and defeat our heuristic.
492 // 497 //
493 // Longer term, support should be added in the kernel to expose a 498 // Longer term, support should be added in the kernel to expose a
494 // direct link from card->client (or client->card) so that all 499 // direct link from card->client (or client->card) so that all
495 // these heuristics will be obsolete. Once that is there, we can 500 // these heuristics will be obsolete. Once that is there, we can
496 // assume our old heuristics will work on old kernels and the new 501 // assume our old heuristics will work on old kernels and the new
497 // robust code will be used on new. Then we will not need to worry 502 // robust code will be used on new. Then we will not need to worry
498 // about changes to kernel internals breaking our code. 503 // about changes to kernel internals breaking our code.
499 // See the TODO above at kMinimumClientIdForCards. 504 // See the TODO above at kMinimumClientIdForCards.
500 for (int device = -1; 505 for (int device = -1;
501 !snd_ctl_hwdep_next_device(handle, &device) && device >= 0;) { 506 !snd_ctl_hwdep_next_device(handle, &device) && device >= 0;) {
502 snd_ctl_hwdep_info(handle, hwdep); 507 snd_ctl_hwdep_info(handle, hwdep);
503 snd_hwdep_iface_t iface = snd_hwdep_info_get_iface(hwdep); 508 snd_hwdep_iface_t iface = snd_hwdep_info_get_iface(hwdep);
504 if (iface == SND_HWDEP_IFACE_OPL2 || iface == SND_HWDEP_IFACE_OPL3 || 509 if (iface == SND_HWDEP_IFACE_OPL2 || iface == SND_HWDEP_IFACE_OPL3 ||
505 iface == SND_HWDEP_IFACE_OPL4) 510 iface == SND_HWDEP_IFACE_OPL4)
506 devices.push_back( 511 ++midi_count;
507 new AlsaRawmidi(this, name, longname, driver, card_index));
508 } 512 }
513
514 if (midi_count > 0)
515 devices.push_back(
516 new AlsaCard(this, name, longname, driver, card_index, midi_count));
509 snd_ctl_close(handle); 517 snd_ctl_close(handle);
510 } 518 }
511 519
512 return devices.Pass(); 520 return devices.Pass();
513 } 521 }
514 522
515 void MidiManagerAlsa::EnumeratePorts() { 523 void MidiManagerAlsa::EnumeratePorts() {
516 ScopedVector<AlsaRawmidi> devices = AllAlsaRawmidis(); 524 ScopedVector<AlsaCard> cards = AllMidiCards();
525 std::vector<const AlsaCard*> devices;
526 for (const auto* card : cards) {
527 // Insert 1 AlsaCard per number of MIDI devices.
528 for (int n = 0; n < card->midi_count(); ++n)
529 devices.push_back(card);
530 }
517 531
518 snd_seq_port_subscribe_t* subs; 532 snd_seq_port_subscribe_t* subs;
519 snd_seq_port_subscribe_alloca(&subs); 533 snd_seq_port_subscribe_alloca(&subs);
520 534
521 int in_client_id = snd_seq_client_id(in_client_); 535 int in_client_id = snd_seq_client_id(in_client_);
522 536
523 // Enumerate all clients. 537 // Enumerate all clients.
524 snd_seq_client_info_t* client_info; 538 snd_seq_client_info_t* client_info;
525 snd_seq_client_info_alloca(&client_info); 539 snd_seq_client_info_alloca(&client_info);
526 snd_seq_port_info_t* port_info; 540 snd_seq_port_info_t* port_info;
(...skipping 17 matching lines...) Expand all
544 558
545 std::string manufacturer; 559 std::string manufacturer;
546 std::string driver; 560 std::string driver;
547 std::string path; 561 std::string path;
548 std::string bus; 562 std::string bus;
549 std::string vendor_id; 563 std::string vendor_id;
550 std::string id; 564 std::string id;
551 std::string card_name; 565 std::string card_name;
552 std::string card_longname; 566 std::string card_longname;
553 567
554 // Join kernel clients against the list of AlsaRawmidis. 568 // Join kernel clients against the list of AlsaCards.
555 // In the current ALSA kernel implementation, kernel clients match the 569 // In the current ALSA kernel implementation, kernel clients match the
556 // kernel devices in the same order, for devices with client_id over 570 // kernel devices in the same order, for clients with client_id over
557 // kMinimumClientIdForCards. 571 // kMinimumClientIdForCards.
558 if ((snd_seq_client_info_get_type(client_info) == SND_SEQ_KERNEL_CLIENT) && 572 if ((snd_seq_client_info_get_type(client_info) == SND_SEQ_KERNEL_CLIENT) &&
559 (current_device < devices.size()) && 573 (current_device < devices.size()) &&
560 (client_id >= kMinimumClientIdForCards)) { 574 (client_id >= kMinimumClientIdForCards)) {
561 const AlsaRawmidi* device = devices[current_device]; 575 const AlsaCard* device = devices[current_device];
562 manufacturer = device->manufacturer(); 576 manufacturer = device->manufacturer();
563 driver = device->alsa_driver(); 577 driver = device->alsa_driver();
564 path = device->path(); 578 path = device->path();
565 bus = device->bus(); 579 bus = device->bus();
566 vendor_id = device->vendor_id(); 580 vendor_id = device->vendor_id();
567 id = device->id(); 581 id = device->id();
568 card_name = device->alsa_name(); 582 card_name = device->alsa_name();
569 card_longname = device->alsa_longname(); 583 card_longname = device->alsa_longname();
570 current_device++; 584 current_device++;
571 } 585 }
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 } 707 }
694 708
695 // Handle announce events. 709 // Handle announce events.
696 if (event->source.client == SND_SEQ_CLIENT_SYSTEM && 710 if (event->source.client == SND_SEQ_CLIENT_SYSTEM &&
697 event->source.port == SND_SEQ_PORT_SYSTEM_ANNOUNCE) { 711 event->source.port == SND_SEQ_PORT_SYSTEM_ANNOUNCE) {
698 switch (event->type) { 712 switch (event->type) {
699 case SND_SEQ_EVENT_CLIENT_START: 713 case SND_SEQ_EVENT_CLIENT_START:
700 // TODO(agoode): rescan hardware devices. 714 // TODO(agoode): rescan hardware devices.
701 break; 715 break;
702 716
717 case SND_SEQ_EVENT_PORT_START:
718 // TODO(agoode): add port.
719 break;
720
703 case SND_SEQ_EVENT_CLIENT_EXIT: 721 case SND_SEQ_EVENT_CLIENT_EXIT:
704 // Check for disconnection of our "out" client. This means "shut down". 722 // Check for disconnection of our "out" client. This means "shut down".
705 if (event->data.addr.client == out_client_id_) 723 if (event->data.addr.client == out_client_id_)
706 return; 724 return;
707 725
708 // TODO(agoode): remove all ports for a client. 726 // TODO(agoode): remove all ports for a client.
709 break; 727 break;
710 728
711 case SND_SEQ_EVENT_PORT_START:
712 // TODO(agoode): add port.
713 break;
714
715 case SND_SEQ_EVENT_PORT_EXIT: 729 case SND_SEQ_EVENT_PORT_EXIT:
716 // TODO(agoode): remove port. 730 // TODO(agoode): remove port.
717 break; 731 break;
718 } 732 }
733 } else {
734 ProcessSingleEvent(event, timestamp);
719 } 735 }
720 736
721 ProcessSingleEvent(event, timestamp);
722
723 // Do again. 737 // Do again.
724 ScheduleEventLoop(); 738 ScheduleEventLoop();
725 } 739 }
726 740
727 void MidiManagerAlsa::ProcessSingleEvent(snd_seq_event_t* event, 741 void MidiManagerAlsa::ProcessSingleEvent(snd_seq_event_t* event,
728 double timestamp) { 742 double timestamp) {
729 std::map<int, uint32>::iterator source_it = 743 auto source_it = source_map_.find(AddrToInt(&event->source));
730 source_map_.find(AddrToInt(&event->source));
731 if (source_it != source_map_.end()) { 744 if (source_it != source_map_.end()) {
732 uint32 source = source_it->second; 745 uint32 source = source_it->second;
733 if (event->type == SND_SEQ_EVENT_SYSEX) { 746 if (event->type == SND_SEQ_EVENT_SYSEX) {
734 // Special! Variable-length sysex. 747 // Special! Variable-length sysex.
735 ReceiveMidiData(source, static_cast<const uint8*>(event->data.ext.ptr), 748 ReceiveMidiData(source, static_cast<const uint8*>(event->data.ext.ptr),
736 event->data.ext.len, timestamp); 749 event->data.ext.len, timestamp);
737 } else { 750 } else {
738 // Otherwise, decode this and send that on. 751 // Otherwise, decode this and send that on.
739 unsigned char buf[12]; 752 unsigned char buf[12];
740 long count = snd_midi_event_decode(decoder_, buf, sizeof(buf), event); 753 long count = snd_midi_event_decode(decoder_, buf, sizeof(buf), event);
741 if (count <= 0) { 754 if (count <= 0) {
742 if (count != -ENOENT) { 755 if (count != -ENOENT) {
743 // ENOENT means that it's not a MIDI message, which is not an 756 // ENOENT means that it's not a MIDI message, which is not an
744 // error, but other negative values are errors for us. 757 // error, but other negative values are errors for us.
745 VLOG(1) << "snd_midi_event_decoder fails " << snd_strerror(count); 758 VLOG(1) << "snd_midi_event_decoder fails " << snd_strerror(count);
746 // TODO(agoode): Record this failure. 759 // TODO(agoode): Record this failure.
747 } 760 }
748 } else { 761 } else {
749 ReceiveMidiData(source, buf, count, timestamp); 762 ReceiveMidiData(source, buf, count, timestamp);
750 } 763 }
751 } 764 }
752 } 765 }
753 } 766 }
754 767
755 MidiManager* MidiManager::Create() { 768 MidiManager* MidiManager::Create() {
756 return new MidiManagerAlsa(); 769 return new MidiManagerAlsa();
757 } 770 }
758 771
759 } // namespace media 772 } // namespace media
OLDNEW
« no previous file with comments | « media/midi/midi_manager_alsa.h ('k') | media/midi/midi_manager_alsa_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698