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 <alsa/asoundlib.h> | 7 #include <alsa/asoundlib.h> |
8 #include <poll.h> | 8 #include <poll.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 19 matching lines...) Expand all Loading... | |
30 namespace midi { | 30 namespace midi { |
31 | 31 |
32 namespace { | 32 namespace { |
33 | 33 |
34 // Per-output buffer. This can be smaller, but then large sysex messages | 34 // Per-output buffer. This can be smaller, but then large sysex messages |
35 // will be (harmlessly) split across multiple seq events. This should | 35 // will be (harmlessly) split across multiple seq events. This should |
36 // not have any real practical effect, except perhaps to slightly reorder | 36 // not have any real practical effect, except perhaps to slightly reorder |
37 // realtime messages with respect to sysex. | 37 // realtime messages with respect to sysex. |
38 const size_t kSendBufferSize = 256; | 38 const size_t kSendBufferSize = 256; |
39 | 39 |
40 // Minimum client id for which we will have ALSA card devices for. When we | |
41 // are searching for card devices (used to get the path, id, and manufacturer), | |
42 // we don't want to get confused by kernel clients that do not have a card. | |
43 // See seq_clientmgr.c in the ALSA code for this. | |
44 // TODO(agoode): Add proper client -> card export from the kernel to avoid | |
45 // hardcoding. | |
46 const int kMinimumClientIdForCards = 16; | |
47 | |
40 // ALSA constants. | 48 // ALSA constants. |
41 const char kAlsaHw[] = "hw"; | 49 const char kAlsaHw[] = "hw"; |
42 | 50 |
43 // udev constants. | 51 // udev constants. |
44 const char kUdev[] = "udev"; | 52 const char kUdev[] = "udev"; |
45 const char kUdevSubsystemSound[] = "sound"; | 53 const char kUdevSubsystemSound[] = "sound"; |
46 const char kUdevPropertySoundInitialized[] = "SOUND_INITIALIZED"; | 54 const char kUdevPropertySoundInitialized[] = "SOUND_INITIALIZED"; |
47 const char kUdevActionChange[] = "change"; | 55 const char kUdevActionChange[] = "change"; |
48 const char kUdevActionRemove[] = "remove"; | 56 const char kUdevActionRemove[] = "remove"; |
49 | 57 |
58 const char kUdevIdVendor[] = "ID_VENDOR"; | |
59 const char kUdevIdVendorEnc[] = "ID_VENDOR_ENC"; | |
60 const char kUdevIdVendorFromDatabase[] = "ID_VENDOR_FROM_DATABASE"; | |
61 const char kUdevIdVendorId[] = "ID_VENDOR_ID"; | |
62 const char kUdevIdModelId[] = "ID_MODEL_ID"; | |
63 const char kUdevIdBus[] = "ID_BUS"; | |
64 const char kUdevIdPath[] = "ID_PATH"; | |
65 const char kUdevIdUsbInterfaceNum[] = "ID_USB_INTERFACE_NUM"; | |
66 const char kUdevIdSerialShort[] = "ID_SERIAL_SHORT"; | |
67 | |
68 const char kSysattrVendorName[] = "vendor_name"; | |
69 const char kSysattrVendor[] = "vendor"; | |
70 const char kSysattrModel[] = "model"; | |
71 const char kSysattrGuid[] = "guid"; | |
72 | |
73 const char kCardSyspath[] = "/card"; | |
74 | |
50 // Constants for the capabilities we search for in inputs and outputs. | 75 // Constants for the capabilities we search for in inputs and outputs. |
51 // See http://www.alsa-project.org/alsa-doc/alsa-lib/seq.html. | 76 // See http://www.alsa-project.org/alsa-doc/alsa-lib/seq.html. |
52 const unsigned int kRequiredInputPortCaps = | 77 const unsigned int kRequiredInputPortCaps = |
53 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; | 78 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ; |
54 const unsigned int kRequiredOutputPortCaps = | 79 const unsigned int kRequiredOutputPortCaps = |
55 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; | 80 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; |
56 | 81 |
57 const unsigned int kCreateOutputPortCaps = | 82 const unsigned int kCreateOutputPortCaps = |
58 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_NO_EXPORT; | 83 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_NO_EXPORT; |
59 const unsigned int kCreateInputPortCaps = | 84 const unsigned int kCreateInputPortCaps = |
60 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_NO_EXPORT; | 85 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_NO_EXPORT; |
61 const unsigned int kCreatePortType = | 86 const unsigned int kCreatePortType = |
62 SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION; | 87 SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION; |
63 | 88 |
64 int AddrToInt(int client, int port) { | 89 int AddrToInt(int client, int port) { |
65 return (client << 8) | port; | 90 return (client << 8) | port; |
66 } | 91 } |
67 | 92 |
93 bool IsCardKernelClient(snd_seq_client_type_t type, int client_id) { | |
94 return (type == SND_SEQ_KERNEL_CLIENT) && | |
95 (client_id >= kMinimumClientIdForCards); | |
96 } | |
97 | |
98 // TODO(agoode): Move this to device/udev_linux. | |
99 const std::string UdevDeviceGetPropertyOrSysattr( | |
100 struct udev_device* udev_device, | |
101 const char* property_key, | |
102 const char* sysattr_key) { | |
103 // First try the property. | |
104 std::string value = | |
105 device::UdevDeviceGetPropertyValue(udev_device, property_key); | |
106 | |
107 // If no property, look for sysattrs and walk up the parent devices too. | |
108 while (value.empty() && udev_device) { | |
109 value = device::UdevDeviceGetSysattrValue(udev_device, sysattr_key); | |
110 udev_device = device::udev_device_get_parent(udev_device); | |
111 } | |
112 return value; | |
113 } | |
114 | |
115 int GetCardNumber(udev_device* dev) { | |
116 const char* syspath = device::udev_device_get_syspath(dev); | |
117 if (!syspath) | |
118 return -1; | |
119 | |
120 std::string syspath_str(syspath); | |
121 size_t i = syspath_str.rfind(kCardSyspath); | |
122 if (i == std::string::npos) | |
123 return -1; | |
124 | |
125 int number; | |
126 if (!base::StringToInt(syspath_str.substr(i + strlen(kCardSyspath)), &number)) | |
127 return -1; | |
128 return number; | |
129 } | |
130 | |
68 void SetStringIfNonEmpty(base::DictionaryValue* value, | 131 void SetStringIfNonEmpty(base::DictionaryValue* value, |
69 const std::string& path, | 132 const std::string& path, |
70 const std::string& in_value) { | 133 const std::string& in_value) { |
71 if (!in_value.empty()) | 134 if (!in_value.empty()) |
72 value->SetString(path, in_value); | 135 value->SetString(path, in_value); |
73 } | 136 } |
74 | 137 |
75 } // namespace | 138 } // namespace |
76 | 139 |
77 MidiManagerAlsa::MidiManagerAlsa() | 140 MidiManagerAlsa::MidiManagerAlsa() |
78 : in_client_(NULL), | 141 : in_client_(NULL), |
79 out_client_(NULL), | 142 out_client_(NULL), |
80 out_client_id_(-1), | 143 out_client_id_(-1), |
81 in_port_id_(-1), | 144 in_port_id_(-1), |
145 alsa_cards_deleter_(&alsa_cards_), | |
146 alsa_card_midi_count_(0), | |
82 decoder_(NULL), | 147 decoder_(NULL), |
83 udev_(device::udev_new()), | 148 udev_(device::udev_new()), |
84 send_thread_("MidiSendThread"), | 149 send_thread_("MidiSendThread"), |
85 event_thread_("MidiEventThread"), | 150 event_thread_("MidiEventThread"), |
86 event_thread_shutdown_(false) { | 151 event_thread_shutdown_(false) { |
87 // Initialize decoder. | 152 // Initialize decoder. |
88 snd_midi_event_new(0, &decoder_); | 153 snd_midi_event_new(0, &decoder_); |
89 snd_midi_event_no_status(decoder_, 1); | 154 snd_midi_event_no_status(decoder_, 1); |
90 } | 155 } |
91 | 156 |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
488 break; | 553 break; |
489 case MidiPort::Type::kOutput: | 554 case MidiPort::Type::kOutput: |
490 web_port_index = num_output_ports_++; | 555 web_port_index = num_output_ports_++; |
491 break; | 556 break; |
492 } | 557 } |
493 port->set_web_port_index(web_port_index); | 558 port->set_web_port_index(web_port_index); |
494 ports()->push_back(port.Pass()); | 559 ports()->push_back(port.Pass()); |
495 return web_port_index; | 560 return web_port_index; |
496 } | 561 } |
497 | 562 |
498 MidiManagerAlsa::AlsaSeqState::AlsaSeqState() : clients_deleter_(&clients_) { | 563 MidiManagerAlsa::AlsaSeqState::AlsaSeqState() |
564 : clients_deleter_(&clients_), kernel_client_count_(0) { | |
499 } | 565 } |
500 | 566 |
501 MidiManagerAlsa::AlsaSeqState::~AlsaSeqState() { | 567 MidiManagerAlsa::AlsaSeqState::~AlsaSeqState() { |
502 } | 568 } |
503 | 569 |
504 void MidiManagerAlsa::AlsaSeqState::ClientStart(int client_id, | 570 void MidiManagerAlsa::AlsaSeqState::ClientStart(int client_id, |
505 const std::string& client_name, | 571 const std::string& client_name, |
506 snd_seq_client_type_t type) { | 572 snd_seq_client_type_t type) { |
507 ClientExit(client_id); | 573 ClientExit(client_id); |
508 clients_[client_id] = new Client(client_name, type); | 574 clients_[client_id] = new Client(client_name, type); |
575 if (IsCardKernelClient(type, client_id)) | |
576 ++kernel_client_count_; | |
509 } | 577 } |
510 | 578 |
511 bool MidiManagerAlsa::AlsaSeqState::ClientStarted(int client_id) { | 579 bool MidiManagerAlsa::AlsaSeqState::ClientStarted(int client_id) { |
512 return clients_.find(client_id) != clients_.end(); | 580 return clients_.find(client_id) != clients_.end(); |
513 } | 581 } |
514 | 582 |
515 void MidiManagerAlsa::AlsaSeqState::ClientExit(int client_id) { | 583 void MidiManagerAlsa::AlsaSeqState::ClientExit(int client_id) { |
516 auto it = clients_.find(client_id); | 584 auto it = clients_.find(client_id); |
517 if (it != clients_.end()) { | 585 if (it != clients_.end()) { |
586 if (IsCardKernelClient(it->second->type(), client_id)) | |
587 --kernel_client_count_; | |
518 delete it->second; | 588 delete it->second; |
519 clients_.erase(it); | 589 clients_.erase(it); |
520 } | 590 } |
521 } | 591 } |
522 | 592 |
523 void MidiManagerAlsa::AlsaSeqState::PortStart( | 593 void MidiManagerAlsa::AlsaSeqState::PortStart( |
524 int client_id, | 594 int client_id, |
525 int port_id, | 595 int port_id, |
526 const std::string& port_name, | 596 const std::string& port_name, |
527 MidiManagerAlsa::AlsaSeqState::PortDirection direction, | 597 MidiManagerAlsa::AlsaSeqState::PortDirection direction, |
(...skipping 12 matching lines...) Expand all Loading... | |
540 | 610 |
541 snd_seq_client_type_t MidiManagerAlsa::AlsaSeqState::ClientType( | 611 snd_seq_client_type_t MidiManagerAlsa::AlsaSeqState::ClientType( |
542 int client_id) const { | 612 int client_id) const { |
543 auto it = clients_.find(client_id); | 613 auto it = clients_.find(client_id); |
544 if (it == clients_.end()) | 614 if (it == clients_.end()) |
545 return SND_SEQ_USER_CLIENT; | 615 return SND_SEQ_USER_CLIENT; |
546 return it->second->type(); | 616 return it->second->type(); |
547 } | 617 } |
548 | 618 |
549 scoped_ptr<MidiManagerAlsa::TemporaryMidiPortState> | 619 scoped_ptr<MidiManagerAlsa::TemporaryMidiPortState> |
550 MidiManagerAlsa::AlsaSeqState::ToMidiPortState() { | 620 MidiManagerAlsa::AlsaSeqState::ToMidiPortState(const AlsaCardMap& alsa_cards) { |
551 scoped_ptr<MidiManagerAlsa::TemporaryMidiPortState> midi_ports( | 621 scoped_ptr<MidiManagerAlsa::TemporaryMidiPortState> midi_ports( |
552 new TemporaryMidiPortState); | 622 new TemporaryMidiPortState); |
553 // TODO(agoode): Use information from udev as well. | 623 // TODO(agoode): Use more information from udev, to allow hardware matching. |
624 // See http://crbug.com/486471. | |
625 auto card_it = alsa_cards.begin(); | |
554 | 626 |
627 int card_midi_device = -1; | |
555 for (const auto& client_pair : clients_) { | 628 for (const auto& client_pair : clients_) { |
556 int client_id = client_pair.first; | 629 int client_id = client_pair.first; |
557 const auto& client = client_pair.second; | 630 const auto& client = client_pair.second; |
558 | 631 |
559 // Get client metadata. | 632 // Get client metadata. |
560 const std::string client_name = client->name(); | 633 const std::string client_name = client->name(); |
561 std::string manufacturer; | 634 std::string manufacturer; |
562 std::string driver; | 635 std::string driver; |
563 std::string path; | 636 std::string path; |
564 std::string id; | 637 std::string id; |
565 std::string serial; | 638 std::string serial; |
566 std::string card_name; | 639 std::string card_name; |
567 std::string card_longname; | 640 std::string card_longname; |
568 int midi_device = -1; | 641 int midi_device = -1; |
569 | 642 |
643 if (IsCardKernelClient(client->type(), client_id)) { | |
644 auto& card = card_it->second; | |
645 if (card_midi_device == -1) | |
646 card_midi_device = 0; | |
647 | |
648 manufacturer = card->manufacturer(); | |
649 midi_device = card_midi_device; | |
650 | |
651 ++card_midi_device; | |
652 if (card_midi_device >= card->midi_device_count()) { | |
653 card_midi_device = -1; | |
654 ++card_it; | |
655 } | |
656 } | |
657 | |
570 for (const auto& port_pair : *client) { | 658 for (const auto& port_pair : *client) { |
571 int port_id = port_pair.first; | 659 int port_id = port_pair.first; |
572 const auto& port = port_pair.second; | 660 const auto& port = port_pair.second; |
573 | 661 |
574 if (port->midi()) { | 662 if (port->midi()) { |
575 std::string version; | 663 std::string version; |
576 if (!driver.empty()) { | 664 if (!driver.empty()) { |
577 version = driver + " / "; | 665 version = driver + " / "; |
578 } | 666 } |
579 version += | 667 version += |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
655 MidiManagerAlsa::AlsaSeqState::Client::PortMap::const_iterator | 743 MidiManagerAlsa::AlsaSeqState::Client::PortMap::const_iterator |
656 MidiManagerAlsa::AlsaSeqState::Client::begin() const { | 744 MidiManagerAlsa::AlsaSeqState::Client::begin() const { |
657 return ports_.begin(); | 745 return ports_.begin(); |
658 } | 746 } |
659 | 747 |
660 MidiManagerAlsa::AlsaSeqState::Client::PortMap::const_iterator | 748 MidiManagerAlsa::AlsaSeqState::Client::PortMap::const_iterator |
661 MidiManagerAlsa::AlsaSeqState::Client::end() const { | 749 MidiManagerAlsa::AlsaSeqState::Client::end() const { |
662 return ports_.end(); | 750 return ports_.end(); |
663 } | 751 } |
664 | 752 |
753 MidiManagerAlsa::AlsaCard::AlsaCard(udev_device* dev, | |
754 const std::string& alsa_name, | |
755 const std::string& alsa_longname, | |
756 const std::string& alsa_driver, | |
757 int midi_device_count) | |
758 : alsa_name_(alsa_name), | |
759 alsa_longname_(alsa_longname), | |
760 alsa_driver_(alsa_driver), | |
761 midi_device_count_(midi_device_count) { | |
762 // Try to get the vendor string. Sometimes it is encoded. | |
763 std::string vendor = device::UdevDecodeString( | |
764 device::UdevDeviceGetPropertyValue(dev, kUdevIdVendorEnc)); | |
765 // Sometimes it is not encoded. | |
766 if (vendor.empty()) | |
767 vendor = | |
768 UdevDeviceGetPropertyOrSysattr(dev, kUdevIdVendor, kSysattrVendorName); | |
769 // Also get the vendor string from the hardware database. | |
770 std::string vendor_from_database = | |
771 device::UdevDeviceGetPropertyValue(dev, kUdevIdVendorFromDatabase); | |
772 | |
773 // Get the device path. | |
774 path_ = device::UdevDeviceGetPropertyValue(dev, kUdevIdPath); | |
775 // Get the bus. | |
776 bus_ = device::UdevDeviceGetPropertyValue(dev, kUdevIdBus); | |
777 | |
778 // Get the "serial" number. (Often untrustable or missing.) | |
779 serial_ = | |
780 UdevDeviceGetPropertyOrSysattr(dev, kUdevIdSerialShort, kSysattrGuid); | |
781 | |
782 // Get the vendor id, by either property or sysattr. | |
783 vendor_id_ = | |
784 UdevDeviceGetPropertyOrSysattr(dev, kUdevIdVendorId, kSysattrVendor); | |
785 // Get the model id, by either property or sysattr. | |
786 model_id_ = | |
787 UdevDeviceGetPropertyOrSysattr(dev, kUdevIdModelId, kSysattrModel); | |
788 // Get the usb interface number. | |
789 usb_interface_num_ = | |
790 device::UdevDeviceGetPropertyValue(dev, kUdevIdUsbInterfaceNum); | |
791 manufacturer_ = ExtractManufacturerString( | |
792 vendor, vendor_id_, vendor_from_database, alsa_name, alsa_longname); | |
793 } | |
794 | |
795 MidiManagerAlsa::AlsaCard::~AlsaCard() { | |
796 } | |
797 | |
665 // static | 798 // static |
666 std::string MidiManagerAlsa::ExtractManufacturerString( | 799 std::string MidiManagerAlsa::AlsaCard::ExtractManufacturerString( |
667 const std::string& udev_id_vendor, | 800 const std::string& udev_id_vendor, |
668 const std::string& udev_id_vendor_id, | 801 const std::string& udev_id_vendor_id, |
669 const std::string& udev_id_vendor_from_database, | 802 const std::string& udev_id_vendor_from_database, |
670 const std::string& alsa_name, | 803 const std::string& alsa_name, |
671 const std::string& alsa_longname) { | 804 const std::string& alsa_longname) { |
672 // Let's try to determine the manufacturer. Here is the ordered preference | 805 // Let's try to determine the manufacturer. Here is the ordered preference |
673 // in extraction: | 806 // in extraction: |
674 // 1. Vendor name from the hardware device string, from udev properties | 807 // 1. Vendor name from the hardware device string, from udev properties |
675 // or sysattrs. | 808 // or sysattrs. |
676 // 2. Vendor name from the udev database (property ID_VENDOR_FROM_DATABASE). | 809 // 2. Vendor name from the udev database (property ID_VENDOR_FROM_DATABASE). |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
916 kUdevPropertySoundInitialized)) | 1049 kUdevPropertySoundInitialized)) |
917 return; | 1050 return; |
918 | 1051 |
919 // Get the action. If no action, then we are doing first time enumeration | 1052 // Get the action. If no action, then we are doing first time enumeration |
920 // and the device is treated as new. | 1053 // and the device is treated as new. |
921 const char* action = device::udev_device_get_action(dev); | 1054 const char* action = device::udev_device_get_action(dev); |
922 if (!action) | 1055 if (!action) |
923 action = kUdevActionChange; | 1056 action = kUdevActionChange; |
924 | 1057 |
925 if (strcmp(action, kUdevActionChange) == 0) { | 1058 if (strcmp(action, kUdevActionChange) == 0) { |
926 // TODO(agoode): add | 1059 AddCard(dev); |
1060 // Generate Web MIDI events. | |
1061 UpdatePortStateAndGenerateEvents(); | |
927 } else if (strcmp(action, kUdevActionRemove) == 0) { | 1062 } else if (strcmp(action, kUdevActionRemove) == 0) { |
928 // TODO(agoode): remove | 1063 RemoveCard(GetCardNumber(dev)); |
1064 // Generate Web MIDI events. | |
1065 UpdatePortStateAndGenerateEvents(); | |
929 } | 1066 } |
930 } | 1067 } |
931 | 1068 |
1069 void MidiManagerAlsa::AddCard(udev_device* dev) { | |
1070 int number = GetCardNumber(dev); | |
1071 if (number == -1) | |
1072 return; | |
1073 | |
1074 RemoveCard(number); | |
1075 | |
1076 snd_ctl_card_info_t* card; | |
1077 snd_hwdep_info_t* hwdep; | |
1078 snd_ctl_card_info_alloca(&card); | |
1079 snd_hwdep_info_alloca(&hwdep); | |
1080 const std::string id = base::StringPrintf("hw:CARD=%i", number); | |
1081 snd_ctl_t* handle; | |
1082 int err = snd_ctl_open(&handle, id.c_str(), 0); | |
1083 if (err != 0) { | |
1084 VLOG(1) << "snd_ctl_open fails: " << snd_strerror(err); | |
1085 return; | |
1086 } | |
1087 err = snd_ctl_card_info(handle, card); | |
1088 if (err != 0) { | |
1089 VLOG(1) << "snd_ctl_card_info fails: " << snd_strerror(err); | |
1090 snd_ctl_close(handle); | |
1091 return; | |
1092 } | |
1093 std::string name = snd_ctl_card_info_get_name(card); | |
1094 std::string longname = snd_ctl_card_info_get_longname(card); | |
1095 std::string driver = snd_ctl_card_info_get_driver(card); | |
1096 | |
1097 // Count rawmidi devices (not subdevices). | |
1098 int midi_count = 0; | |
1099 for (int device = -1; | |
1100 !snd_ctl_rawmidi_next_device(handle, &device) && device >= 0;) | |
1101 ++midi_count; | |
1102 | |
1103 // Count any hwdep synths that become MIDI devices outside of rawmidi. | |
1104 // | |
1105 // Explanation: | |
1106 // Any kernel driver can create an ALSA client (visible to us). | |
1107 // With modern hardware, only rawmidi devices do this. Kernel | |
1108 // drivers create rawmidi devices and the rawmidi subsystem makes | |
1109 // the seq clients. But the OPL3 driver is special, it does not | |
1110 // make a rawmidi device but a seq client directly. (This is the | |
1111 // only one to worry about in the kernel code, as of 2015-03-23.) | |
1112 // | |
1113 // OPL3 is very old (but still possible to get in new | |
1114 // hardware). It is unlikely that new drivers would not use | |
1115 // rawmidi and defeat our heuristic. | |
1116 // | |
1117 // Longer term, support should be added in the kernel to expose a | |
1118 // direct link from card->client (or client->card) so that all | |
1119 // these heuristics will be obsolete. Once that is there, we can | |
1120 // assume our old heuristics will work on old kernels and the new | |
1121 // robust code will be used on new. Then we will not need to worry | |
1122 // about changes to kernel internals breaking our code. | |
1123 // See the TODO above at kMinimumClientIdForCards. | |
1124 for (int device = -1; | |
1125 !snd_ctl_hwdep_next_device(handle, &device) && device >= 0;) { | |
1126 err = snd_ctl_hwdep_info(handle, hwdep); | |
1127 if (err != 0) { | |
1128 VLOG(1) << "snd_ctl_hwdep_info fails: " << snd_strerror(err); | |
1129 continue; | |
1130 } | |
1131 snd_hwdep_iface_t iface = snd_hwdep_info_get_iface(hwdep); | |
1132 if (iface == SND_HWDEP_IFACE_OPL2 || iface == SND_HWDEP_IFACE_OPL3 || | |
1133 iface == SND_HWDEP_IFACE_OPL4) | |
1134 ++midi_count; | |
1135 } | |
1136 snd_ctl_close(handle); | |
1137 | |
1138 if (midi_count > 0) | |
1139 alsa_cards_[number] = new AlsaCard(dev, name, longname, driver, midi_count); | |
1140 alsa_card_midi_count_ += midi_count; | |
1141 } | |
1142 | |
1143 void MidiManagerAlsa::RemoveCard(int number) { | |
1144 auto it = alsa_cards_.find(number); | |
1145 if (it == alsa_cards_.end()) | |
1146 return; | |
1147 | |
1148 alsa_card_midi_count_ -= it->second->midi_device_count(); | |
1149 delete it->second; | |
1150 alsa_cards_.erase(it); | |
1151 } | |
1152 | |
932 void MidiManagerAlsa::UpdatePortStateAndGenerateEvents() { | 1153 void MidiManagerAlsa::UpdatePortStateAndGenerateEvents() { |
1154 if (alsa_card_midi_count_ != alsa_seq_state_.kernel_client_count()) | |
Takashi Toyoshima
2015/05/11 12:32:04
Can you add some comments to know what this check
Adam Goode
2015/05/11 15:17:25
Yes. I also renamed the variables to be more clear
| |
1155 return; | |
1156 | |
933 // Generate new port state. | 1157 // Generate new port state. |
934 auto new_port_state = alsa_seq_state_.ToMidiPortState(); | 1158 auto new_port_state = alsa_seq_state_.ToMidiPortState(alsa_cards_); |
935 | 1159 |
936 // Disconnect any connected old ports that are now missing. | 1160 // Disconnect any connected old ports that are now missing. |
937 for (auto* old_port : port_state_) { | 1161 for (auto* old_port : port_state_) { |
938 if (old_port->connected() && | 1162 if (old_port->connected() && |
939 (new_port_state->FindConnected(*old_port) == new_port_state->end())) { | 1163 (new_port_state->FindConnected(*old_port) == new_port_state->end())) { |
940 old_port->set_connected(false); | 1164 old_port->set_connected(false); |
941 uint32 web_port_index = old_port->web_port_index(); | 1165 uint32 web_port_index = old_port->web_port_index(); |
942 switch (old_port->type()) { | 1166 switch (old_port->type()) { |
943 case MidiPort::Type::kInput: | 1167 case MidiPort::Type::kInput: |
944 source_map_.erase( | 1168 source_map_.erase( |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1132 source_map_[AddrToInt(client_id, port_id)] = port_index; | 1356 source_map_[AddrToInt(client_id, port_id)] = port_index; |
1133 return true; | 1357 return true; |
1134 } | 1358 } |
1135 | 1359 |
1136 MidiManager* MidiManager::Create() { | 1360 MidiManager* MidiManager::Create() { |
1137 return new MidiManagerAlsa(); | 1361 return new MidiManagerAlsa(); |
1138 } | 1362 } |
1139 | 1363 |
1140 } // namespace midi | 1364 } // namespace midi |
1141 } // namespace media | 1365 } // namespace media |
OLD | NEW |