MOOS 0.2375
|
00001 00002 // 00003 // MOOS - Mission Oriented Operating Suite 00004 // 00005 // A suit of Applications and Libraries for Mobile Robotics Research 00006 // Copyright (C) 2001-2005 Massachusetts Institute of Technology and 00007 // Oxford University. 00008 // 00009 // This software was written by Paul Newman at MIT 2001-2002 and Oxford 00010 // University 2003-2005. email: pnewman@robots.ox.ac.uk. 00011 // 00012 // This file is part of a MOOS Utility Component. 00013 // 00014 // This program is free software; you can redistribute it and/or 00015 // modify it under the terms of the GNU General Public License as 00016 // published by the Free Software Foundation; either version 2 of the 00017 // License, or (at your option) any later version. 00018 // 00019 // This program is distributed in the hope that it will be useful, 00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00022 // General Public License for more details. 00023 // 00024 // You should have received a copy of the GNU General Public License 00025 // along with this program; if not, write to the Free Software 00026 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 00027 // 02111-1307, USA. 00028 // 00030 #if (_MSC_VER == 1200) 00031 #pragma warning(disable: 4786) 00032 #pragma warning(disable: 4503) 00033 #endif 00034 00035 #include <MOOSLIB/MOOSLib.h> 00036 00037 #include <FL/Fl_Button.H> 00038 #include <FL/Fl_Clock.H> 00039 #include <FL/Fl_Counter.H> 00040 #include <FL/Fl_File_Chooser.H> 00041 #include <FL/Fl_Check_Browser.H> 00042 #include <FL/Fl_Preferences.H> 00043 #include <FL/filename.H> 00044 #include <FL/fl_ask.H> 00045 #include <FLTKVW/FLTKCheckList.h> 00046 #include <string> 00047 #include "PlaybackWindow.h" 00048 00049 #define DEFAULT_COMMS_TICK 40 00050 #define DEFAULT_TIMER_INTERVAL 0.01 00051 #define _USE_32BIT_TIME_T 00052 00053 class CStaticClock : public Fl_Clock 00054 { 00055 private : 00056 typedef Fl_Clock BASE; 00057 public: 00058 CStaticClock( int X, int Y, int W, int H, char *l=0 ) : BASE(X,Y,W,H,l){}; 00059 int handle(int event) 00060 { 00061 switch (event) 00062 { 00063 case FL_SHOW: 00064 return 0; 00065 break; 00066 default: 00067 return BASE::handle(event); 00068 break; 00069 } 00070 } 00071 }; 00072 00073 void GUIRefresh(void* pParam) 00074 { 00075 CPlaybackWindow *pMe = (CPlaybackWindow*)pParam; 00076 pMe->OnGUIRefresh(); 00077 } 00078 00079 CPlaybackWindow::CPlaybackWindow( int X, int Y, int W, int H, const char *l ) : BASE(X,Y,W,H,l) 00080 { 00081 m_dfTimerInterval = DEFAULT_TIMER_INTERVAL; 00082 00083 CStaticClock* pClock = new CStaticClock(20,20,70,70); 00084 pClock->tooltip("playback time"); 00085 SetID(pClock,ID_CLOCK); 00086 pClock->labelsize(10); 00087 pClock->align(FL_ALIGN_TOP); 00088 00089 Fl_Button* pPlayButton = new Fl_Button( 20, 00090 95, 00091 15,15,"@>"); 00092 pPlayButton->labelcolor(FL_GREEN); 00093 SetID(pPlayButton,ID_PLAY); 00094 pPlayButton->tooltip("start playing"); 00095 00096 Fl_Button* pStopButton = new Fl_Button( 37, 00097 95, 00098 15,15,"@-2square"); 00099 pStopButton->labelcolor(FL_RED); 00100 pStopButton->tooltip("stop playing"); 00101 SetID(pStopButton,ID_STOP); 00102 00103 Fl_Button* pRewindButton = new Fl_Button(55, 00104 95, 00105 15,15,"@|<"); 00106 pRewindButton->tooltip("rewind to start"); 00107 SetID(pRewindButton,ID_REWIND); 00108 00109 00110 Fl_Button* pSeekButton = new Fl_Button(73, 00111 00112 95, 00113 00114 15,15,"@-22>"); 00115 00116 pSeekButton->tooltip(" go to seek time"); 00117 00118 SetID(pSeekButton,ID_SEEK); 00119 00120 00121 Fl_Counter* pCounter = new Fl_Counter(20,120,160,20); 00122 pCounter->tooltip(" % progress (adjust to set seek time)"); 00123 SetID(pCounter,ID_PROGRESS); 00124 pCounter->when(FL_WHEN_RELEASE|FL_WHEN_CHANGED); 00125 pCounter->range(0.0,100.0); 00126 pCounter->labelsize(9); 00127 pCounter->align(FL_ALIGN_BOTTOM| FL_ALIGN_LEFT); 00128 pCounter->label("no file loaded"); 00129 00130 00131 pSourceCheck = new Fl_Check_Browser(200,20,120,120,""); 00132 pSourceCheck->tooltip("Select which processes to replay"); 00133 pSourceCheck->align(FL_ALIGN_TOP| FL_ALIGN_LEFT); 00134 pSourceCheck->labelsize(10); 00135 pSourceCheck->label("0 KB Loaded"); 00136 SetID(pSourceCheck,ID_SOURCE); 00137 00138 00139 Fl_Button* pFileButton = new Fl_Button( 100, 00140 20, 00141 80,20,"File..."); 00142 pFileButton->tooltip("Open *.alog file to replay"); 00143 SetID(pFileButton,ID_FILE); 00144 00145 Fl_Button* pMOOSButton = new Fl_Button( 100, 00146 45, 00147 80,20,"MOOS"); 00148 pMOOSButton->tooltip("Connect to MOOS"); 00149 SetID(pMOOSButton,ID_MOOS); 00150 pMOOSButton->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); 00151 00152 Fl_Button* pConfigureMOOSButton = new Fl_Button( 150, 00153 48, 00154 25,14,"?"); 00155 pConfigureMOOSButton->tooltip("Configure MOOS Connection"); 00156 SetID(pConfigureMOOSButton,ID_MOOS_CONFIGURE); 00157 00158 Fl_Counter* pWarpCounter = new Fl_Counter(100,80,80,20,"warp"); 00159 pWarpCounter->type(FL_SIMPLE_COUNTER); 00160 pWarpCounter->align(FL_ALIGN_TOP); 00161 pWarpCounter->tooltip("alter playback speed"); 00162 SetID(pWarpCounter,ID_WARP); 00163 pWarpCounter->when(FL_WHEN_RELEASE|FL_WHEN_CHANGED); 00164 pWarpCounter->range(0.0,10.0); 00165 pWarpCounter->value(1.0); 00166 00167 //set initial window states 00168 GetByID(ID_PLAY)->deactivate(); 00169 GetByID(ID_STOP)->deactivate(); 00170 GetByID(ID_REWIND)->deactivate(); 00171 GetByID(ID_PROGRESS)->deactivate(); 00172 GetByID(ID_WARP)->deactivate(); 00173 GetByID(ID_SOURCE)->deactivate(); 00174 GetByID(ID_CLOCK)->deactivate(); 00175 00176 //here we read last moos connection info from our preferences 00177 Fl_Preferences app( Fl_Preferences::USER, "MOOS", "uPlayback" ); 00178 char path[ FL_PATH_MAX ]; 00179 app.getUserdataPath( path, sizeof(path) ); 00180 char HostName[FL_PATH_MAX]; 00181 app.get("HostName",HostName,"LOCALHOST",sizeof(HostName)); 00182 int nHost; 00183 app.get("HostPort",nHost,9000); 00184 m_lServerPort = (long)nHost; 00185 m_sServerHost = std::string(HostName); 00186 00187 00188 00189 00190 00191 m_dfSeekTime = 0.0; 00192 00193 00194 //here we add a timer to keep thinsg refreshed 00195 //this fixes a problem with some guio stuff happening outside thread 0 00196 Fl::add_timeout(0.25,GUIRefresh,this); 00197 00198 m_eMode = STOPPED; 00199 } 00200 00201 void CPlaybackWindow::OnGUIRefresh() 00202 { 00203 ManageWidgetStates(); 00204 SetTitle(); 00205 Fl::redraw(); 00206 Fl::add_timeout(0.25,GUIRefresh,this); 00207 } 00208 void CPlaybackWindow::OnControlWidget(Fl_Widget* pWidget,int ID) 00209 { 00210 //this is the swicth yard for all messages 00211 switch(ID) 00212 { 00213 case ID_PLAY: 00214 OnPlayButton(); 00215 ShowProgress(); 00216 m_eMode = PLAYING; 00217 break; 00218 case ID_STOP: 00219 OnStopButton(); 00220 m_eMode = STOPPED; 00221 break; 00222 case ID_MOOS: 00223 OnMOOS(); 00224 GetByID(ID_MOOS_CONFIGURE)->take_focus(); 00225 break; 00226 case ID_REWIND: 00227 StopTimer(); 00228 m_PlayBack.Reset(); 00229 00230 m_eMode = STOPPED; 00231 ShowProgress(); 00232 break; 00233 case ID_WARP: 00234 OnWarp(); 00235 break; 00236 case ID_FILE: 00237 OnFile(); 00238 m_PlayBack.Reset(); 00239 ShowProgress(); 00240 break; 00241 00242 case ID_SEEK: 00243 00244 StopTimer(); 00245 00246 m_eMode = STOPPED; 00247 00248 m_PlayBack.Reset(); 00249 00250 m_PlayBack.GotoTime(m_dfSeekTime); 00251 00252 ShowProgress(); 00253 00254 break; 00255 case ID_PROGRESS: 00256 OnProgress(); 00257 break; 00258 case ID_MOOS_CONFIGURE: 00259 OnMOOSConfigure(); 00260 break; 00261 } 00262 00263 ManageWidgetStates(); 00264 00265 } 00266 bool CPlaybackWindow::OnMOOSConfigure() 00267 { 00268 //ask the user wher he/she wants to connect to 00269 const char * scHost=fl_input("MOOSDB Host Name", m_sServerHost.c_str()); 00270 if(scHost==NULL) 00271 return false; 00272 m_sServerHost = std::string(scHost); 00273 00274 std::string sPort = MOOSFormat("%d",(int)m_lServerPort); 00275 const char * scPort=fl_input("MOOSDB Port", sPort.c_str()); 00276 if(scPort==NULL) 00277 return false; 00278 m_lServerPort = atol(scPort); 00279 SetTitle(); 00280 return true; 00281 } 00282 00283 bool CPlaybackWindow::SetTitle(bool bOnline) 00284 { 00285 Fl_Window* p = GetRootWindow(); 00286 00287 static char sTitle[1024]; 00288 sprintf(sTitle,"uPlayback : %s:%d %s",m_sServerHost.c_str(),(int)m_lServerPort,m_Comms.IsConnected()|| bOnline ? "Online":"Offline"); 00289 p->label(sTitle); 00290 p->labelcolor(FL_RED); 00291 return true; 00292 } 00293 00294 bool CPlaybackWindow::ManageWidgetStates() 00295 { 00296 if(m_Comms.IsConnected()) 00297 { 00298 GetByID(ID_MOOS)->deactivate(); 00299 if(m_PlayBack.IsOpen()) 00300 { 00301 GetByID(ID_CLOCK)->activate(); 00302 GetByID(ID_REWIND)->activate(); 00303 GetByID(ID_PROGRESS)->activate(); 00304 GetByID(ID_WARP)->activate(); 00305 GetByID(ID_MOOS)->deactivate(); 00306 if(m_eMode == PLAYING) 00307 { 00308 GetByID(ID_PLAY)->deactivate(); 00309 GetByID(ID_STOP)->activate(); 00310 } 00311 else if(m_eMode == STOPPED) 00312 { 00313 GetByID(ID_PLAY)->activate(); 00314 GetByID(ID_STOP)->deactivate(); 00315 } 00316 } 00317 else 00318 { 00319 GetByID(ID_CLOCK)->deactivate(); 00320 } 00321 } 00322 return true; 00323 } 00324 00325 bool CPlaybackWindow::OnProgress() 00326 { 00327 if(Fl::event()&FL_RELEASE) 00328 { 00329 double dfPC = ((Fl_Counter*)GetByID(ID_PROGRESS))->value(); 00330 double dfDuration = m_PlayBack.GetFinishTime()-m_PlayBack.GetStartTime(); 00331 double dfT = m_PlayBack.GetStartTime()+dfPC/100.0*dfDuration; 00332 ((Fl_Clock*)GetByID(ID_CLOCK))->value((int)dfT); 00333 m_dfSeekTime = dfT; 00334 return m_PlayBack.GotoTime(dfT); 00335 } 00336 else 00337 { 00338 StopTimer(); 00339 } 00340 return true; 00341 00342 } 00343 bool CPlaybackWindow::OnWarp() 00344 { 00345 if(Fl::event()&FL_RELEASE) 00346 { 00347 double dfWarp = ((Fl_Counter*)GetByID(ID_WARP))->value(); 00348 m_PlayBack.SetTickInterval(dfWarp*m_dfTimerInterval); 00349 } 00350 return true; 00351 } 00352 00353 bool CPlaybackWindow::OnFile() 00354 { 00355 //here we try to recall the last file we opened 00356 Fl_Preferences app( Fl_Preferences::USER, "MOOS", "uPlayback" ); 00357 00358 char path[ FL_PATH_MAX ]; 00359 app.getUserdataPath( path, sizeof(path) ); 00360 00361 char LastFile[FL_PATH_MAX]; 00362 app.get("LastFile",LastFile,"*",sizeof(LastFile)); 00363 00364 const char * pFile = fl_file_chooser("Select an alog file", "*.alog", LastFile); 00365 if(pFile) 00366 { 00367 //CWaitCursor Cursor; 00368 GetRootWindow()->cursor(FL_CURSOR_WAIT ); 00369 00370 00371 00372 GetByID(ID_PROGRESS)->label("LOADING AND PARSING ALOG...PLEASE WAIT"); 00373 00374 redraw(); 00375 00376 Fl::wait(); 00377 00378 00379 if(m_PlayBack.Initialise(pFile)) 00380 { 00381 m_sFileName = std::string(pFile); 00382 pSourceCheck->clear(); 00383 00384 STRING_SET Sources = m_PlayBack.GetSources(); 00385 STRING_SET::iterator p; 00386 int i =0; 00387 for(p = Sources.begin();p!= Sources.end();p++) 00388 { 00389 pSourceCheck->add(p->c_str(),1); 00390 } 00391 00392 GetByID(ID_SOURCE)->activate(); 00393 GetByID(ID_CLOCK)->activate(); 00394 00395 //here we save the last file we opened 00396 app.set( "LastFile",pFile ); 00397 00398 GetByID(ID_PROGRESS)->label(pFile); 00399 00400 //lets tell th user how mucg data has been loaded 00401 static char sFileSize[128]; 00402 sprintf(sFileSize,"%.2f KB loaded",(double)m_PlayBack.m_ALog.GetSize()/1024); 00403 GetByID(ID_SOURCE)->label(sFileSize); 00404 00405 } 00406 else 00407 { 00408 fl_alert("Failed to initialise playback"); 00409 } 00410 GetRootWindow()->cursor(FL_CURSOR_DEFAULT ); 00411 00412 } 00413 00414 take_focus(); 00415 return true; 00416 } 00417 00418 Fl_Window * CPlaybackWindow::GetRootWindow() 00419 { 00420 Fl_Widget * p=this; 00421 while(1) 00422 { 00423 if(p->parent()==NULL) 00424 return (Fl_Window *)p; 00425 else 00426 p = p->parent(); 00427 } 00428 } 00429 00430 bool CPlaybackWindow::OnMOOS() 00431 { 00432 00433 if(m_Comms.IsConnected()) 00434 { 00435 m_Comms.Close(); 00436 } 00437 00438 //next line is pretty crucial... 00439 m_Comms.FakeSource(true); 00440 m_Comms.SetOnConnectCallBack(MOOSConnectCallBack,(void*)this); 00441 m_Comms.SetOnDisconnectCallBack(MOOSDisconnectCallBack,(void*)this); 00442 00443 //here we try to 00444 Fl_Preferences app( Fl_Preferences::USER, "MOOS", "uPlayback" ); 00445 app.set("HostName",m_sServerHost.c_str()); 00446 app.set("HostPort",(int)(m_lServerPort)); 00447 00448 return m_Comms.Run(m_sServerHost.c_str(),m_lServerPort,"uPlayback",DEFAULT_COMMS_TICK); 00449 } 00450 00451 bool CPlaybackWindow::OnMOOSDisconnect() 00452 { 00453 SetTitle(); 00454 return true; 00455 } 00456 00457 00458 bool CPlaybackWindow::OnMOOSConnect() 00459 { 00460 SetTitle(); 00461 redraw(); 00462 return true; 00463 } 00464 00465 00466 bool CPlaybackWindow::OnPlayButton() 00467 { 00468 MakeMessageFilter(); 00469 m_nTimerHits = 0; 00470 00471 StartTimer(m_dfTimerInterval); 00472 00473 return true; 00474 } 00475 bool CPlaybackWindow::OnNewMail(MOOSMSG_LIST &NewMail) 00476 { 00477 00478 CMOOSMsg Msg; 00479 if (m_Comms.PeekMail(NewMail,"PLAYBACK_CHOKE",Msg)) 00480 { 00481 double dfLastTimeProcessed = Msg.m_dfVal; 00482 m_PlayBack.SetLastTimeProcessed(dfLastTimeProcessed); 00483 } 00484 00485 return true; 00486 } 00487 00488 bool CPlaybackWindow::OnStopButton() 00489 { 00490 StopTimer(); 00491 return true; 00492 } 00493 00494 00495 void CPlaybackWindow::OnTimer() 00496 { 00497 if (m_Comms.IsConnected()) 00498 { 00499 MOOSMSG_LIST NewMail; 00500 if(m_Comms.Fetch(NewMail)) 00501 { 00502 OnNewMail(NewMail); 00503 } 00504 } 00505 00506 MOOSMSG_LIST Output; 00507 00508 if(m_PlayBack.Iterate(Output)) 00509 { 00510 MOOSMSG_LIST::iterator p; 00511 00512 for(p = Output.begin();p!=Output.end();p++) 00513 { 00514 CMOOSMsg & rMsg = *p; 00515 00516 if(m_Comms.IsConnected()) 00517 { 00518 m_Comms.Post(rMsg); 00519 } 00520 } 00521 } 00522 else 00523 { 00524 if(m_PlayBack.IsEOF()) 00525 { 00526 OnStopButton(); 00527 } 00528 } 00529 00530 if((m_nTimerHits++)%25==0) 00531 { 00532 ShowProgress(); 00533 } 00534 00535 } 00536 00537 bool CPlaybackWindow::ShowProgress() 00538 { 00539 //show percent elapsed 00540 double dfProgress =0; 00541 double dfDuration = m_PlayBack.GetFinishTime()-m_PlayBack.GetStartTime(); 00542 double dfElapsed = m_PlayBack.GetLastMessageTime()-m_PlayBack.GetStartTime(); 00543 00544 ((Fl_Clock*)GetByID(ID_CLOCK))->value((int)m_PlayBack.GetLastMessageTime()); 00545 if(1 || dfElapsed>=0) 00546 { 00547 dfProgress = 100.0*(dfElapsed)/(dfDuration); 00548 ((Fl_Counter*)GetByID(ID_PROGRESS))->value(dfProgress); 00549 } 00550 Fl_Clock* pClock = (Fl_Clock*)GetByID(ID_CLOCK); 00551 00552 static char Time[256]; 00553 sprintf(Time,"%.2d:%.2d.%.2d",pClock->hour(),pClock->minute(),pClock->second()); 00554 pClock->label(Time); 00555 00556 00557 return true; 00558 } 00559 00560 00561 bool CPlaybackWindow::MakeMessageFilter() 00562 { 00563 m_PlayBack.ClearFilter(); 00564 00565 for(int i = 0;i<=pSourceCheck->nitems();i++) 00566 { 00567 char * pText = pSourceCheck->text(i); 00568 if(pText!=NULL) 00569 { 00570 std::string sSrc(pText); 00571 bool bWanted = pSourceCheck->checked(i)?true:false; 00572 m_PlayBack.Filter(sSrc,bWanted); 00573 } 00574 } 00575 00576 return true; 00577 } 00578 00579