diff --git a/src/gui/GoldenCheetah.pro b/src/gui/GoldenCheetah.pro index cef9630a5..378f09c0d 100644 --- a/src/gui/GoldenCheetah.pro +++ b/src/gui/GoldenCheetah.pro @@ -5,9 +5,10 @@ TEMPLATE = app TARGET += DEPENDPATH += . -INCLUDEPATH += /usr/local/include/qwt ../lib +INCLUDEPATH += /home/srhea/src/qwt-20060130/include ../lib ../srm CONFIG += static -LIBS += /usr/local/lib/libqwt.a ../lib/libgc.a +LIBS += /home/srhea/src/qwt-20060130/lib/libqwt.a ../lib/libgc.a +LIBS += ../srm/libsrm.a LIBS += -lm -lz macx { LIBS += -framework Carbon diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 97223821e..75e216fdf 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -39,7 +39,7 @@ #define RIDE_TYPE 1 static char *rideFileRegExp = ("^(\\d\\d\\d\\d)_(\\d\\d)_(\\d\\d)" - "_(\\d\\d)_(\\d\\d)_(\\d\\d)\\.raw$"); + "_(\\d\\d)_(\\d\\d)_(\\d\\d)\\.(raw|srm)$"); MainWindow::MainWindow(const QDir &home) : home(home), settings(GC_SETTINGS_CO, GC_SETTINGS_APP) @@ -70,13 +70,13 @@ MainWindow::MainWindow(const QDir &home) : QRegExp rx(rideFileRegExp); QStringList filters; - filters << "*.raw"; + filters << "*.raw" << "*.srm"; QTreeWidgetItem *last = NULL; QStringListIterator i(home.entryList(filters, QDir::Files)); while (i.hasNext()) { QString name = i.next(); if (rx.exactMatch(name)) { - assert(rx.numCaptures() == 6); + assert(rx.numCaptures() == 7); QDate date(rx.cap(1).toInt(), rx.cap(2).toInt(),rx.cap(3).toInt()); QTime time(rx.cap(4).toInt(), rx.cap(5).toInt(),rx.cap(6).toInt()); QDateTime dt(date, time); diff --git a/src/gui/RawFile.cpp b/src/gui/RawFile.cpp index 4e47dd02b..fed880991 100644 --- a/src/gui/RawFile.cpp +++ b/src/gui/RawFile.cpp @@ -19,8 +19,11 @@ */ #include "RawFile.h" +#include #include #include +#include "srm.h" + extern "C" { #include "pt.h" } @@ -93,19 +96,43 @@ error_cb(const char *msg, void *context) state->errors.append(QString(msg)); } -RawFile *RawFile::readFile(const QFile &file, QStringList &errors) +RawFile *RawFile::readFile(QFile &file, QStringList &errors) { RawFile *result = new RawFile(file.fileName()); - if (!result->file.open(QIODevice::ReadOnly)) { - delete result; - return NULL; + if (file.fileName().indexOf(".srm") == file.fileName().size() - 4) { + SrmData data; + if (!readSrmFile(file, data, errors)) { + delete result; + return NULL; + } + result->startTime = data.startTime; + result->rec_int = (unsigned) round(data.recint); // TODO + + QListIterator i(data.dataPoints); + while (i.hasNext()) { + SrmDataPoint *p1 = i.next(); + RawFilePoint *p2 = new RawFilePoint( + p1->secs, 0, p1->kph * 0.62137119, p1->watts, + p1->km * 0.62137119, p1->cad, p1->hr, p1->interval); + if (result->powerHist.contains(p2->watts)) + result->powerHist[p2->watts] += data.recint; + else + result->powerHist[p2->watts] = data.recint; + result->points.append(p2); + } + } + else { + if (!result->file.open(QIODevice::ReadOnly)) { + delete result; + return NULL; + } + FILE *f = fdopen(result->file.handle(), "r"); + assert(f); + RawFileReadState state(result->points, result->powerHist, errors); + pt_read_raw(f, 0 /* not compat */, &state, config_cb, + time_cb, data_cb, error_cb); + result->rec_int = state.rec_int; } - FILE *f = fdopen(result->file.handle(), "r"); - assert(f); - RawFileReadState state(result->points, result->powerHist, errors); - pt_read_raw(f, 0 /* not compat */, &state, config_cb, - time_cb, data_cb, error_cb); - result->rec_int = state.rec_int; return result; } diff --git a/src/gui/RawFile.h b/src/gui/RawFile.h index 5c4dd10ae..0cd0c66a9 100644 --- a/src/gui/RawFile.h +++ b/src/gui/RawFile.h @@ -53,7 +53,7 @@ class RawFile int rec_int; QList points; QMap powerHist; - static RawFile *readFile(const QFile &file, QStringList &errors); + static RawFile *readFile(QFile &file, QStringList &errors); }; #endif // _GC_RawFile_h diff --git a/src/srm/Makefile b/src/srm/Makefile index 8357fd488..ce0e71300 100644 --- a/src/srm/Makefile +++ b/src/srm/Makefile @@ -1,8 +1,8 @@ ############################################################################# -# Makefile for building: srm -# Generated by qmake (2.01a) (Qt 4.2.0) on: Sun Apr 8 18:34:58 2007 +# Makefile for building: libsrm.a +# Generated by qmake (2.01a) (Qt 4.2.0) on: Mon Apr 9 13:27:14 2007 # Project: srm.pro -# Template: app +# Template: lib # Command: /usr/bin/qmake -unix -o Makefile srm.pro ############################################################################# @@ -13,14 +13,11 @@ CXX = g++ LEX = flex YACC = yacc DEFINES = -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -CFLAGS = -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) -CXXFLAGS = -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES) +CFLAGS = -pipe -O2 -fPIC -Wall -W -D_REENTRANT $(DEFINES) +CXXFLAGS = -pipe -O2 -fPIC -Wall -W -D_REENTRANT $(DEFINES) LEXFLAGS = YACCFLAGS = -d INCPATH = -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. -LINK = g++ -LFLAGS = -LIBS = $(SUBLIBS) -L/usr/lib -lQtGui -L/build/buildd/qt4-x11-4.2.0/lib -L/usr/X11R6/lib -laudio -lXt -lpng -lSM -lICE -lXrender -lXrandr -lXfixes -lXcursor -lXinerama -lfreetype -lXext -lX11 -lQtCore -lfontconfig -lz -lm -lglib-2.0 -ldl -lpthread AR = ar cqs RANLIB = QMAKE = /usr/bin/qmake @@ -57,6 +54,8 @@ DIST = /usr/share/qt4/mkspecs/common/unix.conf \ /usr/share/qt4/mkspecs/features/default_pre.prf \ /usr/share/qt4/mkspecs/features/release.prf \ /usr/share/qt4/mkspecs/features/default_post.prf \ + /usr/share/qt4/mkspecs/features/static.prf \ + /usr/share/qt4/mkspecs/features/staticlib.prf \ /usr/share/qt4/mkspecs/features/warn_on.prf \ /usr/share/qt4/mkspecs/features/qt.prf \ /usr/share/qt4/mkspecs/features/unix/thread.prf \ @@ -66,7 +65,7 @@ DIST = /usr/share/qt4/mkspecs/common/unix.conf \ srm.pro QMAKE_TARGET = srm DESTDIR = -TARGET = srm +TARGET = libsrm.a first: all ####### Implicit rules @@ -90,10 +89,14 @@ first: all ####### Build rules -all: Makefile $(TARGET) +all: Makefile $(TARGET) + +staticlib: $(TARGET) + +$(TARGET): $(OBJECTS) $(OBJCOMP) + -$(DEL_FILE) $(TARGET) + $(AR) $(TARGET) $(OBJECTS) -$(TARGET): $(OBJECTS) - $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS) Makefile: srm.pro /usr/share/qt4/mkspecs/linux-g++/qmake.conf /usr/share/qt4/mkspecs/common/unix.conf \ /usr/share/qt4/mkspecs/common/g++.conf \ @@ -105,6 +108,8 @@ Makefile: srm.pro /usr/share/qt4/mkspecs/linux-g++/qmake.conf /usr/share/qt4/mk /usr/share/qt4/mkspecs/features/default_pre.prf \ /usr/share/qt4/mkspecs/features/release.prf \ /usr/share/qt4/mkspecs/features/default_post.prf \ + /usr/share/qt4/mkspecs/features/static.prf \ + /usr/share/qt4/mkspecs/features/staticlib.prf \ /usr/share/qt4/mkspecs/features/warn_on.prf \ /usr/share/qt4/mkspecs/features/qt.prf \ /usr/share/qt4/mkspecs/features/unix/thread.prf \ @@ -124,6 +129,8 @@ Makefile: srm.pro /usr/share/qt4/mkspecs/linux-g++/qmake.conf /usr/share/qt4/mk /usr/share/qt4/mkspecs/features/default_pre.prf: /usr/share/qt4/mkspecs/features/release.prf: /usr/share/qt4/mkspecs/features/default_post.prf: +/usr/share/qt4/mkspecs/features/static.prf: +/usr/share/qt4/mkspecs/features/staticlib.prf: /usr/share/qt4/mkspecs/features/warn_on.prf: /usr/share/qt4/mkspecs/features/qt.prf: /usr/share/qt4/mkspecs/features/unix/thread.prf: @@ -137,7 +144,7 @@ qmake: FORCE dist: @$(CHK_DIR_EXISTS) .tmp/srm1.0.0 || $(MKDIR) .tmp/srm1.0.0 - $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/srm1.0.0/ && $(COPY_FILE) --parents srm.cpp .tmp/srm1.0.0/ && (cd `dirname .tmp/srm1.0.0` && $(TAR) srm1.0.0.tar srm1.0.0 && $(COMPRESS) srm1.0.0.tar) && $(MOVE) `dirname .tmp/srm1.0.0`/srm1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/srm1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/srm1.0.0/ && $(COPY_FILE) --parents srm.h .tmp/srm1.0.0/ && $(COPY_FILE) --parents srm.cpp .tmp/srm1.0.0/ && (cd `dirname .tmp/srm1.0.0` && $(TAR) srm1.0.0.tar srm1.0.0 && $(COMPRESS) srm1.0.0.tar) && $(MOVE) `dirname .tmp/srm1.0.0`/srm1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/srm1.0.0 yaccclean: diff --git a/src/srm/srm.cpp b/src/srm/srm.cpp index b52a4417c..819f7cc0f 100644 --- a/src/srm/srm.cpp +++ b/src/srm/srm.cpp @@ -3,9 +3,7 @@ // (http://www.stephanmantler.com/?page_id=86). // -#include -#include -#include +#include "srm.h" #include #include #include @@ -32,18 +30,23 @@ static quint32 readLong(QDataStream &in) return htonl(value); // SRM uses big endian } +struct marker +{ + int start, end; +}; + struct blockhdr { QDateTime dt; quint16 chunkcnt; }; -int main(int argc, char *argv[]) +bool readSrmFile(QFile &file, SrmData &data, QStringList &errorStrings) { - assert(argc > 1); - QFile file(argv[1]); - if (!file.open(QFile::ReadOnly)) - assert(false); + if (!file.open(QFile::ReadOnly)) { + errorStrings << QString("can't open file %1").arg(file.fileName()); + return false; + } QDataStream in(&file); char magic[5]; @@ -65,13 +68,13 @@ int main(int argc, char *argv[]) in.readRawData(comment, sizeof(comment) - 1); comment[commentlen - 1] = '\0'; - double recint = ((double) recint1) / recint2; - unsigned recintms = (unsigned) round(recint * 1000.0); + data.recint = ((double) recint1) / recint2; + unsigned recintms = (unsigned) round(data.recint * 1000.0); printf("magic=%s\n", magic); printf("wheelcirc=%d\n", wheelcirc); printf("dayssince1880=%d\n", dayssince1880); - printf("recint=%f sec\n", recint); + printf("recint=%f sec\n", data.recint); printf("blockcnt=%d\n", blockcnt); printf("markercnt=%d\n", markercnt); printf("commentlen=%d\n", commentlen); @@ -82,6 +85,7 @@ int main(int argc, char *argv[]) printf("date=%s\n", date.toString().toAscii().constData()); + marker *markers = new marker[markercnt + 1]; for (int i = 0; i <= markercnt; ++i) { char mcomment[256]; in.readRawData(mcomment, sizeof(mcomment) - 1); @@ -95,6 +99,8 @@ int main(int argc, char *argv[]) quint16 avgcad = readShort(in); quint16 avgspeed = readShort(in); quint16 pwc150 = readShort(in); + markers[i].start = start; + markers[i].end = end; printf("marker %d:\n", i); printf(" mcomment=%s\n", mcomment); @@ -129,7 +135,15 @@ int main(int argc, char *argv[]) printf("slope=%d\n", slope); printf("datacnt=%d\n", datacnt); - for (int i = 0, blknum = 0, blkidx = 0; i < datacnt; ++i) { + assert(blockcnt > 0); + + int blknum = 0, blkidx = 0, mrknum = 0, interval = 0; + double km = 0.0, secs = 0.0; + + if (markercnt > 0) + mrknum = 1; + + for (int i = 0; i < datacnt; ++i) { quint8 ps[3]; in.readRawData((char*) ps, sizeof(ps)); quint8 cad = readByte(in); @@ -137,17 +151,76 @@ int main(int argc, char *argv[]) double kph = (((((unsigned) ps[1]) & 0xf0) << 3) | (ps[0] & 0x7f)) * 3.0 / 26.0; unsigned watts = (ps[1] & 0x0f) | (ps[2] << 0x4); - QDateTime dt = blockhdrs[blknum].dt.addMSecs(recintms * blkidx); - printf(" %s %5.1f %4d %3d %3d\n", - dt.toString().toAscii().constData(), kph, watts, hr, cad); + if (i == 0) { + data.startTime = blockhdrs[blknum].dt; + printf("startTime=%s\n", + data.startTime.toString().toAscii().constData()); + } + if (i == markers[mrknum].end) { + ++interval; + ++mrknum; + } + + if ((i > 0) && (i == markers[mrknum].start)) + ++interval; + + km += data.recint * kph / 3600.0; + + SrmDataPoint *point = new SrmDataPoint; + point->cad = cad; + point->hr = hr; + point->watts = watts; + point->interval = interval; + point->kph = kph; + point->km = km; + point->secs = secs; + data.dataPoints.append(point); + + printf("%5.1f %5.1f %5.1f %4d %3d %3d %2d\n", + secs, km, kph, watts, hr, cad, interval); + ++blkidx; - if (blkidx == blockhdrs[blknum].chunkcnt) { + if ((blkidx == blockhdrs[blknum].chunkcnt) && (blknum + 1 < blockcnt)) { + QDateTime end = blockhdrs[blknum].dt.addMSecs( + recintms * blockhdrs[blknum].chunkcnt); ++blknum; blkidx = 0; + QDateTime start = blockhdrs[blknum].dt; + qint64 endms = + ((qint64) end.toTime_t()) * 1000 + end.time().msec(); + qint64 startms = + ((qint64) start.toTime_t()) * 1000 + start.time().msec(); + qint64 diff = startms - endms; + if (diff < 0) { + errorStrings << QString("ERROR: time goes backwards by %1 ms" + " on trans " "to block %2" + ).arg(diff).arg(blknum); + secs += data.recint; // for lack of a better option + } + else { + // printf("jumping forward %lld ms\n", diff); + secs += diff / 1000.0; + } + } + else { + secs += data.recint; } } file.close(); - return 0; + return true; } +/* +int main(int argc, char *argv[]) { + assert(argc > 1); + QFile file(argv[1]); + QStringList errorStrings; + SrmData data; + if (readSrmFile(file, data, errorStrings)) + return 0; + else + return -1; +} +*/ + diff --git a/src/srm/srm.h b/src/srm/srm.h new file mode 100644 index 000000000..5c3d957f8 --- /dev/null +++ b/src/srm/srm.h @@ -0,0 +1,31 @@ + +#ifndef _srm_h +#define _srm_h + +#include +#include +#include +#include + +struct SrmDataPoint +{ + int cad, hr, watts, interval; + double kph, km, secs; +}; + +struct SrmData +{ + QDateTime startTime; + double recint; + QList dataPoints; + ~SrmData() { + QListIterator i(dataPoints); + while (i.hasNext()) + delete i.next(); + } +}; + +bool readSrmFile(QFile &file, SrmData &data, QStringList &errorStrings); + +#endif // _srm_h + diff --git a/src/srm/srm.pro b/src/srm/srm.pro index a197b4728..17744ef65 100644 --- a/src/srm/srm.pro +++ b/src/srm/srm.pro @@ -2,14 +2,15 @@ # Automatically generated by qmake (2.01a) Sun Apr 8 17:19:06 2007 ###################################################################### -TEMPLATE = app +TEMPLATE = lib TARGET = DEPENDPATH += . INCLUDEPATH += . -CXXFLAGS += -std=c99 +CONFIG += static LIBS += -lm # Input +HEADERS += srm.h SOURCES += srm.cpp