Subversion Repositories public

Rev

Rev 232 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
95 andreas 1
/***************************************************************************
232 andreas 2
 *   Copyright (C) 2007 - 2009 by Andreas Theofilu                         *
95 andreas 3
 *   andreas@theosys.at                                                    *
4
 *                                                                         *
5
 *   This program is free software; you can redistribute it and/or modify  *
6
 *   it under the terms of the GNU General Public License as published by  *
7
 *   the Free Software Foundation version 3 of the License.                *
8
 *                                                                         *
9
 *   This program is distributed in the hope that it will be useful,       *
10
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12
 *   GNU General Public License for more details.                          *
13
 *                                                                         *
14
 *   You should have received a copy of the GNU General Public License     *
15
 *   along with this program; if not, write to the                         *
16
 *   Free Software Foundation, Inc.,                                       *
17
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18
 ***************************************************************************/
19
 
232 andreas 20
/*
21
 * Ported to KDE4 on Jul. 8 2009 by Andreas Theofilu.
22
 */
95 andreas 23
 
24
#include "progresswidget.h"
132 andreas 25
#include <kapplication.h>
95 andreas 26
#include <kmessagebox.h>
232 andreas 27
#include <KConfig>
95 andreas 28
#include <klocale.h>
29
#include <qlabel.h>
232 andreas 30
#include <QProgressBar>
95 andreas 31
#include "garmin.h"
232 andreas 32
#include "../libgant/gant.h"
95 andreas 33
 
137 andreas 34
#include <iostream>
132 andreas 35
 
137 andreas 36
using std::cout;
37
using std::endl;
38
 
132 andreas 39
extern KApplication *mapp;
143 andreas 40
progressWidget *me;
132 andreas 41
 
232 andreas 42
progressWidget::progressWidget ( QWidget* parent, Qt::WFlags fl )
43
		: QDialog(parent, fl), Ui::Progress ()
95 andreas 44
{
232 andreas 45
	setupUi (this);
143 andreas 46
	step = 0;
47
	psteps = 7;
48
	me = this;
95 andreas 49
}
50
 
51
progressWidget::~progressWidget()
52
{
143 andreas 53
	me = 0;
95 andreas 54
}
55
 
143 andreas 56
/*
57
 * This function is called from the Garmin library libgarmin.a during
58
 * reading data from a GPS device.
59
 */
232 andreas 60
void progressWidget::CallBack(char *)
137 andreas 61
{
143 andreas 62
	if (me)
63
	   me->IncrementBar();
137 andreas 64
}
65
 
143 andreas 66
void progressWidget::IncrementBar()
67
{
68
	step++;
69
 
70
	if (psteps <= step)
71
	{
72
	   psteps += 2;
232 andreas 73
	   barProgress->setRange(0, psteps);
143 andreas 74
	}
75
 
232 andreas 76
	barProgress->setValue(step);
143 andreas 77
}
78
 
95 andreas 79
/*$SPECIALIZATION$*/
143 andreas 80
/*
81
 * The following function reads out all data from a GPS device. It uses
82
 * the library libgarmin.a, who is basicly the "garmintools-0.5", written by
83
 * Dave Bailey (thanks Dave!).
84
 */
137 andreas 85
bool progressWidget::Download()
95 andreas 86
{
100 andreas 87
QString Data, filepath, device;
95 andreas 88
garmin_unit         garmin;
89
garmin_data *       data;
90
garmin_data *       data0;
91
garmin_data *       data1;
92
garmin_data *       data2;
93
garmin_data *       rlaps;
94
garmin_data *       rtracks;
95
garmin_list *       runs   = NULL;
96
garmin_list *       laps   = NULL;
97
garmin_list *       tracks = NULL;
98
garmin_data *       rlist;
99
garmin_list_node *  n;
100
garmin_list_node *  m;
101
uint32              trk;
102
uint32              f_lap;
103
uint32              l_lap;
104
uint32              l_idx;
105
time_type           start;
106
time_t              start_time;
107
char                filename[BUFSIZ];
232 andreas 108
bool		    Serial, Forerunner;
95 andreas 109
struct tm *         tbuf;
110
 
111
	// Find the data path in config file
232 andreas 112
	KConfig cfg (QString("sportwatcher.rc"), KConfig::SimpleConfig);
113
	KConfigGroup ic (&cfg, "SportWatcher");
114
	Data = ic.readEntry("Data", QString("~/.sportwatcher"));
115
	device = ic.readEntry("Device", QString("/dev/ttyUSB1"));
116
	Serial = ic.readEntry("Serial", false);
117
	Forerunner = ic.readEntry("Forerunner", false);
95 andreas 118
 
119
	if (Data.isEmpty())
120
	{
121
	   KMessageBox::error(this, i18n("No data path was set in the settings!"));
137 andreas 122
	   return false;
95 andreas 123
	}
124
 
100 andreas 125
	if (!isVisible())
132 andreas 126
	   setShown(true);
100 andreas 127
 
232 andreas 128
	barProgress->setRange(0, psteps);
143 andreas 129
	step = 0;
232 andreas 130
	garmin_set_device(device.toAscii());
149 andreas 131
	garmin_set_method((Serial) ? 1 : 0);		// Setting to 1 doesn't work!! (reading over garmin_gps kernel module)
143 andreas 132
	// Initialize a callback function to have a real progress bar
137 andreas 133
	garmin_set_hook(&progressWidget::CallBack);
100 andreas 134
 
232 andreas 135
	/*
136
	 * In case we should read the data out of a Forerunner 50 or
137
	 * Forerunner 405 or similar, we must do that with the help of
138
	 * the ANT library. It inserts everything into the garmin structures,
139
	 * so we can use the same procedure for every device.
140
	 */
141
	if (Serial && Forerunner)	// Forerunner 50?
95 andreas 142
	{
232 andreas 143
	gant *ga;
144
	uchar *buffer;
145
	int size;
146
	QString auth = Data + QString("/.auth50");
95 andreas 147
 
232 andreas 148
	   ga = new gant(auth);		// Authority file
149
	   ga->setDevice(device);	// Special device (serial port)
150
	   ga->read_device ();		// FIXME: Parameter to tell the type of Forerunner
95 andreas 151
 
232 andreas 152
	   if ((buffer = ga->getBuffer (&size)) == 0)
153
	   {
154
	      delete ga;
155
	      return false;
156
	   }
132 andreas 157
 
232 andreas 158
	   // FIXME: Here we should decode the data buffer
159
	   delete ga;
160
	}
161
/*	else if (Serial && !Forerunner)	// Forerunner 405
95 andreas 162
	{
232 andreas 163
	gant *ga;
164
	QString auth = Data + QString("/.auth405");
95 andreas 165
 
232 andreas 166
	   ga = new gant(auth);		// Authority file
167
	   ga->setDevice(device);	// Special device (serial port)
168
	   ga->read_device ();		// FIXME: Parameter to tell the type of Forerunner
169
	   // FIXME: Here we need a function to get the data buffer
170
	   delete ga;
171
	} */
172
	else	// We read from a Forerunner 305 or compatible
173
	{
174
	   lblInfo->setText(i18n("Looking for a Garmin GPS device..."));
175
 
176
	   if (garmin_init(&garmin, 0) == 0)
177
	   {
178
	      garmin_close(&garmin);
179
	      garmin_clear_hook();
180
	      return false;
181
	   }
182
 
183
	   barProgress->setValue(++step);
184
	   lblInfo->setText(i18n("Extracting data from Garmin <i>") + QString(garmin.product.product_description) + QString("</i>"));
185
	   lblReading->setText(i18n("Please wait, this may take some time!"));
186
 
132 andreas 187
	   mapp->processEvents();
95 andreas 188
 
232 andreas 189
	   if ((data = garmin_get(&garmin, GET_RUNS)) != NULL )
95 andreas 190
	   {
232 andreas 191
	      /*
192
	       * We should have a list with three elements:
193
	       *
194
	       * 1) The runs (which identify the track and lap indices)
195
	       * 2) The laps (which are related to the runs)
196
	       * 3) The tracks (which are related to the runs)
197
	       */
95 andreas 198
 
232 andreas 199
	      barProgress->setValue(++step);
200
	      lblReading->setText(i18n("Sorting out runs ..."));
132 andreas 201
	      mapp->processEvents();
232 andreas 202
	      data0 = garmin_list_data(data, 0);
203
	      barProgress->setValue(++step);
204
	      lblReading->setText(i18n("Sorting out laps ..."));
205
	      mapp->processEvents();
206
	      data1 = garmin_list_data(data, 1);
207
	      barProgress->setValue(++step);
208
	      lblReading->setText(i18n("Sorting out tracks ..."));
209
	      mapp->processEvents();
210
	      data2 = garmin_list_data(data, 2);
211
	      barProgress->setValue(++step);
212
	      lblReading->setText(i18n("Sorting out data blocks done."));
213
	      mapp->processEvents();
95 andreas 214
 
232 andreas 215
	      if ( data0 != NULL && (runs   = (garmin_list *)data0->data) != NULL &&
216
		data1 != NULL && (laps   = (garmin_list *)data1->data) != NULL &&
217
		data2 != NULL && (tracks = (garmin_list *)data2->data) != NULL )
95 andreas 218
	      {
232 andreas 219
 
220
		 /* For each run, get its laps and track points. */
221
		 /* But first see how much runs to set the progress bar */
222
		 for (n = runs->head; n != NULL; n = n->next)
223
		    psteps++;
224
 
225
		 barProgress->setRange(0, psteps);
132 andreas 226
		 mapp->processEvents();
95 andreas 227
 
232 andreas 228
		 for (n = runs->head; n != NULL; n = n->next)
95 andreas 229
		 {
232 andreas 230
		    barProgress->setValue(++step);
132 andreas 231
		    mapp->processEvents();
95 andreas 232
 
232 andreas 233
		    if (get_run_track_lap_info(n->data, &trk, &f_lap, &l_lap) != 0)
234
		    {
246 andreas 235
		       lblReading->setText(i18n("Running: track ") + QString("%1, ").arg(trk) + i18n("laps ") + QString("%1:").arg(f_lap) + QString("%1").arg(l_lap));
232 andreas 236
		       mapp->processEvents();
237
		       start = 0;
95 andreas 238
 
232 andreas 239
		       /* Get the laps. */
240
		       rlaps = garmin_alloc_data(data_Dlist);
241
 
242
		       for (m = laps->head; m != NULL; m = m->next)
95 andreas 243
		       {
232 andreas 244
			  if (get_lap_index(m->data, &l_idx) != 0)
95 andreas 245
			  {
232 andreas 246
			     if ( l_idx >= f_lap && l_idx <= l_lap )
247
			     {
248
			        garmin_list_append((garmin_list *)rlaps->data, m->data);
95 andreas 249
 
232 andreas 250
			        if ( l_idx == f_lap )
251
				   get_lap_start_time(m->data, &start);
252
			     }
95 andreas 253
			  }
254
		       }
255
 
232 andreas 256
		       /* Get the track points. */
95 andreas 257
 
232 andreas 258
		       rtracks = get_track(tracks,trk);
95 andreas 259
 
232 andreas 260
		       /* Now make a three-element list for this run. */
261
		       rlist = garmin_alloc_data(data_Dlist);
262
		       garmin_list_append((garmin_list *)rlist->data,n->data);
263
		       garmin_list_append((garmin_list *)rlist->data,rlaps);
264
		       garmin_list_append((garmin_list *)rlist->data,rtracks);
95 andreas 265
 
232 andreas 266
		       /*
267
		        * Determine the filename based on the start time of the first lap
268
		        */
95 andreas 269
 
232 andreas 270
		       if ((start_time = start) != 0)
271
		       {
272
			  QByteArray ba = Data.toAscii();
95 andreas 273
 
232 andreas 274
			  tbuf = localtime(&start_time);
275
			  filepath.sprintf("%s/%d/%02d",
276
			     ba.data(), tbuf->tm_year+1900, tbuf->tm_mon + 1);
277
			  strftime(filename, sizeof(filename), "%Y%m%dT%H%M%S.gmn", tbuf);
143 andreas 278
 
232 andreas 279
			  /* Save rlist to the file. */
280
			  garmin_save(rlist, filename, filepath.toAscii());
281
			  lblReading->setText(i18n("Saved file ") + QString(filename) + i18n(" successfully."));
282
			  mapp->processEvents();
283
		       }
284
	               else
285
			  KMessageBox::error(this, i18n("Start time of first lap not found!"));
95 andreas 286
 
232 andreas 287
		       /* Free the temporary lists we were using. */
95 andreas 288
 
232 andreas 289
		       if (rlaps != NULL)
290
		       {
291
			  garmin_free_list_only((garmin_list *)rlaps->data);
292
			  free(rlaps);
293
		       }
95 andreas 294
 
232 andreas 295
		       if (rtracks != NULL)
296
		       {
297
			  garmin_free_list_only((garmin_list *)rtracks->data);
298
			  free(rtracks);
299
		       }
300
 
301
		       if (rlist != NULL)
302
		       {
303
			  garmin_free_list_only((garmin_list *)rlist->data);
304
			  free(rlist);
305
		       }
95 andreas 306
		    }
307
		 }
308
	      }
232 andreas 309
	      else
310
	      {
311
		 if (data0 == NULL)
312
		    KMessageBox::error(this, i18n("Toplevel data missing element 0 (runs)"));
313
		 else if (runs == NULL)
314
		    KMessageBox::error(this, i18n("No runs extracted!"));
95 andreas 315
 
232 andreas 316
		 if ( data1 == NULL )
317
		    KMessageBox::error(this, i18n("Toplevel data missing element 1 (laps)"));
318
		 else if (laps == NULL)
319
		    KMessageBox::error(this, i18n("No laps extracted!"));
95 andreas 320
 
232 andreas 321
		 if (data2 == NULL)
322
		    KMessageBox::error(this, i18n("Toplevel data missing element 2 (tracks)"));
323
		 else if (tracks == NULL)
324
		    KMessageBox::error(this, i18n("No tracks extracted!"));
325
	      }
326
 
327
	      garmin_free_data(data);
95 andreas 328
	   }
232 andreas 329
	   else
330
	      KMessageBox::error(this, i18n("Unable to extract any data!"));
95 andreas 331
	}
332
 
132 andreas 333
	mapp->processEvents();
100 andreas 334
	garmin_close(&garmin);
137 andreas 335
	garmin_clear_hook();
336
 
337
	if (garmin_count_error() > 0)
338
	   return false;
339
 
340
	return true;
95 andreas 341
}
342
 
343
int progressWidget::get_run_track_lap_info ( garmin_data * run,
344
			 uint32 *      track_index,
345
			 uint32 *      first_lap_index,
346
			 uint32 *      last_lap_index )
347
{
348
  D1000 * d1000;
349
  D1009 * d1009;
350
  D1010 * d1010;
351
 
352
  int ok = 1;
353
 
354
  switch ( run->type ) {
355
  case data_D1000:
356
    d1000            = (D1000 *)run->data;
357
    *track_index     = d1000->track_index;
358
    *first_lap_index = d1000->first_lap_index;
359
    *last_lap_index  = d1000->last_lap_index;
360
    break;
361
  case data_D1009:
362
    d1009            = (D1009 *)run->data;
363
    *track_index     = d1009->track_index;
364
    *first_lap_index = d1009->first_lap_index;
365
    *last_lap_index  = d1009->last_lap_index;
366
    break;
367
  case data_D1010:
368
    d1010            = (D1010 *)run->data;
369
    *track_index     = d1010->track_index;
370
    *first_lap_index = d1010->first_lap_index;
371
    *last_lap_index  = d1010->last_lap_index;
372
    break;
373
  default:
132 andreas 374
    fprintf(stderr, "get_run_track_lap_info: run type %d invalid!\n",run->type);
95 andreas 375
    ok = 0;
376
    break;
377
  }
378
 
379
  return ok;
380
}
381
 
382
int progressWidget::get_lap_index ( garmin_data * lap, uint32 * lap_index )
383
{
384
  D1001 * d1001;
385
  D1011 * d1011;
386
  D1015 * d1015;
387
 
388
  int ok = 1;
389
 
390
  switch ( lap->type ) {
391
  case data_D1001:
392
    d1001      = (D1001 *)lap->data;
393
    *lap_index = d1001->index;
394
    break;
395
  case data_D1011:
396
    d1011      = (D1011 *)lap->data;
397
    *lap_index = d1011->index;
398
    break;
399
  case data_D1015:
400
    d1015      = (D1015 *)lap->data;
401
    *lap_index = d1015->index;
402
    break;
403
  default:
404
    fprintf(stderr, "get_lap_index: lap type %d invalid!\n",lap->type);
405
    ok = 0;
406
    break;
407
  }
408
 
409
  return ok;
410
}
411
 
412
 
413
int progressWidget::get_lap_start_time (garmin_data *lap, time_type *start_time)
414
{
415
  D1001 * d1001;
416
  D1011 * d1011;
417
  D1015 * d1015;
418
 
419
  int ok = 1;
420
 
421
  switch ( lap->type ) {
422
  case data_D1001:
423
    d1001       = (D1001 *)lap->data;
424
    *start_time = d1001->start_time + TIME_OFFSET;
425
    break;
426
  case data_D1011:
427
    d1011       = (D1011 *)lap->data;
428
    *start_time = d1011->start_time + TIME_OFFSET;
429
    break;
430
  case data_D1015:
431
    d1015       = (D1015 *)lap->data;
432
    *start_time = d1015->start_time + TIME_OFFSET;
433
    break;
434
  default:
132 andreas 435
    fprintf(stderr, "get_lap_start_time: lap type %d invalid!\n",lap->type);
95 andreas 436
    ok = 0;
437
    break;
438
  }
439
 
440
  return ok;
441
}
442
 
443
 
444
garmin_data *progressWidget::get_track(garmin_list *points, uint32 trk_index)
445
{
446
  garmin_list_node * n;
447
  garmin_data *      track = NULL;
448
  D311 *             d311;
449
  int                done = 0;
450
 
451
  /* Look for a data_D311 with an index that matches. */
452
 
453
  for ( n = points->head; n != NULL; n = n->next ) {    
454
    if ( n->data != NULL ) {
455
      switch ( n->data->type ) {
456
      case data_D311:
457
	if ( track == NULL ) {
458
	  d311 = (D311 *)n->data->data;
459
	  if ( d311->index == trk_index ) {
460
	    track = garmin_alloc_data(data_Dlist);
461
	    garmin_list_append((garmin_list *)track->data,n->data);
462
	  }
463
	} else {
464
	  /* We've reached the end of the track */
465
	  done = 1;
466
	}
467
	break;
468
      case data_D300:
469
      case data_D301:
470
      case data_D302:
471
      case data_D303:
472
      case data_D304:
473
	if ( track != NULL ) {
474
	  garmin_list_append((garmin_list *)track->data,n->data);
475
	}
476
	break;
477
      default:
132 andreas 478
	fprintf(stderr, "get_track: point type %d invalid!\n",n->data->type);
95 andreas 479
	break;
480
      }
481
    }
482
 
483
    if ( done != 0 ) break;
484
  }
485
 
486
  return track;
487
}
488
 
489
 
490
#include "progresswidget.moc"
491