source: pacpusframework/trunk/src/DBITEPlayerLib/DbtPlyFileManager.cpp@ 12

Last change on this file since 12 was 3, checked in by sgosseli, 12 years ago
  • Add the existing Pacpus files from pacpusdev and pacpuscore.
  • Provide a clean build system based on multiple CMake files.
File size: 11.7 KB
Line 
1////////////////////////////////////////////////////////////////////////////////
2// created: 2007/04/12 - 16:30
3//
4// author: Elie Al Alam & Gerald Dherbomez
5//
6// version: $Id: DbtPlyFileManager.cpp 1020 2012-12-19 09:39:40Z kurdejma $
7//
8// purpose: Dbite Player File Manager implementation
9//
10// todo: manage a vector of dbite files and update the functions
11// playModen and configureComponent to support this funtionnality
12//
13// Put the type of data that has just been replayed in a protected
14// variable of the abstract class in order to the derived class can
15// know what to do
16//
17// complete the function playMode2
18//
19// sortir la variable kMaxPendingTimeFromEngineMicrosecs en propriété
20////////////////////////////////////////////////////////////////////////////////
21
22#include "DbitePlayer/DbtPlyFileManager.h"
23
24#include "kernel/ComponentManager.h"
25#include "kernel/DbiteException.h"
26#include "kernel/Log.h"
27
28#include <cassert>
29#include <iostream>
30#include <limits>
31#include <QMetaType>
32#include <QSemaphore>
33
34using namespace std;
35
36namespace pacpus {
37
38DECLARE_STATIC_LOGGER("pacpus.core.DbtPlyFileManager");
39
40const string kPropertyVerbose = "verbose";
41const int kPropertyVerboseDefaultValue = 1;
42
43const string kPropertyDbiteFileName = "dbt";
44
45// It is the maximum time elapsed between the computation of the tDbt and the data replay in microseconds
46static const int kMaxPendingTimeFromEngineMicrosecs = 10000;
47
48////////////////////////////////////////////////////////////////////////////////
49/// Constructor.
50DbtPlyFileManager::DbtPlyFileManager(QString name):ComponentBase(name)
51{
52 LOG_TRACE("constructor");
53
54 sync_ = new QSemaphore(1);
55 sync_->acquire();
56 tMin_ = numeric_limits<road_time_t>::max();
57 tMax_ = numeric_limits<road_time_t>::min();
58}
59
60////////////////////////////////////////////////////////////////////////////////
61/// Destructor.
62DbtPlyFileManager::~DbtPlyFileManager()
63{
64 LOG_TRACE("destructor");
65
66 for (QList<dbtStructFile>::iterator it = dbt_.begin(), itend = dbt_.end(); it != itend; ++it) {
67 dbtStructFile & dbtFile = *it;
68
69 delete[] dbtFile.cur.buffer;
70 delete[] dbtFile.toProcess.buffer;
71 }
72}
73
74////////////////////////////////////////////////////////////////////////////////
75/// Configures the file manager.
76ComponentBase::COMPONENT_CONFIGURATION DbtPlyFileManager::configureComponent(XmlComponentConfig config)
77{
78 ComponentManager * mgr = ComponentManager::getInstance();
79 mEngine = static_cast<DbtPlyEngine *>(mgr->getComponent("dbiteEngine"));
80 if (NULL == mEngine ) {
81 LOG_FATAL("cannot get a pointer of the 'dbiteEngine' component");
82 return CONFIGURED_FAILED;
83 }
84 if (!mEngine->isConfigured()) {
85 LOG_WARN("'dbiteEngine' component was not configured");
86 return CONFIGURATION_DELAYED;
87 }
88
89 // Qt Signal-Slot connections
90 // register the road_time_t type for the connection
91 qRegisterMetaType<road_time_t>("road_time_t");
92 connect(mEngine, SIGNAL(play(road_time_t,road_time_t, bool)),
93 this, SLOT(playData(road_time_t,road_time_t, bool)),
94 Qt::DirectConnection);
95 connect(this, SIGNAL(tMinMaxIs(road_time_t,road_time_t )),
96 mEngine, SLOT(tMinMax(road_time_t, road_time_t)));
97 connect(mEngine, SIGNAL(stopfile()),
98 this, SLOT (beginfile()));
99
100
101 // get the properties in the XML node
102 /////////////////////////////////////////
103 {
104 QString verbose = param.getProperty(kPropertyVerbose.c_str());
105 if (verbose.isNull()) {
106 LOG_INFO("property " << kPropertyVerbose << " not set."
107 << " Set to default = " << kPropertyVerboseDefaultValue
108 );
109 // default value
110 mVerbose = kPropertyVerboseDefaultValue;
111 } else {
112 verbose = verbose.toLower();
113 LOG_DEBUG("property " << kPropertyVerbose << "=\""
114 << verbose.toStdString() << "\"");
115 mVerbose = verbose.toInt();
116 LOG_DEBUG("property interpreted as " << kPropertyVerbose << "=\""
117 << mVerbose << "\"");
118 }
119 }
120
121 /////////////////////////////////////////
122 dbtProperty_ = param.getProperty(kPropertyDbiteFileName.c_str());
123 mShowGui = param.getProperty("ui").toInt();
124 mDbtDataPath = mEngine->getDataDir();
125
126 mDbtFilenameList = dbtProperty_.split("|");
127
128 for (int i = 0; i < mDbtFilenameList.size(); ++i) {
129 mDbtFilenameList[i] = mDbtDataPath + mDbtFilenameList.at(i);
130 LOG_INFO("opening DBT file \"" << mDbtFilenameList.at(i) << "\"");
131
132 // temporary dbt object
133 dbtStructFile dbt;
134 dbt.pfile = new DbiteFile();
135 assert(dbt.pfile);
136 try {
137 dbt.pfile->open(mDbtFilenameList.at(i).toStdString(), ReadMode);
138 } catch (DbiteException & e) {
139 LOG_ERROR("cannot open DBT file \"" << mDbtFilenameList.at(i) << "\"");
140 LOG_DEBUG("error: " << e.what());
141 return CONFIGURED_FAILED;
142 }
143 if (!dbt.pfile->isOpen()) {
144 LOG_ERROR("cannot open DBT file \"" << mDbtFilenameList.at(i) << "\"");
145 return CONFIGURED_FAILED;
146 }
147 cout << "Header: " << "\n"
148 << (string) *dbt.pfile << "\n";
149
150 // alloc buffer with the Data Size given in the header
151 dbt.cur.buffer = new char[dbt.pfile->getRecordSize()];
152 dbt.toProcess.buffer = new char[dbt.pfile->getRecordSize()];
153
154 dbt_.insert(i, dbt);
155
156 // Reading of the first data to put in the buffer_
157 dbt_[i].pfile->readRecord(dbt_[i].cur.t, dbt_[i].cur.tr, reinterpret_cast<char *>(dbt_[i].cur.buffer));
158
159 if (dbt_.at(i).pfile->getRecordCount() > 0) {
160 if (dbt_.at(i).pfile->getTimeMin() < tMin_) {
161 tMin_ = dbt_.at(i).pfile->getTimeMin();
162 }
163 if (dbt_.at(i).pfile->getTimeMax() > tMax_ ) {
164 tMax_ = dbt_.at(i).pfile->getTimeMax();
165 }
166 Q_EMIT tMinMaxIs(tMin_, tMax_);
167 }
168 }
169
170 return CONFIGURED_OK;
171}
172
173////////////////////////////////////////////////////////////////////////////////
174/// Starts activity of the file manager
175void DbtPlyFileManager::startActivity()
176{
177 // graphical user interface
178 if (mShowGui) {
179 displayUI();
180 }
181
182 deltaTDbtTabLoop_ = 0;
183
184 mode_ = mEngine->replayMode();
185 LOG_INFO("replay mode " << mode_);
186 start();
187}
188
189////////////////////////////////////////////////////////////////////////////////
190/// Stops activity of the file manager
191void DbtPlyFileManager::stopActivity()
192{
193 deltaTDbtTabLoop_ = 0;
194}
195
196void DbtPlyFileManager::displayUI()
197{
198 //LOG_WARN("component '" << componentName << "' has no user interface. Please set ui property to 0 in your XML configuration");
199}
200
201////////////////////////////////////////////////////////////////////////////////
202/// Goes back to the beginning of the file.
203/// Places the descriptor to the first data.
204void DbtPlyFileManager::beginfile()
205{
206 LOG_DEBUG("called beginfile()");
207 for (QList<dbtStructFile>::iterator it = dbt_.begin(), itend = dbt_.end(); it != itend; ++it) {
208 dbtStructFile & dbtFile = *it;
209
210 dbtFile.pfile->goToDataBegin();
211 // reinitialize buffer and times to the 1st value
212 dbtFile.pfile->readRecord(dbtFile.cur.t, dbtFile.cur.tr, reinterpret_cast<char *>(dbtFile.cur.buffer));
213 }
214}
215
216bool DbtPlyFileManager::processDbtFileHdfile(dbtStructFile & dbtFile, DbiteFile::ReadDirection direction)
217{
218 dbtFile.toProcess.t = dbtFile.cur.t;
219 dbtFile.toProcess.tr = dbtFile.cur.tr;
220 memcpy(dbtFile.toProcess.buffer, dbtFile.cur.buffer, dbtFile.pfile->getRecordSize());
221
222 if (!dbtFile.pfile->readRecord(dbtFile.cur.t, dbtFile.cur.tr, reinterpret_cast<char *>(dbtFile.cur.buffer), direction)) {
223 LOG_WARN("EOF or there was a problem in read function, no data read");
224 dbtFile.cur.t = tMax_;
225 return false;
226 }
227 return true;
228}
229
230////////////////////////////////////////////////////////////////////////////////
231/// play mode 1
232/// the player replays only the last data that has not been yet replayed
233void DbtPlyFileManager::playMode1(road_time_t tDbt, bool reverse)
234{
235 DbiteFile::ReadDirection readDirection = DbiteFile::ReadForward;
236 if (reverse) {
237 readDirection = DbiteFile::ReadBackward;
238 }
239
240 dbtIndex_ = 0;
241 for (QList<dbtStructFile>::iterator it = dbt_.begin(), itend = dbt_.end(); it != itend; ++it) {
242 dbtStructFile & dbtFile = *it;
243
244 bool mustProcess = false;
245 if (reverse) {
246 // backward
247 while (dbtFile.cur.t > tDbt) {
248 mustProcess = true;
249 if (!processDbtFileHdfile(dbtFile, readDirection)) {
250 break;
251 }
252 }
253 } else {
254 // forward
255 while (dbtFile.cur.t < tDbt) {
256 mustProcess = true;
257 if (!processDbtFileHdfile(dbtFile, readDirection)) {
258 break;
259 }
260 }
261 }
262
263 if (mustProcess) {
264 processData(dbtFile.cur.t, dbtFile.toProcess.tr, dbtFile.cur.buffer);
265 }
266 ++dbtIndex_;
267 }
268}
269
270////////////////////////////////////////////////////////////////////////////////
271// play mode 2
272// the player replays all the data that have not been yet replayed
273void DbtPlyFileManager::playMode2(road_time_t tDbt, bool reverse)
274{
275 DbiteFile::ReadDirection readDirection = DbiteFile::ReadForward;
276 if (reverse) {
277 readDirection = DbiteFile::ReadBackward;
278 }
279
280 dbtIndex_ = 0;
281 for (QList<dbtStructFile>::iterator it = dbt_.begin(), itend = dbt_.end(); it != itend; ++it) {
282 dbtStructFile & dbtFile = *it;
283
284 if (reverse) {
285 // backward
286 while (dbtFile.cur.t > tDbt) {
287 processDbtFileHdfile(dbtFile, readDirection);
288 processData(dbtFile.cur.t, dbtFile.toProcess.tr, dbtFile.cur.buffer);
289 }
290 } else {
291 // forward
292 while (dbtFile.cur.t < tDbt) {
293 processDbtFileHdfile(dbtFile, readDirection);
294 processData(dbtFile.cur.t, dbtFile.toProcess.tr, dbtFile.cur.buffer);
295 }
296 }
297 ++dbtIndex_;
298 }
299}
300
301////////////////////////////////////////////////////////////////////////////////
302// slot
303// Called by the player engine
304// Before replaying data, this funtion verifies that the replayed time is
305// included in the time interval of the data and that the time elapsed between
306// the estimation of this replayed time is not too big
307void DbtPlyFileManager::playData(road_time_t tDbt,road_time_t tNow, bool reverse)
308{
309 // If tDbt is not included in the time interval of the data, we don't have any data to play
310 if ((tDbt>tMax_) || (tDbt<tMin_)) {
311 return;
312 }
313
314 // measure the difference between the current time and the tNow used to calculate the tDbt
315 int deltaT = road_time() - tNow;
316 deltaTDbtTab_[(deltaTDbtTabLoop_++)%1000] = deltaT;
317 if (deltaT > kMaxPendingTimeFromEngineMicrosecs) {
318 LOG_WARN(componentName << ": data not replayed: elapsed time since engine notification too big:" << deltaT << "us");
319 return;
320 }
321
322 timeToRead_ = tDbt;
323 reverse_ = reverse;
324 sync_->release();
325}
326
327////////////////////////////////////////////////////////////////////////////////
328/// Main loop of the thread.
329/// Only synchronize on the player engine and when activated call the correct
330/// replay method.
331void DbtPlyFileManager::run()
332{
333 for (;;) {
334 sync_->acquire();
335
336 switch (mode_) {
337 case 1:
338 playMode1(timeToRead_, reverse_);
339 break;
340
341 case 2:
342 playMode2(timeToRead_, reverse_);
343 break;
344
345 default:
346 break;
347 }
348 }
349}
350
351} // namespace pacpus
Note: See TracBrowser for help on using the repository browser.