734d1d125344b9336d6f865abd22946949c1a61e
[framework/location/libslp-location.git] / location / manager / location-sps.c
1 /*
2  * libslp-location
3  *
4  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
7  *          Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "location-setting.h"
27 #include "location-log.h"
28
29 #include "module-internal.h"
30
31 #include "location-sps.h"
32 #include "location-marshal.h"
33 #include "location-ielement.h"
34 #include "location-signaling-util.h"
35 #include "location-common-util.h"
36
37 typedef struct _LocationSpsPrivate {
38         LocationSpsMod* mod;
39         gboolean is_started;
40         gboolean set_noti;
41         gboolean enabled;
42         guint    interval;
43         LocationPosition *pos;
44         LocationVelocity *vel;
45         LocationAccuracy *acc;
46         GList *boundary_list;
47         ZoneStatus zone_status;
48         LocationPosition *pos_base;
49         LocationVelocity *vel_base;
50         LocationAccuracy *acc_info;
51         LocationSatellite *sat_info;
52 } LocationSpsPrivate;
53
54 enum {
55         PROP_0,
56         PROP_METHOD_TYPE,
57         PROP_LAST_POSITION,
58         PROP_UPDATE_INTERVAL,
59         PROP_BOUNDARY,
60         PROP_REMOVAL_BOUNDARY,
61         PROP_POSITION_BASE,
62         PROP_VELOCITY_BASE,
63         PROP_ACCURACY_INFO,
64         PROP_SATELLITE_INFO,
65         PROP_MAX
66 };
67
68 static guint32 signals[LAST_SIGNAL] = {0, };
69 static GParamSpec *properties[PROP_MAX] = {NULL, };
70
71 #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOCATION_TYPE_SPS, LocationSpsPrivate))
72
73 static void location_ielement_interface_init (LocationIElementInterface *iface);
74
75 G_DEFINE_TYPE_WITH_CODE (LocationSps, location_sps, G_TYPE_OBJECT,
76                          G_IMPLEMENT_INTERFACE (LOCATION_TYPE_IELEMENT,
77                          location_ielement_interface_init));
78
79 static void
80 sps_status_cb (gboolean enabled,
81         LocationStatus status,
82         gpointer self)
83 {
84         LOCATION_LOGD("sps_status_cb");
85         g_return_if_fail(self);
86         LocationSpsPrivate* priv = GET_PRIVATE(self);
87         enable_signaling(self, signals, &(priv->enabled), enabled, status);
88 }
89
90 static void
91 sps_position_cb (gboolean enabled,
92         LocationPosition *pos,
93         LocationAccuracy *acc,
94         gpointer self)
95 {
96         LOCATION_LOGD("sps_position_cb");
97         g_return_if_fail(self);
98         g_return_if_fail(pos);
99         g_return_if_fail(acc);
100         LocationSpsPrivate* priv = GET_PRIVATE(self);
101         enable_signaling(self, signals, &(priv->enabled), enabled, pos->status);
102
103         position_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->pos), &(priv->acc), priv->boundary_list, &(priv->zone_status), enabled, pos, acc);
104 }
105
106 static void
107 sps_velocity_cb (gboolean enabled,
108         LocationVelocity *vel,
109         LocationAccuracy *acc,
110         gpointer self)
111 {
112         LOCATION_LOGD("sps_velocity_cb");
113         g_return_if_fail(self);
114         LocationSpsPrivate* priv = GET_PRIVATE(self);
115         velocity_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->vel), enabled, vel, acc);
116 }
117
118 static void
119 location_setting_sps_cb(keynode_t *key,
120         gpointer self)
121 {
122         LOCATION_LOGD("location_setting_sps_cb");
123         g_return_if_fail(key);
124         g_return_if_fail(self);
125         LocationSpsPrivate* priv = GET_PRIVATE(self);
126         g_return_if_fail (priv->mod);
127         g_return_if_fail (priv->mod->handler);
128
129         int ret = LOCATION_ERROR_NONE;
130
131         if (location_setting_get_key_val(key) == 0) {
132                 if (priv->mod->ops.stop && priv->is_started) {
133                         ret = priv->mod->ops.stop(priv->mod->handler);
134                         if (ret == LOCATION_ERROR_NONE) priv->is_started = FALSE;
135                 }
136         }
137         else {
138                 if (location_setting_get_int(SENSOR_ENABLED) &&
139                                 priv->mod->ops.start && !priv->is_started) {
140                         LOCATION_LOGD("location resumed by setting");
141                         ret = priv->mod->ops.start (priv->mod->handler, sps_status_cb, sps_position_cb, sps_velocity_cb, self);
142                         if (ret == LOCATION_ERROR_NONE) priv->is_started = TRUE;
143                 }
144         }
145
146 }
147
148 static int
149 location_sps_start (LocationSps *self)
150 {
151         LOCATION_LOGD("location_sps_start");
152         LocationSpsPrivate* priv = GET_PRIVATE(self);
153         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
154         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
155         g_return_val_if_fail (priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE);
156         g_return_val_if_fail (priv->mod->ops.update_data, LOCATION_ERROR_NOT_AVAILABLE);
157
158         if( priv->is_started == TRUE) return LOCATION_ERROR_NONE;
159
160         int ret = LOCATION_ERROR_NONE;
161         int noti_err = 0;
162
163         if (!location_setting_get_int(GPS_ENABLED) || !location_setting_get_int(SENSOR_ENABLED)) {
164                 ret = LOCATION_ERROR_NOT_ALLOWED;
165         }
166         else {
167                 ret = priv->mod->ops.start(priv->mod->handler, sps_status_cb, sps_position_cb, sps_velocity_cb, self);
168                 if (ret == LOCATION_ERROR_NONE) {
169                         priv->is_started = TRUE;
170                 }
171                 else {
172                         return ret;
173                 }
174
175                 priv->mod->ops.update_data(priv->mod->handler, priv->pos_base, priv->vel_base, priv->acc_info, priv->sat_info);
176         }
177
178         if (priv->set_noti == FALSE) {
179                 noti_err = location_setting_add_notify (GPS_ENABLED, location_setting_sps_cb, self);
180                 if (noti_err != 0) {
181                         return LOCATION_ERROR_UNKNOWN;
182                 }
183                 noti_err = location_setting_add_notify (SENSOR_ENABLED, location_setting_sps_cb, self);
184                 if (noti_err != 0) {
185                         return LOCATION_ERROR_UNKNOWN;
186                 }
187                 priv->set_noti = TRUE;
188         }
189
190         return ret;
191 }
192
193 static int
194 location_sps_stop (LocationSps *self)
195 {
196         LOCATION_LOGD("location_sps_stop");
197         LocationSpsPrivate* priv = GET_PRIVATE(self);
198         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
199         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
200         g_return_val_if_fail (priv->mod->ops.stop, LOCATION_ERROR_NOT_AVAILABLE);
201
202         int ret = LOCATION_ERROR_NONE;
203         int noti_err = 0;
204
205         if (priv->is_started == TRUE) {
206                 ret = priv->mod->ops.stop (priv->mod->handler);
207                 if (ret == LOCATION_ERROR_NONE) {
208                         priv->is_started = FALSE;
209                 }
210                 else {
211                         return ret;
212                 }
213         }
214
215         if (priv->set_noti == TRUE) {
216                 noti_err = location_setting_ignore_notify (GPS_ENABLED, location_setting_sps_cb);
217                 if (noti_err != 0) {
218                         return LOCATION_ERROR_UNKNOWN;
219                 }
220                 noti_err = location_setting_ignore_notify (SENSOR_ENABLED, location_setting_sps_cb);
221                 if (noti_err != 0) {
222                         return LOCATION_ERROR_UNKNOWN;
223                 }
224                 priv->set_noti = FALSE;
225         }
226
227         return ret;
228 }
229
230 static void
231 location_sps_dispose (GObject *gobject)
232 {
233         LOCATION_LOGD("location_sps_dispose");
234         G_OBJECT_CLASS (location_sps_parent_class)->dispose (gobject);
235 }
236
237 static void
238 location_sps_finalize (GObject *gobject)
239 {
240         LOCATION_LOGD("location_sps_finalize");
241         LocationSpsPrivate* priv = GET_PRIVATE(gobject);
242         module_free(priv->mod, "sps");
243         priv->mod = NULL;
244         G_OBJECT_CLASS (location_sps_parent_class)->finalize (gobject);
245 }
246
247 static void
248 location_sps_set_property (GObject *object,
249         guint property_id,
250         const GValue *value,
251         GParamSpec *pspec)
252 {
253         LocationSpsPrivate* priv = GET_PRIVATE(object);
254
255         g_return_if_fail (priv->mod);
256         g_return_if_fail (priv->mod->handler);
257         LocModSpsOps ops = priv->mod->ops;
258         g_return_if_fail (ops.update_data);
259
260         int ret = 0;
261         switch (property_id){
262                 case PROP_BOUNDARY:{
263                         GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value));
264                         ret = set_prop_boundary(&priv->boundary_list, boundary_list);
265                         if(ret != 0) LOCATION_LOGD("Set boundary. Error[%d]", ret);
266          break;
267                 }
268                 case PROP_REMOVAL_BOUNDARY: {
269                         LocationBoundary *req_boundary = (LocationBoundary*) g_value_dup_boxed(value);
270                         ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary);
271                         if(ret != 0) LOCATION_LOGD("Removal boundary. Error[%d]", ret);
272                         break;
273                 }
274                 case PROP_POSITION_BASE:{
275                         if(priv->pos_base) location_position_free(priv->pos_base);
276                         priv->pos_base = (LocationPosition*) g_value_dup_boxed (value);
277                         LOCATION_LOGD("Set prop>> base position: \t%lf, %lf, %lf, time: %d", priv->pos_base->latitude, priv->pos_base->longitude, priv->pos_base->altitude, priv->pos_base->timestamp);
278                         if (priv->is_started) ops.update_data (priv->mod->handler, priv->pos_base, priv->vel_base, priv->acc_info, priv->sat_info);
279                         break;
280                 }
281                 case PROP_VELOCITY_BASE:{
282                         if(priv->vel_base) location_velocity_free(priv->vel_base);
283                         priv->vel_base = (LocationVelocity*) g_value_dup_boxed (value);
284                         LOCATION_LOGD("Set prop>> base velocity: \t%lf, %lf, %lf, time: %d", priv->vel_base->speed, priv->vel_base->direction, priv->vel_base->climb, priv->vel_base->timestamp);
285                         if(priv->is_started) ops.update_data (priv->mod->handler, priv->pos_base, priv->vel_base, priv->acc_info, priv->sat_info);
286                         break;
287                 }
288                 case PROP_ACCURACY_INFO:{
289                         if(priv->acc_info) location_accuracy_free(priv->acc_info);
290                         priv->acc_info = (LocationAccuracy*) g_value_dup_boxed (value);
291                         LOCATION_LOGD("Set prop>> accuracy information: \t%d, %lf, %lf", priv->acc_info->level, priv->acc_info->horizontal_accuracy, priv->acc_info->vertical_accuracy);
292                         if(priv->is_started) ops.update_data (priv->mod->handler, priv->pos_base, priv->vel_base, priv->acc_info, priv->sat_info);
293                         break;
294                 }
295                 case PROP_SATELLITE_INFO:{
296                         if(priv->sat_info) location_satellite_free(priv->sat_info);
297                         priv->sat_info = (LocationSatellite*) g_value_dup_boxed (value);
298                         LOCATION_LOGD("Set prop>> satellite information: \tNofView:%d, NofUsed:%d", priv->sat_info->num_of_sat_inview, priv->sat_info->num_of_sat_used);
299                         if(priv->is_started) ops.update_data (priv->mod->handler, priv->pos_base, priv->vel_base, priv->acc_info, priv->sat_info);
300                         break;
301                 }
302                 case PROP_UPDATE_INTERVAL: {
303                         guint interval = g_value_get_uint(value);
304                         if(interval > 0) {
305                                 if(interval < LOCATION_UPDATE_INTERVAL_MAX)
306                                         priv->interval = interval;
307                                 else
308                                         priv->interval = (guint)LOCATION_UPDATE_INTERVAL_MAX;
309
310                         }
311                         else
312                                 priv->interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT;
313                         break;
314                 }
315                 default:
316                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
317                         break;
318         }
319 }
320
321 static void
322 location_sps_get_property (GObject *object,
323                            guint property_id,
324                            GValue *value,
325                            GParamSpec *pspec)
326 {
327         LocationSpsPrivate *priv = GET_PRIVATE (object);
328
329         switch (property_id){
330                 case PROP_METHOD_TYPE:
331                         g_value_set_int(value, LOCATION_METHOD_SPS);
332                         break;
333                 case PROP_LAST_POSITION:
334                         g_value_set_boxed (value, priv->pos);
335                         break;
336                 case PROP_BOUNDARY:
337                         g_value_set_pointer(value, g_list_first(priv->boundary_list));
338                         break;
339                 case PROP_POSITION_BASE:
340                         g_value_set_boxed (value, priv->pos_base);
341                         break;
342                 case PROP_VELOCITY_BASE:
343                         g_value_set_boxed (value, priv->vel_base);
344                         break;
345                 case PROP_ACCURACY_INFO:
346                         g_value_set_boxed (value, priv->acc_info);
347                         break;
348                 case PROP_SATELLITE_INFO:
349                         g_value_set_boxed (value, priv->sat_info);
350                         break;
351                 case PROP_UPDATE_INTERVAL:
352                         g_value_set_uint(value, priv->interval);
353                         break;
354                 default:
355                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
356                         break;
357         }
358 }
359
360 static int
361 location_sps_get_position (LocationSps *self,
362         LocationPosition **position,
363         LocationAccuracy **accuracy)
364 {
365         LOCATION_LOGD("location_sps_get_position");
366
367         LocationSpsPrivate *priv = GET_PRIVATE (self);
368         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
369         setting_retval_if_fail(GPS_ENABLED);
370         setting_retval_if_fail(SENSOR_ENABLED);
371
372         LocModSpsOps ops = priv->mod->ops;
373         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
374         g_return_val_if_fail (ops.get_position, LOCATION_ERROR_NOT_AVAILABLE);
375         return ops.get_position(priv->mod->handler, position, accuracy);
376 }
377
378 static int
379 location_sps_get_last_position (LocationSps *self,
380         LocationPosition **position,
381         LocationAccuracy **accuracy)
382 {
383         LOCATION_LOGD("location_sps_get_last_position");
384         return LOCATION_ERROR_NOT_SUPPORTED;
385 }
386
387 static int
388 location_sps_get_velocity (LocationSps *self,
389         LocationVelocity **velocity,
390         LocationAccuracy **accuracy)
391 {
392         LOCATION_LOGD("location_sps_get_velocity");
393
394         LocationSpsPrivate *priv = GET_PRIVATE (self);
395         g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
396         setting_retval_if_fail(GPS_ENABLED);
397         setting_retval_if_fail(SENSOR_ENABLED);
398
399         LocModSpsOps ops = priv->mod->ops;
400         g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
401         g_return_val_if_fail (ops.get_velocity, LOCATION_ERROR_NOT_AVAILABLE);
402         return ops.get_velocity(priv->mod->handler, velocity, accuracy);
403 }
404
405 static int
406 location_sps_get_last_velocity (LocationSps *self,
407         LocationVelocity **velocity,
408         LocationAccuracy **accuracy)
409 {
410         LOCATION_LOGD("location_sps_get_last_velocity");
411         return LOCATION_ERROR_NOT_SUPPORTED;
412 }
413
414 static int
415 location_sps_get_satellite (LocationSps *self,
416         LocationSatellite **satellite)
417 {
418         LOCATION_LOGD("location_sps_get_satellite");
419         return LOCATION_ERROR_NOT_SUPPORTED;
420 }
421
422 static int
423 location_sps_get_last_satellite (LocationSps *self,
424         LocationSatellite **satellite)
425 {
426         LOCATION_LOGD("location_sps_get_last_satellite");
427         return LOCATION_ERROR_NOT_SUPPORTED;
428 }
429
430 static void
431 location_ielement_interface_init (LocationIElementInterface *iface)
432 {
433         iface->start = (TYPE_START_FUNC)location_sps_start;
434         iface->stop = (TYPE_STOP_FUNC)location_sps_stop;
435         iface->get_position = (TYPE_GET_POSITION)location_sps_get_position;
436         iface->get_last_position = (TYPE_GET_POSITION)location_sps_get_last_position;
437         iface->get_velocity = (TYPE_GET_VELOCITY)location_sps_get_velocity;
438         iface->get_last_velocity = (TYPE_GET_VELOCITY)location_sps_get_last_velocity;
439         iface->get_satellite = (TYPE_GET_SATELLITE)location_sps_get_satellite;
440         iface->get_last_satellite = (TYPE_GET_SATELLITE)location_sps_get_last_satellite;
441 }
442
443 static void
444 location_sps_init (LocationSps *self)
445 {
446         LOCATION_LOGD("location_sps_init");
447         LocationSpsPrivate* priv = GET_PRIVATE(self);
448
449         priv->mod = (LocationSpsMod*)module_new("sps");
450         if(!priv->mod)
451                 LOCATION_LOGW("module loading failed");
452
453         priv->is_started = FALSE;
454         priv->enabled= FALSE;
455         priv->interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
456         priv->pos = NULL;
457         priv->vel = NULL;
458         priv->acc = NULL;
459         priv->zone_status = ZONE_STATUS_NONE;
460         priv->boundary_list = NULL;
461
462         priv->pos_base = NULL;
463         priv->vel_base = NULL;
464         priv->acc_info = NULL;
465         priv->sat_info = NULL;
466 }
467
468 static void
469 location_sps_class_init (LocationSpsClass *klass)
470 {
471         LOCATION_LOGD("location_sps_class_init");
472         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
473
474         gobject_class->set_property = location_sps_set_property;
475         gobject_class->get_property = location_sps_get_property;
476
477         gobject_class->dispose = location_sps_dispose;
478         gobject_class->finalize = location_sps_finalize;
479
480         g_type_class_add_private (klass, sizeof (LocationSpsPrivate));
481
482         signals[SERVICE_ENABLED] = g_signal_new ("service-enabled",
483                         G_TYPE_FROM_CLASS (klass),
484                         G_SIGNAL_RUN_FIRST |
485                         G_SIGNAL_NO_RECURSE,
486                         G_STRUCT_OFFSET (LocationSpsClass, enabled),
487                         NULL, NULL,
488                         location_VOID__UINT,
489                         G_TYPE_NONE, 1,
490                         G_TYPE_UINT);
491
492         signals[SERVICE_DISABLED] = g_signal_new ("service-disabled",
493                         G_TYPE_FROM_CLASS (klass),
494                         G_SIGNAL_RUN_FIRST |
495                         G_SIGNAL_NO_RECURSE,
496                         G_STRUCT_OFFSET (LocationSpsClass, disabled),
497                         NULL, NULL,
498                         location_VOID__UINT,
499                         G_TYPE_NONE, 1,
500                         G_TYPE_UINT);
501
502         signals[SERVICE_UPDATED] = g_signal_new ("service-updated",
503                         G_TYPE_FROM_CLASS (klass),
504                         G_SIGNAL_RUN_FIRST |
505                         G_SIGNAL_NO_RECURSE,
506                         G_STRUCT_OFFSET (LocationSpsClass, updated),
507                         NULL, NULL,
508                         location_VOID__UINT_POINTER_POINTER,
509                         G_TYPE_NONE, 3,
510                         G_TYPE_UINT,
511                         G_TYPE_POINTER,
512                         G_TYPE_POINTER);
513
514         signals[ZONE_IN] = g_signal_new ("zone-in",
515                         G_TYPE_FROM_CLASS (klass),
516                         G_SIGNAL_RUN_FIRST |
517                         G_SIGNAL_NO_RECURSE,
518                         G_STRUCT_OFFSET (LocationSpsClass, zone_in),
519                         NULL, NULL,
520                         location_VOID__UINT_POINTER_POINTER,
521                         G_TYPE_NONE, 3,
522                         G_TYPE_UINT,
523                         G_TYPE_POINTER,
524                         G_TYPE_POINTER);
525
526         signals[ZONE_OUT] = g_signal_new ("zone-out",
527                         G_TYPE_FROM_CLASS (klass),
528                         G_SIGNAL_RUN_FIRST |
529                         G_SIGNAL_NO_RECURSE,
530                         G_STRUCT_OFFSET (LocationSpsClass, zone_out),
531                         NULL, NULL,
532                         location_VOID__UINT_POINTER_POINTER,
533                         G_TYPE_NONE, 3,
534                         G_TYPE_UINT,
535                         G_TYPE_POINTER,
536                         G_TYPE_POINTER);
537
538         properties[PROP_METHOD_TYPE]  = g_param_spec_int ("method",
539                         "method type",
540                         "location method type name",
541                         LOCATION_METHOD_SPS,
542                         LOCATION_METHOD_SPS,
543                         LOCATION_METHOD_SPS,
544                         G_PARAM_READABLE);
545
546         properties[PROP_LAST_POSITION] = g_param_spec_boxed ("last-position",
547                         "sps last position prop",
548                         "sps last position data",
549                         LOCATION_TYPE_POSITION,
550                         G_PARAM_READABLE);
551
552         properties[PROP_UPDATE_INTERVAL] = g_param_spec_uint ("update-interval",
553                         "sps update interval prop",
554                         "sps update interval data",
555                         LOCATION_UPDATE_INTERVAL_MIN,
556                         LOCATION_UPDATE_INTERVAL_MAX,
557                         LOCATION_UPDATE_INTERVAL_DEFAULT,
558                         G_PARAM_READWRITE);
559
560         properties[PROP_BOUNDARY] = g_param_spec_pointer ("boundary",
561                         "sps boundary prop",
562                         "sps boundary data",
563                         G_PARAM_READWRITE);
564
565         properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary",
566                         "sps removal boundary prop",
567                         "sps removal boundary data",
568                         LOCATION_TYPE_BOUNDARY,
569                         G_PARAM_READWRITE);
570
571         properties[PROP_POSITION_BASE] = g_param_spec_boxed ("position-base",
572                         "sps position base prop",
573                         "sps position base data",
574                         LOCATION_TYPE_POSITION,
575                         G_PARAM_READWRITE);
576
577         properties[PROP_VELOCITY_BASE] = g_param_spec_boxed ("velocity-base",
578                         "sps velocity base prop",
579                         "sps velocity base data",
580                         LOCATION_TYPE_VELOCITY,
581                         G_PARAM_READWRITE);
582
583         properties[PROP_ACCURACY_INFO] = g_param_spec_boxed ("accuracy-info",
584                         "sps accuracy information prop",
585                         "sps accuracy information data",
586                         LOCATION_TYPE_ACCURACY,
587                         G_PARAM_READWRITE);
588
589         properties[PROP_SATELLITE_INFO] = g_param_spec_boxed ("satellite-info",
590                         "sps satellite information prop",
591                         "sps satellite information data",
592                         LOCATION_TYPE_SATELLITE,
593                         G_PARAM_READWRITE);
594
595         g_object_class_install_properties (gobject_class,
596                         PROP_MAX,
597                         properties);
598 }