Diff of /trunk/src/gps.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 14 by harbaum, Sat Jun 27 19:18:40 2009 UTC revision 233 by harbaum, Wed Dec 9 19:45:36 2009 UTC
# Line 32  Line 32 
32  #include <errno.h>  #include <errno.h>
33  #endif  #endif
34    
35    static void gps_unregister_all(appdata_t *appdata);
36    
37  #ifndef ENABLE_LIBLOCATION  #ifndef ENABLE_LIBLOCATION
38    
39  /* maybe user configurable later on ... */  /* maybe user configurable later on ... */
# Line 97  float gps_get_heading(appdata_t *appdata Line 99  float gps_get_heading(appdata_t *appdata
99    return retval;    return retval;
100  }  }
101    
102  float gps_get_epe(appdata_t *appdata) {  float gps_get_eph(appdata_t *appdata) {
103    float retval = NAN;    float retval = NAN;
104    
105    g_mutex_lock(appdata->gps_state->mutex);    g_mutex_lock(appdata->gps_state->mutex);
# Line 114  static int gps_connect(gps_state_t *gps_ Line 116  static int gps_connect(gps_state_t *gps_
116  #ifdef USE_MAEMO  #ifdef USE_MAEMO
117    char errstr[256] = "";    char errstr[256] = "";
118    
119      if(!gps_state) {
120        printf("No gps state\n");
121        return -1;
122      }
123    
124    /* We need to start gpsd (via gpsbt) first. */    /* We need to start gpsd (via gpsbt) first. */
125    memset(&gps_state->context, 0, sizeof(gpsbt_t));    memset(&gps_state->context, 0, sizeof(gpsbt_t));
126    errno = 0;    errno = 0;
127    
128    if(gpsbt_start(NULL, 0, 0, 0, errstr, sizeof(errstr),    if(gpsbt_start(NULL, 0, 0, 0, errstr, sizeof(errstr),
129                   0, &gps_state->context) < 0) {                   0, &gps_state->context) < 0) {
130      printf("Error connecting to GPS receiver: (%d) %s (%s)\n",      printf("gps: Error connecting to GPS receiver: (%d) %s (%s)\n",
131             errno, strerror(errno), errstr);             errno, strerror(errno), errstr);
132    }    }
133  #endif  #endif
# Line 134  static int gps_connect(gps_state_t *gps_ Line 141  static int gps_connect(gps_state_t *gps_
141    while(retries &&    while(retries &&
142          (GNOME_VFS_OK != (vfs_result = gnome_vfs_inet_connection_create(          (GNOME_VFS_OK != (vfs_result = gnome_vfs_inet_connection_create(
143                  &gps_state->iconn, GPSD_HOST, GPSD_PORT, NULL)))) {                  &gps_state->iconn, GPSD_HOST, GPSD_PORT, NULL)))) {
144      printf("Error creating connection to GPSD, retrying ...\n");      printf("gps: Error creating connection to GPSD, retrying ...\n");
145    
146      retries--;      retries--;
147      sleep(1);      sleep(1);
148    }    }
149    
150    if(!retries) {    if(!retries) {
151      printf("Finally failed ...\n");      printf("gps: Finally failed ...\n");
152      return -1;      return -1;
153    }    }
154    
155    retries = 5;    retries = 5;
156    while(retries && ((gps_state->socket =    while(retries && ((gps_state->socket =
157       gnome_vfs_inet_connection_to_socket(gps_state->iconn)) == NULL)) {       gnome_vfs_inet_connection_to_socket(gps_state->iconn)) == NULL)) {
158      printf("Error creating connecting GPSD socket, retrying ...\n");      printf("gps: Error creating connecting GPSD socket, retrying ...\n");
159    
160      retries--;      retries--;
161      sleep(1);      sleep(1);
162    }    }
163    
164    if(!retries) {    if(!retries) {
165      printf("Finally failed ...\n");      printf("gps: Finally failed ...\n");
166      return -1;      return -1;
167    }    }
168    
169    GTimeVal timeout = { 10, 0 };    GTimeVal timeout = { 10, 0 };
170    if(GNOME_VFS_OK != (vfs_result = gnome_vfs_socket_set_timeout(    if(GNOME_VFS_OK != (vfs_result = gnome_vfs_socket_set_timeout(
171          gps_state->socket, &timeout, NULL))) {          gps_state->socket, &timeout, NULL))) {
172      printf("Error setting GPSD timeout\n");      printf("gps: Error setting GPSD timeout\n");
173      return -1;      return -1;
174    }    }
175    
176    printf("GPSD connected ...\n");    printf("gps: GPSD connected ...\n");
177    
178    return 0;    return 0;
179  }  }
# Line 175  void gps_clear_fix(struct gps_fix_t *fix Line 182  void gps_clear_fix(struct gps_fix_t *fix
182    fixp->mode = MODE_NOT_SEEN;    fixp->mode = MODE_NOT_SEEN;
183    fixp->pos.lat = fixp->pos.lon = NAN;    fixp->pos.lat = fixp->pos.lon = NAN;
184    fixp->track = NAN;    fixp->track = NAN;
   fixp->speed = NAN;  
   fixp->climb = NAN;  
   fixp->altitude = NAN;  
   fixp->ept = NAN;  
185    fixp->eph = NAN;    fixp->eph = NAN;
   fixp->epv = NAN;  
   fixp->epd = NAN;  
   fixp->eps = NAN;  
   fixp->epc = NAN;  
186  }  }
187    
188  /* unpack a daemon response into a status structure */  /* unpack a daemon response into a status structure */
# Line 199  static void gps_unpack(char *buf, struct Line 198  static void gps_unpack(char *buf, struct
198          else *tp = '\0';          else *tp = '\0';
199    
200          switch (*sp) {          switch (*sp) {
201          case 'A':            /* A - altitude is not supported */
           if (sp[2] == '?') {  
             gpsdata->fix.altitude = NAN;  
           } else {  
             (void)sscanf(sp, "A=%lf", &gpsdata->fix.altitude);  
             gpsdata->set |= ALTITUDE_SET;  
           }  
           break;  
202            /* B - baudrate isn't supported by gpxview */            /* B - baudrate isn't supported by gpxview */
203            /* C - cycle isn't supported by gpxview */            /* C - cycle isn't supported by gpxview */
204            /* D - utc time isn't supported by gpxview */            /* D - utc time isn't supported by gpxview */
205          case 'E':          case 'E':
206            gpsdata->epe = gpsdata->fix.eph = gpsdata->fix.epv = NAN;            gpsdata->fix.eph = NAN;
207            /* epe should always be present if eph or epv is */            /* epe should always be present if eph or epv is */
208            if (sp[2] != '?') {            if (sp[2] != '?') {
209              char epe[20], eph[20], epv[20];              char epe[20], eph[20], epv[20];
210              (void)sscanf(sp, "E=%s %s %s", epe, eph, epv);              (void)sscanf(sp, "E=%s %s %s", epe, eph, epv);
211  #define DEFAULT(val) (val[0] == '?') ? NAN : g_ascii_strtod(val, NULL)  #define DEFAULT(val) (val[0] == '?') ? NAN : g_ascii_strtod(val, NULL)
             gpsdata->epe = DEFAULT(epe);  
212              gpsdata->fix.eph = DEFAULT(eph);              gpsdata->fix.eph = DEFAULT(eph);
             gpsdata->fix.epv = DEFAULT(epv);  
213  #undef DEFAULT  #undef DEFAULT
214            }            }
215            break;            break;
# Line 257  static void gps_unpack(char *buf, struct Line 247  static void gps_unpack(char *buf, struct
247  #define DEFAULT(val) (val[0] == '?') ? NAN : g_ascii_strtod(val, NULL)  #define DEFAULT(val) (val[0] == '?') ? NAN : g_ascii_strtod(val, NULL)
248                nf.pos.lat = DEFAULT(lat);                nf.pos.lat = DEFAULT(lat);
249                nf.pos.lon = DEFAULT(lon);                nf.pos.lon = DEFAULT(lon);
               nf.ept = DEFAULT(ept);  
               nf.altitude = DEFAULT(alt);  
250                nf.eph = DEFAULT(eph);                nf.eph = DEFAULT(eph);
               nf.epv = DEFAULT(epv);  
251                nf.track = DEFAULT(track);                nf.track = DEFAULT(track);
               nf.speed = DEFAULT(speed);  
               nf.climb = DEFAULT(climb);  
               nf.epd = DEFAULT(epd);  
               nf.eps = DEFAULT(eps);  
               nf.epc = DEFAULT(epc);  
252  #undef DEFAULT  #undef DEFAULT
253                if (st >= 15)                if (st >= 15)
254                  nf.mode = (mode[0] == '?') ? MODE_NOT_SEEN : atoi(mode);                  nf.mode = (mode[0] == '?') ? MODE_NOT_SEEN : atoi(mode);
255                else                else
256                  nf.mode = (alt[0] == '?') ? MODE_2D : MODE_3D;                  nf.mode = (alt[0] == '?') ? MODE_2D : MODE_3D;
               if (alt[0] != '?')  
                 gpsdata->set |= ALTITUDE_SET | CLIMB_SET;  
257                if (isnan(nf.eph)==0)                if (isnan(nf.eph)==0)
258                  gpsdata->set |= HERR_SET;                  gpsdata->set |= HERR_SET;
               if (isnan(nf.epv)==0)  
                 gpsdata->set |= VERR_SET;  
259                if (isnan(nf.track)==0)                if (isnan(nf.track)==0)
260                  gpsdata->set |= TRACK_SET | SPEED_SET;                  gpsdata->set |= TRACK_SET;
               if (isnan(nf.eps)==0)  
                 gpsdata->set |= SPEEDERR_SET;  
               if (isnan(nf.epc)==0)  
                 gpsdata->set |= CLIMBERR_SET;  
261                gpsdata->fix = nf;                gpsdata->fix = nf;
262                gpsdata->set |= TIME_SET|TIMERR_SET|LATLON_SET|MODE_SET;                gpsdata->set |= LATLON_SET|MODE_SET;
263                gpsdata->status = STATUS_FIX;                gpsdata->status = STATUS_FIX;
264                gpsdata->set |= STATUS_SET;                gpsdata->set |= STATUS_SET;
265              }              }
# Line 303  static void gps_unpack(char *buf, struct Line 277  static void gps_unpack(char *buf, struct
277              gpsdata->set |= LATLON_SET;              gpsdata->set |= LATLON_SET;
278            }            }
279            break;            break;
280          case 'Q':            /* Q is not supported */
           if (sp[2] == '?') {  
             gpsdata->satellites_used = 0;  
             gpsdata->pdop = 0;  
             gpsdata->hdop = 0;  
             gpsdata->vdop = 0;  
           } else {  
             (void)sscanf(sp, "Q=%d %lf %lf %lf %lf %lf",  
                          &gpsdata->satellites_used,  
                          &gpsdata->pdop,  
                          &gpsdata->hdop,  
                          &gpsdata->vdop,  
                          &gpsdata->tdop,  
                          &gpsdata->gdop);  
             gpsdata->set |= HDOP_SET | VDOP_SET | PDOP_SET;  
           }  
           break;  
281          case 'S':          case 'S':
282            if (sp[2] == '?') {            if (sp[2] == '?') {
283              gpsdata->status = -1;              gpsdata->status = -1;
# Line 332  static void gps_unpack(char *buf, struct Line 290  static void gps_unpack(char *buf, struct
290            if (sp[2] == '?') {            if (sp[2] == '?') {
291              gpsdata->fix.track = NAN;              gpsdata->fix.track = NAN;
292            } else {            } else {
293              (void)sscanf(sp, "T=%lf", &gpsdata->fix.track);              (void)sscanf(sp, "T=%f", &gpsdata->fix.track);
294              gpsdata->set |= TRACK_SET;              gpsdata->set |= TRACK_SET;
295            }            }
296            break;            break;
297          case 'U':            /* U - climb is not supported */
298            if (sp[2] == '?') {            /* V - is not supported */
299              gpsdata->fix.climb = NAN;            /* X - online is not supported */
           } else {  
             (void)sscanf(sp, "U=%lf", &gpsdata->fix.climb);  
             gpsdata->set |= CLIMB_SET;  
           }  
           break;  
         case 'V':  
           if (sp[2] == '?') {  
             gpsdata->fix.speed = NAN;  
           } else {  
             (void)sscanf(sp, "V=%lf", &gpsdata->fix.speed);  
             /* V reply is in kt, fix.speed is in metres/sec */  
             gpsdata->fix.speed = gpsdata->fix.speed / MPS_TO_KNOTS;  
             gpsdata->set |= SPEED_SET;  
           }  
           break;  
         case 'X':  
           if (sp[2] == '?')  
             gpsdata->online = -1;  
           else {  
             (void)sscanf(sp, "X=%lf", &gpsdata->online);  
             gpsdata->set |= ONLINE_SET;  
           }  
           break;  
300          case 'Y':          case 'Y':
301            if (sp[2] == '?') {            if (sp[2] == '?') {
302              gpsdata->satellites = 0;              gpsdata->satellites = 0;
# Line 377  static void gps_unpack(char *buf, struct Line 312  static void gps_unpack(char *buf, struct
312              for (j = 0; j < gpsdata->satellites; j++) {              for (j = 0; j < gpsdata->satellites; j++) {
313                PRN[j]=elevation[j]=azimuth[j]=ss[j]=used[j]=0;                PRN[j]=elevation[j]=azimuth[j]=ss[j]=used[j]=0;
314              }              }
315              //      printf("sats = %d\n", gpsdata->satellites);              //      printf("gps: sats = %d\n", gpsdata->satellites);
316              for (j = 0, gpsdata->satellites_used = 0; j < gpsdata->satellites; j++) {              for (j = 0, gpsdata->satellites_used = 0; j < gpsdata->satellites; j++) {
317                if ((sp != NULL) && ((sp = strchr(sp, ':')) != NULL)) {                if ((sp != NULL) && ((sp = strchr(sp, ':')) != NULL)) {
318                  sp++;                  sp++;
# Line 405  static void gps_unpack(char *buf, struct Line 340  static void gps_unpack(char *buf, struct
340    }    }
341  }  }
342    
343    /* call one of the application provided gps callbacks */
344    static void do_app_cb(gpointer data, gpointer user_data) {
345      appdata_t *appdata = (appdata_t*)user_data;
346      gps_cb_t *cb = (gps_cb_t*)data;
347      cb->cb(appdata->gps_state, cb->data);
348    }
349    
350    /* walk though list of all application provided callbacks */
351    static gboolean gps_idle_cb(gpointer data) {
352      appdata_t *appdata = (appdata_t*)data;
353      //  printf("gps: idle callback, calling app callbacks\n");
354    
355      g_slist_foreach(appdata->gps_state->cb, do_app_cb, appdata);
356    
357      return FALSE;
358    }
359    
360  gpointer gps_thread(gpointer data) {  gpointer gps_thread(gpointer data) {
361    GnomeVFSFileSize bytes_read;    GnomeVFSFileSize bytes_read;
362    GnomeVFSResult vfs_result;    GnomeVFSResult vfs_result;
# Line 422  gpointer gps_thread(gpointer data) { Line 374  gpointer gps_thread(gpointer data) {
374    while(1) {    while(1) {
375      if(appdata->use_gps) {      if(appdata->use_gps) {
376        if(!connected) {        if(!connected) {
377          printf("trying to connect\n");          printf("gps: trying to connect\n");
378    
379          if(gps_connect(appdata->gps_state) < 0)          if(gps_connect(appdata->gps_state) < 0)
380            sleep(10);            sleep(10);
# Line 448  gpointer gps_thread(gpointer data) { Line 400  gpointer gps_thread(gpointer data) {
400              if(vfs_result == GNOME_VFS_OK) {              if(vfs_result == GNOME_VFS_OK) {
401                str[bytes_read] = 0;                str[bytes_read] = 0;
402    
403                //          printf("msg: %s (%d)\n", str, strlen(str));                //          printf("gps: msg: %s (%d)\n", str, strlen(str));
404    
405                g_mutex_lock(appdata->gps_state->mutex);                g_mutex_lock(appdata->gps_state->mutex);
406    
407                if(!cnt) appdata->gps_state->gpsdata.set &= ~SATELLITE_SET;                if(!cnt) appdata->gps_state->gpsdata.set &= ~SATELLITE_SET;
408                else     appdata->gps_state->gpsdata.set &=                else     appdata->gps_state->gpsdata.set &=
409                           ~(TIME_SET|TIMERR_SET|LATLON_SET|MODE_SET|STATUS_SET);                           ~(LATLON_SET|MODE_SET|STATUS_SET);
410    
411                gps_unpack(str, &appdata->gps_state->gpsdata);                gps_unpack(str, &appdata->gps_state->gpsdata);
412                g_mutex_unlock(appdata->gps_state->mutex);                g_mutex_unlock(appdata->gps_state->mutex);
413                  g_idle_add(gps_idle_cb, appdata);
414              }              }
415            }            }
416          }          }
# Line 465  gpointer gps_thread(gpointer data) { Line 418  gpointer gps_thread(gpointer data) {
418        }        }
419      } else {      } else {
420        if(connected) {        if(connected) {
421          printf("stopping GPS connection due to user request\n");          printf("gps: stopping GPS connection due to user request\n");
422          gnome_vfs_inet_connection_destroy(appdata->gps_state->iconn, NULL);          gnome_vfs_inet_connection_destroy(appdata->gps_state->iconn, NULL);
423    
424  #ifdef USE_MAEMO  #ifdef USE_MAEMO
# Line 477  gpointer gps_thread(gpointer data) { Line 430  gpointer gps_thread(gpointer data) {
430      }      }
431    }    }
432    
433    printf("GPS thread ended???\n");    printf("gps: thread ended???\n");
434    return NULL;    return NULL;
435  }  }
436    
# Line 491  void gps_init(appdata_t *appdata) { Line 444  void gps_init(appdata_t *appdata) {
444  }  }
445    
446  void gps_release(appdata_t *appdata) {  void gps_release(appdata_t *appdata) {
447      gps_unregister_all(appdata);
448  #ifdef USE_MAEMO  #ifdef USE_MAEMO
449    gpsbt_stop(&appdata->gps_state->context);    gpsbt_stop(&appdata->gps_state->context);
450  #endif  #endif
# Line 505  location_changed(LocationGPSDevice *devi Line 459  location_changed(LocationGPSDevice *devi
459    gps_state->fields = device->fix->fields;    gps_state->fields = device->fix->fields;
460    
461    if(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET) {    if(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET) {
462      gps_state->latitude = device->fix->latitude;      gps_state->fix.pos.lat = device->fix->latitude;
463      gps_state->longitude = device->fix->longitude;      gps_state->fix.pos.lon = device->fix->longitude;
464      gps_state->epe = device->fix->eph;      gps_state->fix.eph = device->fix->eph/100.0;  // we want eph in meters
465    }    }
466    
467    if(gps_state->fields & LOCATION_GPS_DEVICE_TRACK_SET)    if(gps_state->fields & LOCATION_GPS_DEVICE_TRACK_SET)
468      gps_state->heading = device->fix->track;      gps_state->fix.track = device->fix->track;
469    
470    /* update list of sattelites */    /* update list of sattelites */
471    
# Line 546  location_changed(LocationGPSDevice *devi Line 500  location_changed(LocationGPSDevice *devi
500  void gps_init(appdata_t *appdata) {  void gps_init(appdata_t *appdata) {
501    gps_state_t *gps_state = appdata->gps_state = g_new0(gps_state_t, 1);    gps_state_t *gps_state = appdata->gps_state = g_new0(gps_state_t, 1);
502    
503    printf("GPS init: Using liblocation\n");    printf("gps: init: Using liblocation\n");
504    
505    gps_state->device = g_object_new(LOCATION_TYPE_GPS_DEVICE, NULL);    gps_state->device = g_object_new(LOCATION_TYPE_GPS_DEVICE, NULL);
506    if(!gps_state->device) {    if(!gps_state->device) {
507      printf("Unable to connect to liblocation\n");      printf("gps: Unable to connect to liblocation\n");
508      return;      return;
509    }    }
510    
# Line 558  void gps_init(appdata_t *appdata) { Line 512  void gps_init(appdata_t *appdata) {
512      g_signal_connect(gps_state->device, "changed",      g_signal_connect(gps_state->device, "changed",
513                       G_CALLBACK(location_changed), gps_state);                       G_CALLBACK(location_changed), gps_state);
514    
 #if MAEMO_VERSION_MAJOR < 5  
515    gps_state->control = location_gpsd_control_get_default();    gps_state->control = location_gpsd_control_get_default();
516    
517    if(gps_state->control && gps_state->control->can_control) {    if(gps_state->control
518      printf("Having control over GPSD and GPS is to be enabled, starting it\n");  #if MAEMO_VERSION_MAJOR < 5
519         && gps_state->control->can_control
520    #endif
521         ) {
522    
523        printf("gps: Having control over GPSD and GPS is to be enabled, starting it\n");
524      location_gpsd_control_start(gps_state->control);      location_gpsd_control_start(gps_state->control);
525    }    }
 #endif  
526  }  }
527    
528  void gps_release(appdata_t *appdata) {  void gps_release(appdata_t *appdata) {
529    gps_state_t *gps_state = appdata->gps_state;    gps_state_t *gps_state = appdata->gps_state;
530      gps_unregister_all(appdata);
531    
532    if(!gps_state->device) return;    if(!gps_state->device) return;
533    
534      if(gps_state->control
535  #if MAEMO_VERSION_MAJOR < 5  #if MAEMO_VERSION_MAJOR < 5
536    if(gps_state->control && gps_state->control->can_control) {       && gps_state->control->can_control
537      printf("Having control over GPSD, stopping it\n");  #endif
538         ) {
539        printf("gps: Having control over GPSD, stopping it\n");
540      location_gpsd_control_stop(gps_state->control);      location_gpsd_control_stop(gps_state->control);
541    }    }
 #endif  
542    
543    /* Disconnect signal */    /* Disconnect signal */
544    g_signal_handler_disconnect(gps_state->device, gps_state->idd_changed);    g_signal_handler_disconnect(gps_state->device, gps_state->idd_changed);
# Line 598  pos_t *gps_get_pos(appdata_t *appdata) { Line 558  pos_t *gps_get_pos(appdata_t *appdata) {
558    if(!(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET))    if(!(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET))
559      return NULL;      return NULL;
560    
561    pos.lat = gps_state->latitude;    pos.lat = gps_state->fix.pos.lat;
562    pos.lon = gps_state->longitude;    pos.lon = gps_state->fix.pos.lon;
563    
564    return &pos;    return &pos;
565  }  }
# Line 610  float gps_get_heading(appdata_t *appdata Line 570  float gps_get_heading(appdata_t *appdata
570    if(!(gps_state->fields & LOCATION_GPS_DEVICE_TRACK_SET))    if(!(gps_state->fields & LOCATION_GPS_DEVICE_TRACK_SET))
571      return NAN;      return NAN;
572    
573    return gps_state->heading;    return gps_state->fix.track;
574  }  }
575    
576  float gps_get_epe(appdata_t *appdata) {  float gps_get_eph(appdata_t *appdata) {
577    gps_state_t *gps_state = appdata->gps_state;    gps_state_t *gps_state = appdata->gps_state;
578    
579    if(!(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET))    if(!(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET))
580      return NAN;      return NAN;
581    
582    return gps_state->epe;    return gps_state->fix.eph;
583  }  }
584    
585  gps_sat_t *gps_get_sats(appdata_t *appdata) {  gps_sat_t *gps_get_sats(appdata_t *appdata) {
# Line 643  gps_sat_t *gps_get_sats(appdata_t *appda Line 603  gps_sat_t *gps_get_sats(appdata_t *appda
603    
604    
605  #endif  #endif
606    
607    void *gps_register_callback(appdata_t *appdata, gps_cb cb, gpointer data) {
608      printf("gps: register gps callback\n");
609    
610      if(!appdata->gps_state)
611        return NULL;
612    
613      /* allocate callback info strcuture */
614      gps_cb_t *cb_info = g_new0(gps_cb_t, 1);
615      cb_info->cb = cb;
616      cb_info->data = data;
617    
618      /* and insert it into list of callbacks */
619      appdata->gps_state->cb = g_slist_append(appdata->gps_state->cb, cb_info);
620    
621      return cb_info;
622    }
623    
624    
625    void gps_unregister_callback(appdata_t *appdata, void *cb) {
626      printf("gps: unregister gps callback\n");
627    
628      if(!appdata->gps_state)
629        return;
630    
631      /* the item must be in the list */
632      g_assert(g_slist_find(appdata->gps_state->cb, cb));
633    
634      g_free(cb);
635      appdata->gps_state->cb = g_slist_remove(appdata->gps_state->cb, cb);
636    }
637    
638    static void gps_unregister_all(appdata_t *appdata) {
639      printf("gps: unregister all callbacks: ");
640    
641      while(appdata->gps_state->cb) {
642        printf(".");
643        g_free(appdata->gps_state->cb->data);
644        appdata->gps_state->cb = g_slist_remove(appdata->gps_state->cb,
645                                appdata->gps_state->cb->data);
646      }
647      printf("\n");
648    }

Legend:
Removed from v.14  
changed lines
  Added in v.233