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

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

Using boost::shared_ptr for storing components.

  • Property svn:executable set to *
File size: 10.8 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 using boost::dynamic_pointer_cast;
70
71 ComponentManager * mgr = ComponentManager::getInstance();
72 mEngine = dynamic_pointer_cast<DbtPlyEngine>(mgr->getComponent("dbiteEngine"));
73 if (!mEngine) {
74 LOG_FATAL("cannot get a pointer of the 'dbiteEngine' component");
75 return CONFIGURED_FAILED;
76 }
77 if (!mEngine->isConfigured()) {
78 LOG_WARN("'dbiteEngine' component was not configured");
79 return CONFIGURATION_DELAYED;
80 }
81
82 // Qt Signal-Slot connections
83 // register the road_time_t type for the connection
84 qRegisterMetaType<road_time_t>("road_time_t");
85 connect(mEngine.get(), SIGNAL(play(road_time_t,road_time_t, bool)),
86 this, SLOT(playData(road_time_t,road_time_t, bool)),
87 Qt::DirectConnection);
88 connect(this, SIGNAL(tMinMaxIs(road_time_t,road_time_t )),
89 mEngine.get(), SLOT(tMinMax(road_time_t, road_time_t)));
90 connect(mEngine.get(), SIGNAL(stopfile()),
91 this, SLOT (beginfile()));
92
93 // get the properties in the XML node
94 mDbtDataPath = mEngine->getDataDir();
95 mDbtFilenameList = QString(dbtProperty_.c_str()).split(kFilenameSeparator);
96
97 for (int i = 0; i < mDbtFilenameList.size(); ++i) {
98 mDbtFilenameList[i] = mDbtDataPath + mDbtFilenameList.at(i);
99 LOG_INFO("opening DBT file \"" << mDbtFilenameList.at(i) << "\"");
100
101 // temporary dbt object
102 dbtStructFile dbt;
103 dbt.pfile = new DbiteFile();
104 assert(dbt.pfile);
105 try {
106 dbt.pfile->open(mDbtFilenameList.at(i).toStdString(), ReadMode);
107 } catch (DbiteException & e) {
108 (void) e; // unused
109 LOG_ERROR("cannot open DBT file \"" << mDbtFilenameList.at(i) << "\"");
110 LOG_DEBUG("error: " << e.what());
111 return CONFIGURED_FAILED;
112 }
113 if (!dbt.pfile->isOpen()) {
114 LOG_ERROR("cannot open DBT file \"" << mDbtFilenameList.at(i) << "\"");
115 return CONFIGURED_FAILED;
116 }
117 cout << "Header: " << "\n"
118 << (string) *dbt.pfile << "\n";
119
120 // alloc buffer with the Data Size given in the header
121 dbt.cur.buffer = new char[dbt.pfile->getRecordSize()];
122 dbt.toProcess.buffer = new char[dbt.pfile->getRecordSize()];
123
124 dbt_.insert(i, dbt);
125
126 // Reading of the first data to put in the buffer_
127 dbt_[i].pfile->readRecord(dbt_[i].cur.t, dbt_[i].cur.tr, reinterpret_cast<char *>(dbt_[i].cur.buffer));
128
129 if (dbt_.at(i).pfile->getRecordCount() > 0) {
130 if (dbt_.at(i).pfile->getTimeMin() < tMin_) {
131 tMin_ = dbt_.at(i).pfile->getTimeMin();
132 }
133 if (dbt_.at(i).pfile->getTimeMax() > tMax_ ) {
134 tMax_ = dbt_.at(i).pfile->getTimeMax();
135 }
136 Q_EMIT tMinMaxIs(tMin_, tMax_);
137 }
138 }
139
140 return CONFIGURED_OK;
141}
142
143////////////////////////////////////////////////////////////////////////////////
144/// Starts activity of the file manager
145void DbtPlyFileManager::startActivity()
146{
147 // graphical user interface
148 if (hasGui()) {
149 displayUI();
150 }
151
152 deltaTDbtTabLoop_ = 0;
153
154 mode_ = mEngine->replayMode();
155 LOG_INFO("replay mode " << mode_);
156 start();
157}
158
159////////////////////////////////////////////////////////////////////////////////
160/// Stops activity of the file manager
161void DbtPlyFileManager::stopActivity()
162{
163 deltaTDbtTabLoop_ = 0;
164}
165
166void DbtPlyFileManager::displayUI()
167{
168 LOG_WARN("component '" << getName() << "' has no user interface. Please set ui property to 0 in your XML configuration");
169}
170
171////////////////////////////////////////////////////////////////////////////////
172/// Goes back to the beginning of the file.
173/// Places the descriptor to the first data.
174void DbtPlyFileManager::beginfile()
175{
176 LOG_DEBUG("called beginfile()");
177 for (QList<dbtStructFile>::iterator it = dbt_.begin(), itend = dbt_.end(); it != itend; ++it) {
178 dbtStructFile & dbtFile = *it;
179
180 dbtFile.pfile->goToDataBegin();
181 // reinitialize buffer and times to the 1st value
182 dbtFile.pfile->readRecord(dbtFile.cur.t, dbtFile.cur.tr, reinterpret_cast<char *>(dbtFile.cur.buffer));
183 }
184}
185
186bool DbtPlyFileManager::processDbtFileHdfile(dbtStructFile & dbtFile, DbiteFile::ReadDirection direction)
187{
188 dbtFile.toProcess.t = dbtFile.cur.t;
189 dbtFile.toProcess.tr = dbtFile.cur.tr;
190 memcpy(dbtFile.toProcess.buffer, dbtFile.cur.buffer, dbtFile.pfile->getRecordSize());
191
192 if (!dbtFile.pfile->readRecord(dbtFile.cur.t, dbtFile.cur.tr, reinterpret_cast<char *>(dbtFile.cur.buffer), direction)) {
193 LOG_WARN("EOF or there was a problem in read function, no data read");
194 dbtFile.cur.t = tMax_;
195 return false;
196 }
197 return true;
198}
199
200////////////////////////////////////////////////////////////////////////////////
201/// play mode 1
202/// the player replays only the last data that has not been yet replayed
203void DbtPlyFileManager::playMode1(road_time_t tDbt, bool reverse)
204{
205 DbiteFile::ReadDirection readDirection = DbiteFile::ReadForward;
206 if (reverse) {
207 readDirection = DbiteFile::ReadBackward;
208 }
209
210 dbtIndex_ = 0;
211 for (QList<dbtStructFile>::iterator it = dbt_.begin(), itend = dbt_.end(); it != itend; ++it) {
212 dbtStructFile & dbtFile = *it;
213
214 bool mustProcess = false;
215 if (reverse) {
216 // backward
217 while (dbtFile.cur.t > tDbt) {
218 mustProcess = true;
219 if (!processDbtFileHdfile(dbtFile, readDirection)) {
220 break;
221 }
222 }
223 } else {
224 // forward
225 while (dbtFile.cur.t < tDbt) {
226 mustProcess = true;
227 if (!processDbtFileHdfile(dbtFile, readDirection)) {
228 break;
229 }
230 }
231 }
232
233 if (mustProcess) {
234 processData(dbtFile.cur.t, dbtFile.toProcess.tr, dbtFile.cur.buffer);
235 }
236 ++dbtIndex_;
237 }
238}
239
240////////////////////////////////////////////////////////////////////////////////
241// play mode 2
242// the player replays all the data that have not been yet replayed
243void DbtPlyFileManager::playMode2(road_time_t tDbt, bool reverse)
244{
245 DbiteFile::ReadDirection readDirection = DbiteFile::ReadForward;
246 if (reverse) {
247 readDirection = DbiteFile::ReadBackward;
248 }
249
250 dbtIndex_ = 0;
251 for (QList<dbtStructFile>::iterator it = dbt_.begin(), itend = dbt_.end(); it != itend; ++it) {
252 dbtStructFile & dbtFile = *it;
253
254 if (reverse) {
255 // backward
256 while (dbtFile.cur.t > tDbt) {
257 processDbtFileHdfile(dbtFile, readDirection);
258 processData(dbtFile.cur.t, dbtFile.toProcess.tr, dbtFile.cur.buffer);
259 }
260 } else {
261 // forward
262 while (dbtFile.cur.t < tDbt) {
263 processDbtFileHdfile(dbtFile, readDirection);
264 processData(dbtFile.cur.t, dbtFile.toProcess.tr, dbtFile.cur.buffer);
265 }
266 }
267 ++dbtIndex_;
268 }
269}
270
271////////////////////////////////////////////////////////////////////////////////
272// slot
273// Called by the player engine
274// Before replaying data, this funtion verifies that the replayed time is
275// included in the time interval of the data and that the time elapsed between
276// the estimation of this replayed time is not too big
277void DbtPlyFileManager::playData(road_time_t tDbt,road_time_t tNow, bool reverse)
278{
279 // If tDbt is not included in the time interval of the data, we don't have any data to play
280 if ((tDbt>tMax_) || (tDbt<tMin_)) {
281 return;
282 }
283
284 // measure the difference between the current time and the tNow used to calculate the tDbt
285 int deltaT = road_time() - tNow;
286 deltaTDbtTab_[(deltaTDbtTabLoop_++)%1000] = deltaT;
287 if (deltaT > kMaxPendingTimeFromEngineMicrosecs) {
288 LOG_WARN(getName() << ": data not replayed: elapsed time since engine notification too big:" << deltaT << "us");
289 return;
290 }
291
292 timeToRead_ = tDbt;
293 reverse_ = reverse;
294 sync_->release();
295}
296
297////////////////////////////////////////////////////////////////////////////////
298/// Main loop of the thread.
299/// Only synchronize on the player engine and when activated call the correct
300/// replay method.
301void DbtPlyFileManager::run()
302{
303 for (;;) {
304 sync_->acquire();
305
306 switch (mode_) {
307 case 1:
308 playMode1(timeToRead_, reverse_);
309 break;
310
311 case 2:
312 playMode2(timeToRead_, reverse_);
313 break;
314
315 default:
316 break;
317 }
318 }
319}
Note: See TracBrowser for help on using the repository browser.