/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * devicemanager.cpp * Implementation of the device manager, this object tracks what devices are in * use. * Copyright (C) 2005-2009 Simon Newton */ #include #include #include #include #include #include "ola/Logging.h" #include "ola/StringUtils.h" #include "olad/Port.h" #include "olad/PortManager.h" #include "olad/DeviceManager.h" namespace ola { const unsigned int DeviceManager::MISSING_DEVICE_ALIAS = 0; const char DeviceManager::PORT_PREFERENCES[] = "port"; const char DeviceManager::PRIORITY_VALUE_SUFFIX[] = "_priority_value"; const char DeviceManager::PRIORITY_MODE_SUFFIX[] = "_priority_mode"; bool operator <(const device_alias_pair& left, const device_alias_pair &right) { if (left.alias < right.alias) return true; return false; } /* * Constructor */ DeviceManager::DeviceManager(PreferencesFactory *prefs_factory, PortManager *port_manager) : m_port_preferences(NULL), m_port_manager(port_manager), m_next_device_alias(FIRST_DEVICE_ALIAS) { if (prefs_factory) { m_port_preferences = prefs_factory->NewPreference(PORT_PREFERENCES); m_port_preferences->Load(); } } /* * Cleanup */ DeviceManager::~DeviceManager() { if (m_port_preferences) m_port_preferences->Save(); } /* * Register a device * @param device pointer to the device to register * @return true on success, false on failure */ bool DeviceManager::RegisterDevice(AbstractDevice *device) { if (!device) return false; string device_id = device->UniqueId(); if (device_id.empty()) { OLA_WARN << "Device: " << device->Name() << " is missing UniqueId"; return false; } unsigned int alias; map::iterator iter = m_devices.find(device_id); if (iter != m_devices.end()) { if (iter->second.device) { // already registered OLA_INFO << "Device " << device_id << " is already registered"; return false; } else { // was previously registered, reuse alias alias = iter->second.alias; iter->second.device = device; } } else { alias = m_next_device_alias++; device_alias_pair pair; pair.alias = alias; pair.device = device; m_devices[device_id] = pair; } m_alias_map[alias] = device; OLA_INFO << "Installed device: " << device->Name() << ":" << device->UniqueId(); RestoreDevicePortSettings(device); return true; } /* * Unregister a device * @param device_id the id of the device to remove * @return true on sucess, false on failure */ bool DeviceManager::UnregisterDevice(const string &device_id) { map::iterator iter = m_devices.find(device_id); if (iter == m_devices.end() || !iter->second.device) { OLA_WARN << "Device " << device_id << "not found"; return false; } SaveDevicePortSettings(iter->second.device); map::iterator alias_iter = m_alias_map.find(iter->second.alias); if (alias_iter != m_alias_map.end()) m_alias_map.erase(alias_iter); iter->second.device = NULL; return true; } /* * Unregister a Device * @param device a pointer to the device * @return true on sucess, false on failure */ bool DeviceManager::UnregisterDevice(const AbstractDevice *device) { if (!device) return false; string device_id = device->UniqueId(); if (device_id.empty()) return false; return UnregisterDevice(device_id); } /* * Return the number of active devices * @return the number of active devices */ unsigned int DeviceManager::DeviceCount() const { unsigned int count = 0; map::const_iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) if (iter->second.device) count++; return count; } /* * Return a list of all the devices * @return a vector of device_alias_pairs */ vector DeviceManager::Devices() const { vector result; map::const_iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) if (iter->second.device) result.push_back(iter->second); return result; } /* * Find the device with the given alias. * @return a pointer to the device or NULL if the device wasn't found. */ AbstractDevice *DeviceManager::GetDevice(unsigned int alias) const { map::const_iterator alias_iter = m_alias_map.find(alias); if (alias_iter != m_alias_map.end()) return alias_iter->second; return NULL; } /* * Return the device_alias_pair corresponding to the device with the given ID. * @param unique_id the unique id of the device * @return a device_alias_pair, if the device isn't found the alias is set to * MISSING_DEVICE_ALIAS and the device pointer is NULL. */ device_alias_pair DeviceManager::GetDevice(const string &unique_id) const { device_alias_pair result; map::const_iterator iter = m_devices.find(unique_id); if (iter != m_devices.end() && iter->second.device) return iter->second; result.alias = MISSING_DEVICE_ALIAS; result.device = NULL; return result; } /* * Remove all devices and reset the device counter */ void DeviceManager::UnregisterAllDevices() { map::iterator iter; for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) { SaveDevicePortSettings(iter->second.device); iter->second.device = NULL; } m_alias_map.clear(); } /* * Save the port universe patchings for a device * @param device the device to save the settings for */ void DeviceManager::SaveDevicePortSettings(const AbstractDevice *device) { if (!m_port_preferences || !device) return; vector input_ports; vector output_ports; device->InputPorts(&input_ports); device->OutputPorts(&output_ports); SavePortPatchings(input_ports); SavePortPatchings(output_ports); vector::const_iterator input_iter = input_ports.begin(); for (; input_iter != input_ports.end(); ++input_iter) SavePortPriority(**input_iter); vector::const_iterator output_iter = output_ports.begin(); for (; output_iter != output_ports.end(); ++output_iter) SavePortPriority(**output_iter); } /* * Restore the port universe patchings for a list of ports. */ void DeviceManager::RestoreDevicePortSettings(AbstractDevice *device) { if (!m_port_preferences || !device) return; vector input_ports; vector output_ports; device->InputPorts(&input_ports); device->OutputPorts(&output_ports); RestorePortPatchings(input_ports); RestorePortPatchings(output_ports); vector::const_iterator input_iter = input_ports.begin(); for (; input_iter != input_ports.end(); ++input_iter) RestorePortPriority(*input_iter); vector::const_iterator output_iter = output_ports.begin(); for (; output_iter != output_ports.end(); ++output_iter) RestorePortPriority(*output_iter); } /* * Save the patching information for a list of ports. */ template void DeviceManager::SavePortPatchings(const vector &ports) const { typename vector::const_iterator iter = ports.begin(); while (iter != ports.end()) { string port_id = (*iter)->UniqueId(); if (port_id.empty()) return; if ((*iter)->GetUniverse()) { m_port_preferences->SetValue( port_id, IntToString((*iter)->GetUniverse()->UniverseId())); } else { m_port_preferences->RemoveValue(port_id); } iter++; } } /* * Save the priorities for all ports on this device */ void DeviceManager::SavePortPriority(const Port &port) const { if (port.PriorityCapability() == CAPABILITY_NONE) return; string port_id = port.UniqueId(); if (port_id.empty()) return; m_port_preferences->SetValue(port_id + PRIORITY_VALUE_SUFFIX, IntToString(port.GetPriority())); if (port.PriorityCapability() == CAPABILITY_FULL) m_port_preferences->SetValue(port_id + PRIORITY_MODE_SUFFIX, IntToString(port.GetPriorityMode())); } /* * Restore the priority settings for a port */ void DeviceManager::RestorePortPriority(Port *port) const { if (port->PriorityCapability() == CAPABILITY_NONE) return; string port_id = port->UniqueId(); if (port_id.empty()) return; string priority_str = m_port_preferences->GetValue( port_id + PRIORITY_VALUE_SUFFIX); string priority_mode_str = m_port_preferences->GetValue( port_id + PRIORITY_MODE_SUFFIX); if (priority_str.empty() && priority_mode_str.empty()) return; uint8_t priority, priority_mode; // setting the priority to overide mode first means we remember the over // value even if it's in inherit mode if (StringToUInt8(priority_str, &priority)) m_port_manager->SetPriorityOverride(port, priority); if (StringToUInt8(priority_mode_str, &priority_mode)) { if (priority_mode == PRIORITY_MODE_INHERIT) m_port_manager->SetPriorityInherit(port); } } /* * Restore the patching information for a port. */ template void DeviceManager::RestorePortPatchings( const vector &ports) const { typename vector::const_iterator iter = ports.begin(); while (iter != ports.end()) { PortClass *port = *iter; iter++; string port_id = port->UniqueId(); if (port_id.empty()) continue; string uni_id = m_port_preferences->GetValue(port_id); if (uni_id.empty()) continue; errno = 0; int id = static_cast(strtol(uni_id.data(), NULL, 10)); if ((id == 0 && errno) || id < 0) continue; m_port_manager->PatchPort(port, id); } } } // ola