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

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

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