Subversion Repositories public

Rev

Rev 216 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "config.h"
#include <time.h>
#include <string.h>
#include <errno.h>
#include "garmin.h"


int
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;

  if (!run) return 0;

  switch ( run->type ) {
  case data_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            = 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            = 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
get_lap_index ( garmin_data * lap, uint32 * lap_index )
{
  D1001 * d1001;
  D1011 * d1011;
  D1015 * d1015;

  int ok = 1;

  if (!lap) return 0;

  switch ( lap->type ) {
  case data_D1001:
    d1001      = lap->data;
    *lap_index = d1001->index;
    break;
  case data_D1011:
    d1011      = lap->data;
    *lap_index = d1011->index;
    break;
  case data_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
get_lap_start_time ( garmin_data * lap, time_type * start_time )
{
  D1001 * d1001;
  D1011 * d1011;
  D1015 * d1015;

  int ok = 1;

  if (!lap) return 0;

  switch ( lap->type ) {
  case data_D1001:
    d1001       = lap->data;
    *start_time = d1001->start_time + TIME_OFFSET;
    break;
  case data_D1011:
    d1011       = lap->data;
    *start_time = d1011->start_time + TIME_OFFSET;
    break;
  case data_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 *
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. */

  if (!points) return NULL;

  for ( n = points->head; n != NULL; n = n->next ) {    
    if ( n->data != NULL ) {
      switch ( n->data->type ) {
      case data_D311:
        if ( track == NULL ) {
          d311 = n->data->data;
          if ( d311->index == trk_index ) {
            track = garmin_alloc_data(data_Dlist);
            garmin_list_append(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(track->data,n->data);
        }
        break;
      default:
        printf("get_track: point type %d invalid!\n",n->data->type);
        break;
      }
    }

    if ( done != 0 ) break;
  }

  return track;
}


void
garmin_save_runs ( 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];
  char *              filedir = NULL;
  char                path[PATH_MAX];
  char                filepath[BUFSIZ];
  struct tm *         tbuf;

  if (!garmin) return;

  if ( (filedir = getenv("GARMIN_SAVE_RUNS")) != NULL ) {
    filedir = realpath(filedir,path);
    if ( filedir == NULL ) {
      printf("GARMIN_SAVE_RUNS: %s: %s\n",
             getenv("GARMIN_SAVE_RUNS"),strerror(errno));
    }
  }
  if ( filedir == NULL ) {
    filedir = getcwd(path,sizeof(path));
  }

  printf("Extracting data from Garmin %s\n",
         garmin->product.product_description);
  printf("Files will be saved in '%s'\n",filedir);

  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)
    */

    data0 = garmin_list_data(data,0);
    data1 = garmin_list_data(data,1);
    data2 = garmin_list_data(data,2);

    if ( data0 != NULL && (runs   = data0->data) != NULL &&
         data1 != NULL && (laps   = data1->data) != NULL &&
         data2 != NULL && (tracks = data2->data) != NULL ) {

      /* Print some debug output if requested. */

      if ( garmin->verbose != 0 ) {
        for ( m = laps->head; m != NULL; m = m->next ) {
          if ( get_lap_index(m->data,&l_idx) != 0 ) {
            printf("[garmin] lap: index [%d]\n",l_idx);
          } else {
            printf("[garmin] lap: index [??]\n");
          }
        }
      }
      
      /* For each run, get its laps and track points. */

      for ( n = runs->head; n != NULL; n = n->next ) {
        if ( get_run_track_lap_info(n->data,&trk,&f_lap,&l_lap) != 0 ) {

          if ( garmin->verbose != 0 ) {
            printf("[garmin] run: track [%d], laps [%d:%d]\n",trk,f_lap,l_lap);
          }

          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 ) {
                if ( garmin->verbose != 0 ) {
                  printf("[garmin] lap [%d] falls within laps [%d:%d]\n",
                         l_idx,f_lap,l_lap);
                }

                garmin_list_append(rlaps->data,m->data);

                if ( l_idx == f_lap ) {
                  get_lap_start_time(m->data,&start);
                  if ( garmin->verbose != 0 ) {
                    printf("[garmin] first lap [%d] has start time [%d]\n",
                           l_idx,(int)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(rlist->data,n->data);
          garmin_list_append(rlist->data,rlaps);
          garmin_list_append(rlist->data,rtracks);

          /* 
             Determine the filename based on the start time of the first lap. 
          */

          if ( (start_time = start) != 0 ) {
            tbuf = localtime(&start_time);
            snprintf(filepath,sizeof(filepath)-1,"%s/%d/%02d",
                    filedir,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. */

            if ( garmin_save(rlist,filename,filepath) != 0 ) {
              printf("Wrote:   %s/%s\n",filepath,filename);
            } else {
              printf("Skipped: %s/%s\n",filepath,filename);
            }
          } else {
            printf("Start time of first lap not found!\n");
          }

          /* Free the temporary lists we were using. */

          if ( rlaps != NULL ) {
            garmin_free_list_only(rlaps->data);
            free(rlaps);
          }

          if ( rtracks != NULL ) {
            garmin_free_list_only(rtracks->data);
            free(rtracks);
          }

          if ( rlist != NULL ) {
            garmin_free_list_only(rlist->data);
            free(rlist);
          }
        }
      }
    } else {
      if ( data0 == NULL ) {
        printf("Toplevel data missing element 0 (runs)\n");
      } else if ( runs == NULL ) {
        printf("No runs extracted!\n");
      }
      if ( data1 == NULL ) {
        printf("Toplevel data missing element 1 (laps)\n");
      } else if ( laps == NULL ) {
        printf("No laps extracted!\n");
      }
      if ( data2 == NULL ) {
        printf("Toplevel data missing element 2 (tracks)\n");
      } else if ( tracks == NULL ) {
        printf("No tracks extracted!\n");
      }
    }
    garmin_free_data(data);
  } else {
    printf("Unable to extract any data!\n");
  }
}