Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

FileSystemDataSource.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_FileSystemDataSource_h_
00003 #define INCLUDED_FileSystemDataSource_h_
00004 
00005 #include "local/DataSource.h"
00006 #include "Shared/plist.h"
00007 #include "Shared/get_time.h"
00008 #include <list>
00009 #include <iostream>
00010 
00011 class LoggedDataDriver;
00012 
00013 //! Manages the loading of a series of files from disk
00014 /*! Can handle an index file listing other data files and their timestamps,
00015  *  a directory holding a set of files, or a single explicit file. */
00016 class FileSystemDataSource : public virtual DataSource, public virtual plist::Dictionary, public virtual plist::PrimitiveListener {
00017 public:
00018   //! constructor
00019   FileSystemDataSource(LoggedDataDriver& p, const std::string& filter)
00020     : DataSource(), plist::Dictionary(), PrimitiveListener(), path(), filenameFilter(filter), loop(true), files(), curfile(files.begin()),
00021     initialDelay(0), nextTime(0), indexed(true), sn(0), freezeTime(), parent(p), actualLoopTime(0), naturalLoopTime(0)
00022   {
00023     setLoadSavePolicy(FIXED,SYNC);
00024     addEntry("Path",path,"If set, overrides the common LoggedData driver path.  In addition to directory or index file, can also be set to a single input data file.");
00025     addEntry("FileFilter",filenameFilter,"If Source is a directory or index file, only files matching the filter will be loaded from it.");
00026     addEntry("Loop",loop,"If true, restart file list at the beginning when the end is reached; otherwise just stop loading data");
00027   }
00028 
00029   //! destructor
00030   ~FileSystemDataSource();
00031   
00032   virtual unsigned int nextTimestamp();
00033   virtual const std::string& nextName();
00034   virtual unsigned int getData(const char *& payload, unsigned int& payloadSize, unsigned int& timestamp, std::string& name);
00035   virtual void setDataSourceThread(LoadDataThread* th);
00036   virtual void setDataSourceFramerate(float fr);
00037   
00038   //! sets the next frame to be sent (e.g. pass 0 to reset to the first frame)
00039   /*! prepares (pre-loads) @a numPreload frames from the new #curfile onward */
00040   virtual void setFrame(unsigned int f, unsigned int numPreload=2);
00041   
00042   //! increments #curfile to the next frame, preparing (pre-loads) @a numPreload frames from the new #curfile onward
00043   virtual void nextFrame(unsigned int numPreload=2);
00044   
00045   //! returns the total time taken to loop over the files
00046   /*! @param actual if false, will return the "natural" time of a loop, ignoring setLoopTime() effects */
00047   virtual float getLoopTime(bool actual=true) const { return actual ? actualLoopTime : naturalLoopTime; }
00048   virtual void setLoopTime(float t); //!< adds time to the final frame to increase total sequence time to @a t milliseconds
00049   
00050   virtual bool usingIndexFile() const { return indexed; } //!< returns #indexed
00051   
00052   //! empties #files
00053   void clearFiles();
00054   
00055   virtual void plistValueChanged(const plist::PrimitiveBase& pl);
00056   
00057   virtual void loadXML(xmlNode* node);
00058   
00059   //! returns the target path, either #path, or parent.path if #path is empty
00060   virtual const std::string& getUsedPath() const;
00061   
00062   //! call this to (re)load the list of available file names from disk
00063   /*! If @a clearCurrent is set, then the current file list will be cleared;
00064    *  otherwise, the loaded files will be appended to the current queue */
00065   virtual void loadFileList(bool clearCurrent=true, bool reportMissing=true);
00066   
00067   //! The directory, data file, or index file from which to load via call to loadFileListFromDirectory(), loadSingleFile(), or loadFileListFromIndex()
00068   /*! A single file can be either a single data file (e.g. sensor or camera image), or an index file as output by VisionGUI, or in the format 'filename <tab> time', where 'filename' is an absolute path or relative to the directory containing the index file, and 'time' is in milliseconds, relative to the time at which the index file is loaded.\n In the future, this could also be network addresses for teleoperation and remote processing. */
00069   plist::Primitive<std::string> path;
00070   
00071   //! a regular expression (POSIX.2 extended format) to select which files to load from #path, if #path is a directory or index file
00072   plist::Primitive<std::string> filenameFilter;
00073   
00074   //! controls whether to restart #curfile at the beginning of #files when it reaches the end
00075   plist::Primitive<bool> loop;
00076   
00077 protected:
00078   virtual void doFreeze() { freezeTime=get_time(); }
00079   virtual void doUnfreeze() { nextTime+=get_time()-freezeTime; }
00080   
00081   //! if thread is NULL, mark all outputs as ignored, and if thread is non-NULL, mark them all as provided
00082   virtual void updateProvidingOutputs();
00083   
00084   //! load a single file
00085   virtual void loadSingleFile(const std::string& file);
00086   //! load a list of files from a directory specified by #path
00087   virtual void loadFileListFromDirectory();
00088   //! load a list of files from an index file specified by #path
00089   /*! This supports either the format produced by VisionGUI, or a simplier '<code>filename [<tab> time]\\n</code>' format,
00090    *  where if @c time is unspecified, the frame's time is incremented by the #framerate from the previously listed file.
00091    *  Filenames should either be either absolute paths or relative to the directory which contains the index file.*/
00092   virtual bool loadFileListFromIndex();
00093   
00094   //! adds up the lifetime of all #files, plus #initialDelay
00095   virtual float calcLoopTime() const;
00096 
00097   //! does the actual work of loading and processing data from disk, subclasses should override this if they want to decompress/pre-parse the data
00098   /*! This implementation merely loads the data directly into memory with no processing or parsing.
00099    *  @param[in] file full path of file to load
00100    *  @return pointer to the data, or NULL if error */
00101   virtual char* loadData(const std::string& file);
00102   
00103   //! stores basic information regarding each file in the queue, including routines for loading to and from disk
00104   struct FileInfo {
00105     //! default constructor
00106     FileInfo() : filename(), lifetime(0), data(NULL), size(0), prepared(false) {}
00107     //! basic constructor, provide name and lifetime, data and size are left empty until later prepare() is called
00108     FileInfo(const std::string& name, float time) : filename(name), lifetime(time), data(NULL), size(0), prepared(false) {}
00109     //! shallow copy constructor -- doesn't copy #data (have to call prepare() to reload)
00110     FileInfo(const FileInfo& fi) : filename(fi.filename), lifetime(fi.lifetime), data(NULL), size(0), prepared(false) { }
00111     //! shallow assignment -- doesn't copy #data (have to call prepare() to reload)
00112     FileInfo& operator=(const FileInfo& fi) { release(); filename=fi.filename; lifetime=fi.lifetime; return *this; }
00113     //! destructor
00114     virtual ~FileInfo() { release(); }
00115     
00116     virtual void prepare(); //!< make sure data is in physical memory for imminent usage
00117     virtual void done(); //!< we can let the data out of memory if needed
00118     virtual void release(); //!< if data is in an allocated region, free it
00119     
00120     std::string filename; //!< the path to the file to load
00121     float lifetime; //!< time for which this frame is "current", before next frame should be sent
00122     char* data; //!< loaded/parsed contents of #filename, all ready to send, just need to copy into message
00123     unsigned int size; //!< size of buffer pointed to by #data (may be decompressed/processed, different than file size...)
00124     bool prepared; //!< true if prepare() has been called
00125   };
00126   
00127   //! creates a new entry on #files, virtual to allow subclasses to use a FileInfo subclass with more meta data (e.g. see FileSystemImageSource::ImageInfo)
00128   virtual void enqueueFile(const std::string& name, float lifetime) { files.push_back(new FileInfo(name,lifetime)); } 
00129   
00130   static const unsigned int MAX_LOAD=4000; //!< maximum number of data elements to try to keep 'active'.  If there's more than this in #files, we'll only load one at time, and immediately release it afterward
00131   typedef std::list<FileInfo*> files_t; //!< type of #files, the list of files to load
00132   files_t files; // collection of FileInfo entries
00133   files_t::iterator curfile; //!< an iterator referencing #files -- indicates next file to send
00134   float initialDelay; //!< milliseconds to wait before sending first frame
00135   float nextTime; //!< timestamp that #curfile should be sent
00136   bool indexed; //!< true if the file list was specified by an index file
00137   unsigned int sn; //!< frame serial number, incremented by getData()
00138   unsigned int freezeTime; //!< time at which doFreeze was called
00139   LoggedDataDriver& parent; //!< device driver this is a member of
00140   float actualLoopTime; //!< time it would take to run through all of the loaded frames
00141   float naturalLoopTime; //!< time it would take to run through all of the frames as set immediately after load (i.e. no setLoopTime())
00142 };
00143 
00144 /*! @file
00145  * @brief 
00146  * @author Ethan Tira-Thompson (ejt) (Creator)
00147  *
00148  * $Author: ejt $
00149  * $Name: tekkotsu-4_0 $
00150  * $Revision: 1.5 $
00151  * $State: Exp $
00152  * $Date: 2007/11/10 22:58:12 $
00153  */
00154 
00155 #endif

Tekkotsu Hardware Abstraction Layer 4.0
Generated Thu Nov 22 01:00:53 2007 by Doxygen 1.5.4