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-hybrid.h"
32 #include "location-marshal.h"
33 #include "location-ielement.h"
34 #include "location-signaling-util.h"
35 #include "location-common-util.h"
37 #include "location-gps.h"
38 #include "location-wps.h"
39 #include "location-sps.h"
41 typedef struct _LocationHybridPrivate {
52 LocationMethod current_method;
53 LocationPosition *pos;
54 LocationVelocity *vel;
55 LocationAccuracy *acc;
56 LocationSatellite *sat;
58 ZoneStatus zone_status;
60 } LocationHybridPrivate;
68 PROP_REMOVAL_BOUNDARY,
72 static guint32 signals[LAST_SIGNAL] = {0, };
73 static GParamSpec *properties[PROP_MAX] = {NULL, };
75 #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOCATION_TYPE_HYBRID, LocationHybridPrivate))
77 static void location_ielement_interface_init (LocationIElementInterface *iface);
79 G_DEFINE_TYPE_WITH_CODE (LocationHybrid, location_hybrid, G_TYPE_OBJECT,
80 G_IMPLEMENT_INTERFACE (LOCATION_TYPE_IELEMENT,
81 location_ielement_interface_init));
84 static LocationObject*
85 hybrid_get_update_method_obj (LocationHybridPrivate* priv)
87 if(!priv->sps && !priv->gps && !priv->wps) return NULL;
89 LocationObject* obj = NULL;
90 if (priv->sps_enabled) {
91 LOCATION_LOGW("Current method is SPS");
92 priv->current_method = LOCATION_METHOD_SPS;
94 } else if (priv->gps_enabled) {
95 LOCATION_LOGW("Current method is GPS");
96 priv->current_method = LOCATION_METHOD_GPS;
98 } else if (priv->wps_enabled) {
99 LOCATION_LOGW("Current method is WPS");
100 priv->current_method = LOCATION_METHOD_WPS;
103 LOCATION_LOGW("No current method available");
104 priv->current_method = LOCATION_METHOD_HYBRID;
111 hybrid_is_equal_g_type_method(GType g_type, LocationMethod method)
113 if (g_type == LOCATION_TYPE_SPS && method == LOCATION_METHOD_SPS) return TRUE;
114 if (g_type == LOCATION_TYPE_GPS && method == LOCATION_METHOD_GPS) return TRUE;
115 if (g_type == LOCATION_TYPE_WPS && method == LOCATION_METHOD_WPS) return TRUE;
120 hybrid_update_sps(LocationHybrid* self,
125 LocationHybridPrivate* priv = GET_PRIVATE(self);
126 if (!priv->sps) return;
127 LOCATION_LOGD ("hybrid_update_sps");
130 case POSITION_UPDATED: {
131 if (data) g_object_set(priv->sps, "position-base", data, NULL);
133 LocationSatellite* sat = NULL;
134 g_object_get(priv->gps, "satellite", &sat, NULL);
136 g_object_set(priv->sps, "satellite-info", sat, NULL);
137 location_satellite_free (sat);
140 if (accuracy) g_object_set(priv->sps, "accuracy-info", accuracy, NULL);
143 case VELOCITY_UPDATED:
144 if (data) g_object_set(priv->sps, "velocity-base", data, NULL);
145 if (accuracy) g_object_set(priv->sps, "accuracy-info", accuracy, NULL);
151 hybrid_service_updated (GObject *obj,
157 LOCATION_LOGD ("hybrid_service_updated");
158 LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self);
159 GType g_type = G_TYPE_FROM_INSTANCE(obj);
160 if (g_type == LOCATION_TYPE_GPS) {
161 if (type == SATELLITE_UPDATED) {
162 LocationSatellite *sat = (LocationSatellite *) data;
163 satellite_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->sat_timestamp), &(priv->sat), TRUE, sat);
164 } else hybrid_update_sps((LocationHybrid*)self, type, data, accuracy);
167 if (hybrid_is_equal_g_type_method(g_type, priv->current_method)) {
168 LocationAccuracy *acc = (LocationAccuracy*)accuracy;
169 if (type == POSITION_UPDATED) {
170 LocationPosition *pos = (LocationPosition*)data;
171 position_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->pos), &(priv->acc), priv->boundary_list, &(priv->zone_status), TRUE, pos, acc);
172 } else if (type == VELOCITY_UPDATED) {
173 LocationVelocity *vel = (LocationVelocity*) data;
174 velocity_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->vel), TRUE, vel, acc);
175 }else LOCATION_LOGW ("Undefined GType updated");
181 hybrid_service_enabled (GObject *obj,
185 LOCATION_LOGD ("hybrid_service_enabled");
186 LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self);
187 GType g_type = G_TYPE_FROM_INSTANCE(obj);
188 if (g_type == LOCATION_TYPE_SPS) priv->sps_enabled = TRUE;
189 else if(g_type == LOCATION_TYPE_GPS) priv->gps_enabled = TRUE;
190 else if(g_type == LOCATION_TYPE_WPS) priv->wps_enabled = TRUE;
192 LOCATION_LOGW("Undefined GType enabled");
195 hybrid_get_update_method_obj(priv);
196 if(priv->sps_enabled || priv->gps_enabled || priv->wps_enabled)
197 enable_signaling(self, signals, &(priv->enabled), TRUE, status);
201 hybrid_service_disabled (GObject *obj,
205 LOCATION_LOGD ("hybrid_service_disabled");
206 LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self);
207 GType g_type = G_TYPE_FROM_INSTANCE(obj);
208 if (g_type == LOCATION_TYPE_SPS) priv->sps_enabled = FALSE;
209 else if(g_type == LOCATION_TYPE_GPS) priv->gps_enabled = FALSE;
210 else if(g_type == LOCATION_TYPE_WPS) priv->wps_enabled = FALSE;
212 LOCATION_LOGW("Undefined GType disabled");
215 hybrid_get_update_method_obj(priv);
216 if(!priv->sps_enabled && !priv->gps_enabled && !priv->wps_enabled)
217 enable_signaling(self, signals, &(priv->enabled), FALSE, status);
221 location_hybrid_start (LocationHybrid *self)
223 LOCATION_LOGD("location_hybrid_start");
225 int ret_gps = LOCATION_ERROR_NONE;
226 int ret_wps = LOCATION_ERROR_NONE;
227 int ret_sps = LOCATION_ERROR_NONE;
229 LocationHybridPrivate* priv = GET_PRIVATE(self);
230 if (priv->is_started == TRUE)
231 return LOCATION_ERROR_NONE;
233 if(priv->gps) ret_gps = location_start(priv->gps);
234 if(priv->wps) ret_wps = location_start(priv->wps);
235 if(priv->sps) ret_sps = location_start(priv->sps);
237 if (ret_gps != LOCATION_ERROR_NONE &&
238 ret_wps != LOCATION_ERROR_NONE &&
239 ret_sps != LOCATION_ERROR_NONE) {
240 if (ret_gps == LOCATION_ERROR_NOT_ALLOWED ||
241 ret_wps == LOCATION_ERROR_NOT_ALLOWED ||
242 ret_sps == LOCATION_ERROR_NOT_ALLOWED) {
243 priv->is_started = TRUE;
244 return LOCATION_ERROR_NOT_ALLOWED;
247 return LOCATION_ERROR_NOT_AVAILABLE;
251 priv->is_started = TRUE;
252 return LOCATION_ERROR_NONE;
256 location_hybrid_stop (LocationHybrid *self)
258 LOCATION_LOGD("location_hybrid_stop");
260 LocationHybridPrivate* priv = GET_PRIVATE(self);
261 if( priv->is_started == FALSE)
262 return LOCATION_ERROR_NONE;
264 int ret_gps = LOCATION_ERROR_NONE;
265 int ret_wps = LOCATION_ERROR_NONE;
266 int ret_sps = LOCATION_ERROR_NONE;
268 if(priv->gps) ret_gps = location_stop(priv->gps);
269 if(priv->wps) ret_wps = location_stop(priv->wps);
270 if(priv->sps) ret_sps = location_stop(priv->sps);
272 priv->is_started = FALSE;
274 if (ret_gps != LOCATION_ERROR_NONE &&
275 ret_wps != LOCATION_ERROR_NONE &&
276 ret_sps != LOCATION_ERROR_NONE)
277 return LOCATION_ERROR_NOT_AVAILABLE;
279 return LOCATION_ERROR_NONE;
283 location_hybrid_dispose (GObject *gobject)
285 LOCATION_LOGD("location_hybrid_dispose");
286 G_OBJECT_CLASS (location_hybrid_parent_class)->dispose (gobject);
290 location_hybrid_finalize (GObject *gobject)
292 LOCATION_LOGD("location_hybrid_finalize");
293 LocationHybridPrivate* priv = GET_PRIVATE(gobject);
296 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_enabled), gobject);
297 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_disabled), gobject);
298 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_updated), gobject);
299 location_free(priv->gps);
302 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_enabled), gobject);
303 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_disabled), gobject);
304 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_updated), gobject);
305 location_free(priv->wps);
308 g_signal_handlers_disconnect_by_func(priv->sps, G_CALLBACK (hybrid_service_enabled), gobject);
309 g_signal_handlers_disconnect_by_func(priv->sps, G_CALLBACK (hybrid_service_disabled), gobject);
310 g_signal_handlers_disconnect_by_func(priv->sps, G_CALLBACK (hybrid_service_updated), gobject);
311 location_free(priv->sps);
314 G_OBJECT_CLASS (location_hybrid_parent_class)->finalize (gobject);
318 location_hybrid_set_property (GObject *object,
323 LocationHybridPrivate* priv = GET_PRIVATE(object);
324 if (!priv->gps && !priv->wps && !priv->sps) {
325 LOCATION_LOGW("Set property is not available now");
330 switch (property_id){
332 GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value));
333 ret = set_prop_boundary(&priv->boundary_list, boundary_list);
334 if(ret != 0) LOCATION_LOGD("Set boundary. Error[%d]", ret);
337 case PROP_REMOVAL_BOUNDARY: {
338 LocationBoundary *req_boundary = (LocationBoundary*) g_value_dup_boxed(value);
339 ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary);
340 if(ret != 0) LOCATION_LOGD("Removal boundary. Error[%d]", ret);
343 case PROP_UPDATE_INTERVAL: {
344 guint interval = g_value_get_uint(value);
346 if(interval < LOCATION_UPDATE_INTERVAL_MAX)
347 priv->interval = interval;
349 priv->interval = (guint) LOCATION_UPDATE_INTERVAL_MAX;
353 priv->interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
357 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
363 location_hybrid_get_property (GObject *object,
368 LocationHybridPrivate *priv = GET_PRIVATE (object);
369 if(!priv->gps && !priv->wps && !priv->sps){
370 LOCATION_LOGW("Get property is not available now");
374 LOCATION_LOGW("Get Propery ID[%d]", property_id);
376 switch (property_id){
377 case PROP_METHOD_TYPE:
378 g_value_set_int(value, priv->current_method);
380 case PROP_LAST_POSITION:
381 g_value_set_boxed(value, priv->pos);
384 g_value_set_pointer(value, g_list_first(priv->boundary_list));
386 case PROP_UPDATE_INTERVAL:
387 g_value_set_uint(value, priv->interval);
390 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
396 location_hybrid_get_position (LocationHybrid *self,
397 LocationPosition **position,
398 LocationAccuracy **accuracy)
400 LOCATION_LOGD("location_hybrid_get_position");
401 setting_retval_if_fail(GPS_ENABLED);
403 LocationHybridPrivate *priv = GET_PRIVATE (self);
404 LocationObject *obj = hybrid_get_update_method_obj(priv);
405 if(!obj) return LOCATION_ERROR_NOT_AVAILABLE;
406 return location_get_position (obj, position, accuracy);
410 location_hybrid_get_last_position (LocationHybrid *self,
411 LocationPosition **position,
412 LocationAccuracy **accuracy)
414 LOCATION_LOGD("location_hybrid_get_last_position");
415 setting_retval_if_fail(GPS_ENABLED);
417 int ret = LOCATION_ERROR_NONE;
418 LocationPosition *gps_pos = NULL, *wps_pos = NULL;
419 LocationAccuracy *gps_acc = NULL, *wps_acc = NULL;
420 LocationHybridPrivate *priv = GET_PRIVATE (self);
422 if (priv->gps) location_get_last_position (priv->gps, &gps_pos, &gps_acc);
423 if (priv->wps) location_get_last_position (priv->wps, &wps_pos, &wps_acc);
425 if (gps_pos && wps_pos) {
426 if (wps_pos->timestamp > gps_pos->timestamp) {
429 location_position_free (gps_pos);
430 location_accuracy_free (gps_acc);
435 location_position_free (wps_pos);
436 location_accuracy_free (wps_acc);
438 } else if (gps_pos) {
441 } else if (wps_pos) {
445 ret = LOCATION_ERROR_NOT_AVAILABLE;
452 location_hybrid_get_velocity (LocationHybrid *self,
453 LocationVelocity **velocity,
454 LocationAccuracy **accuracy)
456 LOCATION_LOGD("location_hybrid_get_velocity");
457 setting_retval_if_fail(GPS_ENABLED);
459 LocationHybridPrivate *priv = GET_PRIVATE (self);
460 LocationObject *obj = hybrid_get_update_method_obj(priv);
461 if(!obj) return LOCATION_ERROR_NOT_AVAILABLE;
462 return location_get_velocity (obj, velocity, accuracy);
466 location_hybrid_get_last_velocity (LocationHybrid *self,
467 LocationVelocity **velocity,
468 LocationAccuracy **accuracy)
470 LOCATION_LOGD("location_hybrid_get_last_velocity");
471 setting_retval_if_fail(GPS_ENABLED);
473 int ret = LOCATION_ERROR_NONE;
474 LocationHybridPrivate *priv = GET_PRIVATE (self);
475 LocationVelocity *gps_vel = NULL, *wps_vel = NULL;
476 LocationAccuracy *gps_acc = NULL, *wps_acc = NULL;
478 if (priv->gps) location_get_last_velocity (priv->gps, &gps_vel, &gps_acc);
479 if (priv->wps) location_get_last_velocity (priv->wps, &wps_vel, &wps_acc);
481 if (gps_vel && wps_vel) {
482 if (wps_vel->timestamp > gps_vel->timestamp) {
485 location_velocity_free (gps_vel);
486 location_accuracy_free (gps_acc);
490 location_velocity_free (wps_vel);
491 location_accuracy_free (wps_acc);
497 } else if (wps_vel) {
503 ret = LOCATION_ERROR_NOT_AVAILABLE;
510 location_hybrid_get_satellite (LocationHybrid *self,
511 LocationSatellite **satellite)
513 LOCATION_LOGD("location_hybrid_get_satellite");
514 setting_retval_if_fail(GPS_ENABLED);
516 int ret = LOCATION_ERROR_NONE;
517 LocationHybridPrivate *priv = GET_PRIVATE (self);
518 if (priv->gps) ret = location_get_satellite (priv->gps, satellite);
521 ret = LOCATION_ERROR_NOT_AVAILABLE;
528 location_hybrid_get_last_satellite (LocationHybrid *self,
529 LocationSatellite **satellite)
531 LOCATION_LOGD("location_hybrid_get_last_satellite");
532 setting_retval_if_fail(GPS_ENABLED);
534 int ret = LOCATION_ERROR_NONE;
535 LocationHybridPrivate *priv = GET_PRIVATE (self);
537 if (priv->gps) ret = location_get_last_satellite (priv->gps, satellite);
540 ret = LOCATION_ERROR_NOT_AVAILABLE;
547 location_ielement_interface_init (LocationIElementInterface *iface)
549 iface->start = (TYPE_START_FUNC)location_hybrid_start;
550 iface->stop = (TYPE_STOP_FUNC)location_hybrid_stop;
551 iface->get_position = (TYPE_GET_POSITION)location_hybrid_get_position;
552 iface->get_last_position = (TYPE_GET_POSITION)location_hybrid_get_last_position;
553 iface->get_velocity = (TYPE_GET_VELOCITY)location_hybrid_get_velocity;
554 iface->get_last_velocity = (TYPE_GET_VELOCITY)location_hybrid_get_last_velocity;
555 iface->get_satellite = (TYPE_GET_SATELLITE)location_hybrid_get_satellite;
556 iface->get_last_satellite = (TYPE_GET_SATELLITE)location_hybrid_get_last_satellite;
560 location_hybrid_init (LocationHybrid *self)
562 LOCATION_LOGD("location_hybrid_init");
563 LocationHybridPrivate* priv = GET_PRIVATE(self);
565 priv->is_started = FALSE;
566 priv->interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
567 priv->gps_enabled = FALSE;
568 priv->wps_enabled = FALSE;
569 priv->sps_enabled = FALSE;
574 if(location_is_supported_method(LOCATION_METHOD_GPS)) priv->gps = location_new (LOCATION_METHOD_GPS);
575 if(location_is_supported_method(LOCATION_METHOD_WPS)) priv->wps = location_new (LOCATION_METHOD_WPS);
576 if(location_is_supported_method(LOCATION_METHOD_SPS)) priv->sps = location_new (LOCATION_METHOD_SPS);
579 g_signal_connect (priv->gps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
580 g_signal_connect (priv->gps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
581 g_signal_connect (priv->gps, "service-updated", G_CALLBACK(hybrid_service_updated), self);
584 g_signal_connect (priv->wps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
585 g_signal_connect (priv->wps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
586 g_signal_connect (priv->wps, "service-updated", G_CALLBACK(hybrid_service_updated), self);
589 g_signal_connect (priv->sps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
590 g_signal_connect (priv->sps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
591 g_signal_connect (priv->sps, "service-updated", G_CALLBACK(hybrid_service_updated), self);
594 priv->current_method = LOCATION_METHOD_HYBRID;
595 priv->enabled= FALSE;
600 priv->zone_status = ZONE_STATUS_NONE;
601 priv->boundary_list = NULL;
605 location_hybrid_class_init (LocationHybridClass *klass)
607 LOCATION_LOGD("location_hybrid_class_init");
608 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
610 gobject_class->set_property = location_hybrid_set_property;
611 gobject_class->get_property = location_hybrid_get_property;
613 gobject_class->dispose = location_hybrid_dispose;
614 gobject_class->finalize = location_hybrid_finalize;
616 g_type_class_add_private (klass, sizeof (LocationHybridPrivate));
618 signals[SERVICE_ENABLED] = g_signal_new ("service-enabled",
619 G_TYPE_FROM_CLASS (klass),
622 G_STRUCT_OFFSET (LocationHybridClass, enabled),
628 signals[SERVICE_DISABLED] = g_signal_new ("service-disabled",
629 G_TYPE_FROM_CLASS (klass),
632 G_STRUCT_OFFSET (LocationHybridClass, disabled),
638 signals[SERVICE_UPDATED] = g_signal_new ("service-updated",
639 G_TYPE_FROM_CLASS (klass),
642 G_STRUCT_OFFSET (LocationHybridClass, updated),
644 location_VOID__UINT_POINTER_POINTER,
650 signals[ZONE_IN] = g_signal_new ("zone-in",
651 G_TYPE_FROM_CLASS (klass),
654 G_STRUCT_OFFSET (LocationHybridClass, zone_in),
656 location_VOID__UINT_POINTER_POINTER,
662 signals[ZONE_OUT] = g_signal_new ("zone-out",
663 G_TYPE_FROM_CLASS (klass),
666 G_STRUCT_OFFSET (LocationHybridClass, zone_out),
668 location_VOID__UINT_POINTER_POINTER,
674 properties[PROP_METHOD_TYPE] = g_param_spec_int ("method",
676 "location method type name",
677 LOCATION_METHOD_HYBRID,
678 LOCATION_METHOD_HYBRID,
679 LOCATION_METHOD_HYBRID,
682 properties[PROP_LAST_POSITION] = g_param_spec_boxed ("last-position",
683 "hybrid last position prop",
684 "hybrid last position data",
685 LOCATION_TYPE_POSITION,
688 properties[PROP_UPDATE_INTERVAL] = g_param_spec_uint ("update-interval",
689 "update interval prop",
690 "update interval data",
691 LOCATION_UPDATE_INTERVAL_MIN,
692 LOCATION_UPDATE_INTERVAL_MAX,
693 LOCATION_UPDATE_INTERVAL_DEFAULT,
696 properties[PROP_BOUNDARY] = g_param_spec_pointer ("boundary",
697 "hybrid boundary prop",
698 "hybrid boundary data",
701 properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary",
702 "hybrid removal boundary prop",
703 "hybrid removal boundary data",
704 LOCATION_TYPE_BOUNDARY,
707 g_object_class_install_properties (gobject_class,