Skip to content
Snippets Groups Projects
LogReplayLink.h 7.67 KiB
Newer Older
  • Learn to ignore specific revisions
  • /****************************************************************************
     *
    
     *   (c) 2009-2018 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
    
     *
     * QGroundControl is licensed according to the terms in the file
     * COPYING.md in the root of the source code directory.
     *
     ****************************************************************************/
    
    #pragma once
    
    Don Gagne's avatar
     
    Don Gagne committed
    #include "LinkManager.h"
    
    Don Gagne's avatar
    Don Gagne committed
    #include "MAVLinkProtocol.h"
    
    #include <QTimer>
    #include <QFile>
    
    class LogReplayLinkConfiguration : public LinkConfiguration
    {
    
    Don Gagne's avatar
    Don Gagne committed
        Q_OBJECT
    
    
    Don Gagne's avatar
    Don Gagne committed
    public:
    
        Q_PROPERTY(QString  fileName    READ logFilename    WRITE setLogFilename    NOTIFY fileNameChanged)
    
    
    Don Gagne's avatar
    Don Gagne committed
        LogReplayLinkConfiguration(const QString& name);
        LogReplayLinkConfiguration(LogReplayLinkConfiguration* copy);
    
    Don Gagne's avatar
    Don Gagne committed
        QString logFilename(void) { return _logFilename; }
    
        void setLogFilename(const QString logFilename) { _logFilename = logFilename; emit fileNameChanged(); }
    
    Don Gagne's avatar
    Don Gagne committed
        QString logFilenameShort(void);
    
        // Virtuals from LinkConfiguration
    
        LinkType    type                    () { return LinkConfiguration::TypeLogReplay; }
        void        copyFrom                (LinkConfiguration* source);
        void        loadSettings            (QSettings& settings, const QString& root);
        void        saveSettings            (QSettings& settings, const QString& root);
        void        updateSettings          ();
    
        QString     settingsURL             () { return "LogReplaySettings.qml"; }
    
        QString     settingsTitle           () { return tr("Log Replay Link Settings"); }
    
    Don Gagne's avatar
     
    Don Gagne committed
    
    
    signals:
        void fileNameChanged();
    
    Don Gagne's avatar
    Don Gagne committed
    
    private:
        static const char*  _logFilenameKey;
        QString             _logFilename;
    };
    
    class LogReplayLink : public LinkInterface
    {
        Q_OBJECT
    
        friend class LinkManager;
    
    Don Gagne's avatar
    Don Gagne committed
    public:
        /// @return true: log is currently playing, false: log playback is paused
        bool isPlaying(void) { return _readTickTimer.isActive(); }
    
    Don Gagne's avatar
     
    Don Gagne committed
        void play           (void) { emit _playOnThread(); }
        void pause          (void) { emit _pauseOnThread(); }
        void movePlayhead   (qreal percentComplete);
    
    Don Gagne's avatar
    Don Gagne committed
        // Virtuals from LinkInterface
    
    Don Gagne's avatar
     
    Don Gagne committed
        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; }
    
    Don Gagne's avatar
    Don Gagne committed
    
        // 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.
    
    Don Gagne's avatar
     
    Don Gagne committed
        bool connect    (void);
        bool disconnect (void);
    
    public slots:
        /// Sets the acceleration factor: -100: 0.01X, 0: 1.0X, 100: 100.0X
        void setPlaybackSpeed(qreal playbackSpeed) { emit _setPlaybackSpeedOnThread(playbackSpeed); }
    
        virtual void _writeBytes(const QByteArray bytes);
    
    Don Gagne's avatar
    Don Gagne committed
    signals:
    
    Don Gagne's avatar
     
    Don Gagne committed
        void logFileStats                   (int logDurationSecs);
        void playbackStarted                (void);
        void playbackPaused                 (void);
        void playbackAtEnd                  (void);
        void playbackPercentCompleteChanged (qreal percentComplete);
        void currentLogTimeSecs             (int secs);
    
    Don Gagne's avatar
    Don Gagne committed
        // Internal signals
    
    Don Gagne's avatar
     
    Don Gagne committed
        void _playOnThread              (void);
        void _pauseOnThread             (void);
        void _setPlaybackSpeedOnThread  (qreal playbackSpeed);
    
    Don Gagne's avatar
    Don Gagne committed
    
    private slots:
    
    Don Gagne's avatar
     
    Don Gagne committed
        void _readNextLogEntry  (void);
        void _play              (void);
        void _pause             (void);
        void _setPlaybackSpeed  (qreal playbackSpeed);
    
    Don Gagne's avatar
    Don Gagne committed
    
    private:
        // Links are only created/destroyed by LinkManager so constructor/destructor is not public
    
        LogReplayLink(SharedLinkConfigurationPointer& config);
    
    Don Gagne's avatar
    Don Gagne committed
        ~LogReplayLink();
    
    Don Gagne's avatar
     
    Don Gagne committed
        void    _replayError                (const QString& errorMsg);
        quint64 _parseTimestamp             (const QByteArray& bytes);
        quint64 _seekToNextMavlinkMessage   (mavlink_message_t* nextMsg);
        quint64 _findLastTimestamp          (void);
        quint64 _readNextMavlinkMessage     (QByteArray& bytes);
        bool    _loadLogFile                (void);
        void    _finishPlayback             (void);
        void    _resetPlaybackToBeginning   (void);
        void    _signalCurrentLogTimeSecs   (void);
    
    Don Gagne's avatar
    Don Gagne committed
        // Virtuals from LinkInterface
    
    Don Gagne's avatar
     
    Don Gagne committed
        virtual bool _connect   (void);
    
    Don Gagne's avatar
    Don Gagne committed
        virtual void _disconnect(void);
    
    Don Gagne's avatar
    Don Gagne committed
        // Virtuals from QThread
        virtual void run(void);
    
        LogReplayLinkConfiguration* _logReplayConfig;
    
    Don Gagne's avatar
    Don Gagne committed
    
        bool    _connected;
    
    Don Gagne's avatar
     
    Don Gagne committed
        uint8_t _mavlinkChannel;
    
    Don Gagne's avatar
    Don Gagne committed
        QTimer  _readTickTimer;      ///< Timer which signals a read of next log record
    
        QString _errorTitle; ///< Title for communicatorError signals
    
    Don Gagne's avatar
    Don Gagne committed
        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;
    
    Don Gagne's avatar
     
    Don Gagne committed
        qreal   _playbackSpeed;
    
    Don Gagne's avatar
    Don Gagne committed
        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.
    
    Don Gagne's avatar
     
    Don Gagne committed
        quint64 _playbackStartLogTimeUSecs;
    
    Don Gagne's avatar
    Don Gagne committed
        MAVLinkProtocol*    _mavlink;
        QFile               _logFile;
        quint64             _logFileSize;
    
    Don Gagne's avatar
    Don Gagne committed
        static const int cbTimestamp = sizeof(quint64);
    };
    
    
    Don Gagne's avatar
     
    Don Gagne committed
    class LogReplayLinkController : public QObject
    {
        Q_OBJECT
    
    public:
        Q_PROPERTY(LogReplayLink*   link            READ link               WRITE setLink               NOTIFY linkChanged)
        Q_PROPERTY(bool             isPlaying       READ isPlaying          WRITE setIsPlaying          NOTIFY isPlayingChanged)
        Q_PROPERTY(qreal            percentComplete READ percentComplete    WRITE setPercentComplete    NOTIFY percentCompleteChanged)
        Q_PROPERTY(QString          totalTime       MEMBER _totalTime                                   NOTIFY totalTimeChanged)
        Q_PROPERTY(QString          playheadTime    MEMBER _playheadTime                                NOTIFY playheadTimeChanged)
    
    Don Gagne's avatar
     
    Don Gagne committed
        Q_PROPERTY(qreal            playbackSpeed   MEMBER _playbackSpeed                               NOTIFY playbackSpeedChanged)
    
    Don Gagne's avatar
     
    Don Gagne committed
    
        LogReplayLinkController(void);
    
        LogReplayLink*  link            (void) { return _link; }
        bool            isPlaying       (void) { return _isPlaying; }
        qreal           percentComplete (void) { return _percentComplete; }
    
        void setLink            (LogReplayLink* link);
        void setIsPlaying       (bool isPlaying);
        void setPercentComplete (qreal percentComplete);
    
    signals:
        void linkChanged            (LogReplayLink* link);
        void isPlayingChanged       (bool isPlaying);
        void percentCompleteChanged (qreal percentComplete);
        void playheadTimeChanged    (QString playheadTime);
        void totalTimeChanged       (QString totalTime);
    
    Don Gagne's avatar
     
    Don Gagne committed
        void playbackSpeedChanged   (qreal playbackSpeed);
    
    Don Gagne's avatar
     
    Don Gagne committed
    
    private slots:
    
    Don Gagne's avatar
     
    Don Gagne committed
        void _logFileStats                   (int logDurationSecs);
    
    Don Gagne's avatar
     
    Don Gagne committed
        void _playbackStarted                (void);
        void _playbackPaused                 (void);
        void _playbackAtEnd                  (void);
        void _playbackPercentCompleteChanged (qreal percentComplete);
        void _currentLogTimeSecs             (int secs);
        void _linkDisconnected               (void);
    
    private:
        QString _secondsToHMS(int seconds);
    
        LogReplayLink*  _link;
        bool            _isPlaying;
        qreal           _percentComplete;
        int             _playheadSecs;
        QString         _playheadTime;
        QString         _totalTime;
    
    Don Gagne's avatar
     
    Don Gagne committed
        qreal           _playbackSpeed;
    
    Don Gagne's avatar
     
    Don Gagne committed
    };