00001
00002 #ifndef INCLUDED_LoadDataThread_h_
00003 #define INCLUDED_LoadDataThread_h_
00004
00005 #include "IPC/PollThread.h"
00006 #include "Shared/plist.h"
00007 #include "IPC/MessageQueue.h"
00008 #include "Shared/get_time.h"
00009 #include "local/DeviceDriver.h"
00010 #include "local/DataSource.h"
00011 #include <list>
00012 #include <vector>
00013
00014
00015
00016
00017
00018 class LoadDataThread : public virtual PollThread, public virtual plist::Dictionary, public virtual plist::PrimitiveListener, public virtual plist::CollectionListener, public virtual DeviceDriver::SourceListener {
00019 public:
00020
00021 typedef void (DeviceDriver::*getDataSources_t)(std::map<std::string,DataSource*>&);
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 LoadDataThread(getDataSources_t getDS, float fps, MessageQueueBase& messages)
00035 : PollThread(), plist::Dictionary(),
00036 source(), framerate(fps), verbose(0), heartbeat(true), frozen(false),
00037 regions(), getDataSources(getDS), msgr(messages), lock(), lastSent(-1), frameSN(0), sourceSN(0), enabled(false), runloopState(INTERFRAME),
00038 curDS(NULL), dsDriver(NULL)
00039 {
00040 setLoadSavePolicy(FIXED,SYNC);
00041 addEntry("Source",source); getAvailableDataSources();
00042 addEntry("Framerate",framerate,"The rate at which images should be loaded. This is passed as a hint to the source, which may be limited to multiples of its capture device frequency.");
00043 addEntry("Verbose",verbose,"Controls how much feedback to give on the console regarding progress\n 0 - none\n 1 - report when messages are dropped\n 2 - also report when a message is sent\n 3 - also report when heartbeat is sent/dropped, and when loop occurs\n 4 - also report when each message is preloaded");
00044 addEntry("Heartbeat",heartbeat,"If enabled, an empty \"heartbeat\" message is sent at the appropriate framerate, even if no data is being processed (i.e. frozen, no data loaded, or out of frames); this will cause an update event within the simulator, repeating processing on the previous data.");
00045 addEntry("Frozen",frozen,"If true, no frames will be sent, except via explicit 'advance' commands; if false, the thread will run and send messages at the requested times automatically");
00046 source.addPrimitiveListener(this);
00047 framerate.addPrimitiveListener(this);
00048 verbose.addPrimitiveListener(this);
00049 heartbeat.addPrimitiveListener(this);
00050 frozen.addPrimitiveListener(this);
00051 DeviceDriver::getRegistry().addCollectionListener(this);
00052 }
00053
00054 ~LoadDataThread();
00055
00056
00057
00058
00059
00060 plist::Primitive<std::string> source;
00061
00062
00063 plist::Primitive<float> framerate;
00064
00065
00066
00067
00068
00069
00070
00071 plist::Primitive<int> verbose;
00072
00073
00074 plist::Primitive<bool> heartbeat;
00075
00076
00077 plist::Primitive<bool> frozen;
00078
00079
00080
00081
00082 virtual bool advanceFrame(bool forceQueue);
00083
00084 virtual void plistValueChanged(const plist::PrimitiveBase& pl);
00085 virtual void plistCollectionEntryAdded(Collection& , ObjectBase& ) { getAvailableDataSources(); }
00086 virtual void plistCollectionEntryRemoved(Collection& , ObjectBase& ) { getAvailableDataSources(); }
00087 virtual void plistCollectionEntriesChanged(Collection& ) { getAvailableDataSources(); }
00088 virtual void start();
00089 virtual void stop();
00090
00091
00092
00093 static char* deserializeHeader(char* buf, unsigned int size, unsigned int* verbose, unsigned int* sn, std::string* filename, bool* dataInQueue, unsigned int* payloadSize);
00094
00095 virtual unsigned int nextTimestamp() { return (curDS!=NULL) ? curDS->nextTimestamp() : -1U; }
00096 virtual const std::string& nextName() { return (curDS!=NULL) ? curDS->nextName() : emptyStr(); }
00097
00098 virtual DataSource* getDataSource() { return curDS; }
00099
00100 virtual void dataSourcesUpdated() { plistValueChanged(source); }
00101
00102
00103 std::string getAvailableDataSources();
00104
00105 virtual void loadXML(xmlNode* node) {
00106 plist::Dictionary::loadXML(node);
00107 getAvailableDataSources();
00108 }
00109
00110 protected:
00111
00112
00113 virtual void setDataSource(DeviceDriver* dd, DataSource* ds);
00114
00115
00116 virtual unsigned int runloop();
00117
00118
00119 virtual RCRegion* firstUnusedRegion();
00120
00121
00122 virtual char* setupRegion(RCRegion*& region, const std::string& file, unsigned int payload, bool hasMoreData);
00123
00124
00125 virtual void freeRegion(RCRegion* rcr) { if(rcr!=NULL) rcr->RemoveReference(); }
00126
00127
00128 virtual void sendHeartbeat() { sendHeartbeat(get_time()); }
00129
00130 virtual void sendHeartbeat(unsigned int curt);
00131
00132
00133 unsigned int calcNextHeartbeat(unsigned int curt) const;
00134
00135 unsigned int calcSleepTime() { unsigned int curt=get_time(); return static_cast<unsigned int>((calcNextHeartbeat(curt)-curt)/getTimeScale()); }
00136
00137 typedef std::list<RCRegion* > msgbuf_t;
00138 msgbuf_t regions;
00139
00140
00141 getDataSources_t getDataSources;
00142
00143 MessageQueueBase& msgr;
00144 Thread::Lock lock;
00145 float lastSent;
00146 unsigned int frameSN;
00147 unsigned int sourceSN;
00148 bool enabled;
00149 volatile enum {
00150 INTERFRAME,
00151 GET_FRAME,
00152 GOT_FRAME,
00153 ADVANCE_FRAME
00154 } runloopState;
00155
00156 DataSource * curDS;
00157 DeviceDriver * dsDriver;
00158
00159 private:
00160 LoadDataThread(const LoadDataThread&);
00161 LoadDataThread& operator=(const LoadDataThread&);
00162 };
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 #endif