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> |
| 11 |
11 #include <algorithm> | 12 #include <algorithm> |
12 #include <string> | 13 #include <string> |
13 #include <utility> | 14 #include <utility> |
14 | 15 |
15 #include "base/bind.h" | 16 #include "base/bind.h" |
16 #include "base/json/json_string_value_serializer.h" | 17 #include "base/json/json_string_value_serializer.h" |
17 #include "base/logging.h" | 18 #include "base/logging.h" |
18 #include "base/macros.h" | 19 #include "base/macros.h" |
| 20 #include "base/memory/ptr_util.h" |
19 #include "base/message_loop/message_loop.h" | 21 #include "base/message_loop/message_loop.h" |
20 #include "base/posix/eintr_wrapper.h" | 22 #include "base/posix/eintr_wrapper.h" |
21 #include "base/posix/safe_strerror.h" | 23 #include "base/posix/safe_strerror.h" |
22 #include "base/strings/string_number_conversions.h" | 24 #include "base/strings/string_number_conversions.h" |
23 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
24 #include "base/time/time.h" | 26 #include "base/time/time.h" |
25 #include "crypto/sha2.h" | 27 #include "crypto/sha2.h" |
26 #include "media/midi/midi_port_info.h" | 28 #include "media/midi/midi_port_info.h" |
27 | 29 |
28 namespace media { | 30 namespace media { |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 port_id_(port_id), | 392 port_id_(port_id), |
391 client_name_(client_name), | 393 client_name_(client_name), |
392 port_name_(port_name), | 394 port_name_(port_name), |
393 manufacturer_(manufacturer), | 395 manufacturer_(manufacturer), |
394 version_(version) { | 396 version_(version) { |
395 } | 397 } |
396 | 398 |
397 MidiManagerAlsa::MidiPort::~MidiPort() = default; | 399 MidiManagerAlsa::MidiPort::~MidiPort() = default; |
398 | 400 |
399 // Note: keep synchronized with the MidiPort::Match* methods. | 401 // Note: keep synchronized with the MidiPort::Match* methods. |
400 scoped_ptr<base::Value> MidiManagerAlsa::MidiPort::Value() const { | 402 std::unique_ptr<base::Value> MidiManagerAlsa::MidiPort::Value() const { |
401 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue); | 403 std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue); |
402 | 404 |
403 std::string type; | 405 std::string type; |
404 switch (type_) { | 406 switch (type_) { |
405 case Type::kInput: | 407 case Type::kInput: |
406 type = "input"; | 408 type = "input"; |
407 break; | 409 break; |
408 case Type::kOutput: | 410 case Type::kOutput: |
409 type = "output"; | 411 type = "output"; |
410 break; | 412 break; |
411 } | 413 } |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 auto result = FindConnected(port); | 527 auto result = FindConnected(port); |
526 if (result == end()) | 528 if (result == end()) |
527 result = FindDisconnected(port); | 529 result = FindDisconnected(port); |
528 return result; | 530 return result; |
529 } | 531 } |
530 | 532 |
531 MidiManagerAlsa::MidiPortStateBase::iterator | 533 MidiManagerAlsa::MidiPortStateBase::iterator |
532 MidiManagerAlsa::MidiPortStateBase::FindConnected( | 534 MidiManagerAlsa::MidiPortStateBase::FindConnected( |
533 const MidiManagerAlsa::MidiPort& port) { | 535 const MidiManagerAlsa::MidiPort& port) { |
534 // Exact match required for connected ports. | 536 // Exact match required for connected ports. |
535 auto it = std::find_if( | 537 auto it = std::find_if(ports_.begin(), ports_.end(), |
536 ports_.begin(), ports_.end(), | 538 [&port](std::unique_ptr<MidiPort>& p) { |
537 [&port](scoped_ptr<MidiPort>& p) { return p->MatchConnected(port); }); | 539 return p->MatchConnected(port); |
| 540 }); |
538 return it; | 541 return it; |
539 } | 542 } |
540 | 543 |
541 MidiManagerAlsa::MidiPortStateBase::iterator | 544 MidiManagerAlsa::MidiPortStateBase::iterator |
542 MidiManagerAlsa::MidiPortStateBase::FindDisconnected( | 545 MidiManagerAlsa::MidiPortStateBase::FindDisconnected( |
543 const MidiManagerAlsa::MidiPort& port) { | 546 const MidiManagerAlsa::MidiPort& port) { |
544 // Always match on: | 547 // Always match on: |
545 // type | 548 // type |
546 // Possible things to match on: | 549 // Possible things to match on: |
547 // path | 550 // path |
548 // id | 551 // id |
549 // client_id | 552 // client_id |
550 // port_id | 553 // port_id |
551 // midi_device | 554 // midi_device |
552 // client_name | 555 // client_name |
553 // port_name | 556 // port_name |
554 | 557 |
555 if (!port.path().empty()) { | 558 if (!port.path().empty()) { |
556 // If path is present, then we have a card-based client. | 559 // If path is present, then we have a card-based client. |
557 | 560 |
558 // Pass 1. Match on path, id, midi_device, port_id. | 561 // Pass 1. Match on path, id, midi_device, port_id. |
559 // This is the best possible match for hardware card-based clients. | 562 // This is the best possible match for hardware card-based clients. |
560 // This will also match the empty id correctly for devices without an id. | 563 // This will also match the empty id correctly for devices without an id. |
561 auto it = std::find_if( | 564 auto it = std::find_if(ports_.begin(), ports_.end(), |
562 ports_.begin(), ports_.end(), | 565 [&port](std::unique_ptr<MidiPort>& p) { |
563 [&port](scoped_ptr<MidiPort>& p) { return p->MatchCardPass1(port); }); | 566 return p->MatchCardPass1(port); |
| 567 }); |
564 if (it != ports_.end()) | 568 if (it != ports_.end()) |
565 return it; | 569 return it; |
566 | 570 |
567 if (!port.id().empty()) { | 571 if (!port.id().empty()) { |
568 // Pass 2. Match on id, midi_device, port_id. | 572 // Pass 2. Match on id, midi_device, port_id. |
569 // This will give us a high-confidence match when a user moves a device to | 573 // This will give us a high-confidence match when a user moves a device to |
570 // another USB/Firewire/Thunderbolt/etc port, but only works if the device | 574 // another USB/Firewire/Thunderbolt/etc port, but only works if the device |
571 // has a hardware id. | 575 // has a hardware id. |
572 it = std::find_if( | 576 it = std::find_if(ports_.begin(), ports_.end(), |
573 ports_.begin(), ports_.end(), | 577 [&port](std::unique_ptr<MidiPort>& p) { |
574 [&port](scoped_ptr<MidiPort>& p) { return p->MatchCardPass2(port); }); | 578 return p->MatchCardPass2(port); |
| 579 }); |
575 if (it != ports_.end()) | 580 if (it != ports_.end()) |
576 return it; | 581 return it; |
577 } | 582 } |
578 } else { | 583 } else { |
579 // Else, we have a non-card-based client. | 584 // Else, we have a non-card-based client. |
580 // Pass 1. Match on client_id, port_id, client_name, port_name. | 585 // Pass 1. Match on client_id, port_id, client_name, port_name. |
581 // This will give us a reasonably good match. | 586 // This will give us a reasonably good match. |
582 auto it = std::find_if( | 587 auto it = std::find_if(ports_.begin(), ports_.end(), |
583 ports_.begin(), ports_.end(), | 588 [&port](std::unique_ptr<MidiPort>& p) { |
584 [&port](scoped_ptr<MidiPort>& p) { return p->MatchNoCardPass1(port); }); | 589 return p->MatchNoCardPass1(port); |
| 590 }); |
585 if (it != ports_.end()) | 591 if (it != ports_.end()) |
586 return it; | 592 return it; |
587 | 593 |
588 // Pass 2. Match on port_id, client_name, port_name. | 594 // Pass 2. Match on port_id, client_name, port_name. |
589 // This is weaker but similar to pass 2 in the hardware card-based clients | 595 // This is weaker but similar to pass 2 in the hardware card-based clients |
590 // match. | 596 // match. |
591 it = std::find_if( | 597 it = std::find_if(ports_.begin(), ports_.end(), |
592 ports_.begin(), ports_.end(), | 598 [&port](std::unique_ptr<MidiPort>& p) { |
593 [&port](scoped_ptr<MidiPort>& p) { return p->MatchNoCardPass2(port); }); | 599 return p->MatchNoCardPass2(port); |
| 600 }); |
594 if (it != ports_.end()) | 601 if (it != ports_.end()) |
595 return it; | 602 return it; |
596 } | 603 } |
597 | 604 |
598 // No match. | 605 // No match. |
599 return ports_.end(); | 606 return ports_.end(); |
600 } | 607 } |
601 | 608 |
602 MidiManagerAlsa::MidiPortStateBase::MidiPortStateBase() = default; | 609 MidiManagerAlsa::MidiPortStateBase::MidiPortStateBase() = default; |
603 | 610 |
604 MidiManagerAlsa::MidiPortState::MidiPortState() = default; | 611 MidiManagerAlsa::MidiPortState::MidiPortState() = default; |
605 | 612 |
606 uint32_t MidiManagerAlsa::MidiPortState::push_back(scoped_ptr<MidiPort> port) { | 613 uint32_t MidiManagerAlsa::MidiPortState::push_back( |
| 614 std::unique_ptr<MidiPort> port) { |
607 // Add the web midi index. | 615 // Add the web midi index. |
608 uint32_t web_port_index = 0; | 616 uint32_t web_port_index = 0; |
609 switch (port->type()) { | 617 switch (port->type()) { |
610 case MidiPort::Type::kInput: | 618 case MidiPort::Type::kInput: |
611 web_port_index = num_input_ports_++; | 619 web_port_index = num_input_ports_++; |
612 break; | 620 break; |
613 case MidiPort::Type::kOutput: | 621 case MidiPort::Type::kOutput: |
614 web_port_index = num_output_ports_++; | 622 web_port_index = num_output_ports_++; |
615 break; | 623 break; |
616 } | 624 } |
617 port->set_web_port_index(web_port_index); | 625 port->set_web_port_index(web_port_index); |
618 MidiPortStateBase::push_back(std::move(port)); | 626 MidiPortStateBase::push_back(std::move(port)); |
619 return web_port_index; | 627 return web_port_index; |
620 } | 628 } |
621 | 629 |
622 MidiManagerAlsa::AlsaSeqState::AlsaSeqState() = default; | 630 MidiManagerAlsa::AlsaSeqState::AlsaSeqState() = default; |
623 | 631 |
624 MidiManagerAlsa::AlsaSeqState::~AlsaSeqState() = default; | 632 MidiManagerAlsa::AlsaSeqState::~AlsaSeqState() = default; |
625 | 633 |
626 void MidiManagerAlsa::AlsaSeqState::ClientStart(int client_id, | 634 void MidiManagerAlsa::AlsaSeqState::ClientStart(int client_id, |
627 const std::string& client_name, | 635 const std::string& client_name, |
628 snd_seq_client_type_t type) { | 636 snd_seq_client_type_t type) { |
629 ClientExit(client_id); | 637 ClientExit(client_id); |
630 clients_.insert(std::make_pair( | 638 clients_.insert(std::make_pair( |
631 client_id, make_scoped_ptr(new Client(client_name, type)))); | 639 client_id, base::WrapUnique(new Client(client_name, type)))); |
632 if (IsCardClient(type, client_id)) | 640 if (IsCardClient(type, client_id)) |
633 ++card_client_count_; | 641 ++card_client_count_; |
634 } | 642 } |
635 | 643 |
636 bool MidiManagerAlsa::AlsaSeqState::ClientStarted(int client_id) { | 644 bool MidiManagerAlsa::AlsaSeqState::ClientStarted(int client_id) { |
637 return clients_.find(client_id) != clients_.end(); | 645 return clients_.find(client_id) != clients_.end(); |
638 } | 646 } |
639 | 647 |
640 void MidiManagerAlsa::AlsaSeqState::ClientExit(int client_id) { | 648 void MidiManagerAlsa::AlsaSeqState::ClientExit(int client_id) { |
641 auto it = clients_.find(client_id); | 649 auto it = clients_.find(client_id); |
642 if (it != clients_.end()) { | 650 if (it != clients_.end()) { |
643 if (IsCardClient(it->second->type(), client_id)) | 651 if (IsCardClient(it->second->type(), client_id)) |
644 --card_client_count_; | 652 --card_client_count_; |
645 clients_.erase(it); | 653 clients_.erase(it); |
646 } | 654 } |
647 } | 655 } |
648 | 656 |
649 void MidiManagerAlsa::AlsaSeqState::PortStart( | 657 void MidiManagerAlsa::AlsaSeqState::PortStart( |
650 int client_id, | 658 int client_id, |
651 int port_id, | 659 int port_id, |
652 const std::string& port_name, | 660 const std::string& port_name, |
653 MidiManagerAlsa::AlsaSeqState::PortDirection direction, | 661 MidiManagerAlsa::AlsaSeqState::PortDirection direction, |
654 bool midi) { | 662 bool midi) { |
655 auto it = clients_.find(client_id); | 663 auto it = clients_.find(client_id); |
656 if (it != clients_.end()) | 664 if (it != clients_.end()) |
657 it->second->AddPort(port_id, | 665 it->second->AddPort(port_id, |
658 make_scoped_ptr(new Port(port_name, direction, midi))); | 666 base::WrapUnique(new Port(port_name, direction, midi))); |
659 } | 667 } |
660 | 668 |
661 void MidiManagerAlsa::AlsaSeqState::PortExit(int client_id, int port_id) { | 669 void MidiManagerAlsa::AlsaSeqState::PortExit(int client_id, int port_id) { |
662 auto it = clients_.find(client_id); | 670 auto it = clients_.find(client_id); |
663 if (it != clients_.end()) | 671 if (it != clients_.end()) |
664 it->second->RemovePort(port_id); | 672 it->second->RemovePort(port_id); |
665 } | 673 } |
666 | 674 |
667 snd_seq_client_type_t MidiManagerAlsa::AlsaSeqState::ClientType( | 675 snd_seq_client_type_t MidiManagerAlsa::AlsaSeqState::ClientType( |
668 int client_id) const { | 676 int client_id) const { |
669 auto it = clients_.find(client_id); | 677 auto it = clients_.find(client_id); |
670 if (it == clients_.end()) | 678 if (it == clients_.end()) |
671 return SND_SEQ_USER_CLIENT; | 679 return SND_SEQ_USER_CLIENT; |
672 return it->second->type(); | 680 return it->second->type(); |
673 } | 681 } |
674 | 682 |
675 scoped_ptr<MidiManagerAlsa::TemporaryMidiPortState> | 683 std::unique_ptr<MidiManagerAlsa::TemporaryMidiPortState> |
676 MidiManagerAlsa::AlsaSeqState::ToMidiPortState(const AlsaCardMap& alsa_cards) { | 684 MidiManagerAlsa::AlsaSeqState::ToMidiPortState(const AlsaCardMap& alsa_cards) { |
677 scoped_ptr<MidiManagerAlsa::TemporaryMidiPortState> midi_ports( | 685 std::unique_ptr<MidiManagerAlsa::TemporaryMidiPortState> midi_ports( |
678 new TemporaryMidiPortState); | 686 new TemporaryMidiPortState); |
679 auto card_it = alsa_cards.begin(); | 687 auto card_it = alsa_cards.begin(); |
680 | 688 |
681 int card_midi_device = -1; | 689 int card_midi_device = -1; |
682 for (const auto& client_pair : clients_) { | 690 for (const auto& client_pair : clients_) { |
683 int client_id = client_pair.first; | 691 int client_id = client_pair.first; |
684 const auto& client = client_pair.second.get(); | 692 const auto& client = client_pair.second.get(); |
685 | 693 |
686 // Get client metadata. | 694 // Get client metadata. |
687 const std::string client_name = client->name(); | 695 const std::string client_name = client->name(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
721 std::string version; | 729 std::string version; |
722 if (!driver.empty()) { | 730 if (!driver.empty()) { |
723 version = driver + " / "; | 731 version = driver + " / "; |
724 } | 732 } |
725 version += | 733 version += |
726 base::StringPrintf("ALSA library version %d.%d.%d", SND_LIB_MAJOR, | 734 base::StringPrintf("ALSA library version %d.%d.%d", SND_LIB_MAJOR, |
727 SND_LIB_MINOR, SND_LIB_SUBMINOR); | 735 SND_LIB_MINOR, SND_LIB_SUBMINOR); |
728 PortDirection direction = port->direction(); | 736 PortDirection direction = port->direction(); |
729 if (direction == PortDirection::kInput || | 737 if (direction == PortDirection::kInput || |
730 direction == PortDirection::kDuplex) { | 738 direction == PortDirection::kDuplex) { |
731 midi_ports->push_back(make_scoped_ptr(new MidiPort( | 739 midi_ports->push_back(base::WrapUnique(new MidiPort( |
732 path, id, client_id, port_id, midi_device, client->name(), | 740 path, id, client_id, port_id, midi_device, client->name(), |
733 port->name(), manufacturer, version, MidiPort::Type::kInput))); | 741 port->name(), manufacturer, version, MidiPort::Type::kInput))); |
734 } | 742 } |
735 if (direction == PortDirection::kOutput || | 743 if (direction == PortDirection::kOutput || |
736 direction == PortDirection::kDuplex) { | 744 direction == PortDirection::kDuplex) { |
737 midi_ports->push_back(make_scoped_ptr(new MidiPort( | 745 midi_ports->push_back(base::WrapUnique(new MidiPort( |
738 path, id, client_id, port_id, midi_device, client->name(), | 746 path, id, client_id, port_id, midi_device, client->name(), |
739 port->name(), manufacturer, version, MidiPort::Type::kOutput))); | 747 port->name(), manufacturer, version, MidiPort::Type::kOutput))); |
740 } | 748 } |
741 } | 749 } |
742 } | 750 } |
743 } | 751 } |
744 | 752 |
745 return midi_ports; | 753 return midi_ports; |
746 } | 754 } |
747 | 755 |
748 MidiManagerAlsa::AlsaSeqState::Port::Port( | 756 MidiManagerAlsa::AlsaSeqState::Port::Port( |
749 const std::string& name, | 757 const std::string& name, |
750 MidiManagerAlsa::AlsaSeqState::PortDirection direction, | 758 MidiManagerAlsa::AlsaSeqState::PortDirection direction, |
751 bool midi) | 759 bool midi) |
752 : name_(name), direction_(direction), midi_(midi) { | 760 : name_(name), direction_(direction), midi_(midi) { |
753 } | 761 } |
754 | 762 |
755 MidiManagerAlsa::AlsaSeqState::Port::~Port() = default; | 763 MidiManagerAlsa::AlsaSeqState::Port::~Port() = default; |
756 | 764 |
757 MidiManagerAlsa::AlsaSeqState::Client::Client(const std::string& name, | 765 MidiManagerAlsa::AlsaSeqState::Client::Client(const std::string& name, |
758 snd_seq_client_type_t type) | 766 snd_seq_client_type_t type) |
759 : name_(name), type_(type) { | 767 : name_(name), type_(type) { |
760 } | 768 } |
761 | 769 |
762 MidiManagerAlsa::AlsaSeqState::Client::~Client() = default; | 770 MidiManagerAlsa::AlsaSeqState::Client::~Client() = default; |
763 | 771 |
764 void MidiManagerAlsa::AlsaSeqState::Client::AddPort(int addr, | 772 void MidiManagerAlsa::AlsaSeqState::Client::AddPort( |
765 scoped_ptr<Port> port) { | 773 int addr, |
| 774 std::unique_ptr<Port> port) { |
766 ports_[addr] = std::move(port); | 775 ports_[addr] = std::move(port); |
767 } | 776 } |
768 | 777 |
769 void MidiManagerAlsa::AlsaSeqState::Client::RemovePort(int addr) { | 778 void MidiManagerAlsa::AlsaSeqState::Client::RemovePort(int addr) { |
770 ports_.erase(addr); | 779 ports_.erase(addr); |
771 } | 780 } |
772 | 781 |
773 MidiManagerAlsa::AlsaSeqState::Client::PortMap::const_iterator | 782 MidiManagerAlsa::AlsaSeqState::Client::PortMap::const_iterator |
774 MidiManagerAlsa::AlsaSeqState::Client::begin() const { | 783 MidiManagerAlsa::AlsaSeqState::Client::begin() const { |
775 return ports_.begin(); | 784 return ports_.begin(); |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1146 continue; | 1155 continue; |
1147 } | 1156 } |
1148 snd_hwdep_iface_t iface = snd_hwdep_info_get_iface(hwdep); | 1157 snd_hwdep_iface_t iface = snd_hwdep_info_get_iface(hwdep); |
1149 if (iface == SND_HWDEP_IFACE_OPL2 || iface == SND_HWDEP_IFACE_OPL3 || | 1158 if (iface == SND_HWDEP_IFACE_OPL2 || iface == SND_HWDEP_IFACE_OPL3 || |
1150 iface == SND_HWDEP_IFACE_OPL4) | 1159 iface == SND_HWDEP_IFACE_OPL4) |
1151 ++midi_count; | 1160 ++midi_count; |
1152 } | 1161 } |
1153 snd_ctl_close(handle); | 1162 snd_ctl_close(handle); |
1154 | 1163 |
1155 if (midi_count > 0) { | 1164 if (midi_count > 0) { |
1156 scoped_ptr<AlsaCard> card( | 1165 std::unique_ptr<AlsaCard> card( |
1157 new AlsaCard(dev, name, longname, driver, midi_count)); | 1166 new AlsaCard(dev, name, longname, driver, midi_count)); |
1158 alsa_cards_.insert(std::make_pair(number, std::move(card))); | 1167 alsa_cards_.insert(std::make_pair(number, std::move(card))); |
1159 alsa_card_midi_count_ += midi_count; | 1168 alsa_card_midi_count_ += midi_count; |
1160 } | 1169 } |
1161 } | 1170 } |
1162 | 1171 |
1163 void MidiManagerAlsa::RemoveCard(int number) { | 1172 void MidiManagerAlsa::RemoveCard(int number) { |
1164 auto it = alsa_cards_.find(number); | 1173 auto it = alsa_cards_.find(number); |
1165 if (it == alsa_cards_.end()) | 1174 if (it == alsa_cards_.end()) |
1166 return; | 1175 return; |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1385 source_map_[AddrToInt(client_id, port_id)] = port_index; | 1394 source_map_[AddrToInt(client_id, port_id)] = port_index; |
1386 return true; | 1395 return true; |
1387 } | 1396 } |
1388 | 1397 |
1389 MidiManager* MidiManager::Create() { | 1398 MidiManager* MidiManager::Create() { |
1390 return new MidiManagerAlsa(); | 1399 return new MidiManagerAlsa(); |
1391 } | 1400 } |
1392 | 1401 |
1393 } // namespace midi | 1402 } // namespace midi |
1394 } // namespace media | 1403 } // namespace media |
OLD | NEW |