Marsyas
0.6.0-alpha
|
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_receiver.h" 00020 00021 #include <oscpack/ip/IpEndpointName.h> 00022 #include <oscpack/osc/OscPacketListener.h> 00023 #include <oscpack/osc/OscReceivedElements.h> 00024 00025 #include <string> 00026 #include <algorithm> 00027 00028 using namespace std; 00029 00030 namespace Marsyas { 00031 namespace RealTime { 00032 00033 void process_packet( MarSystem * root_system, const char * data, size_t size ); 00034 void process_bundle( MarSystem * root_system, const osc::ReceivedBundle& bundle ); 00035 void process_message( MarSystem * root_system, const osc::ReceivedMessage& message ); 00036 00037 void OscReceiver::addProvider( OscProvider * provider ) 00038 { 00039 auto provider_pos = find(m_providers.begin(), m_providers.end(), provider); 00040 if (provider_pos == m_providers.end()) 00041 m_providers.push_back(provider); 00042 } 00043 00044 void OscReceiver::removeProvider( OscProvider * provider ) 00045 { 00046 auto provider_pos = find(m_providers.begin(), m_providers.end(), provider); 00047 if (provider_pos != m_providers.end()) 00048 m_providers.erase(provider_pos); 00049 } 00050 00051 void OscReceiver::processPacket(const char *data, size_t size) 00052 { 00053 process_packet(m_system, data, size); 00054 } 00055 00056 void OscReceiver::run() 00057 { 00058 OscProviderDestination me(this); 00059 00060 for ( OscProvider *provider : m_providers ) 00061 { 00062 provider->provide(me); 00063 } 00064 } 00065 00066 MarSystem *find_child_system(MarSystem * parent, const char * name, size_t count) 00067 { 00068 const std::vector<MarSystem*> & children = parent->children(); 00069 for( MarSystem * child : children ) 00070 { 00071 const string & child_name = child->getName(); 00072 if (child_name.size() == count && 00073 equal(name, name + count, child_name.data())) 00074 { 00075 return child; 00076 } 00077 } 00078 00079 return 0; 00080 } 00081 00082 MarControlPtr find_local_control(MarSystem * system, const char *name, size_t count) 00083 { 00084 const auto & controls = system->controls(); 00085 for ( const auto & mapping : controls ) 00086 { 00087 const MarControlPtr & control = mapping.second; 00088 const string & id = control->id(); 00089 if (id.size() == count && 00090 equal(name, name + count, id.data())) 00091 { 00092 return control; 00093 } 00094 } 00095 00096 return MarControlPtr(); 00097 } 00098 00099 MarControlPtr find_control( MarSystem *root_system, const char * path ) 00100 { 00101 size_t path_len = strlen(path); 00102 const char * path_end = path + path_len; 00103 const char * component = path; 00104 00105 MarSystem * system = root_system; 00106 00107 while(system) 00108 { 00109 const char * separator = std::find(component, path_end, '/'); 00110 size_t component_len = separator - component; 00111 if (separator != path_end) 00112 { 00113 system = find_child_system(system, component, component_len ); 00114 } 00115 else 00116 { 00117 return find_local_control(system, component, component_len); 00118 } 00119 component = separator + 1; 00120 } 00121 00122 return MarControlPtr(); 00123 } 00124 00125 void process_packet( MarSystem * root_system, const char * data, size_t size ) 00126 { 00127 osc::ReceivedPacket packet( data, size ); 00128 if( packet.IsBundle() ) 00129 process_bundle( root_system, osc::ReceivedBundle(packet) ); 00130 else 00131 process_message( root_system, osc::ReceivedMessage(packet) ); 00132 } 00133 00134 void process_bundle( MarSystem * root_system, const osc::ReceivedBundle& bundle ) 00135 { 00136 // ignore bundle time tag for now 00137 for( osc::ReceivedBundle::const_iterator i = bundle.ElementsBegin(); 00138 i != bundle.ElementsEnd(); ++i ) 00139 { 00140 if( i->IsBundle() ) 00141 process_bundle( root_system, osc::ReceivedBundle(*i) ); 00142 else 00143 process_message( root_system, osc::ReceivedMessage(*i) ); 00144 } 00145 } 00146 00147 void process_message( MarSystem * root_system, const osc::ReceivedMessage& message ) 00148 { 00149 const char * path = message.AddressPattern(); 00150 if (path[0] == '/') ++path; 00151 00152 // FIXME: Constructing std::string is not real-time-safe. 00153 MarControlPtr control = find_control(root_system, path); 00154 if (control.isInvalid()) 00155 { 00156 MRSWARN("OSC receiver: no control for path: " << path); 00157 return; 00158 } 00159 00160 try 00161 { 00162 osc::ReceivedMessage::const_iterator it = message.ArgumentsBegin(); 00163 if (it == message.ArgumentsEnd()) 00164 throw std::runtime_error("OSC receiver: Message has no arguments."); 00165 00166 char tag = it->TypeTag(); 00167 switch(tag) 00168 { 00169 case osc::TRUE_TYPE_TAG: 00170 case osc::FALSE_TYPE_TAG: 00171 control->setValue(it->AsBoolUnchecked()); 00172 break; 00173 case osc::INT32_TYPE_TAG: 00174 control->setValue(it->AsInt32Unchecked()); 00175 break; 00176 case osc::FLOAT_TYPE_TAG: 00177 control->setValue((mrs_real) it->AsFloatUnchecked()); 00178 break; 00179 case osc::DOUBLE_TYPE_TAG: 00180 control->setValue((mrs_real) it->AsDoubleUnchecked()); 00181 break; 00182 case osc::STRING_TYPE_TAG: 00183 control->setValue(it->AsStringUnchecked()); 00184 break; 00185 default: 00186 throw std::runtime_error("OSC receiver: Unsupported message argument type."); 00187 } 00188 } 00189 catch ( std::exception & e ) 00190 { 00191 MRSWARN("OSC receiver: error while parsing message: " << e.what()); 00192 } 00193 } 00194 00195 void OscQueueProvider::provide( OscProviderDestination & destination ) 00196 { 00197 size_t packet_size; 00198 00199 while( (packet_size = m_queue->pop(m_buffer, m_buffer_size)) ) 00200 { 00201 if (packet_size > m_buffer_size) 00202 { 00203 MRSWARN("OSC receiver: dropped too large OSC packet."); 00204 continue; 00205 } 00206 destination.provide(m_buffer, packet_size); 00207 } 00208 } 00209 00210 } 00211 }