LP-311 Remove basic/advanced stabilization tab auto-switch (autotune/txpid lock issues)
[librepilot.git] / ground / gcs / src / libs / utils / logfile.cpp
blob4dad41bf30c6823eb85a3f1809f62992cfebd32b
1 #include "logfile.h"
2 #include <QDebug>
3 #include <QtGlobal>
5 LogFile::LogFile(QObject *parent) :
6 QIODevice(parent),
7 m_lastTimeStamp(0),
8 m_lastPlayed(0),
9 m_timeOffset(0),
10 m_playbackSpeed(1.0),
11 m_nextTimeStamp(0),
12 m_useProvidedTimeStamp(false)
14 connect(&m_timer, SIGNAL(timeout()), this, SLOT(timerFired()));
17 /**
18 * Opens the logfile QIODevice and the underlying logfile. In case
19 * we want to save the logfile, we open in WriteOnly. In case we
20 * want to read the logfile, we open in ReadOnly.
22 bool LogFile::open(OpenMode mode)
24 // start a timer for playback
25 m_myTime.restart();
26 if (m_file.isOpen()) {
27 // We end up here when doing a replay, because the connection
28 // manager will also try to open the QIODevice, even though we just
29 // opened it after selecting the file, which happens before the
30 // connection manager call...
31 return true;
34 if (m_file.open(mode) == false) {
35 qDebug() << "Unable to open " << m_file.fileName() << " for logging";
36 return false;
39 // TODO: Write a header at the beginng describing objects so that in future
40 // they can be read back if ID's change
42 // Must call parent function for QIODevice to pass calls to writeData
43 // We always open ReadWrite, because otherwise we will get tons of warnings
44 // during a logfile replay. Read nature is checked upon write ops below.
45 QIODevice::open(QIODevice::ReadWrite);
47 return true;
50 void LogFile::close()
52 emit aboutToClose();
54 if (m_timer.isActive()) {
55 m_timer.stop();
57 m_file.close();
58 QIODevice::close();
61 qint64 LogFile::writeData(const char *data, qint64 dataSize)
63 if (!m_file.isWritable()) {
64 return dataSize;
67 // If m_nextTimeStamp != -1 then use this timestamp instead of the timer
68 // This is used when saving logs from on-board logging
69 quint32 timeStamp = m_useProvidedTimeStamp ? m_nextTimeStamp : m_myTime.elapsed();
71 m_file.write((char *)&timeStamp, sizeof(timeStamp));
72 m_file.write((char *)&dataSize, sizeof(dataSize));
74 qint64 written = m_file.write(data, dataSize);
75 if (written != -1) {
76 emit bytesWritten(written);
79 return dataSize;
82 qint64 LogFile::readData(char *data, qint64 maxSize)
84 QMutexLocker locker(&m_mutex);
85 qint64 toRead = qMin(maxSize, (qint64)m_dataBuffer.size());
87 memcpy(data, m_dataBuffer.data(), toRead);
88 m_dataBuffer.remove(0, toRead);
89 return toRead;
92 qint64 LogFile::bytesAvailable() const
94 return m_dataBuffer.size();
97 void LogFile::timerFired()
99 qint64 dataSize;
101 if (m_file.bytesAvailable() > 4) {
102 int time;
103 time = m_myTime.elapsed();
105 // TODO: going back in time will be a problem
106 while ((m_lastPlayed + ((time - m_timeOffset) * m_playbackSpeed) > m_lastTimeStamp)) {
107 m_lastPlayed += ((time - m_timeOffset) * m_playbackSpeed);
108 if (m_file.bytesAvailable() < (qint64)sizeof(dataSize)) {
109 stopReplay();
110 return;
113 m_file.read((char *)&dataSize, sizeof(dataSize));
115 if (dataSize < 1 || dataSize > (1024 * 1024)) {
116 qDebug() << "Error: Logfile corrupted! Unlikely packet size: " << dataSize << "\n";
117 stopReplay();
118 return;
121 if (m_file.bytesAvailable() < dataSize) {
122 stopReplay();
123 return;
126 m_mutex.lock();
127 m_dataBuffer.append(m_file.read(dataSize));
128 m_mutex.unlock();
130 emit readyRead();
132 if (m_file.bytesAvailable() < (qint64)sizeof(m_lastTimeStamp)) {
133 stopReplay();
134 return;
137 int save = m_lastTimeStamp;
138 m_file.read((char *)&m_lastTimeStamp, sizeof(m_lastTimeStamp));
139 // some validity checks
140 if (m_lastTimeStamp < save // logfile goes back in time
141 || (m_lastTimeStamp - save) > (60 * 60 * 1000)) { // gap of more than 60 minutes)
142 qDebug() << "Error: Logfile corrupted! Unlikely timestamp " << m_lastTimeStamp << " after " << save << "\n";
143 stopReplay();
144 return;
147 m_timeOffset = time;
148 time = m_myTime.elapsed();
150 } else {
151 stopReplay();
155 bool LogFile::startReplay()
157 m_dataBuffer.clear();
158 m_myTime.restart();
159 m_timeOffset = 0;
160 m_lastPlayed = 0;
161 m_file.read((char *)&m_lastTimeStamp, sizeof(m_lastTimeStamp));
162 m_timer.setInterval(10);
163 m_timer.start();
164 emit replayStarted();
165 return true;
168 bool LogFile::stopReplay()
170 close();
171 emit replayFinished();
172 return true;
175 void LogFile::pauseReplay()
177 m_timer.stop();
180 void LogFile::resumeReplay()
182 m_timeOffset = m_myTime.elapsed();
183 m_timer.start();