Rev 232 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/***************************************************************************
* Copyright (C) 2007 - 2009 by Andreas Theofilu *
* andreas@theosys.at *
* *
* 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 version 3 of the License. *
* *
* 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., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/*
* Ported to KDE4 on Jul. 8 2009 by Andreas Theofilu.
*/
#include "progresswidget.h"
#include <kapplication.h>
#include <kmessagebox.h>
#include <KConfig>
#include <klocale.h>
#include <qlabel.h>
#include <QProgressBar>
#include "garmin.h"
#include "../libgant/gant.h"
#include <iostream>
using std::cout;
using std::endl;
extern KApplication *mapp;
progressWidget *me;
progressWidget::progressWidget ( QWidget* parent, Qt::WFlags fl )
: QDialog(parent, fl), Ui::Progress ()
{
setupUi (this);
step = 0;
psteps = 7;
me = this;
}
progressWidget::~progressWidget()
{
me = 0;
}
/*
* This function is called from the Garmin library libgarmin.a during
* reading data from a GPS device.
*/
void progressWidget::CallBack(char *)
{
if (me)
me->IncrementBar();
}
void progressWidget::IncrementBar()
{
step++;
if (psteps <= step)
{
psteps += 2;
barProgress->setRange(0, psteps);
}
barProgress->setValue(step);
}
/*$SPECIALIZATION$*/
/*
* The following function reads out all data from a GPS device. It uses
* the library libgarmin.a, who is basicly the "garmintools-0.5", written by
* Dave Bailey (thanks Dave!).
*/
bool progressWidget::Download()
{
QString Data, filepath, device;
garmin_unit garmin;
garmin_data * data;
garmin_data * data0;
garmin_data * data1;
garmin_data * data2;
garmin_data * rlaps;
garmin_data * rtracks;
garmin_list * runs = NULL;
garmin_list * laps = NULL;
garmin_list * tracks = NULL;
garmin_data * rlist;
garmin_list_node * n;
garmin_list_node * m;
uint32 trk;
uint32 f_lap;
uint32 l_lap;
uint32 l_idx;
time_type start;
time_t start_time;
char filename[BUFSIZ];
bool Serial, Forerunner;
struct tm * tbuf;
// Find the data path in config file
KConfig cfg (QString("sportwatcher.rc"), KConfig::SimpleConfig);
KConfigGroup ic (&cfg, "SportWatcher");
Data = ic.readEntry("Data", QString("~/.sportwatcher"));
device = ic.readEntry("Device", QString("/dev/ttyUSB1"));
Serial = ic.readEntry("Serial", false);
Forerunner = ic.readEntry("Forerunner", false);
if (Data.isEmpty())
{
KMessageBox::error(this, i18n("No data path was set in the settings!"));
return false;
}
if (!isVisible())
setShown(true);
barProgress->setRange(0, psteps);
step = 0;
garmin_set_device(device.toAscii());
garmin_set_method((Serial) ? 1 : 0); // Setting to 1 doesn't work!! (reading over garmin_gps kernel module)
// Initialize a callback function to have a real progress bar
garmin_set_hook(&progressWidget::CallBack);
/*
* In case we should read the data out of a Forerunner 50 or
* Forerunner 405 or similar, we must do that with the help of
* the ANT library. It inserts everything into the garmin structures,
* so we can use the same procedure for every device.
*/
if (Serial && Forerunner) // Forerunner 50?
{
gant *ga;
uchar *buffer;
int size;
QString auth = Data + QString("/.auth50");
ga = new gant(auth); // Authority file
ga->setDevice(device); // Special device (serial port)
ga->read_device (); // FIXME: Parameter to tell the type of Forerunner
if ((buffer = ga->getBuffer (&size)) == 0)
{
delete ga;
return false;
}
// FIXME: Here we should decode the data buffer
delete ga;
}
/* else if (Serial && !Forerunner) // Forerunner 405
{
gant *ga;
QString auth = Data + QString("/.auth405");
ga = new gant(auth); // Authority file
ga->setDevice(device); // Special device (serial port)
ga->read_device (); // FIXME: Parameter to tell the type of Forerunner
// FIXME: Here we need a function to get the data buffer
delete ga;
} */
else // We read from a Forerunner 305 or compatible
{
lblInfo->setText(i18n("Looking for a Garmin GPS device..."));
if (garmin_init(&garmin, 0) == 0)
{
garmin_close(&garmin);
garmin_clear_hook();
return false;
}
barProgress->setValue(++step);
lblInfo->setText(i18n("Extracting data from Garmin <i>") + QString(garmin.product.product_description) + QString("</i>"));
lblReading->setText(i18n("Please wait, this may take some time!"));
mapp->processEvents();
if ((data = garmin_get(&garmin, GET_RUNS)) != NULL )
{
/*
* We should have a list with three elements:
*
* 1) The runs (which identify the track and lap indices)
* 2) The laps (which are related to the runs)
* 3) The tracks (which are related to the runs)
*/
barProgress->setValue(++step);
lblReading->setText(i18n("Sorting out runs ..."));
mapp->processEvents();
data0 = garmin_list_data(data, 0);
barProgress->setValue(++step);
lblReading->setText(i18n("Sorting out laps ..."));
mapp->processEvents();
data1 = garmin_list_data(data, 1);
barProgress->setValue(++step);
lblReading->setText(i18n("Sorting out tracks ..."));
mapp->processEvents();
data2 = garmin_list_data(data, 2);
barProgress->setValue(++step);
lblReading->setText(i18n("Sorting out data blocks done."));
mapp->processEvents();
if ( data0 != NULL && (runs = (garmin_list *)data0->data) != NULL &&
data1 != NULL && (laps = (garmin_list *)data1->data) != NULL &&
data2 != NULL && (tracks = (garmin_list *)data2->data) != NULL )
{
/* For each run, get its laps and track points. */
/* But first see how much runs to set the progress bar */
for (n = runs->head; n != NULL; n = n->next)
psteps++;
barProgress->setRange(0, psteps);
mapp->processEvents();
for (n = runs->head; n != NULL; n = n->next)
{
barProgress->setValue(++step);
mapp->processEvents();
if (get_run_track_lap_info(n->data, &trk, &f_lap, &l_lap) != 0)
{
lblReading->setText(i18n("Running: track ") + QString("%1, ").arg(trk) + i18n("laps ") + QString("%1:").arg(f_lap) + QString("%1").arg(l_lap));
mapp->processEvents();
start = 0;
/* Get the laps. */
rlaps = garmin_alloc_data(data_Dlist);
for (m = laps->head; m != NULL; m = m->next)
{
if (get_lap_index(m->data, &l_idx) != 0)
{
if ( l_idx >= f_lap && l_idx <= l_lap )
{
garmin_list_append((garmin_list *)rlaps->data, m->data);
if ( l_idx == f_lap )
get_lap_start_time(m->data, &start);
}
}
}
/* Get the track points. */
rtracks = get_track(tracks,trk);
/* Now make a three-element list for this run. */
rlist = garmin_alloc_data(data_Dlist);
garmin_list_append((garmin_list *)rlist->data,n->data);
garmin_list_append((garmin_list *)rlist->data,rlaps);
garmin_list_append((garmin_list *)rlist->data,rtracks);
/*
* Determine the filename based on the start time of the first lap
*/
if ((start_time = start) != 0)
{
QByteArray ba = Data.toAscii();
tbuf = localtime(&start_time);
filepath.sprintf("%s/%d/%02d",
ba.data(), tbuf->tm_year+1900, tbuf->tm_mon + 1);
strftime(filename, sizeof(filename), "%Y%m%dT%H%M%S.gmn", tbuf);
/* Save rlist to the file. */
garmin_save(rlist, filename, filepath.toAscii());
lblReading->setText(i18n("Saved file ") + QString(filename) + i18n(" successfully."));
mapp->processEvents();
}
else
KMessageBox::error(this, i18n("Start time of first lap not found!"));
/* Free the temporary lists we were using. */
if (rlaps != NULL)
{
garmin_free_list_only((garmin_list *)rlaps->data);
free(rlaps);
}
if (rtracks != NULL)
{
garmin_free_list_only((garmin_list *)rtracks->data);
free(rtracks);
}
if (rlist != NULL)
{
garmin_free_list_only((garmin_list *)rlist->data);
free(rlist);
}
}
}
}
else
{
if (data0 == NULL)
KMessageBox::error(this, i18n("Toplevel data missing element 0 (runs)"));
else if (runs == NULL)
KMessageBox::error(this, i18n("No runs extracted!"));
if ( data1 == NULL )
KMessageBox::error(this, i18n("Toplevel data missing element 1 (laps)"));
else if (laps == NULL)
KMessageBox::error(this, i18n("No laps extracted!"));
if (data2 == NULL)
KMessageBox::error(this, i18n("Toplevel data missing element 2 (tracks)"));
else if (tracks == NULL)
KMessageBox::error(this, i18n("No tracks extracted!"));
}
garmin_free_data(data);
}
else
KMessageBox::error(this, i18n("Unable to extract any data!"));
}
mapp->processEvents();
garmin_close(&garmin);
garmin_clear_hook();
if (garmin_count_error() > 0)
return false;
return true;
}
int progressWidget::get_run_track_lap_info ( garmin_data * run,
uint32 * track_index,
uint32 * first_lap_index,
uint32 * last_lap_index )
{
D1000 * d1000;
D1009 * d1009;
D1010 * d1010;
int ok = 1;
switch ( run->type ) {
case data_D1000:
d1000 = (D1000 *)run->data;
*track_index = d1000->track_index;
*first_lap_index = d1000->first_lap_index;
*last_lap_index = d1000->last_lap_index;
break;
case data_D1009:
d1009 = (D1009 *)run->data;
*track_index = d1009->track_index;
*first_lap_index = d1009->first_lap_index;
*last_lap_index = d1009->last_lap_index;
break;
case data_D1010:
d1010 = (D1010 *)run->data;
*track_index = d1010->track_index;
*first_lap_index = d1010->first_lap_index;
*last_lap_index = d1010->last_lap_index;
break;
default:
fprintf(stderr, "get_run_track_lap_info: run type %d invalid!\n",run->type);
ok = 0;
break;
}
return ok;
}
int progressWidget::get_lap_index ( garmin_data * lap, uint32 * lap_index )
{
D1001 * d1001;
D1011 * d1011;
D1015 * d1015;
int ok = 1;
switch ( lap->type ) {
case data_D1001:
d1001 = (D1001 *)lap->data;
*lap_index = d1001->index;
break;
case data_D1011:
d1011 = (D1011 *)lap->data;
*lap_index = d1011->index;
break;
case data_D1015:
d1015 = (D1015 *)lap->data;
*lap_index = d1015->index;
break;
default:
fprintf(stderr, "get_lap_index: lap type %d invalid!\n",lap->type);
ok = 0;
break;
}
return ok;
}
int progressWidget::get_lap_start_time (garmin_data *lap, time_type *start_time)
{
D1001 * d1001;
D1011 * d1011;
D1015 * d1015;
int ok = 1;
switch ( lap->type ) {
case data_D1001:
d1001 = (D1001 *)lap->data;
*start_time = d1001->start_time + TIME_OFFSET;
break;
case data_D1011:
d1011 = (D1011 *)lap->data;
*start_time = d1011->start_time + TIME_OFFSET;
break;
case data_D1015:
d1015 = (D1015 *)lap->data;
*start_time = d1015->start_time + TIME_OFFSET;
break;
default:
fprintf(stderr, "get_lap_start_time: lap type %d invalid!\n",lap->type);
ok = 0;
break;
}
return ok;
}
garmin_data *progressWidget::get_track(garmin_list *points, uint32 trk_index)
{
garmin_list_node * n;
garmin_data * track = NULL;
D311 * d311;
int done = 0;
/* Look for a data_D311 with an index that matches. */
for ( n = points->head; n != NULL; n = n->next ) {
if ( n->data != NULL ) {
switch ( n->data->type ) {
case data_D311:
if ( track == NULL ) {
d311 = (D311 *)n->data->data;
if ( d311->index == trk_index ) {
track = garmin_alloc_data(data_Dlist);
garmin_list_append((garmin_list *)track->data,n->data);
}
} else {
/* We've reached the end of the track */
done = 1;
}
break;
case data_D300:
case data_D301:
case data_D302:
case data_D303:
case data_D304:
if ( track != NULL ) {
garmin_list_append((garmin_list *)track->data,n->data);
}
break;
default:
fprintf(stderr, "get_track: point type %d invalid!\n",n->data->type);
break;
}
}
if ( done != 0 ) break;
}
return track;
}
#include "progresswidget.moc"