Contents of /trunk/src/gps.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 233 - (hide annotations)
Wed Dec 9 19:45:36 2009 UTC (14 years, 5 months ago) by harbaum
File MIME type: text/plain
File size: 17531 byte(s)
File selection fremantleized
1 harbaum 1 /*
2     * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.
3     *
4     * This file is part of GPXView.
5     *
6     * GPXView is free software: you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * GPXView is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with GPXView. If not, see <http://www.gnu.org/licenses/>.
18     */
19    
20     #include <stdio.h>
21     #include <string.h>
22     #include <math.h>
23    
24     #include "gpxview.h"
25    
26    
27     #ifdef USE_MAEMO
28     #ifdef ENABLE_GPSBT
29     #include <gpsbt.h>
30     #include <gpsmgr.h>
31     #endif
32     #include <errno.h>
33     #endif
34    
35 harbaum 156 static void gps_unregister_all(appdata_t *appdata);
36    
37 harbaum 1 #ifndef ENABLE_LIBLOCATION
38    
39     /* maybe user configurable later on ... */
40     #define GPSD_HOST "127.0.0.1"
41     #define GPSD_PORT 2947
42    
43     gps_sat_t *gps_get_sats(appdata_t *appdata) {
44     gps_sat_t *retval = NULL;
45    
46     g_mutex_lock(appdata->gps_state->mutex);
47     if(appdata->gps_state->gpsdata.set & SATELLITE_SET) {
48     int i;
49     retval = malloc(sizeof(gps_sat_t));
50     retval->num = appdata->gps_state->gpsdata.satellites;
51    
52     retval->PRN = malloc(sizeof(int)*retval->num);
53     retval->used = malloc(sizeof(int)*retval->num);
54     retval->ss = malloc(sizeof(int)*retval->num);
55    
56     if(retval->num) {
57     for(i=0;i<retval->num;i++) {
58     retval->PRN[i] = appdata->gps_state->gpsdata.PRN[i];
59     retval->ss[i] = appdata->gps_state->gpsdata.ss[i];
60     retval->used[i] = appdata->gps_state->gpsdata.used[i];
61     }
62     }
63     }
64    
65     g_mutex_unlock(appdata->gps_state->mutex);
66    
67     return retval;
68     }
69    
70     pos_t *gps_get_pos(appdata_t *appdata) {
71     static pos_t retval;
72    
73     retval.lat = NAN;
74    
75     g_mutex_lock(appdata->gps_state->mutex);
76     if(appdata->gps_state->gpsdata.set & STATUS_SET)
77     if(appdata->gps_state->gpsdata.status != STATUS_NO_FIX)
78     if(appdata->gps_state->gpsdata.set & LATLON_SET)
79     retval = appdata->gps_state->gpsdata.fix.pos;
80    
81     g_mutex_unlock(appdata->gps_state->mutex);
82    
83     if(isnan(retval.lat))
84     return NULL;
85    
86     return &retval;
87     }
88    
89     float gps_get_heading(appdata_t *appdata) {
90     float retval = NAN;
91    
92     g_mutex_lock(appdata->gps_state->mutex);
93     if(appdata->gps_state->gpsdata.set & STATUS_SET)
94     if(appdata->gps_state->gpsdata.status != STATUS_NO_FIX)
95     if(appdata->gps_state->gpsdata.set & TRACK_SET)
96     retval = appdata->gps_state->gpsdata.fix.track;
97    
98     g_mutex_unlock(appdata->gps_state->mutex);
99     return retval;
100     }
101    
102 harbaum 53 float gps_get_eph(appdata_t *appdata) {
103 harbaum 1 float retval = NAN;
104    
105     g_mutex_lock(appdata->gps_state->mutex);
106     if(appdata->gps_state->gpsdata.set & STATUS_SET)
107     if(appdata->gps_state->gpsdata.status != STATUS_NO_FIX)
108     retval = appdata->gps_state->gpsdata.fix.eph;
109    
110     g_mutex_unlock(appdata->gps_state->mutex);
111     return retval;
112     }
113    
114     static int gps_connect(gps_state_t *gps_state) {
115     GnomeVFSResult vfs_result;
116     #ifdef USE_MAEMO
117     char errstr[256] = "";
118    
119 harbaum 160 if(!gps_state) {
120     printf("No gps state\n");
121     return -1;
122     }
123    
124 harbaum 1 /* We need to start gpsd (via gpsbt) first. */
125     memset(&gps_state->context, 0, sizeof(gpsbt_t));
126     errno = 0;
127    
128     if(gpsbt_start(NULL, 0, 0, 0, errstr, sizeof(errstr),
129     0, &gps_state->context) < 0) {
130 harbaum 156 printf("gps: Error connecting to GPS receiver: (%d) %s (%s)\n",
131 harbaum 1 errno, strerror(errno), errstr);
132     }
133     #endif
134    
135     /************** from here down pure gnome/gtk/gpsd ********************/
136    
137     /* try to connect to gpsd */
138     /* Create a socket to interact with GPSD. */
139    
140     int retries = 5;
141     while(retries &&
142     (GNOME_VFS_OK != (vfs_result = gnome_vfs_inet_connection_create(
143     &gps_state->iconn, GPSD_HOST, GPSD_PORT, NULL)))) {
144 harbaum 156 printf("gps: Error creating connection to GPSD, retrying ...\n");
145 harbaum 1
146     retries--;
147     sleep(1);
148     }
149    
150     if(!retries) {
151 harbaum 156 printf("gps: Finally failed ...\n");
152 harbaum 1 return -1;
153     }
154    
155     retries = 5;
156     while(retries && ((gps_state->socket =
157     gnome_vfs_inet_connection_to_socket(gps_state->iconn)) == NULL)) {
158 harbaum 156 printf("gps: Error creating connecting GPSD socket, retrying ...\n");
159 harbaum 1
160     retries--;
161     sleep(1);
162     }
163    
164     if(!retries) {
165 harbaum 156 printf("gps: Finally failed ...\n");
166 harbaum 1 return -1;
167     }
168    
169     GTimeVal timeout = { 10, 0 };
170     if(GNOME_VFS_OK != (vfs_result = gnome_vfs_socket_set_timeout(
171     gps_state->socket, &timeout, NULL))) {
172 harbaum 156 printf("gps: Error setting GPSD timeout\n");
173 harbaum 1 return -1;
174     }
175    
176 harbaum 156 printf("gps: GPSD connected ...\n");
177 harbaum 1
178     return 0;
179     }
180    
181     void gps_clear_fix(struct gps_fix_t *fixp) {
182     fixp->mode = MODE_NOT_SEEN;
183     fixp->pos.lat = fixp->pos.lon = NAN;
184     fixp->track = NAN;
185     fixp->eph = NAN;
186     }
187    
188     /* unpack a daemon response into a status structure */
189     static void gps_unpack(char *buf, struct gps_data_t *gpsdata) {
190     char *ns, *sp, *tp;
191    
192     for(ns = buf; ns; ns = strstr(ns+1, "GPSD")) {
193     if(strncmp(ns, "GPSD", 4) == 0) {
194     /* the following should execute each time we have a good next sp */
195     for (sp = ns + 5; *sp != '\0'; sp = tp+1) {
196     tp = sp + strcspn(sp, ",\r\n");
197     if (*tp == '\0') tp--;
198     else *tp = '\0';
199    
200     switch (*sp) {
201 harbaum 233 /* A - altitude is not supported */
202 harbaum 1 /* B - baudrate isn't supported by gpxview */
203     /* C - cycle isn't supported by gpxview */
204     /* D - utc time isn't supported by gpxview */
205     case 'E':
206 harbaum 53 gpsdata->fix.eph = NAN;
207 harbaum 1 /* epe should always be present if eph or epv is */
208     if (sp[2] != '?') {
209     char epe[20], eph[20], epv[20];
210     (void)sscanf(sp, "E=%s %s %s", epe, eph, epv);
211     #define DEFAULT(val) (val[0] == '?') ? NAN : g_ascii_strtod(val, NULL)
212     gpsdata->fix.eph = DEFAULT(eph);
213     #undef DEFAULT
214     }
215     break;
216     /* F - device name isn't supported by gpxview */
217     /* I - gps id isn't supported by gpxview */
218     /* K - known devices list isn't supported by gpxview */
219     case 'M':
220     if (sp[2] == '?') {
221     gpsdata->fix.mode = MODE_NOT_SEEN;
222     } else {
223     gpsdata->fix.mode = atoi(sp+2);
224     gpsdata->set |= MODE_SET;
225     }
226     break;
227     /* N - driver mode reporting isn't supported by gpxview */
228     case 'O':
229     if (sp[2] == '?') {
230     gpsdata->set =
231     (gpsdata->set & SATELLITE_SET) | // fix for below
232     MODE_SET | STATUS_SET; // this clears sat info??
233     gpsdata->status = STATUS_NO_FIX;
234     gps_clear_fix(&gpsdata->fix);
235     } else {
236     struct gps_fix_t nf;
237     char tag[MAXTAGLEN+1], alt[20];
238     char eph[20], epv[20], track[20],speed[20], climb[20];
239     char epd[20], eps[20], epc[20], mode[2];
240     char timestr[20], ept[20], lat[20], lon[20];
241     int st = sscanf(sp+2,
242     "%8s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %19s %1s",
243     tag, timestr, ept, lat, lon,
244     alt, eph, epv, track, speed, climb,
245     epd, eps, epc, mode);
246     if (st >= 14) {
247     #define DEFAULT(val) (val[0] == '?') ? NAN : g_ascii_strtod(val, NULL)
248     nf.pos.lat = DEFAULT(lat);
249     nf.pos.lon = DEFAULT(lon);
250     nf.eph = DEFAULT(eph);
251     nf.track = DEFAULT(track);
252     #undef DEFAULT
253     if (st >= 15)
254     nf.mode = (mode[0] == '?') ? MODE_NOT_SEEN : atoi(mode);
255     else
256     nf.mode = (alt[0] == '?') ? MODE_2D : MODE_3D;
257     if (isnan(nf.eph)==0)
258     gpsdata->set |= HERR_SET;
259     if (isnan(nf.track)==0)
260 harbaum 233 gpsdata->set |= TRACK_SET;
261 harbaum 1 gpsdata->fix = nf;
262 harbaum 233 gpsdata->set |= LATLON_SET|MODE_SET;
263 harbaum 1 gpsdata->status = STATUS_FIX;
264     gpsdata->set |= STATUS_SET;
265     }
266     }
267     break;
268     case 'P':
269     if (sp[2] == '?') {
270     gpsdata->fix.pos.lat = NAN;
271     gpsdata->fix.pos.lon = NAN;
272     } else {
273     char lat[20], lon[20];
274     (void)sscanf(sp, "P=%19s %19s", lat, lon);
275     gpsdata->fix.pos.lat = g_ascii_strtod(lat, NULL);
276     gpsdata->fix.pos.lon = g_ascii_strtod(lon, NULL);
277     gpsdata->set |= LATLON_SET;
278     }
279     break;
280 harbaum 233 /* Q is not supported */
281 harbaum 1 case 'S':
282     if (sp[2] == '?') {
283     gpsdata->status = -1;
284     } else {
285     gpsdata->status = atoi(sp+2);
286     gpsdata->set |= STATUS_SET;
287     }
288     break;
289     case 'T':
290     if (sp[2] == '?') {
291     gpsdata->fix.track = NAN;
292     } else {
293 harbaum 233 (void)sscanf(sp, "T=%f", &gpsdata->fix.track);
294 harbaum 1 gpsdata->set |= TRACK_SET;
295     }
296     break;
297 harbaum 233 /* U - climb is not supported */
298     /* V - is not supported */
299     /* X - online is not supported */
300 harbaum 1 case 'Y':
301     if (sp[2] == '?') {
302     gpsdata->satellites = 0;
303     } else {
304     int j, i1, i2, i3, i4, i5;
305     int PRN[MAXCHANNELS];
306     int elevation[MAXCHANNELS], azimuth[MAXCHANNELS];
307     int ss[MAXCHANNELS], used[MAXCHANNELS];
308     char tag[MAXTAGLEN+1], timestamp[21];
309    
310     (void)sscanf(sp, "Y=%8s %20s %d ",
311     tag, timestamp, &gpsdata->satellites);
312     for (j = 0; j < gpsdata->satellites; j++) {
313     PRN[j]=elevation[j]=azimuth[j]=ss[j]=used[j]=0;
314     }
315 harbaum 156 // printf("gps: sats = %d\n", gpsdata->satellites);
316 harbaum 1 for (j = 0, gpsdata->satellites_used = 0; j < gpsdata->satellites; j++) {
317     if ((sp != NULL) && ((sp = strchr(sp, ':')) != NULL)) {
318     sp++;
319     (void)sscanf(sp, "%d %d %d %d %d", &i1, &i2, &i3, &i4, &i5);
320     PRN[j] = i1;
321     elevation[j] = i2; azimuth[j] = i3;
322     ss[j] = i4; used[j] = i5;
323     if (i5 == 1)
324     gpsdata->satellites_used++;
325     }
326     }
327     memcpy(gpsdata->PRN, PRN, sizeof(PRN));
328     memcpy(gpsdata->elevation, elevation, sizeof(elevation));
329     memcpy(gpsdata->azimuth, azimuth,sizeof(azimuth));
330     memcpy(gpsdata->ss, ss, sizeof(ss));
331     memcpy(gpsdata->used, used, sizeof(used));
332     /*@ +compdef @*/
333     }
334     gpsdata->set |= SATELLITE_SET;
335     break;
336     /* Z and $ - profiling isn't supported by gpxview */
337     }
338     }
339     }
340     }
341     }
342    
343 harbaum 156 /* 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 harbaum 193 // printf("gps: idle callback, calling app callbacks\n");
354 harbaum 156
355     g_slist_foreach(appdata->gps_state->cb, do_app_cb, appdata);
356    
357     return FALSE;
358     }
359    
360 harbaum 1 gpointer gps_thread(gpointer data) {
361     GnomeVFSFileSize bytes_read;
362     GnomeVFSResult vfs_result;
363     char str[512];
364     appdata_t *appdata = (appdata_t*)data;
365     int cnt=1000;
366    
367     const char *msg_pos = "o\r\n"; /* pos request */
368     const char *msg_sat = "y\r\n"; /* sat request */
369    
370     appdata->gps_state->gpsdata.set = 0;
371    
372     gboolean connected = FALSE;
373    
374     while(1) {
375     if(appdata->use_gps) {
376     if(!connected) {
377 harbaum 156 printf("gps: trying to connect\n");
378 harbaum 1
379     if(gps_connect(appdata->gps_state) < 0)
380     sleep(10);
381     else
382     connected = TRUE;
383     } else {
384     const char *msg;
385     if(!cnt) msg = msg_sat;
386     else msg = msg_pos;
387    
388     if(GNOME_VFS_OK ==
389     (vfs_result = gnome_vfs_socket_write(appdata->gps_state->socket,
390     msg, strlen(msg)+1, &bytes_read, NULL))) {
391    
392     /* update every second, wait here to make sure a complete */
393     /* reply is received */
394     if(cnt <= 1) usleep(500000);
395     else sleep(1);
396    
397     if(bytes_read == (strlen(msg)+1)) {
398     vfs_result = gnome_vfs_socket_read(appdata->gps_state->socket,
399     str, sizeof(str)-1, &bytes_read, NULL);
400     if(vfs_result == GNOME_VFS_OK) {
401     str[bytes_read] = 0;
402    
403 harbaum 156 // printf("gps: msg: %s (%d)\n", str, strlen(str));
404 harbaum 1
405     g_mutex_lock(appdata->gps_state->mutex);
406    
407     if(!cnt) appdata->gps_state->gpsdata.set &= ~SATELLITE_SET;
408     else appdata->gps_state->gpsdata.set &=
409 harbaum 233 ~(LATLON_SET|MODE_SET|STATUS_SET);
410 harbaum 1
411     gps_unpack(str, &appdata->gps_state->gpsdata);
412     g_mutex_unlock(appdata->gps_state->mutex);
413 harbaum 156 g_idle_add(gps_idle_cb, appdata);
414 harbaum 1 }
415     }
416     }
417     if(cnt++ >= 5) cnt = 0;
418     }
419     } else {
420     if(connected) {
421 harbaum 156 printf("gps: stopping GPS connection due to user request\n");
422 harbaum 1 gnome_vfs_inet_connection_destroy(appdata->gps_state->iconn, NULL);
423    
424     #ifdef USE_MAEMO
425     gpsbt_stop(&appdata->gps_state->context);
426     #endif
427     connected = FALSE;
428     } else
429     sleep(1);
430     }
431     }
432    
433 harbaum 156 printf("gps: thread ended???\n");
434 harbaum 1 return NULL;
435     }
436    
437     void gps_init(appdata_t *appdata) {
438 harbaum 8 appdata->gps_state = g_new0(gps_state_t, 1);
439 harbaum 1
440     /* start a new thread to listen to gpsd */
441     appdata->gps_state->mutex = g_mutex_new();
442     appdata->gps_state->thread_p =
443     g_thread_create(gps_thread, appdata, FALSE, NULL);
444     }
445    
446     void gps_release(appdata_t *appdata) {
447 harbaum 156 gps_unregister_all(appdata);
448 harbaum 1 #ifdef USE_MAEMO
449     gpsbt_stop(&appdata->gps_state->context);
450     #endif
451 harbaum 8 g_free(appdata->gps_state);
452 harbaum 1 }
453    
454     #else
455    
456     static void
457     location_changed(LocationGPSDevice *device, gps_state_t *gps_state) {
458    
459 harbaum 8 gps_state->fields = device->fix->fields;
460    
461     if(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET) {
462 harbaum 233 gps_state->fix.pos.lat = device->fix->latitude;
463     gps_state->fix.pos.lon = device->fix->longitude;
464     gps_state->fix.eph = device->fix->eph/100.0; // we want eph in meters
465 harbaum 8 }
466 harbaum 7
467 harbaum 8 if(gps_state->fields & LOCATION_GPS_DEVICE_TRACK_SET)
468 harbaum 233 gps_state->fix.track = device->fix->track;
469 harbaum 8
470     /* update list of sattelites */
471 harbaum 7
472 harbaum 8 /* free old list */
473     if(gps_state->sats.num) {
474     g_free(gps_state->sats.PRN);
475     g_free(gps_state->sats.used);
476     g_free(gps_state->sats.ss);
477     gps_state->sats.num = 0;
478 harbaum 1 }
479 harbaum 8
480     /* build new one */
481     if(device->satellites_in_view) {
482     gps_state->sats.PRN = g_new0(int, device->satellites_in_view);
483     gps_state->sats.used = g_new0(int, device->satellites_in_view);
484     gps_state->sats.ss = g_new0(int, device->satellites_in_view);
485    
486     int i;
487     for(i=0;i<device->satellites_in_view;i++) {
488     LocationGPSDeviceSatellite *sat =
489     g_ptr_array_index(device->satellites, i);
490    
491     gps_state->sats.PRN[i] = sat->prn;
492     gps_state->sats.used[i] = sat->in_use;
493     gps_state->sats.ss[i] = sat->signal_strength;
494     }
495    
496     gps_state->sats.num = device->satellites_in_view;
497     }
498 harbaum 1 }
499    
500     void gps_init(appdata_t *appdata) {
501     gps_state_t *gps_state = appdata->gps_state = g_new0(gps_state_t, 1);
502    
503 harbaum 156 printf("gps: init: Using liblocation\n");
504 harbaum 1
505     gps_state->device = g_object_new(LOCATION_TYPE_GPS_DEVICE, NULL);
506     if(!gps_state->device) {
507 harbaum 156 printf("gps: Unable to connect to liblocation\n");
508 harbaum 1 return;
509     }
510    
511     gps_state->idd_changed =
512     g_signal_connect(gps_state->device, "changed",
513     G_CALLBACK(location_changed), gps_state);
514    
515 harbaum 11 gps_state->control = location_gpsd_control_get_default();
516    
517 harbaum 36 if(gps_state->control
518     #if MAEMO_VERSION_MAJOR < 5
519     && gps_state->control->can_control
520     #endif
521     ) {
522    
523 harbaum 156 printf("gps: Having control over GPSD and GPS is to be enabled, starting it\n");
524 harbaum 11 location_gpsd_control_start(gps_state->control);
525     }
526 harbaum 1 }
527    
528     void gps_release(appdata_t *appdata) {
529     gps_state_t *gps_state = appdata->gps_state;
530 harbaum 156 gps_unregister_all(appdata);
531 harbaum 1
532     if(!gps_state->device) return;
533 harbaum 11
534 harbaum 36 if(gps_state->control
535 harbaum 11 #if MAEMO_VERSION_MAJOR < 5
536 harbaum 36 && gps_state->control->can_control
537     #endif
538     ) {
539 harbaum 156 printf("gps: Having control over GPSD, stopping it\n");
540 harbaum 11 location_gpsd_control_stop(gps_state->control);
541     }
542 harbaum 1
543     /* Disconnect signal */
544     g_signal_handler_disconnect(gps_state->device, gps_state->idd_changed);
545    
546     g_free(appdata->gps_state);
547     appdata->gps_state = NULL;
548     }
549    
550     pos_t *gps_get_pos(appdata_t *appdata) {
551     static pos_t pos;
552    
553     if(!appdata->use_gps)
554     return NULL;
555    
556     gps_state_t *gps_state = appdata->gps_state;
557    
558 harbaum 8 if(!(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET))
559 harbaum 1 return NULL;
560    
561 harbaum 233 pos.lat = gps_state->fix.pos.lat;
562     pos.lon = gps_state->fix.pos.lon;
563 harbaum 1
564     return &pos;
565     }
566    
567 harbaum 7 float gps_get_heading(appdata_t *appdata) {
568     gps_state_t *gps_state = appdata->gps_state;
569    
570 harbaum 8 if(!(gps_state->fields & LOCATION_GPS_DEVICE_TRACK_SET))
571 harbaum 7 return NAN;
572 harbaum 1
573 harbaum 233 return gps_state->fix.track;
574 harbaum 7 }
575 harbaum 1
576 harbaum 53 float gps_get_eph(appdata_t *appdata) {
577 harbaum 7 gps_state_t *gps_state = appdata->gps_state;
578    
579 harbaum 8 if(!(gps_state->fields & LOCATION_GPS_DEVICE_LATLONG_SET))
580 harbaum 7 return NAN;
581    
582 harbaum 233 return gps_state->fix.eph;
583 harbaum 7 }
584    
585 harbaum 8 gps_sat_t *gps_get_sats(appdata_t *appdata) {
586     gps_sat_t *retval = NULL;
587     gps_state_t *gps_state = appdata->gps_state;
588 harbaum 1
589 harbaum 8 if(gps_state->sats.num) {
590     retval = g_new0(gps_sat_t, 1);
591     retval->num = gps_state->sats.num;
592    
593     retval->PRN = g_memdup(gps_state->sats.PRN,
594     sizeof(int)*gps_state->sats.num);
595     retval->used = g_memdup(gps_state->sats.used,
596     sizeof(int)*gps_state->sats.num);
597     retval->ss = g_memdup(gps_state->sats.ss,
598     sizeof(int)*gps_state->sats.num);
599     }
600 harbaum 1
601 harbaum 8 return retval;
602     }
603    
604    
605 harbaum 1 #endif
606 harbaum 149
607     void *gps_register_callback(appdata_t *appdata, gps_cb cb, gpointer data) {
608 harbaum 156 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 harbaum 149 }
623    
624    
625     void gps_unregister_callback(appdata_t *appdata, void *cb) {
626 harbaum 156 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 harbaum 149 }
637 harbaum 156
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     }