TOBI SignalServer
0.1
|
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