| // Copyright 2017 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "midis/device_tracker.h" |
| |
| #include <fcntl.h> |
| |
| #include <memory> |
| #include <utility> |
| |
| #include <base/bind.h> |
| #include <base/location.h> |
| |
| #include "midis/seq_handler.h" |
| |
| namespace midis { |
| |
| DeviceTracker::DeviceTracker() {} |
| |
| bool DeviceTracker::InitDeviceTracker() { |
| seq_handler_ = std::make_unique<SeqHandler>( |
| base::Bind(&DeviceTracker::AddDevice, base::Unretained(this)), |
| base::Bind(&DeviceTracker::RemoveDevice, base::Unretained(this)), |
| base::Bind(&DeviceTracker::HandleReceiveData, base::Unretained(this)), |
| base::Bind(&DeviceTracker::IsDevicePresent, base::Unretained(this)), |
| base::Bind(&DeviceTracker::IsPortPresent, base::Unretained(this))); |
| |
| if (!seq_handler_->InitSeq()) { |
| LOG(ERROR) << "Failed to start snd_seq tracker."; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| void DeviceTracker::AddDevice(std::unique_ptr<Device> dev) { |
| uint32_t device_id = GenerateDeviceId(dev->GetCard(), dev->GetDeviceNum()); |
| devices_.emplace(device_id, std::move(dev)); |
| NotifyObserversDeviceAddedOrRemoved(*devices_.at(device_id), true); |
| } |
| |
| void DeviceTracker::RemoveDevice(uint32_t sys_num, uint32_t dev_num) { |
| auto it = devices_.find(GenerateDeviceId(sys_num, dev_num)); |
| if (it != devices_.end()) { |
| NotifyObserversDeviceAddedOrRemoved(*it->second, false); |
| devices_.erase(it); |
| LOG(INFO) << "Device: " << sys_num << "," << dev_num << " removed."; |
| } else { |
| LOG(ERROR) << "Device: " << sys_num << "," << dev_num << " not listed."; |
| } |
| } |
| |
| void DeviceTracker::ListDevices( |
| std::vector<arc::mojom::MidisDeviceInfoPtr>* list) { |
| for (const auto& dev : devices_) { |
| arc::mojom::MidisDeviceInfoPtr dev_info = |
| arc::mojom::MidisDeviceInfo::New(); |
| dev_info->card = dev.second->GetCard(); |
| dev_info->device_num = dev.second->GetDeviceNum(); |
| dev_info->num_subdevices = dev.second->GetNumSubdevices(); |
| dev_info->name = dev.second->GetName(); |
| dev_info->manufacturer = dev.second->GetManufacturer(); |
| list->emplace_back(std::move(dev_info)); |
| } |
| } |
| |
| void DeviceTracker::AddDeviceObserver(Observer* obs) { |
| observer_list_.AddObserver(obs); |
| } |
| |
| void DeviceTracker::RemoveDeviceObserver(Observer* obs) { |
| observer_list_.RemoveObserver(obs); |
| } |
| |
| void DeviceTracker::NotifyObserversDeviceAddedOrRemoved(const Device& dev, |
| bool added) { |
| for (Observer& observer : observer_list_) |
| observer.OnDeviceAddedOrRemoved(dev, added); |
| } |
| |
| base::ScopedFD DeviceTracker::AddClientToReadSubdevice(uint32_t sys_num, |
| uint32_t device_num, |
| uint32_t subdevice_num, |
| uint32_t client_id) { |
| Device* device = FindDevice(sys_num, device_num); |
| if (device) { |
| return device->AddClientToReadSubdevice(client_id, subdevice_num); |
| } |
| return base::ScopedFD(); |
| } |
| |
| void DeviceTracker::RemoveClientFromDevice(uint32_t client_id, |
| uint32_t sys_num, |
| uint32_t device_num) { |
| Device* device = FindDevice(sys_num, device_num); |
| if (device) { |
| device->RemoveClientFromDevice(client_id); |
| } |
| } |
| |
| void DeviceTracker::RemoveClientFromDevices(uint32_t client_id) { |
| for (auto& id_device_pair : devices_) { |
| id_device_pair.second->RemoveClientFromDevice(client_id); |
| } |
| } |
| |
| void DeviceTracker::HandleReceiveData(uint32_t card_id, |
| uint32_t device_id, |
| uint32_t port_id, |
| const char* buffer, |
| size_t buf_len) { |
| Device* device = FindDevice(card_id, device_id); |
| if (device) { |
| device->HandleReceiveData(buffer, port_id, buf_len); |
| } |
| } |
| |
| bool DeviceTracker::IsDevicePresent(uint32_t card_id, uint32_t device_id) { |
| Device* device = FindDevice(card_id, device_id); |
| if (device) { |
| return true; |
| } |
| return false; |
| } |
| |
| bool DeviceTracker::IsPortPresent(uint32_t card_id, |
| uint32_t device_id, |
| uint32_t port_id) { |
| Device* device = FindDevice(card_id, device_id); |
| if (!device) { |
| return false; |
| } |
| |
| // TODO(pmalani): Check |port_caps_| instead. |
| if (port_id >= device->GetNumSubdevices()) { |
| return false; |
| } |
| return true; |
| } |
| |
| Device* DeviceTracker::FindDevice(uint32_t card_id, uint32_t device_id) const { |
| auto it = devices_.find(GenerateDeviceId(card_id, device_id)); |
| if (it != devices_.end()) { |
| return it->second.get(); |
| } |
| return nullptr; |
| } |
| |
| } // namespace midis |