TOBI SignalServer  0.1
/home/breidi/Dropbox/signalserver/src/signalserver/main_old.cpp
00001 /*
00002     This file is part of the TOBI signal server.
00003 
00004     The TOBI signal server 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 3 of the License, or
00007     (at your option) any later version.
00008 
00009     The TOBI signal server 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017     Copyright 2010 Christian Breitwieser
00018     Contact: c.breitwieser@tugraz.at
00019 */
00020 
00025 //-----------------------------------------------------------------------------
00026 
00027 // STL
00028 #include <iostream>
00029 
00030 // Boost
00031 #include <boost/asio.hpp>
00032 #include <boost/thread/thread.hpp>
00033 #include <boost/exception/all.hpp>
00034 #include <boost/filesystem.hpp>
00035 
00036 // local
00037 #include "version.h"
00038 #include "tia/tia_server.h"
00039 #include "config/xml_parser.h"
00040 #include "hardware/hw_access.h"
00041 #include "filereading/data_file_handler.h"
00042 
00043 using namespace std;
00044 
00045 using namespace tobiss;
00046 
00047 const string DEFAULT_XML_CONFIG = "server_config.xml";
00048 const string COMMENTS_XML_CONFIG = "server_config_comments.xml";
00049 
00050 const string XML_CONFIG_FILE_PARAM = "-f";
00051 const string LIST_HARDWARE_PARAM   = "-l";
00052 const string NEW_TIA_PARAM = "-n";
00053 
00054 #ifndef WIN32
00055 const string DEFAULT_XML_CONFIG_HOME_SUBDIR = string("/tobi_sigserver_cfg/");
00056 const string TEMPLATE_XML_CONFIG = string("/usr/share/signalserver/") + DEFAULT_XML_CONFIG;
00057 const string TEMPLATE_XML_CONFIG_COMMENTS = string("/usr/share/signalserver/") + COMMENTS_XML_CONFIG;
00058 #endif
00059 
00060 class DataPacketReader
00061 {
00062   public:
00063     DataPacketReader(HWAccess& hw_access, TiAServer& server) :
00064         hw_access_(hw_access),
00065         server_(server),
00066         stop_reading_(false)
00067     {  }
00068 
00069     void stop()
00070     {
00071       stop_reading_ = true;
00072     }
00073 
00074     void readPacket()
00075     {
00076       while (!stop_reading_)
00077       {
00078         DataPacket p = hw_access_.getDataPacket();
00079         server_.sendDataPacket(p);
00080       }
00081     }
00082 
00083   private:
00084     HWAccess&                   hw_access_;
00085     TiAServer&                  server_;
00086     bool                        stop_reading_;
00087 };
00088 
00089 //-----------------------------------------------------------------------------
00090 string getDefaultConfigFile ()
00091 {
00092     string default_xml_config = DEFAULT_XML_CONFIG;
00093 #ifdef WIN32
00094     // do nothing here at the moment ;)
00095     return default_xml_config;
00096 #else
00097     default_xml_config = string (getenv("HOME")) + DEFAULT_XML_CONFIG_HOME_SUBDIR + default_xml_config;
00098     string comments_xml_config = string (getenv("HOME")) + DEFAULT_XML_CONFIG_HOME_SUBDIR + COMMENTS_XML_CONFIG;
00099     boost::filesystem::path default_config_path (default_xml_config);
00100     boost::filesystem::path comments_config_path (comments_xml_config);
00101 
00102     boost::filesystem::path template_config_path (TEMPLATE_XML_CONFIG);
00103     boost::filesystem::path template_comments_config_path (TEMPLATE_XML_CONFIG_COMMENTS);
00104 
00105     if (!boost::filesystem::exists (default_config_path))
00106     {
00107         if (boost::filesystem::exists (template_config_path))
00108         {
00109             boost::filesystem::create_directory (default_config_path.parent_path());
00110             boost::filesystem::copy_file (template_config_path, default_config_path);
00111         }
00112         if (boost::filesystem::exists (TEMPLATE_XML_CONFIG_COMMENTS))
00113           boost::filesystem::copy_file (template_comments_config_path, comments_config_path);
00114 
00115     }
00116     return default_xml_config;
00117 #endif
00118 }
00119 
00120 
00121 //-----------------------------------------------------------------------------
00122 
00123 void printVersion()
00124 {
00125   cout << endl;
00126   cout << "SignalServer -- Version: " << MAJOR_VERSION;
00127   cout << " (build " << BUILD_NUMBER << ")";
00128   #ifndef WIN32
00129     cout << " -- " << BUILD_STR;
00130   #else
00131     cout << " -- " << __DATE__ << " " << __TIME__;
00132   #endif
00133   cout << endl << endl;
00134   cout << "Laboratory of Brain-Computer Interfaces" << endl;
00135   cout << "Graz University of Technology" << endl;
00136   cout << "http://bci.tugraz.at" << endl;
00137 }
00138 
00139 //-----------------------------------------------------------------------------
00140 
00141 void printPossibleHardware()
00142 {
00143   cout << "Possible hardware abrevations to be used  with this signal server version:" << endl;
00144   vector<string> hw_names = HWAccess::getPossibleHardwareNames();
00145   for(unsigned int n = 0; n < hw_names.size(); n++)
00146     cout << "  * " << hw_names[n] << endl;
00147 }
00148 
00149 //-----------------------------------------------------------------------------
00150 //-----------------------------------------------------------------------------
00151 
00152 int main(int argc, const char* argv[])
00153 {
00154   try
00155   {
00156     printVersion();
00157 
00158     string config_file;
00159     bool running = true;
00160     bool use_new_tia = false;
00161 
00162     if(argc == 1)
00163     {
00164       config_file = getDefaultConfigFile ();
00165       cout << endl << " ***  Loading default XML configuration file: " << config_file << endl << endl;
00166     }
00167     else if(argc == 2)
00168     {
00169       if(argv[1] == LIST_HARDWARE_PARAM)
00170       {
00171         printPossibleHardware();
00172         return(0);
00173       }
00174       else if (argv[1] == NEW_TIA_PARAM)
00175       {
00176         use_new_tia = true;
00177         cout << endl << " *** Signal Server will start with TiA 1.0 ***" << endl;
00178         config_file = getDefaultConfigFile ();
00179         cout << endl << " ***  Loading default XML configuration file: " << config_file << endl << endl;
00180       }
00181       else
00182       {
00183         cout << endl << "  ***  Loading XML configuration file: " << argv[1] << endl << endl;
00184         config_file = argv[1];
00185       }
00186     }
00187     else if(argc == 3 && argv[1] == XML_CONFIG_FILE_PARAM)
00188     {
00189       cout << endl << "  ***  Loading XML configuration file: " << argv[2] << endl << endl;
00190       config_file = argv[2];
00191     }
00192     else
00193       throw(std::invalid_argument(" ERROR -- Failure parsing input arguments!") );
00194 
00195     while(running)
00196     {
00197       XMLParser config(config_file);
00198 
00199 
00200       boost::asio::io_service io_service;
00201 
00202       TiAServer server(io_service, use_new_tia);
00203 
00204 //      DataFileHandler data_file_handler(io_service, config.getFileReaderMap());
00205 
00206       HWAccess hw_access(io_service, config);
00207       DataPacketReader reader(hw_access, server);
00208       boost::thread* io_thread_ptr_1 = 0;
00209       boost::thread* io_thread_ptr_2 = 0;
00210       boost::thread* data_reader_thread_ptr = 0;
00211 
00212       if(config.usesDataFile())
00213       {
00214         // get DataPackets from FileReader and give it to the networking part
00215       }
00216       else
00217       {
00218         // TODO: find a better way to pass this information to the server
00219         server.setMasterBlocksize(hw_access.getMastersBlocksize());
00220         server.setMasterSamplingRate(hw_access.getMastersSamplingRate());
00221         server.setAcquiredSignalTypes(hw_access.getAcquiredSignalTypes());
00222         server.setBlockSizesPerSignalType(hw_access.getBlockSizesPerSignalType());
00223         server.setSamplingRatePerSignalType(hw_access.getSamplingRatePerSignalType());
00224         server.setChannelNames(hw_access.getChannelNames());
00225 
00226         server.initialize(config.parseSubject(),config.parseServerSettings());
00227         hw_access.startDataAcquisition();
00228 
00229         io_thread_ptr_1  = new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service));
00230         io_thread_ptr_2  = new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service));
00231         data_reader_thread_ptr = new boost::thread(boost::bind(&DataPacketReader::readPacket, &reader));
00232 
00233         #ifdef WIN32
00234           SetPriorityClass(io_thread_ptr_1->native_handle(), REALTIME_PRIORITY_CLASS);
00235           SetThreadPriority(io_thread_ptr_1->native_handle(), THREAD_PRIORITY_TIME_CRITICAL );
00236           SetPriorityClass(io_thread_ptr_2->native_handle(), REALTIME_PRIORITY_CLASS);
00237           SetThreadPriority(io_thread_ptr_2->native_handle(), THREAD_PRIORITY_TIME_CRITICAL );
00238 
00239           SetPriorityClass(data_reader_thread_ptr->native_handle(), REALTIME_PRIORITY_CLASS);
00240           SetThreadPriority(data_reader_thread_ptr->native_handle(), THREAD_PRIORITY_TIME_CRITICAL );
00241         #endif
00242       }
00243 
00244       #ifdef WIN32
00245         SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
00246       #endif
00247 
00248       string str;
00249       cout << endl << ">>";
00250 
00251       while(cin >> str)
00252       {
00253         if(str == "q" || str == "quit" || str == "exit")
00254         {
00255           running = false;
00256           break;
00257         }
00258         else if(str == "r")
00259         {
00260           break;
00261         }
00262         else if(str == "h" || str == "help")
00263         {
00264           cout << "q (quit)    ... Quit the signalserver" << endl;
00265           cout << "r (restart) ... Restart the signalserver (WARNING: malfunction with certain amplifiers possible)" << endl;
00266           cout << "l (list)    ... List possible hardware devices" << endl;
00267           cout << "h (help)    ... Print this help" << endl;
00268           cout << endl << ">>";
00269         }
00270         else if(str == "l" || str == "list")
00271         {
00272           printPossibleHardware();
00273           cout << endl << ">>";
00274         }
00275         else
00276           cout << endl << ">>";
00277       }
00278 
00279       reader.stop();
00280       io_service.stop();
00281       hw_access.stopDataAcquisition();
00282       if(io_thread_ptr_1)
00283       {
00284         io_thread_ptr_1->join();;
00285         delete io_thread_ptr_1;
00286         io_thread_ptr_1 = 0;
00287       }
00288       if(io_thread_ptr_2)
00289       {
00290         io_thread_ptr_2->join();
00291         delete io_thread_ptr_2;
00292         io_thread_ptr_2 = 0;
00293       }
00294       if(data_reader_thread_ptr)
00295       {
00296         data_reader_thread_ptr->join();
00297         delete data_reader_thread_ptr;
00298       }
00299 
00300       if(running)
00301       {
00302         cout << endl;
00303         cout << "   ...  Restarting and reloading SignalServer!" << endl;
00304         cout << endl;
00305         boost::this_thread::sleep(boost::posix_time::seconds(1));
00306       }
00307     }
00308   }
00309   catch(ticpp::Exception& ex)
00310   {
00311    cerr << endl << " ***** TICPP Exception caught! *****" << endl;
00312    cerr << " --> " << ex.what() << endl << endl;
00313    std::cin.peek();
00314   }
00315   catch(std::invalid_argument& e)
00316   {
00317    cerr << endl << " ***** STL Exception -- Invalid argument -- caught! *****" << endl;
00318    cerr << " --> " << e.what() << endl << endl;
00319    std::cin.peek();
00320   }
00321   catch(std::length_error& e)
00322   {
00323    cerr << endl << " ***** STL Exception -- Length error -- caught! *****" << endl;
00324    cerr << " --> " << e.what() << endl << endl;
00325    std::cin.peek();
00326   }
00327   catch(std::logic_error& e)
00328   {
00329    cerr << endl << " ***** STL Exception -- Logic error -- caught! *****" << endl;
00330    cerr << " --> " << e.what() << endl << endl;
00331    std::cin.peek();
00332   }
00333   catch(std::range_error& e)
00334   {
00335    cerr << endl << " ***** STL Exception -- Range error -- caught! *****" << endl;
00336    cerr << " --> " << e.what() << endl << endl;
00337    std::cin.peek();
00338   }
00339   catch(std::runtime_error& e)
00340   {
00341    cerr << endl << " ***** STL Exception -- Runtime error -- caught! *****" << endl;
00342    cerr << " --> " << e.what() << endl << endl;
00343    std::cin.peek();
00344   }
00345   catch(std::exception& e)
00346   {
00347    cerr << endl << " ***** STL Exception caught! *****" << endl;
00348    cerr << " --> " << e.what() << endl << endl;
00349    std::cin.peek();
00350   }
00351   catch(boost::exception& e)
00352   {
00353    cerr << endl << " ***** Boost Exception caught! *****" << endl;
00354    cerr << " --> " << boost::diagnostic_information(e) << endl << endl;
00355    std::cin.peek();
00356   }
00357   catch(...)
00358   {
00359    cerr << endl << " ***** Caught unknown exception! *****" << endl;
00360    std::cin.peek();
00361   }
00362 
00363    cerr.flush();
00364    return(0);
00365 }
00366 
00367 //-----------------------------------------------------------------------------
 All Data Structures Files Functions Variables