diff --git a/frameplaybackobject.cpp b/frameplaybackobject.cpp index 8f4f673..d9bc4c8 100644 --- a/frameplaybackobject.cpp +++ b/frameplaybackobject.cpp @@ -1,4 +1,5 @@ #include "frameplaybackobject.h" +#include FramePlaybackObject::FramePlaybackObject() { @@ -290,6 +291,47 @@ void FramePlaybackObject::pausePlayback() emit statusUpdate(currentPosition); } +void FramePlaybackObject::seekPlayback(double timestamp) +{ + if (currentSeqItem == NULL) + return; + + /* make sure we execute in mThread context */ + if (mThread_p && (mThread_p != QThread::currentThread())) + { + QMetaObject::invokeMethod(this, "seekPlayback", Qt::BlockingQueuedConnection, timestamp); + return; + } + + // playbackTimer->stop(); + // playbackActive = false; + + timestamp *= 1000000; // convert to us + + size_t lowIdx = 0; + size_t highIdx = currentSeqItem->data.count() - 1; + + while (lowIdx < highIdx) + { + int midIdx = lowIdx + (highIdx - lowIdx) / 2; + + CANFrame midFrame = currentSeqItem->data[midIdx]; + if (midFrame.timeStamp().seconds() * 1000000 + midFrame.timeStamp().microSeconds() < timestamp) + { + lowIdx = midIdx + 1; + } + else + { + highIdx = midIdx - 1; + } + } + + currentPosition = lowIdx; + emit statusUpdate(currentPosition); + + startPlaybackForward(); +} + void FramePlaybackObject::setSequenceObject(SequenceItem *item) { currentSeqItem = item; diff --git a/frameplaybackobject.h b/frameplaybackobject.h index 0935ffc..4662fe6 100644 --- a/frameplaybackobject.h +++ b/frameplaybackobject.h @@ -54,6 +54,7 @@ public slots: void stepPlaybackBackward(); void stopPlayback(); void pausePlayback(); + void seekPlayback(double timestamp); void setSequenceObject(SequenceItem *item); void setUseOriginalTiming(bool state); diff --git a/frameplaybackwindow.cpp b/frameplaybackwindow.cpp index 10cce13..1e70334 100644 --- a/frameplaybackwindow.cpp +++ b/frameplaybackwindow.cpp @@ -407,10 +407,24 @@ void FramePlaybackWindow::EndOfFrameCache() } } +void FramePlaybackWindow::gotCenterTimeID(uint32_t ID, double timestamp) +{ + Q_UNUSED(ID); + + // isPlaying = false; + // wantPlaying = false; + // haveIncomingTraffic = false; + + playbackObject.seekPlayback(timestamp); +} + void FramePlaybackWindow::getStatusUpdate(int frameNum) { currentPosition = frameNum; updateFrameLabel(); + QCanBusFrame::TimeStamp ts = seqItems[currentSeqNum].data[currentPosition].timeStamp(); + + emit sendCurrentTimestamp((double)(ts.seconds()) + ts.microSeconds() / 1000000.0f); } void FramePlaybackWindow::updateFrameLabel() @@ -426,15 +440,40 @@ void FramePlaybackWindow::updateFrameLabel() { ui->lblCurrPlayback->setText(""); ui->lblPosition->setText(""); + ui->timePosition->setText(""); return; } ui->lblCurrPlayback->setText(currentSeqItem->filename); + // convert current and last timestamp to text according to time format + QVariant currentTimestamp = Utility::formatTimestamp(seqItems[row].data[currentPosition].timeStamp().microSeconds()); + QString currentTimestampText; + if (currentTimestamp.typeId() == QMetaType::Double) + currentTimestampText = QString::number(currentTimestamp.toDouble(), 'f', 5); + else if (currentTimestamp.typeId() == QMetaType::LongLong || currentTimestamp.typeId() == QMetaType::ULongLong) + currentTimestampText = QString::number(currentTimestamp.toLongLong()); + else if (currentTimestamp.typeId() == QMetaType::QDateTime) + currentTimestampText = currentTimestamp.toDateTime().toString(Utility::timeFormat); + else + currentTimestampText = currentTimestamp.toString(); + + QVariant lastTimestamp = Utility::formatTimestamp(seqItems[row].data.last().timeStamp().microSeconds()); + QString lastTimestampText; + if (lastTimestamp.typeId() == QMetaType::Double) + lastTimestampText = QString::number(lastTimestamp.toDouble(), 'f', 5); + else if (lastTimestamp.typeId() == QMetaType::LongLong || lastTimestamp.typeId() == QMetaType::ULongLong) + lastTimestampText = QString::number(lastTimestamp.toLongLong()); + else if (lastTimestamp.typeId() == QMetaType::QDateTime) + lastTimestampText = lastTimestamp.toDateTime().toString(Utility::timeFormat); + else + lastTimestampText = lastTimestamp.toString(); + if (wantPlaying && !isPlaying) ui->lblPosition->setText(QString::number(currentPosition) + tr(" of ") + QString::number(seqItems[row].data.count()) + " (WAITING)"); else ui->lblPosition->setText(QString::number(currentPosition) + tr(" of ") + QString::number(seqItems[row].data.count())); + ui->timePosition->setText(currentTimestampText + tr(" of ") + lastTimestampText); } void FramePlaybackWindow::seqTableCellClicked(int row, int col) diff --git a/frameplaybackwindow.h b/frameplaybackwindow.h index a56bfc8..54c4876 100644 --- a/frameplaybackwindow.h +++ b/frameplaybackwindow.h @@ -42,10 +42,14 @@ private slots: void saveFilters(); void loadFilters(); void useOrigTimingClicked(); + void gotCenterTimeID(uint32_t ID, double timestamp); void getStatusUpdate(int frameNum); void EndOfFrameCache(); void updatedFrames(int); +signals: + void sendCurrentTimestamp(double timestamp); + private: Ui::FramePlaybackWindow *ui; QList foundID; diff --git a/mainwindow.cpp b/mainwindow.cpp index 1ed407d..02390ee 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1684,6 +1684,11 @@ void MainWindow::showGraphingWindow() connect(lastGraphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(uint32_t,double))); connect(flowViewWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), lastGraphingWindow, SLOT(gotCenterTimeID(uint32_t,double))); } + if (playbackWindow) + { + connect(lastGraphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), playbackWindow, SLOT(gotCenterTimeID(uint32_t,double))); + connect(playbackWindow, SIGNAL(sendCurrentTimestamp(double)), lastGraphingWindow, SLOT(gotPlaybackTimestamp(double))); + } lastGraphingWindow->show(); } @@ -1786,6 +1791,13 @@ void MainWindow::showPlaybackWindow() playbackWindow = new FramePlaybackWindow(model->getListReference()); else playbackWindow = new FramePlaybackWindow(model->getFilteredListReference()); + + connect(this, SIGNAL(sendCenterTimeID(uint32_t, double)), playbackWindow, SLOT(gotCenterTimeID(uint32_t, double))); + for (auto &&graphWindow : graphWindows) + { + connect(graphWindow, SIGNAL(sendCenterTimeID(uint32_t, double)), playbackWindow, SLOT(gotCenterTimeID(uint32_t, double))); + connect(playbackWindow, SIGNAL(sendCurrentTimestamp(double)), graphWindow, SLOT(gotPlaybackTimestamp(double))); + } } playbackWindow->show(); } diff --git a/re/graphingwindow.cpp b/re/graphingwindow.cpp index c40db52..6c46140 100644 --- a/re/graphingwindow.cpp +++ b/re/graphingwindow.cpp @@ -69,6 +69,13 @@ GraphingWindow::GraphingWindow(const QVector *frames, QWidget *parent) itemTracer->setStyle(QCPItemTracer::tsCircle); itemTracer->setSize(20); + playbackPen.setWidth(1); + playbackPen.setColor(Qt::red); + playbackLine = new QCPItemStraightLine(ui->graphingView); + playbackLine->setSelectable(false); + playbackLine->setPen(playbackPen); + playbackLine->setVisible(false); + // connect slot that ties some axis selections together (especially opposite axes): connect(ui->graphingView, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged())); //connect up the mouse controls @@ -329,6 +336,28 @@ void GraphingWindow::gotCenterTimeID(uint32_t ID, double timestamp) ui->graphingView->replot(); } +void GraphingWindow::gotPlaybackTimestamp(double timestamp) +{ + if (timestamp == INFINITY) { + playbackLine->setVisible(false); + return; + } + playbackLine->setVisible(true); + + // timestamp is always givin in seconds + if (Utility::timeStyle == TS_MICROS) + timestamp *= 1000000; + else if (Utility::timeStyle == TS_MILLIS) + timestamp *= 1000; + else if (Utility::timeStyle == TS_CLOCK) + timestamp += 3600; // offset of one hour needed + + playbackLine->point1->setCoords(timestamp, 0); + playbackLine->point2->setCoords(timestamp, 1); + + ui->graphingView->replot(); +} + void GraphingWindow::titleDoubleClick(QMouseEvent* event, QCPTextElement* title) { Q_UNUSED(event) diff --git a/re/graphingwindow.h b/re/graphingwindow.h index 0b2ba81..daf3008 100644 --- a/re/graphingwindow.h +++ b/re/graphingwindow.h @@ -84,6 +84,7 @@ private slots: void editSelectedGraph(); void updatedFrames(int); void gotCenterTimeID(uint32_t ID, double timestamp); + void gotPlaybackTimestamp(double timestamp); void resetView(); void zoomIn(); void zoomOut(); @@ -105,6 +106,8 @@ private: QCPSelectionDecorator *selDecorator; QCPItemText *locationText; QCPItemTracer *itemTracer; + QPen playbackPen; + QCPItemStraightLine *playbackLine; bool needScaleSetup; //do we need to set x,y graphing extents? bool useOpenGL; bool followGraphEnd; diff --git a/ui/frameplaybackwindow.ui b/ui/frameplaybackwindow.ui index 430e08b..7f5bcff 100644 --- a/ui/frameplaybackwindow.ui +++ b/ui/frameplaybackwindow.ui @@ -227,6 +227,13 @@ + + + + x of y + + +