Skip to content

Commit ef3cb8b

Browse files
committed
LP-597 Progress bar for GCS log replay - switch to double-function button for Play/Pause
- remove separate play and pause buttons, combine these functions in one playPause button. - update icons & button texts - move resources (icons) to logging plugin's own images folder - explain why looking for the next timestamp after the last played one is useful. It causes the replay process to jump over parts of the logfile where no data has been recorded and jumps straight to the first timestamp after that part of the log where data is missing.
1 parent c53e99e commit ef3cb8b

10 files changed

Lines changed: 217 additions & 330 deletions

File tree

ground/gcs/src/libs/utils/logfile.cpp

Lines changed: 60 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -154,46 +154,29 @@ void LogFile::timerFired()
154154
if (m_replayStatus != PLAYING) {
155155
return;
156156
}
157-
158157
m_timer_tick++;
159-
if ( m_timer_tick % 100 == 0 ) {
160-
qDebug() << "----------------------------------------------------------";
161-
qDebug() << "LogFile::timerFired() -> Tick = " << m_timer_tick;
162-
}
163158

164159
if (m_file.bytesAvailable() > 4) {
165160
int time;
166161
time = m_myTime.elapsed();
167162

168163
/*
169-
This code generates an advancing window. All samples that fit in the window
164+
This code generates an advancing playback window. All samples that fit the window
170165
are replayed. The window is about the size of the timer interval: 10 ms.
171166
172167
Description of used variables:
173168
174-
time : time passed since start of playback (in ms) - current
175-
m_timeOffset : time passed since start of playback (in ms) - when timerFired() was previously run
176-
m_lastPlayed : next log timestamp to advance to (in ms)
177-
m_nextTimeStamp : timestamp of most recently read log entry (in ms)
178-
m_playbackSpeed : 1 .. 10 replay speedup factor
169+
time : real-time interval since start of playback (in ms) - now()
170+
m_timeOffset : real-time interval since start of playback (in ms) - when timerFired() was previously run
171+
m_nextTimeStamp : read log until this log timestamp has been reached (in ms)
172+
m_lastPlayed : log referenced timestamp advanced to during previous cycle (in ms)
173+
m_playbackSpeed : 0.1 .. 1.0 .. 10 replay speedup factor
179174
180175
*/
181176

182177
while ( m_nextTimeStamp < (m_lastPlayed + (double)(time - m_timeOffset) * m_playbackSpeed) ) {
183-
// if ( m_timer_tick % 100 == 0 ) {
184-
// if ( true ) {
185-
// qDebug() << "LogFile::timerFired() -> m_lastPlayed = " << m_lastPlayed;
186-
// qDebug() << "LogFile::timerFired() -> m_nextTimeStamp = " << m_nextTimeStamp;
187-
// qDebug() << "LogFile::timerFired() -> time = " << time;
188-
// qDebug() << "LogFile::timerFired() -> m_timeOffset = " << m_timeOffset;
189-
// qDebug() << "---";
190-
// qDebug() << "LogFile::timerFired() -> m_nextTimeStamp = " << m_nextTimeStamp;
191-
// qDebug() << "LogFile::timerFired() -> (m_lastPlayed + (double)(time - m_timeOffset) * m_playbackSpeed) = " << (m_lastPlayed + (double)(time - m_timeOffset) * m_playbackSpeed);
192-
// qDebug() << "---";
193-
// }
194178

195179
// advance the replay window for the next time period
196-
197180
m_lastPlayed += ((double)(time - m_timeOffset) * m_playbackSpeed);
198181

199182
// read data size
@@ -229,7 +212,7 @@ void LogFile::timerFired()
229212

230213
// rate-limit slider bar position updates to 10 updates per second
231214
if (m_timer_tick % 10 == 0) {
232-
emit replayPosition(m_nextTimeStamp);
215+
emit playbackPosition(m_nextTimeStamp);
233216
}
234217
// read next timestamp
235218
if (m_file.bytesAvailable() < (qint64)sizeof(m_nextTimeStamp)) {
@@ -269,13 +252,11 @@ bool LogFile::isPlaying() const
269252
* Starts a timer: m_timer
270253
*
271254
* This function and the stopReplay() function should only ever be called from the same thread.
272-
* This is required for correctly controlling the timer.
255+
* This is required for correct control of the timer.
273256
*
274257
*/
275258
bool LogFile::startReplay()
276259
{
277-
qDebug() << "startReplay(): start of function, current Thread ID is: " << QThread::currentThreadId();
278-
279260
// Walk through logfile and create timestamp index
280261
// Don't start replay if there was a problem indexing the logfile.
281262
if (!buildIndex()) {
@@ -325,8 +306,6 @@ bool LogFile::startReplay()
325306
*/
326307
bool LogFile::stopReplay()
327308
{
328-
qDebug() << "stopReplay(): start of function, current Thread ID is: " << QThread::currentThreadId();
329-
330309
if (!m_file.isOpen() || !m_timer.isActive()) {
331310
return false;
332311
}
@@ -338,41 +317,59 @@ bool LogFile::stopReplay()
338317
return true;
339318
}
340319

341-
342320
/**
343-
* SLOT: restartReplay()
321+
* SLOT: resumeReplay()
344322
*
345-
* This function starts replay from the begining of the currently opened logfile.
323+
* Resumes replay from the given position.
324+
* If no position is given, resumes from the last position
346325
*
347326
*/
348-
void LogFile::restartReplay()
327+
328+
bool LogFile::resumeReplay(quint32 desiredPosition)
349329
{
350-
qDebug() << "restartReplay(): start of function, current Thread ID is: " << QThread::currentThreadId();
330+
if (m_timer.isActive()) {
331+
return false;
332+
}
333+
334+
// Clear the playout buffer:
335+
m_mutex.lock();
336+
m_dataBuffer.clear();
337+
m_mutex.unlock();
351338

352-
resumeReplayFrom(0);
339+
m_file.seek(0);
353340

354-
qDebug() << "restartReplay(): end of function, current Thread ID is: " << QThread::currentThreadId();
355-
}
341+
/* Skip through the logfile until we reach the desired position.
342+
Looking for the next log timestamp after the desired position
343+
has the advantage that it skips over parts of the log
344+
where data might be missing.
345+
*/
346+
for (int i = 0; i < m_timeStamps.size(); i++) {
347+
if (m_timeStamps.at(i) >= desiredPosition) {
356348

357-
/**
358-
* SLOT: haltReplay()
359-
*
360-
* Stops replay without storing the current playback position
361-
*
362-
*/
363-
void LogFile::haltReplay()
364-
{
365-
qDebug() << "haltReplay(): start of function, current Thread ID is: " << QThread::currentThreadId();
349+
m_file.seek(m_timeStampPositions.at(i));
350+
m_lastPlayed = m_timeStamps.at(i);
351+
break;
352+
}
353+
}
354+
m_file.read((char *)&m_nextTimeStamp, sizeof(m_nextTimeStamp));
366355

367-
qDebug() << "haltReplay() time = m_myTime.elapsed() = " << m_myTime.elapsed();
368-
qDebug() << "haltReplay() m_timeOffset = " << m_timeOffset;
369-
qDebug() << "haltReplay() m_nextTimeStamp = " << m_nextTimeStamp;
370-
qDebug() << "haltReplay() m_lastPlayed = " << m_lastPlayed;
356+
// Real-time timestamps don't not need to match the log timestamps.
357+
// However the delta between real-time variables "m_timeOffset" and "m_myTime" is important.
358+
// This delta determines the number of log entries replayed per cycle.
371359

372-
m_replayStatus = STOPPED;
360+
// Set the real-time interval to 0 to start with:
361+
m_myTime.restart();
362+
m_timeOffset = 0;
363+
364+
m_replayStatus = PLAYING;
365+
366+
m_timer.start();
373367

374-
qDebug() << "haltReplay(): end of function, current Thread ID is: " << QThread::currentThreadId();
368+
// Notify UI that playback has resumed
369+
emit replayStarted();
370+
return true;
375371
}
372+
376373
/**
377374
* SLOT: pauseReplay()
378375
*
@@ -381,13 +378,6 @@ void LogFile::haltReplay()
381378
*/
382379
bool LogFile::pauseReplay()
383380
{
384-
qDebug() << "pauseReplay(): start of function, current Thread ID is: " << QThread::currentThreadId();
385-
386-
qDebug() << "pauseReplay() time = m_myTime.elapsed() = " << m_myTime.elapsed();
387-
qDebug() << "pauseReplay() m_timeOffset = " << m_timeOffset;
388-
qDebug() << "pauseReplay() m_nextTimeStamp = " << m_nextTimeStamp;
389-
qDebug() << "pauseReplay() m_lastPlayed = " << m_lastPlayed;
390-
391381
if (!m_timer.isActive()) {
392382
return false;
393383
}
@@ -401,97 +391,25 @@ bool LogFile::pauseReplay()
401391
}
402392

403393
/**
404-
* SLOT: resumeReplay()
394+
* SLOT: pauseAndResetPosition()
405395
*
406-
* Resumes replay from the stored playback position
396+
* Pauses replay and resets the playback position to the start of the logfile
407397
*
408398
*/
409-
bool LogFile::resumeReplay()
399+
bool LogFile::pauseAndResetPosition()
410400
{
411-
qDebug() << "resumeReplay(): start of function, current Thread ID is: " << QThread::currentThreadId();
412-
413-
m_mutex.lock();
414-
m_dataBuffer.clear();
415-
m_mutex.unlock();
416-
417-
m_file.seek(0);
418-
419-
for (int i = 0; i < m_timeStamps.size(); ++i) {
420-
if (m_timeStamps.at(i) >= m_lastPlayed) {
421-
m_file.seek(m_timeStampPositions.at(i));
422-
break;
423-
}
424-
}
425-
m_file.read((char *)&m_nextTimeStamp, sizeof(m_nextTimeStamp));
426-
427-
m_myTime.restart();
428-
m_myTime = m_myTime.addMSecs(-m_timeOffset); // Set startpoint this far back in time.
429-
430-
qDebug() << "resumeReplay() time = m_myTime.elapsed() = " << m_myTime.elapsed();
431-
qDebug() << "resumeReplay() m_timeOffset = " << m_timeOffset;
432-
qDebug() << "resumeReplay() m_nextTimeStamp = " << m_nextTimeStamp;
433-
qDebug() << "resumeReplay() m_lastPlayed = " << m_lastPlayed;
434-
435-
qDebug() << "resumeReplay(): end of function, current Thread ID is: " << QThread::currentThreadId();
436-
if (m_timer.isActive()) {
401+
if (!m_file.isOpen() || !m_timer.isActive()) {
437402
return false;
438403
}
439-
qDebug() << "LogFile - resumeReplay";
440-
m_timeOffset = m_myTime.elapsed();
441-
m_timer.start();
442-
m_replayStatus = PLAYING;
443-
444-
// Notify UI that replay has been resumed
445-
emit replayStarted();
446-
return true;
447-
}
448-
449-
/**
450-
* SLOT: resumeReplayFrom()
451-
*
452-
* Resumes replay from the given position
453-
*
454-
*/
455-
void LogFile::resumeReplayFrom(quint32 desiredPosition)
456-
{
457-
qDebug() << "resumeReplayFrom(): start of function, current Thread ID is: " << QThread::currentThreadId();
458-
459-
m_mutex.lock();
460-
m_dataBuffer.clear();
461-
m_mutex.unlock();
462-
463-
m_file.seek(0);
464-
465-
qint32 i;
466-
for (i = 0; i < m_timeStamps.size(); ++i) {
467-
if (m_timeStamps.at(i) >= desiredPosition) {
468-
m_file.seek(m_timeStampPositions.at(i));
469-
m_lastPlayed = m_timeStamps.at(i);
470-
break;
471-
}
472-
}
473-
m_file.read((char *)&m_nextTimeStamp, sizeof(m_nextTimeStamp));
474-
475-
if (m_nextTimeStamp != m_timeStamps.at(i)) {
476-
qDebug() << "resumeReplayFrom() m_nextTimeStamp != m_timeStamps.at(i) -> " << m_nextTimeStamp << " != " << m_timeStamps.at(i);
477-
}
478-
479-
// m_timeOffset = (m_lastPlayed - m_nextTimeStamp) / m_playbackSpeed;
480-
m_timeOffset = 0;
481-
482-
m_myTime.restart();
483-
// m_myTime = m_myTime.addMSecs(-m_timeOffset); // Set startpoint this far back in time.
484-
// TODO: The above line is a possible memory leak. I'm not sure how to handle this correctly.
485-
486-
qDebug() << "resumeReplayFrom() time = m_myTime.elapsed() = " << m_myTime.elapsed();
487-
qDebug() << "resumeReplayFrom() m_timeOffset = " << m_timeOffset;
488-
qDebug() << "resumeReplayFrom() m_nextTimeStamp = " << m_nextTimeStamp;
489-
qDebug() << "resumeReplayFrom() m_lastPlayed = " << m_lastPlayed;
404+
m_timer.stop();
405+
m_replayStatus = STOPPED;
490406

491-
m_replayStatus = PLAYING;
492-
emit replayStarted();
407+
m_timeOffset = 0;
408+
m_lastPlayed = m_timeStamps.at(0);
409+
m_previousTimeStamp = 0;
410+
m_nextTimeStamp = 0;
493411

494-
qDebug() << "resumeReplayFrom(): end of function, current Thread ID is: " << QThread::currentThreadId();
412+
return true;
495413
}
496414

497415
/**
@@ -532,7 +450,6 @@ bool LogFile::buildIndex()
532450
dataStream.readRawData((char *)&timeStamp, 4);
533451
m_timeStamps.append(timeStamp);
534452
m_timeStampPositions.append(readPointer);
535-
qDebug() << "LogFile::buildIndex() element index = " << index << " \t-> timestamp = " << timeStamp << " \t-> bytes in file = " << readPointer;
536453
readPointer += 4;
537454
index++;
538455
m_beginTimeStamp = timeStamp;
@@ -569,13 +486,11 @@ bool LogFile::buildIndex()
569486
// read the next timestamp
570487
if (totalSize - readPointer >= 4) {
571488
dataStream.readRawData((char *)&timeStamp, 4);
572-
qDebug() << "LogFile::buildIndex() element index = " << index << " \t-> timestamp = " << timeStamp << " \t-> bytes in file = " << readPointer;
573489

574490
// some validity checks
575491
if (timeStamp < m_endTimeStamp // logfile goes back in time
576492
|| (timeStamp - m_endTimeStamp) > (60 * 60 * 1000)) { // gap of more than 60 minutes)
577493
qDebug() << "Error: Logfile corrupted! Unlikely timestamp " << timeStamp << " after " << m_endTimeStamp;
578-
// return false;
579494
}
580495

581496
m_timeStamps.append(timeStamp);
@@ -589,30 +504,10 @@ bool LogFile::buildIndex()
589504
}
590505
}
591506

592-
qDebug() << "buildIndex() -> first timestamp in log = " << m_beginTimeStamp;
593-
qDebug() << "buildIndex() -> last timestamp in log = " << m_endTimeStamp;
594-
595507
emit updateBeginAndEndtimes(m_beginTimeStamp, m_endTimeStamp);
596508

597509
// reset the read pointer to the start of the file
598510
m_file.seek(0);
599511

600512
return true;
601513
}
602-
603-
/**
604-
* FUNCTION: setReplaySpeed()
605-
*
606-
* Update the replay speed.
607-
*
608-
* FIXME: currently, changing the replay speed, while skipping through the logfile
609-
* with the position bar causes position alignment to be lost.
610-
*
611-
*/
612-
void LogFile::setReplaySpeed(double val)
613-
{
614-
m_playbackSpeed = val;
615-
qDebug() << "Playback speed is now " << QString("%1").arg(m_playbackSpeed, 4, 'f', 2, QChar('0'));
616-
}
617-
618-

ground/gcs/src/libs/utils/logfile.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,22 +81,25 @@ class QTCREATOR_UTILS_EXPORT LogFile : public QIODevice {
8181
ReplayState getReplayStatus();
8282

8383
public slots:
84-
void setReplaySpeed(double val);
84+
void setReplaySpeed(double val)
85+
{
86+
m_playbackSpeed = val;
87+
qDebug() << "Playback speed is now" << m_playbackSpeed;
88+
};
8589
bool startReplay();
8690
bool stopReplay();
91+
92+
bool resumeReplay(quint32);
8793
bool pauseReplay();
88-
bool resumeReplay();
89-
void resumeReplayFrom(quint32);
90-
void restartReplay();
91-
void haltReplay();
94+
bool pauseAndResetPosition();
9295

9396
protected slots:
9497
void timerFired();
9598

9699
signals:
97100
void replayStarted();
98101
void replayFinished();
99-
void replayPosition(quint32);
102+
void playbackPosition(quint32);
100103
void updateBeginAndEndtimes(quint32, quint32);
101104

102105
protected:
1.31 KB
Loading
1.41 KB
Loading
970 Bytes
Loading

ground/gcs/src/plugins/logging/logging.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,5 @@ OTHER_FILES += LoggingGadget.pluginspec
2424

2525
FORMS += logging.ui
2626

27+
RESOURCES += \
28+
res.qrc

0 commit comments

Comments
 (0)