syndilights/open-lighting-architecture/ola-0.8.4/olad/Device.cpp

239 lines
5.6 KiB
C++

/*
* 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.
*
* Device.cpp
* Base implementation of the device class.
* Copyright (C) 2005-2008 Simon Newton
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/service.h>
#include <map>
#include <string>
#include <vector>
#include "ola/Logging.h"
#include "olad/Device.h"
#include "olad/Plugin.h"
#include "olad/Port.h"
#include "olad/Universe.h"
namespace ola {
using google::protobuf::RpcController;
using google::protobuf::Closure;
using std::pair;
/*
* Create a new device
* @param owner the plugin that owns this device
* @param name a nice name for this device
*/
Device::Device(AbstractPlugin *owner, const string &name)
: AbstractDevice(),
m_enabled(false),
m_owner(owner),
m_name(name) {
}
/*
* Stop this device
*/
Device::~Device() {
// we can't call stop from here because it uses virtual methods
if (m_enabled)
OLA_FATAL << "Device " << m_name << " wasn't stopped before deleting, " <<
"this represents a serious programming error.";
}
/*
* Start the Device
*/
bool Device::Start() {
if (m_enabled)
return true;
bool ret = StartHook();
if (ret)
m_enabled = true;
return ret;
}
/*
* Stop this device
*/
bool Device::Stop() {
if (!m_enabled)
return true;
PrePortStop();
DeleteAllPorts();
PostPortStop();
m_enabled = false;
return true;
}
/*
* Add a port to this device
* @param port the port to add
* @return true on success, false if the port already exists
*/
bool Device::AddPort(InputPort *port) {
return GenericAddPort(port, &m_input_ports);
}
/*
* Add a port to this device
* @param port the port to add
* @return 0 on success, non 0 on failure
*/
bool Device::AddPort(OutputPort *port) {
return GenericAddPort(port, &m_output_ports);
}
void Device::InputPorts(vector<InputPort*> *ports) const {
GenericFetchPortsVector(ports, m_input_ports);
}
void Device::OutputPorts(vector<OutputPort*> *ports) const {
GenericFetchPortsVector(ports, m_output_ports);
}
/*
* Returns the InputPort with the id port_id
*/
InputPort *Device::GetInputPort(unsigned int port_id) const {
map<unsigned int, InputPort*>::const_iterator iter =
m_input_ports.find(port_id);
if (iter == m_input_ports.end())
return NULL;
return iter->second;
}
/*
* Returns the OutputPort with the id port_id
*/
OutputPort *Device::GetOutputPort(unsigned int port_id) const {
map<unsigned int, OutputPort *>::const_iterator iter =
m_output_ports.find(port_id);
if (iter == m_output_ports.end())
return NULL;
return iter->second;
}
/*
* Delete all ports and clear the port list
*/
void Device::DeleteAllPorts() {
map<unsigned int, InputPort*>::iterator input_iter;
map<unsigned int, OutputPort*>::iterator output_iter;
for (input_iter = m_input_ports.begin(); input_iter != m_input_ports.end();
++input_iter) {
GenericDeletePort(input_iter->second);
}
for (output_iter = m_output_ports.begin();
output_iter != m_output_ports.end(); ++output_iter) {
GenericDeletePort(output_iter->second);
}
m_input_ports.clear();
m_output_ports.clear();
}
/*
* Returns a unique id for this device
*/
string Device::UniqueId() const {
if (m_unique_id.empty()) {
if (!Owner()) {
OLA_WARN << "Device: " << Name() << " missing owner";
return "";
}
std::stringstream str;
str << Owner()->Id() << "-" << DeviceId();
m_unique_id = str.str();
}
return m_unique_id;
}
/*
* Device Config request
*/
void Device::Configure(RpcController *controller,
const string &request,
string *response,
Closure *done) {
controller->SetFailed("Not Implemented");
done->Run();
(void) request;
(void) response;
}
template<class PortClass>
bool Device::GenericAddPort(PortClass *port,
map<unsigned int, PortClass*> *port_map) {
if (!port)
return false;
typename map<unsigned int, PortClass*>::iterator iter =
port_map->find(port->PortId());
if (iter == port_map->end()) {
pair<unsigned int, PortClass*> p(port->PortId(), port);
port_map->insert(p);
return true;
} else if (iter->second != port) {
OLA_WARN << "Attempt to insert a port but this port id is already " <<
"associated with a diferent port.";
return true;
}
return true;
}
template<class PortClass>
void Device::GenericFetchPortsVector(
vector<PortClass*> *ports,
const map<unsigned int, PortClass*> &port_map) const {
typename map<unsigned int, PortClass*>::const_iterator iter;
for (iter = port_map.begin(); iter != port_map.end(); ++iter) {
ports->push_back(iter->second);
}
}
template <class PortClass>
void Device::GenericDeletePort(PortClass *port) {
Universe *universe = port->GetUniverse();
if (universe)
universe->RemovePort(port);
delete port;
}
} // ola