#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include "cereal/messaging/messaging.h" #include "tools/cabana/dbc/dbcmanager.h" #include "tools/cabana/utils/util.h" #include "tools/replay/util.h" struct CanData { void compute(const MessageId &msg_id, const uint8_t *dat, const int size, double current_sec, double playback_speed, const std::vector &mask, double in_freq = 0); double ts = 0.; uint32_t count = 0; double freq = 0; std::vector dat; std::vector colors; struct ByteLastChange { double ts = 0; int delta = 0; int same_delta_counter = 0; bool suppressed = false; }; std::vector last_changes; std::vector> bit_flip_counts; double last_freq_update_ts = 0; }; struct CanEvent { uint8_t src; uint32_t address; uint64_t mono_time; uint8_t size; uint8_t dat[]; }; struct CompareCanEvent { constexpr bool operator()(const CanEvent *const e, uint64_t ts) const { return e->mono_time < ts; } constexpr bool operator()(uint64_t ts, const CanEvent *const e) const { return ts < e->mono_time; } }; typedef std::unordered_map> MessageEventsMap; using CanEventIter = std::vector::const_iterator; class AbstractStream : public QObject { Q_OBJECT public: AbstractStream(QObject *parent); virtual ~AbstractStream() {} virtual void start() = 0; virtual bool liveStreaming() const { return true; } virtual void seekTo(double ts) {} virtual QString routeName() const = 0; virtual QString carFingerprint() const { return ""; } virtual QDateTime beginDateTime() const { return {}; } virtual uint64_t beginMonoTime() const { return 0; } virtual double minSeconds() const { return 0; } virtual double maxSeconds() const { return 0; } virtual void setSpeed(float speed) {} virtual double getSpeed() { return 1; } virtual bool isPaused() const { return false; } virtual void pause(bool pause) {} void setTimeRange(const std::optional> &range); const std::optional> &timeRange() const { return time_range_; } inline double currentSec() const { return current_sec_; } inline uint64_t toMonoTime(double sec) const { return beginMonoTime() + std::max(sec, 0.0) * 1e9; } inline double toSeconds(uint64_t mono_time) const { return std::max(0.0, (mono_time - beginMonoTime()) / 1e9); } inline const std::unordered_map &lastMessages() const { return last_msgs; } bool isMessageActive(const MessageId &id) const; inline const MessageEventsMap &eventsMap() const { return events_; } inline const std::vector &allEvents() const { return all_events_; } const CanData &lastMessage(const MessageId &id) const; const std::vector &events(const MessageId &id) const; std::pair eventsInRange(const MessageId &id, std::optional> time_range) const; size_t suppressHighlighted(); void clearSuppressed(); void suppressDefinedSignals(bool suppress); signals: void paused(); void resume(); void seeking(double sec); void seekedTo(double sec); void timeRangeChanged(const std::optional> &range); void eventsMerged(const MessageEventsMap &events_map); void msgsReceived(const std::set *new_msgs, bool has_new_ids); void sourcesUpdated(const SourceSet &s); void privateUpdateLastMsgsSignal(); public: SourceSet sources; protected: void mergeEvents(const std::vector &events); const CanEvent *newEvent(uint64_t mono_time, const cereal::CanData::Reader &c); void updateEvent(const MessageId &id, double sec, const uint8_t *data, uint8_t size); void waitForSeekFinshed(); std::vector all_events_; double current_sec_ = 0; std::optional> time_range_; private: void updateLastMessages(); void updateLastMsgsTo(double sec); void updateMasks(); MessageEventsMap events_; std::unordered_map last_msgs; std::unique_ptr event_buffer_; // Members accessed in multiple threads. (mutex protected) std::mutex mutex_; std::condition_variable seek_finished_cv_; bool seek_finished_ = false; std::set new_msgs_; std::unordered_map messages_; std::unordered_map> masks_; }; class AbstractOpenStreamWidget : public QWidget { Q_OBJECT public: AbstractOpenStreamWidget(QWidget *parent = nullptr) : QWidget(parent) {} virtual AbstractStream *open() = 0; signals: void enableOpenButton(bool); }; class DummyStream : public AbstractStream { Q_OBJECT public: DummyStream(QObject *parent) : AbstractStream(parent) {} QString routeName() const override { return tr("No Stream"); } void start() override {} }; // A global pointer referring to the unique AbstractStream object extern AbstractStream *can;