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/location-setting.h"
27 #include "location/location-log.h"
29 #include "location/location-module-internal.h"
31 #include "location/location-hybrid.h"
32 #include "location/location-marshal.h"
33 #include "location/location-ielement.h"
34 #include "location/location-signaling-util.h"
35 #include "location/location-common-util.h"
37 #include "location/location-gps.h"
38 #include "location/location-wps.h"
39 #include "location/location-sps.h"
41 typedef struct _LocationHybridPrivate {
51 LocationMethod current_method;
52 LocationPosition *pos;
53 LocationVelocity *vel;
54 LocationAccuracy *acc;
56 ZoneStatus zone_status;
58 } LocationHybridPrivate;
66 PROP_REMOVAL_BOUNDARY,
70 static guint32 signals[LAST_SIGNAL] = {0, };
71 static GParamSpec *properties[PROP_MAX] = {NULL, };
73 #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOCATION_TYPE_HYBRID, LocationHybridPrivate))
75 static void location_ielement_interface_init (LocationIElementInterface *iface);
77 G_DEFINE_TYPE_WITH_CODE (LocationHybrid, location_hybrid, G_TYPE_OBJECT,
78 G_IMPLEMENT_INTERFACE (LOCATION_TYPE_IELEMENT,
79 location_ielement_interface_init));
82 static LocationObject*
83 hybrid_get_update_method_obj (LocationHybridPrivate* priv)
85 if(!priv->sps && !priv->gps && !priv->wps) return NULL;
87 LocationObject* obj = NULL;
88 if (priv->sps_enabled) {
89 LOCATION_LOGW("Current method is SPS");
90 priv->current_method = LOCATION_METHOD_SPS;
92 } else if (priv->gps_enabled) {
93 LOCATION_LOGW("Current method is GPS");
94 priv->current_method = LOCATION_METHOD_GPS;
96 } else if (priv->wps_enabled) {
97 LOCATION_LOGW("Current method is WPS");
98 priv->current_method = LOCATION_METHOD_WPS;
101 LOCATION_LOGW("No current method available");
102 priv->current_method = LOCATION_METHOD_HYBRID;
109 hyrid_is_equal_g_type_method(GType g_type, LocationMethod method)
111 if (g_type == LOCATION_TYPE_SPS && method == LOCATION_METHOD_SPS) return TRUE;
112 if (g_type == LOCATION_TYPE_GPS && method == LOCATION_METHOD_GPS) return TRUE;
113 if (g_type == LOCATION_TYPE_WPS && method == LOCATION_METHOD_WPS) return TRUE;
118 hybrid_update_sps(LocationHybrid* self,
123 LocationHybridPrivate* priv = GET_PRIVATE(self);
124 if (!priv->sps) return;
125 LOCATION_LOGD ("hybrid_update_sps");
128 case POSITION_UPDATED: {
129 if (data) g_object_set(priv->sps, "position-base", data, NULL);
131 LocationSatellite* sat = NULL;
132 g_object_get(priv->gps, "satellite", &sat, NULL);
134 g_object_set(priv->sps, "satellite-info", sat, NULL);
135 location_satellite_free (sat);
138 if (accuracy) g_object_set(priv->sps, "accuracy-info", accuracy, NULL);
141 case VELOCITY_UPDATED:
142 if (data) g_object_set(priv->sps, "velocity-base", data, NULL);
143 if (accuracy) g_object_set(priv->sps, "accuracy-info", accuracy, NULL);
149 hybrid_service_updated (GObject *obj,
155 LOCATION_LOGD ("hybrid_service_updated");
156 LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self);
157 GType g_type = G_TYPE_FROM_INSTANCE(obj);
158 if (g_type == LOCATION_TYPE_GPS) hybrid_update_sps((LocationHybrid*)self, type, data, accuracy);
159 if (hyrid_is_equal_g_type_method(g_type, priv->current_method)) {
160 LocationAccuracy *acc = (LocationAccuracy*)accuracy;
161 if (type == POSITION_UPDATED) {
162 LocationPosition *pos = (LocationPosition*)data;
163 position_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->pos), &(priv->acc), priv->boundary_list, &(priv->zone_status), TRUE, pos, acc);
164 } else if (type == VELOCITY_UPDATED) {
165 LocationVelocity *vel = (LocationVelocity*) data;
166 velocity_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->vel), TRUE, vel, acc);
167 } else LOCATION_LOGW ("Undefined GType updated");
173 hybrid_service_enabled (GObject *obj,
177 LOCATION_LOGD ("hybrid_service_enabled");
178 LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self);
179 GType g_type = G_TYPE_FROM_INSTANCE(obj);
180 if (g_type == LOCATION_TYPE_SPS) priv->sps_enabled = TRUE;
181 else if(g_type == LOCATION_TYPE_GPS) priv->gps_enabled = TRUE;
182 else if(g_type == LOCATION_TYPE_WPS) priv->wps_enabled = TRUE;
184 LOCATION_LOGW("Undefined GType enabled");
187 hybrid_get_update_method_obj(priv);
188 if(priv->sps_enabled || priv->gps_enabled || priv->wps_enabled)
189 enable_signaling(self, signals, &(priv->enabled), TRUE, status);
193 hybrid_service_disabled (GObject *obj,
197 LOCATION_LOGD ("hybrid_service_disabled");
198 LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self);
199 GType g_type = G_TYPE_FROM_INSTANCE(obj);
200 if (g_type == LOCATION_TYPE_SPS) priv->sps_enabled = FALSE;
201 else if(g_type == LOCATION_TYPE_GPS) priv->gps_enabled = FALSE;
202 else if(g_type == LOCATION_TYPE_WPS) priv->wps_enabled = FALSE;
204 LOCATION_LOGW("Undefined GType disabled");
207 hybrid_get_update_method_obj(priv);
208 if(!priv->sps_enabled && !priv->gps_enabled && !priv->wps_enabled)
209 enable_signaling(self, signals, &(priv->enabled), FALSE, status);
213 location_hybrid_start (LocationHybrid *self)
215 LOCATION_LOGD("location_hybrid_start");
217 int ret_gps = LOCATION_ERROR_NONE;
218 int ret_wps = LOCATION_ERROR_NONE;
219 int ret_sps = LOCATION_ERROR_NONE;
221 LocationHybridPrivate* priv = GET_PRIVATE(self);
222 if (priv->is_started == TRUE)
223 return LOCATION_ERROR_NONE;
225 if(priv->gps) ret_gps = location_start(priv->gps);
226 if(priv->wps) ret_wps = location_start(priv->wps);
227 if(priv->sps) ret_sps = location_start(priv->sps);
229 if (ret_gps != LOCATION_ERROR_NONE &&
230 ret_wps != LOCATION_ERROR_NONE &&
231 ret_sps != LOCATION_ERROR_NONE) {
232 if (ret_gps == LOCATION_ERROR_NOT_ALLOWED ||
233 ret_wps == LOCATION_ERROR_NOT_ALLOWED ||
234 ret_sps == LOCATION_ERROR_NOT_ALLOWED) {
235 priv->is_started = TRUE;
236 return LOCATION_ERROR_NOT_ALLOWED;
239 return LOCATION_ERROR_NOT_AVAILABLE;
243 priv->is_started = TRUE;
244 return LOCATION_ERROR_NONE;
248 location_hybrid_stop (LocationHybrid *self)
250 LOCATION_LOGD("location_hybrid_stop");
252 LocationHybridPrivate* priv = GET_PRIVATE(self);
253 if( priv->is_started == FALSE)
254 return LOCATION_ERROR_NONE;
256 int ret_gps = LOCATION_ERROR_NONE;
257 int ret_wps = LOCATION_ERROR_NONE;
258 int ret_sps = LOCATION_ERROR_NONE;
260 if(priv->gps) ret_gps = location_stop(priv->gps);
261 if(priv->wps) ret_wps = location_stop(priv->wps);
262 if(priv->sps) ret_sps = location_stop(priv->sps);
264 priv->is_started = FALSE;
266 if (ret_gps != LOCATION_ERROR_NONE &&
267 ret_wps != LOCATION_ERROR_NONE &&
268 ret_sps != LOCATION_ERROR_NONE)
269 return LOCATION_ERROR_NOT_AVAILABLE;
271 return LOCATION_ERROR_NONE;
275 location_hybrid_dispose (GObject *gobject)
277 LOCATION_LOGD("location_hybrid_dispose");
278 G_OBJECT_CLASS (location_hybrid_parent_class)->dispose (gobject);
282 location_hybrid_finalize (GObject *gobject)
284 LOCATION_LOGD("location_hybrid_finalize");
285 LocationHybridPrivate* priv = GET_PRIVATE(gobject);
288 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_enabled), gobject);
289 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_disabled), gobject);
290 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_updated), gobject);
291 location_free(priv->gps);
294 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_enabled), gobject);
295 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_disabled), gobject);
296 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_updated), gobject);
297 location_free(priv->wps);
300 g_signal_handlers_disconnect_by_func(priv->sps, G_CALLBACK (hybrid_service_enabled), gobject);
301 g_signal_handlers_disconnect_by_func(priv->sps, G_CALLBACK (hybrid_service_disabled), gobject);
302 g_signal_handlers_disconnect_by_func(priv->sps, G_CALLBACK (hybrid_service_updated), gobject);
303 location_free(priv->sps);
306 G_OBJECT_CLASS (location_hybrid_parent_class)->finalize (gobject);
310 location_hybrid_set_property (GObject *object,
315 LocationHybridPrivate* priv = GET_PRIVATE(object);
316 if (!priv->gps && !priv->wps && !priv->sps) {
317 LOCATION_LOGW("Set property is not available now");
322 switch (property_id){
324 GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value));
325 ret = set_prop_boundary(&priv->boundary_list, boundary_list);
326 if(ret != 0) LOCATION_LOGD("Set boundary. Error[%d]", ret);
329 case PROP_REMOVAL_BOUNDARY: {
330 LocationBoundary *req_boundary = (LocationBoundary*) g_value_dup_boxed(value);
331 ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary);
332 if(ret != 0) LOCATION_LOGD("Removal boundary. Error[%d]", ret);
335 case PROP_UPDATE_INTERVAL: {
336 guint interval = g_value_get_uint(value);
338 if(interval < LOCATION_UPDATE_INTERVAL_MAX)
339 priv->interval = interval;
341 priv->interval = (guint) LOCATION_UPDATE_INTERVAL_MAX;
345 priv->interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
349 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
355 location_hybrid_get_property (GObject *object,
360 LocationHybridPrivate *priv = GET_PRIVATE (object);
361 if(!priv->gps && !priv->wps && !priv->sps){
362 LOCATION_LOGW("Get property is not available now");
366 LOCATION_LOGW("Get Propery ID[%d]", property_id);
368 switch (property_id){
369 case PROP_METHOD_TYPE:
370 g_value_set_int(value, priv->current_method);
372 case PROP_LAST_POSITION:
373 g_value_set_boxed(value, priv->pos);
376 g_value_set_pointer(value, g_list_first(priv->boundary_list));
378 case PROP_UPDATE_INTERVAL:
379 g_value_set_uint(value, priv->interval);
382 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
388 location_hybrid_get_position (LocationHybrid *self,
389 LocationPosition **position,
390 LocationAccuracy **accuracy)
392 LOCATION_LOGD("location_hybrid_get_position");
393 setting_retval_if_fail(GPS_ENABLED);
395 LocationHybridPrivate *priv = GET_PRIVATE (self);
396 LocationObject *obj = hybrid_get_update_method_obj(priv);
397 if(!obj) return LOCATION_ERROR_NOT_AVAILABLE;
398 return location_get_position (obj, position, accuracy);
402 location_hybrid_get_velocity (LocationHybrid *self,
403 LocationVelocity **velocity,
404 LocationAccuracy **accuracy)
406 LOCATION_LOGD("location_hybrid_get_velocity");
407 setting_retval_if_fail(GPS_ENABLED);
409 LocationHybridPrivate *priv = GET_PRIVATE (self);
410 LocationObject *obj = hybrid_get_update_method_obj(priv);
411 if(!obj) return LOCATION_ERROR_NOT_AVAILABLE;
412 return location_get_velocity (obj, velocity, accuracy);
416 location_ielement_interface_init (LocationIElementInterface *iface)
418 iface->start = (TYPE_START_FUNC)location_hybrid_start;
419 iface->stop = (TYPE_STOP_FUNC)location_hybrid_stop;
420 iface->get_position = (TYPE_GET_POSITION)location_hybrid_get_position;
421 iface->get_velocity = (TYPE_GET_VELOCITY)location_hybrid_get_velocity;
425 location_hybrid_init (LocationHybrid *self)
427 LOCATION_LOGD("location_hybrid_init");
428 LocationHybridPrivate* priv = GET_PRIVATE(self);
430 priv->is_started = FALSE;
431 priv->interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
432 priv->gps_enabled = FALSE;
433 priv->wps_enabled = FALSE;
434 priv->sps_enabled = FALSE;
439 if(location_is_supported_method(LOCATION_METHOD_GPS)) priv->gps = location_new (LOCATION_METHOD_GPS);
440 if(location_is_supported_method(LOCATION_METHOD_WPS)) priv->wps = location_new (LOCATION_METHOD_WPS);
441 if(location_is_supported_method(LOCATION_METHOD_SPS)) priv->sps = location_new (LOCATION_METHOD_SPS);
444 g_signal_connect (priv->gps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
445 g_signal_connect (priv->gps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
446 g_signal_connect (priv->gps, "service-updated", G_CALLBACK(hybrid_service_updated), self);
449 g_signal_connect (priv->wps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
450 g_signal_connect (priv->wps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
451 g_signal_connect (priv->wps, "service-updated", G_CALLBACK(hybrid_service_updated), self);
454 g_signal_connect (priv->sps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
455 g_signal_connect (priv->sps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
456 g_signal_connect (priv->sps, "service-updated", G_CALLBACK(hybrid_service_updated), self);
459 priv->current_method = LOCATION_METHOD_HYBRID;
460 priv->enabled= FALSE;
465 priv->zone_status = ZONE_STATUS_NONE;
466 priv->boundary_list = NULL;
470 location_hybrid_class_init (LocationHybridClass *klass)
472 LOCATION_LOGD("location_hybrid_class_init");
473 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
475 gobject_class->set_property = location_hybrid_set_property;
476 gobject_class->get_property = location_hybrid_get_property;
478 gobject_class->dispose = location_hybrid_dispose;
479 gobject_class->finalize = location_hybrid_finalize;
481 g_type_class_add_private (klass, sizeof (LocationHybridPrivate));
483 signals[SERVICE_ENABLED] = g_signal_new ("service-enabled",
484 G_TYPE_FROM_CLASS (klass),
487 G_STRUCT_OFFSET (LocationHybridClass, enabled),
493 signals[SERVICE_DISABLED] = g_signal_new ("service-disabled",
494 G_TYPE_FROM_CLASS (klass),
497 G_STRUCT_OFFSET (LocationHybridClass, disabled),
503 signals[SERVICE_UPDATED] = g_signal_new ("service-updated",
504 G_TYPE_FROM_CLASS (klass),
507 G_STRUCT_OFFSET (LocationHybridClass, updated),
509 location_VOID__UINT_POINTER_POINTER,
515 signals[ZONE_IN] = g_signal_new ("zone-in",
516 G_TYPE_FROM_CLASS (klass),
519 G_STRUCT_OFFSET (LocationHybridClass, zone_in),
521 location_VOID__UINT_POINTER_POINTER,
527 signals[ZONE_OUT] = g_signal_new ("zone-out",
528 G_TYPE_FROM_CLASS (klass),
531 G_STRUCT_OFFSET (LocationHybridClass, zone_out),
533 location_VOID__UINT_POINTER_POINTER,
539 properties[PROP_METHOD_TYPE] = g_param_spec_int ("method",
541 "location method type name",
542 LOCATION_METHOD_HYBRID,
543 LOCATION_METHOD_HYBRID,
544 LOCATION_METHOD_HYBRID,
547 properties[PROP_LAST_POSITION] = g_param_spec_boxed ("last-position",
548 "hybrid last position prop",
549 "hybrid last position data",
550 LOCATION_TYPE_POSITION,
553 properties[PROP_UPDATE_INTERVAL] = g_param_spec_uint ("update-interval",
554 "update interval prop",
555 "update interval data",
556 LOCATION_UPDATE_INTERVAL_MIN,
557 LOCATION_UPDATE_INTERVAL_MAX,
558 LOCATION_UPDATE_INTERVAL_DEFAULT,
561 properties[PROP_BOUNDARY] = g_param_spec_pointer ("boundary",
562 "hybrid boundary prop",
563 "hybrid boundary data",
566 properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary",
567 "hybrid removal boundary prop",
568 "hybrid removal boundary data",
569 LOCATION_TYPE_BOUNDARY,
572 g_object_class_install_properties (gobject_class,