SPIN Framework
|
00001 // ----------------------------------------------------------------------------- 00002 // | ___ ___ _ _ _ ___ _ | 00003 // | / __>| . \| || \ | | __>_ _ ___ ._ _ _ ___ _ _ _ ___ _ _ | |__ | 00004 // | \__ \| _/| || | | _>| '_><_> || ' ' |/ ._>| | | |/ . \| '_>| / / | 00005 // | <___/|_| |_||_\_| |_| |_| <___||_|_|_|\___.|__/_/ \___/|_| |_\_\ | 00006 // | | 00007 // |---------------------------------------------------------------------------| 00008 // 00009 // http://spinframework.sourceforge.net 00010 // Copyright (C) 2009 Mike Wozniewski, Zack Settel 00011 // 00012 // Developed/Maintained by: 00013 // Mike Wozniewski (http://www.mikewoz.com) 00014 // Zack Settel (http://www.sheefa.net/zack) 00015 // 00016 // Principle Partners: 00017 // Shared Reality Lab, McGill University (http://www.cim.mcgill.ca/sre) 00018 // La Societe des Arts Technologiques (http://www.sat.qc.ca) 00019 // 00020 // Funding by: 00021 // NSERC/Canada Council for the Arts - New Media Initiative 00022 // Heritage Canada 00023 // Ministere du Developpement economique, de l'Innovation et de l'Exportation 00024 // 00025 // ----------------------------------------------------------------------------- 00026 // This file is part of the SPIN Framework. 00027 // 00028 // SPIN Framework is free software: you can redistribute it and/or modify 00029 // it under the terms of the GNU Lesser General Public License as published by 00030 // the Free Software Foundation, either version 3 of the License, or 00031 // (at your option) any later version. 00032 // 00033 // SPIN Framework is distributed in the hope that it will be useful, 00034 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00035 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00036 // GNU Lesser General Public License for more details. 00037 // 00038 // You should have received a copy of the GNU Lesser General Public License 00039 // along with SPIN Framework. If not, see <http://www.gnu.org/licenses/>. 00040 // ----------------------------------------------------------------------------- 00041 00042 #ifndef __spinApp_H 00043 #define __spinApp_H 00044 00045 #include "config.h" 00046 00047 #ifndef DISABLE_PYTHON 00048 //#include "Python.h" 00049 //#include <Python.h> 00050 #include <boost/python.hpp> 00051 00052 #endif 00053 00054 #include <stdarg.h> 00055 #include <osg/Timer> 00056 #include <lo/lo_types.h> 00057 #include <osg/ref_ptr> 00058 00059 #include "spinUtil.h" 00060 00061 namespace spatosc 00062 { 00063 class Scene; 00064 } 00065 00066 namespace spin 00067 { 00068 00069 class spinBaseContext; 00070 class SceneManager; 00071 class ReferencedNode; 00072 class UserNode; 00073 00074 #define SPIN_ARGS_END LO_ARGS_END 00075 00082 class spinApp 00083 { 00084 public: 00090 static spinApp& Instance(); 00091 00092 void setContext(spinBaseContext *c); 00093 spinBaseContext *getContext() { return context; } 00094 00095 void createScene(); 00096 void destroyScene(); 00097 00103 void registerUser(); 00104 00105 00113 void InfoMessage(const std::string &OSCpath, const char *types, ...); 00114 void InfoMessage(const std::string &OSCpath, const char *types, va_list ap); 00115 void InfoMessage(const std::string &OSCpath, lo_message msg); 00116 00117 void SceneMessage(const char *types, ...); 00118 void SceneMessage(const char *types, va_list ap); 00119 void SceneMessage(lo_message msg); 00120 00121 void NodeMessage(const char *nodeId, const char *types, ...); 00122 void NodeMessage(const char *nodeId, const char *types, va_list ap); 00123 void NodeMessage(const char *nodeId, lo_message msg); 00124 00125 void NodeBundle(std::string nodeId, std::vector<lo_message> msgs, lo_address addr = 0); 00126 void SceneBundle(std::vector<lo_message> msgs, lo_address addr = 0); 00127 00128 void setSceneID(const std::string &s) { sceneID = s; } 00129 std::string getSceneID() const { return sceneID; } 00130 00131 void setSyncStart(osg::Timer_t t) { _syncStartTick = t; } 00132 osg::Timer_t getSyncStart() const { return _syncStartTick; } 00133 00137 bool initPython(); 00138 00142 bool execPython( const std::string& cmd ); 00146 std::string getCurrentPyException(); 00147 00148 #ifndef DISABLE_PYTHON 00149 boost::python::object _pyMainModule; 00150 boost::python::object _pyNamespace; 00151 #endif 00152 bool _pyInitialized; 00153 00154 osg::ref_ptr<UserNode> userNode; 00155 00156 #ifdef WITH_SPATOSC 00157 spatosc::Scene *audioScene; 00158 #endif 00159 00165 bool hasAudioRenderer; 00166 00167 SceneManager *sceneManager_; 00168 00169 void setUserID(const std::string &id) { userID_ = id; } 00170 std::string getUserID() const { return userID_; } 00171 00172 private: 00173 00174 std::string userID_; 00175 void sendBundle(const std::string &OSCpath, std::vector<lo_message> msgs, lo_address txAddr = 0); 00176 00177 // singleton constructors & desctructor (hidden): 00178 spinApp(); 00179 spinApp(spinApp const&); // copy constructor 00180 // hide the assignment operator, otherwise it would be possible to 00181 // assign the singleton spinApp to itself: 00182 spinApp& operator=(spinApp const&); 00183 ~spinApp(); 00184 00185 std::string sceneID; 00186 00187 osg::Timer_t _syncStartTick; 00188 00189 spinBaseContext *context; 00190 }; 00191 00192 } // end of namespace spin 00193 00194 00195 // Internal server-side MACROS for sending messages. Clients should NEVER use 00196 // these macros, and should rather use spinContext::send* methods. But just in 00197 // case, the macros always check that spinApp is operating in server mode 00198 00199 00200 00201 #define SCENE_MSG(types, ...) \ 00202 if (spinApp::Instance().getContext() && \ 00203 (spinApp::Instance().getContext()->isRunning()) && \ 00204 (spinApp::Instance().getContext()->isServer()) ) \ 00205 for (std::vector<lo_address>::iterator addrIter=spinApp::Instance().getContext()->lo_txAddrs_.begin(); addrIter != spinApp::Instance().getContext()->lo_txAddrs_.end(); ++addrIter) \ 00206 lo_send((*addrIter), \ 00207 ("/SPIN/" + spinApp::Instance().getSceneID()).c_str(), \ 00208 types, ##__VA_ARGS__, SPIN_ARGS_END) 00209 00210 #define SCENE_LO_MSG(msg) \ 00211 if (spinApp::Instance().getContext() && \ 00212 (spinApp::Instance().getContext()->isRunning()) && \ 00213 (spinApp::Instance().getContext()->isServer()) ) \ 00214 for (std::vector<lo_address>::iterator addrIter=spinApp::Instance().getContext()->lo_txAddrs_.begin(); addrIter != spinApp::Instance().getContext()->lo_txAddrs_.end(); ++addrIter) \ 00215 lo_send_message((*addrIter), \ 00216 ("/SPIN/" + spinApp::Instance().getSceneID()).c_str(), msg) 00217 00218 #define SCENE_LO_MSG_TCP(msg, addr) \ 00219 if (spinApp::Instance().getContext() && \ 00220 (spinApp::Instance().getContext()->isRunning()) && \ 00221 (spinApp::Instance().getContext()->isServer()) ) \ 00222 lo_send_message((addr), \ 00223 ("/SPIN/" + spinApp::Instance().getSceneID()).c_str(), \ 00224 msg) 00225 00226 #define NODE_MSG(pNode, types, ...) \ 00227 if (spinApp::Instance().getContext() && \ 00228 (spinApp::Instance().getContext()->isRunning()) && \ 00229 (spinApp::Instance().getContext()->isServer()) ) \ 00230 for (std::vector<lo_address>::iterator addrIter=spinApp::Instance().getContext()->lo_txAddrs_.begin(); addrIter != spinApp::Instance().getContext()->lo_txAddrs_.end(); ++addrIter) \ 00231 lo_send((*addrIter), \ 00232 ("/SPIN/" + spinApp::Instance().getSceneID() + "/" + \ 00233 pNode->getID()).c_str(), \ 00234 types, ##__VA_ARGS__, SPIN_ARGS_END) 00235 00236 #define NODE_LO_MSG(s, pNode, msg) \ 00237 if (spinApp::Instance().getContext() && \ 00238 (spinApp::Instance().getContext()->isRunning()) && \ 00239 (spinApp::Instance().getContext()->isServer()) ) \ 00240 for (std::vector<lo_address>::iterator addrIter=spinApp::Instance().getContext()->lo_txAddrs_.begin(); addrIter != spinApp::Instance().getContext()->lo_txAddrs_.end(); ++addrIter) \ 00241 lo_send_message((*addrIter), \ 00242 ("/SPIN/" + spinApp::Instance().getSceneID() + "/" + \ 00243 pNode->getID()).c_str(), msg) 00244 00245 00246 00247 // This stuff is replaced by the tx_Addrs_ vector!! 00248 /* 00249 00250 #define SCENE_MSG(types, ...) \ 00251 if (spinApp::Instance().getContext() && \ 00252 (spinApp::Instance().getContext()->isRunning()) && \ 00253 (spinApp::Instance().getContext()->isServer()) ) \ 00254 lo_send(spinApp::Instance().getContext()->lo_txAddr, \ 00255 ("/SPIN/" + spinApp::Instance().getSceneID()).c_str(), \ 00256 types, ##__VA_ARGS__, SPIN_ARGS_END) 00257 00258 #define SCENE_MSG_TCP(types, addr, ...) \ 00259 if (spinApp::Instance().getContext() && \ 00260 (spinApp::Instance().getContext()->isRunning()) && \ 00261 (spinApp::Instance().getContext()->isServer()) ) \ 00262 lo_send((addr), \ 00263 ("/SPIN/" + spinApp::Instance().getSceneID()).c_str(), \ 00264 types, ##__VA_ARGS__, SPIN_ARGS_END) 00265 00266 #define SCENE_LO_MSG(msg) \ 00267 if (spinApp::Instance().getContext() && \ 00268 (spinApp::Instance().getContext()->isRunning()) && \ 00269 (spinApp::Instance().getContext()->isServer()) ) \ 00270 lo_send_message(spinApp::Instance().getContext()->lo_txAddr, \ 00271 ("/SPIN/" + spinApp::Instance().getSceneID()).c_str(), msg) 00272 00273 #define SCENE_LO_MSG_TCP(msg, addr) \ 00274 if (spinApp::Instance().getContext() && \ 00275 (spinApp::Instance().getContext()->isRunning()) && \ 00276 (spinApp::Instance().getContext()->isServer()) ) \ 00277 lo_send_message((addr), \ 00278 ("/SPIN/" + spinApp::Instance().getSceneID()).c_str(), \ 00279 msg) 00280 00281 #define NODE_MSG(pNode, types, ...) \ 00282 if (spinApp::Instance().getContext() && \ 00283 (spinApp::Instance().getContext()->isRunning()) && \ 00284 (spinApp::Instance().getContext()->isServer()) ) \ 00285 lo_send(spinApp::Instance().getContext()->lo_txAddr, \ 00286 ("/SPIN/" + spinApp::Instance().getSceneID() + "/" + \ 00287 pNode->getID()).c_str(), \ 00288 types, ##__VA_ARGS__, SPIN_ARGS_END) 00289 00290 #define NODE_LO_MSG(s, pNode, msg) \ 00291 if (spinApp::Instance().getContext() && \ 00292 (spinApp::Instance().getContext()->isRunning()) && \ 00293 (spinApp::Instance().getContext()->isServer()) ) \ 00294 lo_send_message(spinApp::Instance().getContext()->lo_txAddr, \ 00295 ("/SPIN/" + spinApp::Instance().getSceneID() + "/" + \ 00296 pNode->getID()).c_str(), msg) 00297 */ 00298 00299 // backwards compatibility (TODO: replace all BROADCAST messages with NODE_MSG) 00300 #define BROADCAST(pNode, types, ...) NODE_MSG(pNode, types, ##__VA_ARGS__) 00301 00302 #endif