syndilights/open-lighting-architecture/ola-0.8.4/plugins/artnet/ArtNetDevice.cpp

202 lines
5.9 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.
*
* artnetdevice.cpp
* Art-Net device
* Copyright (C) 2005 Simon Newton
*
* An Art-Net device is an instance of libartnet bound to a single IP address
* Art-Net is limited to four ports per direction per IP, so in this case
* our device has 8 ports :
*
* Ids 0-3 : Input ports (recv dmx)
* Ids 4-7 : Output ports (send dmx)
*/
#include <google/protobuf/service.h>
#include <google/protobuf/stubs/common.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sstream>
#include <string>
#include "ola/Closure.h"
#include "ola/Logging.h"
#include "ola/StringUtils.h"
#include "ola/network/InterfacePicker.h"
#include "ola/network/NetworkUtils.h"
#include "olad/PluginAdaptor.h"
#include "olad/Port.h"
#include "olad/Preferences.h"
#include "plugins/artnet/ArtNetDevice.h"
#include "plugins/artnet/ArtNetPort.h"
namespace ola {
namespace plugin {
namespace artnet {
using google::protobuf::RpcController;
using google::protobuf::Closure;
using ola::network::AddressToString;
using ola::plugin::artnet::Request;
using ola::plugin::artnet::Reply;
const char ArtNetDevice::K_SHORT_NAME_KEY[] = "short_name";
const char ArtNetDevice::K_LONG_NAME_KEY[] = "long_name";
const char ArtNetDevice::K_SUBNET_KEY[] = "subnet";
const char ArtNetDevice::K_IP_KEY[] = "ip";
const char ArtNetDevice::K_DEVICE_NAME[] = "ArtNet";
/*
* Create a new Artnet Device
*/
ArtNetDevice::ArtNetDevice(AbstractPlugin *owner,
ola::Preferences *preferences,
const PluginAdaptor *plugin_adaptor):
Device(owner, K_DEVICE_NAME),
m_preferences(preferences),
m_node(NULL),
m_plugin_adaptor(plugin_adaptor),
m_timeout_id(ola::network::INVALID_TIMEOUT) {
}
/*
* Start this device
* @return true on success, false on failure
*/
bool ArtNetDevice::StartHook() {
string value = m_preferences->GetValue(K_SUBNET_KEY);
unsigned int subnet;
if (!ola::StringToUInt(m_preferences->GetValue(K_SUBNET_KEY), &subnet))
subnet = 0;
ola::network::Interface interface;
ola::network::InterfacePicker *picker =
ola::network::InterfacePicker::NewPicker();
if (!picker->ChooseInterface(&interface, m_preferences->GetValue(K_IP_KEY))) {
delete picker;
OLA_INFO << "Failed to find an interface";
return false;
}
delete picker;
m_node = new ArtNetNode(interface,
m_preferences->GetValue(K_SHORT_NAME_KEY),
m_preferences->GetValue(K_LONG_NAME_KEY),
m_plugin_adaptor,
subnet);
for (unsigned int i = 0; i < ARTNET_MAX_PORTS; i++) {
AddPort(new ArtNetOutputPort(this, i, m_node));
AddPort(new ArtNetInputPort(this,
i,
m_plugin_adaptor->WakeUpTime(),
m_node));
}
if (!m_node->Start()) {
DeleteAllPorts();
delete m_node;
m_node = NULL;
return false;
}
stringstream str;
str << K_DEVICE_NAME << " [" << AddressToString(interface.ip_address) << "]";
SetName(str.str());
m_timeout_id = m_plugin_adaptor->RegisterRepeatingTimeout(
POLL_INTERVAL,
NewClosure(m_node, &ArtNetNode::MaybeSendPoll));
return true;
}
/*
* Stop this device
*/
void ArtNetDevice::PostPortStop() {
if (m_timeout_id != ola::network::INVALID_TIMEOUT) {
m_plugin_adaptor->RemoveTimeout(m_timeout_id);
m_timeout_id = ola::network::INVALID_TIMEOUT;
}
m_node->Stop();
delete m_node;
m_node = NULL;
}
/*
* Handle device config messages
* @param controller An RpcController
* @param request the request data
* @param response the response to return
* @param done the closure to call once the request is complete
*/
void ArtNetDevice::Configure(RpcController *controller,
const string &request,
string *response,
Closure *done) {
Request request_pb;
if (!request_pb.ParseFromString(request)) {
controller->SetFailed("Invalid Request");
done->Run();
return;
}
switch (request_pb.type()) {
case ola::plugin::artnet::Request::ARTNET_OPTIONS_REQUEST:
HandleOptions(&request_pb, response);
break;
default:
controller->SetFailed("Invalid Request");
}
done->Run();
}
/*
* Handle an options request
*/
void ArtNetDevice::HandleOptions(Request *request, string *response) {
bool status = true;
if (request->has_options()) {
const ola::plugin::artnet::OptionsRequest options = request->options();
if (options.has_short_name()) {
status &= m_node->SetShortName(options.short_name());
}
if (options.has_long_name()) {
status &= m_node->SetLongName(options.long_name());
}
if (options.has_subnet()) {
status &= m_node->SetSubnetAddress(options.subnet());
}
}
ola::plugin::artnet::Reply reply;
reply.set_type(ola::plugin::artnet::Reply::ARTNET_OPTIONS_REPLY);
ola::plugin::artnet::OptionsReply *options_reply = reply.mutable_options();
options_reply->set_status(status);
options_reply->set_short_name(m_node->ShortName());
options_reply->set_long_name(m_node->LongName());
options_reply->set_subnet(m_node->SubnetAddress());
reply.SerializeToString(response);
}
} // artnet
} // plugin
} // ola