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_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 }