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

Last change on this file since 255 was 181, checked in by Marek Kurdej, 11 years ago

Minor fixes. Clean-up.

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