mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-15 05:32:21 +00:00
Realtime checkpoint - WIN32 and Configurable Realtime
Fixups to compile video on WIN32 and added more configurability in the realtime screens, but still not the chart and video use-case needs to be decided.
This commit is contained in:
@@ -55,6 +55,9 @@ DialWindow::DialWindow(MainWindow *mainWindow) :
|
||||
|
||||
// setup fontsize etc
|
||||
resizeEvent(NULL);
|
||||
|
||||
// set to zero
|
||||
telemetryUpdate(RealtimeData());
|
||||
}
|
||||
|
||||
void
|
||||
@@ -85,15 +88,38 @@ void
|
||||
DialWindow::telemetryUpdate(RealtimeData rtData)
|
||||
{
|
||||
// we got some!
|
||||
RealtimeData::DataSeries series = static_cast<RealtimeData::DataSeries>(seriesSelector->itemData(seriesSelector->currentIndex()).toInt());
|
||||
RealtimeData::DataSeries series = static_cast<RealtimeData::DataSeries>
|
||||
(seriesSelector->itemData(seriesSelector->currentIndex()).toInt());
|
||||
|
||||
double value = rtData.value(series);
|
||||
valueLabel->setText(QString("%1").arg(round(value)));
|
||||
|
||||
switch (series) {
|
||||
|
||||
case RealtimeData::Time:
|
||||
case RealtimeData::LapTime:
|
||||
{
|
||||
long msecs = value;
|
||||
valueLabel->setText(QString("%1:%2:%3.%4").arg(msecs/3600000)
|
||||
.arg((msecs%3600000)/60000,2,10,QLatin1Char('0'))
|
||||
.arg((msecs%60000)/1000,2,10,QLatin1Char('0'))
|
||||
.arg((msecs%1000)/100));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
valueLabel->setText(QString("%1").arg(round(value)));
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void DialWindow::resizeEvent(QResizeEvent * )
|
||||
{
|
||||
|
||||
if (geometry().height()-37 < 0) return;
|
||||
|
||||
QFont font;
|
||||
font.setPointSize(geometry().height()/2);
|
||||
font.setPointSize((geometry().height()-37));
|
||||
font.setWeight(QFont::Bold);
|
||||
valueLabel->setFont(font);
|
||||
}
|
||||
|
||||
@@ -279,6 +279,7 @@ class MainWindow : public QMainWindow
|
||||
SummaryWindow *summaryWindow;
|
||||
DiaryWindow *diaryWindow;
|
||||
HomeWindow *homeWindow;
|
||||
TrainWindow *trainWindow;
|
||||
AllPlotWindow *allPlotWindow;
|
||||
HistogramWindow *histogramWindow;
|
||||
WeeklySummaryWindow *weeklySummaryWindow;
|
||||
@@ -297,9 +298,6 @@ class MainWindow : public QMainWindow
|
||||
RideMetadata *_rideMetadata;
|
||||
QSplitter *summarySplitter;
|
||||
|
||||
// Train
|
||||
TrainWindow *trainWindow;
|
||||
|
||||
//QwtPlotCurve *weeklyBSCurve;
|
||||
//QwtPlotCurve *weeklyRICurve;
|
||||
PerformanceManagerWindow *performanceManagerWindow;
|
||||
|
||||
@@ -128,7 +128,7 @@ QuarqdClient::parseElement(QString &strBuf) // updates QuarqdClient::telemetry
|
||||
|
||||
if (ok && mid != "nan" && mid != "inf") {
|
||||
telemetry.setWatts(value);
|
||||
telemetry.setTime(getTimeStamp(str));
|
||||
telemetry.setMsecs(getTimeStamp(str));
|
||||
lastReadWatts = elapsedTime.elapsed();
|
||||
}
|
||||
} else if(str.startsWith(cadenceStr))
|
||||
@@ -142,7 +142,7 @@ QuarqdClient::parseElement(QString &strBuf) // updates QuarqdClient::telemetry
|
||||
|
||||
if (ok && mid != "nan" && mid != "inf") {
|
||||
telemetry.setCadence(value);
|
||||
telemetry.setTime(getTimeStamp(str));
|
||||
telemetry.setMsecs(getTimeStamp(str));
|
||||
lastReadCadence = elapsedTime.elapsed();
|
||||
}
|
||||
} else if(str.startsWith(speedStr))
|
||||
@@ -163,7 +163,7 @@ QuarqdClient::parseElement(QString &strBuf) // updates QuarqdClient::telemetry
|
||||
telemetry.setWheelRpm(value);
|
||||
lastReadSpeed = elapsedTime.elapsed();
|
||||
}
|
||||
telemetry.setTime(getTimeStamp(str));
|
||||
telemetry.setMsecs(getTimeStamp(str));
|
||||
}
|
||||
} else if(str.startsWith(heartRateStr))
|
||||
{
|
||||
@@ -176,7 +176,7 @@ QuarqdClient::parseElement(QString &strBuf) // updates QuarqdClient::telemetry
|
||||
|
||||
if (ok && mid != "nan" && mid != "inf") {
|
||||
telemetry.setHr(value);
|
||||
telemetry.setTime(getTimeStamp(str));
|
||||
telemetry.setMsecs(getTimeStamp(str));
|
||||
}
|
||||
} else if(str.startsWith(sensorDropStr) || str.startsWith(sensorStaleStr) || str.startsWith(sensorLostStr))//Try and save
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ RealtimeData::RealtimeData()
|
||||
{
|
||||
name[0] = '\0';
|
||||
watts = hr = speed = wheelRpm = cadence = load = 0;
|
||||
time = 0;
|
||||
msecs = lapMsecs = bikeScore = joules = 0;
|
||||
}
|
||||
|
||||
void RealtimeData::setName(char *name)
|
||||
@@ -40,10 +40,6 @@ void RealtimeData::setHr(double hr)
|
||||
{
|
||||
this->hr = (int)hr;
|
||||
}
|
||||
void RealtimeData::setTime(long time)
|
||||
{
|
||||
this->time = time;
|
||||
}
|
||||
void RealtimeData::setSpeed(double speed)
|
||||
{
|
||||
this->speed = speed;
|
||||
@@ -60,6 +56,31 @@ void RealtimeData::setLoad(double load)
|
||||
{
|
||||
this->load = load;
|
||||
}
|
||||
void RealtimeData::setMsecs(long x)
|
||||
{
|
||||
this->msecs = x;
|
||||
}
|
||||
void RealtimeData::setLapMsecs(long x)
|
||||
{
|
||||
this->lapMsecs = x;
|
||||
}
|
||||
void RealtimeData::setDistance(double x)
|
||||
{
|
||||
this->distance = x;
|
||||
}
|
||||
void RealtimeData::setJoules(long x)
|
||||
{
|
||||
this->joules = x;
|
||||
}
|
||||
void RealtimeData::setBikeScore(long x)
|
||||
{
|
||||
this->bikeScore = x;
|
||||
}
|
||||
void RealtimeData::setXPower(long x)
|
||||
{
|
||||
this->xPower = x;
|
||||
}
|
||||
|
||||
char *
|
||||
RealtimeData::getName()
|
||||
{
|
||||
@@ -73,11 +94,6 @@ double RealtimeData::getHr()
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
long RealtimeData::getTime()
|
||||
{
|
||||
return time;
|
||||
}
|
||||
|
||||
double RealtimeData::getSpeed()
|
||||
{
|
||||
return speed;
|
||||
@@ -94,12 +110,51 @@ double RealtimeData::getLoad()
|
||||
{
|
||||
return load;
|
||||
}
|
||||
long RealtimeData::getMsecs()
|
||||
{
|
||||
return msecs;
|
||||
}
|
||||
long RealtimeData::getLapMsecs()
|
||||
{
|
||||
return lapMsecs;
|
||||
}
|
||||
double RealtimeData::getDistance()
|
||||
{
|
||||
return distance;
|
||||
}
|
||||
long RealtimeData::getJoules()
|
||||
{
|
||||
return joules;
|
||||
}
|
||||
long RealtimeData::getBikeScore()
|
||||
{
|
||||
return bikeScore;
|
||||
}
|
||||
long RealtimeData::getXPower()
|
||||
{
|
||||
return xPower;
|
||||
}
|
||||
|
||||
double RealtimeData::value(DataSeries series) const
|
||||
{
|
||||
switch (series) {
|
||||
|
||||
case Time: return time;
|
||||
case Time: return msecs;
|
||||
break;
|
||||
|
||||
case LapTime: return lapMsecs;
|
||||
break;
|
||||
|
||||
case Distance: return distance;
|
||||
break;
|
||||
|
||||
case Joules: return joules;
|
||||
break;
|
||||
|
||||
case BikeScore: return bikeScore;
|
||||
break;
|
||||
|
||||
case XPower: return xPower;
|
||||
break;
|
||||
|
||||
case Watts: return watts;
|
||||
@@ -135,11 +190,16 @@ const QList<RealtimeData::DataSeries> &RealtimeData::listDataSeries()
|
||||
// better populate it first!
|
||||
seriesList << None;
|
||||
seriesList << Time;
|
||||
seriesList << LapTime;
|
||||
seriesList << Distance;
|
||||
seriesList << Watts;
|
||||
seriesList << Speed;
|
||||
seriesList << Cadence;
|
||||
seriesList << HeartRate;
|
||||
seriesList << Load;
|
||||
seriesList << BikeScore;
|
||||
seriesList << XPower;
|
||||
seriesList << Joules;
|
||||
}
|
||||
return seriesList;
|
||||
}
|
||||
@@ -155,6 +215,21 @@ QString RealtimeData::seriesName(DataSeries series)
|
||||
case Time: return tr("Time");
|
||||
break;
|
||||
|
||||
case LapTime: return tr("Lap Time");
|
||||
break;
|
||||
|
||||
case BikeScore: return tr("BikeScore");
|
||||
break;
|
||||
|
||||
case Joules: return tr("Joules");
|
||||
break;
|
||||
|
||||
case XPower: return tr("XPower");
|
||||
break;
|
||||
|
||||
case Distance: return tr("Distance");
|
||||
break;
|
||||
|
||||
case Watts: return tr("Power");
|
||||
break;
|
||||
|
||||
|
||||
@@ -30,7 +30,10 @@ class RealtimeData
|
||||
public:
|
||||
|
||||
// abstract to dataseries
|
||||
enum dataseries { None=0, Time, Watts, Speed, Cadence, HeartRate, Load };
|
||||
enum dataseries { None=0, Time, LapTime, Distance, Lap,
|
||||
Watts, Speed, Cadence, HeartRate, Load,
|
||||
XPower, BikeScore, Joules };
|
||||
|
||||
typedef enum dataseries DataSeries;
|
||||
double value(DataSeries) const;
|
||||
static QString seriesName(DataSeries);
|
||||
@@ -38,6 +41,7 @@ public:
|
||||
|
||||
RealtimeData();
|
||||
void reset(); // set all values to zero
|
||||
|
||||
void setName(char *name);
|
||||
void setWatts(double watts);
|
||||
void setHr(double hr);
|
||||
@@ -46,6 +50,13 @@ public:
|
||||
void setWheelRpm(double wheelRpm);
|
||||
void setCadence(double aCadence);
|
||||
void setLoad(double load);
|
||||
void setMsecs(long);
|
||||
void setLapMsecs(long);
|
||||
void setDistance(double);
|
||||
void setBikeScore(long);
|
||||
void setJoules(long);
|
||||
void setXPower(long);
|
||||
|
||||
char *getName();
|
||||
double getWatts();
|
||||
double getHr();
|
||||
@@ -54,13 +65,27 @@ public:
|
||||
double getWheelRpm();
|
||||
double getCadence();
|
||||
double getLoad();
|
||||
long getMsecs();
|
||||
long getLapMsecs();
|
||||
double getDistance();
|
||||
long getBikeScore();
|
||||
long getJoules();
|
||||
long getXPower();
|
||||
|
||||
|
||||
private:
|
||||
char name[64];
|
||||
unsigned long time;
|
||||
|
||||
// realtime telemetry
|
||||
double hr, watts, speed, wheelRpm, load;
|
||||
double cadence; // in rpm
|
||||
|
||||
// derived data
|
||||
double distance;
|
||||
int lap;
|
||||
long msecs;
|
||||
long lapMsecs;
|
||||
long bikeScore, joules, xPower;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -561,32 +561,45 @@ void RealtimeWindow::guiUpdate() // refreshes the telemetry
|
||||
if (status&RT_RUNNING && deviceController->doesPull() == true) {
|
||||
|
||||
deviceController->getRealtimeData(rtData);
|
||||
main->notifyTelemetryUpdate(rtData); // signal everyone to update telemetry
|
||||
|
||||
// Distance assumes current speed for the last second. from km/h to km/sec
|
||||
displayDistance += displaySpeed / (5 * 3600); // XXX assumes 200ms refreshrate
|
||||
displayWorkoutDistance += displaySpeed / (5 * 3600); // XXX assumes 200ms refreshrate
|
||||
rtData.setDistance(displayDistance);
|
||||
|
||||
// time
|
||||
total_msecs = session_elapsed_msec + session_time.elapsed();
|
||||
lap_msecs = lap_elapsed_msec + lap_time.elapsed();
|
||||
rtData.setMsecs(total_msecs);
|
||||
rtData.setLapMsecs(lap_msecs);
|
||||
|
||||
// metrics
|
||||
rtData.setJoules(kjoules);
|
||||
rtData.setBikeScore(bikescore);
|
||||
rtData.setXPower(xpower);
|
||||
|
||||
// update those LCDs!
|
||||
timeLCD->display(QString("%1:%2:%3.%4").arg(total_msecs/3600000)
|
||||
.arg((total_msecs%3600000)/60000,2,10,QLatin1Char('0'))
|
||||
.arg((total_msecs%60000)/1000,2,10,QLatin1Char('0'))
|
||||
.arg((total_msecs%1000)/100));
|
||||
|
||||
laptimeLCD->display(QString("%1:%2:%3.%4").arg(lap_msecs/3600000,2)
|
||||
.arg((lap_msecs%3600000)/60000,2,10,QLatin1Char('0'))
|
||||
.arg((lap_msecs%60000)/1000,2,10,QLatin1Char('0'))
|
||||
.arg((lap_msecs%1000)/100));
|
||||
|
||||
// local stuff ...
|
||||
displayPower = rtData.getWatts();
|
||||
displayCadence = rtData.getCadence();
|
||||
displayHeartRate = rtData.getHr();
|
||||
displaySpeed = rtData.getSpeed();
|
||||
displayLoad = rtData.getLoad();
|
||||
|
||||
// go update the displays...
|
||||
main->notifyTelemetryUpdate(rtData); // signal everyone to update telemetry
|
||||
}
|
||||
|
||||
// Distance assumes current speed for the last second. from km/h to km/sec
|
||||
displayDistance += displaySpeed / (5 * 3600); // XXX assumes 200ms refreshrate
|
||||
displayWorkoutDistance += displaySpeed / (5 * 3600); // XXX assumes 200ms refreshrate
|
||||
|
||||
total_msecs = session_elapsed_msec + session_time.elapsed();
|
||||
lap_msecs = lap_elapsed_msec + lap_time.elapsed();
|
||||
|
||||
// update those LCDs!
|
||||
timeLCD->display(QString("%1:%2:%3.%4").arg(total_msecs/3600000)
|
||||
.arg((total_msecs%3600000)/60000,2,10,QLatin1Char('0'))
|
||||
.arg((total_msecs%60000)/1000,2,10,QLatin1Char('0'))
|
||||
.arg((total_msecs%1000)/100));
|
||||
|
||||
laptimeLCD->display(QString("%1:%2:%3.%4").arg(lap_msecs/3600000,2)
|
||||
.arg((lap_msecs%3600000)/60000,2,10,QLatin1Char('0'))
|
||||
.arg((lap_msecs%60000)/1000,2,10,QLatin1Char('0'))
|
||||
.arg((lap_msecs%1000)/100));
|
||||
|
||||
// Cadence, HR and Power needs to be rounded to 0 decimal places
|
||||
powerLCD->display(round(displayPower));
|
||||
double val = round(displaySpeed * (useMetricUnits ? 1.0 : MILES_PER_KM) * 10.00)/10.00;
|
||||
|
||||
@@ -228,7 +228,7 @@ bool SimpleNetworkClient::read_next_line(QMutexLocker &locker,
|
||||
read_into_me.setName(namechar);
|
||||
read_into_me.setWatts(watts);
|
||||
read_into_me.setHr(hr);
|
||||
read_into_me.setTime(time);
|
||||
read_into_me.setMsecs(time);
|
||||
read_into_me.setSpeed(speed);
|
||||
read_into_me.setCadence(rpm);
|
||||
read_into_me.setLoad(load);
|
||||
@@ -238,7 +238,7 @@ DISPATCHER->dispatch(&read_into_me);
|
||||
|
||||
printf("Read from network: %f %f %ld %f %f %f\n",
|
||||
read_into_me.getWatts(), read_into_me.getHr(),
|
||||
read_into_me.getTime(), read_into_me.getSpeed(),
|
||||
read_into_me.getMsecs(), read_into_me.getSpeed(),
|
||||
read_into_me.getCadence(), read_into_me.getLoad());
|
||||
}
|
||||
return true;
|
||||
@@ -251,7 +251,7 @@ bool SimpleNetworkClient::write_next_line(QMutexLocker &locker,
|
||||
int num_written;
|
||||
snprintf(buffer, MAX_BYTES_PER_LINE-1,
|
||||
"%.2f %.2f %ld %.2f %.2f %.3f\n",
|
||||
record.getWatts(), record.getHr(), record.getTime(),
|
||||
record.getWatts(), record.getHr(), record.getMsecs(),
|
||||
record.getSpeed(), record.getCadence(), record.getLoad());
|
||||
locker.unlock();
|
||||
num_written = server.write(buffer, strlen(buffer));
|
||||
|
||||
@@ -32,7 +32,7 @@ GcWindow(parent), home(home), main(parent)
|
||||
"-I", "dummy", /* Don't use any interface */
|
||||
"--ignore-config", /* Don't use VLC's config */
|
||||
"--extraintf=logger", //log anything
|
||||
"--verbose=2" // -1 = no output at all
|
||||
"--verbose=-1" // -1 = no output at all
|
||||
};
|
||||
|
||||
/* create an exception handler */
|
||||
@@ -66,13 +66,14 @@ GcWindow(parent), home(home), main(parent)
|
||||
x11Container = new QX11EmbedContainer(this);
|
||||
layout->addWidget(x11Container);
|
||||
libvlc_media_player_set_xwindow (mp, x11Container->winId());
|
||||
//vlc_exceptions(&exceptions);
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
container = new QWidget(this);
|
||||
layout->addWidget(container);
|
||||
libvlc_media_player_set_hwnd (mp, container->winId());
|
||||
#endif
|
||||
|
||||
#if 0 // XXX what abut windows and mac!!!
|
||||
/* or on windows */
|
||||
libvlc_media_player_set_hwnd (mp, hwnd);
|
||||
/* or on mac os */
|
||||
#if 0 // XXX what abut mac!!!
|
||||
libvlc_media_player_set_nsobject (mp, view);
|
||||
#endif
|
||||
|
||||
@@ -82,8 +83,10 @@ GcWindow(parent), home(home), main(parent)
|
||||
|
||||
VideoWindow::~VideoWindow()
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
// unembed vlc backend first
|
||||
x11Container->discardClient();
|
||||
#endif
|
||||
|
||||
// stop playback & wipe player
|
||||
libvlc_media_player_stop (mp);
|
||||
@@ -95,9 +98,5 @@ VideoWindow::~VideoWindow()
|
||||
|
||||
void VideoWindow::resizeEvent(QResizeEvent * )
|
||||
{
|
||||
#if 0
|
||||
if (isVisible()) {
|
||||
x11Container->show();
|
||||
}
|
||||
#endif
|
||||
// do nothing .. for now
|
||||
}
|
||||
|
||||
@@ -33,13 +33,16 @@ extern "C" {
|
||||
// QT stuff etc
|
||||
#include <QtGui>
|
||||
#include <QTimer>
|
||||
#include <QX11EmbedContainer>
|
||||
#include "MainWindow.h"
|
||||
#include "DeviceConfiguration.h"
|
||||
#include "DeviceTypes.h"
|
||||
#include "RealtimeData.h"
|
||||
#include "TrainTool.h"
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <QX11EmbedContainer>
|
||||
#endif
|
||||
|
||||
class VideoWindow : public GcWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -71,6 +74,9 @@ class VideoWindow : public GcWindow
|
||||
#ifdef Q_OS_LINUX
|
||||
QX11EmbedContainer *x11Container;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
QWidget *container;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // _GC_VideoWindow_h
|
||||
|
||||
@@ -92,8 +92,10 @@ D2XX_INCLUDE = /usr/local/include/D2XX
|
||||
# will need to use the latest distro (e.g. Meerkat
|
||||
# on Ubuntu) to be sure apt-get installs the latest
|
||||
# builds (we need 1.1.6 or higher).
|
||||
#
|
||||
# e.g. LINUX
|
||||
#VLC_INSTALL = /usr/include/vlc/
|
||||
# e.g. WINDOWS
|
||||
#VLC_INSTALL = /c/GC/vlc-1.1.8/sdk
|
||||
|
||||
# We recommend a debug build for development, and a static build for releases.
|
||||
CONFIG += debug
|
||||
|
||||
@@ -92,10 +92,16 @@ qwt3d {
|
||||
# are we supporting video playback?
|
||||
!isEmpty( VLC_INSTALL ) {
|
||||
INCLUDEPATH += $${VLC_INSTALL}/include
|
||||
LIBS += -lvlc
|
||||
DEFINES += GC_HAVE_VLC
|
||||
HEADERS += VideoWindow.h
|
||||
SOURCES += VideoWindow.cpp
|
||||
|
||||
win32 {
|
||||
LIBS += $${VLC_INSTALL}/lib/libvlc.dll.a
|
||||
LIBS += $${VLC_INSTALL}/lib/libvlccore.dll.a
|
||||
} else {
|
||||
LIBS += -lvlc
|
||||
}
|
||||
}
|
||||
|
||||
macx {
|
||||
|
||||
Reference in New Issue
Block a user