TOBI SignalServer  0.1
/home/breidi/Dropbox/signalserver/src/signalserver/main.cpp
Go to the documentation of this file.
00001 /*
00002     This file is part of the TOBI SignalServer.
00003 
00004     Commercial Usage
00005     Licensees holding valid Graz University of Technology Commercial
00006     licenses may use this file in accordance with the Graz University
00007     of Technology Commercial License Agreement provided with the
00008     Software or, alternatively, in accordance with the terms contained in
00009     a written agreement between you and Graz University of Technology.
00010 
00011     --------------------------------------------------
00012 
00013     GNU General Public License Usage
00014     Alternatively, this file may be used under the terms of the GNU
00015     General Public License version 3.0 as published by the Free Software
00016     Foundation and appearing in the file gpl.txt included in the
00017     packaging of this file.  Please review the following information to
00018     ensure the GNU General Public License version 3.0 requirements will be
00019     met: http://www.gnu.org/copyleft/gpl.html.
00020 
00021     In case of GNU General Public License Usage ,the TOBI SignalServer
00022     is distributed in the hope that it will be useful,
00023     but WITHOUT ANY WARRANTY; without even the implied warranty of
00024     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025     GNU General Public License for more details.
00026 
00027     You should have received a copy of the GNU General Public License
00028     along with the TOBI SignalServer. If not, see <http://www.gnu.org/licenses/>.
00029 
00030     Copyright 2010 Graz University of Technology
00031     Contact: SignalServer@tobi-project.org
00032 */
00033 
00038 //-----------------------------------------------------------------------------
00039 
00040 // STL
00041 #include <iostream>
00042 
00043 // Boost
00044 #include <boost/thread/thread.hpp>
00045 #include <boost/exception/all.hpp>
00046 #include <boost/filesystem.hpp>
00047 #include <boost/program_options.hpp>
00048 
00049 // local
00050 #include "version.h"
00051 #include "config/xml_parser.h"
00052 #include "signalserver/signalserver.h"
00053 
00054 using namespace std;
00055 using namespace tobiss;
00056 namespace po = boost::program_options;
00057 
00058 const string DEFAULT_XML_CONFIG = "server_config.xml";
00059 const string COMMENTS_XML_CONFIG = "server_config_comments.xml";
00060 
00061 const string XML_CONFIG_FILE_PARAM = "server-config";
00062 const string LIST_HARDWARE_PARAM   = "list-hardware";
00063 const string OLD_TIA_PARAM = "use-old-tia";
00064 const string HELP_PARAM = "help";
00065 
00066 #ifndef WIN32
00067   const string DEFAULT_XML_CONFIG_HOME_SUBDIR = string("/tobi_sigserver_cfg/");
00068   const string TEMPLATE_XML_CONFIG = string("/usr/share/signalserver/") + DEFAULT_XML_CONFIG;
00069   const string TEMPLATE_XML_CONFIG_COMMENTS = string("/usr/share/signalserver/") + COMMENTS_XML_CONFIG;
00070 #endif
00071 
00072 template<class T> ostream& operator<<(ostream& os, const vector<T>& v);
00073 string getDefaultConfigFile ();
00074 void printPossibleHardware();
00075 void printVersion();
00076 int parseInput(int argc, const char* argv[], string& config_file, bool& use_new_tia);
00077 void printRuntimeCommands();
00078 
00079 
00080 //-----------------------------------------------------------------------------
00081 //-----------------------------------------------------------------------------
00082 
00083 int main(int argc, const char* argv[])
00084 {
00085   try
00086   {
00087     printVersion();
00088 
00089     string config_file;
00090     bool use_new_tia = true;
00091 
00092     if( parseInput(argc, argv, config_file, use_new_tia) )
00093       return 0;
00094 
00095     bool running = true;
00096     while(running)
00097     {
00098       XMLParser config(config_file);
00099 
00100 
00101       tobiss::SignalServer sig_server(config, use_new_tia);
00102       boost::thread* sig_server_ptr = 0;
00103 
00104       sig_server_ptr = new boost::thread(boost::bind(&SignalServer::readPackets, &sig_server));
00105 
00106       #ifdef WIN32
00107         SetPriorityClass(sig_server_ptr->native_handle(),  HIGH_PRIORITY_CLASS);
00108         SetThreadPriority(sig_server_ptr->native_handle(), THREAD_PRIORITY_HIGHEST );
00109         SetPriorityClass(GetCurrentProcess(),              REALTIME_PRIORITY_CLASS);
00110       #endif
00111 
00112       string str;
00113       cout << endl << ">>";
00114 
00115       while(cin >> str)
00116       {
00117         if(str == "q" || str == "quit" || str == "exit")
00118         {
00119           running = false;
00120           break;
00121         }
00122         else if(str == "r")
00123         {
00124           break;
00125         }
00126         else if(str == "h" || str == "help")
00127         {
00128           printRuntimeCommands();
00129           cout << endl << ">>";
00130         }
00131         else if(str == "l" || str == "list")
00132         {
00133           printPossibleHardware();
00134           cout << endl << ">>";
00135         }
00136         else
00137           cout << endl << ">>";
00138       }
00139 
00140       sig_server.stop();
00141       if(sig_server_ptr)
00142       {
00143         sig_server_ptr->join();
00144         delete sig_server_ptr;
00145       }
00146 
00147       if(running)
00148       {
00149         cout << endl;
00150         cout << "   ...  Restarting and reloading SignalServer!" << endl;
00151         cout << endl;
00152         boost::this_thread::sleep(boost::posix_time::seconds(1));
00153       }
00154     }
00155   }
00156   catch(ticpp::Exception& ex)
00157   {
00158    cerr << endl << " ***** TICPP Exception caught! *****" << endl;
00159    cerr << " --> " << ex.what() << endl << endl;
00160    std::cin.peek();
00161   }
00162   catch(std::exception& e)
00163   {
00164    cerr << endl << " ***** STL Exception caught! *****" << endl;
00165    cerr << " --> " << e.what() << endl << endl;
00166    std::cin.peek();
00167   }
00168   catch(boost::exception& e)
00169   {
00170    cerr << endl << " ***** Boost Exception caught! *****" << endl;
00171    cerr << " --> " << boost::diagnostic_information(e) << endl << endl;
00172    std::cin.peek();
00173   }
00174   catch(...)
00175   {
00176    cerr << endl << " ***** Caught unknown exception! *****" << endl;
00177    std::cin.peek();
00178   }
00179 
00180    cerr.flush();
00181    return(0);
00182 }
00183 
00184 //-----------------------------------------------------------------------------
00185 
00186 
00187 std::string getDefaultConfigFile ()
00188 {
00189     string default_xml_config = DEFAULT_XML_CONFIG;
00190 #ifdef WIN32
00191     // do nothing here at the moment ;)
00192     return default_xml_config;
00193 #else
00194     default_xml_config = string (getenv("HOME")) + DEFAULT_XML_CONFIG_HOME_SUBDIR + default_xml_config;
00195     string comments_xml_config = string (getenv("HOME")) + DEFAULT_XML_CONFIG_HOME_SUBDIR + COMMENTS_XML_CONFIG;
00196     boost::filesystem::path default_config_path (default_xml_config);
00197     boost::filesystem::path comments_config_path (comments_xml_config);
00198 
00199     boost::filesystem::path template_config_path (TEMPLATE_XML_CONFIG);
00200     boost::filesystem::path template_comments_config_path (TEMPLATE_XML_CONFIG_COMMENTS);
00201 
00202     if (!boost::filesystem::exists (default_config_path))
00203     {
00204         if (boost::filesystem::exists (template_config_path))
00205         {
00206             boost::filesystem::create_directory (default_config_path.parent_path());
00207             boost::filesystem::copy_file (template_config_path, default_config_path);
00208         }
00209         if (boost::filesystem::exists (TEMPLATE_XML_CONFIG_COMMENTS))
00210           boost::filesystem::copy_file (template_comments_config_path, comments_config_path);
00211 
00212     }
00213     return default_xml_config;
00214 #endif
00215 }
00216 
00217 
00218 //-----------------------------------------------------------------------------
00219 
00220 void printVersion()
00221 {
00222   cout << endl;
00223   cout << "SignalServer -- Version: " << MAJOR_VERSION;
00224   cout << " (build " << BUILD_NUMBER << ")";
00225   #ifndef WIN32
00226     cout << " -- " << BUILD_STR;
00227   #else
00228     cout << " -- " << __DATE__ << " " << __TIME__;
00229   #endif
00230   cout << endl << endl;
00231   cout << "Laboratory of Brain-Computer Interfaces" << endl;
00232   cout << "Graz University of Technology" << endl;
00233   cout << "http://bci.tugraz.at" << endl;
00234   cout << "Important: This software comes with ABSOLUTELY NO WARRANTY, to the extent ";
00235   cout << "permitted by applicable law." << endl;
00236 }
00237 
00238 //-----------------------------------------------------------------------------
00239 
00240 void printPossibleHardware()
00241 {
00242   cout << "Possible hardware abrevations to be used  with this signal server version:" << endl;
00243   vector<string> hw_names = SignalServer::getPossibleHardwareNames();
00244   for(unsigned int n = 0; n < hw_names.size(); n++)
00245     cout << "  * " << hw_names[n] << endl;
00246 }
00247 
00248 //---------------------------------------------------------------------------------------
00249 
00250 template<class T>
00251 ostream& operator<<(ostream& os, const vector<T>& v)
00252 {
00253   std::copy(v.begin(), v.end(), ostream_iterator<T>(cout, " "));
00254     return os;
00255 }
00256 
00257 //-----------------------------------------------------------------------------
00258 
00259 int parseInput(int argc, const char* argv[], std::string& config_file, bool& use_new_tia)
00260 {
00261   po::options_description desc("Allowed options");
00262 
00263   string str(HELP_PARAM +            ",h");
00264   desc.add_options() (str.c_str() ,  "   ... produce help message");
00265 
00266   str = LIST_HARDWARE_PARAM +   ",l";
00267   desc.add_options() (str.c_str() ,  "   ... list supported hardware");
00268 
00269   str = OLD_TIA_PARAM +         ",o";
00270   desc.add_options() (str.c_str() ,  "   ... use old version of TiA (undocumented)");
00271 
00272   str = XML_CONFIG_FILE_PARAM + ",f";
00273   desc.add_options() (str.c_str() ,  po::value< string >() , "   ... signal server config file path");
00274 
00275   po::positional_options_description p;
00276   p.add(XML_CONFIG_FILE_PARAM.c_str(), -1);
00277 
00278   po::variables_map vm;
00279   po::store(po::command_line_parser(argc, const_cast<char **>(argv)).options(desc).positional(p).run(), vm);
00280   po::notify(vm);
00281 
00282   if(vm.count(HELP_PARAM))
00283   {
00284     cout << endl << "Usage: " << argv[0] << " [options]\n" << desc;
00285     cout << endl << "Runtime Commands: " << endl;
00286     printRuntimeCommands();
00287     return 1;
00288   }
00289 
00290   if(vm.count( LIST_HARDWARE_PARAM ))
00291   {
00292     printPossibleHardware();
00293     return 1;
00294   }
00295 
00296   if(vm.count( OLD_TIA_PARAM ))
00297   {
00298     use_new_tia = false;
00299     cout << endl << " ***  Signal Server will start with TiA 0.1 ***" << endl;
00300     vm.erase( OLD_TIA_PARAM );
00301   }
00302   else
00303     cout << endl << " ***  Signal Server will start with TiA 1.0 ***" << endl;
00304 
00305   if(vm.size() == 0)
00306   {
00307     config_file = getDefaultConfigFile ();
00308     cout << " ***  Loading default XML configuration file: " << config_file << endl << endl;
00309   }
00310 
00311   if(vm.count( XML_CONFIG_FILE_PARAM ))
00312   {
00313     config_file = vm[ XML_CONFIG_FILE_PARAM ].as< string >();
00314     cout << " ***  Loading XML configuration file: " << config_file << endl << endl;
00315   }
00316   return 0;
00317 }
00318 
00319 //-----------------------------------------------------------------------------
00320 
00321 void printRuntimeCommands()
00322 {
00323   cout << " q (quit)    ... Quit the signalserver" << endl;
00324   cout << " r (restart) ... Restart the signalserver (WARNING: malfunction with certain amplifiers possible)" << endl;
00325   cout << " l (list)    ... List possible hardware devices" << endl;
00326   cout << " h (help)    ... Print this help" << endl;
00327 }
00328 
00329 //-----------------------------------------------------------------------------
00330 
00331 //    cout << "  -- Input files are: " << vm["input-files"].as< vector<string> >() << endl;
00332 //    if(argc == 1)
00333 //    {
00334 //      config_file = getDefaultConfigFile ();
00335 //      cout << endl << " ***  Loading default XML configuration file: " << config_file << endl << endl;
00336 //    }
00337 //    else if(argc == 2)
00338 //    {
00339 //      if(argv[1] == LIST_HARDWARE_PARAM)
00340 //      {
00341 //        printPossibleHardware();
00342 //        return(0);
00343 //      }
00344 //      else if (argv[1] == NEW_TIA_PARAM)
00345 //      {
00346 //        use_new_tia = true;
00347 //        cout << endl << " *** Signal Server will start with TiA 1.0 ***" << endl;
00348 //        config_file = getDefaultConfigFile ();
00349 //        cout << endl << " ***  Loading default XML configuration file: " << config_file << endl << endl;
00350 //      }
00351 //      else
00352 //      {
00353 //        cout << endl << "  ***  Loading XML configuration file: " << argv[1] << endl << endl;
00354 //        config_file = argv[1];
00355 //      }
00356 //    }
00357 //    else if(argc == 3 && argv[1] == XML_CONFIG_FILE_PARAM)
00358 //    {
00359 //      cout << endl << "  ***  Loading XML configuration file: " << argv[2] << endl << endl;
00360 //      config_file = argv[2];
00361 //    }
00362 //    else
00363 //      throw(std::invalid_argument(" ERROR -- Failure parsing input arguments!") );
00364 
 All Data Structures Files Functions Variables