SPIN Framework

include/spinApp.h

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