LogReplayLink.h 5.82 KB
Newer Older
Don Gagne's avatar
Don Gagne committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
/*=====================================================================

 QGroundControl Open Source Ground Control Station

 (c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>

 This file is part of the QGROUNDCONTROL project

 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.

 ======================================================================*/

#ifndef LogReplayLink_H
#define LogReplayLink_H

#include "LinkInterface.h"
#include "LinkConfiguration.h"
#include "MAVLinkProtocol.h"

#include <QTimer>
#include <QFile>

class LogReplayLinkConfiguration : public LinkConfiguration
{
Don Gagne's avatar
Don Gagne committed
36 37
    Q_OBJECT

Don Gagne's avatar
Don Gagne committed
38 39 40
public:
    LogReplayLinkConfiguration(const QString& name);
    LogReplayLinkConfiguration(LogReplayLinkConfiguration* copy);
41

Don Gagne's avatar
Don Gagne committed
42 43
    QString logFilename(void) { return _logFilename; }
    void setLogFilename(const QString& logFilename) { _logFilename = logFilename; }
44

Don Gagne's avatar
Don Gagne committed
45 46 47
    QString logFilenameShort(void);

    // Virtuals from LinkConfiguration
48
    virtual LinkType type() { return LinkConfiguration::TypeLogReplay; }
Don Gagne's avatar
Don Gagne committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
    virtual void copyFrom(LinkConfiguration* source);
    virtual void loadSettings(QSettings& settings, const QString& root);
    virtual void saveSettings(QSettings& settings, const QString& root);
    virtual void updateSettings();

private:
    static const char*  _logFilenameKey;
    QString             _logFilename;
};

class LogReplayLink : public LinkInterface
{
    Q_OBJECT

    friend class LinkManager;
64

Don Gagne's avatar
Don Gagne committed
65 66 67
public:
    /// @return true: log is currently playing, false: log playback is paused
    bool isPlaying(void) { return _readTickTimer.isActive(); }
68

Don Gagne's avatar
Don Gagne committed
69 70
    /// Start replay at current position
    void play(void) { emit _playOnThread(); }
71

Don Gagne's avatar
Don Gagne committed
72 73
    /// Pause replay
    void pause(void) { emit _pauseOnThread(); }
74

Don Gagne's avatar
Don Gagne committed
75 76
    /// Move the playhead to the specified percent complete
    void movePlayhead(int percentComplete);
77

Don Gagne's avatar
Don Gagne committed
78 79
    /// Sets the acceleration factor: -100: 0.01X, 0: 1.0X, 100: 100.0X
    void setAccelerationFactor(int factor) { emit _setAccelerationFactorOnThread(factor); }
80

Don Gagne's avatar
Don Gagne committed
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    // Virtuals from LinkInterface
    virtual QString getName(void) const { return _config->name(); }
    virtual void requestReset(void){ }
    virtual bool isConnected(void) const { return _connected; }
    virtual qint64 getConnectionSpeed(void) const { return 100000000; }
    virtual qint64 bytesAvailable(void) { return 0; }
    virtual bool isLogReplay(void) { return true; }

    // These are left unimplemented in order to cause linker errors which indicate incorrect usage of
    // connect/disconnect on link directly. All connect/disconnect calls should be made through LinkManager.
    bool connect(void);
    bool disconnect(void);

public slots:
    virtual void writeBytes(const char *bytes, qint64 cBytes);
96

Don Gagne's avatar
Don Gagne committed
97 98 99 100 101 102 103
signals:
    void logFileStats(bool logTimestamped, int logDurationSecs, int binaryBaudRate);
    void playbackStarted(void);
    void playbackPaused(void);
    void playbackAtEnd(void);
    void playbackError(void);
    void playbackPercentCompleteChanged(int percentComplete);
104

Don Gagne's avatar
Don Gagne committed
105 106 107 108 109 110 111 112
    // Internal signals
    void _playOnThread(void);
    void _pauseOnThread(void);
    void _setAccelerationFactorOnThread(int factor);

protected slots:
    // FIXME: This should not be part of LinkInterface. It is an internal link implementation detail.
    virtual void readBytes(void);
113

Don Gagne's avatar
Don Gagne committed
114 115 116 117 118 119 120 121 122 123
private slots:
    void _readNextLogEntry(void);
    void _play(void);
    void _pause(void);
    void _setAccelerationFactor(int factor);

private:
    // Links are only created/destroyed by LinkManager so constructor/destructor is not public
    LogReplayLink(LogReplayLinkConfiguration* config);
    ~LogReplayLink();
124

Don Gagne's avatar
Don Gagne committed
125 126 127 128 129 130 131
    void _replayError(const QString& errorMsg);
    quint64 _parseTimestamp(const QByteArray& bytes);
    quint64 _seekToNextMavlinkMessage(mavlink_message_t* nextMsg);
    bool _loadLogFile(void);
    void _finishPlayback(void);
    void _playbackError(void);
    void _resetPlaybackToBeginning(void);
132

Don Gagne's avatar
Don Gagne committed
133 134
    // Virtuals from LinkInterface
    virtual bool _connect(void);
Don Gagne's avatar
Don Gagne committed
135
    virtual void _disconnect(void);
136

Don Gagne's avatar
Don Gagne committed
137 138
    // Virtuals from QThread
    virtual void run(void);
139

Don Gagne's avatar
Don Gagne committed
140 141 142 143
    LogReplayLinkConfiguration* _config;

    bool    _connected;
    QTimer _readTickTimer;      ///< Timer which signals a read of next log record
144

Don Gagne's avatar
Don Gagne committed
145
    static const char* _errorTitle; ///< Title for communicatorError signals
146

Don Gagne's avatar
Don Gagne committed
147 148 149 150
    quint64 _logCurrentTimeUSecs;   ///< The timestamp of the next message in the log file.
    quint64 _logStartTimeUSecs;     ///< The first timestamp in the current log file.
    quint64 _logEndTimeUSecs;       ///< The last timestamp in the current log file.
    quint64 _logDurationUSecs;
151

Don Gagne's avatar
Don Gagne committed
152 153
    static const int    _defaultBinaryBaudRate = 57600;
    int                 _binaryBaudRate;        ///< Playback rate for binary log format
154

Don Gagne's avatar
Don Gagne committed
155 156
    float   _replayAccelerationFactor;  ///< Factor to apply to playback rate
    quint64 _playbackStartTimeMSecs;    ///< The time when the logfile was first played back. This is used to pace out replaying the messages to fix long-term drift/skew. 0 indicates that the player hasn't initiated playback of this log file.
157

Don Gagne's avatar
Don Gagne committed
158 159 160 161
    MAVLinkProtocol*    _mavlink;
    QFile               _logFile;
    quint64             _logFileSize;
    bool                _logTimestamped;    ///< true: Timestamped log format, false: no timestamps
162

Don Gagne's avatar
Don Gagne committed
163 164 165 166
    static const int cbTimestamp = sizeof(quint64);
};

#endif