4 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. All rights reserved.
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>
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
26 #include "location-setting.h"
27 #include "location-log.h"
29 #include "module-internal.h"
31 #include "location-cps.h"
32 #include "location-marshal.h"
33 #include "location-ielement.h"
34 #include "location-signaling-util.h"
35 #include "location-common-util.h"
37 typedef struct _LocationCpsPrivate {
42 guint pos_updated_timestamp;
44 guint vel_updated_timestamp;
46 LocationPosition *pos;
47 LocationVelocity *vel;
48 LocationAccuracy *acc;
50 ZoneStatus zone_status;
61 PROP_REMOVAL_BOUNDARY,
65 static guint32 signals[LAST_SIGNAL] = {0, };
66 static GParamSpec *properties[PROP_MAX] = {NULL, };
69 #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOCATION_TYPE_CPS, LocationCpsPrivate))
71 static void location_ielement_interface_init (LocationIElementInterface *iface);
73 G_DEFINE_TYPE_WITH_CODE (LocationCps, location_cps, G_TYPE_OBJECT,
74 G_IMPLEMENT_INTERFACE (LOCATION_TYPE_IELEMENT,
75 location_ielement_interface_init));
78 _position_timeout_cb (gpointer data)
80 GObject *object = (GObject *)data;
81 LocationCpsPrivate *priv = GET_PRIVATE(object);
82 if (!priv) return FALSE;
84 LocationPosition *pos = NULL;
85 LocationAccuracy *acc = NULL;
88 pos = location_position_copy(priv->pos);
91 pos = location_position_new (0, 0.0, 0.0, 0.0, LOCATION_STATUS_NO_FIX);
95 acc = location_accuracy_copy (priv->acc);
98 acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
101 LOCATION_LOGD("VELOCITY SERVICE_UPDATED");
102 g_signal_emit(object, signals[SERVICE_UPDATED], 0, POSITION_UPDATED, pos, acc);
104 location_position_free (pos);
105 location_accuracy_free (acc);
111 _velocity_timeout_cb (gpointer data)
113 GObject *object = (GObject *)data;
114 LocationCpsPrivate *priv = GET_PRIVATE(object);
115 if (!priv) return FALSE;
117 LocationVelocity *vel = NULL;
118 LocationAccuracy *acc = NULL;
121 vel = location_velocity_copy(priv->vel);
124 vel = location_velocity_new (0, 0.0, 0.0, 0.0);
128 acc = location_accuracy_copy (priv->acc);
131 acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0);
134 LOCATION_LOGD("VELOCITY SERVICE_UPDATED");
135 g_signal_emit(object, signals[SERVICE_UPDATED], 0, VELOCITY_UPDATED, vel, acc);
137 location_velocity_free (vel);
138 location_accuracy_free (acc);
144 cps_status_cb (gboolean enabled,
145 LocationStatus status,
148 LOCATION_LOGD("cps_status_cb");
149 g_return_if_fail(self);
150 LocationCpsPrivate* priv = GET_PRIVATE(self);
151 enable_signaling(self, signals, &(priv->enabled), enabled, status);
152 if (!priv->enabled) {
153 if (priv->pos_timer) {
154 g_source_remove(g_source_remove(priv->pos_timer));
157 if (priv->vel_timer) {
158 g_source_remove(g_source_remove(priv->vel_timer));
165 cps_position_cb (gboolean enabled,
166 LocationPosition *pos,
167 LocationAccuracy *acc,
170 LOCATION_LOGD("cps_position_cb");
171 g_return_if_fail(self);
172 g_return_if_fail(pos);
173 g_return_if_fail(acc);
174 LocationCpsPrivate* priv = GET_PRIVATE(self);
176 if (enabled && !priv->enabled) {
177 if (!priv->pos_timer) priv->pos_timer = g_timeout_add_seconds (priv->pos_interval, _position_timeout_cb, self);
178 if (!priv->vel_timer) priv->vel_timer = g_timeout_add_seconds (priv->vel_interval, _velocity_timeout_cb, self);
181 enable_signaling(self, signals, &(priv->enabled), enabled, pos->status);
182 position_signaling(self, signals, &(priv->enabled), priv->pos_interval, FALSE, &(priv->pos_updated_timestamp), &(priv->pos), &(priv->acc), priv->boundary_list, &(priv->zone_status), pos, acc);
186 cps_velocity_cb(gboolean enabled,
187 LocationVelocity *vel,
188 LocationAccuracy *acc,
191 LOCATION_LOGD("cps_velocity_cb");
192 g_return_if_fail(self);
193 LocationCpsPrivate* priv = GET_PRIVATE(self);
194 velocity_signaling(self, signals, &(priv->enabled), priv->vel_interval, FALSE, &(priv->vel_updated_timestamp), &(priv->vel), vel, acc);
198 location_setting_cps_cb (keynode_t *key,
201 LOCATION_LOGD("location_setting_cps_cb");
202 g_return_if_fail (key);
203 g_return_if_fail (self);
205 LocationCpsPrivate *priv = GET_PRIVATE(self);
206 g_return_if_fail (priv->mod);
207 g_return_if_fail (priv->mod->handler);
209 int ret = LOCATION_ERROR_NONE;
211 if (location_setting_get_key_val (key) == 0) {
212 if (priv->mod->ops.stop && priv->is_started) {
213 ret = priv->mod->ops.stop (priv->mod->handler);
214 if (ret == LOCATION_ERROR_NONE) {
215 priv->is_started = FALSE;
220 if (1 == location_setting_get_int (VCONFKEY_LOCATION_NETWORK_ENABLED) && priv->mod->ops.start && !priv->is_started) {
221 LOCATION_LOGD("location resumed by setting");
222 ret = priv->mod->ops.start (priv->mod->handler, cps_status_cb, cps_position_cb, cps_velocity_cb, NULL, self);
223 if (ret == LOCATION_ERROR_NONE) {
224 priv->is_started = TRUE;
231 location_cps_dispose (GObject *gobject)
233 LOCATION_LOGD("location_cps_dispose");
235 LocationCpsPrivate *priv = GET_PRIVATE(gobject);
236 if (priv->set_noti == TRUE) {
237 location_setting_ignore_notify (VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_cps_cb);
238 priv->set_noti = FALSE;
241 if (priv->pos_timer) {
242 g_source_remove (priv->pos_timer);
246 if (priv->vel_timer) {
247 g_source_remove (priv->vel_timer);
251 G_OBJECT_CLASS (location_cps_parent_class)->dispose (gobject);
255 location_cps_finalize (GObject *gobject)
257 LOCATION_LOGD("location_cps_finalize");
258 LocationCpsPrivate* priv = GET_PRIVATE(gobject);
259 module_free(priv->mod, "cps");
262 if (priv->boundary_list) {
263 g_list_free_full (priv->boundary_list, free_boundary_list);
264 priv->boundary_list = NULL;
268 location_position_free(priv->pos);
273 location_velocity_free(priv->vel);
278 location_accuracy_free(priv->acc);
282 G_OBJECT_CLASS (location_cps_parent_class)->finalize (gobject);
286 location_cps_set_property (GObject *object,
291 LocationCpsPrivate *priv = GET_PRIVATE(object);
295 switch (property_id) {
297 GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value));
298 ret = set_prop_boundary(&priv->boundary_list, boundary_list);
299 if(ret != 0) LOCATION_LOGD("Set boundary. Error[%d]", ret);
302 case PROP_REMOVAL_BOUNDARY: {
303 LocationBoundary *req_boundary = (LocationBoundary*) g_value_dup_boxed(value);
304 ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary);
305 if(ret != 0) LOCATION_LOGD("Set removal boundary. Error[%d]", ret);
308 case PROP_POS_INTERVAL: {
309 guint interval = g_value_get_uint (value);
312 if (interval < LOCATION_UPDATE_INTERVAL_MAX)
313 priv->pos_interval = interval;
315 priv->pos_interval = (guint) LOCATION_UPDATE_INTERVAL_MAX;
318 priv->pos_interval = (guint) LOCATION_UPDATE_INTERVAL_DEFAULT;
321 if (priv->pos_timer) {
322 g_source_remove (priv->pos_timer);
323 priv->pos_timer = g_timeout_add_seconds (priv->pos_interval, _position_timeout_cb, object);
329 case PROP_VEL_INTERVAL: {
330 guint interval = g_value_get_uint(value);
332 if(interval < LOCATION_UPDATE_INTERVAL_MAX)
333 priv->vel_interval = interval;
335 priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX;
338 priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT;
340 if (priv->vel_timer) {
341 g_source_remove (priv->vel_timer);
342 priv->vel_timer = g_timeout_add_seconds (priv->vel_interval, _velocity_timeout_cb, object);
348 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
354 location_cps_get_property (GObject *object,
359 LocationCpsPrivate *priv = GET_PRIVATE (object);
361 switch (property_id){
362 case PROP_METHOD_TYPE:
363 g_value_set_int(value, LOCATION_METHOD_CPS);
366 g_value_set_pointer(value, g_list_first(priv->boundary_list));
368 case PROP_POS_INTERVAL: {
369 g_value_set_uint (value, priv->pos_interval);
373 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
379 location_cps_start (LocationCps *self)
381 LOCATION_LOGD("location_cps_start");
383 LocationCpsPrivate* priv = GET_PRIVATE(self);
384 g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
385 g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
386 g_return_val_if_fail (priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE);
388 if (priv->is_started == TRUE) return LOCATION_ERROR_NONE;
390 int ret = LOCATION_ERROR_NONE;
392 if (!location_setting_get_int (VCONFKEY_LOCATION_NETWORK_ENABLED)) {
393 ret = LOCATION_ERROR_NOT_ALLOWED;
396 ret = priv->mod->ops.start (priv->mod->handler, cps_status_cb, cps_position_cb, cps_velocity_cb, NULL, self);
397 if (ret == LOCATION_ERROR_NONE) {
398 priv->is_started = TRUE;
405 if (priv->set_noti == FALSE) {
406 location_setting_add_notify (VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_cps_cb, self);
407 priv->set_noti = TRUE;
414 location_cps_stop (LocationCps *self)
416 LOCATION_LOGD("location_cps_stop");
417 LocationCpsPrivate* priv = GET_PRIVATE(self);
418 g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
419 g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
420 g_return_val_if_fail (priv->mod->ops.stop, LOCATION_ERROR_NOT_AVAILABLE);
422 int ret = LOCATION_ERROR_NONE;
424 if (priv->is_started == TRUE) {
425 ret = priv->mod->ops.stop (priv->mod->handler);
426 if (ret == LOCATION_ERROR_NONE) {
427 priv->is_started = FALSE;
434 if (priv->set_noti == TRUE) {
435 location_setting_ignore_notify (VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_cps_cb);
436 priv->set_noti = FALSE;
443 location_cps_get_position (LocationCps *self,
444 LocationPosition **position,
445 LocationAccuracy **accuracy)
447 int ret = LOCATION_ERROR_NOT_AVAILABLE;
448 LOCATION_LOGD("location_cps_get_position");
450 LocationCpsPrivate *priv = GET_PRIVATE (self);
451 g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
453 setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED);
456 *position = location_position_copy (priv->pos);
457 ret = LOCATION_ERROR_NONE;
463 *accuracy = location_accuracy_copy (priv->acc);
470 location_cps_get_last_position (LocationCps *self,
471 LocationPosition **position,
472 LocationAccuracy **accuracy)
474 LOCATION_LOGD("location_cps_get_last_position");
476 /* Do not need to check GPS_ENABLED and NETWORK_ENABLED */
478 LocationCpsPrivate *priv = GET_PRIVATE(self);
479 g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE);
481 LocModCpsOps ops = priv->mod->ops;
482 g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE);
483 g_return_val_if_fail (ops.get_last_position, LOCATION_ERROR_NOT_AVAILABLE);
485 return ops.get_last_position (priv->mod->handler, position, accuracy);
489 location_cps_get_velocity (LocationCps *self,
490 LocationVelocity **velocity,
491 LocationAccuracy **accuracy)
493 LOCATION_LOGD("location_cps_get_velocity");
494 return LOCATION_ERROR_NOT_SUPPORTED;
498 location_cps_get_last_velocity (LocationCps *self,
499 LocationVelocity **velocity,
500 LocationAccuracy **accuracy)
502 LOCATION_LOGD("location_cps_get_last_velocity");
503 return LOCATION_ERROR_NOT_SUPPORTED;
507 location_cps_get_satellite (LocationCps *self,
508 LocationSatellite **satellite)
510 LOCATION_LOGD("location_cps_get_satellite");
511 return LOCATION_ERROR_NOT_SUPPORTED;
515 location_cps_get_last_satellite (LocationCps *self)
517 LOCATION_LOGD("location_cps_get_last_satellite");
518 return LOCATION_ERROR_NOT_SUPPORTED;
522 location_ielement_interface_init (LocationIElementInterface *iface)
524 iface->start = (TYPE_START_FUNC) location_cps_start;
525 iface->stop = (TYPE_STOP_FUNC) location_cps_stop;
526 iface->get_position = (TYPE_GET_POSITION) location_cps_get_position;
527 iface->get_last_position = (TYPE_GET_POSITION) location_cps_get_last_position;
528 iface->get_velocity = (TYPE_GET_VELOCITY) location_cps_get_velocity;
529 iface->get_last_velocity = (TYPE_GET_VELOCITY)location_cps_get_last_velocity;
530 iface->get_satellite = (TYPE_GET_SATELLITE)location_cps_get_satellite;
531 iface->get_last_satellite = (TYPE_GET_SATELLITE)location_cps_get_last_satellite;
535 location_cps_init (LocationCps *self)
537 LOCATION_LOGD("location_cps_init");
538 LocationCpsPrivate* priv = GET_PRIVATE(self);
540 priv->mod = (LocationCpsMod*)module_new("cps");
541 if(!priv->mod) LOCATION_LOGW("module loading failed");
543 priv->is_started = FALSE;
544 priv->set_noti = FALSE;
545 priv->enabled = FALSE;
547 priv->pos_interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
548 priv->vel_interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
550 priv->pos_updated_timestamp = 0;
551 priv->vel_updated_timestamp = 0;
556 priv->zone_status = ZONE_STATUS_NONE;
557 priv->boundary_list = NULL;
564 location_cps_class_init (LocationCpsClass *klass)
566 LOCATION_LOGD("location_cps_class_init");
567 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
569 gobject_class->get_property = location_cps_get_property;
570 gobject_class->set_property = location_cps_set_property;
572 gobject_class->dispose = location_cps_dispose;
573 gobject_class->finalize = location_cps_finalize;
575 g_type_class_add_private (klass, sizeof (LocationCpsPrivate));
577 signals[SERVICE_ENABLED] = g_signal_new ("service-enabled",
578 G_TYPE_FROM_CLASS (klass),
581 G_STRUCT_OFFSET (LocationCpsClass, enabled),
587 signals[SERVICE_DISABLED] = g_signal_new ("service-disabled",
588 G_TYPE_FROM_CLASS (klass),
591 G_STRUCT_OFFSET (LocationCpsClass, disabled),
597 signals[SERVICE_UPDATED] = g_signal_new ("service-updated",
598 G_TYPE_FROM_CLASS (klass),
601 G_STRUCT_OFFSET (LocationCpsClass, updated),
603 location_VOID__UINT_POINTER_POINTER,
609 signals[ZONE_IN] = g_signal_new ("zone-in",
610 G_TYPE_FROM_CLASS (klass),
613 G_STRUCT_OFFSET (LocationCpsClass, zone_in),
615 location_VOID__UINT_POINTER_POINTER,
621 signals[ZONE_OUT] = g_signal_new ("zone-out",
622 G_TYPE_FROM_CLASS (klass),
625 G_STRUCT_OFFSET (LocationCpsClass, zone_out),
627 location_VOID__UINT_POINTER_POINTER,
633 properties[PROP_METHOD_TYPE] = g_param_spec_int ("method",
635 "location method type name",
641 properties[PROP_POS_INTERVAL] = g_param_spec_uint ("pos-interval",
642 "cps position interval prop",
643 "cps position interval data",
644 LOCATION_UPDATE_INTERVAL_MIN,
645 LOCATION_UPDATE_INTERVAL_MAX,
646 LOCATION_UPDATE_INTERVAL_DEFAULT,
649 properties[PROP_VEL_INTERVAL] = g_param_spec_uint ("vel-interval",
650 "cps velocity interval prop",
651 "cps velocity interval data",
652 LOCATION_UPDATE_INTERVAL_MIN,
653 LOCATION_UPDATE_INTERVAL_MAX,
654 LOCATION_UPDATE_INTERVAL_DEFAULT,
657 properties[PROP_BOUNDARY] = g_param_spec_pointer ("boundary",
662 properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary",
663 "cps removal boundary prop",
664 "cps removal boundary data",
665 LOCATION_TYPE_BOUNDARY,
668 g_object_class_install_properties (gobject_class,