MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Tools/Graphical/uIndexedPlayBack/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 #include <alogTools/indexWriter.h>
00050 
00051 #define DEFAULT_COMMS_TICK 40
00052 #define DEFAULT_TIMER_INTERVAL 0.01
00053 #define _USE_32BIT_TIME_T
00054 
00055 class CStaticClock : public Fl_Clock
00056 {
00057 private :
00058     typedef Fl_Clock BASE;
00059 public:    
00060     CStaticClock( int X, int Y, int W, int H,  char *l=0 ) : BASE(X,Y,W,H,l){};
00061     int handle(int event) 
00062     {
00063         switch (event) 
00064         {
00065         case FL_SHOW:            
00066             return 0;
00067             break;
00068         default:
00069             return BASE::handle(event);
00070             break;
00071         }
00072     }
00073 };
00074 
00075 void GUIRefresh(void* pParam)
00076 {
00077     CPlaybackWindow *pMe = (CPlaybackWindow*)pParam;
00078     pMe->OnGUIRefresh();
00079 }
00080 
00081 CPlaybackWindow::CPlaybackWindow( int X, int Y, int W, int H,  const char *l ) : BASE(X,Y,W,H,l)
00082 {
00083     m_dfTimerInterval = DEFAULT_TIMER_INTERVAL;
00084 
00085     CStaticClock* pClock = new CStaticClock(20,20,70,70);
00086     pClock->tooltip("playback time");
00087     SetID(pClock,ID_CLOCK);
00088     pClock->labelsize(10);
00089     pClock->align(FL_ALIGN_TOP);
00090 
00091     Fl_Button* pPlayButton = new Fl_Button( 20,
00092                                         95,
00093                                         15,15,"@>");
00094     pPlayButton->labelcolor(FL_GREEN);
00095     SetID(pPlayButton,ID_PLAY);
00096     pPlayButton->tooltip("start playing");
00097 
00098     Fl_Button* pStopButton = new Fl_Button( 37,
00099                                             95,
00100                                             15,15,"@-2square");
00101     pStopButton->labelcolor(FL_RED);
00102     pStopButton->tooltip("stop playing");
00103     SetID(pStopButton,ID_STOP);
00104 
00105     Fl_Button* pRewindButton = new Fl_Button(55,
00106                                             95,
00107                                             15,15,"@|<");
00108     pRewindButton->tooltip("rewind to start");
00109     SetID(pRewindButton,ID_REWIND);
00110 
00111 
00112     Fl_Button* pSeekButton = new Fl_Button(73,
00113 
00114                                             95,
00115 
00116                                             15,15,"@-22>");
00117 
00118     pSeekButton->tooltip(" go to seek time");
00119 
00120     SetID(pSeekButton,ID_SEEK);
00121 
00122 
00123     Fl_Counter* pCounter = new Fl_Counter(20,120,160,20);
00124     pCounter->tooltip(" % progress  (adjust to set seek time)");
00125     SetID(pCounter,ID_PROGRESS);
00126     pCounter->when(FL_WHEN_RELEASE|FL_WHEN_CHANGED);
00127     pCounter->range(0.0,100.0);
00128     pCounter->labelsize(9);
00129     pCounter->align(FL_ALIGN_BOTTOM| FL_ALIGN_LEFT);
00130     pCounter->label("no file loaded");
00131 
00132 
00133     pSourceCheck = new Fl_Check_Browser(200,20,120,120,"");
00134     pSourceCheck->tooltip("Select which processes to replay");
00135     pSourceCheck->align(FL_ALIGN_TOP| FL_ALIGN_LEFT);
00136       pSourceCheck->labelsize(10);
00137     pSourceCheck->label("");
00138     SetID(pSourceCheck,ID_SOURCE);
00139 
00140 
00141     Fl_Button* pFileButton = new Fl_Button( 100,
00142                                             20,
00143                                             80,20,"File...");
00144     pFileButton->tooltip("Open *.alog file to replay");
00145     SetID(pFileButton,ID_FILE);
00146     
00147     Fl_Button* pMOOSButton = new Fl_Button( 100,
00148                                             45,
00149                                             80,20,"MOOS");
00150     pMOOSButton->tooltip("Connect to MOOS");
00151     SetID(pMOOSButton,ID_MOOS);
00152     pMOOSButton->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
00153 
00154     Fl_Button* pConfigureMOOSButton = new Fl_Button( 150,
00155                                             48,
00156                                             25,14,"?");
00157     pConfigureMOOSButton->tooltip("Configure MOOS Connection");
00158     SetID(pConfigureMOOSButton,ID_MOOS_CONFIGURE);
00159 
00160     Fl_Counter* pWarpCounter = new Fl_Counter(100,80,80,20,"warp");
00161     pWarpCounter->type(FL_SIMPLE_COUNTER);
00162     pWarpCounter->align(FL_ALIGN_TOP);
00163     pWarpCounter->tooltip("alter playback speed");
00164     SetID(pWarpCounter,ID_WARP);
00165     pWarpCounter->when(FL_WHEN_RELEASE|FL_WHEN_CHANGED);
00166     pWarpCounter->range(0.0,10.0);
00167     pWarpCounter->value(1.0);
00168 
00169     //set initial window states
00170     GetByID(ID_PLAY)->deactivate();
00171     GetByID(ID_STOP)->deactivate();
00172     GetByID(ID_REWIND)->deactivate();
00173     GetByID(ID_PROGRESS)->deactivate();
00174     GetByID(ID_WARP)->deactivate();
00175     GetByID(ID_SOURCE)->deactivate();
00176     GetByID(ID_CLOCK)->deactivate();
00177 
00178     //here we read last moos connection info from our preferences
00179     Fl_Preferences app( Fl_Preferences::USER, "MOOS", "uPlayback" );
00180     char path[ FL_PATH_MAX ];
00181     app.getUserdataPath( path, sizeof(path) );
00182     char HostName[FL_PATH_MAX];
00183     app.get("HostName",HostName,"LOCALHOST",sizeof(HostName));
00184     int nHost;
00185     app.get("HostPort",nHost,9000);
00186     m_lServerPort = (long)nHost;
00187     m_sServerHost = std::string(HostName);
00188 
00189 
00190 
00191 
00192 
00193     m_dfSeekTime = 0.0;
00194 
00195 
00196     //here we add a timer to keep thinsg refreshed
00197     //this fixes a problem with some guio stuff happening outside thread 0
00198     Fl::add_timeout(0.25,GUIRefresh,this);
00199 
00200     m_eMode = STOPPED;
00201 }
00202 
00203 void CPlaybackWindow::OnGUIRefresh()
00204 {    
00205     ManageWidgetStates();
00206     SetTitle();
00207     Fl::redraw();
00208     Fl::add_timeout(0.25,GUIRefresh,this);
00209 }
00210 void CPlaybackWindow::OnControlWidget(Fl_Widget* pWidget,int ID)
00211 {
00212     //this is the swicth yard for all messages
00213     switch(ID)
00214     {        
00215     case ID_PLAY:
00216         OnPlayButton();
00217         ShowProgress();
00218         m_eMode = PLAYING;
00219         break;
00220     case ID_STOP:
00221         OnStopButton();
00222         m_eMode = STOPPED;
00223         break;
00224     case ID_MOOS:
00225         OnMOOS();
00226         GetByID(ID_MOOS_CONFIGURE)->take_focus();
00227         break;
00228     case ID_REWIND:
00229         StopTimer();
00230         m_PlayBack.Reset();
00231 
00232         m_eMode = STOPPED;
00233         ShowProgress();
00234         break;
00235     case ID_WARP:
00236         OnWarp();
00237         break;
00238     case ID_FILE:
00239         OnFile();    
00240         m_PlayBack.Reset();
00241         ShowProgress();
00242         break;
00243 
00244     case ID_SEEK:
00245 
00246         StopTimer();
00247 
00248         m_eMode = STOPPED;
00249 
00250         m_PlayBack.Reset();
00251 
00252         m_PlayBack.GotoTime(m_dfSeekTime);
00253 
00254         ShowProgress();
00255 
00256         break;
00257     case ID_PROGRESS:
00258         OnProgress();
00259         break;
00260     case ID_MOOS_CONFIGURE:
00261         OnMOOSConfigure();
00262         break;
00263     }
00264 
00265     ManageWidgetStates();
00266 
00267 }
00268 bool CPlaybackWindow::OnMOOSConfigure()
00269 {
00270     //ask the user wher he/she wants to connect to
00271     const char * scHost=fl_input("MOOSDB Host Name", m_sServerHost.c_str());
00272     if(scHost==NULL)
00273         return false;
00274     m_sServerHost = std::string(scHost);
00275 
00276     std::string sPort = MOOSFormat("%d",(int)m_lServerPort);
00277     const char * scPort=fl_input("MOOSDB Port", sPort.c_str());
00278     if(scPort==NULL)
00279         return false;
00280     m_lServerPort = atol(scPort);
00281     SetTitle();
00282     return true;
00283 }
00284 
00285 bool CPlaybackWindow::SetTitle(bool bOnline)
00286 {
00287     Fl_Window* p = GetRootWindow();
00288 
00289     static char sTitle[1024];
00290     sprintf(sTitle,"uPlayback : %s:%d %s",m_sServerHost.c_str(),(int)m_lServerPort,m_Comms.IsConnected()|| bOnline ? "Online":"Offline");
00291     p->label(sTitle);
00292     p->labelcolor(FL_RED);
00293     return true;
00294 }
00295 
00296 bool CPlaybackWindow::ManageWidgetStates()
00297 {
00298     if(m_Comms.IsConnected())
00299     {
00300         GetByID(ID_MOOS)->deactivate();        
00301         if(m_PlayBack.IsOpen())
00302         {
00303             GetByID(ID_CLOCK)->activate();
00304             GetByID(ID_REWIND)->activate();
00305             GetByID(ID_PROGRESS)->activate();
00306             GetByID(ID_WARP)->activate();
00307             GetByID(ID_MOOS)->deactivate();
00308             if(m_eMode == PLAYING)
00309             {
00310                 GetByID(ID_PLAY)->deactivate();
00311                 GetByID(ID_STOP)->activate();            
00312             }
00313             else if(m_eMode == STOPPED)
00314             {
00315                 GetByID(ID_PLAY)->activate();
00316                 GetByID(ID_STOP)->deactivate();            
00317             }
00318         }
00319         else
00320         {
00321             GetByID(ID_CLOCK)->deactivate();
00322         }
00323     }
00324     return true;
00325 }
00326 
00327 bool CPlaybackWindow::OnProgress()
00328 {
00329     if(Fl::event()&FL_RELEASE)
00330     {
00331         double dfPC = ((Fl_Counter*)GetByID(ID_PROGRESS))->value();
00332         double dfDuration = m_PlayBack.GetFinishTime()-m_PlayBack.GetStartTime();
00333         double dfT = m_PlayBack.GetStartTime()+dfPC/100.0*dfDuration;
00334         ((Fl_Clock*)GetByID(ID_CLOCK))->value((int)dfT);
00335         m_dfSeekTime = dfT;
00336         return m_PlayBack.GotoTime(dfT);
00337     }
00338     else
00339     {
00340         StopTimer();
00341     }
00342     return true;
00343 
00344 }
00345 bool CPlaybackWindow::OnWarp()
00346 {
00347     if(Fl::event()&FL_RELEASE)
00348     {
00349         double dfWarp = ((Fl_Counter*)GetByID(ID_WARP))->value();
00350         m_PlayBack.SetTickInterval(dfWarp*m_dfTimerInterval);
00351     }
00352     return true;
00353 }
00354 
00355 bool CPlaybackWindow::OnFile()
00356 {
00357     //here we try to recall the last file we opened
00358     Fl_Preferences app( Fl_Preferences::USER, "MOOS", "uPlayback" );
00359 
00360     char path[ FL_PATH_MAX ];
00361     app.getUserdataPath( path, sizeof(path) );
00362 
00363     char LastFile[FL_PATH_MAX];
00364     app.get("LastFile",LastFile,"*",sizeof(LastFile));
00365 
00366     const char * pFile = fl_file_chooser("Select an alog file", "*.alog", LastFile);
00367 
00368     bool bInitialised = false;
00369     if(pFile)
00370     {
00371         //CWaitCursor Cursor;
00372         GetRootWindow()->cursor(FL_CURSOR_WAIT );
00373 
00374         GetByID(ID_PROGRESS)->label("LOADING AND PARSING ALOG...PLEASE WAIT");
00375 
00376         redraw();
00377 
00378         Fl::wait();
00379 
00380         while (!bInitialised)
00381         {
00382             if(m_PlayBack.Initialise(pFile))
00383             {
00384                 m_sFileName = std::string(pFile);
00385                 pSourceCheck->clear();
00386 
00387                 STRING_SET Sources = m_PlayBack.GetSources();
00388                 STRING_SET::iterator p;
00389                 int i =0;
00390                 for(p = Sources.begin();p!= Sources.end();p++)
00391                 {
00392                     pSourceCheck->add(p->c_str(),1);
00393                 }
00394 
00395                 GetByID(ID_SOURCE)->activate();
00396                 GetByID(ID_CLOCK)->activate();
00397 
00398                 //here we save the last file we opened
00399                 app.set( "LastFile",pFile );
00400 
00401                 GetByID(ID_PROGRESS)->label(pFile);
00402 
00403                 //lets tell the user how much data has been loaded
00404                 static char sNumRecords[128];
00405                 sprintf(sNumRecords,"%d records",m_PlayBack.m_ALog.GetLineCount());
00406                 GetByID(ID_SOURCE)->label(sNumRecords);
00407 
00408                 bInitialised = true;
00409             }
00410             else
00411             {
00412                 int v = fl_choice("Cannot find index file for this alog.  Would you like to create one?",
00413                         "No", "Yes", NULL);
00414 
00415                 if (v == 0)
00416                     break;
00417                 else
00418                 {
00419                     indexWriter idxWriter;
00420                     idxWriter.parseAlogFile(string(pFile));
00421                     idxWriter.writeIndexFile(string(pFile)+string(".idx"));
00422                 }
00423 
00424             }
00425 
00426         }
00427 
00428         GetRootWindow()->cursor(FL_CURSOR_DEFAULT );
00429     }    
00430 
00431     take_focus();
00432     return bInitialised;
00433 }
00434 
00435 Fl_Window * CPlaybackWindow::GetRootWindow()
00436 {
00437     Fl_Widget * p=this;
00438     while(1)
00439     {
00440         if(p->parent()==NULL)
00441             return (Fl_Window *)p;
00442         else
00443             p = p->parent();
00444     }
00445 }
00446 
00447 bool CPlaybackWindow::OnMOOS()
00448 {
00449 
00450     if(m_Comms.IsConnected())
00451     {
00452         m_Comms.Close();
00453     }
00454     
00455     //next line is pretty crucial...
00456     m_Comms.FakeSource(true);
00457     m_Comms.SetOnConnectCallBack(MOOSConnectCallBack,(void*)this);
00458     m_Comms.SetOnDisconnectCallBack(MOOSDisconnectCallBack,(void*)this);
00459 
00460     //here we try to 
00461     Fl_Preferences app( Fl_Preferences::USER, "MOOS", "uPlayback" );
00462     app.set("HostName",m_sServerHost.c_str());
00463     app.set("HostPort",(int)(m_lServerPort));
00464 
00465     return m_Comms.Run(m_sServerHost.c_str(),m_lServerPort,"uPlayback",DEFAULT_COMMS_TICK);
00466 }
00467 
00468 bool CPlaybackWindow::OnMOOSDisconnect()
00469 {
00470     SetTitle();
00471     return true;
00472 }
00473 
00474 
00475 bool CPlaybackWindow::OnMOOSConnect()
00476 {
00477     SetTitle();
00478     redraw();
00479     return true;
00480 }
00481 
00482 
00483 bool CPlaybackWindow::OnPlayButton()
00484 {
00485     MakeMessageFilter();
00486     m_nTimerHits = 0;
00487 
00488     StartTimer(m_dfTimerInterval);
00489 
00490     return true;
00491 }
00492 bool CPlaybackWindow::OnNewMail(MOOSMSG_LIST &NewMail)
00493 {
00494 
00495     CMOOSMsg Msg;
00496     if (m_Comms.PeekMail(NewMail,"PLAYBACK_CHOKE",Msg))
00497     {
00498         double dfLastTimeProcessed = Msg.m_dfVal;
00499         m_PlayBack.SetLastTimeProcessed(dfLastTimeProcessed);
00500     }
00501 
00502     return true;
00503 }
00504 
00505 bool CPlaybackWindow::OnStopButton() 
00506 {
00507     StopTimer();
00508     return true;
00509 }
00510 
00511 
00512 void CPlaybackWindow::OnTimer()
00513 {
00514     if (m_Comms.IsConnected())
00515     {
00516         MOOSMSG_LIST NewMail;
00517         if(m_Comms.Fetch(NewMail))
00518         {
00519             OnNewMail(NewMail);
00520         }
00521     }
00522 
00523     MOOSMSG_LIST Output;
00524 
00525     if(m_PlayBack.Iterate(Output))
00526     {
00527         MOOSMSG_LIST::iterator p;
00528 
00529         for(p = Output.begin();p!=Output.end();p++)
00530         {
00531             CMOOSMsg & rMsg = *p;
00532 
00533             if(m_Comms.IsConnected())
00534             {
00535                 m_Comms.Post(rMsg);
00536             }
00537         }
00538     }
00539     else
00540     {
00541         if(m_PlayBack.IsEOF())
00542         {
00543             OnStopButton();
00544         }
00545     }
00546 
00547     if((m_nTimerHits++)%25==0)
00548     {
00549         ShowProgress();
00550     }
00551     
00552 }
00553 
00554 bool CPlaybackWindow::ShowProgress()
00555 {
00556     //show percent elapsed
00557     double dfProgress =0;
00558     double dfDuration = m_PlayBack.GetFinishTime()-m_PlayBack.GetStartTime();
00559     double dfElapsed = m_PlayBack.GetLastMessageTime()-m_PlayBack.GetStartTime();
00560 
00561     ((Fl_Clock*)GetByID(ID_CLOCK))->value((int)m_PlayBack.GetLastMessageTime());
00562     if(1 || dfElapsed>=0)
00563     {
00564         dfProgress = 100.0*(dfElapsed)/(dfDuration);
00565         ((Fl_Counter*)GetByID(ID_PROGRESS))->value(dfProgress);
00566     }
00567     Fl_Clock* pClock = (Fl_Clock*)GetByID(ID_CLOCK);
00568 
00569     static char Time[256];
00570     sprintf(Time,"%.2d:%.2d.%.2d",pClock->hour(),pClock->minute(),pClock->second());
00571     pClock->label(Time);
00572 
00573     
00574     return true;
00575 }
00576 
00577 
00578 bool CPlaybackWindow::MakeMessageFilter()
00579 {
00580     m_PlayBack.ClearFilter();
00581 
00582     for(int i = 0;i<=pSourceCheck->nitems();i++)
00583     {
00584         char * pText = pSourceCheck->text(i);
00585         if(pText!=NULL)
00586         {
00587             std::string sSrc(pText);
00588             bool bWanted = pSourceCheck->checked(i)?true:false;
00589             m_PlayBack.Filter(sSrc,bWanted);
00590         }
00591     }
00592 
00593     return true;
00594 }
00595 
00596 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines