Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/realtime/osc_transmitter.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 2014 George Tzanetakis <gtzan@cs.uvic.ca>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #include "osc_transmitter.h"
00020 
00021 #include <marsyas/system/MarSystem.h>
00022 #include <marsyas/common_source.h>
00023 
00024 #include <oscpack/osc/OscOutboundPacketStream.h>
00025 
00026 #include <stack>
00027 #include <vector>
00028 #include <algorithm>
00029 
00030 using namespace std;
00031 
00032 namespace Marsyas {
00033 namespace RealTime {
00034 
00035 string OscTransmitter::make_osc_path( MarControlPtr control, char separator )
00036 {
00037   string id("/");
00038   stack<MarSystem*> system_stack;
00039   //MarSystem *system_stack[30];
00040   //int system_stack_size = 0;
00041 
00042   MarSystem *system = control->getMarSystem();
00043   while( system != m_system )
00044   {
00045     system_stack.push(system);
00046     system = system->getParent();
00047   }
00048 
00049   while(!system_stack.empty())
00050   {
00051     MarSystem *system = system_stack.top();
00052     system_stack.pop();
00053     id.append(system->getName());
00054     id.push_back(separator);
00055   }
00056 
00057   id.append(control->id());
00058 
00059   return id;
00060 }
00061 
00062 bool OscTransmitter::subscribe( MarControlPtr control, OscSubscriber * subscriber )
00063 {
00064   if (control.isInvalid())
00065     return false;
00066 
00067   string path = make_osc_path(control);
00068 
00069   string handler_name(path);
00070   std::replace( handler_name.begin(), handler_name.end(), '/', '.');
00071   string handler_path = control->getType() + '/' + handler_name;
00072 
00073   MarControlPtr handler = getControl(handler_path);
00074   if (handler.isInvalid())
00075   {
00076     addControl(handler_path, *control, handler);
00077     handler->setState(true);
00078     handler->linkTo(control, false);
00079     m_subscribers[handler()].path = path;
00080   }
00081 
00082   subscription &slot = m_subscribers[handler()];
00083   if (!slot.contains(subscriber))
00084     slot.add(subscriber);
00085 
00086   return true;
00087 }
00088 
00089 void OscTransmitter::unsubscribe( MarControlPtr control, OscSubscriber * subscriber )
00090 {
00091   if (control.isInvalid())
00092     return;
00093 
00094   string path = make_osc_path(control);
00095 
00096   string handler_name(path);
00097   std::replace( handler_name.begin(), handler_name.end(), '/', '.');
00098   string handler_path = control->getType() + '/' + handler_name;
00099 
00100   MarControlPtr handler = getControl(handler_path);
00101   if (handler.isInvalid())
00102     return;
00103 
00104   // Find subscribers for control:
00105   auto subscribers_it = m_subscribers.find(handler());
00106   if (subscribers_it != m_subscribers.end())
00107   {
00108     // Find subscriber:
00109     subscription & slot = subscribers_it->second;
00110     slot.remove(subscriber);
00111 
00112     // If no subscriber for control left:
00113     if (slot.empty())
00114     {
00115       // Delete the map entry:
00116       m_subscribers.erase(subscribers_it);
00117 
00118       // Unlink the handler control:
00119       handler->unlinkFromAll();
00120       // TODO: Delete the handler control.
00121     }
00122   }
00123 }
00124 
00125 void OscTransmitter::myProcess(realvec &, realvec &)
00126 {
00127   // no-op
00128 }
00129 
00130 void OscTransmitter::myUpdate( MarControlPtr handler )
00131 {
00132   if (handler.isInvalid())
00133     return;
00134 
00135   auto subscribers_it = m_subscribers.find(handler());
00136   if (subscribers_it == m_subscribers.end())
00137     return;
00138 
00139   subscription & slot = subscribers_it->second;
00140   if (slot.empty())
00141     return;
00142 
00143   osc::OutboundPacketStream packet( m_buffer, m_buffer_size );
00144   try
00145   {
00146     packet << osc::BeginMessage( slot.path.c_str() );
00147     if (handler->hasType<bool>())
00148       packet << handler->to<bool>();
00149     else if (handler->hasType<mrs_natural>())
00150       packet << ((int) handler->to<mrs_natural>());
00151     else if (handler->hasType<mrs_real>())
00152       packet << ((float) handler->to<mrs_real>());
00153     else if (handler->hasType<mrs_string>())
00154       packet << handler->to<mrs_string>().c_str();
00155     else
00156       throw std::runtime_error("Unsupported control type.");
00157     packet << osc::EndMessage;
00158   }
00159   catch ( std::exception & e )
00160   {
00161     MRSWARN("OSC sender: " << e.what());
00162   }
00163 
00164   for( OscSubscriber * subscriber : slot.subscribers )
00165   {
00166     subscriber->process(packet.Data(), packet.Size());
00167   }
00168 }
00169 
00170 }
00171 }