From c0218be3699344340d54480855781383e13a5ffe Mon Sep 17 00:00:00 2001 From: edouard Date: Thu, 20 Jan 2011 22:28:38 +0000 Subject: [PATCH] OP-263 Update Logging plugin to prepare the scopes auto stop/start. Logging replay is now done through the connection manager, as a virtual device. Pressing "Connect" prompts for the file to be replayed. git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@2494 ebee16cc-31ac-478f-84a7-5cbb03baadba --- ground/src/plugins/logging/logfile.cpp | 25 ++++- ground/src/plugins/logging/logfile.h | 3 + ground/src/plugins/logging/loggingplugin.cpp | 103 ++++++++++++++----- ground/src/plugins/logging/loggingplugin.h | 39 ++++++- 4 files changed, 141 insertions(+), 29 deletions(-) diff --git a/ground/src/plugins/logging/logfile.cpp b/ground/src/plugins/logging/logfile.cpp index 1cabc104d..70df96c06 100644 --- a/ground/src/plugins/logging/logfile.cpp +++ b/ground/src/plugins/logging/logfile.cpp @@ -8,10 +8,22 @@ LogFile::LogFile(QObject *parent) : connect(&timer, SIGNAL(timeout()), this, SLOT(timerFired())); } +/** + * Opens the logfile QIODevice and the underlying logfile. In case + * we want to save the logfile, we open in WriteOnly. In case we + * want to read the logfile, we open in ReadOnly. + */ bool LogFile::open(OpenMode mode) { // start a timer for playback myTime.restart(); + if (file.isOpen()) { + // We end up here when doing a replay, because the connection + // manager will also try to open the QIODevice, even though we just + // opened it after selecting the file, which happens before the + // connection manager call... + return true; + } if(file.open(mode) == FALSE) { @@ -23,18 +35,25 @@ bool LogFile::open(OpenMode mode) { // they can be read back if ID's change // Must call parent function for QIODevice to pass calls to writeData - QIODevice::open(mode); + // We always open ReadWrite, because otherwise we will get tons of warnings + // during a logfile replay. Read nature is checked upon write ops below. + QIODevice::open(QIODevice::ReadWrite); return true; } void LogFile::close() { + if (timer.isActive()) + timer.stop(); file.close(); QIODevice::close(); } qint64 LogFile::writeData(const char * data, qint64 dataSize) { + if (!file.isWritable()) + return dataSize; + quint32 timeStamp = myTime.elapsed(); file.write((char *) &timeStamp,sizeof(timeStamp)); @@ -48,6 +67,7 @@ qint64 LogFile::writeData(const char * data, qint64 dataSize) { } qint64 LogFile::readData(char * data, qint64 maxSize) { + QMutexLocker locker(&mutex); qint64 toRead = qMin(maxSize,(qint64)dataBuffer.size()); memcpy(data,dataBuffer.data(),toRead); dataBuffer.remove(0,toRead); @@ -65,6 +85,7 @@ void LogFile::timerFired() if(file.bytesAvailable() > 4) { + // TODO: going back in time will be a problem while ((myTime.elapsed() - timeOffset) * playbackSpeed > lastTimeStamp) { @@ -80,7 +101,9 @@ void LogFile::timerFired() return; } + mutex.lock(); dataBuffer.append(file.read(dataSize)); + mutex.unlock(); emit readyRead(); if(file.bytesAvailable() < 4) { diff --git a/ground/src/plugins/logging/logfile.h b/ground/src/plugins/logging/logfile.h index 6cd03a685..6e6676d08 100644 --- a/ground/src/plugins/logging/logfile.h +++ b/ground/src/plugins/logging/logfile.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,8 @@ protected: QTime myTime; QFile file; qint32 lastTimeStamp; + QMutex mutex; + int timeOffset; int pausedTime; diff --git a/ground/src/plugins/logging/loggingplugin.cpp b/ground/src/plugins/logging/loggingplugin.cpp index 4a5ee9159..3d72ffb4a 100644 --- a/ground/src/plugins/logging/loggingplugin.cpp +++ b/ground/src/plugins/logging/loggingplugin.cpp @@ -47,6 +47,78 @@ #include "uavobjects/uavobjectmanager.h" #include + +LoggingConnection::LoggingConnection() +{ + +} + +LoggingConnection::~LoggingConnection() +{ +} + +void LoggingConnection::onEnumerationChanged() +{ + emit availableDevChanged(this); +} + +QStringList LoggingConnection::availableDevices() +{ + QStringList list; + list << "Logfile replay..."; + + return list; +} + +QIODevice* LoggingConnection::openDevice(const QString &deviceName) +{ + if (logFile.isOpen()){ + logFile.close(); + } + QFileDialog * fd = new QFileDialog(); + fd->setAcceptMode(QFileDialog::AcceptOpen); + fd->setNameFilter("OpenPilot Log (*.opl)"); + connect(fd, SIGNAL(fileSelected(QString)), this, SLOT(startReplay(QString))); + fd->exec(); + return &logFile; +} + +void LoggingConnection::startReplay(QString file) +{ + logFile.setFileName(file); + if(logFile.open(QIODevice::ReadOnly)) { + qDebug() << "Replaying " << file; + // state = REPLAY; + logFile.startReplay(); + } +} + +void LoggingConnection::closeDevice(const QString &deviceName) +{ + Q_UNUSED(deviceName); + //we have to delete the serial connection we created + if (logFile.isOpen()){ + logFile.close(); + m_deviceOpened = false; + } +} + + +QString LoggingConnection::connectionName() +{ + return QString("Logfile replay"); +} + +QString LoggingConnection::shortName() +{ + return QString("Logfile"); +} + + + + + + /** * Sets the file to use for logging and takes the parent plugin * to connect to stop logging signal @@ -259,7 +331,7 @@ bool LoggingPlugin::initialize(const QStringList& args, QString *errMsg) QList() << Core::Constants::C_GLOBAL_ID); cmd->setDefaultKeySequence(QKeySequence("Ctrl+L")); - cmd->action()->setText("Logging..."); + cmd->action()->setText("Start logging..."); ac->menu()->addSeparator(); ac->appendGroup("Logging"); @@ -268,6 +340,7 @@ bool LoggingPlugin::initialize(const QStringList& args, QString *errMsg) connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(toggleLogging())); // Command to replay logging + /* Core::Command* cmd2 = am->registerAction(new QAction(this), "LoggingPlugin.Playback", QList() << @@ -279,6 +352,7 @@ bool LoggingPlugin::initialize(const QStringList& args, QString *errMsg) ac->addAction(cmd2, "Replay"); connect(cmd2->action(), SIGNAL(triggered(bool)), this, SLOT(toggleReplay())); + */ mf = new LoggingGadgetFactory(this); addAutoReleasedObject(mf); @@ -353,31 +427,6 @@ void LoggingPlugin::startLogging(QString file) } } -/** - * Starts the logging thread replaying a certain file - */ -void LoggingPlugin::startReplay(QString file) -{ - - logFile.setFileName(file); - if(logFile.open(QIODevice::ReadOnly)) { - qDebug() << "Replaying " << file; - state = REPLAY; - - ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); - UAVObjectManager *objManager = pm->getObject(); - - uavTalk = new UAVTalk(&logFile, objManager); - logFile.startReplay(); - - emit stateChanged("REPLAY"); - } else { - QErrorMessage err; - err.showMessage("Unable to open file for replay"); - err.exec(); - } -} - /** * Send the stop logging signal to the LoggingThread */ @@ -428,7 +477,7 @@ void LoggingPlugin::replayStopped() void LoggingPlugin::extensionsInitialized() { - // Do nothing + addAutoReleasedObject(new LoggingConnection); } void LoggingPlugin::shutdown() diff --git a/ground/src/plugins/logging/loggingplugin.h b/ground/src/plugins/logging/loggingplugin.h index 1c4f65791..3c57cb6de 100644 --- a/ground/src/plugins/logging/loggingplugin.h +++ b/ground/src/plugins/logging/loggingplugin.h @@ -27,6 +27,7 @@ #ifndef LOGGINGPLUGIN_H_ #define LOGGINGPLUGIN_H_ +#include #include #include #include "uavobjects/gcstelemetrystats.h" @@ -40,6 +41,43 @@ class LoggingPlugin; class LoggingGadgetFactory; +/** +* Define a connection via the IConnection interface +* Plugin will add a instance of this class to the pool, +* so the connection manager can use it. +*/ +class LoggingConnection + : public Core::IConnection +{ + Q_OBJECT +public: + LoggingConnection(); + virtual ~LoggingConnection(); + + virtual QStringList availableDevices(); + virtual QIODevice *openDevice(const QString &deviceName); + virtual void closeDevice(const QString &deviceName); + + virtual QString connectionName(); + virtual QString shortName(); + + bool deviceOpened() {return m_deviceOpened;} + + +private: + LogFile logFile; + + +protected slots: + void onEnumerationChanged(); + void startReplay(QString file); + +protected: + bool m_deviceOpened; +}; + + + class LoggingThread : public QThread { Q_OBJECT @@ -99,7 +137,6 @@ private slots: void toggleLogging(); void toggleReplay(); void startLogging(QString file); - void startReplay(QString file); void stopLogging(); void loggingStopped(); void replayStopped();