MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Tools/Graphical/uPlayBack/PlaybackWindow.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines