Files
GoldenCheetah/src/SrmDevice.cpp
Sean Rhea 2be608410a fix inexplicable naming conflict
Somehow this SrmData conflicts with the one in srm.h.  I would have expected
the compiler to flag that, but it didn't.  Weird.
2009-08-24 21:21:44 -07:00

149 lines
4.5 KiB
C++

/*
* Copyright (c) 2008 Sean C. Rhea (srhea@srhea.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "SrmDevice.h"
#include "SrmRideFile.h"
#include <srmio.h>
#include <QMessageBox>
#include <boost/scoped_ptr.hpp>
#include <boost/foreach.hpp>
#include <errno.h>
static bool srmRegistered = Device::addDevice("SRM", new SrmDevice());
QString
SrmDevice::downloadInstructions() const
{
return ""; // no particular instructions for SRM
}
static Device::StatusCallback cb;
static void
logfunc(const char *msg)
{
// XXX: better log function
// fprintf(stderr, "%s\n", msg);
cb(QString(msg).left(40));
}
static bool
get_tmpname(const QDir &tmpdir, QString &tmpname, QString &err)
{
QString tmpl = tmpdir.absoluteFilePath(".srmdl.XXXXXX.srm");
QTemporaryFile tmp(tmpl);
tmp.setAutoRemove(false);
if (!tmp.open()) {
err = "Failed to create temporary file "
+ tmpl + ": " + tmp.error();
return false;
}
tmpname = tmp.fileName(); // after close(), tmp.fileName() is ""
tmp.close();
return true;
}
struct SrmpcConn : public boost::noncopyable
{
srmpc_conn_t d;
SrmpcConn(const QString &path, srmpc_log_callback_t logfunc = NULL) {
int opt_force = 0; // setting this to 1 is potentially dangerous
d = srmpc_open(path.toAscii().constData(), opt_force, logfunc);
}
~SrmpcConn() { if (d) srmpc_close(d); }
};
struct SrmioData : public boost::noncopyable
{
srm_data_t d;
SrmioData(srm_data_t d) : d(d) {}
~SrmioData() { if (d) srm_data_free(d); }
};
static bool
dev2path(CommPortPtr dev, QString &path, QString &err)
{
// Read device path out of device name. Sketchy.
QRegExp rx("^Serial: (.+)$");
if (!rx.exactMatch(dev->name())) {
err = "SRM download not supported by device " + dev->name();
return false;
}
path = rx.cap(1);
return true;
}
bool
SrmDevice::download(CommPortPtr dev, const QDir &tmpdir,
QString &tmpname, QString &filename,
StatusCallback statusCallback, QString &err)
{
// Totally ghetto, proof-of-concept integration with srmio.
cb = statusCallback;
QString path;
if (!dev2path(dev, path, err))
return false;
if (!get_tmpname(tmpdir, tmpname, err))
return false;
SrmpcConn srm(path, logfunc);
if (!srm.d) {
err = "Couldn't open device " + path + ": " + strerror(errno);
return false;
}
int opt_all = 0; // XXX: what does this do?
int opt_fixup = 1; // fix bad data like srmwin.exe does
SrmioData srmdata(srmpc_get_data(srm.d, opt_all, opt_fixup));
if (!srmdata.d) {
err = "srmpc_get_data failed";
return false;
}
if (srm_data_write_srm7(srmdata.d, tmpname.toAscii().constData()) < 0) {
err = "Couldn't write to file " + tmpname + ": " + strerror(errno);
return false;
}
// Read it back in to get the ride start time.
SrmFileReader reader;
QStringList errs;
QFile file(tmpname);
QStringList errors;
boost::scoped_ptr<RideFile> ride(
RideFileFactory::instance().openRideFile(file, errors));
BOOST_FOREACH(QString err, errors)
fprintf(stderr, "error: %s\n", err.toAscii().constData());
filename = ride->startTime().toString("yyyy_MM_dd_hh_mm_ss") + ".srm";
return true;
}
void
SrmDevice::cleanup(CommPortPtr dev)
{
QString path, err;
if (!dev2path(dev, path, err))
assert(false);
if (QMessageBox::question(0, "Powercontrol",
"Erase downloaded ride from device memory?",
"&Erase", "&Save Only", "", 1, 1) == 0) {
SrmpcConn srm(path);
if(!srm.d || (srmpc_clear_chunks(srm.d) < 0)) {
QMessageBox::warning(0, "Error",
"Error communicating with device.");
}
}
}