/* * 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 #include #include #include #include #include #include #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