From 8844d894be764f9924fea5a9415f9203b97c02a3 Mon Sep 17 00:00:00 2001 From: Jinkun Jang Date: Wed, 13 Mar 2013 01:48:44 +0900 Subject: [PATCH] Tizen 2.1 base --- AUTHORS | 3 + LICENSE | 204 ++ Makefile.am | 6 + TC/_export_env.sh | 8 + TC/_export_target_env.sh | 7 + TC/build.sh | 16 + TC/config | 2 + TC/excute.sh | 16 + TC/making_new_tet_scen.py | 69 + TC/tet_scen | 33 + TC/tetbuild.cfg | 5 + TC/tetclean.cfg | 5 + TC/tetexec.cfg | 5 + TC/unit/Makefile | 72 + TC/unit/stc_gps_nmea.c | 175 ++ TC/unit/stc_gps_position.c | 197 ++ TC/unit/stc_gps_satellite.c | 177 ++ TC/unit/stc_gps_velocity.c | 186 ++ TC/unit/stc_gps_zone.c | 306 +++ TC/unit/tslist | 28 + TC/unit/utc_location_free.c | 85 + TC/unit/utc_location_get_address.c | 119 + TC/unit/utc_location_get_address_from_position.c | 126 + TC/unit/utc_location_get_last_known_position.c | 76 + TC/unit/utc_location_get_last_position.c | 100 + TC/unit/utc_location_get_last_satellite.c | 89 + TC/unit/utc_location_get_last_velocity.c | 105 + TC/unit/utc_location_get_position.c | 128 + TC/unit/utc_location_get_position_from_address.c | 153 ++ ...location_get_position_from_freeformed_address.c | 148 + TC/unit/utc_location_get_satellite.c | 112 + TC/unit/utc_location_get_velocity.c | 128 + TC/unit/utc_location_init.c | 55 + TC/unit/utc_location_new.c | 70 + TC/unit/utc_location_search_poi.c | 400 +++ TC/unit/utc_location_start.c | 76 + TC/unit/utc_location_stop.c | 78 + TC/unit/utc_properties_boundary.c | 114 + TC/unit/utc_properties_method.c | 60 + TC/unit/utc_signals_service_disabled.c | 91 + TC/unit/utc_signals_service_enabled.c | 81 + TC/unit/utc_signals_service_updated.c | 83 + TC/unit/utc_signals_zone_in.c | 93 + TC/unit/utc_signals_zone_out.c | 95 + autogen.sh | 21 + configure.ac | 89 + image/SLP_Location_PG.h | 20 + image/location_image001.png | Bin 0 -> 133313 bytes image/location_image002.png | Bin 0 -> 138108 bytes libslp-location.manifest | 5 + location.pc.in | 13 + location/Makefile.am | 50 + location/include/location-log.h | 65 + location/include/location-map-types.h | 296 ++ location/include/location-types.h | 132 + location/manager/Makefile.am | 41 + location/manager/location-accuracy.c | 105 + location/manager/location-accuracy.h | 139 + location/manager/location-boundary.c | 458 ++++ location/manager/location-boundary.h | 316 +++ location/manager/location-common-util.c | 334 +++ location/manager/location-common-util.h | 66 + location/manager/location-cps.c | 748 ++++++ location/manager/location-cps.h | 64 + location/manager/location-gps.c | 954 +++++++ location/manager/location-gps.h | 65 + location/manager/location-hybrid.c | 1067 ++++++++ location/manager/location-hybrid.h | 66 + location/manager/location-ielement.c | 177 ++ location/manager/location-ielement.h | 94 + location/manager/location-marshal.list | 3 + location/manager/location-position.c | 202 ++ location/manager/location-position.h | 176 ++ location/manager/location-satellite.c | 139 + location/manager/location-satellite.h | 143 + location/manager/location-setting.c | 101 + location/manager/location-setting.h | 59 + location/manager/location-signaling-util.c | 164 ++ location/manager/location-signaling-util.h | 54 + location/manager/location-velocity.c | 91 + location/manager/location-velocity.h | 111 + location/manager/location-wps.c | 783 ++++++ location/manager/location-wps.h | 64 + location/manager/location.c | 370 +++ location/manager/location.h | 879 ++++++ location/map-service/Makefile.am | 28 + location/map-service/location-address.c | 104 + location/map-service/location-address.h | 108 + location/map-service/location-geocode.c | 27 + location/map-service/location-geocode.h | 39 + location/map-service/location-landmark-ext.h | 247 ++ location/map-service/location-landmark.c | 528 ++++ location/map-service/location-landmark.h | 147 + location/map-service/location-map-ielement.c | 265 ++ location/map-service/location-map-ielement.h | 101 + location/map-service/location-map-pref.c | 222 ++ location/map-service/location-map-pref.h | 116 + location/map-service/location-map-service-ext.h | 40 + location/map-service/location-map-service.c | 384 +++ location/map-service/location-map-service.h | 1287 +++++++++ location/map-service/location-poi.c | 289 ++ location/map-service/location-poi.h | 282 ++ location/map-service/location-route-ext.h | 877 ++++++ location/map-service/location-route.c | 2823 ++++++++++++++++++++ location/map-service/location-route.h | 2057 ++++++++++++++ location/map-service/map-internal.c | 241 ++ location/map-service/map-internal.h | 82 + location/map-service/map-service.c | 340 +++ location/map-service/map-service.h | 71 + location/module/Makefile.am | 20 + location/module/location-module.h | 148 + location/module/module-internal.c | 348 +++ location/module/module-internal.h | 81 + packaging/libslp-location.spec | 94 + tests/Makefile.am | 37 + tests/address-sample.c | 213 ++ tests/cps-test.c | 67 + tests/gps-test.c | 243 ++ tests/hybrid-test.c | 205 ++ tests/location-api-test-util.c | 205 ++ tests/location-api-test-util.h | 42 + tests/location-api-test.c | 847 ++++++ tests/location-api-test.json | 220 ++ tests/map-service-test.c | 1585 +++++++++++ tests/nmea-sample.c | 100 + tests/position-sample-gps.c | 126 + tests/property-sample.c | 119 + tests/satellite-sample.c | 114 + tests/velocity-sample.c | 117 + tests/wps-test.c | 201 ++ tests/zone-sample.c | 131 + 131 files changed, 28877 insertions(+) create mode 100644 AUTHORS create mode 100644 LICENSE create mode 100644 Makefile.am create mode 100755 TC/_export_env.sh create mode 100644 TC/_export_target_env.sh create mode 100755 TC/build.sh create mode 100644 TC/config create mode 100755 TC/excute.sh create mode 100755 TC/making_new_tet_scen.py create mode 100644 TC/tet_scen create mode 100644 TC/tetbuild.cfg create mode 100644 TC/tetclean.cfg create mode 100644 TC/tetexec.cfg create mode 100644 TC/unit/Makefile create mode 100644 TC/unit/stc_gps_nmea.c create mode 100644 TC/unit/stc_gps_position.c create mode 100644 TC/unit/stc_gps_satellite.c create mode 100644 TC/unit/stc_gps_velocity.c create mode 100644 TC/unit/stc_gps_zone.c create mode 100644 TC/unit/tslist create mode 100644 TC/unit/utc_location_free.c create mode 100644 TC/unit/utc_location_get_address.c create mode 100644 TC/unit/utc_location_get_address_from_position.c create mode 100644 TC/unit/utc_location_get_last_known_position.c create mode 100644 TC/unit/utc_location_get_last_position.c create mode 100644 TC/unit/utc_location_get_last_satellite.c create mode 100644 TC/unit/utc_location_get_last_velocity.c create mode 100644 TC/unit/utc_location_get_position.c create mode 100644 TC/unit/utc_location_get_position_from_address.c create mode 100644 TC/unit/utc_location_get_position_from_freeformed_address.c create mode 100644 TC/unit/utc_location_get_satellite.c create mode 100644 TC/unit/utc_location_get_velocity.c create mode 100644 TC/unit/utc_location_init.c create mode 100644 TC/unit/utc_location_new.c create mode 100644 TC/unit/utc_location_search_poi.c create mode 100644 TC/unit/utc_location_start.c create mode 100644 TC/unit/utc_location_stop.c create mode 100644 TC/unit/utc_properties_boundary.c create mode 100644 TC/unit/utc_properties_method.c create mode 100644 TC/unit/utc_signals_service_disabled.c create mode 100644 TC/unit/utc_signals_service_enabled.c create mode 100644 TC/unit/utc_signals_service_updated.c create mode 100644 TC/unit/utc_signals_zone_in.c create mode 100644 TC/unit/utc_signals_zone_out.c create mode 100755 autogen.sh create mode 100755 configure.ac create mode 100755 image/SLP_Location_PG.h create mode 100644 image/location_image001.png create mode 100644 image/location_image002.png create mode 100644 libslp-location.manifest create mode 100644 location.pc.in create mode 100755 location/Makefile.am create mode 100644 location/include/location-log.h create mode 100644 location/include/location-map-types.h create mode 100644 location/include/location-types.h create mode 100644 location/manager/Makefile.am create mode 100644 location/manager/location-accuracy.c create mode 100644 location/manager/location-accuracy.h create mode 100644 location/manager/location-boundary.c create mode 100644 location/manager/location-boundary.h create mode 100644 location/manager/location-common-util.c create mode 100644 location/manager/location-common-util.h create mode 100644 location/manager/location-cps.c create mode 100644 location/manager/location-cps.h create mode 100644 location/manager/location-gps.c create mode 100644 location/manager/location-gps.h create mode 100644 location/manager/location-hybrid.c create mode 100644 location/manager/location-hybrid.h create mode 100644 location/manager/location-ielement.c create mode 100644 location/manager/location-ielement.h create mode 100644 location/manager/location-marshal.list create mode 100644 location/manager/location-position.c create mode 100644 location/manager/location-position.h create mode 100644 location/manager/location-satellite.c create mode 100644 location/manager/location-satellite.h create mode 100644 location/manager/location-setting.c create mode 100644 location/manager/location-setting.h create mode 100644 location/manager/location-signaling-util.c create mode 100644 location/manager/location-signaling-util.h create mode 100644 location/manager/location-velocity.c create mode 100644 location/manager/location-velocity.h create mode 100644 location/manager/location-wps.c create mode 100644 location/manager/location-wps.h create mode 100644 location/manager/location.c create mode 100644 location/manager/location.h create mode 100644 location/map-service/Makefile.am create mode 100644 location/map-service/location-address.c create mode 100644 location/map-service/location-address.h create mode 100644 location/map-service/location-geocode.c create mode 100644 location/map-service/location-geocode.h create mode 100644 location/map-service/location-landmark-ext.h create mode 100644 location/map-service/location-landmark.c create mode 100644 location/map-service/location-landmark.h create mode 100644 location/map-service/location-map-ielement.c create mode 100644 location/map-service/location-map-ielement.h create mode 100644 location/map-service/location-map-pref.c create mode 100644 location/map-service/location-map-pref.h create mode 100644 location/map-service/location-map-service-ext.h create mode 100644 location/map-service/location-map-service.c create mode 100644 location/map-service/location-map-service.h create mode 100644 location/map-service/location-poi.c create mode 100644 location/map-service/location-poi.h create mode 100644 location/map-service/location-route-ext.h create mode 100644 location/map-service/location-route.c create mode 100644 location/map-service/location-route.h create mode 100644 location/map-service/map-internal.c create mode 100644 location/map-service/map-internal.h create mode 100644 location/map-service/map-service.c create mode 100644 location/map-service/map-service.h create mode 100644 location/module/Makefile.am create mode 100644 location/module/location-module.h create mode 100644 location/module/module-internal.c create mode 100644 location/module/module-internal.h create mode 100755 packaging/libslp-location.spec create mode 100644 tests/Makefile.am create mode 100644 tests/address-sample.c create mode 100644 tests/cps-test.c create mode 100644 tests/gps-test.c create mode 100644 tests/hybrid-test.c create mode 100644 tests/location-api-test-util.c create mode 100644 tests/location-api-test-util.h create mode 100644 tests/location-api-test.c create mode 100644 tests/location-api-test.json create mode 100755 tests/map-service-test.c create mode 100644 tests/nmea-sample.c create mode 100644 tests/position-sample-gps.c create mode 100644 tests/property-sample.c create mode 100644 tests/satellite-sample.c create mode 100644 tests/velocity-sample.c create mode 100644 tests/wps-test.c create mode 100644 tests/zone-sample.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..a879250 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,3 @@ +Youngae Kang +Minjune Kim +Genie Kim diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9c13a9b --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..f227da9 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,6 @@ +ACLOCAL_AMFLAGS=-I m4 + +SUBDIRS=location + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = location.pc diff --git a/TC/_export_env.sh b/TC/_export_env.sh new file mode 100755 index 0000000..72a11ec --- /dev/null +++ b/TC/_export_env.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +. ./config +export TET_INSTALL_PATH=$TET_INSTALL_HOST_PATH # tetware root path +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target # tetware target path +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH +export TET_ROOT=$TET_TARGET_PATH diff --git a/TC/_export_target_env.sh b/TC/_export_target_env.sh new file mode 100644 index 0000000..5ddaa53 --- /dev/null +++ b/TC/_export_target_env.sh @@ -0,0 +1,7 @@ +#!/bin/sh +. ./config +export TET_INSTALL_PATH=$TET_INSTALL_TARGET_PATH # path to path +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH +export TET_ROOT=$TET_TARGET_PATH diff --git a/TC/build.sh b/TC/build.sh new file mode 100755 index 0000000..72aad6c --- /dev/null +++ b/TC/build.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +. ./_export_env.sh # setting environment variables + +export TET_SUITE_ROOT=`pwd` +FILE_NAME_EXTENSION=`date +%s` + +RESULT_DIR=results +HTML_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.html +JOURNAL_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.journal + +mkdir -p $RESULT_DIR + +tcc -c -p ./ +tcc -b -j $JOURNAL_RESULT -p ./ +grw -c 7 -f chtml -o $HTML_RESULT $JOURNAL_RESULT diff --git a/TC/config b/TC/config new file mode 100644 index 0000000..ba387c7 --- /dev/null +++ b/TC/config @@ -0,0 +1,2 @@ +TET_INSTALL_HOST_PATH=/home/june/SBS2/work/tetware/TETware +TET_INSTALL_TARGET_PATH=/mnt/nfs/SBS2/work/tetware/TETware diff --git a/TC/excute.sh b/TC/excute.sh new file mode 100755 index 0000000..2c6167e --- /dev/null +++ b/TC/excute.sh @@ -0,0 +1,16 @@ +. ./_export_target_env.sh # setting environment variables + +echo PATH=$PATH +echo LD_LIBRARY_PATH=$LD_LIBRARY_PATH +echo TET_ROOT=$TET_ROOT +echo TET_SUITE_ROOT=$TET_SUITE_ROOT +echo ARCH=$ARCH + +RESULT_DIR=results-$ARCH +HTML_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.html +JOURNAL_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.journal + +mkdir $RESULT_DIR + +tcc -e -j $JOURNAL_RESULT -p ./ # executing tcc, with –e option +grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT # reporting the result diff --git a/TC/making_new_tet_scen.py b/TC/making_new_tet_scen.py new file mode 100755 index 0000000..6c5b845 --- /dev/null +++ b/TC/making_new_tet_scen.py @@ -0,0 +1,69 @@ +#!/usr/bin/python + +############################################# +# tet_scen auto generator +# +# ** argv[1] = TC root +############################################# + +import sys,string,os + + +write_file = open("tet_scen", 'w') + +# +# making new tet_scen +# +def making_tet_scen (filename): + #tmp_list = filename.strip().split('/') + n_filename = filename.replace(' ', '\\ ') + #print n_filename + #new_path = "/"+ sys.argv[1] +"/"+n_filename[2:-6] + new_path = "/"+n_filename[:-6] + #print new_path + file = open(filename, 'r') + lines = file.readlines() + for line in lines: + if len(line.strip()) > 1: + list = line.strip().split('/') + #print new_path + list[-1] + write_file.write("\t"+new_path+list[-1]+"\n") + +# +# usage() +# +def usage(): + print(" ") + print("./making_new_tet_scen.py tc_root") + print("Put the Test Case's root directory.") + print("Do not include '/' at the end") + print(" ") + +# +# main() +# +def main(): + if len(sys.argv) < 2: + usage() + sys.exit(0) + + os.system('find '+ sys.argv[1] +' -name "tslist" > tslist.txt') + + #write_file = open("tetscen", w) + write_file.write("# auto generated tet_scen\n") + write_file.write("all\n") + write_file.write("\t\"Starting Full Test Suite\"\n") + + for file in open("tslist.txt", 'r'): + #print file.strip() + making_tet_scen(file.strip()) + + write_file.write("\t\"Completed Full Test Suite\"\n") + write_file.write("# EOF\n") + write_file.close() + print(" ") + print("==============================") + print("New tet_scen file is made~~~~") + print("==============================") + print(" ") +main() diff --git a/TC/tet_scen b/TC/tet_scen new file mode 100644 index 0000000..bf662fc --- /dev/null +++ b/TC/tet_scen @@ -0,0 +1,33 @@ +# auto generated tet_scen +all + "Starting Full Test Suite" + /unit/stc_gps_nmea + /unit/stc_gps_position + /unit/stc_gps_satellite + /unit/stc_gps_velocity + /unit/stc_gps_zone + /unit/utc_location_free + /unit/utc_location_get_address + /unit/utc_location_get_last_known_position + /unit/utc_location_get_address_from_position + /unit/utc_location_get_position_from_address + /unit/utc_location_get_position_from_freeformed_address + /unit/utc_location_get_position + /unit/utc_location_get_last_position + /unit/utc_location_get_velocity + /unit/utc_location_get_last_velocity + /unit/utc_location_get_satellite + /unit/utc_location_get_last_satellite + /unit/utc_location_search_poi + /unit/utc_location_init + /unit/utc_location_new + /unit/utc_location_start + /unit/utc_location_stop + /unit/utc_properties_method + /unit/utc_signals_service_disabled + /unit/utc_signals_service_enabled + /unit/utc_signals_service_updated + /unit/utc_signals_zone_in + /unit/utc_signals_zone_out + "Completed Full Test Suite" +# EOF diff --git a/TC/tetbuild.cfg b/TC/tetbuild.cfg new file mode 100644 index 0000000..f7eda55 --- /dev/null +++ b/TC/tetbuild.cfg @@ -0,0 +1,5 @@ +TET_OUTPUT_CAPTURE=True # capture option for build operation checking +TET_BUILD_TOOL=make # build with using make command +TET_BUILD_FILE=-f Makefile # execution file (Makefile) for build +TET_API_COMPLIANT=True # use TET API in Test Case ? +TET_PASS_TC_NAME=True # report passed TC name in Journal file? diff --git a/TC/tetclean.cfg b/TC/tetclean.cfg new file mode 100644 index 0000000..02d7030 --- /dev/null +++ b/TC/tetclean.cfg @@ -0,0 +1,5 @@ +TET_OUTPUT_CAPTURE=True # capture option +TET_CLEAN_TOOL= make clean # clean tool +TET_CLEAN_FILE= Makefile # file for clean +TET_API_COMPLIANT=True # TET API useage +TET_PASS_TC_NAME=True # showing name , passed TC diff --git a/TC/tetexec.cfg b/TC/tetexec.cfg new file mode 100644 index 0000000..ef3e452 --- /dev/null +++ b/TC/tetexec.cfg @@ -0,0 +1,5 @@ +TET_OUTPUT_CAPTURE=True # capturing execution or not +TET_EXEC_TOOL= # ex) exec : execution tool set up/ Optional +TET_EXEC_FILE= # ex) exectool : execution file/ Optional +TET_API_COMPLIANT=True # Test case or Tool usesTET API? +TET_PASS_TC_NAME=True # showing Passed TC name ? diff --git a/TC/unit/Makefile b/TC/unit/Makefile new file mode 100644 index 0000000..62fc0c8 --- /dev/null +++ b/TC/unit/Makefile @@ -0,0 +1,72 @@ +################################################### +# add your TestCase List Here +# +# e.g., +# TC1 = utc_frameworkName_apiName_func +# TC2 = utc_ApplicationLib_recurGetDayOfWeek_func +TC1 = stc_gps_position +TC2 = stc_gps_velocity +TC3 = stc_gps_satellite +TC4 = stc_gps_nmea +TC5 = stc_gps_zone +TC6 = utc_location_init +TC7 = utc_location_new +TC8 = utc_location_start +TC9 = utc_location_stop +TC10 = utc_location_free +TC11 = utc_location_get_position +TC12 = utc_location_get_last_position +TC13 = utc_location_get_last_known_position +TC14 = utc_location_get_velocity +TC15 = utc_location_get_last_velocity +TC16 = utc_location_get_satellite +TC17 = utc_location_get_last_satellite +TC18 = utc_properties_method +TC19 = utc_signals_service_disabled +TC20 = utc_signals_service_enabled +TC21 = utc_signals_service_updated +TC22 = utc_signals_zone_in +TC23 = utc_signals_zone_out +TC24 = utc_location_get_address +TC25 = utc_location_get_address_from_position +TC26 = utc_location_get_position_from_address +TC27 = utc_location_get_position_from_freeformed_address +TC28 = utc_location_search_poi + +# +# add your Package Config Info Here +# +# e.g., +# PKGS=calendar +PKGS= gconf-2.0 network vconf location + +LDLIBS = $(TET_ROOT)/lib/tet3/tcm_s.o +LDLIBS += -L$(TET_ROOT)/lib/tet3 -ltcm_s +LDLIBS += -L$(TET_ROOT)/lib/tet3 -lapi_s +LDLIBS += `pkg-config --libs $(PKGS)` + +TTLIBS = $(TET_ROOT)/lib/tet3/tcm_s.o +TTLIBS += -L$(TET_ROOT)/lib/tet3 -ltcm_s +TTLIBS += -L$(TET_ROOT)/lib/tet3 -lapi_s +TTLIBS += `pkg-config --libs $(PKGS)` + +CC = gcc +INCS = -I$(TET_ROOT)/inc/tet3 +INCS += -I.`pkg-config --cflags $(PKGS)` +CFLAGS = -Wall -D_TETWARE_MODE +CFLAGS += $(INCS) + +################################################### +# Modify here +# depending on the Test Case you want to build +# +# e.g., +# +TCLIST = $(TC1) $(TC2) $(TC3) $(TC4) $(TC5) $(TC6) $(TC7) $(TC8) $(TC9) $(TC10) $(TC11) $(TC12) $(TC13) $(TC14) $(TC16) $(TC17) $(TC18) $(TC19) $(TC20) $(TC21) $(TC22) $(TC23) $(TC24) $(TC25) $(TC26) $(TC27) $(TC28) + +all: $(TCLIST) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +clean: + rm -f $(TCLIST) + rm -f *.o diff --git a/TC/unit/stc_gps_nmea.c b/TC/unit/stc_gps_nmea.c new file mode 100644 index 0000000..8408eb5 --- /dev/null +++ b/TC/unit/stc_gps_nmea.c @@ -0,0 +1,175 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_init(); +static void utc_location_new(); +static void utc_location_start(); +static void utc_get_method(); +static void utc_get_devname(); +static void utc_location_get_nmea(); +static void utc_location_svc_disabled(); +static void utc_location_free(); + + +struct tet_testlist tet_testlist[] = { + {utc_location_init,1}, + {utc_location_new,1}, + {utc_location_start,1}, + {utc_get_method,1}, + {utc_get_devname,1}, + {utc_location_get_nmea,1}, + {utc_location_svc_disabled,1}, + {utc_location_free,1}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + + +static void startup() +{ + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + tet_printf("\n TC End"); +} + +static void +utc_location_init() +{ + ret = location_init(); + if(ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_new() +{ + loc = location_new(LOCATION_METHOD_GPS); + if (loc) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_start() +{ + ret = location_start(loc); + if(ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_get_method() +{ + LocationMethod method; + g_object_get(loc, "method", &method, NULL); + if (LOCATION_METHOD_HYBRID <= method && method<= LOCATION_METHOD_WPS) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_get_devname() +{ + char* devname = NULL; + g_object_get(loc, "dev-name", &devname, NULL); + if(devname){ + tet_result(TET_PASS); + g_free(devname); + } else tet_result(TET_FAIL); +} + +static void +_get_nmea (GObject *self, + guint _status, + gpointer userdata) +{ + char* nmea_data; + g_object_get(loc, "nmea", &nmea_data, NULL); + if (nmea_data) { + tet_result(TET_PASS); + g_free(nmea_data); + } else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +static void +utc_location_get_nmea() +{ + loop = g_main_loop_new (NULL, TRUE); + g_signal_connect (loc, "service-updated", G_CALLBACK(_get_nmea), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + +static void +_cb_disabled (GObject *self, + guint _status, + gpointer userdata) +{ + if( LOCATION_STATUS_NO_FIX <= _status && _status <= LOCATION_STATUS_3D_FIX) tet_result(TET_PASS); + else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +gboolean +_stop_location() +{ + location_stop(loc); + return FALSE; +} + +static void +utc_location_svc_disabled() +{ + g_signal_connect (loc, "service-disabled", G_CALLBACK(_cb_disabled), loc); + g_timeout_add_seconds(1, _stop_location, NULL); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); + +} + +static void +utc_location_free() +{ + ret = location_free(loc); + if(ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/stc_gps_position.c b/TC/unit/stc_gps_position.c new file mode 100644 index 0000000..8cb4c2a --- /dev/null +++ b/TC/unit/stc_gps_position.c @@ -0,0 +1,197 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_init(); +static void utc_location_new(); +static void utc_location_start(); +static void utc_get_method(); +static void utc_get_devname(); +static void utc_location_get_position(); +static void utc_location_svc_updated(); +static void utc_location_stop(); +static void utc_get_lastpostion(); +static void utc_location_free(); + + +struct tet_testlist tet_testlist[] = { + {utc_location_init,1}, + {utc_location_new,1}, + {utc_location_start,1}, + {utc_get_method,1}, + {utc_get_devname,1}, + {utc_location_get_position,1}, + {utc_location_svc_updated,1}, + {utc_location_stop,1}, + {utc_get_lastpostion,1}, + {utc_location_free,1}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +static gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + + +static void startup() +{ + tet_printf("\n TC startup"); + loop = g_main_loop_new (NULL, TRUE); +} + +static void cleanup() +{ + tet_printf("\n TC End"); +} + +static void +utc_location_init() +{ + ret = location_init(); + if(ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_new() +{ + loc = location_new(LOCATION_METHOD_GPS); + if (loc) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_start() +{ + ret = location_start(loc); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_get_method() +{ + LocationMethod method; + g_object_get(loc, "method", &method, NULL); + + if(LOCATION_METHOD_HYBRID <= method && method<= LOCATION_METHOD_WPS) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_get_devname() +{ + char* devname = NULL; + g_object_get(loc, "dev-name", &devname, NULL); + + if (devname) { + tet_result(TET_PASS); + g_free(devname); + } else tet_result(TET_FAIL); +} + +static void +utc_get_lastpostion() +{ + LocationPosition *pos = NULL; + g_object_get(loc, "last-position", &pos, NULL); + + if (pos) { + tet_result(TET_PASS); + location_position_free (pos); + } else tet_result(TET_FAIL); +} + +static void +_get_position (GObject *self, + guint _status, + gpointer userdata) +{ + LocationAccuracy *acc = NULL; + LocationPosition *pos = NULL; + LocationObject *loc = (LocationObject*)userdata; + + ret = location_get_position (loc, &pos, &acc); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); + + g_main_loop_quit (loop); +} + +static void +utc_location_get_position() +{ + g_signal_connect (loc, "service-enabled", G_CALLBACK(_get_position), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + +static void +utc_location_stop() +{ + ret = location_stop(loc); + + if(ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +_cb_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + if ( POSITION_UPDATED <= type && type <= REVERSEGEOCODE_UPDATED) tet_result(TET_PASS); + else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +static void +utc_location_svc_updated() +{ + g_signal_connect (loc, "service-updated", G_CALLBACK(_cb_updated), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + +static void +utc_location_free() +{ + ret = location_free(loc); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/stc_gps_satellite.c b/TC/unit/stc_gps_satellite.c new file mode 100644 index 0000000..60c349b --- /dev/null +++ b/TC/unit/stc_gps_satellite.c @@ -0,0 +1,177 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_init(); +static void utc_location_new(); +static void utc_location_start(); +static void utc_get_method(); +static void utc_get_devname(); +static void utc_location_get_satellite(); +static void utc_location_svc_disabled(); +static void utc_location_free(); + + +struct tet_testlist tet_testlist[] = { + {utc_location_init,1}, + {utc_location_new,1}, + {utc_location_start,1}, + {utc_get_method,1}, + {utc_get_devname,1}, + {utc_location_get_satellite,1}, + {utc_location_svc_disabled,1}, + {utc_location_free,1}, + {NULL,0}, +}; + + + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + tet_printf("\n TC End"); +} + +static void +utc_location_init() +{ + ret = location_init(); + if(ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_new() +{ + loc = location_new(LOCATION_METHOD_GPS); + if(loc) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_start() +{ + ret = location_start(loc); + if(ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_get_method() +{ + LocationMethod method; + g_object_get(loc, "method", &method, NULL); + if (LOCATION_METHOD_HYBRID <= method && method<= LOCATION_METHOD_WPS) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_get_devname() +{ + char* devname = NULL; + g_object_get(loc, "dev-name", &devname, NULL); + if (devname) { + tet_result(TET_PASS); + g_free(devname); + } else tet_result(TET_FAIL); +} + +static void +_get_satellite (GObject *self, + guint _status, + gpointer userdata) +{ + LocationSatellite *sat = NULL; + int ret = 0; + + ret = location_get_satellite (loc, &sat); + if (ret == LOCATION_ERROR_NONE) { + tet_result(TET_PASS); + location_satellite_free (sat); + } else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +static void +utc_location_get_satellite() +{ + loop = g_main_loop_new (NULL, TRUE); + g_signal_connect (loc, "service-enabled", G_CALLBACK(_get_satellite), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + +static void +_cb_disabled (GObject *self, + guint _status, + gpointer userdata) +{ + if( LOCATION_STATUS_NO_FIX <= _status && _status <= LOCATION_STATUS_3D_FIX) tet_result(TET_PASS); + else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +gboolean +_stop_location() +{ + location_stop(loc); + return FALSE; +} + +static void +utc_location_svc_disabled() +{ + g_signal_connect (loc, "service-disabled", G_CALLBACK(_cb_disabled), loc); + g_timeout_add_seconds(1, _stop_location, NULL); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + +static void +utc_location_free() +{ + ret = location_free(loc); + if(ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/stc_gps_velocity.c b/TC/unit/stc_gps_velocity.c new file mode 100644 index 0000000..9770767 --- /dev/null +++ b/TC/unit/stc_gps_velocity.c @@ -0,0 +1,186 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_init(); +static void utc_location_new(); +static void utc_location_start(); +static void utc_get_method(); +static void utc_get_devname(); +static void utc_location_get_velocity(); +static void utc_location_stop(); +static void utc_location_svc_updated(); +static void utc_location_free(); + +struct tet_testlist tet_testlist[] = { + {utc_location_init,1}, + {utc_location_new,1}, + {utc_location_start,1}, + {utc_get_method,1}, + {utc_get_devname,1}, + {utc_location_get_velocity,1}, + {utc_location_svc_updated,1}, + {utc_location_stop,1}, + {utc_location_free,1}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +static gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + tet_printf("\n TC End"); +} + +static void +utc_location_init() +{ + ret = location_init(); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_new() +{ + loc = location_new(LOCATION_METHOD_GPS); + if (loc) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_start() +{ + ret = location_start(loc); + + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_get_method() +{ + LocationMethod method; + g_object_get(loc, "method", &method, NULL); + + if (LOCATION_METHOD_HYBRID <= method && method<= LOCATION_METHOD_WPS) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_get_devname() +{ + char* devname = NULL; + g_object_get(loc, "dev-name", &devname, NULL); + + if(devname){ + tet_result(TET_PASS); + g_free(devname); + } else tet_result(TET_FAIL); +} + +static void +_get_velocity (GObject *self, + guint _status, + gpointer userdata) +{ + LocationVelocity *vel = NULL; + LocationAccuracy *acc = NULL; + LocationObject *loc = (LocationObject*)userdata; + + ret = location_get_velocity (loc, &vel, &acc); + if (ret == LOCATION_ERROR_NONE) { + location_velocity_free (vel); + location_accuracy_free (acc); + tet_result(TET_PASS); + } + else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +static void +utc_location_get_velocity() +{ + loop = g_main_loop_new (NULL, TRUE); + + g_signal_connect (loc, "service-enabled", G_CALLBACK(_get_velocity), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + +static void +utc_location_stop() +{ + ret = location_stop(loc); + + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +_cb_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + if ( POSITION_UPDATED <= type && type <= REVERSEGEOCODE_UPDATED) tet_result(TET_PASS); + else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +static void +utc_location_svc_updated() +{ + g_signal_connect (loc, "service-updated", G_CALLBACK(_cb_updated), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + +static void +utc_location_free() +{ + ret = location_free(loc); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/stc_gps_zone.c b/TC/unit/stc_gps_zone.c new file mode 100644 index 0000000..39110fc --- /dev/null +++ b/TC/unit/stc_gps_zone.c @@ -0,0 +1,306 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static gboolean g_is_found = FALSE; + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_init(); +static void utc_location_new(); +static void utc_location_start(); +static void utc_get_method(); +static void utc_get_devname(); +static void utc_location_svc_enabled(); +static void utc_set_boundary_in_suwonHQ(); +static void utc_get_boundary_in_suwonHQ(); +static void utc_zone_in(); +static void utc_set_boundary_in_Santorini(); +static void utc_get_boundary_in_Santorini(); +static void utc_zone_out(); +static void utc_location_stop(); +static void utc_location_free(); + + +struct tet_testlist tet_testlist[] = { + {utc_location_init,1}, + {utc_location_new,1}, + {utc_location_start,1}, + {utc_get_method,1}, + {utc_get_devname,1}, + {utc_location_svc_enabled,1}, + {utc_set_boundary_in_suwonHQ,1}, + {utc_get_boundary_in_suwonHQ,1}, + {utc_zone_in,1}, + {utc_set_boundary_in_Santorini,1}, + {utc_get_boundary_in_Santorini,1}, + {utc_zone_out,1}, + {utc_location_stop,1}, + {utc_location_free,1}, + {NULL,0}, +}; + + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +static void comp_boundary(LocationBoundary *bound, gpointer user_data) +{ + LocationBoundary *check_bound = (LocationBoundary *) user_data; + + if(bound && bound->type == check_bound->type) { + switch(bound->type) { + case LOCATION_BOUNDARY_RECT: + if(bound->rect.right_bottom->latitude == check_bound->rect.right_bottom->latitude && + bound->rect.right_bottom->longitude == check_bound->rect.right_bottom->longitude && + bound->rect.left_top->latitude == check_bound->rect.left_top->latitude && + bound->rect.left_top->longitude == check_bound->rect.left_top->longitude ){ + g_is_found = TRUE; + } + break; + default: + break; + } + } +} + + +static gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + tet_printf("\n TC startup"); + loop = g_main_loop_new (NULL, TRUE); +} + +static void cleanup() +{ + tet_printf("\n TC End"); +} + +static void +utc_location_init() +{ + ret = location_init(); + if(ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_new() +{ + loc = location_new(LOCATION_METHOD_GPS); + if(loc) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_start() +{ + ret = location_start(loc); + + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_get_method() +{ + LocationMethod method; + g_object_get(loc, "method", &method, NULL); + + if(LOCATION_METHOD_HYBRID <= method && method<= LOCATION_METHOD_WPS) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_get_devname() +{ + char* devname = NULL; + g_object_get(loc, "dev-name", &devname, NULL); + + if(devname){ + tet_result(TET_PASS); + g_free(devname); + } else tet_result(TET_FAIL); +} + +static void +_cb_svc_enabled (GObject *self, + guint _status, + gpointer userdata) +{ + if(LOCATION_STATUS_NO_FIX <= _status && _status <= LOCATION_STATUS_3D_FIX) tet_result(TET_PASS); + else tet_result(TET_FAIL); + g_main_loop_quit(loop); +} + + +static void +utc_location_svc_enabled() +{ + g_signal_connect (loc, "service-enabled", G_CALLBACK(_cb_svc_enabled), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + +static void +utc_set_boundary_in_suwonHQ() +{ + int ret = 0; + LocationPosition *rb = location_position_new(0, 37.253, 127.058, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 37.261, 127.052, 0, LOCATION_STATUS_2D_FIX); + LocationBoundary *bound = location_boundary_new_for_rect(lt, rb); + location_position_free (rb); + location_position_free (lt); + ret = location_boundary_add(loc, bound); + if (!ret) tet_result(TET_PASS); + else tet_result(TET_FAIL); + + location_boundary_free (bound); +} + +static void +utc_get_boundary_in_suwonHQ() +{ + LocationPosition *rb = location_position_new(0, 37.253, 127.058, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 37.261, 127.052, 0, LOCATION_STATUS_2D_FIX); + LocationBoundary *bound = location_boundary_new_for_rect(lt, rb); + location_position_free (rb); + location_position_free (lt); + + g_is_found = FALSE; + location_boundary_foreach(loc, comp_boundary, bound); + if(g_is_found) tet_result(TET_PASS); + else tet_result(TET_FAIL); + + location_boundary_free (bound); +} + +static void +_cb_zone_in(LocationObject *self, + guint type, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + if( (37.253 <= pos->latitude && pos->latitude <= 37.261) && + (127.052 <= pos->longitude && pos->longitude <= 127.058) ) { + tet_result(TET_PASS); // I am in Suwon HQ + } else tet_result(TET_FAIL); + + g_main_loop_quit(loop); +} + +static void +utc_zone_in() +{ + g_signal_connect (loc, "zone-in", G_CALLBACK(_cb_zone_in), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + +static void +utc_set_boundary_in_Santorini() +{ + int ret = 0; + LocationPosition *rb = location_position_new(0, 36.395, 25.41, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 36.413, 25.388, 0, LOCATION_STATUS_2D_FIX); + LocationBoundary* bound = location_boundary_new_for_rect(lt, rb); + location_position_free (rb); + location_position_free (lt); + + ret = location_boundary_add(loc, bound); + if (!ret) tet_result(TET_PASS); + else tet_result(TET_FAIL); + + location_boundary_free (bound); +} + +static void +utc_get_boundary_in_Santorini() +{ + LocationPosition *rb = location_position_new(0, 36.395, 25.41, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 36.413, 25.388, 0, LOCATION_STATUS_2D_FIX); + LocationBoundary* bound = location_boundary_new_for_rect(lt, rb); + location_position_free (rb); + location_position_free (lt); + + g_is_found = FALSE; + location_boundary_foreach(loc, comp_boundary, bound); + if(g_is_found) tet_result(TET_PASS); + else tet_result(TET_FAIL); + + location_boundary_free (bound); +} + +static void +_cb_zone_out(LocationObject *self, + guint type, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + + if( (37.253 <= pos->latitude && pos->latitude <= 37.261) && + (27.052 <= pos->longitude && pos->longitude <= 127.058) ) { + tet_result(TET_PASS); // I am in Suwon HQ + } else tet_result(TET_FAIL); + g_main_loop_quit(loop); +} + + +static void +utc_zone_out() +{ + g_signal_connect (loc, "zone-out", G_CALLBACK(_cb_zone_out), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + +static void +utc_location_stop() +{ + ret = location_stop(loc); + + if(ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_free() +{ + ret = location_free(loc); + if(ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/tslist b/TC/unit/tslist new file mode 100644 index 0000000..6cf5690 --- /dev/null +++ b/TC/unit/tslist @@ -0,0 +1,28 @@ +stc_gps_nmea +stc_gps_position +stc_gps_satellite +stc_gps_velocity +stc_gps_zone +utc_location_free +utc_location_get_address +utc_location_get_last_known_position +utc_location_get_address_from_position +utc_location_get_position_from_address +utc_location_get_position_from_freeformed_address +utc_location_get_position +utc_location_get_last_position +utc_location_get_velocity +utc_location_get_last_velocity +utc_location_get_satellite +utc_location_get_last_satellite +utc_location_search_poi +utc_location_init +utc_location_new +utc_location_start +utc_location_stop +utc_properties_method +utc_signals_service_disabled +utc_signals_service_enabled +utc_signals_service_updated +utc_signals_zone_in +utc_signals_zone_out diff --git a/TC/unit/utc_location_free.c b/TC/unit/utc_location_free.c new file mode 100644 index 0000000..88b5eab --- /dev/null +++ b/TC/unit/utc_location_free.c @@ -0,0 +1,85 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_free_01(); +static void utc_location_free_02(); + +struct tet_testlist tet_testlist[] = { + {utc_location_free_01,1}, + {utc_location_free_02,2}, + {NULL,0}, +}; + +int ret; +LocationObject* loc; + +static void startup() +{ + ret = location_init(); + loc = location_new(LOCATION_METHOD_GPS); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + if(loc) + location_free(loc); + + tet_printf("\n TC End"); +} + +static void +utc_location_free_01() +{ + ret = location_free(loc); + + tet_printf("Returned value: %d", ret); + if(ret == LOCATION_ERROR_NONE){ + tet_result(TET_PASS); + loc = NULL; + } + else{ + tet_result(TET_FAIL); + } +} + +static void +utc_location_free_02() +{ + ret = location_free(NULL); + + tet_printf("Returned value: %d", ret); + if(ret == LOCATION_ERROR_PARAMETER){ + tet_result(TET_PASS); + } + else{ + tet_result(TET_FAIL); + } +} + diff --git a/TC/unit/utc_location_get_address.c b/TC/unit/utc_location_get_address.c new file mode 100644 index 0000000..b46e865 --- /dev/null +++ b/TC/unit/utc_location_get_address.c @@ -0,0 +1,119 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_get_address_01(); +static void utc_location_get_address_02(); +static void utc_location_get_address_03(); + +struct tet_testlist tet_testlist[] = { + {utc_location_get_address_01,1}, + {utc_location_get_address_02,2}, + {utc_location_get_address_03,3}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +LocationObject* loc = NULL; +int ret = LOCATION_ERROR_NONE; +int isNetStarted = 0; + +static gboolean +exit_loop_fail (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + + loop = g_main_loop_new(NULL,FALSE); + + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_stop(loc); + location_free(loc); + tet_printf("\n TC End"); +} + +static void +_get_address (GObject *self, + guint _status, + gpointer userdata) +{ + LocationAccuracy *acc = NULL; + LocationAddress *addr = NULL; + + ret = location_get_address(loc, &addr, &acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE || + ret == LOCATION_ERROR_CONFIGURATION) { + location_address_free(addr); + location_accuracy_free(acc); + tet_result(TET_PASS); + } else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +static void +utc_location_get_address_01() +{ + g_signal_connect (loc, "service-enabled", G_CALLBACK(_get_address), loc); + location_start(loc); + g_timeout_add_seconds(60, exit_loop_fail, loop); + g_main_loop_run (loop); +} + +static void +utc_location_get_address_02() +{ + LocationAccuracy *acc = NULL; + LocationAddress *addr = NULL; + + ret = location_get_address(NULL, &addr, &acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_address_03() +{ + LocationAccuracy *acc = NULL; + ret = location_get_address(loc, NULL, &acc); + tet_printf("Returned value: %d", ret); + if(ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/utc_location_get_address_from_position.c b/TC/unit/utc_location_get_address_from_position.c new file mode 100644 index 0000000..4f68981 --- /dev/null +++ b/TC/unit/utc_location_get_address_from_position.c @@ -0,0 +1,126 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_get_address_from_position_01(); +static void utc_location_get_address_from_position_02(); +static void utc_location_get_address_from_position_03(); +static void utc_location_get_address_from_position_04(); + +struct tet_testlist tet_testlist[] = { + {utc_location_get_address_from_position_01,1}, + {utc_location_get_address_from_position_02,2}, + {utc_location_get_address_from_position_03,3}, + {utc_location_get_address_from_position_04,4}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +LocationObject* loc; +int ret; +int isNetStarted = 0; +int g_state = 0; + +static gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + + loop = g_main_loop_new(NULL,FALSE); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_free(loc); + tet_printf("\n TC End"); +} + +static void +utc_location_get_address_from_position_01() +{ + LocationPosition *pos = location_position_new(0, 37.257809, 127.056383, 0, LOCATION_STATUS_2D_FIX); + LocationAccuracy *acc = NULL; + LocationAddress *addr = NULL; + ret = location_get_address_from_position(loc, pos, &addr, &acc); + location_position_free(pos); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE || + ret == LOCATION_ERROR_CONFIGURATION) { + location_address_free(addr); + location_accuracy_free(acc); + tet_result(TET_PASS); + } else tet_result(TET_FAIL); +} + +static void +utc_location_get_address_from_position_02() +{ + LocationPosition *pos = location_position_new(0, 37.257809, 127.056383, 0, LOCATION_STATUS_2D_FIX); + LocationAccuracy *acc = NULL; + LocationAddress *addr = NULL; + + ret = location_get_address_from_position(NULL, pos, &addr, &acc); + location_position_free(pos); + location_address_free(addr); + location_accuracy_free(acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + + static void +utc_location_get_address_from_position_03() +{ + LocationAccuracy *acc = NULL; + LocationAddress *addr = NULL; + ret = location_get_address_from_position(loc, NULL, &addr, &acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + + static void +utc_location_get_address_from_position_04() +{ + LocationAccuracy *acc = NULL; + LocationPosition *pos = location_position_new(0, 37.257809, 127.056383, 0, LOCATION_STATUS_2D_FIX); + + ret = location_get_address_from_position(loc, pos, NULL, &acc); + location_position_free(pos); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/utc_location_get_last_known_position.c b/TC/unit/utc_location_get_last_known_position.c new file mode 100644 index 0000000..33d5d30 --- /dev/null +++ b/TC/unit/utc_location_get_last_known_position.c @@ -0,0 +1,76 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_get_last_known_position_01(); +static void utc_location_get_last_known_position_02(); + +struct tet_testlist tet_testlist[] = { + {utc_location_get_last_known_position_01,1}, + {utc_location_get_last_known_position_02,2}, + {NULL,0}, +}; + +int ret; +LocationObject* loc; + +static void startup() +{ + ret = location_init(); + loc = location_new(LOCATION_METHOD_GPS); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + if( loc ) + location_free(loc); + tet_printf("\n TC End"); +} + +static void +utc_location_get_last_known_position_01() +{ + int ret = 0; + LocationLastPosition last_known_position = {0, }; + + ret = location_get_last_known_position(loc, LOCATION_METHOD_HYBRID, &last_known_position); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_last_known_position_02() +{ + int ret = 0; + LocationLastPosition last_known_position = {0, }; + ret = location_get_last_known_position(NULL, LOCATION_METHOD_HYBRID, &last_known_position); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + diff --git a/TC/unit/utc_location_get_last_position.c b/TC/unit/utc_location_get_last_position.c new file mode 100644 index 0000000..6bde9c8 --- /dev/null +++ b/TC/unit/utc_location_get_last_position.c @@ -0,0 +1,100 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_get_last_position_01(); +static void utc_location_get_last_position_02(); +static void utc_location_get_last_position_03(); +static void utc_location_get_last_position_04(); + +struct tet_testlist tet_testlist[] = { + {utc_location_get_last_position_01,1}, + {utc_location_get_last_position_02,2}, + {utc_location_get_last_position_03,3}, + {utc_location_get_last_position_04,4}, + {NULL,0}, +}; + +int ret; +LocationObject* loc; + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_free(loc); + tet_printf("\n TC End"); +} + +static void +utc_location_get_last_position_01() +{ + LocationPosition *last_pos = NULL; + LocationAccuracy *last_acc = NULL; + + ret = location_get_last_position (loc, LOCATION_METHOD_GPS, &last_pos, &last_acc); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_last_position_02() +{ + LocationAccuracy *last_acc = NULL; + LocationPosition *last_pos = NULL; + + ret = location_get_last_position (NULL, LOCATION_METHOD_HYBRID, &last_pos, &last_acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_last_position_03() +{ + LocationAccuracy *last_acc = NULL; + ret = location_get_last_position (loc, LOCATION_METHOD_GPS, NULL, &last_acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_last_position_04() +{ + LocationPosition *last_pos = NULL; + ret = location_get_last_position (loc, LOCATION_METHOD_GPS, &last_pos, NULL); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/utc_location_get_last_satellite.c b/TC/unit/utc_location_get_last_satellite.c new file mode 100644 index 0000000..b348298 --- /dev/null +++ b/TC/unit/utc_location_get_last_satellite.c @@ -0,0 +1,89 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_get_last_satellite_01(); +static void utc_location_get_last_satellite_02(); +static void utc_location_get_last_satellite_03(); + +struct tet_testlist tet_testlist[] = { + {utc_location_get_last_satellite_01,1}, + {utc_location_get_last_satellite_02,2}, + {utc_location_get_last_satellite_03,3}, + {NULL,0}, +}; + +int ret; +LocationObject* loc; + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_free(loc); + tet_printf("\n TC End"); +} + +static void +utc_location_get_last_satellite_01() +{ + int ret = 0; + LocationSatellite *last_sat = NULL; + + ret = location_get_last_satellite (loc, &last_sat); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE) { + location_satellite_free(last_sat); + tet_result(TET_PASS); + } else tet_result(TET_FAIL); + +} + +static void +utc_location_get_last_satellite_02() +{ + LocationSatellite *last_sat = NULL; + ret = location_get_last_satellite (NULL, &last_sat); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_last_satellite_03() +{ + ret = location_get_last_satellite (loc, NULL); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/utc_location_get_last_velocity.c b/TC/unit/utc_location_get_last_velocity.c new file mode 100644 index 0000000..c0c10c5 --- /dev/null +++ b/TC/unit/utc_location_get_last_velocity.c @@ -0,0 +1,105 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_get_last_velocity_01(); +static void utc_location_get_last_velocity_02(); +static void utc_location_get_last_velocity_03(); +static void utc_location_get_last_velocity_04(); + +struct tet_testlist tet_testlist[] = { + {utc_location_get_last_velocity_01,1}, + {utc_location_get_last_velocity_02,2}, + {utc_location_get_last_velocity_03,3}, + {utc_location_get_last_velocity_04,4}, + {NULL,0}, +}; + +int ret; +LocationObject* loc; + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_free(loc); + tet_printf("\n TC End"); +} + + +static void +utc_location_get_last_velocity_01() +{ + LocationVelocity *last_vel = NULL; + LocationAccuracy *last_acc = NULL; + ret = location_get_last_velocity (loc, &last_vel, &last_acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE) { + location_velocity_free (last_vel); + location_accuracy_free (last_acc); + tet_result(TET_PASS); + } else tet_result(TET_FAIL); + +} + + +static void +utc_location_get_last_velocity_02() +{ + LocationVelocity *last_vel = NULL; + LocationAccuracy *last_acc = NULL; + ret = location_get_last_velocity (NULL, &last_vel, &last_acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_last_velocity_03() +{ + LocationAccuracy *last_acc = NULL; + ret = location_get_velocity (loc, NULL, &last_acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_last_velocity_04() +{ + LocationVelocity *last_vel = NULL; + ret = location_get_velocity (loc, &last_vel, NULL); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/utc_location_get_position.c b/TC/unit/utc_location_get_position.c new file mode 100644 index 0000000..601e456 --- /dev/null +++ b/TC/unit/utc_location_get_position.c @@ -0,0 +1,128 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_get_position_01(); +static void utc_location_get_position_02(); +static void utc_location_get_position_03(); +static void utc_location_get_position_04(); + +struct tet_testlist tet_testlist[] = { + {utc_location_get_position_01,1}, + {utc_location_get_position_02,2}, + {utc_location_get_position_03,3}, + {utc_location_get_position_04,4}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +static gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + location_start(loc); + loop = g_main_loop_new(NULL,FALSE); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_stop(loc); + location_free(loc); + tet_printf("\n TC End"); +} + +static void +_get_position (GObject *self, + guint _status, + gpointer userdata) +{ + LocationAccuracy *acc = NULL; + LocationPosition *pos = NULL; + LocationObject *loc = (LocationObject*)userdata; + + ret = location_get_position (loc, &pos, &acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE) { + location_position_free (pos); + location_accuracy_free (acc); + tet_result(TET_PASS); + } else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +static void +utc_location_get_position_01() +{ + g_signal_connect (loc, "service-enabled", G_CALLBACK(_get_position), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + +static void +utc_location_get_position_02() +{ + LocationAccuracy *acc = NULL; + LocationPosition *pos = NULL; + + ret = location_get_position (NULL, &pos, &acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_position_03() +{ + LocationAccuracy *acc = NULL; + ret = location_get_position (loc, NULL, &acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_position_04() +{ + LocationPosition *pos = NULL; + ret = location_get_position (loc, &pos, NULL); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/utc_location_get_position_from_address.c b/TC/unit/utc_location_get_position_from_address.c new file mode 100644 index 0000000..89b1789 --- /dev/null +++ b/TC/unit/utc_location_get_position_from_address.c @@ -0,0 +1,153 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_get_position_from_address_01(); +static void utc_location_get_position_from_address_02(); +static void utc_location_get_position_from_address_03(); +static void utc_location_get_position_from_address_04(); + +struct tet_testlist tet_testlist[] = { + {utc_location_get_position_from_address_01,1}, + {utc_location_get_position_from_address_02,2}, + {utc_location_get_position_from_address_03,3}, + {utc_location_get_position_from_address_04,4}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +LocationObject* loc; +int ret; +int isNetStarted = 0; +int g_state = 0; +gboolean is_found = FALSE; + +static gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + + loop = g_main_loop_new(NULL,FALSE); + + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_free(loc); + tet_printf("\n TC End"); +} + +static void comp_position (gpointer data, gpointer user_data) +{ + if (!data) return; + + LocationPosition *pos = (LocationPosition *)data; + + if (pos) { + if (37.325276 <= pos->latitude && pos->latitude <= 37.345276 && + -121.900059 <= pos->longitude && pos->longitude<= -121.880059) { + is_found = TRUE; + } + + location_position_free(pos); + } +} + +static void free_accuracy (gpointer data, gpointer user_data) +{ + if (!data) return; + + LocationAccuracy *acc = (LocationAccuracy *)data; + + if (acc) location_accuracy_free(acc); +} + +static void +utc_location_get_position_from_address_01() +{ + GList *pos_list = NULL; + GList *acc_list = NULL; + LocationAddress *addr = location_address_new ("1", "Post Street", NULL, "san jose", "ca", NULL, "95113",NULL,NULL,NULL); + ret = location_get_position_from_address (loc, addr, &pos_list, &acc_list); + location_address_free(addr); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE) { + is_found = FALSE; + g_list_foreach (pos_list, comp_position, NULL); + g_list_foreach (acc_list, free_accuracy, NULL); + if (is_found) + tet_result(TET_PASS); + else + tet_result(TET_FAIL); + } else tet_result(TET_FAIL); +} + +static void +utc_location_get_position_from_address_02() +{ + GList *pos_list = NULL; + GList *acc_list = NULL; + LocationAddress *addr = location_address_new ("1", "Post Street", NULL, "san jose", "ca", NULL, "95113",NULL,NULL,NULL); + ret = location_get_position_from_address (NULL, addr, &pos_list, &acc_list); + location_address_free(addr); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_position_from_address_03() +{ + GList *pos_list = NULL; + GList *acc_list = NULL; + ret = location_get_position_from_address(loc, NULL, &pos_list, &acc_list); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_position_from_address_04() +{ + LocationAddress *addr = location_address_new ("1", "Post Street", NULL, "san jose", "ca", NULL, "95113",NULL,NULL,NULL); + GList *acc_list = NULL; + ret = location_get_position_from_address(loc, addr, NULL, &acc_list); + location_address_free (addr); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/utc_location_get_position_from_freeformed_address.c b/TC/unit/utc_location_get_position_from_freeformed_address.c new file mode 100644 index 0000000..c1067e7 --- /dev/null +++ b/TC/unit/utc_location_get_position_from_freeformed_address.c @@ -0,0 +1,148 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_get_position_from_freeformed_address_01(); +static void utc_location_get_position_from_freeformed_address_02(); +static void utc_location_get_position_from_freeformed_address_03(); +static void utc_location_get_position_from_freeformed_address_04(); + +struct tet_testlist tet_testlist[] = { + {utc_location_get_position_from_freeformed_address_01,1}, + {utc_location_get_position_from_freeformed_address_02,2}, + {utc_location_get_position_from_freeformed_address_03,3}, + {utc_location_get_position_from_freeformed_address_04,4}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +LocationObject* loc; +int ret; +int isNetStarted = 0; +gboolean is_found = FALSE; + +static gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + + loop = g_main_loop_new(NULL,FALSE); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_free(loc); + tet_printf("\n TC End"); +} + +static void comp_position (gpointer data, gpointer user_data) +{ + if (!data) return; + LocationPosition *pos = (LocationPosition *)data; + if (pos) { + if (37.325276 <= pos->latitude && pos->latitude <= 37.345276 && + -121.900059 <= pos->longitude && pos->longitude<= -121.880059) { + is_found = TRUE; + } + location_position_free (pos); + } +} + +static void free_accuracy (gpointer data, gpointer user_data) +{ + if (!data) return; + + LocationAccuracy *acc = (LocationAccuracy *)data; + if (acc) location_accuracy_free(acc); +} + +static void +utc_location_get_position_from_freeformed_address_01() +{ + GList *pos_list = NULL; + GList *acc_list = NULL; + char* addr_str = g_strdup("4 N 2nd Street 95113"); + ret = location_get_position_from_freeformed_address(loc, addr_str, &pos_list, &acc_list); + g_free(addr_str); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE ) { + g_list_foreach (pos_list, comp_position, NULL); + g_list_foreach (acc_list, free_accuracy, NULL); + if (is_found == TRUE) + tet_result(TET_PASS); + else + tet_result(TET_FAIL); + } + else + tet_result(TET_FAIL); +} + +static void +utc_location_get_position_from_freeformed_address_02() +{ + GList *pos_list = NULL; + GList *acc_list = NULL; + char* addr_str = g_strdup("4 N 2nd Street 95113"); + ret = location_get_position_from_freeformed_address(NULL, addr_str, &pos_list, &acc_list); + g_free(addr_str); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_position_from_freeformed_address_03() +{ + GList *pos_list = NULL; + GList *acc_list = NULL; + ret = location_get_position_from_freeformed_address(loc, NULL, &pos_list, &acc_list); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_position_from_freeformed_address_04() +{ + GList *acc_list = NULL; + char* addr_str = g_strdup("4 N 2nd Street 95113"); + ret = location_get_position_from_freeformed_address(loc, addr_str, NULL, &acc_list); + g_free (addr_str); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + diff --git a/TC/unit/utc_location_get_satellite.c b/TC/unit/utc_location_get_satellite.c new file mode 100644 index 0000000..0556625 --- /dev/null +++ b/TC/unit/utc_location_get_satellite.c @@ -0,0 +1,112 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_get_satellite_01(); +static void utc_location_get_satellite_02(); +static void utc_location_get_satellite_03(); + +struct tet_testlist tet_testlist[] = { + {utc_location_get_satellite_01,1}, + {utc_location_get_satellite_02,2}, + {utc_location_get_satellite_03,3}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +static gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + location_start(loc); + loop = g_main_loop_new(NULL,FALSE); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_stop(loc); + location_free(loc); + tet_printf("\n TC End"); +} + +static void +_get_satellite (GObject *self, + guint _status, + gpointer userdata) +{ + LocationSatellite *sat = NULL; + LocationObject *loc = (LocationObject*)userdata; + + ret = location_get_satellite (loc, &sat); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE) { + location_satellite_free(sat); + tet_result(TET_PASS); + } else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +static void +utc_location_get_satellite_01() +{ + g_signal_connect (loc, "service-enabled", G_CALLBACK(_get_satellite), loc); + g_timeout_add_seconds(60, exit_loop, loop); + g_main_loop_run (loop); +} + +static void +utc_location_get_satellite_02() +{ + LocationSatellite *sat = NULL; + ret = location_get_satellite (NULL, &sat); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_satellite_03() +{ + LocationSatellite *sat = NULL; + ret = location_get_satellite (loc, NULL); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/utc_location_get_velocity.c b/TC/unit/utc_location_get_velocity.c new file mode 100644 index 0000000..d29e808 --- /dev/null +++ b/TC/unit/utc_location_get_velocity.c @@ -0,0 +1,128 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_get_velocity_01(); +static void utc_location_get_velocity_02(); +static void utc_location_get_velocity_03(); +static void utc_location_get_velocity_04(); + +struct tet_testlist tet_testlist[] = { + {utc_location_get_velocity_01,1}, + {utc_location_get_velocity_02,2}, + {utc_location_get_velocity_03,3}, + {utc_location_get_velocity_04,4}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +static gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + location_start(loc); + loop = g_main_loop_new(NULL,FALSE); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_stop(loc); + location_free(loc); + tet_printf("\n TC End"); +} + + +static void +_get_velocity (GObject *self, + guint _status, + gpointer userdata) +{ + LocationVelocity *vel = NULL; + LocationAccuracy *acc = NULL; + LocationObject *loc = (LocationObject*)userdata; + ret = location_get_velocity (loc, &vel, &acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE) { + location_velocity_free (vel); + location_accuracy_free (acc); + tet_result(TET_PASS); + } else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +static void +utc_location_get_velocity_01() +{ + g_signal_connect (loc, "service-enabled", G_CALLBACK(_get_velocity), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} + + +static void +utc_location_get_velocity_02() +{ + LocationVelocity *vel = NULL; + LocationAccuracy *acc = NULL; + ret = location_get_velocity (NULL, &vel, &acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_velocity_03() +{ + LocationAccuracy *acc = NULL; + ret = location_get_velocity (loc, NULL, &acc); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_get_velocity_04() +{ + LocationVelocity *vel = NULL; + ret = location_get_velocity (loc, &vel, NULL); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/utc_location_init.c b/TC/unit/utc_location_init.c new file mode 100644 index 0000000..cbe5949 --- /dev/null +++ b/TC/unit/utc_location_init.c @@ -0,0 +1,55 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_init(); + +struct tet_testlist tet_testlist[] = { + {utc_location_init,1}, + {NULL,0}, +}; + +int ret; + +static void startup() +{ + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + tet_printf("\n TC End"); +} + +static void +utc_location_init() +{ + ret = location_init(); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/utc_location_new.c b/TC/unit/utc_location_new.c new file mode 100644 index 0000000..6e30652 --- /dev/null +++ b/TC/unit/utc_location_new.c @@ -0,0 +1,70 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_new_01(); +static void utc_location_new_02(); + +struct tet_testlist tet_testlist[] = { + {utc_location_new_01,1}, + {utc_location_new_02,1}, + {NULL,0}, +}; + +int ret; +LocationObject* loc; + +static void startup() +{ + ret = location_init(); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + if (loc) location_free(loc); + tet_printf("\n TC End"); +} + +static void +utc_location_new_01() +{ + loc = location_new(LOCATION_METHOD_GPS); + if (loc) tet_result(TET_PASS); + else tet_result(TET_FAIL); + location_free(loc); +} + +static void +utc_location_new_02() +{ + loc = location_new(-1); + if (!loc) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + diff --git a/TC/unit/utc_location_search_poi.c b/TC/unit/utc_location_search_poi.c new file mode 100644 index 0000000..b0d403f --- /dev/null +++ b/TC/unit/utc_location_search_poi.c @@ -0,0 +1,400 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_search_poi_01(); +static void utc_location_search_poi_02(); +static void utc_location_search_poi_03(); +static void utc_location_search_poi_04(); +static void utc_location_search_poi_05(); +static void utc_location_search_poi_06(); +static void utc_location_search_poi_07(); +static void utc_location_search_poi_08(); +static void utc_location_search_poi_09(); +static void utc_location_search_poi_10(); + +struct tet_testlist tet_testlist[] = { + {utc_location_search_poi_01,1}, + {utc_location_search_poi_02,2}, + {utc_location_search_poi_03,3}, + {utc_location_search_poi_04,4}, + {utc_location_search_poi_05,5}, + {utc_location_search_poi_06,6}, + {utc_location_search_poi_07,7}, + {utc_location_search_poi_08,8}, + {utc_location_search_poi_09,9}, + {utc_location_search_poi_10,10}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +LocationObject* loc; +int ret; +int isNetStarted = 0; + +static gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + return FALSE; +} + +static gboolean +exit_loop_fail (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + + loop = g_main_loop_new(NULL,FALSE); + g_main_loop_run (loop); + + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_free(loc); + tet_printf("\n TC End"); +} + +static void __location_POI_cb(LocationError error, guint req_id, GList * landmark_list, gchar * error_code, gchar * error_msg, gpointer userdata) +{ + tet_printf("\n===== __location_POI_cb ======\n"); + if (error != LOCATION_ERROR_NONE) { + tet_result(TET_FAIL); + tet_printf("Failed :%d\n", error); + } + + if (landmark_list) tet_result(TET_PASS); + g_main_loop_quit (loop); +} + + +static void +utc_location_search_poi_01() +{ + guint req_id = 0; + int ret = 0; + tet_printf("Keyword-cafe, Max - 10 and sort by Distance"); + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("KEYWORD"); + gchar *value = g_strdup("cafe"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 10); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_DESC); + + LocationPosition *position = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + + ret = location_search_poi(loc, filter, position, pref, __location_POI_cb, NULL, &req_id); + if(ret != LOCATION_ERROR_NONE) { + tet_result(TET_FAIL); + tet_printf("Fail to search POI. Error[%d]\n", ret); + } else { + g_timeout_add_seconds(60, exit_loop_fail, NULL); + tet_printf("Seach POI sucess, req_id %d\n", req_id); + } + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_position_free(position); +} + +static void +utc_location_search_poi_02() +{ + guint req_id = 0; + int ret = 0; + tet_printf("Category-restaurant, Max - 10 and sort by Distance"); + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("CATEGORY"); + gchar *value = g_strdup("restaurant"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 10); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_DESC); + + LocationPosition *position = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + + ret = location_search_poi(loc, filter, position, pref, __location_POI_cb, NULL, &req_id); + if(ret != LOCATION_ERROR_NONE) { + tet_result(TET_FAIL); + tet_printf("Fail to search POI. Error[%d]\n", ret); + } else { + g_timeout_add_seconds(60, exit_loop_fail, NULL); + tet_printf("Seach POI sucess, req_id %d\n", req_id); + } + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_position_free(position); +} + +static void +utc_location_search_poi_03() +{ + guint req_id = 0; + int ret = 0; + tet_printf("POIName-cafe, Max - 20 and sort by Distance"); + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("POIName"); + gchar *value = g_strdup("cafe"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 20); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + LocationPosition *position = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + + ret = location_search_poi(loc, filter, position, pref, __location_POI_cb, NULL, &req_id); + if(ret != LOCATION_ERROR_NONE) { + tet_result(TET_FAIL); + tet_printf("Fail to search POI. Error[%d]\n", ret); + } else { + g_timeout_add_seconds(60, exit_loop_fail, NULL); + tet_printf("Seach POI sucess, req_id %d\n", req_id); + } + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_position_free(position); +} + +static void +utc_location_search_poi_04() +{ + guint req_id = 0; + int ret = 0; + tet_printf("POIName-restaurant, Max - 50 and sort by Distance"); + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("POIName"); + gchar *value = g_strdup("restaurant"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 50); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + LocationPosition *position = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + + ret = location_search_poi(loc, filter, position, pref, __location_POI_cb, NULL, &req_id); + if(ret != LOCATION_ERROR_NONE) { + tet_result(TET_FAIL); + tet_printf("Fail to search POI. Error[%d]\n", ret); + } else { + g_timeout_add_seconds(60, exit_loop_fail, NULL); + tet_printf("Seach POI sucess, req_id %d\n", req_id); + } + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_position_free(position); +} + +static void +utc_location_search_poi_05() +{ + guint req_id = 0; + int ret = 0; + tet_printf("POIName-restaurant, Max - 50 and sort by Distance"); + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("POIName"); + gchar *value = g_strdup("restaurant"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 50); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + LocationPosition *position = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + + ret = location_search_poi(NULL, filter, position, pref, __location_POI_cb, NULL, &req_id); + if(ret == LOCATION_ERROR_PARAMETER) { + tet_result(TET_PASS); + } else { + tet_result(TET_FAIL); + } + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_position_free(position); +} + +static void +utc_location_search_poi_06() +{ + guint req_id = 0; + int ret = 0; + tet_printf("POIName-restaurant, Max - 50 and sort by Distance"); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 50); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + LocationPosition *position = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + + ret = location_search_poi(loc, NULL, position, pref, __location_POI_cb, NULL, &req_id); + if(ret == LOCATION_ERROR_PARAMETER) { + tet_result(TET_PASS); + } else { + tet_result(TET_FAIL); + } + location_poi_pref_free(pref); + location_position_free(position); +} + +static void +utc_location_search_poi_07() +{ + guint req_id = 0; + int ret = 0; + tet_printf("POIName-restaurant, Max - 50 and sort by Distance"); + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("POIName"); + gchar *value = g_strdup("restaurant"); + location_poi_filter_set(filter, key, value); + + LocationPosition *position = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + + ret = location_search_poi(loc, filter, position, NULL, __location_POI_cb, NULL, &req_id); + if(ret == LOCATION_ERROR_PARAMETER) { + tet_result(TET_PASS); + } else { + tet_result(TET_FAIL); + } + location_poi_filter_free(filter); + location_position_free(position); +} + +static void +utc_location_search_poi_08() +{ + guint req_id = 0; + int ret = 0; + tet_printf("POIName-restaurant, Max - 50 and sort by Distance"); + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("POIName"); + gchar *value = g_strdup("restaurant"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 50); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_search_poi(loc, filter, NULL, pref, __location_POI_cb, NULL, &req_id); + if(ret == LOCATION_ERROR_PARAMETER) { + tet_result(TET_PASS); + } else { + tet_result(TET_FAIL); + } + + location_poi_filter_free(filter); + location_poi_pref_free(pref); +} + +static void +utc_location_search_poi_09() +{ + guint req_id = 0; + int ret = 0; + tet_printf("POIName-restaurant, Max - 50 and sort by Distance"); + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("POIName"); + gchar *value = g_strdup("restaurant"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 50); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + LocationPosition *position = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + + ret = location_search_poi(loc, filter, position, pref, NULL, NULL, &req_id); + if(ret == LOCATION_ERROR_PARAMETER) { + tet_result(TET_PASS); + } else { + tet_result(TET_FAIL); + } + + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_position_free(position); +} + +static void +utc_location_search_poi_10() +{ + int ret = 0; + tet_printf("POIName-restaurant, Max - 50 and sort by Distance"); + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("POIName"); + gchar *value = g_strdup("restaurant"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 50); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + LocationPosition *position = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + + ret = location_search_poi(loc, filter, position, pref, __location_POI_cb, NULL, NULL); + if(ret == LOCATION_ERROR_PARAMETER) { + tet_result(TET_PASS); + } else { + tet_result(TET_FAIL); + } + + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_position_free(position); +} diff --git a/TC/unit/utc_location_start.c b/TC/unit/utc_location_start.c new file mode 100644 index 0000000..615fb0a --- /dev/null +++ b/TC/unit/utc_location_start.c @@ -0,0 +1,76 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_start_01(); +static void utc_location_start_02(); + +struct tet_testlist tet_testlist[] = { + {utc_location_start_01,1}, + {utc_location_start_02,2}, + {NULL,0}, +}; + +int ret; +LocationObject* loc; + +static void startup() +{ + ret = location_init(); + loc = location_new(LOCATION_METHOD_GPS); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + if( loc ) + location_free(loc); + tet_printf("\n TC End"); +} + +static void +utc_location_start_01() +{ + ret = location_start(loc); + + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); + location_stop(loc); +} + +static void +utc_location_start_02() +{ + ret = location_start(NULL); + + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + diff --git a/TC/unit/utc_location_stop.c b/TC/unit/utc_location_stop.c new file mode 100644 index 0000000..04e74f3 --- /dev/null +++ b/TC/unit/utc_location_stop.c @@ -0,0 +1,78 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_stop_01(); +static void utc_location_stop_02(); + +struct tet_testlist tet_testlist[] = { + {utc_location_stop_01,1}, + {utc_location_stop_02,2}, + {NULL,0}, +}; + +int ret; +LocationObject* loc; + +static void startup() +{ + ret = location_init(); + loc = location_new(LOCATION_METHOD_GPS); + ret = location_start(loc); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + if( loc ){ + location_stop(loc); + location_free(loc); + } + tet_printf("\n TC End"); +} + +static void +utc_location_stop_01() +{ + ret = location_stop(loc); + + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_NONE) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + +static void +utc_location_stop_02() +{ + location_start(loc); + ret = location_stop(NULL); + tet_printf("Returned value: %d", ret); + if (ret == LOCATION_ERROR_PARAMETER) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} + diff --git a/TC/unit/utc_properties_boundary.c b/TC/unit/utc_properties_boundary.c new file mode 100644 index 0000000..d2a9bac --- /dev/null +++ b/TC/unit/utc_properties_boundary.c @@ -0,0 +1,114 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "test_common.c" + +static gboolean g_is_found = FALSE; +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_set_boundary_in_suwonHQ(); +static void utc_get_boundary_in_suwonHQ(); + +struct tet_testlist tet_testlist[] = { + {utc_set_boundary_in_suwonHQ,1}, + {utc_get_boundary_in_suwonHQ,2}, + {NULL,0}, +}; + +int ret; +LocationObject* loc; + +static void comp_boundary(LocationBoundary *bound, gpointer user_data) +{ + LocationBoundary *check_bound = (LocationBoundary *) user_data; + + if(bound && bound->type == check_bound->type) { + switch(bound->type) { + case LOCATION_BOUNDARY_RECT: + if(bound->rect.right_bottom->latitude == check_bound->rect.right_bottom->latitude && + bound->rect.right_bottom->longitude == check_bound->rect.right_bottom->longitude && + bound->rect.left_top->latitude == check_bound->rect.left_top->latitude && + bound->rect.left_top->longitude == check_bound->rect.left_top->longitude ){ + g_is_found = TRUE; + } + break; + + default: + break; + } + } +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + location_start(loc); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_stop(loc); + location_free(loc); + tet_printf("\n TC End"); +} + +static void +utc_set_boundary_in_suwonHQ() +{ + int ret = 0; + LocationPosition *rb = location_position_new(0, 37.258, 127.056, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 37.260, 127.054, 0, LOCATION_STATUS_2D_FIX); + LocationBoundary* bound = location_boundary_new_for_rect(lt, rb); + + ret = location_boundary_add(loc, bound); + if (!ret) { + tet_result(TET_PASS); + } else tet_result(TET_FAIL); + + location_position_free (rb); + location_position_free (lt); + location_boundary_free(bound); +} + +static void +utc_get_boundary_in_suwonHQ() +{ + LocationPosition *rb = location_position_new(0, 37.258, 127.056, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 37.260, 127.054, 0, LOCATION_STATUS_2D_FIX); + LocationBoundary* bound = location_boundary_new_for_rect(lt, rb); + + g_is_found = FALSE; + location_boundary_foreach(loc, comp_boundary, bound); + if(g_is_found) tet_result(TET_PASS); + else tet_result(TET_FAIL); + + location_position_free (rb); + location_position_free (lt); + location_boundary_free (bound); +} diff --git a/TC/unit/utc_properties_method.c b/TC/unit/utc_properties_method.c new file mode 100644 index 0000000..0dca24a --- /dev/null +++ b/TC/unit/utc_properties_method.c @@ -0,0 +1,60 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_get_method(); + +struct tet_testlist tet_testlist[] = { + {utc_get_method,1}, + {NULL,0}, +}; + +int ret; +LocationObject* loc; + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_free(loc); + tet_printf("\n TC End"); +} + +static void +utc_get_method() +{ + LocationMethod method; + g_object_get(loc, "method", &method, NULL); + if (method == LOCATION_METHOD_GPS) tet_result(TET_PASS); + else tet_result(TET_FAIL); +} diff --git a/TC/unit/utc_signals_service_disabled.c b/TC/unit/utc_signals_service_disabled.c new file mode 100644 index 0000000..09dddba --- /dev/null +++ b/TC/unit/utc_signals_service_disabled.c @@ -0,0 +1,91 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_svc_disabled(); + +struct tet_testlist tet_testlist[] = { + {utc_location_svc_disabled,1}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + location_start(loc); + loop = g_main_loop_new(NULL,FALSE); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_stop(loc); + location_free(loc); + tet_printf("\n TC End"); +} + +static void +cb_enabled (GObject *self, + guint _status, + gpointer userdata) +{ + location_stop(loc); +} + +static void +cb_disabled (GObject *self, + guint _status, + gpointer userdata) +{ + if( LOCATION_STATUS_NO_FIX <= _status && _status <= LOCATION_STATUS_3D_FIX) tet_result(TET_PASS); + else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +static void +utc_location_svc_disabled() +{ + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_enabled), loc); + g_signal_connect (loc, "service-disabled", G_CALLBACK(cb_disabled), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); + +} diff --git a/TC/unit/utc_signals_service_enabled.c b/TC/unit/utc_signals_service_enabled.c new file mode 100644 index 0000000..18a129f --- /dev/null +++ b/TC/unit/utc_signals_service_enabled.c @@ -0,0 +1,81 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_svc_enabled(); + +struct tet_testlist tet_testlist[] = { + {utc_location_svc_enabled,1}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + location_start(loc); + loop = g_main_loop_new(NULL,FALSE); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_stop(loc); + location_free(loc); + tet_printf("\n TC End"); +} + +static void +_cb_svc_enabled (GObject *self, + guint _status, + gpointer userdata) +{ + if (LOCATION_STATUS_NO_FIX <= _status && _status <= LOCATION_STATUS_3D_FIX) tet_result(TET_PASS); + else tet_result(TET_FAIL); + g_main_loop_quit(loop); +} + +static void +utc_location_svc_enabled() +{ + g_signal_connect (loc, "service-enabled", G_CALLBACK(_cb_svc_enabled), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} diff --git a/TC/unit/utc_signals_service_updated.c b/TC/unit/utc_signals_service_updated.c new file mode 100644 index 0000000..9898977 --- /dev/null +++ b/TC/unit/utc_signals_service_updated.c @@ -0,0 +1,83 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_location_svc_updated(); + +struct tet_testlist tet_testlist[] = { + {utc_location_svc_updated,1}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + location_start(loc); + loop = g_main_loop_new(NULL,FALSE); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_stop(loc); + location_free(loc); + tet_printf("\n TC End"); +} + +static void +cb_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + if ( POSITION_UPDATED <= type && type <= REVERSEGEOCODE_UPDATED) tet_result(TET_PASS); + else tet_result(TET_FAIL); + g_main_loop_quit (loop); +} + +static void +utc_location_svc_updated() +{ + g_signal_connect (loc, "service-updated", G_CALLBACK(cb_updated), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} diff --git a/TC/unit/utc_signals_zone_in.c b/TC/unit/utc_signals_zone_in.c new file mode 100644 index 0000000..4c5a3f5 --- /dev/null +++ b/TC/unit/utc_signals_zone_in.c @@ -0,0 +1,93 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_zone_in(); + +struct tet_testlist tet_testlist[] = { + {utc_zone_in,1}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + location_start(loc); + loop = g_main_loop_new(NULL,FALSE); + + LocationPosition *rb = location_position_new(0, 37.254, 127.057, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 37.261, 127.050, 0, LOCATION_STATUS_2D_FIX); + LocationBoundary* bound = location_boundary_new_for_rect(lt, rb); + location_boundary_add(loc, bound); + + location_position_free (rb); + location_position_free (lt); + location_boundary_free (bound); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_stop(loc); + location_free(loc); + tet_printf("\n TC End"); +} + +static void +cb_zone_in(LocationObject *self, + guint type, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + + if( (37.255 <= pos->latitude && pos->latitude <= 37.265) && + (127.052 <= pos->longitude && pos->longitude <= 127.058)) tet_result(TET_PASS); // I am in Suwon HQ + else tet_result(TET_FAIL); + g_main_loop_quit(loop); +} + +static void +utc_zone_in() +{ + g_signal_connect (loc, "zone-in", G_CALLBACK(cb_zone_in), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} diff --git a/TC/unit/utc_signals_zone_out.c b/TC/unit/utc_signals_zone_out.c new file mode 100644 index 0000000..098e750 --- /dev/null +++ b/TC/unit/utc_signals_zone_out.c @@ -0,0 +1,95 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static void startup(), cleanup(); +void (*tet_startup) () = startup; +void (*tet_cleanup) () = cleanup; + +static void utc_zone_out(); + +struct tet_testlist tet_testlist[] = { + {utc_zone_out,1}, + {NULL,0}, +}; + +static GMainLoop *loop = NULL; +int ret; +LocationObject* loc; + +gboolean +exit_loop (gpointer data) +{ + g_main_loop_quit (loop); + tet_result(TET_FAIL); + return FALSE; +} + +static void startup() +{ + location_init(); + loc = location_new(LOCATION_METHOD_GPS); + location_start(loc); + loop = g_main_loop_new(NULL,FALSE); + + LocationPosition *rb = location_position_new(0, 36.395, 25.41, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 36.413, 25.388, 0, LOCATION_STATUS_2D_FIX); + LocationBoundary* bound = location_boundary_new_for_rect(lt, rb); + location_boundary_add(loc, bound); + + location_position_free (rb); + location_position_free (lt); + location_boundary_free (bound); + tet_printf("\n TC startup"); +} + +static void cleanup() +{ + location_stop(loc); + location_free(loc); + tet_printf("\n TC End"); +} + +static void +_cb_zone_out(LocationObject *self, + guint type, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + + if( (37.255 <= pos->latitude && pos->latitude <= 37.265) && + (27.052 <= pos->longitude && pos->longitude <= 127.060) ) tet_result(TET_PASS); // I am in Suwon HQ + else tet_result(TET_FAIL); + g_main_loop_quit(loop); +} + + +static void +utc_zone_out() +{ + g_signal_connect (loc, "zone-out", G_CALLBACK(_cb_zone_out), loc); + g_timeout_add_seconds(60, exit_loop, NULL); + g_main_loop_run (loop); +} diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..e6f3a78 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,21 @@ +#!/bin/sh +rm -f config.cache +rm -f acconfig.h + +echo "- libtoolize..." +libtoolize --force || exit $? + +echo "- aclocal..." +aclocal --force -I m4 || exit $? + +echo "- autoheader..." +autoheader --force || exit $? + +echo "- automake..." +automake --add-missing --force-missing || exit $? + +echo "- autoconf..." +autoconf --force || exit $? + +echo "- ready!" +exit diff --git a/configure.ac b/configure.ac new file mode 100755 index 0000000..06e7dfd --- /dev/null +++ b/configure.ac @@ -0,0 +1,89 @@ +# Initialize +AC_PREREQ(2.61) +AC_INIT(Location, 0.1, [sena06.kim@samsung.com]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_HEADER([config.h]) +AC_CONFIG_SRCDIR([location]) +AM_INIT_AUTOMAKE([1.10.2 foreign -Wall -Werror]) + +# Check programs for making executable +AC_PROG_CC +AM_PROG_CC_C_O +AC_PROG_INSTALL + +# Check programs for making libraries. +AM_PROG_LIBTOOL +AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal) + +# Add default build options to CFLAGS, LDFLAGS +if test "x$GCC" = "xyes"; then + CFLAGS="$CFLAGS -Wall" # -Werror + LDFLAGS="$LDFLAGS -Wl,-z,defs -Wl,--as-needed -Wl,--hash-style=both" +fi + +# Add -g option to CFLAGS +AC_ARG_ENABLE([debug], + [AC_HELP_STRING([--enable-debug],[turn on debugging [default=no]])], + [case "${enableval}" in + yes) enable_dbg=yes ;; + no) enable_dbg=no ;; + *) AC_MSG_ERROR([Bad value ${enableval} for --enable-debug]) ;; + esac],[enable_dbg=no]) +if ([test "x$enable_dbg" = xyes]); then + CFLAGS="$CFLAGS -g" +fi + +# Check GCC EFL visibility +AC_MSG_CHECKING(for ELF visibility) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ + __attribute__((visibility("default"))) + int var=10; + ]])], + [has_visibility=yes + AC_DEFINE([EXPORT_API], [__attribute__((visibility("default")))], [Symbol visibility prefix]) + CFLAGS="$CFLAGS -fvisibility=hidden"], + [has_visibility=no + AC_DEFINE([EXPORT_API], [], [Symbol visibility prefix]) ] +) +AC_MSG_RESULT($has_visibility) + +# Check dependencies +PKG_CHECK_MODULES(LOCATION, [glib-2.0 gobject-2.0 dbus-glib-1 gmodule-2.0 vconf vconf-internal-keys location-appman]) +AC_SUBST(LOCATION_LIBS) +AC_SUBST(LOCATION_CFLAGS) + +#PKG_CHECK_MODULES(TEST, [glib-2.0 gconf-2.0 json-glib-1.0]) +#AC_SUBST(TEST_LIBS) +#AC_SUBST(TEST_CFLAGS) + +# Check dlog libraries +AC_ARG_ENABLE([dlog], + [AC_HELP_STRING([--enable-dlog],[show dlog message [default=no]])], + [case "${enableval}" in + yes) enable_dlog=yes ;; + no) enable_dlog=no ;; + *) AC_MSG_ERROR([Bad value ${enableval} for --enable-dlog]) ;; + esac],[enable_dlog=no]) +if ([test "x$enable_dlog" = xyes]); then + PKG_CHECK_MODULES(DLOG, [dlog], have_dlog="yes", have_dlog="no") + AC_SUBST(DLOG_LIBS) + AC_SUBST(DLOG_CFLAGS) + if test "x$have_dlog" = "xyes"; then + LOCATION_CFLAGS="$LOCATION_CFLAGS -DLOCATION_DLOG_DEBUG $DLOG_CFLAGS" + LOCATION_LIBS="$LOCATION_LIBS $DLOG_LIBS" + fi +fi + +# Generate files +AC_CONFIG_FILES([ +location.pc +Makefile +location/Makefile +location/manager/Makefile +location/map-service/Makefile +location/module/Makefile +]) + +AC_OUTPUT diff --git a/image/SLP_Location_PG.h b/image/SLP_Location_PG.h new file mode 100755 index 0000000..532091a --- /dev/null +++ b/image/SLP_Location_PG.h @@ -0,0 +1,20 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/image/location_image001.png b/image/location_image001.png new file mode 100644 index 0000000000000000000000000000000000000000..bbddf7ba2776c4c762556dd549dbf1a6c4576dd2 GIT binary patch literal 133313 zcmbSSWl$VVv_*qEgy2qacXxN!B{&3khXi+bcMa~aK!Q624el(ii`(1p$E)}M)lS#! zcJ1_Z_1t^zxu@?$sj0}KArm4)K|!I(%SmZKLBT>A^aJ82NKd1UqZ{M|?WQ3s0aZ6m zd<^;V$xKmJ3hLv(Phn3*3Zw_gSxz7FH+<~>8nku69Ap3}1b2C5X@pf23{+;$VM{QN0em zD>APqqw|X+qa%^T;o;QBf|0*Ob~m_4yuD|xtmNlcU!3Hx{7?~|5gB*%x--;v>bdLP zYTtYa^Pgz{e;#(y%KH`MTQ|)AcLcK527SCc{6P5O__Q+GPWv5CW4temP-FK|vK=WQ z;Hb1~ebtPz{W7w=fk687OV09ban#Gq;%zbivF)^1)6SHRl(pSqUdzbPuyRmyedk0s zk+751b^brZBix|v9u@7Mv*gh+(r9+SR6LwS0T=jCRew~$Kj zfgwwdrT**91glZE|`-zQmVkJb|hEpGb6BB zTUC<)3ophM$xaiRh=+&AWYm!;N1eRB$R&{mK%3X$Ny64tD zWd^Ty9}4(_nD)ma$b>Hy7RQv_pP`KQ^64pk@1rb$IG!Ep1)AF7Q;Ney=mmKyG9eTG zp9)`*r;j-oo7FV-iF=@Xk!-vYAanwee6M%94yMr z`9cXJsh>LZ=5%)wf5MiLj!ul) zGQEmITTPdYky|#5Siy#zT6$+i?q$n}iaz)o0KHEx3k_Z-q#p@CRkdTPlfL>e#Pc9k z4&Jr$deD20%7%YXP!||Akm)49>8^R-b6?}m|M+^9ZN;Q9#Cwz`UsNJWN6Er9^Sp97 z_f_;o-;KBP*n0{0XB&}ff82DT5Uneh2$`Qa$iej{$;l~Yc@@5tvq6@LE-w%`PU~;a zfKU9geq6L1Z%laMAqvi%EkId0-V;LFUy*QO3uiw46s&K~y7&B|VgU*%=LSmo<(D)4Gz!YH@C4i~97j+ThEoet zocJ*=V9V{sl4ldY-sur6p_qkK%^j=hhqgRelUu91ZmV>l;OTn|%dri>d}iF8E28T3 zO;bL$XQ+4OaZ6dD{A+`VNP|EyN|omHv}Ax7iytgcbG%rIeO3XTh4)neLaYwmtleTDuD*Iu5H+vn^Cdt7lMODD~ff4S; zv2zF&X>C!pTb(la#!Ia;SpQY~n?T5wC6DXM2!K7xPUE_Wt!TvV@>850HYsvYTbI~p zAuHECalTEw!0D9oEA*P*YlUumfu1rY*NM7G;ztu3||4P9~IMISTM0 zxhel#7gwOXdfnx%lOK2?Kx`Ssf~hU}YD1j5#U~^B zs`Q)N3tVwKSJ5>I50l62B+;NJg~5OB$vv~bnlozUAMQVQcCB0PIyClD?z$3zuZt8* zx0@}5hLd7QTK%;AlhVc_3RRQctbqb=B ztX5}}6Ki2sp(gyNhT?*dT-;MYhKq&OyNM&A*4UeVO*XkV`}REF7+~v3SK#iu6e=kt zC-s6I@lIXD6CFEfFJp|UHHGj!}R6DC@Mk3U}S-%Z8= z-C&tWtH{3bENkk@in+uG58b;anZgi@p$SijDNK=XI?Z>`n&t58EJm=Rl0Z7^u2UtuJ8aQp7_=}%R{B0l%;>xnYaaomoe&zP^V_QCn03b@qgxkMiI zF0l?tX0y(FVEXX86hz;sC&K}VU{s&_GuWdYHMX4l6iE?F%VQPqePFTJNa^}|+Kq&i z#P5s_v`a2YJ6I==$5<4<@)QnoxEY@ zvQj-II~c=Udd%0f0&Zp)r^ga<$zz_Th}56ju6csqwZwP3^5Z}ye>;>-8|13hok!utLx1^0+gEO?{m~Nh^;{9JYkvc{u6a#v}vQb z$rdG3$w>8v$b3o28Nf6Ff6Bk!C!mOfQ@)d2c4FuL0VztCp?})ftkrfzV<5|$!Wl#r zyX()9#a*a8s}xUb4+@OX8ww{ZH+=2F96&&kXQZf`(w!#v4#d8>0hiiXeN z6R8gJ()~v8b=FNeo4@KEGp?Vk&3#;RP<=qU5V*|#Ri6HVvPg;NwY2VH1rG+qZ9EYY z2W$?*yC z2ObR~2WeX@|zZfER>-0n~`+~IE03fQV2bYeXY>) z!zY_T3F&cUAPc_9)YNVu49dOaK66uK=;9Jq4aE>p9~ z5)E`ob0U(xy-dr>gYp)qyr@Y0|v{&!^`5NpRu+;3@pDXFe5J_n1_ z@~_rji>uYV@y%`}&%UzK@=tOavB&)vkw<%W&A#WPH_uD+BV(usvvx;$24ZkUe*2`l z2nF9qcBA{rYfx097W;1LM$VT5#rHavVUHleOvY)F)ecYnV*mQS7w!+z zTO?i+7w=U<$3AVya_W^C2-A3N#uch~G zM*9&&PM@yd;qJZ=cvH5xt~$@G_9&NE^@NS?8X+FhqiUq`esw>*QK(bl@fLFGs|FpS zY5Au2Jj(idb4mRc&WSr)2vD?`F<&LZch5?sRkKxU{K)$~ZEsm)1pi>Qx*v~X{iBL(cU-g!AsWd`&kr`DFn|~Bl0)a)G?dr7@6TLqT@|;>OfT))>p%Wov%$z$V?M56@_gq z{kmH$pfTOv?XgCaCRbxTL=^eCc`eM{?y$a_K}8degNd?*CF$fa7jfE{-S@7hX!iQa z?EzcGM3>`WI;5Oj94(!Nrn3y>=on-^>wo!BN|{0!{Y4fWh)6py!@wK(gdR4uAB%Q& zkC!!^kG`9%YM2VsDc_!0@gPfsuk`55g7~K;OY~}~)TzqIB&Sf90T{Z2IRoU$18rs| zp-w20eoO!MCwa^JEUZfD!(wFs@>i>M#76v=}tttD2ev{LK8}oIvrH9uNfF3hDyrD zscNIeEqs$(9|EB@EdN-m)=@V7Ux=oGH`+^1l~jZ=I8AVjy&d6o8xx&}>DTL`Rt(&& zNu>Z{vwfeC&Zluny`Hvg(;z>JyTzT42W+Syeg_OX`u$i&fc)$GKN5O6bak?*rY-q| zo4fUbs=7F}FX&jv`mq6zT@1k3Ss8hq@3rgaO6&})?N0eWRzK7Y@ykm2CY3Wt z2Jt`_72?76d#sESQszvV&ADV5^(C^)ZK$hOID}>s@dWR55N{ImP==!@G+r~y?|i_G z7y4$08GNUGcNTObIholkw0M9NF#}4IofaFU(NI7ac%q}Z3)I=v~!ZY8>pQ<)tI9~5$ zqJUD2;X94ShvqveJU{Ba6~*R>qMZ^r>gV*DeScw+)ehDsM>3! z#6@V`OnUwVUR3;7>gQvXew{2a4Se;1n&va*mC%XodPbB~dF3^kF;wwT4lVA7fkb_@ zdf{vQbSC4mz^@{sbp|yR*8F@Fmg<9rW4lKwBY^gH2bxk4onD*i4SNboo?LLTbLReVe9Na4`xhMy2*)h8)t8@~$t7f0&K@f8*O?KQ>d~;4cQP0TrWQdg`@W#LGd@Ifz zV z@Unq^gtUnn;jD+|z#)cz_g6*buV3PbNra25(S(36yg38msNXV3c*@Fo`a7cBglC^h z<@K-dr9g^b8a_zu=j(}@w|a8b_>RkvA~L}%l=mC8yd%U-BnTL!V$zn(ULrT@{qtHz zqbBtqWSoagpqwaO@){W&eSbmxf>w+{9EAP9AfchxA;zlwAR>-u>ZBpBtAU%=b@weP zDLyGu-xedOrHN5>GeQoe( zE-AUZ$Kwxum^x_4n&7@gAGFt}>=g)jiJ& zB-^@)H#O1}^EK+>XUUKMg=Iqqz%z#<i->>h)IXUrk-I zFtj_|P?UdO551#&udjCSn%3`P2hRp=!dK{}siDcbBn95bZloU%w*L3m!J*a{slpvW z3yp{q#ZATGH|KR8(nX<|TCZLCE;xM$5H~EFPv0nF=`RR(luW2Q|MIr3<=Az7x z+hfFGh8WVeg<875^s;r()xCK*?6pmv_dgo+ z_`>EP0EP@xdJp>D(B(?b4<|kb+t%zMqXzZ7TfX0dM}Wdlg7<4BeX4N0C~yKLF-GL$ z$iA+D?S1sS&@iPVUcQX3$lt zUxjWk9SFDhC*9lXDmflECLJDPH&lQ6^wfR_al)jgX-hR6afN?@H5X9p&jn-at{-Eu zKnED83Q}%5Qz#@lWc*T|y%7_pot0(l>zl`VBz;P}5o|j#X)~U~s38g#oP11#Jk9bC zu>fkB_Gt%t26Ra#ta`3OReY$6fL+aLLA$Mm+psVS1;JKvokjJ3WqGSvUl-jd5583X z3bu(=70Ddg#v$8HCK|bZw+jmELadMd$Of4dj6rNs(*RrL(pOTLbE`LYBcUq+@`Mul z@*8<2Cew4gR3>2?p2|t|`+7f@ZYP0o@-yE9x@d1K z2X|W(37f`UxLOj2NHD%)djX%`+aq~ErEmO3->z4{WoLc5eJ$)5>s?XVgB(dMDzb;3FI-0lcbCVhGH^(u2%3vFEZb_Vmyz;FmwHEYnLzmsj^seF8tST%49!z|kWTm3CN! z{4MNUvXI9plR-T`f_IbN1`(Ep2Bxj)g zZ?#jz(a-o4Nt?$1TCz_wsvXtG0B#+H@;AU4AnjpQzlhsC#aC>o_}2r}JqKFP9HpBN z?(DZWQOFv)(>LXdKXfQkiyTY&iW4REMaY|N$Jx6?ZF{ZNE@LhNG*h6OKq`ErqkPI+ zsubp0?D5@1!e?z)DjNLkZT1ny6!^|ulnY?<$Ed8cp2_oN_c%;odNxISd-jx;F^_ac zG;`_waN({nx}h`{Xfs_s#sBMd8&4cKtm*%B$I;q^iA-Us)j89Cyc`z{6LXU7tI?V) z@wu61AR0*JF(xr2#zSfOX*RHDu1{*P4BMP znCyfOcx`vfQysTUTlWXZmOrOA@(DV&({CvOlX*8^($`4ee*}pNhZXrbjOD2250r1L zX&PwAT>?maF4JO?WyHvKdP}-S1A7*hsSc??g;S|gmOoN)!Z&zXqj+V+u44qcO zEc>*aC*CeO1EyU?^6!O5@?TJ)s8luymX=*^EfHXycco{pFCuOqU8gzTpMFy>X)j!z z2X9qY*Ht`Nk^Bot5OHT>RW|Zcw}ecv**xR=9NqW_nNe3LPTy2Svc){0w(w~(z~oQ zt0(ODvR$zzObM6wsk-%9cC$k-3|EF72xgCC?Z)L_(@?L_E%2B3n{+vLvk9jWjFs>o zV|3XANHak2hc3!odjPdqS%PJ1|3PkU$=5VHE6q24J09L?k>Ekv)mR#BBb=j$GIlfo zdwbxEP1YkFFRRu-8vjHSV#Gk`fN3aZ)fVq7FD`P~`_h#?UFxX&*6n;W76&HV<3_0tqyk^XO8)-tCK+?^e~dpg!Sq zBMfc*WQlbW;&WQ$Rr=Q5QTd~Wl^EFrtFH413gBmrPWAEh`9b8J9YVjeH@)<+)=1pH z2KafDSJFu_5nA7^es3e24awgar)Of?KK4^R*xo7WJiNa)a(j7PSR(^^Q;`4j6;p+z z0;;3|fea(Lw{TGP!UDmv`5#INM-j}lO8JTb)WcP>m#BB@m368`{$U3+#2&M4u{n>- zIHLN$|BPHD`v%P9`8BU4J(Ru&Jlu`ULgwBuWetjV;JZA@sMIsbIjUzH+?poLy?|f% za!DfCzW0PMvtNo*09gru{M$kB{KL;|-#VcWs0(7@sGokDV#>@3$UFT^{|K<93CC)sEg0^!T{Kx-h$PAFf7PCw{sql7uRkY^%Zu>%Rj=kgS z0n>{A8}ESg8tzGY@XczeAM@Ov8IddcRFD?Yz3xPTTk;JbvVX8#6Qu|h5j-g{` z7y+l%)hJbh^SaB(^>W`kx1~`WnP`5{$IDh~M#gPI&})cz$R~AU=<4pIejChyCqzN=%9 zV#nLg*rXva*(ISse&oIkqJIG8b)DA+QdZQAM;vrXrn$Y8wjsc!u44eFH~Rbq|J{dG zz{_Uf&Z}=Ce(hcfu78kv4SXtd5Z)E4O%?)se?Id%M&)xIr@#L8IFkEX@$>Z{bz`N; z3*Uk(x&basngXJW%hf9jP}jrInAx|j197;kihGfD1BfBJC$c`>$ufIIl0-83eWDTQ z1Y+Xihy)pDO}C%@pAO56Jk|`)x(2M)?;ohL-tSbaz!wWr-Y0dM9XCrZxU&7IM;l=; zj(q7o4;Kh`>J~<>v)i>#=QTM#;HN5~yBkoh_aiwZ^Wt1{Sfomlq9EK$5{z)U+J=7J zyFgkOJ>f$q26E@PvsRSyt$UNq=J!-mPeSOPQhh!N-$zRiwi}&&xP)=69g9Gw)8R)y z4KHwf-PEsi*k{N`a^;t-pUlP!ddY_eN65oJY<)7-812)|GLnLxK!S|*D~6nVo0+%_ zQW;xYQ-)-d-NIPao{wz{r6dZ z6iWKgLn3XQa#uS7Ql4P?^(G4b?XX~T=iW{fBJ{^&9~GbXC{NWt2D4;lo^z=H>TJ(% z9>;paOK)BCwTgo9O&KvAv^&?pw=G&1md^ONMpQhWG>$sakb**$u4(HL!YA%lA(`ueta1QM)m(jCd9Y;-te3kvt+5Jt)t`m z{siK5*_HCWI|)lo?s?eEiDB){40<~?(bCc3@V@%?nZ*e4_nK4R)YZ;FmPmkr;3bd~ zicz<2f0A>?;u(Bw-*sHhWY`vK?6r|b|1r*X`_MgCrqwsdGQ-B_9!L5nj#oq0WXl2P;t7?K9-4*1ujXC6Izaf@Fig= zF)4FzecaNj!G5;499;ca=|V~JF?}?L`x8BRkwsSj(7)*EKC`IM#w9T`l4(gu?p3?_ zy3C~BjB}9tX_rhCoC4cBeIO|E5L~6p->_Usa4)gsN*O^)*yp0mzq4GphqyFy=9IB6 zU~>eI0dx984hF#O1aTHJHFb4%r=e&(Ep6>ik+n7lLj^^}s;a87$Ry-22_f*Tq>;}- znwFMUY12N5?@^Ke<4(kX<}f4j66-c2oUxZ6n!hs;p{c1k5P~5x+G0D;cL}`hc)95A zydEa%Jgw`ltgS7pq)Vco66=^$`eS_uF+{6A@x(!(HVAV-;jB@*yudWw$p2| z!AcOm|ME508D=0HZ78y1b@cOuyVB|7{x3Ik2?7Sn<<#C$c{yn=2!m|IC z$YP97On8BVT3O2$A_s#`%z6IMIry2BZf(WNM-CC^4CnJJQ>R`&>k)RP&)!*bu#|~I zCsbo4=xOZG_}nRsmSS&4PM2;*e?P+Fu#}?)G{?2FSiKmRlVeJVh3Lvt$Pq#+189N5 zch|$#np=tt7wqJpDVj$cVWpynaYX0h9ZZl5JY{3gc@0kcNE zaYgR$3v`r8h!FHS=sK+{>FpJ9T50)q8`P@G7gj2{jmYaB24xdJlIK(<-pG0J3uVf! zQ|c+3(vuo-{430G{G(J>ZghC~wA|d0ZDbsW1e;rS*mOgXF;H?Tt2KBwC{#zEBfKEtq71NcQE57Ymkx)WTPcMo@jjy8Pz#+{4S68n3ox24lu4HNErqi3 zB>@DS&1IZ1U;2K{*ogWy^6zE89?@CQzbM(xPKI&mRe!cgw`_Dj)`0NUbMESznj{S~ z{m+nfI)lJF7i;>TLGN3~0mYRHNT3!#i@>!~m{p*v5o zdY{0bN;&t6>wmchdQUz1hulO8H0!{QS4;wMxti0Vg;zr+Am@e2iUNCYn`ISY(rymN zi8{-mnJoPnqpNaDxe9z$kPT~T(>MBAvt=f|E+*gpZ|DAVw%N5c;_8}~vp8_u?55JB6=NqwW zQ%Hcl1SZpI@iE|PSGg&Zhzk@4Zj2xy565?6c%VVwrjZMmuJ}XfPVDGbR8%A$p(yOQ zd|;vY^#b-A1aN*Cv_}62IIaf@)z#Gm7_NjadUXon~RMC3ghs4T&Uyonqkt00fT0<@RtR=Wzs47B~ei7Vob!|kLn z;wJ&Og|g};1=Txd##&l-pZ>{zzb69h9=+|VBwd1^M_K7l{u}UTgxCKJZ{xXg*s;PG zQ|u!1?5ph~Fy@SFvzY_I?~iTh+CyhRz2G!C1<6Y;)C&;lzGkix{9+6ZgYfN>Sz_3QI_QJs z=&rA5ciExN-Z}OGNY)=sQR*TUYGdrO2w?>R^9bSz3fZoZe4u=jy+pDZBufbp8cNqK%>}Aqp|72 z({I1cWq3&~XbbUMJ{wI7+uHorpML`_&+iwV)c}<>2p81n2?S|xRN%hI#)BxQ=A{IF zC$+iHm5=!Ro%OG6X-VaASS@{nNKSOPW~a67hZO~ZyYYe-h1N6q;Iow!>wKSZuT7tb zlaudl|IAQ&A9qpW1y1NZS1j=lr}GpuSd4#2`KP8P3qP!<6a+p;sh7z7tZY!aRaRC;Z+;9}XY=(A7x3wF!tJzR0z@gT*loMvE;Fcm znpow%Our;-KJWC{ap}_`T82Az(V5EYK@8S*8?i)3J+-iy3|V_H;P6w|v`)L_M<~BW z&j)jP7~xoWk!>)O3)omO4-v}=vSwQ?jl<`4R_|e7^;k`*WDNQJ+|73FS$3nz2(Uuq zB=9qMb`gb0cXv%umex2onJ%a$y6bLk7hy)z%IGi7F?LNK-HRjK@J9p68O;$tEGz(b z#o}x)YeVhmt9?FA_ww|%Yi+f2U#hCBDL==QAs>GJOq*=KxU_^FCzGUs9VMj)^maKp z*(jEd`6A#>C;A4)(S*nsYYy$oL)u{jrpPELNg5iux)~=_xX6FYm5Fw*`G|Pzp$bb& zL!J4Q92}UFZI3J~*x^{7kZ!^3vxtcw_{Y ze{Y*3{4eyi+gNl1z5G?-l7b|dN1Br-9Ff$RraI7u>wYbVn)cA*375N$TYSJzxqg;X z@jHXZbN-44QZvYyUbP1(1o5~|S^%1|h+YK6_v=&OL|X^dzG$s1*LY;&iHj=`K;_&Ngs{vN(+Coc@XS<=HCZ82 zYe@97-Kv2Q$F??}^G+MC?DWz8xC?)~{LkC2Wf|>bG_+yvNC=eaXuh?6vXB1; z9k;N<=?ZLi&ZKEaHQMMHKOtrpq&7Ly70|{2s`*msi?Jw~9_9SM9Czynktb#5KB9Ry=RR65?&uyc58?M_;JB(zzU_ zqCRQarh3d?A>MTK)N{R^GE&MQSX=U~^<+3=lshkQ`u0axxToVN^ajKB(5xnNu*D50 zbZy9${AX9n0mKYK0Ca%5d*9waK0_ZL{sf^LM6ay?UX;&F-!hCncM3z$%^=}t(5%s- zXYzHi8%S|5{3_4_lT?=|R}Vf$qbmbf6(Sd0?yLPw$(CdsNNo9=byt)oDb4AOC7 zyK(6$-tTWRFNsCxD3QQb^7X6CuQc;bFoy#1i*l73J*1Z1On{3}4rAJ$7zi(D%lgz@TK-J$Vauj6e(Z z&s=n(wq$jL<>r0VkjQj9 zh0Z#V2!-C8`$W~JtlvD9XX>Q*IqXL4G30(I-b>k32P=q{+!P zww96GYR1kwb1yKf`|*iKKC9+)2<`)SQXcK^NW9pQmfwgh%V7I0oGFSCrMiqPzynyL z&JwB%?^}$U$?6P6dk3v8f9o zhm#YYj=^)aJIXju6jJf`38U-OtJHsqX9TwNqIzz;e?|IoAB9-{RJbXZu$NxK1Ongc|ZkRQ6(<~uDJ(`0Mk z0*ZE&S8`k0e?O-AQ~SrS<$R)mCda0)6?LD_t?~pW$BZ0g{yu;i$Xi91SZkgCn7a}+s-a$#sa`xZ zW$jaEjqp?Vhva+Tuu$n!aQ7K@k~)0J%cw~s^h)Cw5B$`OI`!Pn%Jd zzj?WlzF|F1`5?YyfeW_&=t-kEvGi?>7ut~TD7);9LpKk2lP_gOOTNyXEu?mO?g((g&Bd}Ze4V5tb;TFlC}BginvY~-FO zTVe{@b77cRgY0@%CXCQAv@|r(7&qKn8Gs|?@0WqC ze~wpLYdP71KUQRN+1}SJ+F^zzs9;bmf;A150pwie zC=APwd@;6lPI9TM%*NLKr5I0_Bj!hXycMBypd4_14tWYaZD)DJ2Q@%6;g`uUnFOZE+`0;l(*O@>KRPu|Lz zwNC#mYkZ|bMI~jPwJ70q5S6tn2%CA-?8SI?w>k zT_e&BL#cs2X8*yJ=TmRl=<1Q~Pv_}^={EQBQZGgnD!iaXizSP{1oGZjIeF+4ine&) z7lh-yxPbI!U7zJ-Itl9qq*;)oPSmE-DijP^W52cNr$78;9RtS-oN|^O&T9N>mpYej znChnCl8I+qt^Q6mHs+R2(MSJ-yh?2{EG8*+mB^Ezg0m&pzlI|@mt)$znJ{e^E8FnX zbgSn$Us1Y?hF4wH$}V}BpcvQJEG2ZmLfM8kfglEX-|__*3*^l_#+><)7WXR}w) zH{K|}omPA~wf(73d#(e4AOf(p&(y|*UmYhc&_aXdAW~)6l8RLu>@dj-pZrnJ+a6l< zp2?eibB46t9GSnG1&?fs{ZG}J-O1| zo8sHw_`YSM8gzK$14?ng@o@K&ei>D9X!69rmCSfmvg^qV`HBa4u08XYz+!r0#S5I{ z5wy%3v1gCU8XccTE&vReow&;>WHTqL(X#XbuiU6OiFpT&<9sHRr`B3tUCeN(U8U5- zG843#W2?JeW-NmwJYx$**YndV7)<0l6NZmT{ddIF_6N$2bBz3=_V)?cj^+uaMGt<( z+v=PLBlc_BO*fjECvbkn7`>!Z`Rw3^kI$^Ob#>!|k$EZ#EV-O5`OdlUOl#}}&nJdT z3NuR1=1%&=DIoWqGBizeYC_z2yC{&N4A>FRV_twwpOTfZimn|cm6}GwjZol@M5AFi|@$F1>>Smxh-OXj~JI>&KQf0&jeZ=5?&?y2hu(;uLmT z7e&&Sd8c)aSqqGQRTz}xTD8vU`k4-zH0!Zc-P})RF~iJA80ISoeFP(8QN%+qFKkLp zNmR@SXvhq#%EQ@qGl6cKxXyWuDc-($zo-2wA;@VbXUh{zBJWPwB4I`PSs{_KNGx(r zV~|}Ix?xuoW4;8~LkNFM(jHphQTEA4L)}=}$JVxlQp0G__9HM60~9ziNu&69RnRW( z;E?X3hz#Ga@T!9QnIfK#>w01B^7r%Ialq#^wzGG?C&v{I9UYw;u*b*t#83=z|1`^$ z(Qf+Lc;v}*9^+g>*A~};_E$k+%r5)g^cEM_N<2hS7scsb;BI=8xPo?sj-3ou$RIP) zg6=`9iz|A4=bl&kDip8ybKGt^?!#zo-50yvbS-hsIpwFugfV_n z&CAZ)=lmX4>-FR^eY=ciI)~aYfJ!Cg?pqJ%!n)VFBmNyjV_Cz@w!%S#R%wn~Jh6u3 zWwCZedilRM$u)geuzBINw(Ku*U~DJ1ee}Mg(u%)#ne@I*qtTCiY9vFom8*qipC@Ut zMRe{eo~`pgG$s^DdW$21B-ogkIZQj{AO&FLF7kSTK zU4vQ7?Q{FSYlX?KsACmPlk@@M&=fr3aRsZ1i(+}zDf~~3W$Uy%oPmYA;;5#;=TsM) zrd89f2-Mwl1LGytEc&m;PiU^`ck|kZ?P^P^GmY(HOEdNsR(A2XufprNqh&vjqDlAT z%KTpj2sF@#+i@c^7*dkdB!Z7~c*64K-afS$E87CmtXClQ#C*6GH~dLEOR8gVrk3w$ zQ4MgocsIwdPf>kgObu`xEEI%0EfkV`=Y=7Kb)*DQ&^mi}-ln>%mcDJ3;lC#r>Y46H zTo>;~Vyl#26JljLZ#r-~Zc0tnbTb^~=<%S|o{^HkvZ#|uKIo_%g z?;n|E@9PTXf^=LI0WPlbu>Fij{26yiO?O&Zg&oRKso(d~&$#FUi zVD+=z_e&q17Rx=f@3p+}N-v6kt<2Q)0dncE|E7raATN+{-HwWy3X*Fysz5@nb!pE6 zfto}`6n&z`3&yC$;+c)mbj2;mWjDafZ6wEuEocZCF(T!KjpB=xI=g5sV9KGsZ@S^- z(){8EFRsOaBK_BE913Yrsv8;6R4V*!A$cffaKUn&mYybuyv5c|4^6|hOiQRLtZp>P{s9ataq5EZ-$5;U z+Gw)O_5BbA^1BJ(;?bO||0(5nkguy=tIdCx@-gPelBy ztpr-P{XR$2|Doxd!{ch+ztg6T)ik!P#&#NOla0~Xwu_*#t;V)(+vdi$@t)`VUcY~H zot)i0GjrcFADyKXa5%(Di6r+_vS~enUSHuY7Fj6!vN`lll1`(h3#ay;l5L}Iq7BW{ zSaEoi7?ZL1O*JUa!jG!9=t*U2YfisMO+II+tD*iirK<*6T`Es(3yamqhRs~*Wm7}F z<;wb8QEK4+bVy(4L446X7R6VLO%20msm*eld1JYs%%r(=Gzohwsq-5#CnZrd57%Ah ztT*@i#6uwTE}Cn~N$c-Gbporht4ek#0yx40lTd9grL7E%Lg%NlC zZ>-S1C=fbAKvX-w^Wz=ty;Kt^qMn<6-l@;nng*X?HjM6tnjeEjF?1r~6DdLGdHan~{mui$iMFg*nGtrwJuZl^z4WGjR$m zqZV0a>9U=YOhrh374!9)4=MYh<(*vkU81l<%ZJafdPe@;e%r5{rFjc*LicR zLl?>Ac6MRT;c>?3U@427aAcXI+~*H=H;r~&P{WM+YD{;_B!Sz|AGM|lN<7*;kJT9M z(IDbneS9&)lq|X3a3s8jxK+jPnnLMh!<4o|+{XphHzCb>9oJtPC~792lJDfRWJ-VF zH04-k_d7Zk}2tG%U6Cdlg+=|plQ z9{(s_ea0=Rwu^koNAe(@-MD=+rMCj8(=@-gM;-6WzLWOnGYkxjC_4|a;Z8f1$>dSIT>%$U8xxgNGa~<=3@HO-1 z$rLK|#ls_ZWqUJ>;U$uRGFW|J{r!Qj1FUAh8!cI5a(`A@R=%AaDYOk->M+oxE|ZV!3;l#?zRgu9j|E%rpt5VoKSd^VAqKz4(``??`9_c=~~e0Gidc5-5%o# zx(msKhO&JwQjYhUJJ%^MNg{}#3L5TL-CfTWBK7WN#GP$dF8gBah6>*747I6Vso9c3Q7&WjRoiYL zCw3inb42^SkLmS^9P*8c`yomkNijEKh${j>*}sGi6c(0mMc-4ix;;AjYShK}G^_`H zkt9lI%^erKxezxMlz5rC=?i_ZxV4N}a#6PxI=!JtGM}mulYDzQhjsTjGSl&#ohrI? zVPxKas~Lx(*e7=7HWEx51tuP)Q6I)&1R4`;qmggfjk+D4D+1w4Jv6Oml`Han`z_Ub z21`cEI5++6XhhpH%TcbuU#0Cnd0rR8(F8wo^w6rT`h>9-*S!Emp{=(|J66X+GxCQC)L47*Di
l&0*$=gtba=1X@iWqit9E0TE$C$TG22J*g3zK558scO2>fE~~bzho^ z>tlu@sPbU~JU=me%cU!#1?>4(oDwFlWjHm3z}a%VVR(H7GZqc2;a3}C^Aj6?H0M@4C^$veR;GTfF{ecWy z$NobQfuqzBe*Oj>GqWUISIvarh_WPQwYs{R+H|=tAArvXFaJF8UMWPT-O7?~nvDlp zh=}IUEX5;E6&jam)Fjk_!8hg`A4&?jqc2FA4(FN>p-|=AQ=cnZL%h~K5rIm9D%_8U zFf*)rnpcwPm2hu5u~(8OyI871J#W4EgAWP$mJ^jTP4X*NXyx7G5qvKKAfkk@U$_~G`Tx3VkleriTZ}4 zJE+_q=RO`6rflfy7*12go_4f%97eD8yGB?7aX@sn|E?dPilCM zxdX-)ZSr~z$tm;y&_$IrHHRdLeJ~m$Q&LjG1dXb2?pK{q0U-{<^JxQdPY`MWMUh`J z=ZNXgWn`BBF;3gthW==?v$JTy;(#nTE-nr&{5zZZaD$qe)FJ0@^dmK#&nda+`|2%>NX-+;9V^~Q6eT3EDKDZt8zXeQg5C(J4GAXZ=$v4|0?^py+6`nnLK~$ z@Hy>|iwZ<+sqMM3AEQqB=w-VAeEhvKXbdKNry? z{@{%?oexrk)-+?`;mY>Mk_ymMRqe&nw*K<)icAaDJ~e4^&`?U@yZp$?Lb&p;xi`4++l$?|9Czj zUzPQk<=fL_$Kh-}V@_at$~XK!p7;4~4YsY9yUt9WR}P%#(*d^}b^P20{FDI!1a;R; z$?6}$3n{FYg270=@9o(7|C-yGZqG9ac^&t@4J`f$yJ5O-zr#~lbW;59=zcN)KWj1| z=%ci-@c}_pF6G)~yUC{h!-(M(my`9x-_a70ZYsDO<#NF{_cJdm0&Jl-nw7hwzJG!~ zQJ0PKu(pP|wY2}60YBJ5<`~=m063%0&c6q30NF-T|M|PiZ_mCdxGXip@F?E`E&%6< znIyQO38R`zVs|nmXvlqRFX0;OGoNmw=btAhx0Uw1PSpmknX?LACKkuQ_|AjDjnw{V+8y z2H=HZPzZ1uBSS($YTu5IjuvfOPPw=LlK;myXDQK`eaGljQ55Ktz}EGTi&PZ zdU^PL-#!!gEu^=ym>@9ACC98T{8ndbOB>^L3)F~9f4H6cb2Z?OD^{e&qM_G8nTcAQxN3 z6JLl*LM%^~&M1rJAcf*VZ`Vd9Vyb(yITOj8T{(RvRunbb6%g<{|0YIp?hc#BjKb!5z$!CxSC7uDs&qgDxK9a6o#jfMNi zF{s}VcQ8ijm%42|c*9jRYaQsmz*juS3Z?< z)$_RQq_PLa!VlF_ylA?}?Jx$;01#lRbH7~l-~#H~bY7S2;^Gj2yG8QbaX|Tg6{vd5 zk(;(oRpGp^hk#VS;x!~jj|E|dC6JQ$p@2-KJn(}aKHu4~jC$Y1 zJlwZiyx)&2ZVnbnl^1BSAQR81CL=@w59gA^tpE0@f;)$${1H(E%(XO}TAcbxa7Ey`R=Yq6pn`om#Fa1hCSV>mjRuQ1ZQ=QP3hO`|*P>5}{Ga&_gNX zg#)JXLY?;B#Aq4mhLai?o1Fumc*pTPg$@0cB+<9NHdZS#LbhOrPouGwUt{NB)9DgE0*Ge!>Rwo)=+I1h_8WybRH(w%U zlk$xQADMoO)o+=@t<+_CIyt{wy;sL1wwWlaoi+KAULq~=BKmg5E_yj3Mq1uOS7|}t z2?Ks2{)Ho*OUQ^rp7PAB)HfV^hHPlbn|iXYBW&9;5GFQweX)6EFV$|GG>D-4izGqx z)~_oo@jkvT6D*2S&aIW=1K>gMaNY$2r z33oVK^cB({E_JNmaH1*j}J&sAVW+P;?3>U`~fM0lRkK*KKm`f1-jF( zysYMw{fi{f0jF-s2cT^KPeO83SM~aNS`t z`D{BxtoxwqbvR(m&eeGz*>wcf>$8LKJI@!%^QAgug6DK2K^{W>{q~^z&*Z`vZNv7C zvnW?L2)H+pCq8g~(~ftE42{Nt5&Ef2WAz(4OyF131M4VykBslJv2*;b$#h1dsd#IX zsfT91J_Y3s=RA&4GHD5lujyrS!}%TIHl>WwPb-mM_7==7kJ?i$edkhy5T9N-tZ!M z1sPD}rD4EG`ThBQ3VY}_)^9^w-?;sxo8l&&^MDX7Q4QOdA8f8WBq>iTI95@Ql zuqejMwH7*luYl`&CJ1nZfBVr1l^ge;aPU8+V3m<%zFczmKaoFZq8CHdnHLv5s7`yy zW~TA{17!a;xfJv`|@l_&I6qEdiI*h7>C3No6Tz^y&*(=@EpHCad08mU;N7Z$& zS7^lvm%h^Ws1c?Ddp>YY?AQAj8g=_ARx#fz2qm1TDjx-C1V<^?WOadE_jK*bwu}b( zy>tV`G@ugMyPu>Td2d{ys@txWokQ2y@)8D%WD8RJ5JeVESt)odA-8|dNGGP6Mt z0GB5|KYz7a=eOU4FDc?9FgwSQAL6#MIHvno37o5z_W&T{lh>*E)8{)p;OOO9Y6180 z^+Yz?p{r)!f@(H7guo+!8JXGXZxGy0(An=PlPa@VjS-2~D&pG#OIU)ftk_~&LBVFR z&3cr9Dic~~^?4O!bwjAh?rdP;DCduw-94$n-8A>K5IKzA{5zOBRffo-(bYv;giogx zO`)^(DUFoBJrX_+7}!{BHP0+(MOjQC_j%C; zC1AOLy;TBQQ%pladg>q8&SO-`k8pQzK8fx(OW80@0pK!7)W&AJV9Sj${JW)qEJ6=F z;YMMY4Yco9TL%uNmjo@VS?_~kyKa`i-hlmSe%TL?oIN!Z$RKbF&24+gEFBUxGj?#X zRGGHO3OfYZWi=*Kb$gS|r7i1zRq^P_lo?dQiWZ>xonNJCmOxV|mF>16HG5TyA1v>o z(pk}UD51@?(3=Zos}h#Q0TAGq#yI$t^3%op+U+*8fpKU4^Ca4|eZ6New!&(qawfCL zhYhMQ30>*FgjdDvlMDfb2fuGx)@jfK>#&r(5*&kx>ObKnTP?@kxjPLoS^zA?Nhgi1 zbRn{R4p|-R_2lJ^=~4LxJho!6E!21;B`S7s-Xa6Y1PS3>Of&Jz1cj|M4c7P=VsgLJ z2S`GcDJzrt{|5Od3G;aqz^`KV|Fe%+W4D#=+V2R`Ac}oUIm{Ox-?8J=tFSg70b55) zM=x7%XT4w*As<~{;uFuQe$%tyV9w)H$_ou2j-q5$nHa%WdAxgO&vh|k07&Ac2` zD`H7lKKk8_^XY{goxPv4v8~wV=rvDc(9$g`eZgNu3nz>pAo}VZR%LaSWM~+UPAu;& z$C5%#^(bK!8cc{3i7X=g0aHY{QaM+u$>uyE`TE&tBz-M?Dc$D&Y};GE!pC7LU4YN2 zecx;R{<;h$WfthmxzUv#IKK?_j`|u@{CDFw_&41?-86oTmip)=GL~qN>nJd$SLO$O7ePYey(#ZIchUHNgu1!?QAH!d^z2gX@#x{ayw})@Nn%z2Kb$ZmO*r$z`1Z@ zP@9#0Hw2j^fisA1sZA93xC{v_RHJ6VPYL8Y`Z?XCdp2StaDpTon{$a!`j^@!&XkwdZs@2j4F$a*!I%1Y zjLL3EnJL6Mp}}}XXgI&tvp4MTiScgv*Jt*uQy|! z65qY3Ihm3t&C$0NOplB{eybt@bls_zp+omP&pU4@d3CjQ`rT_)M^wfYudkY&k(J+G zmNfZw9S>KaavA8WjE{*;>g9|_tOmIcA&#kfS#teOI@@Y4+C9m&iMqJ5T%h#o2mt>HAEBrFHYvDa2GIu!zVKd%45u*DarZ2+!v+(Q~8+d`Xd8wcO z&IlAG2{84rF^$ARgG0<*9?}T!1d{8v{-S-prt^>Q z`j^79WmbD6pqn{=n=q*JO+Ua4aMyAXxL-G3VMADLS7!1-{1sOTrRdrn6=^?+vCBs3 zrnk_=g5W2rY)Hzu>mKiJ*Ztw$UziR71cvYi!Yd?WC|ZD~zajbCMzxH$sQgo+860#X z6Njf#*>P%P*uIy@NQBGH@6W*v=qp8-d8CVlEnpeRq4CTPB^Hab6hvsOlwDBAlbWtY z5!5>Q3?HB{?9YEReuq|ae^ba7re1txI9C}IGR=TiWO1oomDxgplYssuJYlb?nyycm z-Id2fcW)y)E?r5-~fcG4TQq zgG{0fChcx5k6cehNypesu6p4=1jhY4wq7-(U=;A`A0=d>r~giL>}qY++3X?(K8=!$ zEu|E|0U6@J$P0K?d0hNZC!!CVl}hTeTFCByj4Ag|?W&B6DO7r}>=hJm({sC`lcxIB zKbCs9UW+IJ=bzpChc=`zMPsIhT6y%{(mo7EoN9glyEb<^pNCAb=TD)z3g{H z6(1=WQeG%8Eb&^Pm-!0a^3@MG$d0msl|9_l7IyeDVh~l6T{v1N;?H9Ka6o?HzUoo>Y1)M|&4ah=&J`mPwhtmg6Osoj_VJ4@HO{;U*y6#wX=Feq z%Rb3Qk~kpi*q`jnOUQ4Qed+jVd{sI9;hW1CPYt51K-Qpgb0!L^X}l|hl6uS~e$77H z_@Z^49+pK?QZ1$lZ1ha_gDg5JQU)?NohK}4T55-i!=IriKj`G$k$Xsrk8Arexc~{x z?=6-LVJP`{xFTb2>by_7GRx#&khp#qlF_1vqeqBenB#@uasAD`Nk^CJA+f}%4G^`} zvd@b_`y@u%`U^@6ME&jF`s+{|2L?)xEHt8 z=PVaYBN2`hb>-ex2v0arP9j%S!h*%BR!_jxaw(ory{jhg79byBN=kT;)Mpz_NFuXv zySTJpk#)ZMPA{9}xw0u>LCEVbMG;o)5p%zJRJ-9x5^u{`sr3?!uE~joPz~33LIe7D z%)2GkyQ`EJ6X&1f8DyrDl~d|uNQ=V?ACi|Es+=6uR{r(djfRxXuz_OrMhq!sa~$w| zv8BK)0l?3ujSl>B{gkhnMEMW;i`W1Qg{`>0$;WMbimmp;v#k zw)(T|+03k~_N1ds8%-2GpCx8)hq{GIQ!Z)AmH&~)iiyfVnVYP}0b!mpS^lGi%YkeU z@Kd&F3_rseXRkW_z8!+8p;EGL^e#0PH1!WIz=nkFw;VFzl$Wu@Oa-$ z&S$Cbk^C)zm+VWw6A~X&oVS!qMO2%i280sgm|-XLK(t%aqU6{P6RHDy^a0w#wK1sAJ5=!) zCQFwgeo<2PZn_{aS>zp3r2gTs5#@-nj6!fgc51ClV}JiJmBjM()bLkTnMq@g3|t)e zt(W!cUzH4eAXlHNpK3Ie9~!UJq^#{iLR^bPrJM;K zLeTw!7e`D?ZY!0f69p*cU5Azs7xH8vC4<5Sd}8Qb^N?D=-66qGspjl-1QGJA7Xs4i)`mW~CKd_y^DLfl!BDoC>-m z1O`rnhD8a34cYUX(~l*^-OAEL`Mu(Zh!>|I3D$3vrHZ`*%Gqq=Y>6^sveZKmCU6Bh zlelZ=3CIPPJMF46E`a8QU*T{oKq2LM`D2dGdBJ--PphKyZ<-+huwz4bAXL=)JTBfR z5;^cEn?{`MOPKqa?nj)%=8R7SM3JyyaO{EyKT&z>m5f@cMi*d0jxfNHOXXz5T8B$8 zq7V5!03pRd*t+!ufGnJRc4Q794G0IR+H#JrKOBF+q9DD0-RnHvF+AU*wxNOgmog28 zOw+kJd&t7Eyyw{{2HYp^{WK>ym_M}l`?sDdd%|GwtUGF-6vglIZznUep_X-^J7(|%6uL#juZa+;cO z!Qf;bCn{uQq~%-*}i{nIw~&ttAX+J`uR1CkPqu8;9}47 zPJkP+GB+2VVfPj!9vd5jBW--WTd}aV-q{Kw?%%(z@_xJut6C`24q7YR@)S^MDQ#?Qbi7XM{`1YsC9?(qrq28sL@$iRsD<*`rhw0)`H3BIwn>w= zPJ`M6H@M;VI#lX!28wi^F;uvm>OUMO8tJwQYSp`Si%~A(%H3O3^IB_%{!~McEUnXn zldr9hnKrzf;>b;M@bl+|+!kc8w5pBaf#@DSyY@$_Kd`8K-H6OPZXM5r!0cvfSaZd% zXn&$BD=U+>8wK2vEJ%NR?v{d_#(9FoPFV*ZBO=j}|{-dy>0#?d1?&B{gkj(PRiVBo6;JExH{PRCQDqv!D z0K!t7fXl7`Z0q76Cz32Lx2b7qx&~}Z2URa^6|O}`$SfC@MD!Xi~LN?mT!1?xb#0#|IKJgA`vh+Lh#Al^X8yywn(K3 zm<)i!{KMwvAJn}@NQCUi3TNKCMWe^13EzI8E(UCzH~0jK(~xumR_iDbtH+gbe~{Xi{OPITOt`-Oe0rX=xl) zV&t5pD?;VS$gmJmXi=qlG3&l-bHa@Ml=XcACXR{M22$F|aE>1zEgGDXzJ8{+JTR5b z*@pv>@y*T6e@tadyc|dh87@{DKv}Of$3I^0s{l(9Kyatn!&7aWX-!4}Kj7$IOKZQr!K^C0jB%&hqJT`Qi? zwaD|qY%gbIgpQwN1}eCWQ%x8}RWO5&j|Ci7Fx*55CD{ZDE=;g{%yR0-H6!ttYR^~9 z9RCGNH26PI`af%X`}^y;6QI{(HR%2XWcT!Z#@2!A{Exo@#ugZRzMl~Y0sp09@wuJ| z!vQ*Yo2v!|!AD~h!G|BfltA@IW6*0&0%Er`KGL!&vA)~f*(bNDE$BEQ1M8Uz4ekP{ z)s!2=T($&XsR3_9hc7>{0&zQ{aaQ=%DA2Ro+5{k6rV|-s0RJ2?v2XNnv4w=sSvn*3 zd{wb*HvT7i#~^wzMlxQRaufsW0E9_^PKBB`x6edevj5M`qb?Q7P)EYc?V~b$z{0MD zi?V0CVf_mk-&+D*0bMHB=#bZ=kaxl#N=9`Vt+9y)yQbRu`fB^F?l=~131xE|n_VFI z#R#xT1ATiS>6E2~aLS zBVqw2tq)0TW+?bvwz*|x;Xr&5_h&6L<7bM|0=2^lU&VLUYE0*hUcT)W*FBx>)Y zJTBKIYjv0vdM#23=&2DUqr{$Y6)9o*YBOwj2`LsUwpXW@FTCJ_U9f<49g);TPnDw| zQFkJ3;-OWR+(uxxNr6sJL|xovwS@LN?~p8gMxSiK@^z_LesPG|p^r&%lX3l+uldMK zt$=+)bWf>SPAO9pd)R1OHJV=kK(UUV)($=IUXi8%NT%|8b=dBwe|(>R(2^pB^x>%W zgQGo*UheR2kb0y7+wwXpis^ucYSwS2SCI&Wy1CHYrX;+)14U5&1RV$rV19i6X4Fq{ z4+4Xij3Na<{io|~d}}Rkik?A0*g))6)5f_OkRXG*o=G4L%C*mL}^#<{g$ z6PCB#X~Ccp$(^sav1N=wE?G=Ragcic0Yf*`ga%wKvnr_$!Y#ftxmGffrjYY&$d!NG z?Z!0UntJ%r1Cyb3`K@NbclaVhplSCnId029#-I|-p5W~x?q#POo_F$)-Phphxj&5nyX z4_gc}ffZ=oIUa*R#sMGxy(B*GJ7#+7ccnfX?V1h(n~?B*6Yh7v_7w z1@&UJ{CKif!j;rHD~P%tnNL&Nc!c-&XsGFx3TH>??U5lR`(m0hk?rU$dDgQHO57#A z$SZO)O*sdb%U%gR2|DR}>$^3?d5Ir})ReL`v+mm|gJ8T9~4yI97HW^}|#-D%>*4QINI z@7-gPlz`3I+~jhU_MsA*0@L<19z?c{aFC|BaB(t>Ir@AgYs>efp@1Wp<{63lB6#IYdcd{xU19GC97+dG-c;db97`u0as2Zel!rlR~gE*Wu8<^0xh?4gI-prWlfs6Z{_ zGoPS39x+FF-Aet{a&z6N)|H^Zi|-k)D{BxczAdkp$^^|COA@~^j#(sLpMe*O!d71S z@u+4)!t;81B--y|RDm>FugJm-)m0szlr%hEnKkv|$ttJYxERfTw8MK7gMTg-4WGmQ z6W9$9x)B5s`*Qm|j_5N8faXL$v+vX$qwe1DVRgqDhNDp`cYYPl=0M*H8+ae?5YkS3 zIeD$%x||J(YL$;-X@`I+Vw zp}fbab2-eFFgtBHP}{F%1yK)JBLryFKOV<L4ChD8PZqaixq=Kk?AD)3hN&9B}DU##U`YW)5=m6O$M zO^Yan6;m}pv0eH!{-P^kZ1r}0W!2@x_|0ltnS?Twvvhy*-G^eg*{@8muMUC=dHY(R z>Z|!c$Ee*QfMa~PpkGjK2Vc_Q7wfndq|NEHvSN3&F_1av5+pB-2V>{=hAa8Ht2ktZ zWfO+0@9Qx8ZPj!3Tm1Wl%x%yeB}1+gpi7zFfA8y0*xNBP6MDv2^Y(RJzhYCu5L|EO z0Hbi(?PYwvZoC~ddg%K$@H@`?;+Cpk006_A|69Ae5R{$h^R$dFxJnK`7EgSnX}ZAZ z+Xb>iF3cUB?+kizS8x6UZ-bX&L2UcmvPLkXp=_2*dlgM~Ti&+3)*tVQ{K%w+sI?oa z&wEg_Qt$Hp{OTi|zK3rWS?vGP+ZtR%aL3S^ZpA@Mr&q1qtYQpf$F)q84+*l@nyc{l zlHXQ$ZsXriUwP_F05YwBeLEGlo;xX!V)=tb!zY?I0GhTXgwEq8e%M`6<0gepFVG*& z-#Pu#?**E^W2yhf=iX?!@EiMsw|};>n$3G4DyLoj%USkFyQD0?D~7NN#-t0D-D=b) z<(mAo?!S6%aL2s#^)|at3#LvxneU0aY~{w{6-lAhjOYd%LBxjYG`+P`M%->UIG!+; z=I}v}_9LbgRRJ>umS(HOrd4@m@u{dnzoo?jx4~deb}px_j<+u4_YAS~6g(#0&40PK z1V4-`*7;d)RmlRo?(RtZ9xtFX^xHy${oeG|bRWe6U5_(Z!=0EL;S4+_6RYj*;&!X0 zR;1_$M@apl);8nX426#*o%A7T4zOe^D_``O-yg3+hpf(%g(5XoI=;d#A`sgwee49r zBF{SFn)#8*K-X;S?i84A+N)PjI^%=_fd&Gej*yOhC>E!yOM*o|s6cj&joCQDSvB;( z)h8mVkEyG`BAF@3PhhkudoegFs=7VBr4-V4U%H3;PFDJ2itpC?O2zf+g#y%tv7gPJ z<$gAtQ1`@s=+F13p|&{QOSPfQuBXN57%{sfibeUFP2L!y7pv6tJlDz8Upm(Y6ilr* zd_VCMaW>RmEC!9RW?Y|!GKnR^9J`)vs-KTS674#=9-q%f1jBtAJe}HbJD?N~U(PkakddC!R2nXd`q=F#LrG-@^PSM)(NjwV)ji3~(SV z;?;_eQCqyK;cGe_MT;pVbRT=Ql&Q_gi_;O>2dnwkgd^UqWp-qExXLK>N*jKnp<~4x z`msqW79>_E;3C}f!+W)-@-5{Ucd^WCI>lpqoqQ4_pv0`B`(EGkR};2QSh2;Z`{8HT z0MVBTY3gfWUq!l3BL~+-OaA?1Rcp$KzIO&NTEL>8df84IBD^muPGk3G#(RI(WAc5= zOyh8LX3a(Vx4v(*J!vpxUtRP4e56THXh?-#$aMZWw8`xXo;K2cbTf#|W6B_kuFcdHG(8xdRZ%6?nlfOZ4=+%3*eHPyE& z%g@3=u=EN+sD!|)qD6Y*!z>D{k)5RyMS1{w?MZfW}{QWu&M3 zOdE7V+)2N$|C3tJQ4_Aqp(oI(&mf4rXDjSc$n;_|>Fys5dw{6U?a|1~RT-DZ-S1F$ z+c|2emy=#v!d7wnuEswM6PLv-prxTA6_Qw>zD-t*W%4mLF;|E0eqsq$z##uDp$vDr zEK#Vgm>WkqrzZZwWh~1k<0;r8+d_zmyPT-FV3~aP%Klza3uP!_9ftnEYAgLV7OY|z z6j@9rC;Ukm2g`OX1y9AWO}M`9%3w8?1=9HkcX5&tw*i^NB^?)*Xmn!3J-y7v=2MRH z?^6-eisv{V&)e-52+GM{Sj9c`K8)5vgUYHV+{kSEwTB+Q?XCdfBi=SEtESTfqsPb8 ziW>VKPby?WQxAJe;i=MC#jT=v;(_keX-;KIG^unI71$&6G&BbyEq1-~f4{#X3knUO z5Op8xdygl|w=C9ZbE(;`$Z%&I-)taaSK1Dsq==Gw!hB?}tFQd=3Zyt6M3o+Y!&6^` zbvs4@v6?*SwN~G$l)vuRyj&d^9jd9LM#Ck|%Lk-}xjs*RT8o1FA?yQPj7HEjkkR@& zm-wuL3(iO zf=EDQfyZjcJmb~)^ZVnd$|{cqtH3cnojywX-Cfa-%KP>HB<1a*n(?l$%oL;_f7RA3 z4B|y#PZ_lmEVXcn=jgDy5=8n`hK0VraryeJ!n3;`6YZOD;P6!M)W!4K(QZ_QJ`x(_ zLGK+w$Cp&7dc+6z`es|;rK*=14~(bR!v4VtR7Pi^{A6DI9e`T|yzX)pH`;ZlDdzJ+ zU_c>#-EK#DGTs|Z4$&xF_R)^H_%O`AcutS^CsSW>tsz-%*cUxZ%mq64Lwp+bs~MF%YWUCiEVB1XrMQ zIM5B&)%CYkz(5vg#y0#{Q4-`oq?aMo_l!E7xduHo9|MR4ygpPdUOJOd`aVJ8-u;|< zA`g;X8!?SNzgQ$x80)tUBfx)k*mcy1Bx-%@+b>B6=wBlv^qdTL12+aFKpTCYA1=puP*Bufqyf5Pz{g0U&g1UyeD)cJGWczwZmfE z;R?layxx+u?=kp#V05&hg!zL`x2gp2S6O6n5SRk{3Qgd4$b!U@r#v`dW%o^gT7vrq zq3e>z>xa1)j~C zz)C4#votzKMCL5nn*ed%udkHy{F~K~myX-P)~fTvr>BLv7H z_g|H1FTSI8C^ns-swnPy!4kw>t?wmZsY)1}Mx653k=0`{t@{xi@VXJO1#@*gq;>c{ zeE6@)``TZ)+X}wG-JQ&r8J^-rIAM*%H^hzA?A*8!;2KX)JnAg0$Ci!$()cB zYp|s$mfE>x=@Caf0)hgYm4%dmD-0Yc=-34Nkj2+Zr(ntD5F{Imsc=U1fu=!fj#Z|uPp1A z2yOMY-R%K=bu+?<>KEF}+l~tNv^hhG03h29#i;r;k`*%emIj7`$-$PhJ_$67&k_p8Y- zDX?IoR!+u=bEoa=0+98%n1Pk`c-T=% z=Jb@i#pM7Y;bS)SX%R`OH5@3jielhDsNWNk?JKuY1w#WEsVf?9EGeAe2`E?$^e- zWMqRFEw~F>LV1!sT$n_d1WoD?ad*0bNNS1Eky7YaJ%)k-onMBl5=M1Yz>f|=p9k|1 zEV8mPch!IrRDrM(YJv}X%zw_>(~Je=7oEqEDp(LQf3;vhVqauef$=-i=I1*x`ZDD88RZxuUW5dbW z0CfQ&j~FaoL?AU^u7dtqBN-9l(Y0-Wi5}Ik9?e^j-;LRKPT%M;Z?v_Zzo1YIqzcx@O(^!T+pNpMdma_@hs(NVfdm zABB7%?;2G$^gUj8!xwMb%AzP0M1C~t1kNly&G+I*gpL~fw~pfn-_mL}-dd}VzUB)& zvoDN!!~=Wr=@xX^vpq{`rNgVD<1}t>?wW=2Jd*{5qgK7U^BL^NP(ER0?)~8R0XBMd zjqB-Sa_fUp?hBH)>wjX41?uM*dh_o5{~g&Chy?<<=F4_R3*N`;D%!etvc!N+t3*gr z9OfY_eL7leJBp|M{ak#;D`Nb2>s_p~Zq>0<9{NOiF`Zy0s{BkLp#R2{qK%fM`<7T- zoNb|XrEib}-K_c=S5Way;Em%lCb>J&U9-;%F&h4#|G&5~5`#oIoBz`SV36X>wS4)h zDU0RCt{N^*fPvXPBgIdLSHrQ+x2GxCT7RS0+!)1w#jTa5n2cL20xut4 zh{8YIBD;g*=T3{-60(10|D#2KKEnTt2jlntkYjArEnXE|Nwk}FZ@6oO zip#?COjSbj->Cr#fMmuOKZO@QHf8snVdc~Pa8}ie%Z7ln;%IEzo9Y6ZGJUWzE51j; z0DzV3Km_z=oy#%YcXHqpZGH9oxm$cas81W#yV3{JJ2!0wKq$2QM1S8IbCeY}-l6^j zPptP9fWs2FT{J_*wj|bd-Ips%`+O67fCw8}*_2Xr2ITJgMhYpqb$@U_R&%XyP~YfL z!|y=)!zS6EqO2!m#>uz5jCM)(nbje|oj?EJXCuM7Cm-;M<89Pwqm@K$AdGxxo-|fZ zeW3b=hck|qO4A4HUn01F@3}?Ttte;nkYY%@4_q*HW9N;`Y+E9ucYWPa`z_QF4yzy- z@3Xz%K*$`qWMy|}bJ7!W=eqvvX%sL_lAL!!$kkA{*_N({Nh}5@qD|B5a=$7zI~%xr z9ggq5otGHnm5%nC8VF~e;IjRDYdv!9#yat-#3i{TGgtRhC_@g;kZ~3~z$7jlQv&r} zMMX?kS65mONVx>KG<3L67w-JDBr?sEQ@SMaAM#^9ni)7qx2Dk;1b;I=e1ZcwFaUm2 z_TM~Os<_wymMY+1>JCI{R+z_Q^o&!gg<#IRc+M|4P2@rrm*>B~wz*Zgzp4YL;1n@Z zJ)OFknanr7DfcQ^FwLyH&x`LcZLMTZ+SLx^#oH4CNR!5Fpz zN9Gjvhluan%(96T720pN3$yD^*!rBO+gq`UdGo|lU&LuC4|u!G{lNgBwB{!;Aa>4} ztxnR397GsRT5F)I=uxgD%?}E;&*FanR7Dqt5I-BqCpL8=Z#WJAEHnfWZj1@PSla)`*IS2G8FX#mo9^zAQaUA+ z?vjx17Aa|vPU%LZk#066pmcW$2m;a#(k%_|?E87+dA>is<1qFCJFY!5*UXwVzjdDB zzptKd*vji2=vlD9g|^s=Sy=f91-G~rn9y%oMSL`uO-5jpVz^9_u5A_>7pw@!Gup{W zH8%ZOZ!aB7I=*atiFWvl>ABBk@z-%3KUcFdU!9Xfa^!;Be;ex$182K&hX+^TE2m?r zIR%PuG|4Oe)P|nt_`)X~kzt0?P$G+DoK;9_HC?Bd=r&m>s$;J_t@FHUsGsPl;;>OI zLl@Q0DkDNKE;Msm^EcnsF&LmuX&;{kxstGA2D&f_%~^J-gT!@;xO47|e#Q83n}C4K zt*@^Ml9APVRtqloZ|r8@dS5@p98OgWVo_?Z(q~_61Gh;S3jQCQ*oX@bVI1G{pv*y|i_Xhp3w)y=$W>$)6+B0g3en6c zPTnelvVggVNg>K%b@E8=Cj6fTYlDpeyF&2;J2(5Q!ht{%md#&<>Hq z^%bQ<#MQqy(=G3}-A|%(id#$2B`#7uT+Vw7P-P45*DGItDViYAEbzLXZQ9`}HhI$3 zGr}ArujAzLI9e@ks&>AK9(M(QOMG{zt#YE1zDS|qtbtAcRuUui&iYQyNaFx3YjRAT zrdM^U%TnSXk zlryOu8*kZ)iKGLboXAXG^+DaJPX1Q>xpfbG{^Dez598)=J(MiR$a%FZnR+HQ+C&TT z*}QG}<5BuY;mQQm@e0GP-hs#08_kTF4E7jZCZe~29ljS5;Ozz0nQo`2wOGz8+DP-y zTvZ8t4|Gh%pM)Nis zT|!BTEt1M&z|kr8G#L^NwCPuc;ugHR7h03jRAUj^v!eLtLrlRO(T1&IT}=f8To%=B zX>IQ8IBfczK|pq4rVS;P+KGk{lVZ$R#Cuyfg&cpzx@UE!AbxA{<=xppk>d4b%Q@L} z%j+k;HTia)cht={4{yFDUO!NPemlQficg)bSle-IADgXYH~hBpxajm3vH$Wo2lI7i z*4Ch$EFoZTPQW3k5%sA#NDN^= z#1s$H^;?Q0RI8bVY4ofHK0YKqwOKzoGk-nEy+tN(70p=x8Fgi2hbXmOcdh$O#i_$` ztQ@lFeo>Pte%U!@`f*3RVA{y{ks3ZG4JgeEU(kHvKGX;O(|y;=LA< zC%#q&wZ(kH-S3&Ri@BY%<$kRDjl|@|hp`2Su;8Uorik~)QS-IJFZoq<|Dd*>ms5QA ztJAtaW^$;#fROrfDu{qJbvSa31nv~JYLb-5xs&Kq$4!rRa!v;<6t4#uS;3ms$h`c~ z-?v`%@?%uU&3gDOEV6EYn#6!Cy7VSwzP2>^w?Eb3eQixNuVcq!=$eGCN`mUNVX>mz z&RJ9#U`~B|wflAQ*LmUd_!vKj86uahjjgt2borB?O(tEZij#ijH@{W%`OLmh-z7uBbI=uj!ple0 z@ySMiK$bYRzk=s9w)->pjMb23!I#6sXOK5)@0?dMh&8?ysBwK%9FaO}>%DX?XZ>Y8 zjBM#;^a9^jHXS>P5NYz(3~!o8(!fQO#1t_&UD?~!ZvJb$Se#LT+*UQowckQRm4lYr>Hw~2ryT&H*uc_ibKeDMAmHcSS z0%x3^yH?)@a-I}AU(^wml%~D!i8$vV8ULani9T+(S=~)I;-St zWG-WNx4gWnCI->PHf48pxTIkc(z7-WHfFZAtnVh@%Ra8xM{Sy`GidRpm&8zER5u9w z*t_6qj14I4Sn!WFQ$GgEbIC8=R{#CgCL|iqSl>Vl_oX%{U9vN6L$-ykT+PL8#h-LR zdn)VMN88e#{nOlH((jqVj+T6XaZ;+ATo)5|#83|q>BNnvX=GzaYsRaLT14j>ou7jP z+N%0v^*3dJrFwk0o2oQuKtR8cCt65){WW*^jPwQObIYOc3;UtpmU@3`he}`4lm}sH zfAx}k{zjxARnwc3g>jZXr_b!nr)oz%N+eKyFSan;4_#xr9UbFXQRq9*Hvdtq!qcd5 zj(fO=ODzAI1^t3LH}*WspQXw7Qg1eX3=-9=6A6z{+X+OyC@s`Vx5!x%+2T4Bu5cND z7p6omi-}6&B)jD&s{OBVi750Vkxg|685R+N zrJ_BA?za{*MSE*SQ^hTzo9skW)~|E6JL6o#4(B;N8@-k?m zW0Pmbz6fis2EZluGJ^C?3wPw_LP|C#v4r6M$ZN>-)RHqOHC;N8eI${e!;p(o{bP5A z*41F}Ek(Izsi%D}xxo-6QZZR#uA-RZ3A)g^cII@&WtS#`61E0kx@58PLr^TsGdK!v z`mK*15&Ek7g<$#(#jd%B`d?@GL9oeD&)*kZC<;;?(O4bj5}&3QA;Klr(lolAfiL5q zOz>)c$39XNy{L`mv8F{GQ9I9NB&v;a{nMSld98jLA-DFZgG1{XZv8&(mU`%U!Xj;k zcC*S4FQ^L{T+}pURN$7k#gNo81m1l zqR#SLTNb&NGCcEtsOmx|3sf^vzoLWp3dNz9O(@b@%(mNn36Bkm$)ml$1B{x=)scR_ zTlwhKL_x|Q(w4fi<#h2gc5R- zt3#L?t5uRT5|^qt%^IEJ`_WaU93Qu(vy2=GkI+oxppP#8R`|EWu*)C*T{?gmz zp{8ggy$Ca-5tInT>~S)*Yy*%WjI;yzL<)h5a6$u++yPlPfXfX~x?%z&CEewYW56N; zwB=?!nls89J7;_V7&O8B@-k-dMvI{=uNR#VN-|y0{X4|=Va^0Fs_=AUpw9o{_J#E% zZ|v?=3CwCt6v#}p9_<4UCPw_oKmL!8cgH+{Dg!tk3zB?MLFUJcLQ__70% zub;`NsS<+1YBjB7uyLgFId~}>OP-9#9$Dk!^%>v%#oz%mPe-*4xpDREcRNHVv^Xh4 zC8hxYx$Z}cLyJwW0Mn6Yo@@6L0;R&64_7NCMMd-$%lKEO9K>Hp#oWr!d6gB76FuLa z^JEMtwK`@uNMBpD3$xbJI#y+?YtJfRz!B8Qw!X4_MNb%HI>s547(SV@aIQ2~9vn39v@@C?(8hbyHE0GCU z&Cx8O)cxv?Y+&4#2720H8L(CqjcZ}xhIXP6yPF&TyV4PG22SsG>9al8(JX&vSfE*p zUaulJwBK0zp9E7ofof@d>~IaqfBkXKMu4}`NDLVduH-lCUvvygX`NCyB1!PLU%!5Z z**C&gbr|{xbc*CaAPbCgI0J4JsXSLdZKhSXo}uH2UemxhQ*bB_UdM|R!T|XVFuf*l zIsBWSrC@^=BxZnN6b$1$14YcP50|s90GhPCbRj}3#Mee(1)-8IeFY-@p*I}roO2|+ zBwmD5no4z>cf+^#(D{YaEhj(iPziSOP*qggq~C_6c0|jCh4$kjdTs-p<h5xd9j;ZoH~ ze!c98(6JH^g)Rc)j78uafl0<4Qr+>G0gBtHSxs};X1<G29uVbYPE^LSC>3vgNB$0Y*%IiE3$ zTY&jYDT6l>h)yNJ#)&D{V8H!AKp`aY69P&tfbC!^L;!0a1a6&;7n6z_ow@*oMnJ~Q zt*OBSY^jht+i}N}C;(Y0ojTzz4i{2^SsP==`LvG7>AwX>MiC8go%CszC-xscyaQ3ET&G`S<2%szgW~<8o~S z!D885X|>EHe49k_n(^VQwMF0M-*6Gqec1W6=S%cG*T&WcqjvYJ{Q(g2%JQi$B7YND z{NXpEFYjOE?qkJgB8N^yQ9-JNnmO^$&bNQzqv4^;)iQXxR|=@|H%gw&w_xz^Mm(pi zkW)*4rw}eYbK`q);aw@!p@g0oLG7M5U2dI%YlnkB9s8%<@K-;}ozE0j77$l*I!SwA zF?}Gi)FP4W+W%FGh4_~k$7ray7yVrxljQ7NjVE4Z7tNYA@A2m(h4u2;{k1hlDy#mR zDYWqCMja&)lI{2y0#LN;G9A98ki35A>*7RopP~!>Epj0eCztPH{LCiV%3>dTwBV|m z_gElRjqB(zj81Ol&8B4A879Z#XVA7jj+`iXSlvn+8`q`q~~u~g3OTuTcD(> z=VZYkzYdYiH~S4_y8RA1%1Gj-^wbSK*L@U8I4QN$+lNvtEYD^SIlR-4%H>qjlDVbe zqVf(GBY*vte(^_E^Y!P+L38t?O)EE3KKq+(if#)mHMXfwbo5csASj)!?Jw}!sXg3n zQqSnK%P8pjsWp?3NA7DrJhaevXS(#ALwghpuN_{rnjxs2yG9HfIJ(EP;F3b429Bld z|Av*w#bbMYS8EQ*&;7un?}`fe6nO)RU!_!u1MkvbG$T9hHIG#(e?LHyuUXNml3qo)Nx#RxL#p`TEqA1T4s0d`RweVXb{sz^JqEIygg)~Cq?;dgxxYF z&nx#^dt$L%I>N%@cfV)yFaO4A>&zw;tPwV*ZOuelF|Ravp!ZJ}U}uIs*B`T}Px@Si zaa^wH{cp}n;PCsDwWFh4!^;a$NTQC#m9U@z;BGvH)VJVx7_8b*C_sB93zMYjUOwO5 zEy)=J)6Br#amV=ixY!CDId3d*w);Y0QS7!qa|*zA7od3r9GJiaRa{)0boa|Gs|Q;s zX1ZMG{HWzPf8Sd+Zu<6e|I|}ho*6B?2N50)_+Rz@J6yn%e7|Xv&isL3`yM#8y##is z+oS1;nH@7T+TcMCz~^^?-y6&=RRAa|+3&O=iYsi|MAp>`%ljaNy^)yEOb#5EYiJhK zl%c1L%}w3>%yf#)mKj^Zf}R2WRV~LEl;Fh3VqA3jo{8=#0gASIM^z<%r&)beD=|WA&ak*8Lx<&HvV)s`achbHvTqABSGYg-;nA<0av2wIt zL#P`kvkWS)4DIUqR3%4LK5BOYY8Y*$GFI~NEHCc*rT5>3me&dDUh+bE?lPIL0o{C? zk&!0MaBZCzh$bVEfS)rf=V$*60+*9hN~OF}K)_nlW99b2iR0bTN23x3++4?T<5NGG zkF|zGVx@G5RLTYQ#bFuZ5cceetlEZtqPgDoy3MC+tbnZeT`L^PJhld@WxFYa$f1VE3a-cV4zCTk5+}#FG9l>)M zp8k0X11(w-SaA#4^ili$nIa6}hiRRGU?(X-5mrj!+Jp5PhOD20l9@BGD(Hy@7u&!L z6=9a7V431ISLwJ~_7OPgM1XzJ>D_}cAie5OdNAM?iF3NYW0Oy_>G z7;3TQGcsUhZ48T8Ky(ZOCzvL#QYL=_z?Q)^3taxzxcTYm-}7>SGBNXs8^X-mnRH~K zfEvo|sF0>$qR(KQu_=d2h?udR*UyO;CE0l_HH(F5vq@cSARFx@TF8u^Q9RjELt;N9 zl|NazLWjlaPPu9vkJ2$dYlbIZm;XkPrQzCFbT71X{}gxnvd~J6m;lX0ec!|1+^dzU z{s-?=wNCXgMA?h2D5OJDi%2*FrDHaFc0=N&PrgzsZz?0!wJ$2|$=yAe&2;o;6*kJ~ z5Jjs~AKQEg+`kl>d_u;iMU)JbJ6}EbHa{!1Nimb&R*(~o55LWTP$|cb6fDzr6V;k* z^O$PRmSG_No&BS`=zYMeM?~x!!@O!-O#(h_faQtX!TGJ>@vnDzfzW)_eVp8ZEw$oM z9UXXi7jErJF-T`%yPpkvahfuTmn?x#c|Mb;2$ioWXFESlJtDLFu@E!I7fyK=#2Aaa zXL9FkwUFYAo8)Jq0*190-(TFa!3m%C5-0&<*sqT5=^YP;j-GAC0F>-_ysQ@Zn;Q)C zY)lgi@E@M%LGZ34QLOu8oBxXmwtR55p1{L4Fe)OKgt!>g2P++7ZfxTJv#>=3B$Z$x#u^OLAI@eg>OH;!wK-sF0d-jMC{&(-u)uRm6syM+=qa)p zHhxy*XbJ(DCvL}OVc9s!$YL8|Fc$95Qad(ZcidpXqFD%x2=2IBI&OS=yz@HgLTTDc zG5A7+N${}~4&?+ErT*lbb(*tCb>2*n1IYwn9{CFFC)WnV9$)GhxoH{GKp`|1L{BV} zodoZD7p#b|UDKDb^VE~m`gFAjF?V~ueXwSLqC{9n1r1irX{mkj zP1+^qGE>KHHP%#qp1V(a+N0&3Zbwv7!z#HtEqrnGD_GT=G=XV1HaYg{&4%p#w+Z|+ z(tsk!dN0Q_F@6MR|Lvp!7D(!^(zunK5}m7~tcL0&Ge_l+a_iG?ZHSyjNo6HfXoPou zqP)t{WPIpb=AkFwIdJQIua15pbQs~Kq4T4-Ds(U($j6Qp(;-e$y4&g~*AaRtzRhL@ z9y*M((VjhKiqC%K>sUuMFe_fa8>1{=N_9V+2VU2vTxs~(Grz%liw`Og@z6s_#r%aq zr+)wOqsHsp5)7CwQ(RiaudnR$+uE`~n46sQbiV_NN5}+i} z`^Oi-I5Vdq`qY!QW50MO{?Skp<3W&qyav-uB35iDE~q*oh?TtoJ(W;VTLNX#G4`UL zHS&1YW%?N`Rlk`*0m@vxy}_A(3D}PTH8oif`yL)14yg+Da80;n!Kxc59_oMmzyo=Y z@E+JCmFYI42dER75GH>05Xqz2{S(+)C-*nNo%l&7i5tUJs|$`X$S}LV7TE{aj-z{VFAyGgPdc z>)9iBw40(DAr~g0a-E4Ckw1TN{Gp@c!2YSKMiqKYR_?_Re;OC7^IZN^DDE4XXN=S6 ztbPyZpP($B2%px=IkkfldN2b+AN(uQHq}S2niTsr(DzKO<<_hT ze89g{VP=IfbBl|a@OB6P@<1P8E`X$qtXfjiiP-s%$UVaA;}@Kw}3A8JeE93h5cRi|fpZ|Nu( zcip6MWq9x#$#>&u~*2H523KyFi$3P;1-Uw@%cfsUGq)z0IF-FMHGpP9+j`1{Ich59&sdhuO9YC z*NB|T1MRPCFX0Zf__T3L(8rPGd~EZY)U=H&)RSZz5bTj+?FIkJ%$Mch39{7%R*$`8 zfDfUAFTm{MC_v77t5K}926lI5Tf@n|$381P$5-a0vdf*FMfdU}K2kOIY>dhr1{!ZQ z(LdJ`2=9{`j|BG)|FAC_6oN|YtTVW2ZxmhV;J>l;l-NkVU5=vUEQ^`5Z+6DbbTwe3 zR}nI|OPp@BJO4V)LqDVYsUr~!^XtId;fsw~GBvKcdwklftrkpn#8)&le7&XR zIX^VbF`6w+*e}luDF_c!s%?DDUb`n(t`N?RfC&#qY%GV}t6Wj_s@cyXS=J z?jlt7Uz$uqL$4w!*Zxex$0qCCkVsBY;oV;^W?A&DWZ5R-Wjb}E!Tv%xBB1g#(>1{c zs4+%liZ)oe-*EM#rB>8EUG3rD5>>0ShTgo0PjP8g7qz7-QVZ?zA_!eHC?m%s&Y0Nm zJ=6ZH&(gI>BBEn+_i{KKbP?)wRz5hEJy1-kAM0K%eEdya!J*f z>37==tl1?KBDueG5H;q76+ocmlUA9+aL1rM=UNXSf);N<)x zzgc;>_$}LsUy_$RmZ*az)JmZ@UmIv67%TTwfA~n$L<3d-q&dT#vfKToGWbU*4auI1 zyQ#8=UF6VJr_;L>d1_9)eZ#>vy;z;n>7laqgmDSgD)sUrOf{w%C}Ty11HEcLAk{Og zR^GiIsR_>uLB?j>n7hXD8p5*exE?duH_K+bFZt+`@ z@zBGl#wzuL$^Jo;3n4+O71_mG8W}Y}XB+^&+2~XfCCp5m89LFAaSQaKCklK#_9!S6 zzmBb`|3F|aXRw`I=b=YwR4~jr&^Bn@f|5F_<`Mt!eWlGve4=jfH#0^jhHsLYI&;iS z05mzizmA=xWBY!-?pD=e_RN^>^DKMihOg8m`wfde>dapHqpe#l|Dwo*O!SoR<0kQ5 zEo}{56|LG@9dr~4Qz*3gk2I|iVWeP)P@o$v6s4%NG_f$K(_H0$pFldqJeZW7Wy7Lp zHUB{F-;opMu%yZt>%>oqpiYnY0sNr(*4tOqM3&6qKS}H|H;H1j(3?6+jzx8Yr?Z-n zWXYP5feeig``QAP2}MeSoIgk^bU&|t^jB=NR4n_eb$-hpF1$&p$gk7g{7%J1&{*`r z=nRg#NV_+BNn6Org!Sst;6szgUKxwqb3I1WwneMp#1-b9IaTyy^%7Zh z)Xc5db6c`-la%Os+0e8|VqB11Ws3T85J32qTyJs(Y+$b+{72eVIs9xtC3V)`ILI=Y zRJE1~SDJ?E|2|;*7^;6CRWsq%R|lk-lG8BMqGUtH+`B1VwTfF4)ORHLv*N1;4fggf zSoLGoj0o zH0L-R6KA3D9JX}E{TIZ@WN-bp$U8Vh3d8dy@wSTr4lA=`8D(-krI^Zm^I=pIl+aQ2 zN2LjCU*Y0%E>Hp6>Y0*+DASs!zRTgzIrD2eOBp_Fa~3q#@q`Z7uMjyEr%r8Xywy7% z^(*9|GdhD;d7mPovin9~6gRol4%&O?O}rHR6RwoICDcMSj`QL&1CVTRp7qoQGO2R65H2=8* zeI=L4JP-YJ|99Tc-0)aDX>ab09PqWZD2;AkAuz8k-kRPtd~|T$!;Cg*sx)xl5UANE z+T&yT_#DaT}RgZY?h%6tfsx z@XXOM_Vfk3-`p+Jit>JQ6ziMaF(9hKyyGBNO-#g}05p6cMSWT?eQM+F= zejeOgqEMjVRDTmnit z$J8*n+LI~ou)MO`a5$rhqJ3FtR>O8al;hDArno{*LqAE}G3sn@De#dN5q_f8zg_Rv zs@`ttjiT*m>)(TI4G}?NY-=9q&t>qw+pqKr1vJK~7XI-^N?z~6HM;0AYT2#-9y-@p zMCR7>wMhF|@gyzTi6(iKYS^xi0N&j}x95JqUsCh+Fn?+bnwUcEtC4fzFxt86QrKte%yE^^XG5C9Bxr*XOq)VQ7xqG;^*w{y2{cwBCS3U%^4V|;23q85X3R_s0)71 z8Aeue??`;TLbR6K|B6yap0cNsw-pkz&%{mS2>$G$$PH!5c5`uNJ1hg0L)+w?skn zTYLM!M?asrgOAhj+0vnLT7SoPJaG8ns38cqmwD`@E?pX-$3!(}Yv9N$zIh&ET#X_# zG`YucbJc*s)zrseNMrF_`t5n%-@lq!6L}%h5?#mV`Aq2kIVd97`BBx<%*{^0LvNwb zTpRR<+m9uOPjy#Ir`m)&cjH1WC5vy{G-YV=^HFt!5%r0JFz1;Sxq@ONH7YPxUFqPIDD}~V}J(I zt< zVF?3_%5CKGO(EGs921Evc%Kne#2K>d4Wpr~U5VYtWJLpGq-lTMZ!7y3z9;M7PzHRF z5RmaLN30`KgEo_Ka?eO|<#_#GE_T3C82lztQ8!}_LO%=Z0@m@ogZr1r{g{5(k@J6N z`XVP&Sv>xFj;(P081OW5F*(Ca!O6#uMBFPU=ejPq3qCYxQWwLqeCaE)uENcAerRo)NguZRpEP~C%Y;mfv}_Uj_7z1cbwE^Ha?Ou zq41ZMM}~ptBO=sr^Q+u4-Ny`f>Ix0orj$j)#drU_e$iOx>P~StVlU4&N7O!0&kKVpJ&hhK><)f)%_V^={_{AmQs9~G@!2Jd*Hmn6paOxaQb0_&l+ zM#yOqK|iyO1%5}it~xw_=Ha{47u{*wHhAOI(3K@Cm?B0!TCNLH=shF3B#1Tzn#P}R z1$w>u#5HH0Co2@;M)#@CqM3!B>SAh5Pk*y-8TeGDu=BAABOoGsn&500KD*I4`gaqP z1?MlvM#XfO_B5P9buW&q8e*iwhW&}*_RPSchqI3qsjid~^Wu1|PH>5>WgBs+t_Mu- zD4ACHJ-3mrTAd;z%Fgh!c&Ym;uyE!+2H)ksC&*&@Dsw=96hAshkJ!rOMXCA~$AcpC z%*5+KJwaK1TdIh9E5m?r;Q7vMtr}Lh8GpOHu{|_XBVROyJJr}8DIF)-%k<34smgUu z-)eLLLyK3XbhH(h%vfZ8HO@7nW!5WjjVN zXTeVz*`S`;@TG!<>K5B7f0Cy}-%#;RUeR#0I`#=otLh@-86gXf>2aC0M&upQ%}6K# z|JM7drNSsX<{tbP-7CMuTbx+e+op_n`bK@G} zHH+=gJ0Z~>)uV(lx9l|;Do=GjeP_5%CYQHaJD*)Eg}Mluq&zHI*|sUwv*OWDy1lRk zET+7$-Dvp-;fWmLXA= zQ@C<)Ccg{==kgHgkaoYj{Hm(AWqwnpzeV@7c#P~<@aM|T0u?4MckKjcIS zrQPYK-(w4V+Cgirn(vtOH>2#Gbi|_2!s)a`OT&;p;&Z;w^LBuAxA3zm5uzuH#K;rV zsU1z!st1_7;CxS$RYNzRipi-tYa`&fcIkG+g+`RHm^sTuWMieCr0kJsk*v(J;i<5i zU`MJ%)AQn*&WpQD>4A;D`ppk^^lr>2*HZB~Lo>75wzN`AVPXCQbJV@J8px;FW2`=_KoUbxVaE4ziAB3$K6_jS!JMk#p@Z8-9`QWeZDdr95j+?N%aTE5Yx} zRwsj-Qhe=p?vPM4sTWZ{&WH%~wK-T#(1`zjsqkHjB|+Do4U%i_@yM)=g!nl*2E&O= z853JGBr40l=ZUbIujZ8To{zRqJco=qTa_9M^q|pN7o@#vkth_Odrqafm6zsx{pltU z4+rT(n4~-h5}6#C@IjN?k!UzgyeAXtG;8oc`MU&oLc>=Gp}Rypal@(}W6c6!AfA+) zJfP2-1c>PC>vMtRJFEkEm0LlI{SN>Wx=4Et=IUyI;2bXA43J9$EdxZxa_j4fafDAG zz{9Qvcw(8}U!Ur>dcFkeZBYP_B9;on>>5sH1k5l%oI>=wQZ zP){3xOZaKj?F){pOo7mnx2Zum-Gfgm=Kv3M*=x7^ux7yT3Y z?Fh!5&*8htu9Oa2bJNHpOl6~5>|YF9Y36*La$+-B2a8ivYov{xX3gloDEId&5HI?k zB>r?c%};XM8?zu7WDwX)L{5neiweSzhYt&7d!QyC=UZMAO;&M*#s7S_4p|3}_ zLvLc_+^AiC40*M~?l)R^osVAdt1fhADdiZs5rbI5;$^HiGU!fV>sleF5&O z)#m-G9+26$5(Yif>dK~W-7l6wQ)L}L`IcKFpMg#c&_YRYhFY>yITc6Ixn>^ya!{;nfIpJgZ3!6Vxt7|=%noE1pxXBKMTap8pTIZeMB(zznNqi1F|`Vyr1 zZs_>SJhYSi9IC(lNR`Zj!(v``VZ0_BzPPVLSSt@Vc3IVo9Bf#@yt7>XPPG)5GqX0G zZ{{XTD*NGtMKVt?ZW*HrwrIfEp35DKhTBIPNp$y;Qs6b`jQNX8^HPM6d;Z3<<;%o^r?nHfKH+UDrojc=U_4b>Vz=W zFJOHWWTE$Wssx8^q#Gb^5ip7huq@pGHBqr>2L~}`KoHOKa$4tfLJ9{C0`Mm>v(?T| zx=k+h%YIiz0A(wN1iDes0K;3ds#qzv4UVv3U~uQAMNMf>YIDVi$@8#RA*$+;j+65W zRYbN*sVC5e6mF-6V#M-jrL|WS(Jpv+BCL9y=8mk06Y(`>=eM?45={j$PqJ;K59TaU za{j(7^~xXT_4(|vdrWtm4r0y=|1x;*7VSe*^{sZsxqP>4C4F;^xvBFjQ<~@a`NPe= z8T*{71Km)rkAEj9J8Rf5sQoVR>gOyeV6ttnQ&QacfpaLFrE9#g|BVIAMaKHW2T4Ca z5#aih#A>)UHtVuY12oOdVYpV8fDVh3Sq1|*_zncen54xv@4%$#^)TdJ2Vja2pq{t} z2L4Z<}`Ff&3;UZ9~T_W~a;jMy@u#jFPz=$V;;V|*amC+_1T%6039N1MJNr>6?Z$r!b_-gT!y=swBlpW{Lb2=TJMZp-vg z)cmy)cR9A-YMvPTwD0~9_xlF5(#LEvjqNPdZ+k~VZ0sb->qvNwW~7lBd(dq+lS&h; z&ZAgE5rDJSn0CS2Ew_>x)Z29da4{O377~F$(+j+mf{fhfkbpHNs{6bRBSaju-m=%u zGuX*-*XB^-OQ%(FAOgpsnitLHISK5pcHud;9?5%XlV|3ht{3QR|7^M*ui1TV+s)q+Elquwde~l{F3t;S=)a2$js6 z0OFe&;H16b!W)Rx37Yp~vIX2!PD4I`-_y@QzCiRLcF3j{%NuQGCz-A=C0LTlS#S)8 zk#Gl~T-ZVi4(HaRSgSh0q!&@9QL+vuyS|ApHU2E|@zpfHImy0o_9a zgg}Gr7hq994d6V?hm)A)i_~Gq!2CPl0hl9T^X_Dk;(vlvAT-)5f$}UwlO+^3K>)bB zUtlLQ7|7D0fN(&9jkrfk#|UYp)@hizWEIdteIVq(f}{ab0H#UW!{r3{!?pN;`{%If zz|gsmD5CEjteapr3{0IBwg&k5`8Dt`e#3NvBB`R}l8ehDlyxR$fcvL_Rl9ciJ}66bDH9C6=e}yOi=f$|OtIL?K77%`<#L!_jJ8m3w&31X zS4$fjQSMSXBz)=X8K`Mwq?sYMaNj?;Ul>B6Q0|_!6Jp3d?`!X)Pd`bct+rJW%BYmqocQfB zELj7q!Owa5EFL>v6wvb3W7t+I}yZsvB(n)t` zaJ8Z*zI8u(-QWFX z^5AciriqCO1$MXroZaumzfCBw@aTD5OFwDi6gM|FN0^bmY@_lK{$cgF5=1AAn^DhF z%LANiOk{8=;JzIec0Y^hVs@~_J7Ry2{JDwnBfp8jD`Xmbn_s`B%8H8_97tu=$IZu$ zrEXV3rC*?{F{(DTlGLbkm!^djT8W(_Gj9sKidOV&@-1DQ!)b*)V7{p`I5Nmfib z#mh*AEF6ElgC~A#406TTU4P1!Yop?Gd&$Sk`$u}yjo=4E8v~!s@FylZ_?KZnp1g3% z_4Ox$G9+Io0s+~Y`+g5c+)^4PeXv@TXE$(svot*Z!})h_LJ@ya=uZ{;4RxV zjd>X&Mf*7!UWK7E5$%t~a82GvEDxt12-wA}IbpZjfLDW?FoV|yAfbuHRByoZC23)A zpO;6g^P|dedbu{2nLIYXxEL9j1;o6>D&+kPd+PswP1%lG{egS^riYtb1{{IV|6u|6 zNX<*3(BV&|E}r$kwHFg)6%iBU3v&yb7{D9+=d=Fv277o(m#7xUwCLeIO@_q^A;?z8 zuedRv?<7nbGyl&g)&vftxv-?0lyxN{tN-uIg}sG6Q4-dvYfzQ~!fR!6`TzIMlfMhf zcqEdFmnCk4jQ-E}`>%`s@81~qlmGsGz!&=;p9{V!0`vd>%WY_i{%>=@9{i8104??Z zx!hiXS*1V2L%-Q3{%@=4&%U(A?Gr%Rp?ouDrh}=3hY7Dlr@Fm` z==?vgxlHa8(?WfMLeaMbCDler@nMAyi+W)wi-vxtc`D`PSbP14Yia#!n z9Z|xZwXT>6r!QZuqlHA6{#VNIzqg?)bGlOgj~_&()nlH8!x#?yD4+Y4t!*9UDs8p{ zlZq?jKTeDOzt%C}6A)3a@uW=thlLmDDGVkNvxWL>NS81F`G7ZzO?=XSwLfg286y;{ z551T`Gjkt$uRta}S05V|hCJYy2-cJ1S8IWpu3+B{{=7(h)BCPw5)xsv4(w2Y7Qr)6 zwJ>eomGtkwb@d+6`vrHT^2?^K@McCR7`Holv~)1hVM&%`DA$DIJFv-9FpYJM11jvKC{35Js2d5JmjSpIAzRRN z=?<11v%TMCK%?cSh}d156Mv>pl}$z?Aj_OUXuJlN$pH{rpMa2HbADX34ooZ!ar=9F z;?hl`Rtp=M1^;#HS!KBq$AMTcbC%=I&Z?ulyc~oSC{w(y55VIcT)>E5!vaECs@Qe4 zv73nX+6O4xk015jwQM5k-Xb6NkT3dKtN-33fH}oJl-DB1j|FAE<+KsT=9z>2Od7v4 zo#^AWIaj~9G%Ry5#=n6HR9$gkOdP00G0k8A;AS{%)dk-QBr-&@eU1ch@v54($qUt) zaq&d&4tM}zhbtX|!P$xn>U+e&o|%}#FapRO2hh-gtOlqBL5As!13z4+{mO>zsP|yk z018-8Vf%#bv8-qyG>&3E5cd>Ev--> z;;X%AyCbI{pzd?rh_GzX;1FjP5{LNt_lOXGs3h%OkjC42OZ(w=zmZ~Pv!4msiYC7Q zY<@l&G`S2ui|5QLYx>0#`Le&d`Q-leO6(!EWqx7)qd*ar(y8v~^^(0J!{Xzg9AsOE z3&XvsYLj=5{yeA2eU2;NoeM;t`-qg*i!PPbIIAI_U$BI73>kN4;=$A`bo#co_s-V7!s^^UfTWP z;(hh%-B_kT#K49pC;iZe_7ZH@K<@$NcS0B%x$M2q4%?UWgFOcjxOahc z7Q~B2f!po8ZPq5(t z`sx}aY@=nOiPxSUkDtCRxi5ea5-m;0g9B)m#{+GCUm&G!T45W!uNg>)U>Yu&P*jiQ z;A*GUelVGSIDh*n1y|f?>wsVDt=zh1x16zSp z5Pz-#6n?hx;{TJ#1oorx{r&x|6I~Pzjc_BWoC6_f1Q1BMPIdnPbwCUV;PJo|2EGjJ3j)v`yq06 zfJn&u*7(L)g_C%eP7D?TPOsDRzd~{Np1W3$AC~Y3<~gAfPe)Uy6zIUl``nKu7?Na> zmHY=c`MSWxK4Hu~BCt3G_wmx0NWBai6&oylu9Vd&HmfT{bfLO4oNqy2W2S-lbW=*J zJKH$Upo-4f=<#*Q*$8@2AXBRpDf4TT+wjM{bZeVR>JUqw@!PB@Aoh&`7HP0F1leSGf_)TBY1;SVm)!MCLwhK!i&8ya zV8s617OOOFBZuvNZL8bD@}$DSRQe+ES;ban0XW@;Rk#5W{`h#YM^f+{X)xQ7nqSX$ zJcfcq$Of3B`a$JOP{7mO${%nm)_^;39VEm0K|LM>0(e%i0uLUHYjfB+fy88Q6cH;7 zE#3h7@2r0vVOc24pX3K%hXG6H4sT#a~>?dun_$h!@>i>^n8*O?_x{}wPC2k5q)=6<{|*{oT?#^!pdjmqdBMu{CLUxE;C|vll07AU54sV;>t_5ey@fiQG+;-hZwn;MOqOArMr71q`N^RhVFajUH5*u zA6N@mFzd{m^RMUGzrD}s*vS}&Y=85wP=#)#tJ!`ar;5pt7N9z5?t~86CEN~${AM9s z7vuV^7CSE}|G*KQxSdJDZRS_~vb3Y=BI>A3a}ezhXpzr2?T<-_E?}4dFW&W3{m|!Arv_mai^X0I9v{c=2}P$mt*pcnpv!N z!#mvueMmU z7MMrSis>k5B;#yjx|I5$MO`u0m~39Bg<@Sqm2A3ZZMvZ1opdz<$rwboVbd*!P|D-({U>_w6K8XQc2q5vH3-~F~kRu8{uLs^= zMFO==fOdf6xImZ(F}(bg&Z?8F%H$5L$h%!&0t=vw;tMSGwE*2fPl-zp6q3HxPsjk( zLqNa&Ur{#Kxd8#BS|~v!7Xe^+$nYs2m~cEGTGQnkgK$VfHJb;4-QfF?wkweII}E}{ z!GCh=ElVi;9>R2|Sygm%59T-6ntntGi$~F3-cn)p8qkIKCcp_w{$;=nG*E z_UG&HpM9&?N9BwjqSK(J0b+UnL@uN?h_L;@cdk_{##v4gIitgh&Q}i3bfCT2l#lO~ zm7vf`8{ZxOTkCykG9R=l9cryp!s#~WKUTV58DXcm6Luf6L3k4r(#Bz1&97$`JByCt zyP;j1xf0B~n|Fa_$O@56=a@u*9H0rsrl^rb#lK76-JgK$obw;T^Iej4_gIMxrRfmdZZ&Fj+N6iZSx$C{WCaLiCZbPhJ9qA}&yOyfq*H^cvn(O74(k%TWFdbP)f})hP5PuJvT1{T)r5 z7DA&F?Z;nXjB0>N%5N1(1E&KX>|Xvt=D&~b&n6d*bJzLn@>eD`*Yay;ejNs)RfV?+ z+=_*w;Xn@z-UNB|>XoW)sQdPYD$50*7Ofj*OC@0&XJWz2(5`ptW|;wm)HifBXeoE0 zcqtjgR7!S`=)BF)8bZv>`gkQ&Re8!ANLM8`n#3^f18Bo~>Qq90VT`T3e~5{MJy+L$ z#dEamgqC@|{8d0qC3S)`JTAdHGh_s2R~&Bq?g$%{>9u zX;|bZW=laSvNCvSSVJPupNoIDyhR>Mn;fz}jcrFn>AXf-S8eN5k^O^FunMuuRsL*x zI;)uj?K#7`u)y3GtZ=$}Ax~_hvltcO&Y?(c-FBfR)I|0^B>1B_d>k7xtiFQ1_-S3O zvM2k4d%1LJdtfU_AO;6dU0)H0#+`9BtV8)tXJNI4U+{lY-edud+TgW&R1%Hy73X-<|BOUQ&+cFw_G3wM@xwC_#-UK|J`EAXA| zADO3TC0kBtlby`Qh3GIcnvH}PTU3wQN6!eVPNWpOYz&CAB}46Oibh3Tp_fMSI$>CJ z8cBpjhW&~ThL^j^QhM(&O%^*BJ|5#Jf4I-SmIfv>(Kj#4NU$jMCO{j{YYeHk?e~-# zLh8}ux3#x~hb*At;$$kQI6By3Tz>a;WkiY6{rZ*>ZQ*Mqt(V`|&OsXxNUTIww9hEE zI-MDM`!Lv1+`cag)6GL6@xz-Z%hl`(dckIvg$Q%?4V@y{)a!B6b+P@99F&4mxsC1N z$cVyIz7AHo4des7^E1?zc2x$Ubwqh;-H#q2zsp8ukY-Ti{BcllIX)PF!A9~u*4FJ^U_bb5D;n@NKCVo6`k%@tT8lN6>W*MZsyO6S z`%71shQ_6#r@zeDWSBsbEs;iJQ>TMWLt)s&q%$lx?{hez8KJ z@<;5s==PASv-w+Cz3ynewS|iK6a$(HT_m=2`+2(S&(x?QrM7c3n6p2~nAjUSCv+Q6pYGK?u!NE6-AN(pnFtbK`L7~Qn zb}OT-THC2=nC5@NeZXn&3KXtF*#E$eE`2sOh?Zd-+I<=4*@}VcIVMII|MD8cHU>wP zAvs~Ykr~EXD#jqhWWS11GbZgd?uWLDf bzo87m>=Feo%w6Z_6Ij5bXh0Xf%d6Br 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⪻~V#$d~@?|@5xc@aK( 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 a`k%pNrPdZTrH*e5K;Y@>=d#Wzp$PzL(@ISM literal 0 HcmV?d00001 diff --git a/libslp-location.manifest b/libslp-location.manifest new file mode 100644 index 0000000..97e8c31 --- /dev/null +++ b/libslp-location.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/location.pc.in b/location.pc.in new file mode 100644 index 0000000..a9a8641 --- /dev/null +++ b/location.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +datarootdir = @datarootdir@ +datadir=@datadir@ + +Name: location +Description: SLP Location FW +Requires: glib-2.0 gobject-2.0 gmodule-2.0 vconf location-appman +Version: @VERSION@ +Libs: -L${libdir} -lSLP-location +Cflags: -I${includedir} -I${includedir}/location diff --git a/location/Makefile.am b/location/Makefile.am new file mode 100755 index 0000000..b4ada5b --- /dev/null +++ b/location/Makefile.am @@ -0,0 +1,50 @@ +SUBDIRS = manager map-service module +lib_LTLIBRARIES = libSLP-location.la + +COMMON_HEADER_DIR = include +MANAGER_DIR = manager +MAP_SERVICE_DIR = map-service +MODULE_DIR = module + +libSLP_location_la_SOURCES = \ + ${MANAGER_DIR}/location.c\ + ${MAP_SERVICE_DIR}/location-map-service.c + + +libSLP_location_la_CFLAGS = \ + -fPIC\ + -I${srcdir} \ + -I${srcdir}/include \ + -I${srcdir}/${MANAGER_DIR} \ + -I${srcdir}/${MODULE_DIR} \ + -I${srcdir}/${MAP_SERVICE_DIR} \ + $(LOCATION_CFLAGS) + +libSLP_location_la_LIBADD = \ + ${MANAGER_DIR}/liblocation-manager.la \ + ${MAP_SERVICE_DIR}/liblocation-map-service.la \ + ${MODULE_DIR}/liblocation-module.la \ + -lm\ + $(LOCATION_LIBS) + +libSLP_location_includedir = $(includedir)/location +libSLP_location_include_HEADERS = \ + ${COMMON_HEADER_DIR}/location-types.h \ + ${COMMON_HEADER_DIR}/location-map-types.h \ + ${MANAGER_DIR}/location.h \ + ${MANAGER_DIR}/location-position.h \ + ${MANAGER_DIR}/location-velocity.h \ + ${MANAGER_DIR}/location-accuracy.h \ + ${MANAGER_DIR}/location-boundary.h \ + ${MANAGER_DIR}/location-satellite.h \ + ${MAP_SERVICE_DIR}/location-address.h \ + ${MAP_SERVICE_DIR}/location-map-service.h \ + ${MAP_SERVICE_DIR}/location-map-service-ext.h \ + ${MAP_SERVICE_DIR}/location-poi.h \ + ${MAP_SERVICE_DIR}/location-route.h \ + ${MAP_SERVICE_DIR}/location-route-ext.h \ + ${MAP_SERVICE_DIR}/location-geocode.h \ + ${MAP_SERVICE_DIR}/location-map-pref.h \ + ${MAP_SERVICE_DIR}/location-landmark.h \ + ${MAP_SERVICE_DIR}/location-landmark-ext.h \ + ${MODULE_DIR}/location-module.h diff --git a/location/include/location-log.h b/location/include/location-log.h new file mode 100644 index 0000000..e929f4e --- /dev/null +++ b/location/include/location-log.h @@ -0,0 +1,65 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_LOG_H__ +#define __LOCATION_LOG_H__ + +/** + * @file location-log.h + * @brief This file contains macro functions for logging. + */ + +/* Tag defines */ +#define TAG_LOCATION_FWK "LOCATION" + + +#ifdef LOCATION_DLOG_DEBUG /* if debug mode, show filename & line number */ +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#define LOG_TAG TAG_LOCATION_FWK +#endif + +#define LOCATION_LOGD(fmt,args...) LOGD(fmt, ##args) +#define LOCATION_LOGW(fmt,args...) LOGW(fmt, ##args) +#define LOCATION_LOGI(fmt,args...) LOGI(fmt, ##args) +#define LOCATION_LOGE(fmt,args...) LOGE(fmt, ##args) +#elif LOCATION_DLOG_RELEASE /* if release mode */ +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#define LOG_TAG TAG_LOCATION_FWK +#endif + +#define LOCATION_LOGD(fmt,args...) LOGD(fmt, ##args) +#define LOCATION_LOGW(fmt,args...) LOGW(fmt, ##args) +#define LOCATION_LOGI(fmt,args...) LOGI(fmt, ##args) +#define LOCATION_LOGE(fmt,args...) LOGE(fmt, ##args) +#else /* if do not use dlog */ +#define LOCATION_LOGD(...) g_debug(__VA_ARGS__) +#define LOCATION_LOGW(...) g_warning(__VA_ARGS__) +#define LOCATION_LOGI(...) g_message(__VA_ARGS__) +#define LOCATION_LOGE(...) g_error(__VA_ARGS__) +#endif + +#endif diff --git a/location/include/location-map-types.h b/location/include/location-map-types.h new file mode 100644 index 0000000..7430986 --- /dev/null +++ b/location/include/location-map-types.h @@ -0,0 +1,296 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_MAP_TYPES_H__ +#define __LOCATION_MAP_TYPES_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * @file location-map-types.h + * @brief This file contains the Location related structure, enumeration, and asynchronous function definitions. + * @addtogroup LocationFW + * @{ + * @defgroup LocationMapTypes Location Map Types + * @brief This sub module provides structure, enumeration, and asynchronous function definitions. + * @addtogroup LocationMapTypes + * @{ + */ + +typedef enum { + MAP_SERVICE_PREF_LANGUAGE, + MAP_SERVICE_PREF_COUNTRY, + MAP_SERVICE_PREF_DISTANCE_UNIT, + + MAP_SERVICE_PREF_PROPERTY, + + MAP_SERVICE_GEOCODE_TYPE, + MAP_SERVICE_REVERSE_GEOCODE_TYPE, + + MAP_SERVICE_POI_TYPE, + MAP_SERVICE_POI_SEARCH_BY_ADDRESS, + MAP_SERVICE_POI_SEARCH_BY_FREEFORM_ADDRESS, + MAP_SERVICE_POI_SEARCH_BY_CIRCLE_BOUNDARY, + MAP_SERVICE_POI_SEARCH_BY_RECT_BOUNDARY, + MAP_SERVICE_POI_SEARCH_BY_POLYGON_BOUNDARY, + MAP_SERVICE_POI_PREF_SORT_BY, + MAP_SERVICE_POI_PREF_PROPERTY, + MAP_SERVICE_POI_FILTER, + MAP_SERVICE_POI_FILTER_CATEGORY, + + MAP_SERVICE_ROUTE_REQUEST_FREEFORM_ADDR_TO_AVOID, + MAP_SERVICE_ROUTE_REQUEST_STRUCTED_ADDR_TO_AVOID, + MAP_SERVICE_ROUTE_REQUEST_CIRCLE_AREA_TO_AVOID, + MAP_SERVICE_ROUTE_REQUEST_RECT_AREA_TO_AVOID, + MAP_SERVICE_ROUTE_REQUEST_POLYGON_AREA_TO_AVOID, + MAP_SERVICE_ROUTE_REQUEST_FEATURE_TO_AVOID, + MAP_SERVICE_ROUTE_PREF_TYPE, + MAP_SERVICE_ROUTE_PREF_TRANSPORT_MODE, + MAP_SERVICE_ROUTE_PREF_GEOMETRY_BOUNDING_BOX, + MAP_SERVICE_ROUTE_PREF_GEOMETRY_RETRIEVAL, + MAP_SERVICE_ROUTE_PREF_INSTRUCTION_GEOMETRY, + MAP_SERVICE_ROUTE_PREF_INSTRUCTION_BOUNDING_BOX, + MAP_SERVICE_ROUTE_PREF_INSTRUCTION_RETRIEVAL, + MAP_SERVICE_ROUTE_PREF_REALTIME_TRAFFIC, + MAP_SERVICE_ROUTE_PREF_PROPERTY, + MAP_SERVICE_ROUTE_DISTANCE_UNIT, + MAP_SERVICE_ROUTE_PROPERTY, + MAP_SERVICE_ROUTE_SEGMENT_PROPERTY, + MAP_SERVICE_ROUTE_STEP_PROPERTY, + MAP_SERVICE_TYPE_MAX + +} LocationMapServiceType; + +/** +* This enumeration defines values that represent road and road feature +* types. +*/ +typedef enum { + FOW_UNDEFINED, ///< Indicates that the road or road type is undefined/unknown. + FOW_MOTORWAY, ///< Identifies a road as a motorway. + FOW_MULTI_CARRIAGEWAY, ///< Identifies a road as a multi-lane carriageway. + FOW_SINGLE_CARRIAGEWAY, ///< Identifies a road as a single carriageway. + FOW_ROUNDABOUT, ///< Identifies a road feature as a roundabout/rotary. + FOW_SPECIAL_TRAFFIC_FIGURE, ///< Identifies a road features as a special traffic figure. + FOW_SLIPROAD, ///< Identifies a road as a slip road. + FOW_PEDESTRIAN_ZONE, ///< Identifies an area or road section as a pedestrian zone. + FOW_PEDESTRIAN_WALKWAY, ///< Identifies a pedestrian walkway. + FOW_SERVICE_ACCESS_PARKING, ///< Identifies access to a parking facility. + FOW_SERVICE_ACCESS_OTHER, ///< Identifies access to an unspecified service or facility. + FOW_SERVICE_ROAD, ///< Identifies a road as a service road. + FOW_ETA_PARKING_PLACE, ///< Identifies a parking facility. + FOW_ETA_PARKING_BUILDING, ///< Identifies a parking house. + FOW_ETA_UNSTRUCTURED_TRAFFIC_SQUARE, ///< Identifies an unstructured traffic square. + FOW_ROAD_FOR_AUTHORITIES ///< Identifies a road restricted for authorized access only. +} FormOfWay; + +/** +* This enumeration defines identifiers indicating the validity of the +* estimated time of arrival (ETA) and of the desired time of arrival (DTA) +* set with RoutePlan::set_time(...). These values are +* returned by the method method get_eta(). +*/ +typedef enum { + ROUTE_ETA_INVALID, ///< Indicates that the ETA for the given route is not calculated or otherwise invalid. + ROUTE_ETA_VALID, ///< Indicates that the ETA is valid, but the route plan did not include DTA. + ROUTE_ETA_DTA_VALID, ///< Indicates that both the ETA and DTA are valid. + ROUTE_ETA_DTA_LATE, ///< Indicates that the DTA cannot be achieved. + ROUTE_ETA_DTA_IN_PAST ///< Indicates that the DTA is in the past. +} RouteETAValidity; + +/** +* This enumeration defines identifiers for travel direction indicators. +*/ +typedef enum { + UNDEFINED = 0x00, ///< Indicates that direction is undefined. + STRAIGHT = 0x01, ///< Indicates direction as "straight". + SLIGHTLY_RIGHT = 0x02, ///< Indicates direction as "slightly right". + RIGHT = 0x04, ///< Indicates direction as "right". + SHARP_RIGHT = 0x08, ///< Indicates direction as "sharp right". + U_TURN_LEFT = 0x10, ///< Indicates a left u-turn. + SHARP_LEFT = 0x20, ///< Indicates direction as "sharp left". + LEFT = 0x40, ///< Indicates direction as "left". + SLIGHTLY_LEFT = 0x80, ///< Indicates direction as "slightly left". + U_TURN_RIGHT = 0x100, ///< Indicates a right u-turn. + DIRECTION_UNKNOWN = 0xFFFFFFFF ///< Indicates that direction is unknown. +} DIRECTION; + +/** + * This enumeration defines identifiers to represent driving direction on a road segment. + * + * @ingroup basicTypes + */ +typedef enum { + DIR_BOTH, ///< Indicates that the road segment can be traveled in both directions. + DIR_FORWARD, ///< Indicates that the road segment can be traveled from start to end, relative to the road geometry. + DIR_BACKWARD ///< Indicates that the road segment can be traveled from end to start, relative to the road geometry. +} DrivingDirection; + + +/** Possible traffic directions - what side of road one +* has to drive +*/ +typedef enum { + ///< Traffic is left sided (for example UK, Australia) + TRAFFIC_DIR_LEFT, + ///< Traffic is right sided + TRAFFIC_DIR_RIGHT +} TrafficDirection; + +/** Types of transit. */ +typedef enum { + TRANSIT_TYPE_BUS_PUBLIC = 0, + TRANSIT_TYPE_BUS_TOURISTIC, + TRANSIT_TYPE_BUS_INTERCITY, + TRANSIT_TYPE_BUS_EXPRESS, + TRANSIT_TYPE_RAIL_METRO, + TRANSIT_TYPE_RAIL_LIGHT, + TRANSIT_TYPE_RAIL_REGIONAL, + TRANSIT_TYPE_TRAIN_REGIONAL, + TRANSIT_TYPE_TRAIN_INTERCITY, + TRANSIT_TYPE_TRAIN_HIGH_SPEED, + TRANSIT_TYPE_MONORAIL, + TRANSIT_TYPE_AERIAL, ///< Cable car + TRANSIT_TYPE_INCLINED, + TRANSIT_TYPE_WATER, + TRANSIT_TYPE_AIRLINE, + TRANSIT_TYPE_RESERVED, ///< Reserved for future usage + TRANSIT_TYPE_COUNT, + TRANSIT_TYPE_UNKNOWN = TRANSIT_TYPE_COUNT +} TransitType; + +/** + * @brief Location Map Object redefined by GObject. + */ +typedef GObject LocationMapObject; + +/** + * @brief This represents address information such as building number, street name, etc. + */ +typedef struct _LocationAddress LocationAddress; + +/** + * @brief This represents a structure of Location Map Preference. + */ +typedef struct _LocationMapPref LocationMapPref; + +/** + * @brief This represents a structure of Location POI filter. + */ +typedef struct _LocationPOIFilter LocationPOIFilter; + +/** + * @brief This represents a structure of Location POI preference. + */ +typedef struct _LocationPOIPreference LocationPOIPreference; + +/** + * @brief This represents a structure of Landmark information. + */ +typedef struct _LocationLandmark LocationLandmark; + +/** + * @brief This represents a structure of Landmark Url. + */ +typedef struct _LocationLandmarkUrl LocationLandmarkUrl; + +/** + * @brief This represents a structure of Location route preference. + */ +typedef struct _LocationRoutePreference LocationRoutePreference; + +/** + * @brief This represents a structure of Location route. + */ +typedef struct _LocationRoute LocationRoute; + +/** + * @brief This represents a structure of Location route segment. + */ +typedef struct _LocationRouteSegment LocationRouteSegment; + +/** + * @brief This represents a structure of Location route step. + */ +typedef struct _LocationRouteStep LocationRouteStep; + +/** + * @brief This represents a structure of Location maneuver. + */ +typedef struct _LocationRouteManeuver LocationRouteManeuver; + +/** + * @brief This represents a structure of Location public transit stop. + */ +typedef struct _LocationRouteTransitStop LocationRouteTransitStop; + +/** + * @brief This represents a structure of Location Road or Public transit element. + */ +typedef struct _LocationRoadElement LocationRoadElement; + +/** + * @brief This represents a structure of Location Road Element Penalty. + */ +typedef struct _LocationRoadElementPenalty LocationRoadElementPenalty; + +/** + * @brief This represents a structure of Location Route Lane infomation. + */ +typedef struct _LocationRouteLaneInfo LocationRouteLaneInfo; + +/** + * @brief This represents a structure of Location Route options. + */ +typedef struct _LocationRouteOptions LocationRouteOptions; + + +/** + * @brief This represents callback function which will be called to give position information. + */ +typedef void (*LocationPositionCB)(LocationError error, GList *position_list, GList *accuracy_list, gpointer userdata); + +/** + * @brief This represents callback function which will be called to give address information. + */ +typedef void (*LocationAddressCB)(LocationError error, LocationAddress *address, LocationAccuracy *acc, gpointer userdata); + +/** + * @brief This represents callback function which will be called to give POI information. + */ +typedef void (*LocationPOICB)(LocationError error, guint req_id, GList *landmark_list, gchar *error_code, gchar *error_msg, gpointer userdata); + +/** + * @brief This represents callback function which will be called to give Route information. + */ +typedef void (*LocationRouteCB)(LocationError error, guint req_id, GList *route_list, gchar *error_code, gchar *error_msg, gpointer userdata); + +/** + * @}@} + */ + +G_END_DECLS + +#endif /* __LOCATION_MAP_TYPES_H__ */ diff --git a/location/include/location-types.h b/location/include/location-types.h new file mode 100644 index 0000000..93aaff5 --- /dev/null +++ b/location/include/location-types.h @@ -0,0 +1,132 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_TYPES_H__ +#define __LOCATION_TYPES_H__ + +#include +#include + +G_BEGIN_DECLS + +/** + * @file location-types.h + * @brief This file contains the Location related structure, enumeration, and asynchronous function definitions. + * @addtogroup LocationFW + * @{ + * @defgroup LocationTypes Location Types + * @brief This sub module provides structure, enumeration, and asynchronous function definitions. + * @addtogroup LocationTypes + * @{ + */ + +/** + * @brief This represents the returned error code of used functions. + */ +typedef enum { + LOCATION_ERROR_NONE = 0, ///< Success. + LOCATION_ERROR_NOT_ALLOWED, ///< Location servie is not allowed. + LOCATION_ERROR_NOT_AVAILABLE, ///< Location service is not available. + LOCATION_ERROR_NETWORK_FAILED, ///< Network is not available. + LOCATION_ERROR_NETWORK_NOT_CONNECTED, ///< Network is not connected. + LOCATION_ERROR_CONFIGURATION, ///< Configuration setting is not correct. + LOCATION_ERROR_PARAMETER, ///< Input parameter is not correct. + LOCATION_ERROR_NOT_FOUND, ///< Output is not found. + LOCATION_ERROR_NOT_SUPPORTED, ///< Not supported. + LOCATION_ERROR_UNKNOWN, ///< Unknown error. + LOCATION_ERROR_SETTING_OFF, ///< Location setting(GPS/WPS) is off + LOCATION_ERROR_SECURITY_DENIED, ///< system disables location service. +} LocationError; + +/** + * @brief This represents location method to be used. + */ +typedef enum +{ + LOCATION_METHOD_NONE = -1, ///< Undefined method. + LOCATION_METHOD_HYBRID = 0, ///< This method selects best method. + LOCATION_METHOD_GPS, ///< This method uses Global Positioning System. + LOCATION_METHOD_WPS, ///< This method uses Wifi Positioning System. + LOCATION_METHOD_CPS, ///< This method uses cell ID of base station. +} LocationMethod; + +/** + * @brief This represents the update type given by signal callback. + */ +typedef enum { + UPDATE_TYPE_NONE = -1, ///< Undefined update type. + POSITION_UPDATED = 0, ///< This type is used when position information is updated. + VELOCITY_UPDATED, ///< This type is used when velocity information is updated. + SATELLITE_UPDATED, ///< This type is used when satellite information is updated. +} LocationUpdateType; + +/** + * @brief This represents the state whether an application is able to use location service + */ +typedef enum { + LOCATION_ACCESS_NONE, ///< An application is not registered. + LOCATION_ACCESS_DENIED, ///< An application is not permited to use location service. + LOCATION_ACCESS_ALLOWED, ///< An application is able to use location service. +} LocationAccessState; + +/** + * @brief Location object redefined by GObject. + */ +typedef GObject LocationObject; + +/** + * @brief This represents position information such as latitude-longitude-altitude values and timestamp. + */ +typedef struct _LocationPosition LocationPosition; + +/** + * @brief This represents last known position information such as latitude-longitude values and accuracy. \n + * This would be deprecated soon. + */ +typedef struct _LocationLastPosition LocationLastPosition; + +/** + * @brief This represents position information such as number of satellites in used or in view. + */ +typedef struct _LocationSatellite LocationSatellite; + +/** + * @brief This represents velocity information such as as speed, direction, climb. + */ +typedef struct _LocationVelocity LocationVelocity; + +/** + * @brief This represents location accuracy information such as accuracy level, horizontal and vertical accuracy. + */ +typedef struct _LocationAccuracy LocationAccuracy; + +/** + * @brief This represents boundary information such as rectangular or circle area. + */ +typedef struct _LocationBoundary LocationBoundary; + +/** + * @}@} + */ + +G_END_DECLS + +#endif /* __LOCATION_TYPES_H__ */ diff --git a/location/manager/Makefile.am b/location/manager/Makefile.am new file mode 100644 index 0000000..cce6736 --- /dev/null +++ b/location/manager/Makefile.am @@ -0,0 +1,41 @@ +noinst_LTLIBRARIES = liblocation-manager.la + +COMMON_HEADER_DIR = include +MANAGER_DIR = manager +MAP_SERVICE_DIR = map-service +MODULE_DIR = module + +liblocation_manager_la_SOURCES = \ + location-marshal.c \ + location-marshal.h \ + location-ielement.c \ + location-setting.c \ + location-position.c \ + location-velocity.c \ + location-accuracy.c \ + location-boundary.c \ + location-satellite.c \ + location-signaling-util.c \ + location-common-util.c \ + location-gps.c \ + location-wps.c \ + location-cps.c \ + location-hybrid.c + +liblocation_manager_la_CFLAGS = \ + -fPIC\ + -I${srcdir} \ + -I${srcdir}/.. \ + -I${srcdir}/../include \ + -I${srcdir}/../${MANAGER_DIR} \ + -I${srcdir}/../${MODULE_DIR} \ + -I${srcdir}/../${MAP_SERVICE_DIR} \ + $(LOCATION_CFLAGS) + +EXTRA_DIST = \ + location-marshal.list + +location-marshal.h: location-marshal.list $(GLIB_GENMARSHAL) + $(GLIB_GENMARSHAL) $< --header --prefix=location > $@ +location-marshal.c: location-marshal.list location-marshal.h $(GLIB_GENMARSHAL) + echo "#include \"location-marshal.h\"" > $@ && $(GLIB_GENMARSHAL) location-marshal.list --body --prefix=location >> $@ diff --git a/location/manager/location-accuracy.c b/location/manager/location-accuracy.c new file mode 100644 index 0000000..ea70b82 --- /dev/null +++ b/location/manager/location-accuracy.c @@ -0,0 +1,105 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-accuracy.h" +#include "location-log.h" + +GType +location_accuracy_get_type (void) +{ + static volatile gsize type_volatile = 0; + if(g_once_init_enter(&type_volatile)) { + GType type = g_boxed_type_register_static ( + g_intern_static_string ("LocationAccuracy"), + (GBoxedCopyFunc) location_accuracy_copy, + (GBoxedFreeFunc) location_accuracy_free); + g_once_init_leave(&type_volatile, type); + } + return type_volatile; +} + +EXPORT_API LocationAccuracy* +location_accuracy_new (LocationAccuracyLevel level, + gdouble horizontal_accuracy, + gdouble vertical_accuracy) +{ + LocationAccuracy* accuracy = g_slice_new0 (LocationAccuracy); + accuracy->level = level; + accuracy->horizontal_accuracy = horizontal_accuracy; + accuracy->vertical_accuracy = vertical_accuracy; + + return accuracy; +} + +EXPORT_API void +location_accuracy_free (LocationAccuracy* accuracy) +{ + g_return_if_fail (accuracy); + g_slice_free (LocationAccuracy, accuracy); +} + +static int +comp_int(int a, int b){ + if (a < b) return -1; + if (a == b) return 0; + return 1; +} + +static int +comp_double_reverse(double a, double b) { + if (a > b) return -1; + else if (a == b) return 0; + return 1; +} + +int +location_accuracy_level_compare(const LocationAccuracy *accuracy1, const LocationAccuracy *accuracy2) +{ + g_return_val_if_fail(accuracy1, -1); + g_return_val_if_fail(accuracy2, 1); + + return comp_int(accuracy1->level, accuracy2->level); +} + +EXPORT_API int +location_accuracy_compare (const LocationAccuracy *accuracy1, const LocationAccuracy *accuracy2) +{ + int ret = 0; + ret = location_accuracy_level_compare(accuracy1, accuracy2); + if(!ret){ + ret = comp_double_reverse(accuracy1->horizontal_accuracy, accuracy2->horizontal_accuracy); + if(!ret) return comp_double_reverse(accuracy1->vertical_accuracy, accuracy2->vertical_accuracy); + } + return ret; +} + +EXPORT_API LocationAccuracy* +location_accuracy_copy (const LocationAccuracy *accuracy) +{ + g_return_val_if_fail(accuracy, NULL); + return location_accuracy_new(accuracy->level, + accuracy->horizontal_accuracy, + accuracy->vertical_accuracy); +} diff --git a/location/manager/location-accuracy.h b/location/manager/location-accuracy.h new file mode 100644 index 0000000..21f1985 --- /dev/null +++ b/location/manager/location-accuracy.h @@ -0,0 +1,139 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_ACCURACY_H_ +#define __LOCATION_ACCURACY_H_ + +#include + +G_BEGIN_DECLS + +GType location_accuracy_get_type(void); +#define LOCATION_TYPE_ACCURACY (location_accuracy_get_type()) + +/** + * @file location-accuracy.h + * @brief This file contains the definitions, structures, and functions related to accuracy information. + */ + +/** + * @addtogroup LocationAPI + * @{ + * @defgroup LocationAPIAccuracy Location Accuracy + * @breif This provides APIs related to Location Accuracy. + * @addtogroup LocationAPIAccuracy + * @{ + */ + +/** + * @brief This represents the approximate accuracy level of given information. + */ +typedef enum { + LOCATION_ACCURACY_LEVEL_NONE = 0, ///< Invalid data. + LOCATION_ACCURACY_LEVEL_COUNTRY, ///< Country accuracy level-> + LOCATION_ACCURACY_LEVEL_REGION, ///< Regional accuracy level-> + LOCATION_ACCURACY_LEVEL_LOCALITY, ///< Local accuracy level-> + LOCATION_ACCURACY_LEVEL_POSTALCODE, ///< Postal accuracy level-> + LOCATION_ACCURACY_LEVEL_STREET, ///< Street accuracy level-> + LOCATION_ACCURACY_LEVEL_DETAILED, ///< Detailed accuracy level-> +} LocationAccuracyLevel; + +/** + * @brief This represents location accuracy information such as accuracy level, horizontal and vertical accuracy. + */ +struct _LocationAccuracy +{ + LocationAccuracyLevel level; ///< The accuracy level of the location information. + gdouble horizontal_accuracy; ///< The horizontal position uncertainty of the location in meters. + gdouble vertical_accuracy; ///< The vertical position uncertainty of the location in meters. +}; + +/** + * @brief Create a new #LocationAccuracy with given information. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] level - The accuracy level of the location information. + * @param [in] horizontal_accuracy - The horizontal position uncertainty of the location in meters. + * @param [in] vertical_accuracy - The vertical position uncertainty of the location in meters. + * @return a new #LocationAccuracy + * @retval NULL if error occured + */ +LocationAccuracy *location_accuracy_new (LocationAccuracyLevel level, gdouble horizontal_accuracy, gdouble vertical_accuracy); + +/** + * @brief Free a #LocationAccuracy. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] accuracy - a #LocationAccuracy. + * @return None. + */ +void location_accuracy_free (LocationAccuracy *accuracy); + +/** + * @brief Compare for two accuracys. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] accuracy1 - a #LocationAccuracy + * @param [in] accuracy2 - another #LocationAccuracy + * @return integer + * @retval\n + * 0 - if the accuracy match\n + * positive value - if accuracy of accuracy1 is better than accuracy of accuracy2\n + * negative value - if accuracy of accuracy1 is worse than accuracy of accuracy2 + */ +int location_accuracy_compare (const LocationAccuracy *accuracy1, const LocationAccuracy *accuracy2); + +/** + * @brief Compare for two accuracys' level. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] accuracy1 - a #LocationAccuracy + * @param [in] accuracy2 - another #LocationAccuracy + * @return integer + * @retval\n + * 0 - if the accuracy match\n + * positive value - if accuracy1's level is better than accuracy2's level\n + * negative value - if accuracy1's level is worse than accuracy2's level + */ +int location_accuracy_level_compare(const LocationAccuracy *accuracy1, const LocationAccuracy *accuracy2); + +/** + * @brief Makes a copy of #LocationAccuracy + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] accuracy - a #LocationAccuracy + * @return a new #LocationAccuracy + * @retval NULL if error occured + */ +LocationAccuracy *location_accuracy_copy (const LocationAccuracy *accuracy); + +/** + * @} @} + */ + +G_END_DECLS + +#endif diff --git a/location/manager/location-boundary.c b/location/manager/location-boundary.c new file mode 100644 index 0000000..78ca1d3 --- /dev/null +++ b/location/manager/location-boundary.c @@ -0,0 +1,458 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * location_boundary_if_inside(LocationBoundary* boundary, + * LocationPosition* position) + * code from + * + * Copyright (c) 1970-2003, Wm. Randolph Franklin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * 1.Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimers. + * 2.Redistributions in binary form must reproduce the above copyright notice + * in the documentation and/or other materials provided with the distribution. + * 3.The name of W. Randolph Franklin may not be used to endorse or promote + * products derived from this Software without specific prior written permission. + * + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* + * location_boundary_get_center_position (LocationBoundary *boundary) + * algorithm from http://en.wikipedia.org/wiki/Centroid + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "location-boundary.h" +#include "location-common-util.h" +#include "location-log.h" + +GType +location_boundary_get_type (void) +{ + static volatile gsize type_volatile = 0; + if(g_once_init_enter(&type_volatile)) { + GType type = g_boxed_type_register_static ( + g_intern_static_string ("LocationBoundary"), + (GBoxedCopyFunc) location_boundary_copy, + (GBoxedFreeFunc) location_boundary_free); + g_once_init_leave(&type_volatile, type); + } + return type_volatile; +} + +static void _append_polygon_position(gpointer data, gpointer user_data) +{ + g_return_if_fail(data); + g_return_if_fail(user_data); + + LocationBoundary* boundary = (LocationBoundary*)user_data; + LocationPosition* position = (LocationPosition *)data; + LocationPosition* new_position = location_position_copy(position); + + boundary->polygon.position_list = g_list_append(boundary->polygon.position_list, new_position); +} + +static void _free_polygon_position(gpointer data) +{ + g_return_if_fail(data); + + LocationPosition* position = (LocationPosition *)data; + location_position_free(position); +} + + +EXPORT_API LocationBoundary * +location_boundary_new_for_rect (LocationPosition* left_top, + LocationPosition* right_bottom) +{ + g_return_val_if_fail(left_top, NULL); + g_return_val_if_fail(right_bottom, NULL); + + gdouble lon_interval = right_bottom->longitude - left_top->longitude; + + if(lon_interval < 180 && lon_interval > -180) { + if(right_bottom->longitude <= left_top->longitude || right_bottom->latitude >= left_top->latitude) + return NULL; + } + else { + if(right_bottom->longitude >= left_top->longitude || right_bottom->latitude >= left_top->latitude) + return NULL; + } + + LocationBoundary* boundary = g_slice_new0 (LocationBoundary); + boundary->type = LOCATION_BOUNDARY_RECT; + boundary->rect.left_top = location_position_copy(left_top); + boundary->rect.right_bottom = location_position_copy(right_bottom); + return boundary; +} + +EXPORT_API LocationBoundary * +location_boundary_new_for_circle (LocationPosition* center, + gdouble radius) +{ + g_return_val_if_fail(center, NULL); + g_return_val_if_fail(radius > 0, NULL); + LocationBoundary* boundary = g_slice_new0 (LocationBoundary); + boundary->type = LOCATION_BOUNDARY_CIRCLE; + boundary->circle.center = location_position_copy(center); + boundary->circle.radius = radius; + return boundary; +} + +EXPORT_API LocationBoundary * +location_boundary_new_for_polygon(GList *position_list) +{ + g_return_val_if_fail(position_list, NULL); + g_return_val_if_fail(g_list_length(position_list) > 2, NULL); + + LocationBoundary *boundary = g_slice_new0 (LocationBoundary); + + g_list_foreach(position_list, (GFunc)_append_polygon_position, boundary); + boundary->type = LOCATION_BOUNDARY_POLYGON; + boundary->polygon.position_list = g_list_first(boundary->polygon.position_list); + + return boundary; +} + +EXPORT_API void +location_boundary_free (LocationBoundary* boundary) +{ + g_return_if_fail(boundary); + + if (boundary->type == LOCATION_BOUNDARY_RECT) { + location_position_free(boundary->rect.left_top); + location_position_free(boundary->rect.right_bottom); + } else if (boundary->type == LOCATION_BOUNDARY_CIRCLE) { + location_position_free(boundary->circle.center); + } else if (boundary->type == LOCATION_BOUNDARY_POLYGON) { + g_list_free_full(boundary->polygon.position_list, (GDestroyNotify)_free_polygon_position); + } + g_slice_free(LocationBoundary, boundary); +} + +EXPORT_API LocationBoundary* +location_boundary_copy (const LocationBoundary* boundary) +{ + g_return_val_if_fail(boundary, NULL); + if (boundary->type == LOCATION_BOUNDARY_RECT) { + return location_boundary_new_for_rect(boundary->rect.left_top, boundary->rect.right_bottom); + } else if (boundary->type == LOCATION_BOUNDARY_CIRCLE) { + return location_boundary_new_for_circle(boundary->circle.center, boundary->circle.radius); + } else if (boundary->type == LOCATION_BOUNDARY_POLYGON) { + return location_boundary_new_for_polygon(boundary->polygon.position_list); + } + return NULL; +} + +EXPORT_API gboolean +location_boundary_if_inside (LocationBoundary* boundary, + LocationPosition* position) +{ + g_return_val_if_fail(boundary, FALSE); + g_return_val_if_fail(position, FALSE); + + gboolean is_inside = FALSE; + + switch(boundary->type) { + case LOCATION_BOUNDARY_RECT: { + gdouble y = position->latitude; + gdouble x = position->longitude; + + gdouble lt_y = boundary->rect.left_top->latitude; + gdouble lt_x = boundary->rect.left_top->longitude; + gdouble rb_y = boundary->rect.right_bottom->latitude; + gdouble rb_x = boundary->rect.right_bottom->longitude; + + if (lt_x - rb_x < 180 && lt_x - rb_x > -180) { + if ((rb_y < y && y < lt_y) && ( lt_x < x && x < rb_x)) { + LOCATION_LOGD("\tInside of Rectangular boundary"); + is_inside = TRUE; + } + } + else { + if ((rb_y < y && y < lt_y) && ( lt_x < x || x < rb_x)) { + LOCATION_LOGD("\tInside of Rectangular boundary near 180th meridian"); + is_inside = TRUE; + } + } + break; + } + case LOCATION_BOUNDARY_CIRCLE: { + + LocationPosition center; + gulong distance = 0; + + center.latitude = boundary->circle.center->latitude; + center.longitude = boundary->circle.center->longitude; + + location_get_distance(¢er, position, &distance); + if (distance < boundary->circle.radius){ + LOCATION_LOGD("\tInside Circle boundary"); + is_inside = TRUE; + } + break; + } + case LOCATION_BOUNDARY_POLYGON: { + + int i, j; + double interval_x = 0.0, interval_y = 0.0; + double x0, y0; + gboolean edge_area; + int crossing_num = 0; + GList *position_list = boundary->polygon.position_list; + int count = g_list_length(position_list); + GList *pos1_list = NULL; + GList *pos2_list = NULL; + LocationPosition* pos1 = NULL; + LocationPosition* pos2 = NULL; + + i = 0; + j = count - 1; + pos1_list = g_list_first(position_list); + pos2_list = g_list_last(position_list); + while(pos1_list) { + edge_area = FALSE; + pos1 = pos1_list->data; + pos2 = pos2_list->data; + interval_y = pos1->longitude - pos2->longitude; + interval_x = pos1->latitude - pos2->latitude; + /** + * Case 1. -180 < longitude2 - longitude1 < 180 : normal case + * Case 2. longitude2 - longitude1 < -180 : interval_y = longitude2 - longitude1 + 360 + * Case 3. longitude2 - longitude1 > 180 : intreval_y = longitude2 - longitude1 - 360 + */ + if (interval_y > 180) { + interval_y = interval_y - 360; + edge_area = TRUE; + } + else if (interval_y < -180) { + interval_y = interval_y + 360; + edge_area = TRUE; + } + + if (edge_area && (pos1->longitude > position->longitude) == (pos2->longitude > position->longitude)){ + if (pos2->longitude * position->longitude > 0) { + x0 = pos2->latitude; + y0 = pos2->longitude; + } + else { + x0 = pos1->latitude; + y0 = pos1->longitude; + } + + if (position->latitude < ((interval_x/interval_y)*(position->longitude - y0) + x0)) { + + LOCATION_LOGD("Reverse"); + crossing_num++; + } + } + else if (!edge_area && (pos1->longitude > position->longitude) != (pos2->longitude > position->longitude)) { + x0 = pos2->latitude; + y0 = pos2->longitude; + if (position->latitude < ((interval_x/interval_y)*(position->longitude - y0) + x0)) { + LOCATION_LOGD("Common"); + crossing_num++; + } + } + else LOCATION_LOGD("It is not crossed."); + + pos2_list = pos1_list; + pos1_list = g_list_next(pos1_list); + } + LOCATION_LOGW("num[%d]", crossing_num); + is_inside = crossing_num & 1; // Odd : inside, Even : outside + + break; + } + default: { + LOCATION_LOGW("\tboundary type is undefined.[%d]", boundary->type); + break; + } + } + + return is_inside; +} + +EXPORT_API int +location_boundary_add(const LocationObject *obj, const LocationBoundary *boundary) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (boundary, LOCATION_ERROR_PARAMETER); + + GList *boundary_priv_list = NULL; + + LocationBoundaryPrivate *priv = g_slice_new0(LocationBoundaryPrivate); + + priv->boundary = location_boundary_copy(boundary); + priv->zone_status = ZONE_STATUS_NONE; + + boundary_priv_list = g_list_append(boundary_priv_list, (gpointer) priv); + + g_object_set(G_OBJECT(obj), "boundary", boundary_priv_list, NULL); + + return LOCATION_ERROR_NONE; +} + +EXPORT_API int +location_boundary_remove(const LocationObject *obj, const LocationBoundary *boundary) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (boundary, LOCATION_ERROR_PARAMETER); + + g_object_set(G_OBJECT(obj), "removal-boundary", boundary, NULL); + + return LOCATION_ERROR_NONE; +} + +EXPORT_API int +location_boundary_foreach(const LocationObject *obj, LocationBoundaryFunc func, gpointer user_data) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (func, LOCATION_ERROR_PARAMETER); + + int index = 0; + GList * boundary_priv_list = NULL; + GList * boundary_list = NULL; + LocationBoundaryPrivate *priv; + + g_object_get(G_OBJECT(obj), "boundary", &boundary_priv_list, NULL); + + if (boundary_priv_list == NULL) { + LOCATION_LOGD("There is no boundary."); + return LOCATION_ERROR_UNKNOWN; + } + + while((priv = (LocationBoundaryPrivate *)g_list_nth_data(boundary_priv_list, index))!= NULL) { + boundary_list = g_list_append(boundary_list, (gpointer) priv->boundary); + index++; + } + + g_list_foreach(boundary_list, (GFunc)func, user_data); + + return LOCATION_ERROR_NONE; +} + +EXPORT_API LocationBoundary * +location_boundary_get_bounding_box (LocationBoundary *boundary) +{ + g_return_val_if_fail (boundary, NULL); + LocationBoundary *bbox = NULL; + + return bbox; +} + +EXPORT_API LocationPosition * +location_boundary_get_center_position (LocationBoundary *boundary) +{ + g_return_val_if_fail (boundary, NULL); + + LocationPosition *center = NULL; + + switch(boundary->type) { + case LOCATION_BOUNDARY_RECT: { + gdouble latitude, longitude, altitude; + latitude = (boundary->rect.left_top->latitude + boundary->rect.right_bottom->latitude) / 2.0; + longitude = (boundary->rect.left_top->longitude + boundary->rect.right_bottom->longitude) / 2.0; + altitude = (boundary->rect.left_top->altitude + boundary->rect.right_bottom->altitude) / 2.0; + + center = location_position_new(boundary->rect.left_top->timestamp, latitude, longitude, altitude, boundary->rect.left_top->status); + break; + } + case LOCATION_BOUNDARY_CIRCLE: { + center = location_position_copy(boundary->circle.center); + break; + } + case LOCATION_BOUNDARY_POLYGON: { + gdouble center_latitude = 0.0; + gdouble center_longitude = 0.0; + gdouble area = 0.0; + + gdouble x1, y1; + gdouble x2, y2; + GList *position_list = boundary->polygon.position_list; + GList *pos1_list = g_list_first(position_list); + GList *pos2_list = g_list_next(pos1_list); + LocationPosition* pos1 = NULL; + LocationPosition* pos2 = NULL; + + while(pos2_list) { + pos1 = pos1_list->data; + pos2 = pos2_list->data; + + x1 = pos1->latitude + 90.0; + y1 = pos1->longitude + 180.0; + x2 = pos2->latitude + 90.0; + y2 = pos2->longitude + 180.0; + + center_latitude += (x1 + x2) * (x1*y2 - x2*y1); + center_longitude += (y1 + y2) * (x1*y2 - x2*y1); + area += x1*y2 - x2*y1; + + pos1_list = pos2_list; + pos2_list = g_list_next(pos2_list); + } + + pos2_list = g_list_first(position_list); + pos1 = pos1_list->data; + pos2 = pos2_list->data; + + x1 = pos1->latitude + 90.0; + y1 = pos1->longitude + 180.0; + x2 = pos2->latitude + 90.0; + y2 = pos2->longitude + 180.0; + + center_latitude += (x1 + x2) * (x1*y2 - x2*y1); + center_longitude += (y1 + y2) * (x1*y2 - x2*y1); + area += x1*y2 - x2*y1; + + area = fabs(area / 2.0); + if (area != 0) { + center_latitude = (center_latitude - 90.0) / (6.0 * area); + center_longitude = (center_longitude - 180.0) / (6.0 * area); + center = location_position_new(0, center_latitude, center_longitude, 0, LOCATION_STATUS_2D_FIX); + } + break; + } + } + return center; +} diff --git a/location/manager/location-boundary.h b/location/manager/location-boundary.h new file mode 100644 index 0000000..48b863e --- /dev/null +++ b/location/manager/location-boundary.h @@ -0,0 +1,316 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_BOUNDARY_H_ +#define __LOCATION_BOUNDARY_H_ + +#include +#include + +G_BEGIN_DECLS + +GType location_boundary_get_type (void); +#define LOCATION_TYPE_BOUNDARY (location_boundary_get_type ()) + +/** + * @file location-boundary.h + * @brief This file contains the definitions, structures, and functions related to boundary information. + */ +/** + * @addtogroup LocationAPI + * @{ + * @defgroup LocationAPIBoundary Location Boundary + * @breif This provides APIs related to Location Boundary + * @addtogroup LocationAPIBoundary + * @{ + */ + +/** + * @brief + * The type of the @location_boundary_foreach function of #LocationObject + */ +typedef void (*LocationBoundaryFunc) (LocationBoundary *boundary, gpointer user_data); + +/** + * @brief This represents used geographical type, and supports rectangle or circle area. + */ +typedef enum { + LOCATION_BOUNDARY_NONE = 0, ///< Undefined geographical area type. + LOCATION_BOUNDARY_RECT, ///< Rectangular geographical area type. + LOCATION_BOUNDARY_CIRCLE, ///< Circle geographical area type. + LOCATION_BOUNDARY_POLYGON ///< Polygon geographical area type. +} LocationBoundaryType; + +/** + * @brief This represents a rectangular geographical area. + */ +typedef struct { + LocationPosition* left_top; ///< The left top position of rectangle. + LocationPosition* right_bottom; ///< The right bottom position of rectangle. +} LocationRect; + +/** + * @brief This represents a circle geographical area with center geographic position and radius. + */ +typedef struct { + LocationPosition* center; ///< The center position of a circle. + gdouble radius; ///< The radius of a circle. +} LocationCircle; + +/** + * @brief This represents a polygon geographical area. + */ +typedef struct { + GList *position_list; ///< The collection of positions +} LocationPolygon; + +/** + * @brief This represents boundary information such as rectangular or circle area. + */ +struct _LocationBoundary{ + LocationBoundaryType type; ///< The boundary type of this information. + union { + LocationRect rect; ///< The geographical information of a rectangle. + LocationCircle circle; ///< The geographical information of a circle. + LocationPolygon polygon; ///< The geographical information of a polygon. + }; +}; + +/** + * @brief Create a rectangular type of new #LocationBoundary with given information. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] left_top - left top position. + * @param [in] right_bottom - right bottom position. + * @return a new #LocationBoundary + * @retval NULL if error occured + */ +LocationBoundary *location_boundary_new_for_rect (LocationPosition *left_top, LocationPosition *right_bottom); + +/** + * @brief Create a circle type of new #LocationBoundary with given information. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] center - center position. + * @param [in] radius - radius. + * @return a new #LocationBoundary + * @retval NULL if error occured + */ +LocationBoundary *location_boundary_new_for_circle (LocationPosition *center, gdouble radius); + +/** + * @brief Create a polygon type of new #LocationBoundary with given information. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] position_list - the list of positions. + * @return a new #LocationBoundary + * @retval NULL if error occured + */ +LocationBoundary *location_boundary_new_for_polygon(GList *position_list); + +/** + * @brief Free a #LocationBoundary. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] boundary - a #LocationBoundary. + * @return None. + */ +void location_boundary_free (LocationBoundary *boundary); + +/** + * @brief Makes a copy of #LocationBoundary + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] boundary - a #LocationBoundary + * @return a new #LocationBoundary + * @retval NULL if error occured + */ +LocationBoundary *location_boundary_copy (const LocationBoundary* boundary); + +/** + * @brief + * Add Boundary on LocationFW. + * You should call this fuction when you want to receive a crossing signal(zone-in/zone-out) from #LocationBoundary. + * @remarks It supports multi-boundaries. \n + However a duplicated boundary would not be allowed. + * @pre + * #location_new should be called before.\n + * @post None. + * @param [in] obj - a #LocationObject + * @param [in] boundary - a #LocationBoundary + * @return int + * @retval 0 Success + * Please refer #LocationError for more information. + * @par Example + * @code +#include + +static void cb_zone_in (GObject *self, gpointer boundary, gpointer position, gpointer accuracy, gpointer user_data) +{ + g_printf ("[zone-in] position - lat: %f, long: %f", position->latitude, position->longitude); +} + +static void cb_zone_out (GObject *self, gpointer boundary, gpointer position, gpointer accuracy, gpointer user_data) +{ + g_printf ("[zone-out] position - lat: %f, long: %f", position->latitude, position->longitude); +} + +void location_test_boundary_add(LocationObject *loc) +{ + LocationPosition* rb = location_position_new (0, 37.300, -121.86, 0, LOCATION_STATUS_2D_FIX); + LocationPosition* lt = location_position_new (0, 37.360, -121.92, 0, LOCATION_STATUS_2D_FIX); + + LoationBoundary *boundary = location_boundary_new_for_rect (lt, rb); + + ret = location_boundary_add(loc, boundary); + + g_signal_connect(loc, "zone-in", G_CALLBACK(cb_zone_in), NULL); + g_siganl_connect(loc, "zone-out", G_CALLBACK(cb_zone_out), NULL); + + location_position_free(rb); + location_position_free(lt); +} + * @endcode + */ +int location_boundary_add(const LocationObject *obj, const LocationBoundary *boundary); + +/** + * @brief + * Remove Boundary on LocationFW. + * You should call this function when you don't want to receive a crossing signal(zone-in/zone-out) from #LocationBoundary any more. + * @remarks It supports multi-boundaries. + * @pre + * #location_init should be called before.\n + * @post None. + * @param [in] obj - a #LocationObject + * @param [in] boundary - a #LocationBoundary + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @par Example + * @code +#include + +void location_test_boundary_remove(LocationObject *loc) +{ + int ret = 0; + LocationPosition* rb = location_position_new (0, 37.300, -121.86, 0, LOCATION_STATUS_2D_FIX); + LocationPosition* lt = location_position_new (0, 37.360, -121.92, 0, LOCATION_STATUS_2D_FIX); + + LoationBoundary *boundary = location_boundary_new_for_rect (lt, rb); + + ret = location_boundary_remove(loc, boundary); + + location_position_free(rb); + location_position_free(lt); + +} + * @endcode + */ +int location_boundary_remove(const LocationObject *obj, const LocationBoundary *boundary); + +/** + * @brief + * Call a function for each element of a Boundary list. + * @remarks None. + * @pre + * #location_init should be called before.\n + * @post None. + * @param [in] obj - a #LocationObject + * @param [in] func - a #LocationBoundaryFunc + * @param [in] user_data - a #void + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @par Example + * @code +#include + +static void remove_boundary(LocationBoundary *boundary, void *user_data) +{ + LocationBoundary *loc = (LocationBoundary *) user_data; + if (loc == NULL || boundary == NULL) return; + + location_boundary_remove(loc, boundary); +} + +void location_test_boundary_foreach(LocationObject *loc) +{ + int ret = location_boundary_foreach(loc, remove_boundary, loc); +} + * @endcode + */ +int location_boundary_foreach(const LocationObject *obj, LocationBoundaryFunc func, gpointer user_data); + + +/** + * @brief Check if #LocationPosition is inside #LocationBoundary. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None.* @param [in] boundary - a #LocationBoundary + * @param [in] position - a #LocationPosition + * @return gboolean + * @retval\n + * TRUE - if inside\n + * FALSE - if outside\n + * @par Example + * @code +#include + +void location_test_boundary_if_inside(LocationObject *loc, LocationBoundary *boundary) +{ + gboolean is_inside = FALSE; + LocationPosition* position = location_position_new (0, 37.300, -121.86, 0, LOCATION_STATUS_2D_FIX); + is_inside = location_boundary_if_inside(boundary, position); + if (is_inside == TRUE) g_printf("The position is inside of the boundary\n"); + else g_printf("The position is outside of the boundary\n"); + +} + * @endcode + + */ +gboolean location_boundary_if_inside (LocationBoundary *boundary, LocationPosition *position); + +/** + * @brief Get bounding box of #LocationBoundary + */ +LocationBoundary *location_boundary_get_bounding_box (LocationBoundary *boundary); + + +/** + * @brief Get the center position of #LocationBoundary + */ +LocationPosition * location_boundary_get_center_position (LocationBoundary *boundary); + +/** + * @} @} + */ + +G_END_DECLS + +#endif diff --git a/location/manager/location-common-util.c b/location/manager/location-common-util.c new file mode 100644 index 0000000..8bf7e67 --- /dev/null +++ b/location/manager/location-common-util.c @@ -0,0 +1,334 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "location.h" +#include "location-common-util.h" +#include "location-setting.h" +#include "location-log.h" + + +int location_application_get_authority (void) +{ + pid_t pid = getpid(); + location_appman_s *appman; + int enabled; + int found; + + if (location_appman_get_package_by_pid(pid, &appman) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGE("Fail to location_appman_get_package_by_pid"); + return LOCATION_APP_NOT_FOUND; + } + + if (location_appman_find_package(appman->package, &found) != LOCATION_APPMAN_ERROR_NONE || found == LOCATION_APPMAN_PACKAGE_NOTFOUND) { + LOCATION_LOGE("Cannot find package [%s]", appman->package); + return LOCATION_APP_NOT_FOUND; + } + + if (location_appman_is_enabled(appman->package, &enabled) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGE("Fail to location_appman_is_enabled"); + return LOCATION_APP_NOT_FOUND; + } + + if (enabled) { + return LOCATION_APP_ON; + } + else { + return LOCATION_APP_OFF; + + } + + return LOCATION_APP_NOT_FOUND; +} + +int location_application_set_authority (int auth) +{ + pid_t pid = getpid(); + location_appman_s *appman; + int enabled; + int found; + + if (location_appman_get_package_by_pid(pid, &appman) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGE("Fail to location_appman_get_package_by_pid"); + return LOCATION_ERROR_UNKNOWN; + } + + if (location_appman_find_package(appman->package, &found) != LOCATION_APPMAN_ERROR_NONE || found == LOCATION_APPMAN_PACKAGE_NOTFOUND) { + LOCATION_LOGE("Cannot find package [%s]", appman->package); + return LOCATION_ERROR_UNKNOWN; + } + + if (location_appman_set_on(appman->package, auth) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGE("Fail to location_appman_is_enabled"); + return LOCATION_ERROR_UNKNOWN; + } + + return LOCATION_ERROR_NONE; +} + +int location_application_add_app_to_applist (void) +{ + pid_t pid = getpid(); + location_appman_s *appman; + int found; + time_t timestamp; + + if (location_appman_get_package_by_pid(pid, &appman) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGE("Fail to location_appman_get_package_by_pid"); + return FALSE; + } + + if (location_appman_find_package(appman->package, &found) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGE("Cannot find package [%s]", appman->package); + if (appman) g_free(appman); + return FALSE; + } + + if (found == LOCATION_APPMAN_PACKAGE_NOTFOUND) { + LOCATION_LOGD("First time to use location [%s]", appman->package); + if (location_appman_register_package(appman) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGE("Fail to register [%s]", appman->package); + if (appman) g_free(appman); + return FALSE; + } + } else { + LOCATION_LOGD("[%s] is already registered. Update recently used time", appman->package); + if (appman) g_free(appman); + return FALSE; + } + + if (appman) g_free(appman); + return TRUE; +} + +int location_application_enabled (void) +{ + pid_t pid = getpid(); + location_appman_s *appman; + int enabled; + int found; + time_t timestamp; + + if (TRUE == location_appman_check_developer_mode()) { + LOCATION_LOGE("Location is Enabled"); + return TRUE; + } + + if (location_appman_get_package_by_pid(pid, &appman) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGE("Fail to location_appman_get_package_by_pid"); + return FALSE; + } + + if (location_appman_find_package(appman->package, &found) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGE("Cannot find package [%s]", appman->package); + if (appman) g_free(appman); + return FALSE; + } + + if (found == LOCATION_APPMAN_PACKAGE_NOTFOUND) { + LOCATION_LOGD("First time to use location [%s]", appman->package); + if (location_appman_register_package(appman) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGE("Fail to register [%s]", appman->package); + if (appman) g_free(appman); + return FALSE; + } + } else { + LOCATION_LOGD("[%s] is already registered. Update recently used time", appman->package); + time(×tamp); + if (location_appman_set_recently_used(appman->package, timestamp) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGD("Cannot update recently used time"); + } + } + + if (location_appman_is_enabled(appman->package, &enabled) != LOCATION_APPMAN_ERROR_NONE) { + LOCATION_LOGE("Fail to location_appman_is_enabled"); + if (appman) g_free(appman); + return FALSE; + } + + if (appman) g_free(appman); + return enabled; +} + +static gint compare_position (gconstpointer a, gconstpointer b) +{ + g_return_val_if_fail(a, 1); + g_return_val_if_fail(b, -1); + + if(location_position_equal((LocationPosition*) a, (LocationPosition *)b) == TRUE) { + return 0; + } + + return -1; +} + +static int +boundary_compare (gconstpointer comp1, gconstpointer comp2) +{ + g_return_val_if_fail(comp1, 1); + g_return_val_if_fail(comp2, -1); + + int ret = -1; + + LocationBoundaryPrivate *priv1 = (LocationBoundaryPrivate *)comp1; + LocationBoundaryPrivate *priv2 = (LocationBoundaryPrivate *)comp2; + + if (priv1->boundary->type == priv2->boundary->type) { + switch (priv1->boundary->type) { + case LOCATION_BOUNDARY_CIRCLE: { + if (location_position_equal(priv1->boundary->circle.center, priv2->boundary->circle.center) + && priv1->boundary->circle.radius == priv2->boundary->circle.radius) { + ret = 0; + } + break; + } + case LOCATION_BOUNDARY_RECT: { + if (location_position_equal(priv1->boundary->rect.left_top, priv2->boundary->rect.left_top) + && location_position_equal(priv1->boundary->rect.right_bottom, priv2->boundary->rect.right_bottom)) { + ret = 0; + } + break; + } + case LOCATION_BOUNDARY_POLYGON: { + GList *boundary1_next = NULL; + GList *boundary2_start = NULL, *boundary2_prev = NULL, *boundary2_next = NULL; + if (g_list_length(priv1->boundary->polygon.position_list) != g_list_length(priv2->boundary->polygon.position_list)) { + return -1; + } + + // Find a matching index of Boundary2 with Boundary1's 1st postion. + boundary2_start = g_list_find_custom(priv2->boundary->polygon.position_list, g_list_nth_data(priv1->boundary->polygon.position_list, 0), (GCompareFunc) compare_position); + if (boundary2_start == NULL) return -1; + + boundary2_prev = g_list_previous(boundary2_start); + boundary2_next = g_list_next(boundary2_start); + if (boundary2_prev == NULL) boundary2_prev = g_list_last(priv2->boundary->polygon.position_list); + if (boundary2_next == NULL) boundary2_next = g_list_first(priv2->boundary->polygon.position_list); + + boundary1_next = g_list_next(priv1->boundary->polygon.position_list); + if (location_position_equal((LocationPosition*)boundary1_next->data, (LocationPosition*)boundary2_prev->data) == TRUE){ + boundary1_next = g_list_next(boundary1_next); + while (boundary1_next) { + boundary2_prev = g_list_previous(boundary2_prev); + if (boundary2_prev == NULL) boundary2_prev = g_list_last(priv2->boundary->polygon.position_list); + if (location_position_equal((LocationPosition*)boundary1_next->data, (LocationPosition*) boundary2_prev->data) == FALSE){ + return -1; + } + boundary1_next = g_list_next(boundary1_next); + } + ret = 0; + } + else if (location_position_equal((LocationPosition*)boundary1_next->data, (LocationPosition*)boundary2_next->data) == TRUE) { + boundary1_next = g_list_next(boundary1_next); + while(boundary1_next) { + boundary2_next = g_list_next(boundary2_next); + if (boundary2_next == NULL) boundary2_next = g_list_first(priv2->boundary->polygon.position_list); + if (location_position_equal((LocationPosition*)boundary1_next->data, (LocationPosition*) boundary2_next->data) == FALSE){ + return -1; + } + boundary1_next = g_list_next(boundary1_next); + } + ret = 0; + } + else { + return -1; + } + break; + } + default:{ + ret = -1; + break; + } + + } + } + + return ret; +} + +int set_prop_boundary(GList **prev_boundary_priv_list, GList *new_boundary_priv_list) +{ + g_return_val_if_fail(new_boundary_priv_list, LOCATION_ERROR_PARAMETER); + + int index = 0; + GList *check_list = NULL; + + LocationBoundaryPrivate *new_priv = NULL; + LocationBoundaryPrivate *copy_priv = g_slice_new0(LocationBoundaryPrivate); + + while((new_priv = (LocationBoundaryPrivate *) g_list_nth_data(new_boundary_priv_list, index)) != NULL) { + check_list = g_list_find_custom(*prev_boundary_priv_list, new_priv, (GCompareFunc)boundary_compare); + if (check_list == NULL) { + LOCATION_LOGD("Set Prop >> boundary type: [%d]", new_priv->boundary->type); + copy_priv->boundary = location_boundary_copy(new_priv->boundary); + copy_priv->zone_status = new_priv->zone_status; + *prev_boundary_priv_list = g_list_append(*prev_boundary_priv_list, copy_priv); + } + index++; + } + *prev_boundary_priv_list = g_list_first(*prev_boundary_priv_list); + + return LOCATION_ERROR_NONE; +} + + +int set_prop_removal_boundary(GList **prev_boundary_list, LocationBoundary* boundary) +{ + g_return_val_if_fail(*prev_boundary_list, LOCATION_ERROR_PARAMETER); + + GList *check_list = NULL; + LocationBoundaryPrivate *remove_priv = g_slice_new0(LocationBoundaryPrivate); + + remove_priv->boundary = location_boundary_copy(boundary); + + check_list = g_list_find_custom (*prev_boundary_list, remove_priv, (GCompareFunc) boundary_compare); + if (check_list) { + LOCATION_LOGD("Found"); + *prev_boundary_list = g_list_delete_link(*prev_boundary_list, check_list); + g_slice_free(LocationBoundaryPrivate, remove_priv); + } + + if (g_list_length(*prev_boundary_list) == 0 ) { + LOCATION_LOGD("Boundary List is empty"); + g_list_free(*prev_boundary_list); + *prev_boundary_list = NULL; + } + + g_slice_free(LocationBoundaryPrivate, remove_priv); + return LOCATION_ERROR_NONE; +} + +void free_boundary_list (gpointer data) +{ + LocationBoundaryPrivate *priv= (LocationBoundaryPrivate *)data; + + location_boundary_free(priv->boundary); + g_slice_free(LocationBoundaryPrivate, priv); +} + diff --git a/location/manager/location-common-util.h b/location/manager/location-common-util.h new file mode 100644 index 0000000..91f0b0a --- /dev/null +++ b/location/manager/location-common-util.h @@ -0,0 +1,66 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_COMMON_UTIL_H__ +#define __LOCATION_COMMON_UTIL_H__ + +#include +#include +#include + +/** + * @file location-common-util.h + * @brief This file contains the common utils for LocationObject. + */ + +G_BEGIN_DECLS + +typedef enum { + LOCATION_APP_OFF = 0, + LOCATION_APP_ON, + LOCATION_APP_NOT_FOUND +} LOCATION_APP_STATE; + +typedef enum { + ZONE_STATUS_NONE = 0, + ZONE_STATUS_IN, + ZONE_STATUS_OUT, +} ZoneStatus; + +typedef struct _LocationBoundaryPrivate { + LocationBoundary *boundary; + ZoneStatus zone_status; +} LocationBoundaryPrivate; + +int location_application_manager (void); +int location_application_enabled (void); + +int location_application_get_authority(void); +int location_application_set_authority (int auth); +int location_application_add_app_to_applist (void); + +int set_prop_boundary(GList **prev_boundary_list, GList *new_boundary_list); +int set_prop_removal_boundary(GList **prev_boundary_list, LocationBoundary *boundary); +void free_boundary_list (gpointer data); + +G_END_DECLS + +#endif diff --git a/location/manager/location-cps.c b/location/manager/location-cps.c new file mode 100644 index 0000000..8595d5f --- /dev/null +++ b/location/manager/location-cps.c @@ -0,0 +1,748 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-setting.h" +#include "location-log.h" + +#include "module-internal.h" + +#include "location-cps.h" +#include "location-marshal.h" +#include "location-ielement.h" +#include "location-signaling-util.h" +#include "location-common-util.h" + +typedef struct _LocationCpsPrivate { + LocationCpsMod *mod; + gboolean is_started; + gboolean set_noti; + gboolean enabled; + guint pos_updated_timestamp; + guint pos_interval; + guint vel_updated_timestamp; + guint vel_interval; + LocationPosition *pos; + LocationVelocity *vel; + LocationAccuracy *acc; + GList *boundary_list; + guint pos_timer; + guint vel_timer; +} LocationCpsPrivate; + +enum { + PROP_0, + PROP_METHOD_TYPE, + PROP_POS_INTERVAL, + PROP_VEL_INTERVAL, + PROP_BOUNDARY, + PROP_REMOVAL_BOUNDARY, + PROP_MAX +}; + +static guint32 signals[LAST_SIGNAL] = {0, }; +static GParamSpec *properties[PROP_MAX] = {NULL, }; + + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOCATION_TYPE_CPS, LocationCpsPrivate)) + +static void location_ielement_interface_init (LocationIElementInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (LocationCps, location_cps, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (LOCATION_TYPE_IELEMENT, + location_ielement_interface_init)); + +static gboolean +_position_timeout_cb (gpointer data) +{ + GObject *object = (GObject *)data; + LocationCpsPrivate *priv = GET_PRIVATE(object); + if (!priv) return FALSE; + + LocationPosition *pos = NULL; + LocationAccuracy *acc = NULL; + + if (priv->pos) { + pos = location_position_copy(priv->pos); + } + else { + pos = location_position_new (0, 0.0, 0.0, 0.0, LOCATION_STATUS_NO_FIX); + } + + if (priv->acc) { + acc = location_accuracy_copy (priv->acc); + } + else { + acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + } + + LOCATION_LOGD("VELOCITY SERVICE_UPDATED"); + g_signal_emit(object, signals[SERVICE_UPDATED], 0, POSITION_UPDATED, pos, acc); + + location_position_free (pos); + location_accuracy_free (acc); + + return TRUE; +} + +static gboolean +_velocity_timeout_cb (gpointer data) +{ + GObject *object = (GObject *)data; + LocationCpsPrivate *priv = GET_PRIVATE(object); + if (!priv) return FALSE; + + LocationVelocity *vel = NULL; + LocationAccuracy *acc = NULL; + + if (priv->vel) { + vel = location_velocity_copy(priv->vel); + } + else { + vel = location_velocity_new (0, 0.0, 0.0, 0.0); + } + + if (priv->acc) { + acc = location_accuracy_copy (priv->acc); + } + else { + acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + } + + LOCATION_LOGD("VELOCITY SERVICE_UPDATED"); + g_signal_emit(object, signals[SERVICE_UPDATED], 0, VELOCITY_UPDATED, vel, acc); + + location_velocity_free (vel); + location_accuracy_free (acc); + + return TRUE; +} + +static void +__reset_pos_data_from_priv(LocationCpsPrivate *priv) +{ + LOCATION_LOGD("__reset_pos_data_from_priv"); + g_return_if_fail(priv); + + if (priv->pos) { + location_position_free(priv->pos); + priv->pos = NULL; + } + + if (priv->vel) { + location_velocity_free(priv->vel); + priv->vel = NULL; + } + + if (priv->acc) { + location_accuracy_free(priv->acc); + priv->acc = NULL; + } +} + +static void +cps_status_cb (gboolean enabled, + LocationStatus status, + gpointer self) +{ + LOCATION_LOGD("cps_status_cb"); + g_return_if_fail(self); + LocationCpsPrivate* priv = GET_PRIVATE(self); + enable_signaling(self, signals, &(priv->enabled), enabled, status); + if (!priv->enabled) { + if (priv->pos_timer) { + g_source_remove(g_source_remove(priv->pos_timer)); + priv->pos_timer = 0; + } + if (priv->vel_timer) { + g_source_remove(g_source_remove(priv->vel_timer)); + priv->vel_timer = 0; + } + } +} + +static void +cps_position_ext_cb (gboolean enabled, + LocationPosition *pos, + LocationVelocity *vel, + LocationAccuracy *acc, + gpointer self) +{ + LOCATION_LOGD("cps_position_ext_cb"); + g_return_if_fail(self); + g_return_if_fail(pos); + g_return_if_fail(vel); + g_return_if_fail(acc); + LocationCpsPrivate* priv = GET_PRIVATE(self); + + if (enabled && !priv->enabled) { + if (!priv->pos_timer) priv->pos_timer = g_timeout_add_seconds (priv->pos_interval, _position_timeout_cb, self); + if (!priv->vel_timer) priv->vel_timer = g_timeout_add_seconds (priv->vel_interval, _velocity_timeout_cb, self); + } + + enable_signaling(self, signals, &(priv->enabled), enabled, pos->status); + position_signaling(self, signals, &(priv->enabled), priv->pos_interval, FALSE, &(priv->pos_updated_timestamp), &(priv->pos), &(priv->acc), priv->boundary_list, pos, acc); + velocity_signaling(self, signals, &(priv->enabled), priv->vel_interval, FALSE, &(priv->vel_updated_timestamp), &(priv->vel), vel, acc); +} + +static void +location_setting_cps_cb (keynode_t *key, + gpointer self) +{ + LOCATION_LOGD("location_setting_cps_cb"); + g_return_if_fail (key); + g_return_if_fail (self); + + LocationCpsPrivate *priv = GET_PRIVATE(self); + g_return_if_fail (priv->mod); + g_return_if_fail (priv->mod->handler); + + int ret = LOCATION_ERROR_NONE; + + if (location_setting_get_key_val (key) == 0) { + if (priv->mod->ops.stop && priv->is_started) { + ret = priv->mod->ops.stop (priv->mod->handler); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = FALSE; + __reset_pos_data_from_priv(priv); + } + } + } + else { + if (1 == location_setting_get_int (VCONFKEY_LOCATION_NETWORK_ENABLED) && priv->mod->ops.start && !priv->is_started) { + LOCATION_LOGD("location resumed by setting"); + ret = priv->mod->ops.start (priv->mod->handler, cps_status_cb, cps_position_ext_cb, NULL, self); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = TRUE; + } + } + } +} + +static void +location_cps_dispose (GObject *gobject) +{ + LOCATION_LOGD("location_cps_dispose"); + + LocationCpsPrivate *priv = GET_PRIVATE(gobject); + if (priv->set_noti == TRUE) { + location_setting_ignore_notify (VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_cps_cb); + priv->set_noti = FALSE; + } + + if (priv->pos_timer) { + g_source_remove (priv->pos_timer); + priv->pos_timer = 0; + } + + if (priv->vel_timer) { + g_source_remove (priv->vel_timer); + priv->vel_timer = 0; + } + + G_OBJECT_CLASS (location_cps_parent_class)->dispose (gobject); +} + +static void +location_cps_finalize (GObject *gobject) +{ + LOCATION_LOGD("location_cps_finalize"); + LocationCpsPrivate* priv = GET_PRIVATE(gobject); + module_free(priv->mod, "cps"); + priv->mod = NULL; + + if (priv->boundary_list) { + g_list_free_full (priv->boundary_list, free_boundary_list); + priv->boundary_list = NULL; + } + + if (priv->pos) { + location_position_free(priv->pos); + priv->pos = NULL; + } + + if (priv->vel) { + location_velocity_free(priv->vel); + priv->vel = NULL; + } + + if (priv->acc) { + location_accuracy_free(priv->acc); + priv->acc = NULL; + } + + G_OBJECT_CLASS (location_cps_parent_class)->finalize (gobject); +} + +static void +location_cps_set_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + LocationCpsPrivate *priv = GET_PRIVATE(object); + + int ret = 0; + + switch (property_id) { + case PROP_BOUNDARY:{ + GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value)); + ret = set_prop_boundary(&priv->boundary_list, boundary_list); + if(ret != 0) LOCATION_LOGD("Set boundary. Error[%d]", ret); + break; + } + case PROP_REMOVAL_BOUNDARY: { + LocationBoundary *req_boundary = (LocationBoundary*) g_value_dup_boxed(value); + ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary); + if(ret != 0) LOCATION_LOGD("Set removal boundary. Error[%d]", ret); + break; + } + case PROP_POS_INTERVAL: { + guint interval = g_value_get_uint (value); + + if (interval > 0) { + if (interval < LOCATION_UPDATE_INTERVAL_MAX) + priv->pos_interval = interval; + else + priv->pos_interval = (guint) LOCATION_UPDATE_INTERVAL_MAX; + } + else { + priv->pos_interval = (guint) LOCATION_UPDATE_INTERVAL_DEFAULT; + } + + if (priv->pos_timer) { + g_source_remove (priv->pos_timer); + priv->pos_timer = g_timeout_add_seconds (priv->pos_interval, _position_timeout_cb, object); + } + + break; + } + + case PROP_VEL_INTERVAL: { + guint interval = g_value_get_uint(value); + if(interval > 0) { + if(interval < LOCATION_UPDATE_INTERVAL_MAX) + priv->vel_interval = interval; + else + priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX; + } + else + priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT; + + if (priv->vel_timer) { + g_source_remove (priv->vel_timer); + priv->vel_timer = g_timeout_add_seconds (priv->vel_interval, _velocity_timeout_cb, object); + } + + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +location_cps_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + LocationCpsPrivate *priv = GET_PRIVATE (object); + + switch (property_id){ + case PROP_METHOD_TYPE: + g_value_set_int(value, LOCATION_METHOD_CPS); + break; + case PROP_BOUNDARY: + g_value_set_pointer(value, g_list_first(priv->boundary_list)); + break; + case PROP_POS_INTERVAL: { + g_value_set_uint (value, priv->pos_interval); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static int +location_cps_start (LocationCps *self) +{ + LOCATION_LOGD("location_cps_start"); + + LocationCpsPrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE); + + if (priv->is_started == TRUE) return LOCATION_ERROR_NONE; + + int ret = LOCATION_ERROR_NONE; + + if (!location_setting_get_int (VCONFKEY_LOCATION_NETWORK_ENABLED)) { + ret = LOCATION_ERROR_SETTING_OFF; + } + else { + ret = priv->mod->ops.start (priv->mod->handler, cps_status_cb, cps_position_ext_cb, NULL, self); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = TRUE; + } + else { + return ret; + } + } + + if (priv->set_noti == FALSE) { + location_setting_add_notify (VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_cps_cb, self); + priv->set_noti = TRUE; + } + + return ret; +} + +static int +location_cps_stop (LocationCps *self) +{ + LOCATION_LOGD("location_cps_stop"); + LocationCpsPrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.stop, LOCATION_ERROR_NOT_AVAILABLE); + + int ret = LOCATION_ERROR_NONE; + + if (priv->is_started == TRUE) { + ret = priv->mod->ops.stop (priv->mod->handler); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = FALSE; + __reset_pos_data_from_priv(priv); + } + else { + LOCATION_LOGD("Failed to stop. Error[%d]", ret); + } + } + + if (priv->set_noti == TRUE) { + location_setting_ignore_notify (VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_cps_cb); + priv->set_noti = FALSE; + } + + return ret; +} + +static int +location_cps_get_position (LocationCps *self, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + int ret = LOCATION_ERROR_NOT_AVAILABLE; + LOCATION_LOGD("location_cps_get_position"); + + LocationCpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + + setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED); + + if (priv->is_started != TRUE) { + LOCATION_LOGD("location is not started"); + return LOCATION_ERROR_NOT_AVAILABLE; + } + + if (priv->pos) { + *position = location_position_copy (priv->pos); + if (priv->acc) *accuracy = location_accuracy_copy(priv->acc); + else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + ret = LOCATION_ERROR_NONE; + } + + return ret; +} + +static int +location_cps_get_position_ext (LocationCps *self, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + int ret = LOCATION_ERROR_NOT_AVAILABLE; + LOCATION_LOGD("location_cps_get_position"); + + LocationCpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + + setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED); + + if (priv->is_started != TRUE) { + LOCATION_LOGD("location is not started"); + return LOCATION_ERROR_NOT_AVAILABLE; + } + + if (priv->pos && priv->vel) { + *position = location_position_copy (priv->pos); + *velocity = location_velocity_copy (priv->vel); + if (priv->acc) *accuracy = location_accuracy_copy(priv->acc); + else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + ret = LOCATION_ERROR_NONE; + } + + return ret; +} + + +static int +location_cps_get_last_position (LocationCps *self, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_cps_get_last_position"); + + /* Do not need to check GPS_ENABLED and NETWORK_ENABLED */ + + LocationCpsPrivate *priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + + LocationError ret = LOCATION_ERROR_NONE; + LocationVelocity *_velocity = NULL; + + LocModCpsOps ops = priv->mod->ops; + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (ops.get_last_position, LOCATION_ERROR_NOT_AVAILABLE); + + ret = ops.get_last_position (priv->mod->handler, position, &_velocity, accuracy); + if (!_velocity) location_velocity_free (_velocity); + + return ret; +} + +static int +location_cps_get_last_position_ext (LocationCps *self, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_cps_get_last_position"); + + /* Do not need to check GPS_ENABLED and NETWORK_ENABLED */ + + LocationCpsPrivate *priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + + LocationError ret = LOCATION_ERROR_NONE; + + LocModCpsOps ops = priv->mod->ops; + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (ops.get_last_position, LOCATION_ERROR_NOT_AVAILABLE); + + return ops.get_last_position (priv->mod->handler, position, velocity, accuracy); +} + + +static int +location_cps_get_velocity (LocationCps *self, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_cps_get_velocity"); + return LOCATION_ERROR_NOT_SUPPORTED; +} + +static int +location_cps_get_last_velocity (LocationCps *self, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_cps_get_last_velocity"); + return LOCATION_ERROR_NOT_SUPPORTED; +} + +static int +location_cps_get_satellite (LocationCps *self, + LocationSatellite **satellite) +{ + LOCATION_LOGD("location_cps_get_satellite"); + return LOCATION_ERROR_NOT_SUPPORTED; +} + +static int +location_cps_get_last_satellite (LocationCps *self) +{ + LOCATION_LOGD("location_cps_get_last_satellite"); + return LOCATION_ERROR_NOT_SUPPORTED; +} + +static void +location_ielement_interface_init (LocationIElementInterface *iface) +{ + iface->start = (TYPE_START_FUNC) location_cps_start; + iface->stop = (TYPE_STOP_FUNC) location_cps_stop; + iface->get_position = (TYPE_GET_POSITION) location_cps_get_position; + iface->get_position_ext = (TYPE_GET_POSITION_EXT) location_cps_get_position_ext; + iface->get_last_position = (TYPE_GET_POSITION) location_cps_get_last_position; + iface->get_last_position_ext = (TYPE_GET_POSITION_EXT) location_cps_get_last_position_ext; + iface->get_velocity = (TYPE_GET_VELOCITY) location_cps_get_velocity; + iface->get_last_velocity = (TYPE_GET_VELOCITY)location_cps_get_last_velocity; + iface->get_satellite = (TYPE_GET_SATELLITE)location_cps_get_satellite; + iface->get_last_satellite = (TYPE_GET_SATELLITE)location_cps_get_last_satellite; +} + +static void +location_cps_init (LocationCps *self) +{ + LOCATION_LOGD("location_cps_init"); + LocationCpsPrivate* priv = GET_PRIVATE(self); + + priv->mod = (LocationCpsMod*)module_new("cps"); + if(!priv->mod) LOCATION_LOGW("module loading failed"); + + priv->is_started = FALSE; + priv->set_noti = FALSE; + priv->enabled = FALSE; + + priv->pos_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + priv->vel_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + + priv->pos_updated_timestamp = 0; + priv->vel_updated_timestamp = 0; + + priv->pos = NULL; + priv->acc = NULL; + priv->vel = NULL; + priv->boundary_list = NULL; + + priv->pos_timer = 0; + priv->vel_timer = 0; +} + +static void +location_cps_class_init (LocationCpsClass *klass) +{ + LOCATION_LOGD("location_cps_class_init"); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = location_cps_get_property; + gobject_class->set_property = location_cps_set_property; + + gobject_class->dispose = location_cps_dispose; + gobject_class->finalize = location_cps_finalize; + + g_type_class_add_private (klass, sizeof (LocationCpsPrivate)); + + signals[SERVICE_ENABLED] = g_signal_new ("service-enabled", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationCpsClass, enabled), + NULL, NULL, + location_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[SERVICE_DISABLED] = g_signal_new ("service-disabled", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationCpsClass, disabled), + NULL, NULL, + location_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[SERVICE_UPDATED] = g_signal_new ("service-updated", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationCpsClass, updated), + NULL, NULL, + location_VOID__UINT_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_UINT, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[ZONE_IN] = g_signal_new ("zone-in", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationCpsClass, zone_in), + NULL, NULL, + location_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_POINTER, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[ZONE_OUT] = g_signal_new ("zone-out", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationCpsClass, zone_out), + NULL, NULL, + location_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_POINTER, + G_TYPE_POINTER, + G_TYPE_POINTER); + + properties[PROP_METHOD_TYPE] = g_param_spec_int ("method", + "method type", + "location method type name", + LOCATION_METHOD_CPS, + LOCATION_METHOD_CPS, + LOCATION_METHOD_CPS, + G_PARAM_READABLE); + + properties[PROP_POS_INTERVAL] = g_param_spec_uint ("pos-interval", + "cps position interval prop", + "cps position interval data", + LOCATION_UPDATE_INTERVAL_MIN, + LOCATION_UPDATE_INTERVAL_MAX, + LOCATION_UPDATE_INTERVAL_DEFAULT, + G_PARAM_READWRITE); + + properties[PROP_VEL_INTERVAL] = g_param_spec_uint ("vel-interval", + "cps velocity interval prop", + "cps velocity interval data", + LOCATION_UPDATE_INTERVAL_MIN, + LOCATION_UPDATE_INTERVAL_MAX, + LOCATION_UPDATE_INTERVAL_DEFAULT, + G_PARAM_READWRITE); + + properties[PROP_BOUNDARY] = g_param_spec_pointer ("boundary", + "cps boundary prop", + "cps boundary data", + G_PARAM_READWRITE); + + properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary", + "cps removal boundary prop", + "cps removal boundary data", + LOCATION_TYPE_BOUNDARY, + G_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, + PROP_MAX, + properties); + +} diff --git a/location/manager/location-cps.h b/location/manager/location-cps.h new file mode 100644 index 0000000..355586a --- /dev/null +++ b/location/manager/location-cps.h @@ -0,0 +1,64 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_CPS_H__ +#define __LOCATION_CPS_H__ + +#include + +/** + * @file location-cps.h + * @brief This file contains the internal definitions and structures related to CPS. + */ + +G_BEGIN_DECLS + +#define LOCATION_TYPE_CPS (location_cps_get_type ()) +#define LOCATION_CPS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOCATION_TYPE_CPS, LocationCps)) +#define LOCATION_IS_CPS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LOCATION_TYPE_CPS)) +#define LOCATION_CPS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LOCATION_TYPE_CPS, LocationCpsClass)) +#define LOCATION_IS_CPS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LOCATION_TYPE_CPS)) +#define LOCATION_CPS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LOCATION_TYPE_CPS, LocationCpsClass)) + +typedef struct _LocationCps LocationCps; +typedef struct _LocationCpsClass LocationCpsClass; + +struct _LocationCps +{ + GObject parent_instance; +}; + +struct _LocationCpsClass +{ + GObjectClass parent_class; + + void (* enabled) (guint type); + void (* disabled) (guint type); + void (* updated) (guint type, gpointer data, gpointer accuracy); + void (* zone_in) (gpointer boundary, gpointer position, gpointer accuracy); + void (* zone_out) (gpointer boundary, gpointer position, gpointer accuracy); +}; + +GType location_cps_get_type (void); + +G_END_DECLS + +#endif diff --git a/location/manager/location-gps.c b/location/manager/location-gps.c new file mode 100644 index 0000000..25ede96 --- /dev/null +++ b/location/manager/location-gps.c @@ -0,0 +1,954 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-setting.h" +#include "location-log.h" + +#include "module-internal.h" + +#include "location-gps.h" +#include "location-marshal.h" +#include "location-ielement.h" +#include "location-signaling-util.h" +#include "location-common-util.h" + +#include + +typedef struct _LocationGpsPrivate { + LocationGpsMod* mod; + gboolean is_started; + gboolean set_noti; + gboolean enabled; + guint pos_updated_timestamp; + guint pos_interval; + guint vel_updated_timestamp; + guint vel_interval; + guint sat_updated_timestamp; + guint sat_interval; + LocationPosition* pos; + LocationVelocity* vel; + LocationAccuracy* acc; + LocationSatellite* sat; + GList* boundary_list; + + guint pos_timer; + guint vel_timer; + +} LocationGpsPrivate; + +enum { + PROP_0, + PROP_DEV_NAME, + PROP_METHOD_TYPE, + PROP_LAST_POSITION, + PROP_POS_INTERVAL, + PROP_VEL_INTERVAL, + PROP_SAT_INTERVAL, + PROP_BOUNDARY, + PROP_REMOVAL_BOUNDARY, + PROP_NMEA, + PROP_SATELLITE, + PROP_MAX +}; + +static guint32 signals[LAST_SIGNAL] = {0, }; +static GParamSpec *properties[PROP_MAX] = {NULL, }; + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOCATION_TYPE_GPS, LocationGpsPrivate)) + +static void location_ielement_interface_init (LocationIElementInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (LocationGps, location_gps, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (LOCATION_TYPE_IELEMENT, + location_ielement_interface_init)); + +static gboolean +_position_timeout_cb (gpointer data) +{ + GObject *object = (GObject *)data; + LocationGpsPrivate *priv = GET_PRIVATE(object); + if (!priv) return FALSE; + + LocationPosition *pos = NULL; + LocationAccuracy *acc = NULL; + + if (priv->pos) { + pos = location_position_copy(priv->pos); + } + else { + pos = location_position_new (0, 0.0, 0.0, 0.0, LOCATION_STATUS_NO_FIX); + } + + if (priv->acc) { + acc = location_accuracy_copy (priv->acc); + } + else { + acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + } + + LOCATION_LOGD("POSITION SERVICE_UPDATED"); + g_signal_emit(object, signals[SERVICE_UPDATED], 0, POSITION_UPDATED, pos, acc); + + location_position_free (pos); + location_accuracy_free (acc); + + return TRUE; +} + +static gboolean +_velocity_timeout_cb (gpointer data) +{ + GObject *object = (GObject *)data; + LocationGpsPrivate *priv = GET_PRIVATE(object); + if (!priv) return FALSE; + + LocationVelocity *vel = NULL; + LocationAccuracy *acc = NULL; + + if (priv->vel) { + vel = location_velocity_copy(priv->vel); + } + else { + vel = location_velocity_new (0, 0.0, 0.0, 0.0); + } + + if (priv->acc) { + acc = location_accuracy_copy (priv->acc); + } + else { + acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + } + + LOCATION_LOGD("VELOCITY SERVICE_UPDATED"); + g_signal_emit(object, signals[SERVICE_UPDATED], 0, VELOCITY_UPDATED, vel, acc); + + location_velocity_free (vel); + location_accuracy_free (acc); + + return TRUE; +} + +static void +__reset_pos_data_from_priv(LocationGpsPrivate *priv) +{ + LOCATION_LOGD("__reset_pos_data_from_priv"); + g_return_if_fail(priv); + + if (priv->pos) { + location_position_free(priv->pos); + priv->pos = NULL; + } + + if (priv->vel) { + location_velocity_free(priv->vel); + priv->vel = NULL; + } + + if (priv->sat) { + location_satellite_free(priv->sat); + priv->sat = NULL; + } + + if (priv->acc) { + location_accuracy_free(priv->acc); + priv->acc = NULL; + } +} + +static void +gps_status_cb (gboolean enabled, + LocationStatus status, + gpointer self) +{ + LOCATION_LOGD("gps_status_cb"); + g_return_if_fail(self); + LocationGpsPrivate* priv = GET_PRIVATE(self); + enable_signaling(self, signals, &(priv->enabled), enabled, status); + + if (!priv->enabled) { + if (priv->pos_timer) g_source_remove (priv->pos_timer); + if (priv->vel_timer) g_source_remove (priv->vel_timer); + priv->pos_timer = 0; + priv->vel_timer = 0; + } +} + +static void +gps_position_ext_cb (gboolean enabled, + LocationPosition *pos, + LocationVelocity *vel, + LocationAccuracy *acc, + gpointer self) +{ + LOCATION_LOGD("gps_position_ext_cb"); + g_return_if_fail(self); + g_return_if_fail(pos); + g_return_if_fail(vel); + g_return_if_fail(acc); + LocationGpsPrivate* priv = GET_PRIVATE(self); + + enable_signaling(self, signals, &(priv->enabled), enabled, pos->status); + position_signaling(self, signals, &(priv->enabled), priv->pos_interval, TRUE, &(priv->pos_updated_timestamp), &(priv->pos), &(priv->acc), priv->boundary_list, pos, acc); + velocity_signaling(self, signals, &(priv->enabled), priv->vel_interval, TRUE, &(priv->vel_updated_timestamp), &(priv->vel), vel, acc); +} + +static void +gps_satellite_cb (gboolean enabled, + LocationSatellite *sat, + gpointer self) +{ + LOCATION_LOGD("gps_satellite_cb"); + g_return_if_fail(self); + LocationGpsPrivate* priv = GET_PRIVATE(self); + satellite_signaling(self, signals, &(priv->enabled), priv->sat_interval, TRUE, &(priv->sat_updated_timestamp), &(priv->sat), sat); +} + +static void +location_setting_search_cb (keynode_t *key, gpointer self) +{ + LOCATION_LOGD("location_setting_search_cb"); + g_return_if_fail(key); + g_return_if_fail(self); + LocationGpsPrivate* priv = GET_PRIVATE(self); + g_return_if_fail (priv->mod); + g_return_if_fail (priv->mod->handler); + + if (location_setting_get_key_val(key) == VCONFKEY_LOCATION_GPS_SEARCHING) { + if (!priv->pos_timer) priv->pos_timer = g_timeout_add (priv->pos_interval * 1000, _position_timeout_cb, self); + if (!priv->vel_timer) priv->vel_timer = g_timeout_add (priv->vel_interval * 1000, _velocity_timeout_cb, self); + } + else { + if (priv->pos_timer) g_source_remove (priv->pos_timer); + if (priv->vel_timer) g_source_remove (priv->vel_timer); + priv->pos_timer = 0; + priv->vel_timer = 0; + } +} + +static void +location_setting_gps_cb (keynode_t *key, + gpointer self) +{ + LOCATION_LOGD("location_setting_gps_cb"); + g_return_if_fail(key); + g_return_if_fail(self); + LocationGpsPrivate* priv = GET_PRIVATE(self); + g_return_if_fail (priv->mod); + g_return_if_fail (priv->mod->handler); + + int ret = LOCATION_ERROR_NONE; + + if (0 == location_setting_get_key_val(key) && priv->mod->ops.stop && priv->is_started) { + LOCATION_LOGD("location stopped by setting"); + ret = priv->mod->ops.stop(priv->mod->handler); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = FALSE; + __reset_pos_data_from_priv(priv); + } + } + else if (1 == location_setting_get_key_val(key) && priv->mod->ops.start && !priv->is_started) { + LOCATION_LOGD("location resumed by setting"); + ret = priv->mod->ops.start (priv->mod->handler, gps_status_cb, gps_position_ext_cb, gps_satellite_cb, self); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = TRUE; + } + } +} + +static int +location_gps_start (LocationGps *self) +{ + LOCATION_LOGD("location_gps_start"); + LocationGpsPrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE); + + if (priv->is_started == TRUE) return LOCATION_ERROR_NONE; + + int ret = LOCATION_ERROR_NONE; + + if (!location_setting_get_int(VCONFKEY_LOCATION_ENABLED)) { + ret = LOCATION_ERROR_SETTING_OFF; + } + else { + ret = priv->mod->ops.start (priv->mod->handler, gps_status_cb, gps_position_ext_cb, gps_satellite_cb, self); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = TRUE; + } + else { + return ret; + } + } + + if(priv->set_noti == FALSE) { + location_setting_add_notify (VCONFKEY_LOCATION_ENABLED, location_setting_gps_cb, self); + location_setting_add_notify (VCONFKEY_LOCATION_GPS_STATE, location_setting_search_cb, self); + priv->set_noti = TRUE; + } + + return ret; +} + +static int +location_gps_stop (LocationGps *self) +{ + LOCATION_LOGD("location_gps_stop"); + LocationGpsPrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.stop, LOCATION_ERROR_NOT_AVAILABLE); + + int ret = LOCATION_ERROR_NONE; + + if ( priv->is_started == TRUE) { + ret = priv->mod->ops.stop (priv->mod->handler); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = FALSE; + } + else { + LOCATION_LOGD("Failed to stop. Error[%d]", ret); + } + } + + if (priv->pos_timer ) g_source_remove (priv->pos_timer); + if (priv->vel_timer ) g_source_remove (priv->vel_timer); + priv->pos_timer = 0; + priv->vel_timer = 0; + + if(priv->set_noti == TRUE) { + location_setting_ignore_notify (VCONFKEY_LOCATION_ENABLED, location_setting_gps_cb); + location_setting_ignore_notify (VCONFKEY_LOCATION_GPS_STATE, location_setting_search_cb); + priv->set_noti = FALSE; + } + __reset_pos_data_from_priv(priv); + + return ret; +} + +static void +location_gps_dispose (GObject *gobject) +{ + LOCATION_LOGD("location_gps_dispose"); + + LocationGpsPrivate* priv = GET_PRIVATE(gobject); + + if (priv->pos_timer) g_source_remove (priv->pos_timer); + if (priv->vel_timer) g_source_remove (priv->vel_timer); + priv->pos_timer = 0; + priv->vel_timer = 0; + + if(priv->set_noti == TRUE) { + location_setting_ignore_notify (VCONFKEY_LOCATION_ENABLED, location_setting_gps_cb); + location_setting_ignore_notify (VCONFKEY_LOCATION_GPS_STATE, location_setting_search_cb); + priv->set_noti = FALSE; + } + +} + +static void +location_gps_finalize (GObject *gobject) +{ + LOCATION_LOGD("location_gps_finalize"); + LocationGpsPrivate* priv = GET_PRIVATE(gobject); + + module_free(priv->mod, "gps"); + priv->mod = NULL; + + if (priv->boundary_list) { + g_list_free_full (priv->boundary_list, free_boundary_list); + priv->boundary_list = NULL; + } + + if (priv->pos) { + location_position_free(priv->pos); + priv->pos = NULL; + } + + if (priv->vel) { + location_velocity_free(priv->vel); + priv->vel = NULL; + } + + if (priv->acc) { + location_accuracy_free(priv->acc); + priv->acc = NULL; + } + + if (priv->sat) { + location_satellite_free(priv->sat); + priv->sat = NULL; + } + G_OBJECT_CLASS (location_gps_parent_class)->finalize (gobject); +} + +static void +location_gps_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + LocationGpsPrivate* priv = GET_PRIVATE(object); + + g_return_if_fail (priv->mod); + g_return_if_fail (priv->mod->handler); + LocModGpsOps ops = priv->mod->ops; + + int ret = 0; + switch (property_id){ + case PROP_DEV_NAME: { + char* devname = g_value_dup_string(value); + LOCATION_LOGD("Set prop>> device_name: %s", devname); + if(ops.set_devname) + ops.set_devname(priv->mod->handler, devname); + g_free(devname); + break; + } + case PROP_BOUNDARY: { + GList *boundary_list = g_list_copy(g_value_get_pointer(value)); + ret = set_prop_boundary(&priv->boundary_list, boundary_list); + if(ret != 0) LOCATION_LOGD("Set boundary. Error[%d]", ret); + break; + } + case PROP_REMOVAL_BOUNDARY: { + LocationBoundary *req_boundary = (LocationBoundary*) g_value_dup_boxed(value); + ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary); + if(ret != 0) LOCATION_LOGD("Removal boundary. Error[%d]", ret); + break; + } + case PROP_POS_INTERVAL: { + guint interval = g_value_get_uint(value); + LOCATION_LOGD("Set prop>> update-interval: %u", interval); + if(interval > 0) { + if(interval < LOCATION_UPDATE_INTERVAL_MAX) + priv->pos_interval = interval; + else + priv->pos_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX; + } + else + priv->pos_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT; + + if (priv->pos_timer) { + g_source_remove (priv->pos_timer); + priv->pos_timer = g_timeout_add (priv->pos_interval * 1000, _position_timeout_cb, object); + } + + break; + } + case PROP_VEL_INTERVAL: { + guint interval = g_value_get_uint(value); + LOCATION_LOGD("Set prop>> update-interval: %u", interval); + if(interval > 0) { + if(interval < LOCATION_UPDATE_INTERVAL_MAX) + priv->vel_interval = interval; + else + priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX; + } + else + priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT; + + if (priv->vel_timer) { + g_source_remove (priv->vel_timer); + priv->vel_timer = g_timeout_add (priv->vel_interval * 1000, _velocity_timeout_cb, object); + } + + break; + } + case PROP_SAT_INTERVAL: { + guint interval = g_value_get_uint(value); + LOCATION_LOGD("Set prop>> update-interval: %u", interval); + if(interval > 0) { + if(interval < LOCATION_UPDATE_INTERVAL_MAX) + priv->sat_interval = interval; + else + priv->sat_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX; + } + else + priv->sat_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT; + + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +location_gps_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + LocationGpsPrivate *priv = GET_PRIVATE (object); + + g_return_if_fail (priv->mod); + g_return_if_fail (priv->mod->handler); + LocModGpsOps ops = priv->mod->ops; + switch (property_id) { + case PROP_DEV_NAME: { + char* devname = NULL; + if(ops.get_devname) + ops.get_devname(priv->mod->handler, &devname); + LOCATION_LOGD ("Get prop>> device_name: %s", devname); + g_value_set_string (value, devname); + g_free(devname); + break; + } + case PROP_METHOD_TYPE: + g_value_set_int(value, LOCATION_METHOD_GPS); + break; + case PROP_LAST_POSITION: + g_value_set_boxed (value, priv->pos); + break; + case PROP_POS_INTERVAL: + g_value_set_uint(value, priv->pos_interval); + break; + case PROP_VEL_INTERVAL: + g_value_set_uint(value, priv->vel_interval); + break; + case PROP_SAT_INTERVAL: + g_value_set_uint(value, priv->sat_interval); + break; + case PROP_BOUNDARY: + g_value_set_pointer(value, g_list_first(priv->boundary_list)); + break; + case PROP_NMEA: { + char *nmea_data = NULL; + if (ops.get_nmea && LOCATION_ERROR_NONE == ops.get_nmea(priv->mod->handler, &nmea_data) && nmea_data) { + LOCATION_LOGD("Get prop>> Lastest nmea: \n%s", nmea_data); + g_value_set_string(value, nmea_data); + g_free(nmea_data); + } else { + LOCATION_LOGW("Get prop>> Lastest nmea: failed"); + g_value_set_string(value, NULL); + } + break; + } + case PROP_SATELLITE: { + LocationSatellite *satellite = NULL; + if (ops.get_satellite && priv->mod->handler && LOCATION_ERROR_NONE == ops.get_satellite(priv->mod->handler, &satellite) && satellite){ + LOCATION_LOGD("Get prop>> Last sat: num_used(%d) num_view(%d)", satellite->num_of_sat_used, satellite->num_of_sat_inview); + g_value_set_boxed (value, satellite); + location_satellite_free(satellite); + } else { + LOCATION_LOGW("Get prop>> Last sat: failed"); + g_value_set_boxed (value, NULL); + } + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static int +location_gps_get_position (LocationGps *self, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + int ret = LOCATION_ERROR_NOT_AVAILABLE; + LOCATION_LOGD("location_gps_get_position"); + + LocationGpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + setting_retval_if_fail(VCONFKEY_LOCATION_ENABLED); + + LocModGpsOps ops = priv->mod->ops; + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (ops.get_position, LOCATION_ERROR_NOT_AVAILABLE); + + if (priv->is_started != TRUE) { + LOCATION_LOGD("location is not started"); + return LOCATION_ERROR_NOT_AVAILABLE; + } + + if (priv->pos) { + *position = location_position_copy (priv->pos); + if (priv->acc) *accuracy = location_accuracy_copy (priv->acc); + else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + ret = LOCATION_ERROR_NONE; + } + + return ret; +} + +static int +location_gps_get_position_ext (LocationGps *self, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + int ret = LOCATION_ERROR_NOT_AVAILABLE; + LOCATION_LOGD("location_gps_get_position_ext"); + + LocationGpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + setting_retval_if_fail(VCONFKEY_LOCATION_ENABLED); + + if (priv->is_started != TRUE) { + LOCATION_LOGD("location is not started"); + return LOCATION_ERROR_NOT_AVAILABLE; + } + + if (priv->pos && priv->vel) { + *position = location_position_copy (priv->pos); + *velocity = location_velocity_copy (priv->vel); + if (priv->acc) *accuracy = location_accuracy_copy (priv->acc); + else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + ret = LOCATION_ERROR_NONE; + } + + return ret; +} + + +static int +location_gps_get_last_position (LocationGps *self, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_gps_get_last_position"); + // Enable to get a last position even though GPS_ENABLE dose not set on + + LocationGpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + + LocationError ret = LOCATION_ERROR_NOT_AVAILABLE; + LocationVelocity *_velocity = NULL; + + LocModGpsOps ops = priv->mod->ops; + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (ops.get_last_position, LOCATION_ERROR_NOT_AVAILABLE); + ret = ops.get_last_position(priv->mod->handler, position, &_velocity, accuracy); + + if (!_velocity) return LOCATION_ERROR_NOT_AVAILABLE; + + return ret; +} + +static int +location_gps_get_last_position_ext (LocationGps *self, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_gps_get_last_position"); + // Enable to get a last position even though GPS_ENABLE dose not set on + + LocationGpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + + LocModGpsOps ops = priv->mod->ops; + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (ops.get_last_position, LOCATION_ERROR_NOT_AVAILABLE); + return ops.get_last_position(priv->mod->handler, position, velocity, accuracy); + +} + + +static int +location_gps_get_velocity (LocationGps *self, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_gps_get_velocity"); + + int ret = LOCATION_ERROR_NOT_AVAILABLE; + + LocationGpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + setting_retval_if_fail(VCONFKEY_LOCATION_ENABLED); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + + if (priv->is_started != TRUE) { + LOCATION_LOGD("location is not started"); + return LOCATION_ERROR_NOT_AVAILABLE; + } + + if (priv->vel) { + *velocity = location_velocity_copy (priv->vel); + if (priv->acc) *accuracy = location_accuracy_copy (priv->acc); + else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + ret = LOCATION_ERROR_NONE; + } + + return ret; +} + +static int +location_gps_get_last_velocity (LocationGps *self, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_gps_get_last_velocity"); + + LocationGpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + setting_retval_if_fail(VCONFKEY_LOCATION_ENABLED); + + LocationError ret = LOCATION_ERROR_NONE; + LocationPosition *_position = NULL; + + LocModGpsOps ops = priv->mod->ops; + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (ops.get_last_position, LOCATION_ERROR_NOT_AVAILABLE); + ret = ops.get_last_position(priv->mod->handler, &_position, velocity, accuracy); + if (!_position) return LOCATION_ERROR_NOT_AVAILABLE; + + return ret; +} + +static int +location_gps_get_satellite (LocationGps *self, + LocationSatellite **satellite) +{ + int ret = LOCATION_ERROR_NOT_AVAILABLE; + LOCATION_LOGD("location_gps_get_satellite"); + + LocationGpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + setting_retval_if_fail(VCONFKEY_LOCATION_ENABLED); + + if (priv->is_started != TRUE) { + LOCATION_LOGD("location is not started"); + return LOCATION_ERROR_NOT_AVAILABLE; + } + + if (priv->sat) { + *satellite = location_satellite_copy (priv->sat); + ret = LOCATION_ERROR_NONE; + } + + return ret; +} + +static int +location_gps_get_last_satellite (LocationGps *self, + LocationSatellite **satellite) +{ + LOCATION_LOGD("location_gps_get_last_satellite"); + + LocationGpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + setting_retval_if_fail(VCONFKEY_LOCATION_ENABLED); + + LocModGpsOps ops = priv->mod->ops; + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (ops.get_last_satellite, LOCATION_ERROR_NOT_AVAILABLE); + return ops.get_last_satellite(priv->mod->handler, satellite); +} + +static void +location_ielement_interface_init (LocationIElementInterface *iface) +{ + iface->start = (TYPE_START_FUNC)location_gps_start; + iface->stop = (TYPE_STOP_FUNC)location_gps_stop; + iface->get_position = (TYPE_GET_POSITION)location_gps_get_position; + iface->get_position_ext = (TYPE_GET_POSITION_EXT)location_gps_get_position_ext; + iface->get_last_position = (TYPE_GET_POSITION)location_gps_get_last_position; + iface->get_last_position_ext = (TYPE_GET_POSITION_EXT)location_gps_get_last_position_ext; + iface->get_velocity = (TYPE_GET_VELOCITY)location_gps_get_velocity; + iface->get_last_velocity = (TYPE_GET_VELOCITY)location_gps_get_last_velocity; + iface->get_satellite = (TYPE_GET_SATELLITE)location_gps_get_satellite; + iface->get_last_satellite = (TYPE_GET_SATELLITE)location_gps_get_last_satellite; +} + +static void +location_gps_init (LocationGps *self) +{ + LOCATION_LOGD("location_gps_init"); + LocationGpsPrivate* priv = GET_PRIVATE(self); + + priv->mod = (LocationGpsMod*)module_new("gps"); + if(!priv->mod) LOCATION_LOGW("module loading failed"); + + priv->is_started = FALSE; + priv->set_noti = FALSE; + priv->enabled= FALSE; + + priv->pos_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + priv->vel_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + priv->sat_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + + priv->pos_updated_timestamp = 0; + priv->vel_updated_timestamp = 0; + priv->sat_updated_timestamp = 0; + + priv->pos = NULL; + priv->vel = NULL; + priv->acc = NULL; + priv->sat = NULL; + priv->boundary_list = NULL; + + priv->pos_timer = 0; + priv->vel_timer = 0; + +} + +static void +location_gps_class_init (LocationGpsClass *klass) +{ + LOCATION_LOGD("location_gps_class_init"); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = location_gps_set_property; + gobject_class->get_property = location_gps_get_property; + + gobject_class->dispose = location_gps_dispose; + gobject_class->finalize = location_gps_finalize; + + g_type_class_add_private (klass, sizeof (LocationGpsPrivate)); + + signals[SERVICE_ENABLED] = g_signal_new ("service-enabled", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationGpsClass, enabled), + NULL, NULL, + location_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[SERVICE_DISABLED] = g_signal_new ("service-disabled", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationGpsClass, disabled), + NULL, NULL, + location_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[SERVICE_UPDATED] = g_signal_new ("service-updated", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationGpsClass, updated), + NULL, NULL, + location_VOID__UINT_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_UINT, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[ZONE_IN] = g_signal_new ("zone-in", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationGpsClass, zone_in), + NULL, NULL, + location_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_POINTER, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[ZONE_OUT] = g_signal_new ("zone-out", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationGpsClass, zone_out), + NULL, NULL, + location_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_POINTER, + G_TYPE_POINTER, + G_TYPE_POINTER); + + properties[PROP_DEV_NAME] = g_param_spec_string ("dev-name", + "gps device name prop", + "gps device name", + "/dev/rfcomm0", + G_PARAM_READWRITE); + + properties[PROP_METHOD_TYPE] = g_param_spec_int ("method", + "method type", + "location method type name", + LOCATION_METHOD_GPS, + LOCATION_METHOD_GPS, + LOCATION_METHOD_GPS, + G_PARAM_READABLE); + + properties[PROP_LAST_POSITION] = g_param_spec_boxed ("last-position", + "gps last position prop", + "gps last position data", + LOCATION_TYPE_POSITION, + G_PARAM_READABLE); + + properties[PROP_POS_INTERVAL] = g_param_spec_uint ("pos-interval", + "gps position interval prop", + "gps position interval data", + LOCATION_UPDATE_INTERVAL_MIN, + LOCATION_UPDATE_INTERVAL_MAX, + LOCATION_UPDATE_INTERVAL_DEFAULT, + G_PARAM_READWRITE); + + properties[PROP_VEL_INTERVAL] = g_param_spec_uint ("vel-interval", + "gps velocity interval prop", + "gps velocity interval data", + LOCATION_UPDATE_INTERVAL_MIN, + LOCATION_UPDATE_INTERVAL_MAX, + LOCATION_UPDATE_INTERVAL_DEFAULT, + G_PARAM_READWRITE); + + properties[PROP_SAT_INTERVAL] = g_param_spec_uint ("sat-interval", + "gps satellite interval prop", + "gps satellite interval data", + LOCATION_UPDATE_INTERVAL_MIN, + LOCATION_UPDATE_INTERVAL_MAX, + LOCATION_UPDATE_INTERVAL_DEFAULT, + G_PARAM_READWRITE); + ; + properties[PROP_BOUNDARY] = g_param_spec_pointer ("boundary", + "gps boundary prop", + "gps boundary data", + G_PARAM_READWRITE); + + properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary", + "gps removal boundary prop", + "gps removal boundary data", + LOCATION_TYPE_BOUNDARY, + G_PARAM_READWRITE); + + + properties[PROP_NMEA] = g_param_spec_string ("nmea", + "gps NMEA name prop", + "gps NMEA", + NULL, + G_PARAM_READABLE); + + properties[PROP_SATELLITE] = g_param_spec_boxed ("satellite", + "gps satellite prop", + "gps satellite data", + LOCATION_TYPE_SATELLITE, + G_PARAM_READABLE); + + g_object_class_install_properties (gobject_class, + PROP_MAX, + properties); + +} diff --git a/location/manager/location-gps.h b/location/manager/location-gps.h new file mode 100644 index 0000000..1f18268 --- /dev/null +++ b/location/manager/location-gps.h @@ -0,0 +1,65 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_GPS_H__ +#define __LOCATION_GPS_H__ + +#include + + +/** + * @file location-gps.h + * @brief This file contains the internal definitions and structures related to GPS. + */ + +G_BEGIN_DECLS + +#define LOCATION_TYPE_GPS (location_gps_get_type ()) +#define LOCATION_GPS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOCATION_TYPE_GPS, LocationGps)) +#define LOCATION_IS_GPS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LOCATION_TYPE_GPS)) +#define LOCATION_GPS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LOCATION_TYPE_GPS, LocationGpsClass)) +#define LOCATION_IS_GPS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LOCATION_TYPE_GPS)) +#define LOCATION_GPS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LOCATION_TYPE_GPS, LocationGpsClass)) + +typedef struct _LocationGps LocationGps; +typedef struct _LocationGpsClass LocationGpsClass; + +struct _LocationGps +{ + GObject parent_instance; +}; + +struct _LocationGpsClass +{ + GObjectClass parent_class; + + void (* enabled) (guint type); + void (* disabled) (guint type); + void (* updated) (guint type, gpointer data, gpointer accuracy); + void (* zone_in) (gpointer boundary, gpointer position, gpointer accuracy); + void (* zone_out) (gpointer boundary, gpointer position, gpointer accuracy); +}; + +GType location_gps_get_type (void); + +G_END_DECLS + +#endif diff --git a/location/manager/location-hybrid.c b/location/manager/location-hybrid.c new file mode 100644 index 0000000..096c063 --- /dev/null +++ b/location/manager/location-hybrid.c @@ -0,0 +1,1067 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-setting.h" +#include "location-log.h" + +#include "module-internal.h" + +#include "location-hybrid.h" +#include "location-marshal.h" +#include "location-ielement.h" +#include "location-signaling-util.h" +#include "location-common-util.h" + +#include "location-gps.h" +#include "location-wps.h" +#include "location-cps.h" + +typedef struct _LocationHybridPrivate { + gboolean is_started; + gboolean gps_enabled; + gboolean wps_enabled; + guint pos_updated_timestamp; + guint pos_interval; + guint vel_updated_timestamp; + guint vel_interval; + guint sat_updated_timestamp; + guint sat_interval; + LocationObject *gps; + LocationObject *wps; + gboolean enabled; + LocationMethod current_method; + LocationPosition *pos; + LocationVelocity *vel; + LocationAccuracy *acc; + LocationSatellite *sat; + GList* boundary_list; + gboolean set_noti; + guint pos_timer; + guint vel_timer; +} LocationHybridPrivate; + +enum { + PROP_0, + PROP_METHOD_TYPE, + PROP_LAST_POSITION, + PROP_POS_INTERVAL, + PROP_VEL_INTERVAL, + PROP_SAT_INTERVAL, + PROP_BOUNDARY, + PROP_REMOVAL_BOUNDARY, + PROP_MAX +}; + +static guint32 signals[LAST_SIGNAL] = {0, }; +static GParamSpec *properties[PROP_MAX] = {NULL, }; + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOCATION_TYPE_HYBRID, LocationHybridPrivate)) + +static void location_ielement_interface_init (LocationIElementInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (LocationHybrid, location_hybrid, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (LOCATION_TYPE_IELEMENT, + location_ielement_interface_init)); + +static LocationMethod +hybrid_get_current_method(LocationHybridPrivate* priv) +{ + g_return_val_if_fail (priv, LOCATION_METHOD_NONE); + LOCATION_LOGW("Current Method [%d]\n", priv->current_method); + return priv->current_method; +} + +static gboolean +hybrid_set_current_method (LocationHybridPrivate* priv, GType g_type) +{ + g_return_val_if_fail (priv, FALSE); + + if (g_type == LOCATION_TYPE_GPS) { + priv->current_method = LOCATION_METHOD_GPS; + LOCATION_LOGW("Set current Method [%d]\n", priv->current_method); + } else if (g_type == LOCATION_TYPE_WPS) { + priv->current_method = LOCATION_METHOD_WPS; + LOCATION_LOGW("Set current Method [%d]\n", priv->current_method); + } else if (g_type == LOCATION_TYPE_HYBRID){ + priv->current_method = LOCATION_METHOD_HYBRID; + LOCATION_LOGW("Set current Method [%d]\n", priv->current_method); + } else + return FALSE; + + return TRUE; +} + + +static int +hybrid_get_update_method (LocationHybridPrivate* priv) +{ + if(!priv->gps && !priv->wps) return -1; + + if (priv->gps_enabled) { + hybrid_set_current_method (priv, LOCATION_TYPE_GPS); + } else if (priv->wps_enabled) { + hybrid_set_current_method (priv, LOCATION_TYPE_WPS); + } else { + hybrid_set_current_method (priv,LOCATION_TYPE_HYBRID); + } + + return 0; +} + +static LocationObject * +hybrid_get_current_object (LocationHybridPrivate* priv) +{ + LocationMethod method = hybrid_get_current_method (priv); + + LocationObject *obj = NULL; + switch (method) { + case LOCATION_METHOD_GPS: + obj = priv->gps; + break; + case LOCATION_METHOD_WPS: + obj = priv->wps; + break; + default: + break; + } + + return obj; +} + +static gboolean /* True : Receive more accurate info. False : Receive less accurate info */ +hybrid_compare_g_type_method(LocationHybridPrivate *priv, GType g_type) +{ + if (g_type == LOCATION_TYPE_GPS) { + hybrid_set_current_method(priv, LOCATION_TYPE_GPS); + return TRUE; + } else if (g_type == LOCATION_TYPE_WPS && hybrid_get_current_method(priv) == LOCATION_METHOD_WPS) { + hybrid_set_current_method(priv, LOCATION_TYPE_WPS); + return TRUE; + } + + return FALSE; +} + +static gboolean +_position_timeout_cb (gpointer data) +{ + LOCATION_LOGD("_position_timeout_cb"); + GObject *object = (GObject *)data; + if (!object) return FALSE; + LocationHybridPrivate *priv = GET_PRIVATE(object); + if (!priv) return FALSE; + + LocationPosition *pos = NULL; + LocationAccuracy *acc = NULL; + + if (priv->pos) { + pos = location_position_copy (priv->pos); + } + else { + pos = location_position_new (0, 0.0, 0.0, 0.0, LOCATION_STATUS_NO_FIX); + } + + if (priv->acc) { + acc = location_accuracy_copy (priv->acc); + } + else { + acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + } + + LOCATION_LOGD("POSITION SERVICE_UPDATED"); + g_signal_emit(object, signals[SERVICE_UPDATED], 0, POSITION_UPDATED, pos, acc); + + location_position_free (pos); + location_accuracy_free (acc); + + return TRUE; +} + +static gboolean +_velocity_timeout_cb (gpointer data) +{ + LOCATION_LOGD("_velocity_timeout_cb"); + GObject *object = (GObject *)data; + LocationHybridPrivate *priv = GET_PRIVATE(object); + if (!priv) return FALSE; + + LocationVelocity *vel = NULL; + LocationAccuracy *acc = NULL; + + if (priv->vel) { + vel = location_velocity_copy(priv->vel); + } + else { + vel = location_velocity_new (0, 0.0, 0.0, 0.0); + } + + if (priv->acc) { + acc = location_accuracy_copy (priv->acc); + } + else { + acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + } + + LOCATION_LOGD("VELOCITY SERVICE_UPDATED"); + g_signal_emit(object, signals[SERVICE_UPDATED], 0, VELOCITY_UPDATED, vel, acc); + + location_velocity_free (vel); + location_accuracy_free (acc); + + return TRUE; +} + + +static void +location_hybrid_state_cb (keynode_t *key, gpointer self) +{ + LOCATION_LOGD("location_hybrid_state_cb"); + g_return_if_fail (key); + g_return_if_fail (self); + LocationHybridPrivate *priv = GET_PRIVATE(self); + + if (location_setting_get_key_val (key) == VCONFKEY_LOCATION_POSITION_SEARCHING) { + if (!priv->pos_timer) priv->pos_timer = g_timeout_add (priv->pos_interval * 1000, _position_timeout_cb, self); + if (!priv->vel_timer) priv->vel_timer = g_timeout_add (priv->vel_interval * 1000, _velocity_timeout_cb, self); + + } + else { + if (priv->pos_timer) g_source_remove (priv->pos_timer); + if (priv->vel_timer) g_source_remove (priv->vel_timer); + + priv->pos_timer = 0; + priv->vel_timer = 0; + } +} + +static void +hybrid_service_updated (GObject *obj, + guint type, + gpointer data, + gpointer accuracy, + gpointer self) +{ + LocationPosition *pos = NULL; + LocationVelocity *vel = NULL; + LocationSatellite *sat = NULL; + LOCATION_LOGD ("hybrid_service_updated"); + + /* To discard invalid data in a hybrid */ + switch (type) { + case POSITION_UPDATED: { + pos = (LocationPosition *)data; + if (!pos->timestamp) return; + break; + } + case VELOCITY_UPDATED: { + vel = (LocationVelocity *)data; + if (!vel->timestamp) return; + break; + } + case SATELLITE_UPDATED: { + sat = (LocationSatellite *)data; + if (!sat->timestamp) return; + break; + } + } + + LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self); + GType g_type = G_TYPE_FROM_INSTANCE(obj); + if (g_type == LOCATION_TYPE_GPS) { + if (type == SATELLITE_UPDATED) { + satellite_signaling(self, signals, &(priv->enabled), priv->sat_interval, TRUE, &(priv->sat_updated_timestamp), &(priv->sat), sat); + return ; + } + else if (location_setting_get_int (VCONFKEY_LOCATION_GPS_STATE) == VCONFKEY_LOCATION_GPS_SEARCHING) { + LOCATION_LOGD ("Searching GPS"); + return; + } + + } + else if ((g_type == LOCATION_TYPE_WPS || g_type == LOCATION_TYPE_CPS) && location_setting_get_int (VCONFKEY_LOCATION_WPS_STATE) == VCONFKEY_LOCATION_WPS_SEARCHING) { + LOCATION_LOGD ("Searching WPS or CPS"); + return; + } + + if (hybrid_compare_g_type_method(priv, g_type)) { + LocationAccuracy *acc = (LocationAccuracy*)accuracy; + if (type == POSITION_UPDATED) { + position_signaling(self, signals, &(priv->enabled), priv->pos_interval, TRUE, &(priv->pos_updated_timestamp), &(priv->pos), &(priv->acc), priv->boundary_list, pos, acc); + LOCATION_LOGW("Position updated. timestamp [%d]", priv->pos->timestamp); + } else if (type == VELOCITY_UPDATED) { + velocity_signaling(self, signals, &(priv->enabled), priv->vel_interval, TRUE, &(priv->vel_updated_timestamp), &(priv->vel), vel, acc); + LOCATION_LOGW("Velocity updated. timestamp [%d]", priv->vel->timestamp); + } + + } else if (type == POSITION_UPDATED && priv->pos) { + if (pos->timestamp - priv->pos->timestamp > HYBRID_POSITION_EXPIRATION_TIME) { + hybrid_set_current_method(priv, g_type); + } + } +} + +static void +hybrid_service_enabled (GObject *obj, + guint status, + gpointer self) +{ + LOCATION_LOGD ("hybrid_service_enabled"); + LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self); + GType g_type = G_TYPE_FROM_INSTANCE(obj); + if(g_type == LOCATION_TYPE_GPS) priv->gps_enabled = TRUE; + else if(g_type == LOCATION_TYPE_WPS) priv->wps_enabled = TRUE; + else { + LOCATION_LOGW("Undefined GType enabled"); + return; + } + hybrid_get_update_method(priv); + if(priv->gps_enabled || priv->wps_enabled) + enable_signaling(self, signals, &(priv->enabled), TRUE, status); + +} + +static void +hybrid_service_disabled (GObject *obj, + guint status, + gpointer self) +{ + LOCATION_LOGD ("hybrid_service_disabled"); + LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self); + GType g_type = G_TYPE_FROM_INSTANCE(obj); + if(g_type == LOCATION_TYPE_GPS) priv->gps_enabled = FALSE; + else if(g_type == LOCATION_TYPE_WPS) priv->wps_enabled = FALSE; + else { + LOCATION_LOGW("Undefined GType disabled"); + return; + } + hybrid_get_update_method(priv); + if(!priv->gps_enabled && !priv->wps_enabled) + enable_signaling(self, signals, &(priv->enabled), FALSE, status); + +} + +static int +location_hybrid_start (LocationHybrid *self) +{ + LOCATION_LOGD("location_hybrid_start"); + + int ret_gps = LOCATION_ERROR_NONE; + int ret_wps = LOCATION_ERROR_NONE; + + LocationHybridPrivate* priv = GET_PRIVATE(self); + if (priv->is_started == TRUE) + return LOCATION_ERROR_NONE; + + if(priv->gps) ret_gps = location_start(priv->gps); + if(priv->wps) ret_wps = location_start(priv->wps); + + if (ret_gps != LOCATION_ERROR_NONE && + ret_wps != LOCATION_ERROR_NONE) { + if (ret_gps == LOCATION_ERROR_SECURITY_DENIED || + ret_wps == LOCATION_ERROR_SECURITY_DENIED) { + return LOCATION_ERROR_SECURITY_DENIED; + } else if (ret_gps == LOCATION_ERROR_SETTING_OFF && ret_wps == LOCATION_ERROR_SETTING_OFF) { + return LOCATION_ERROR_SETTING_OFF; + } else { + return LOCATION_ERROR_NOT_AVAILABLE; + } + } + + priv->is_started = TRUE; + + if (priv->set_noti == FALSE) { + location_setting_add_notify (VCONFKEY_LOCATION_POSITION_STATE, location_hybrid_state_cb, self); + priv->set_noti = TRUE; + } + + + return LOCATION_ERROR_NONE; +} + +static int +location_hybrid_stop (LocationHybrid *self) +{ + LOCATION_LOGD("location_hybrid_stop"); + + LocationHybridPrivate* priv = GET_PRIVATE(self); + if( priv->is_started == FALSE) + return LOCATION_ERROR_NONE; + + int ret_gps = LOCATION_ERROR_NONE; + int ret_wps = LOCATION_ERROR_NONE; + + if(priv->gps) ret_gps = location_stop(priv->gps); + if(priv->wps) ret_wps = location_stop(priv->wps); + + priv->is_started = FALSE; + + if (ret_gps != LOCATION_ERROR_NONE && + ret_wps != LOCATION_ERROR_NONE) + return LOCATION_ERROR_NOT_AVAILABLE; + + if (priv->pos_timer) g_source_remove (priv->pos_timer); + if (priv->vel_timer) g_source_remove (priv->vel_timer); + priv->pos_timer = 0; + priv->vel_timer = 0; + + if (priv->set_noti == TRUE) { + location_setting_ignore_notify (VCONFKEY_LOCATION_POSITION_STATE, location_hybrid_state_cb); + priv->set_noti = FALSE; + } + + return LOCATION_ERROR_NONE; +} + +static void +location_hybrid_dispose (GObject *gobject) +{ + LOCATION_LOGD("location_hybrid_dispose"); + LocationHybridPrivate *priv = GET_PRIVATE(gobject); + + if (priv->pos_timer) g_source_remove (priv->pos_timer); + if (priv->vel_timer) g_source_remove (priv->vel_timer); + priv->pos_timer = 0; + priv->vel_timer = 0; + + if (priv->set_noti == TRUE) { + location_setting_ignore_notify (VCONFKEY_LOCATION_POSITION_STATE, location_hybrid_state_cb); + priv->set_noti = FALSE; + } + + G_OBJECT_CLASS (location_hybrid_parent_class)->dispose (gobject); +} + +static void +location_hybrid_finalize (GObject *gobject) +{ + LOCATION_LOGD("location_hybrid_finalize"); + LocationHybridPrivate* priv = GET_PRIVATE(gobject); + + if (priv->gps) { + g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_enabled), gobject); + g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_disabled), gobject); + g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_updated), gobject); + location_free(priv->gps); + } + if (priv->wps) { + g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_enabled), gobject); + g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_disabled), gobject); + g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_updated), gobject); + location_free(priv->wps); + } + + if (priv->boundary_list) { + g_list_free_full(priv->boundary_list, free_boundary_list); + priv->boundary_list = NULL; + } + + if (priv->pos) { + location_position_free(priv->pos); + priv->pos = NULL; + } + + if (priv->vel) { + location_velocity_free(priv->vel); + priv->vel = NULL; + } + + if (priv->acc) { + location_accuracy_free(priv->acc); + priv->acc = NULL; + } + + if (priv->sat) { + location_satellite_free(priv->sat); + priv->sat = NULL; + } + + G_OBJECT_CLASS (location_hybrid_parent_class)->finalize (gobject); +} + +static void +location_hybrid_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + LocationHybridPrivate* priv = GET_PRIVATE(object); + if (!priv->gps && !priv->wps) { + LOCATION_LOGW("Set property is not available now"); + return; + } + + int ret = 0; + switch (property_id){ + case PROP_BOUNDARY:{ + GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value)); + ret = set_prop_boundary(&priv->boundary_list, boundary_list); + if(ret != 0) LOCATION_LOGD("Set boundary. Error[%d]", ret); + break; + } + case PROP_REMOVAL_BOUNDARY: { + LocationBoundary *req_boundary = (LocationBoundary*) g_value_dup_boxed(value); + ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary); + if(ret != 0) LOCATION_LOGD("Removal boundary. Error[%d]", ret); + break; + } + case PROP_POS_INTERVAL: { + guint interval = g_value_get_uint(value); + if(interval > 0) { + if(interval < LOCATION_UPDATE_INTERVAL_MAX) + priv->pos_interval = interval; + else + priv->pos_interval = (guint) LOCATION_UPDATE_INTERVAL_MAX; + + } + else + priv->pos_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + + if (priv->pos_timer) { + g_source_remove (priv->pos_timer); + priv->pos_timer = g_timeout_add (priv->pos_interval * 1000, _position_timeout_cb, object); + } + + break; + } + case PROP_VEL_INTERVAL: { + guint interval = g_value_get_uint(value); + if(interval > 0) { + if(interval < LOCATION_UPDATE_INTERVAL_MAX) + priv->vel_interval = interval; + else + priv->vel_interval = (guint) LOCATION_UPDATE_INTERVAL_MAX; + + } + else + priv->vel_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + + if (priv->vel_timer) { + g_source_remove (priv->vel_timer); + priv->vel_timer = g_timeout_add (priv->vel_interval * 1000, _velocity_timeout_cb, object); + } + + break; + } + case PROP_SAT_INTERVAL: { + guint interval = g_value_get_uint(value); + if(interval > 0) { + if(interval < LOCATION_UPDATE_INTERVAL_MAX) + priv->sat_interval = interval; + else + priv->sat_interval = (guint) LOCATION_UPDATE_INTERVAL_MAX; + + } + else + priv->sat_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +location_hybrid_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + LocationHybridPrivate *priv = GET_PRIVATE (object); + if(!priv->gps && !priv->wps){ + LOCATION_LOGW("Get property is not available now"); + return; + } + + LOCATION_LOGW("Get Propery ID[%d]", property_id); + + switch (property_id){ + case PROP_METHOD_TYPE: + g_value_set_int(value, hybrid_get_current_method (priv)); + break; + case PROP_LAST_POSITION: + g_value_set_boxed(value, priv->pos); + break; + case PROP_BOUNDARY: + g_value_set_pointer(value, g_list_first(priv->boundary_list)); + break; + case PROP_POS_INTERVAL: + g_value_set_uint(value, priv->pos_interval); + break; + case PROP_VEL_INTERVAL: + g_value_set_uint(value, priv->vel_interval); + break; + case PROP_SAT_INTERVAL: + g_value_set_uint(value, priv->sat_interval); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static int +location_hybrid_get_position (LocationHybrid *self, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + int ret = LOCATION_ERROR_NOT_AVAILABLE; + LOCATION_LOGD("location_hybrid_get_position"); + if (!location_setting_get_int(VCONFKEY_LOCATION_ENABLED) && !location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED)) { + return LOCATION_ERROR_SETTING_OFF; + } + + LocationHybridPrivate *priv = GET_PRIVATE (self); + + if (priv->pos) { + *position = location_position_copy (priv->pos); + ret = LOCATION_ERROR_NONE; + } + + if (priv->acc) { + *accuracy = location_accuracy_copy (priv->acc); + } + + return ret; +} + +static int +location_hybrid_get_position_ext (LocationHybrid *self, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_hybrid_get_position_ext"); + if (!location_setting_get_int(VCONFKEY_LOCATION_ENABLED) && !location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED)) { + return LOCATION_ERROR_SETTING_OFF; + } + + LocationHybridPrivate *priv = GET_PRIVATE (self); + + if (priv->pos && priv->vel) { + *position = location_position_copy (priv->pos); + *velocity = location_velocity_copy (priv->vel); + } + else { + LOCATION_LOGE("There is invalid data."); + return LOCATION_ERROR_NOT_AVAILABLE; + } + + if (priv->acc) { + *accuracy = location_accuracy_copy (priv->acc); + } + else { + *accuracy = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + } + + return LOCATION_ERROR_NONE; +} + + +static int +location_hybrid_get_last_position (LocationHybrid *self, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_hybrid_get_last_position"); + + int ret = LOCATION_ERROR_NONE; + LocationPosition *gps_pos = NULL, *wps_pos = NULL; + LocationAccuracy *gps_acc = NULL, *wps_acc = NULL; + LocationHybridPrivate *priv = GET_PRIVATE (self); + + if (priv->gps) location_get_last_position (priv->gps, &gps_pos, &gps_acc); + if (priv->wps) location_get_last_position (priv->wps, &wps_pos, &wps_acc); + + if (gps_pos && wps_pos) { + if (wps_pos->timestamp > gps_pos->timestamp) { + *position = wps_pos; + *accuracy = wps_acc; + location_position_free (gps_pos); + location_accuracy_free (gps_acc); + } + else { + *position = gps_pos; + *accuracy = gps_acc; + location_position_free (wps_pos); + location_accuracy_free (wps_acc); + } + } else if (gps_pos) { + *position = gps_pos; + *accuracy = gps_acc; + } else if (wps_pos) { + *position = wps_pos; + *accuracy = wps_acc; + } else { + ret = LOCATION_ERROR_NOT_AVAILABLE; + } + + return ret; +} + +static int +location_hybrid_get_last_position_ext (LocationHybrid *self, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_hybrid_get_last_position_ext"); + + int ret = LOCATION_ERROR_NONE; + LocationPosition *gps_pos = NULL, *wps_pos = NULL; + LocationVelocity *gps_vel = NULL, *wps_vel = NULL; + LocationAccuracy *gps_acc = NULL, *wps_acc = NULL; + LocationHybridPrivate *priv = GET_PRIVATE (self); + + if (priv->gps) location_get_last_position_ext (priv->gps, &gps_pos, &gps_vel, &gps_acc); + if (priv->wps) location_get_last_position_ext (priv->wps, &wps_pos, &wps_vel, &wps_acc); + + if (gps_pos && wps_pos && gps_vel && wps_vel) { + if (wps_pos->timestamp > gps_pos->timestamp) { + *position = wps_pos; + *velocity = wps_vel; + *accuracy = wps_acc; + location_position_free (gps_pos); + location_velocity_free (gps_vel); + location_accuracy_free (gps_acc); + } + else { + *position = gps_pos; + *velocity = gps_vel; + *accuracy = gps_acc; + location_position_free (wps_pos); + location_velocity_free (wps_vel); + location_accuracy_free (wps_acc); + } + } else if (gps_pos && gps_vel) { + *position = gps_pos; + *velocity = gps_vel; + *accuracy = gps_acc; + } else if (wps_pos && wps_vel) { + *position = wps_pos; + *velocity = wps_vel; + *accuracy = wps_acc; + } else { + ret = LOCATION_ERROR_NOT_AVAILABLE; + } + + return ret; +} + + +static int +location_hybrid_get_velocity (LocationHybrid *self, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + int ret = LOCATION_ERROR_NOT_AVAILABLE; + LOCATION_LOGD("location_hybrid_get_velocity"); + if (!location_setting_get_int(VCONFKEY_LOCATION_ENABLED) && !location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED)) { + return LOCATION_ERROR_SETTING_OFF; + } + + LocationHybridPrivate *priv = GET_PRIVATE (self); + + if (priv->vel) { + *velocity = location_velocity_copy (priv->vel); + ret = LOCATION_ERROR_NONE; + } + + if (priv->acc) { + *accuracy = location_accuracy_copy (priv->acc); + } + + return ret; +} + +static int +location_hybrid_get_last_velocity (LocationHybrid *self, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_hybrid_get_last_velocity"); + + int ret = LOCATION_ERROR_NONE; + LocationHybridPrivate *priv = GET_PRIVATE (self); + LocationVelocity *gps_vel = NULL, *wps_vel = NULL; + LocationAccuracy *gps_acc = NULL, *wps_acc = NULL; + + if (priv->gps) location_get_last_velocity (priv->gps, &gps_vel, &gps_acc); + if (priv->wps) location_get_last_velocity (priv->wps, &wps_vel, &wps_acc); + + if (gps_vel && wps_vel) { + if (wps_vel->timestamp > gps_vel->timestamp) { + *velocity = wps_vel; + *accuracy = wps_acc; + location_velocity_free (gps_vel); + location_accuracy_free (gps_acc); + } else { + *velocity = gps_vel; + *accuracy = gps_acc; + location_velocity_free (wps_vel); + location_accuracy_free (wps_acc); + } + } + else if (gps_vel) { + *velocity = gps_vel; + *accuracy = gps_acc; + } else if (wps_vel) { + *velocity = wps_vel; + *accuracy = wps_acc; + } else { + *velocity = NULL; + *accuracy = NULL; + ret = LOCATION_ERROR_NOT_AVAILABLE; + } + + return ret; +} + +static int +location_hybrid_get_satellite (LocationHybrid *self, + LocationSatellite **satellite) +{ + int ret = LOCATION_ERROR_NOT_AVAILABLE; + LOCATION_LOGD("location_hybrid_get_satellite"); + if (!location_setting_get_int(VCONFKEY_LOCATION_ENABLED) && !location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED)) { + return LOCATION_ERROR_SETTING_OFF; + } + + LocationHybridPrivate *priv = GET_PRIVATE (self); + if (priv->sat) { + *satellite = location_satellite_copy (priv->sat); + ret = LOCATION_ERROR_NONE; + } + + return ret; +} + +static int +location_hybrid_get_last_satellite (LocationHybrid *self, + LocationSatellite **satellite) +{ + LOCATION_LOGD("location_hybrid_get_last_satellite"); + + int ret = LOCATION_ERROR_NONE; + LocationHybridPrivate *priv = GET_PRIVATE (self); + + if (priv->gps) ret = location_get_last_satellite (priv->gps, satellite); + else { + *satellite = NULL; + ret = LOCATION_ERROR_NOT_AVAILABLE; + } + + return ret; +} + +static void +location_ielement_interface_init (LocationIElementInterface *iface) +{ + iface->start = (TYPE_START_FUNC)location_hybrid_start; + iface->stop = (TYPE_STOP_FUNC)location_hybrid_stop; + iface->get_position = (TYPE_GET_POSITION)location_hybrid_get_position; + iface->get_position_ext = (TYPE_GET_POSITION_EXT)location_hybrid_get_position_ext; + iface->get_last_position = (TYPE_GET_POSITION)location_hybrid_get_last_position; + iface->get_last_position_ext = (TYPE_GET_POSITION_EXT)location_hybrid_get_last_position_ext; + iface->get_velocity = (TYPE_GET_VELOCITY)location_hybrid_get_velocity; + iface->get_last_velocity = (TYPE_GET_VELOCITY)location_hybrid_get_last_velocity; + iface->get_satellite = (TYPE_GET_SATELLITE)location_hybrid_get_satellite; + iface->get_last_satellite = (TYPE_GET_SATELLITE)location_hybrid_get_last_satellite; +} + +static void +location_hybrid_init (LocationHybrid *self) +{ + LOCATION_LOGD("location_hybrid_init"); + LocationHybridPrivate* priv = GET_PRIVATE(self); + + priv->is_started = FALSE; + priv->pos_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + priv->vel_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + priv->sat_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + + priv->pos_updated_timestamp = 0; + priv->vel_updated_timestamp = 0; + priv->sat_updated_timestamp = 0; + + priv->gps_enabled = FALSE; + priv->wps_enabled = FALSE; + + priv->gps = NULL; + priv->wps = NULL; + + priv->set_noti = FALSE; + + priv->pos_timer = 0; + priv->vel_timer = 0; + + if(location_is_supported_method(LOCATION_METHOD_GPS)) priv->gps = location_new (LOCATION_METHOD_GPS); + if(location_is_supported_method(LOCATION_METHOD_WPS)) priv->wps = location_new (LOCATION_METHOD_WPS); + + if(priv->gps){ + g_signal_connect (priv->gps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self); + g_signal_connect (priv->gps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self); + g_signal_connect (priv->gps, "service-updated", G_CALLBACK(hybrid_service_updated), self); + } + if(priv->wps){ + g_signal_connect (priv->wps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self); + g_signal_connect (priv->wps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self); + g_signal_connect (priv->wps, "service-updated", G_CALLBACK(hybrid_service_updated), self); + } + + hybrid_set_current_method (priv, LOCATION_TYPE_HYBRID); + priv->enabled= FALSE; + + priv->pos = NULL; + priv->vel = NULL; + priv->acc = NULL; + priv->sat = NULL; + + priv->boundary_list = NULL; +} + +static void +location_hybrid_class_init (LocationHybridClass *klass) +{ + LOCATION_LOGD("location_hybrid_class_init"); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = location_hybrid_set_property; + gobject_class->get_property = location_hybrid_get_property; + + gobject_class->dispose = location_hybrid_dispose; + gobject_class->finalize = location_hybrid_finalize; + + g_type_class_add_private (klass, sizeof (LocationHybridPrivate)); + + signals[SERVICE_ENABLED] = g_signal_new ("service-enabled", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationHybridClass, enabled), + NULL, NULL, + location_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[SERVICE_DISABLED] = g_signal_new ("service-disabled", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationHybridClass, disabled), + NULL, NULL, + location_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[SERVICE_UPDATED] = g_signal_new ("service-updated", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationHybridClass, updated), + NULL, NULL, + location_VOID__UINT_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_UINT, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[ZONE_IN] = g_signal_new ("zone-in", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationHybridClass, zone_in), + NULL, NULL, + location_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_POINTER, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[ZONE_OUT] = g_signal_new ("zone-out", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationHybridClass, zone_out), + NULL, NULL, + location_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_POINTER, + G_TYPE_POINTER, + G_TYPE_POINTER); + + properties[PROP_METHOD_TYPE] = g_param_spec_int ("method", + "method type", + "location method type name", + LOCATION_METHOD_HYBRID, + LOCATION_METHOD_HYBRID, + LOCATION_METHOD_HYBRID, + G_PARAM_READABLE); + + properties[PROP_LAST_POSITION] = g_param_spec_boxed ("last-position", + "hybrid last position prop", + "hybrid last position data", + LOCATION_TYPE_POSITION, + G_PARAM_READABLE); + + properties[PROP_POS_INTERVAL] = g_param_spec_uint ("pos-interval", + "position interval prop", + "position interval data", + LOCATION_UPDATE_INTERVAL_MIN, + LOCATION_UPDATE_INTERVAL_MAX, + LOCATION_UPDATE_INTERVAL_DEFAULT, + G_PARAM_READWRITE); + properties[PROP_VEL_INTERVAL] = g_param_spec_uint ("vel-interval", + "velocity interval prop", + "velocity interval data", + LOCATION_UPDATE_INTERVAL_MIN, + LOCATION_UPDATE_INTERVAL_MAX, + LOCATION_UPDATE_INTERVAL_DEFAULT, + G_PARAM_READWRITE); + properties[PROP_SAT_INTERVAL] = g_param_spec_uint ("sat-interval", + "satellite interval prop", + "satellite interval data", + LOCATION_UPDATE_INTERVAL_MIN, + LOCATION_UPDATE_INTERVAL_MAX, + LOCATION_UPDATE_INTERVAL_DEFAULT, + G_PARAM_READWRITE); + + properties[PROP_BOUNDARY] = g_param_spec_pointer ("boundary", + "hybrid boundary prop", + "hybrid boundary data", + G_PARAM_READWRITE); + + properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary", + "hybrid removal boundary prop", + "hybrid removal boundary data", + LOCATION_TYPE_BOUNDARY, + G_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, + PROP_MAX, + properties); + +} diff --git a/location/manager/location-hybrid.h b/location/manager/location-hybrid.h new file mode 100644 index 0000000..5a3e40e --- /dev/null +++ b/location/manager/location-hybrid.h @@ -0,0 +1,66 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_HYBRID_H__ +#define __LOCATION_HYBRID_H__ + +#include + +/** + * @file location-hybrid.h + * @brief This file contains the internal definitions and structures related to Hybrid method. + */ + +G_BEGIN_DECLS + +typedef struct _LocationHybrid LocationHybrid; +typedef struct _LocationHybridClass LocationHybridClass; + +#define LOCATION_TYPE_HYBRID (location_hybrid_get_type ()) +#define LOCATION_HYBRID(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOCATION_TYPE_HYBRID, LocationHybrid)) +#define LOCATION_IS_HYBRID(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LOCATION_TYPE_HYBRID)) +#define LOCATION_HYBRID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LOCATION_TYPE_HYBRID, LocationHybridClass)) +#define LOCATION_IS_HYBRID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LOCATION_TYPE_HYBRID)) +#define LOCATION_HYBRID_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LOCATION_TYPE_HYBRID, LocationHybridClass)) + +struct _LocationHybrid +{ + GObject parent_instance; +}; + +struct _LocationHybridClass +{ + GObjectClass parent_class; + + void (* enabled) (guint type); + void (* disabled) (guint type); + void (* updated) (guint type, gpointer data, gpointer accuracy); + void (* zone_in) (gpointer boundary, gpointer position, gpointer accuracy); + void (* zone_out) (gpointer boundary, gpointer position, gpointer accuracy); +}; + +GType location_hybrid_get_type (void); + +#define HYBRID_POSITION_EXPIRATION_TIME 9 + +G_END_DECLS + +#endif diff --git a/location/manager/location-ielement.c b/location/manager/location-ielement.c new file mode 100644 index 0000000..3be96bd --- /dev/null +++ b/location/manager/location-ielement.c @@ -0,0 +1,177 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-log.h" +#include "location-ielement.h" + +static void +location_ielement_base_init (gpointer g_class) +{ + static gboolean is_initialized = FALSE; + + if (is_initialized){ + /* add properties and signals to the interface here */ + + is_initialized = TRUE; + } +} + +GType +location_ielement_get_type (void) +{ + static GType iface_type = 0; + + if (iface_type == 0) { + static const GTypeInfo info = { + sizeof (LocationIElementInterface), + location_ielement_base_init, /* base_init */ + NULL /* base_finalize */ + }; + + iface_type = g_type_register_static (G_TYPE_INTERFACE, "LocationIElement", + &info, 0); + } + + return iface_type; +} + +int +location_ielement_start (LocationIElement *self) +{ + g_return_val_if_fail (LOCATION_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_IELEMENT_GET_INTERFACE (self)->start, LOCATION_ERROR_NOT_AVAILABLE); + return LOCATION_IELEMENT_GET_INTERFACE (self)->start (self); +} + +int +location_ielement_stop (LocationIElement *self) +{ + g_return_val_if_fail (LOCATION_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_IELEMENT_GET_INTERFACE (self)->stop, LOCATION_ERROR_NOT_AVAILABLE); + return LOCATION_IELEMENT_GET_INTERFACE (self)->stop (self); +} + +int +location_ielement_get_position (LocationIElement *self, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (LOCATION_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (accuracy, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_IELEMENT_GET_INTERFACE (self)->get_position, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_IELEMENT_GET_INTERFACE (self)->get_position (self, position, accuracy); +} + +int +location_ielement_get_position_ext (LocationIElement *self, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (LOCATION_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (velocity, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (accuracy, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_IELEMENT_GET_INTERFACE (self)->get_position_ext, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_IELEMENT_GET_INTERFACE (self)->get_position_ext (self, position, velocity, accuracy); +} + + +int +location_ielement_get_last_position (LocationIElement *self, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (LOCATION_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (accuracy, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_IELEMENT_GET_INTERFACE (self)->get_last_position, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_IELEMENT_GET_INTERFACE (self)->get_last_position (self, position, accuracy); +} + +int +location_ielement_get_last_position_ext (LocationIElement *self, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (LOCATION_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (velocity, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (accuracy, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_IELEMENT_GET_INTERFACE (self)->get_last_position_ext, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_IELEMENT_GET_INTERFACE (self)->get_last_position_ext (self, position, velocity, accuracy); +} + + +int +location_ielement_get_satellite (LocationIElement *self, + LocationSatellite **satellite) +{ + g_return_val_if_fail (LOCATION_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (satellite, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_IELEMENT_GET_INTERFACE (self)->get_satellite, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_IELEMENT_GET_INTERFACE (self)->get_satellite (self, satellite); +} + +int +location_ielement_get_last_satellite (LocationIElement *self, + LocationSatellite **satellite) +{ + g_return_val_if_fail (LOCATION_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (satellite, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_IELEMENT_GET_INTERFACE (self)->get_last_satellite, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_IELEMENT_GET_INTERFACE (self)->get_last_satellite (self, satellite); +} + + +int +location_ielement_get_velocity (LocationIElement *self, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (LOCATION_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (velocity, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_IELEMENT_GET_INTERFACE (self)->get_velocity, LOCATION_ERROR_NOT_AVAILABLE); + return LOCATION_IELEMENT_GET_INTERFACE (self)->get_velocity (self, velocity, accuracy); +} + +int +location_ielement_get_last_velocity (LocationIElement *self, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (LOCATION_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (velocity, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_IELEMENT_GET_INTERFACE (self)->get_last_velocity, LOCATION_ERROR_NOT_AVAILABLE); + return LOCATION_IELEMENT_GET_INTERFACE (self)->get_last_velocity (self, velocity, accuracy); +} diff --git a/location/manager/location-ielement.h b/location/manager/location-ielement.h new file mode 100644 index 0000000..c9a95b8 --- /dev/null +++ b/location/manager/location-ielement.h @@ -0,0 +1,94 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_IELEMENT_H__ +#define __LOCATION_IELEMENT_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @file location-ielement.h + * @brief This file contains the internal definitions and structures related to location interface. + */ + +G_BEGIN_DECLS + +enum { + SERVICE_ENABLED, + SERVICE_DISABLED, + SERVICE_UPDATED, + ZONE_IN, + ZONE_OUT, + LAST_SIGNAL +}; + +#define LOCATION_TYPE_IELEMENT (location_ielement_get_type ()) +#define LOCATION_IELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOCATION_TYPE_IELEMENT, LocationIElement)) +#define LOCATION_IS_IELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LOCATION_TYPE_IELEMENT)) +#define LOCATION_IELEMENT_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), LOCATION_TYPE_IELEMENT, LocationIElementInterface)) + +typedef struct _LocationIElement LocationIElement; +typedef struct _LocationIElementInterface LocationIElementInterface; + +typedef int (*TYPE_START_FUNC)(LocationIElement *self); +typedef int (*TYPE_STOP_FUNC) (LocationIElement *self); +typedef int (*TYPE_GET_POSITION)(LocationIElement *self, LocationPosition **position, LocationAccuracy **accuracy); +typedef int (*TYPE_GET_POSITION_EXT)(LocationIElement *self, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy); +typedef int (*TYPE_GET_VELOCITY)(LocationIElement *self, LocationVelocity **velocity, LocationAccuracy **accuracy); +typedef int (*TYPE_GET_SATELLITE)(LocationIElement *self, LocationSatellite **satellite); + +struct _LocationIElementInterface +{ + GTypeInterface parent_iface; + + TYPE_START_FUNC start; + TYPE_STOP_FUNC stop; + TYPE_GET_POSITION get_position; + TYPE_GET_POSITION_EXT get_position_ext; + TYPE_GET_POSITION get_last_position; + TYPE_GET_POSITION_EXT get_last_position_ext; + TYPE_GET_VELOCITY get_velocity; + TYPE_GET_VELOCITY get_last_velocity; + TYPE_GET_SATELLITE get_satellite; + TYPE_GET_SATELLITE get_last_satellite; +}; + +GType location_ielement_get_type (void); + +int location_ielement_start (LocationIElement *self); +int location_ielement_stop(LocationIElement *self); +int location_ielement_get_position (LocationIElement *self, LocationPosition **position, LocationAccuracy **accuracy); +int location_ielement_get_last_position (LocationIElement *self, LocationPosition **position, LocationAccuracy **accuracy); +int location_ielement_get_velocity (LocationIElement *self, LocationVelocity **velocity, LocationAccuracy **accuracy); +int location_ielement_get_last_velocity (LocationIElement *self, LocationVelocity **velocity, LocationAccuracy **accuracy); +int location_ielement_get_satellite (LocationIElement *self, LocationSatellite **satellite); +int location_ielement_get_last_satellite (LocationIElement *self, LocationSatellite **satellite); + +G_END_DECLS + +#endif diff --git a/location/manager/location-marshal.list b/location/manager/location-marshal.list new file mode 100644 index 0000000..8acae65 --- /dev/null +++ b/location/manager/location-marshal.list @@ -0,0 +1,3 @@ +VOID:POINTER,POINTER,POINTER +VOID:UINT,POINTER,POINTER +VOID:UINT diff --git a/location/manager/location-position.c b/location/manager/location-position.c new file mode 100644 index 0000000..1bf57e0 --- /dev/null +++ b/location/manager/location-position.c @@ -0,0 +1,202 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "location-position.h" +#include "location-setting.h" +#include "location-log.h" + +#define DEG2RAD(x) ((x) * M_PI / 180) + +GType +location_position_get_type (void) +{ + static volatile gsize type_volatile = 0; + if(g_once_init_enter(&type_volatile)) { + GType type = g_boxed_type_register_static ( + g_intern_static_string ("LocationPosition"), + (GBoxedCopyFunc) location_position_copy, + (GBoxedFreeFunc) location_position_free); + g_once_init_leave(&type_volatile, type); + } + return type_volatile; +} + +EXPORT_API LocationPosition * +location_position_new (guint timestamp, + gdouble latitude, + gdouble longitude, + gdouble altitude, + LocationStatus status) +{ + if (latitude < -90 || latitude > 90) return NULL; + if (longitude < -180 || longitude > 180) return NULL; + + LocationPosition* position = g_slice_new0(LocationPosition); + position->timestamp = timestamp; + position->latitude = latitude; + position->longitude = longitude; + position->altitude = altitude; + position->status = status; + return position; +} + +EXPORT_API void +location_position_free (LocationPosition* position) +{ + g_return_if_fail(position); + g_slice_free(LocationPosition, position); +} + +EXPORT_API gboolean +location_position_equal (const LocationPosition *position1, const LocationPosition *position2) +{ + g_return_val_if_fail(position1, FALSE); + g_return_val_if_fail(position2, FALSE); + + if (position1->latitude == position2->latitude && + position1->longitude == position2->longitude && + position1->altitude == position2->altitude) + return TRUE; + return FALSE; +} + +EXPORT_API LocationPosition* +location_position_copy (const LocationPosition *position) +{ + g_return_val_if_fail(position, NULL); + + LocationPosition *new_position = NULL; + + new_position = location_position_new (position->timestamp, + position->latitude, + position->longitude, + position->altitude, + position->status); + + return new_position; + +} + +/* Vincenty formula. WGS-84 */ +EXPORT_API int +location_get_distance(const LocationPosition *pos1, const LocationPosition *pos2, gulong *distance) +{ + g_return_val_if_fail(pos1, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail(pos2, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail(distance, LOCATION_ERROR_PARAMETER); + + *distance = 0; + + const double a = 6378137.0, b = 6356752.314245, f = 1/298.257223563; + double delta_lon = DEG2RAD(pos2->longitude-pos1->longitude); + double u_1 = atan((1-f) * tan(DEG2RAD(pos1->latitude))); + double u_2 = atan((1-f) * tan(DEG2RAD(pos2->latitude))); + + double lambdaP, iter_limit = 100.0; + double lambda = delta_lon; + + double sin_sigma, sin_alpha, cos_sigma, sigma, sq_cos_alpha, cos_2sigma, C; + double sq_u, cal1, cal2, delta_sigma, cal_dist; + double sin_lambda, cos_lambda; + + double sin_u1 = sin(u_1); + double cos_u1 = cos(u_1); + double sin_u2 = sin(u_2); + double cos_u2 = cos(u_2); + + do { + sin_lambda = sin(lambda); + cos_lambda = cos(lambda); + + sin_sigma = sqrt((cos_u2*sin_lambda)*(cos_u2*sin_lambda) + \ + (cos_u1*sin_u2-sin_u1*cos_u2*cos_lambda) * \ + (cos_u1*sin_u2-sin_u1*cos_u2*cos_lambda)); + + if (sin_sigma ==0) + return LOCATION_ERROR_NONE; // co-incident points + + cos_sigma = sin_u1*sin_u2 + cos_u1*cos_u2*cos_lambda; + sigma = atan2(sin_sigma, cos_sigma); + + sin_alpha = cos_u1 * cos_u2 * sin_lambda / sin_sigma; + sq_cos_alpha = 1.0 - sin_alpha*sin_alpha; + cos_2sigma = cos_sigma - 2.0*sin_u1*sin_u2/sq_cos_alpha; + + if (isnan(cos_2sigma)) + cos_2sigma = 0; + + C = f/16.0*sq_cos_alpha*(4.0+f*(4.0-3.0*sq_cos_alpha)); + + lambdaP = lambda; + lambda = delta_lon + (1.0-C) * f * sin_alpha * \ + (sigma + C*sin_sigma*(cos_2sigma+C*cos_sigma*(-1.0+2.0*cos_2sigma*cos_2sigma))); + + } while (abs(lambda-lambdaP) > 1e-12 && --iter_limit>0); + + if (iter_limit==0) return LOCATION_ERROR_UNKNOWN; + + sq_u = sq_cos_alpha * (a*a - b*b) / (b*b); + + cal1 = 1.0 + sq_u/16384.0*(4096.0+sq_u*(-768.0+sq_u*(320.0-175.0*sq_u))); + cal2 = sq_u/1024.0 * (256.0+sq_u*(-128.0+sq_u*(74.0-47.0*sq_u))); + + delta_sigma = cal2*sin_sigma*(cos_2sigma+cal2/4.0*(cos_sigma*(-1.0+2.0*cos_2sigma*cos_2sigma)- \ + cal2/6.0*cos_2sigma*(-3.0+4.0*sin_sigma*sin_sigma)*(-3.0+4.0*cos_2sigma*cos_2sigma))); + cal_dist = b*cal1*(sigma-delta_sigma); + + *distance = (gulong) cal_dist; + + return LOCATION_ERROR_NONE; + +} + +EXPORT_API void +location_last_position_a2i(char *position, int *lat, int *lon) +{ + char *d_lat, *d_lon; + char latitude[HALF_KEY_LENGTH]; + char longitude[HALF_KEY_LENGTH]; + + memcpy(latitude, position + 1, HALF_KEY_LENGTH - 1); + memcpy(longitude, position + HALF_KEY_LENGTH + 1, HALF_KEY_LENGTH - 1); + latitude[HALF_KEY_LENGTH - 1] = '\0'; + longitude[HALF_KEY_LENGTH - 1] = '\0'; + d_lat = position; + d_lon = position + HALF_KEY_LENGTH; + + *lat = atoi(latitude); + *lon = atoi(longitude); + + if (*d_lat == 'S') { + *lat = *lat * -1; + } + if (*d_lon == 'W') { + *lon = *lon * -1; + } +} diff --git a/location/manager/location-position.h b/location/manager/location-position.h new file mode 100644 index 0000000..5ce3284 --- /dev/null +++ b/location/manager/location-position.h @@ -0,0 +1,176 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_POSITION_H_ +#define __LOCATION_POSITION_H_ + +#include + +#define MAX_KEY_LENGTH 16 +#define HALF_KEY_LENGTH 8 + +G_BEGIN_DECLS + +GType location_position_get_type (void); +#define LOCATION_TYPE_POSITION (location_position_get_type ()) + +/** + * @file location-position.h + * @brief This file contains the internal definitions and structures related to position information. + */ +/** + * @addtogroup LocationAPI + * @{ + * @defgroup LocationAPIPosition Location Position + * @breif This provides APIs related to Location Position + * @addtogroup LocationAPIPosition + * @{ + * + */ + +/** + * @brief This represents the various fix states. + */ +typedef enum +{ + LOCATION_STATUS_NO_FIX = 0, ///< No fix status. + LOCATION_STATUS_2D_FIX, ///< 2D fix status (latitude/longitude/speed/direction). + LOCATION_STATUS_3D_FIX ///< 3D fix status (altitude/climb as well). +} LocationStatus; + +/** + * @brief This represents position information such as latitude-longitude-altitude values and timestamp. + */ +struct _LocationPosition +{ + guint timestamp; ///< Time stamp. + gdouble latitude; ///< Latitude data. + gdouble longitude; ///< Longitude data. + gdouble altitude; ///< Altitude data. + LocationStatus status; ///< Fix states. +}; + +/** + * @brief This represents last known position information such as latitude-longitude values and accuracy. + */ +struct _LocationLastPosition +{ + LocationMethod method; ///< Location Method. + guint timestamp; ///< Time stamp. + gdouble latitude; ///< Latitude data. + gdouble longitude; ///< Longitude data. + gdouble altitude; ///< Altitude data. + gdouble horizontal_accuracy; ///< Horizontal accuracy data. + gdouble vertical_accuracy; ///< Vertical accuracy data. +}; + +/** + * @brief Create a new #LocationPosition with given information. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] timestamp - Time stamp. + * @param [in] latitude - Latitude data. + * @param [in] longitude - Longitude data. + * @param [in] altitude - Altitude data. + * @param [in] status - a #LocationStatus. + * @return a new #LocationPosition + * @retval NULL if error occured + */ +LocationPosition *location_position_new (guint timestamp, gdouble latitude, gdouble longitude, gdouble altitude, LocationStatus status); + +/** + * @brief Free a #LocationPosition. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] position - a #LocationPosition. + * @return None. + */ +void location_position_free (LocationPosition *position); + +/** + * @brief Compares two positions for equality, returning TRUE if they are equal. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] position1 - a #LocationPosition + * @param [in] position2 - a #LocationPosition + * @return gboolean + * @retval\n + * TRUE - if equal\n + * FALSE - if not equal\n + */ +gboolean location_position_equal (const LocationPosition *position1, const LocationPosition *position2); + +/** + * @brief Makes a copy of #LocationPosition + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] position - a #LocationPosition + * @return a new #LocationPosition + * @retval NULL if error occured + */ +LocationPosition *location_position_copy (const LocationPosition *position); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Vincenty Inverse Solution of Geodesics on the Ellipsoid (c) Chris Veness 2002-2010 */ +/* */ +/* from: Vincenty inverse formula - T Vincenty, "Direct and Inverse Solutions of Geodesics on the */ +/* Ellipsoid with application of nested equations", Survey Review, vol XXII no 176, 1975 */ +/* http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf */ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/** + * @brief Gets the approximate distance between two points. A distance is defined using the WGS84 ellipsoid. + * @remarks Uses meters as a unit of measurement for a distance. + * @pre None. + * @post None. + * @param [in] pos1 - a #LocationPosition (decimal degree) + * @param [in] pos2 - a #LocationPosition (decimal degree) + * @param [out] distance - a #gulong (meters) + * @return int + * @retval 0 Success. + * + * Please refer #LocationError for more information. + */ +int location_get_distance(const LocationPosition *pos1, const LocationPosition *pos2, gulong *distance); + +/** + * @brief Change position string to latitude and longitude integer. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] position - string of last position. + * @param [in] lat - latitude. + * @param [in] lon - longitude. + * @return None. + */ +void location_last_position_a2i(char *position, int *lat, int *lon); + +/** + * @} @} + */ + +G_END_DECLS + +#endif diff --git a/location/manager/location-satellite.c b/location/manager/location-satellite.c new file mode 100644 index 0000000..5d4bec7 --- /dev/null +++ b/location/manager/location-satellite.c @@ -0,0 +1,139 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-satellite.h" +#include "location-log.h" + +GType +location_satellite_get_type (void) +{ + static volatile gsize type_volatile = 0; + if(g_once_init_enter(&type_volatile)) { + GType type = g_boxed_type_register_static ( + g_intern_static_string ("LocationSatellite"), + (GBoxedCopyFunc) location_satellite_copy, + (GBoxedFreeFunc) location_satellite_free); + g_once_init_leave(&type_volatile, type); + } + return type_volatile; +} + +static void +update_num_of_used (LocationSatellite *satellite) +{ + g_return_if_fail(satellite); + satellite->num_of_sat_used = 0; + if (satellite->num_of_sat_inview > 0 && satellite->sat_inview) { + int i = 0; + for (i = 0 ; i < satellite->num_of_sat_inview ; i++) + if(satellite->sat_inview[i].used) (satellite->num_of_sat_used)++; + } +} + +EXPORT_API LocationSatellite* +location_satellite_new (int num_of_sat_inview) +{ + LocationSatellite* satellite = g_slice_new0(LocationSatellite); + satellite->num_of_sat_inview = num_of_sat_inview; + satellite->num_of_sat_used = 0; + satellite->sat_inview = g_new0(LocationSatelliteDetail, satellite->num_of_sat_inview); + return satellite; +} + +EXPORT_API void +location_satellite_free (LocationSatellite* satellite) +{ + g_return_if_fail(satellite); + g_free(satellite->sat_inview); + g_slice_free(LocationSatellite, satellite); +} + +EXPORT_API LocationSatellite* +location_satellite_copy (const LocationSatellite *satellite) +{ + g_return_val_if_fail(satellite, NULL); + LocationSatellite* satellite_dup = location_satellite_new(satellite->num_of_sat_inview); + satellite_dup->timestamp = satellite->timestamp; + satellite_dup->num_of_sat_used = satellite->num_of_sat_used; + int i = 0; + for (i = 0 ; i < satellite_dup->num_of_sat_inview ; i++) + location_satellite_set_satellite_details(satellite_dup, i, + satellite->sat_inview[i].prn, + satellite->sat_inview[i].used, + satellite->sat_inview[i].elevation, + satellite->sat_inview[i].azimuth, + satellite->sat_inview[i].snr); + return satellite_dup; +} + +EXPORT_API gboolean +location_satellite_get_satellite_details (const LocationSatellite *satellite, + guint index, + guint* prn, + gboolean* used, + guint* elevation, + guint* azimuth, + gint* snr) +{ + g_return_val_if_fail(satellite, FALSE); + g_return_val_if_fail(prn, FALSE); + g_return_val_if_fail(used, FALSE); + g_return_val_if_fail(elevation, FALSE); + g_return_val_if_fail(azimuth, FALSE); + g_return_val_if_fail(snr, FALSE); + g_return_val_if_fail(satellite->sat_inview, FALSE); + g_return_val_if_fail(index < satellite->num_of_sat_inview, FALSE); + + *prn = satellite->sat_inview[index].prn; + *used = satellite->sat_inview[index].used; + *elevation = satellite->sat_inview[index].elevation; + *azimuth = satellite->sat_inview[index].azimuth; + *snr = satellite->sat_inview[index].snr; + + return TRUE; +} + +EXPORT_API gboolean +location_satellite_set_satellite_details (LocationSatellite *satellite, + guint index, + guint prn, + gboolean used, + guint elevation, + guint azimuth, + gint snr) +{ + g_return_val_if_fail(satellite, FALSE); + g_return_val_if_fail(satellite->sat_inview, FALSE); + g_return_val_if_fail(index < satellite->num_of_sat_inview, FALSE); + + satellite->sat_inview[index].prn= prn; + satellite->sat_inview[index].used= used; + satellite->sat_inview[index].elevation= elevation; + satellite->sat_inview[index].azimuth= azimuth; + satellite->sat_inview[index].snr= snr; + update_num_of_used (satellite); + + return TRUE; +} diff --git a/location/manager/location-satellite.h b/location/manager/location-satellite.h new file mode 100644 index 0000000..33f271c --- /dev/null +++ b/location/manager/location-satellite.h @@ -0,0 +1,143 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_SATELLITE_H_ +#define __LOCATION_SATELLITE_H_ + +#include + +G_BEGIN_DECLS + +GType location_satellite_get_type (void); +#define LOCATION_TYPE_SATELLITE (location_satellite_get_type ()) + +/** + * @file location-satellite.h + * @brief This file contains the internal definitions and structures related to satellite information. + */ +/** + * @addtogroup LocationAPI + * @{ + * @defgroup LocationAPISatellite Location Satellite + * @breif This provides APIs related to Location Satellite + * @addtogroup LocationAPISatellite + * @{ + */ + +/** + * @brief This represents one satellite information in view. + */ +typedef struct { + guint prn; ///< The PRNs(Pseudo-Random Noise code) of a satellite. + gboolean used; ///< TRUE if currently used satellite. + guint elevation; ///< The elevation of a satellite. + guint azimuth; ///< The degree from true north 000 to 359 of a satellite. + gint snr; ///< The signal-to-noise ratio, dB of a satellite. +} LocationSatelliteDetail; + +/** + * @brief This represents position information such as number of satellites in used or in view. + */ +struct _LocationSatellite +{ + guint timestamp; ///< Time stamp. + guint num_of_sat_inview; ///< The number of satellites in view. + guint num_of_sat_used; ///< The number of satellites in used. + LocationSatelliteDetail* sat_inview; ///< The information of satellites in view . +}; + +/** + * @brief Create a new #LocationSatellite with given number of #LocationSatelliteDetail. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] num_of_sat_inview - number of #LocationSatelliteDetail. + * @return a new #LocationSatellite + * @retval NULL if error occured + */ +LocationSatellite *location_satellite_new (int num_of_sat_inview); + +/** + * @brief Free a #LocationSatellite. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] satellite - a #LocationSatellite. + * @return None. + */ +void location_satellite_free (LocationSatellite *satellite); + +/** + * @brief Makes a copy of #LocationSatellite + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] satellite - a #LocationSatellite + * @return a new #LocationSatellite + * @retval NULL if error occured + */ +LocationSatellite *location_satellite_copy (const LocationSatellite *satellite); + +/** + * @brief Get elements of #LocationSatelliteDetail with given index in #LocationSatellite. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] satellite - a #LocationSatellite + * @param [in] index - index of #LocationSatelliteDetail in #LocationSatellite + * @param [out] prn - The PRNs(Pseudo-Random Noise code) of a #LocationSatellite + * @param [out] used - TRUE if a #LocationSatellite in used. + * @param [out] elevation - The elevation of a #LocationSatellite + * @param [out] azimuth - The degree from true north 000 to 359 of a#LocationSatellite + * @param [out] snr - The signal-to-noise ratio, dB of #LocationSatellite + * @return gboolean + * @retval\n + * TRUE - if success\n + * FALSE - if error occured\n + */ +gboolean location_satellite_get_satellite_details (const LocationSatellite *satellite, guint index, guint *prn, gboolean *used, guint *elevation, guint *azimuth, gint *snr); + +/** + * @brief Set elements of #LocationSatelliteDetail with given index in #LocationSatellite. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] satellite - a #LocationSatellite + * @param [in] index - index of #LocationSatelliteDetail in #LocationSatellite + * @param [in] prn - The PRNs(Pseudo-Random Noise code) of a #LocationSatellite + * @param [in] used - TRUE if a #LocationSatellite in used. + * @param [in] elevation - The elevation of a #LocationSatellite + * @param [in] azimuth - The degree from true north 000 to 359 of a#LocationSatellite + * @param [in] snr - The signal-to-noise ratio, dB of #LocationSatellite + * @return gboolean + * @retval\n + * TRUE - if success\n + * FALSE - if error occured\n + */ +gboolean location_satellite_set_satellite_details( LocationSatellite *satellite, guint index, guint prn, gboolean used, guint elevation, guint azimuth, gint snr); + +/** + * @} @} + */ + +G_END_DECLS + +#endif diff --git a/location/manager/location-setting.c b/location/manager/location-setting.c new file mode 100644 index 0000000..dee52a3 --- /dev/null +++ b/location/manager/location-setting.c @@ -0,0 +1,101 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "location-log.h" +#include "location-setting.h" + + +gint location_setting_get_key_val(keynode_t *key) +{ + g_return_val_if_fail(key, -1); + int val = -1; + switch(vconf_keynode_get_type(key)) + { + case VCONF_TYPE_INT: + val = vconf_keynode_get_int(key); + LOCATION_LOGD("Setting changed [%s]:[%d]", vconf_keynode_get_name(key), val); + break; + default: + LOCATION_LOGW("Unused type(%d)", vconf_keynode_get_type(key)); + break; + } + return val; +} + +gint location_setting_get_int(const gchar* path) +{ + g_return_val_if_fail(path, -1); + int val = -1; + if( vconf_get_int(path, &val)){ + LOCATION_LOGW("vconf_get_int: failed [%s]", path); + val = -1; + } else if (val == 0) + LOCATION_LOGD("vconf_get_int: [%s]:[%d]", path, val); + return val; +} + +gboolean location_setting_get_bool(const gchar* path) +{ + g_return_val_if_fail(path, -1); + gboolean val = FALSE; + if( vconf_get_bool(path, &val)){ + LOCATION_LOGW("vconf_get_int: failed [%s]", path); + val = FALSE; + } + return val; +} + +gchar *location_setting_get_string(const gchar* path) +{ + g_return_val_if_fail(path, -1); + return vconf_get_str(path); +} + +gint location_setting_add_notify(const gchar* path, SettingCB setting_cb, gpointer self) +{ + g_return_val_if_fail(path, -1); + g_return_val_if_fail(self, -1); + + if( vconf_notify_key_changed(path, setting_cb, self)){ + LOCATION_LOGW("vconf notify add failed [%s]", path); + return -1; + } + LOCATION_LOGD("vconf notify added [%s]", path); + return 0; +} + +gint location_setting_ignore_notify(const gchar* path, SettingCB setting_cb) +{ + g_return_val_if_fail(path, -1); + g_return_val_if_fail(setting_cb, -1); + + if( vconf_ignore_key_changed(path, setting_cb)){ + LOCATION_LOGW("vconf notify remove failed [%s]", path); + return -1; + } + LOCATION_LOGD("vconf notify removed [%s]", path); + return 0; +} diff --git a/location/manager/location-setting.h b/location/manager/location-setting.h new file mode 100644 index 0000000..631df65 --- /dev/null +++ b/location/manager/location-setting.h @@ -0,0 +1,59 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_SETTING_H__ +#define __LOCATION_SETTING_H__ + +#include +#include +#include + +/** + * @file location-setting.h + * @brief This file contains the definitions and functions for setting. + */ + +#define LOCATION_UPDATE_INTERVAL_MIN 1 +#define LOCATION_UPDATE_INTERVAL_MAX 120 +#define LOCATION_UPDATE_INTERVAL_DEFAULT LOCATION_UPDATE_INTERVAL_MIN + +typedef void (*SettingCB)(keynode_t *key, gpointer data); + +gint location_setting_get_key_val(keynode_t *key); +gint location_setting_get_int(const gchar* path); +gchar *location_setting_get_string(const gchar* path); +gint location_setting_add_notify(const gchar* path, SettingCB setting_cb, gpointer self); +gint location_setting_ignore_notify(const gchar* path, SettingCB setting_cb); + +#define setting_retval_if_fail(path) {\ + if(!location_setting_get_int(path)){\ + return LOCATION_ERROR_UNKNOWN;\ + }\ +} + +#define setting_ret_if_fail(path) {\ + if(!location_setting_get_int(path)){\ + return;\ + }\ +} + + +#endif diff --git a/location/manager/location-signaling-util.c b/location/manager/location-signaling-util.c new file mode 100644 index 0000000..33ded5e --- /dev/null +++ b/location/manager/location-signaling-util.c @@ -0,0 +1,164 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-signaling-util.h" +#include "location-common-util.h" +#include "location-log.h" + +void +enable_signaling (LocationObject *obj, + guint32 signals[LAST_SIGNAL], + gboolean *prev_enabled, + gboolean enabled, + LocationStatus status) +{ + g_return_if_fail(obj); + g_return_if_fail(signals); + g_return_if_fail(prev_enabled); + if (*prev_enabled == TRUE && enabled == FALSE) { + *prev_enabled = FALSE; + LOCATION_LOGD("Signal emit: SERVICE_DISABLED"); + g_signal_emit (obj, signals[SERVICE_DISABLED], 0, LOCATION_STATUS_NO_FIX); + } else if (*prev_enabled == FALSE && enabled == TRUE){ + *prev_enabled = TRUE; + LOCATION_LOGD("Signal emit: SERVICE_ENABLED"); + g_signal_emit (obj, signals[SERVICE_ENABLED], 0, status); + } +} + +void +position_signaling (LocationObject *obj, + guint32 signals[LAST_SIGNAL], + gboolean *prev_enabled, + int interval, + gboolean emit, + guint *updated_timestamp, + LocationPosition **prev_pos, + LocationAccuracy **prev_acc, + GList *prev_bound, + const LocationPosition *pos, + const LocationAccuracy *acc) +{ + g_return_if_fail(pos); + g_return_if_fail(acc); + g_return_if_fail(obj); + g_return_if_fail(signals); + + int index = 0; + gboolean is_inside = FALSE; + GList *boundary_list = prev_bound; + LocationBoundaryPrivate *priv = NULL; + + if (!pos->timestamp) return; + + if (*prev_pos) location_position_free (*prev_pos); + if (*prev_acc) location_accuracy_free (*prev_acc); + + *prev_pos = location_position_copy(pos); + *prev_acc = location_accuracy_copy (acc); + LOCATION_LOGD("timestamp[%d], lat [%f], lon [%f]", (*prev_pos)->timestamp, (*prev_pos)->latitude, (*prev_pos)->longitude); + + if (emit && pos->timestamp - *updated_timestamp >= interval) { + LOCATION_LOGD("POSITION SERVICE_UPDATED"); + g_signal_emit(obj, signals[SERVICE_UPDATED], 0, POSITION_UPDATED, pos, acc); + *updated_timestamp = pos->timestamp; + } + + if(boundary_list) { + while((priv = (LocationBoundaryPrivate *)g_list_nth_data(boundary_list, index)) != NULL) { + is_inside = location_boundary_if_inside(priv->boundary, pos); + if(is_inside) { + if(priv->zone_status != ZONE_STATUS_IN) { + LOCATION_LOGD("Signal emit: ZONE IN"); + g_signal_emit(obj, signals[ZONE_IN], 0, priv->boundary, pos, acc); + priv->zone_status = ZONE_STATUS_IN; + } + } else { + if (priv->zone_status != ZONE_STATUS_OUT) { + LOCATION_LOGD("Signal emit : ZONE_OUT"); + g_signal_emit(obj, signals[ZONE_OUT], 0, priv->boundary, pos, acc); + priv->zone_status = ZONE_STATUS_OUT; + } + } + index++; + } + } +} + +void +velocity_signaling (LocationObject *obj, + guint32 signals[LAST_SIGNAL], + gboolean *prev_enabled, + int interval, + gboolean emit, + guint *updated_timestamp, + LocationVelocity **prev_vel, + const LocationVelocity *vel, + const LocationAccuracy *acc) +{ + g_return_if_fail(obj); + g_return_if_fail(signals); + g_return_if_fail(vel); + + if (!vel->timestamp) return; + + if (*prev_vel) location_velocity_free (*prev_vel); + + *prev_vel = location_velocity_copy (vel); + LOCATION_LOGD("timestamp[%d]", (*prev_vel)->timestamp); + + if (emit && vel->timestamp - *updated_timestamp >= interval) { + LOCATION_LOGD("VELOCITY SERVICE_UPDATED"); + g_signal_emit(obj, signals[SERVICE_UPDATED], 0, VELOCITY_UPDATED, vel, acc); + *updated_timestamp = vel->timestamp; + } +} + +void +satellite_signaling(LocationObject *obj, + guint32 signals[LAST_SIGNAL], + gboolean *prev_enabled, + int interval, + gboolean emit, + guint *updated_timestamp, + LocationSatellite **prev_sat, + const LocationSatellite *sat) +{ + g_return_if_fail(obj); + g_return_if_fail(signals); + g_return_if_fail(sat); + + if (!sat->timestamp) return; + + if (*prev_sat) location_satellite_free (*prev_sat); + *prev_sat = location_satellite_copy (sat); + + if (emit && sat->timestamp - *updated_timestamp >= interval) { + LOCATION_LOGD("SATELLITE SERVICE_UPDATED"); + g_signal_emit(obj, signals[SERVICE_UPDATED], 0, SATELLITE_UPDATED, sat, NULL); + *updated_timestamp = sat->timestamp; + } + +} diff --git a/location/manager/location-signaling-util.h b/location/manager/location-signaling-util.h new file mode 100644 index 0000000..b1f0231 --- /dev/null +++ b/location/manager/location-signaling-util.h @@ -0,0 +1,54 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_SIGNALING_UTIL_H__ +#define __LOCATION_SIGNALING_UTIL_H__ + +#include +#include + +/** + * @file location-signaling.h + * @brief This file contains the signaling utils for LocationObject. + */ + +G_BEGIN_DECLS + +void enable_signaling (LocationObject *obj, guint32 signals[LAST_SIGNAL], gboolean *prev_enabled, gboolean enabled, LocationStatus status); + +void position_signaling (LocationObject *obj, guint32 signals[LAST_SIGNAL], + gboolean *prev_enabled, int interval, gboolean emit, + guint *updated_interval, LocationPosition **prev_pos, LocationAccuracy **prev_acc, + GList *prev_bound, const LocationPosition *pos, const LocationAccuracy *acc); + +void velocity_signaling (LocationObject* obj, guint32 signals[LAST_SIGNAL], + gboolean *prev_enabled, int interval, gboolean emit, + guint *updated_timestamp, LocationVelocity **prev_vel, + const LocationVelocity *vel, const LocationAccuracy *acc); + +void satellite_signaling(LocationObject *obj, guint32 signals[LAST_SIGNAL], + gboolean *prev_enabled, int interval, gboolean emit, + guint *updated_timestamp, LocationSatellite **pre_sat, + const LocationSatellite *sat); + +G_END_DECLS + +#endif diff --git a/location/manager/location-velocity.c b/location/manager/location-velocity.c new file mode 100644 index 0000000..58af071 --- /dev/null +++ b/location/manager/location-velocity.c @@ -0,0 +1,91 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-velocity.h" +#include "location-log.h" + +GType +location_velocity_get_type (void) +{ + static volatile gsize type_volatile = 0; + if(g_once_init_enter(&type_volatile)) { + GType type = g_boxed_type_register_static ( + g_intern_static_string ("LocationVelocity"), + (GBoxedCopyFunc) location_velocity_copy, + (GBoxedFreeFunc) location_velocity_free); + g_once_init_leave(&type_volatile, type); + } + return type_volatile; +} + +EXPORT_API LocationVelocity* +location_velocity_new (guint timestamp, + gdouble speed, + gdouble direction, + gdouble climb) +{ + LocationVelocity* velocity = g_slice_new0(LocationVelocity); + velocity->timestamp = timestamp; + velocity->speed = speed; + velocity->direction = direction; + velocity->climb = climb; + return velocity; +} + +EXPORT_API void +location_velocity_free (LocationVelocity* velocity) +{ + g_return_if_fail(velocity); + g_slice_free(LocationVelocity, velocity); +} + +EXPORT_API gboolean +location_velocity_equal (const LocationVelocity *velocity1, const LocationVelocity *velocity2) +{ + g_return_val_if_fail(velocity1, FALSE); + g_return_val_if_fail(velocity2, FALSE); + + if (velocity1->timestamp == velocity2->timestamp && + velocity1->speed == velocity2->speed && + velocity1->direction == velocity2->direction && + velocity1->climb == velocity2->climb) + return TRUE; + return FALSE; +} + +EXPORT_API LocationVelocity* +location_velocity_copy (const LocationVelocity *velocity) +{ + g_return_val_if_fail(velocity, NULL); + + LocationVelocity *new_velocity = NULL; + + new_velocity = location_velocity_new(velocity->timestamp, + velocity->speed, + velocity->direction, + velocity->climb); + + return new_velocity; +} diff --git a/location/manager/location-velocity.h b/location/manager/location-velocity.h new file mode 100644 index 0000000..4955556 --- /dev/null +++ b/location/manager/location-velocity.h @@ -0,0 +1,111 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_VELOCITY_H_ +#define __LOCATION_VELOCITY_H_ + +#include + +G_BEGIN_DECLS + +GType location_velocity_get_type (void); +#define LOCATION_TYPE_VELOCITY (location_velocity_get_type ()) + +/** + * @file location-velocity.h + * @brief This file contains the internal definitions and structures related to velocity information. + */ +/** + * @addtogroup LocationAPI + * @{ + * @defgroup LocationAPIVelocity Location Velocity + * @breif This provides APIs related to Location Velocity + * @addtogroup LocationAPIVelocity + * @{ + */ + +/** + * @brief This represents velocity information such as as speed, direction, climb. + */ +struct _LocationVelocity +{ + guint timestamp; ///< Time stamp. + gdouble speed; ///< The speed over ground. (km/h) + gdouble direction; ///< The course made in degrees relative to true north. The value is always in the range [0.0, 360.0] degree. + gdouble climb; ///< The vertical speed. (km/h) +}; + +/** + * @brief Create a new #LocationVelocity with given information. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] timestamp - Time stamp. + * @param [in] speed - The speed over ground. (km/h) + * @param [in] direction - The course made in degrees relative to true north. The value is always in the range [0.0, 360.0] degree. + * @param [in] climb - The vertical speed. (km/h) + * @return a new #LocationVelocity + * @retval NULL if error occured + */ +LocationVelocity *location_velocity_new (guint timestamp, gdouble speed, gdouble direction, gdouble climb); + +/** + * @brief Free a #LocationVelocity. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] velocity - a #LocationVelocity. + * @return None. + */ +void location_velocity_free (LocationVelocity *velocity); + +/** + * @brief Compares two velocities for equality, returning TRUE if they are equal. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] velocity1 - a #LocationVelocity + * @param [in] velocity2 - a #LocationVelocity + * @return gboolean + * @retval\n + * TRUE - if equal\n + * FALSE - if not equal\n + */ +gboolean location_velocity_equal (const LocationVelocity *velocity1, const LocationVelocity *velocity2); + +/** + * @brief Makes a copy of #LocationVelocity + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] velocity - a #LocationVelocity + * @return a new #LocationVelocity + * @retval NULL if error occured + */ +LocationVelocity *location_velocity_copy (const LocationVelocity *velocity); + +/** + * @} @} + */ + +G_END_DECLS + +#endif diff --git a/location/manager/location-wps.c b/location/manager/location-wps.c new file mode 100644 index 0000000..c439fa9 --- /dev/null +++ b/location/manager/location-wps.c @@ -0,0 +1,783 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-setting.h" +#include "location-log.h" + +#include "module-internal.h" + +#include "location-wps.h" +#include "location-marshal.h" +#include "location-ielement.h" +#include "location-signaling-util.h" +#include "location-common-util.h" +/* + * forward definitions + */ + +typedef struct _LocationWpsPrivate { + LocationWpsMod* mod; + gboolean is_started; + gboolean set_noti; + gboolean enabled; + guint pos_updated_timestamp; + guint pos_interval; + guint vel_updated_timestamp; + guint vel_interval; + LocationPosition *pos; + LocationVelocity *vel; + LocationAccuracy *acc; + GList *boundary_list; + guint pos_timer; + guint vel_timer; +} LocationWpsPrivate; + +enum { + PROP_0, + PROP_METHOD_TYPE, + PROP_LAST_POSITION, + PROP_POS_INTERVAL, + PROP_VEL_INTERVAL, + PROP_BOUNDARY, + PROP_REMOVAL_BOUNDARY, + PROP_MAX +}; + +static guint32 signals[LAST_SIGNAL] = {0, }; +static GParamSpec *properties[PROP_MAX] = {NULL, }; + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOCATION_TYPE_WPS, LocationWpsPrivate)) + +static void location_ielement_interface_init (LocationIElementInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (LocationWps, location_wps, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (LOCATION_TYPE_IELEMENT, + location_ielement_interface_init)); + +static gboolean +_position_timeout_cb (gpointer data) +{ + GObject *object = (GObject *)data; + LocationWpsPrivate *priv = GET_PRIVATE(object); + if (!priv) return FALSE; + + LocationPosition *pos = NULL; + LocationAccuracy *acc = NULL; + + if (priv->pos) { + pos = location_position_copy(priv->pos); + } + else { + pos = location_position_new (0, 0.0, 0.0, 0.0, LOCATION_STATUS_NO_FIX); + } + + if (priv->acc) { + acc = location_accuracy_copy (priv->acc); + } + else { + acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + } + + LOCATION_LOGD("POSITION SERVICE_UPDATED"); + g_signal_emit(object, signals[SERVICE_UPDATED], 0, POSITION_UPDATED, pos, acc); + + location_position_free (pos); + location_accuracy_free (acc); + + return TRUE; +} + +static gboolean +_velocity_timeout_cb (gpointer data) +{ + GObject *object = (GObject *)data; + LocationWpsPrivate *priv = GET_PRIVATE(object); + if (!priv) return FALSE; + + LocationVelocity *vel = NULL; + LocationAccuracy *acc = NULL; + + if (priv->vel) { + vel = location_velocity_copy(priv->vel); + } + else { + vel = location_velocity_new (0, 0.0, 0.0, 0.0); + } + + if (priv->acc) { + acc = location_accuracy_copy (priv->acc); + } + else { + acc = location_accuracy_new (LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + } + + LOCATION_LOGD("POSITION SERVICE_UPDATED"); + g_signal_emit(object, signals[SERVICE_UPDATED], 0, VELOCITY_UPDATED, vel, acc); + + location_velocity_free (vel); + location_accuracy_free (acc); + + return TRUE; +} + +static void +__reset_pos_data_from_priv(LocationWpsPrivate *priv) +{ + LOCATION_LOGD("__reset_pos_data_from_priv"); + g_return_if_fail(priv); + + if (priv->pos) { + location_position_free(priv->pos); + priv->pos = NULL; + } + if (priv->vel) { + location_velocity_free(priv->vel); + priv->vel = NULL; + } + if (priv->acc) { + location_accuracy_free(priv->acc); + priv->acc = NULL; + } +} + +static void +wps_status_cb (gboolean enabled, + LocationStatus status, + gpointer self) +{ + LOCATION_LOGD("wps_status_cb"); + g_return_if_fail(self); + LocationWpsPrivate* priv = GET_PRIVATE(self); + enable_signaling(self, signals, &(priv->enabled), enabled, status); + if (!priv->enabled) { + if (priv->pos_timer) { + g_source_remove (priv->pos_timer); + priv->pos_timer = 0; + } + if (priv->vel_timer) { + g_source_remove (priv->vel_timer); + priv->vel_timer = 0; + } + } +} + +static void +wps_position_ext_cb (gboolean enabled, + LocationPosition *pos, + LocationVelocity *vel, + LocationAccuracy *acc, + gpointer self) +{ + LOCATION_LOGD("wps_position_ext_cb"); + g_return_if_fail(self); + g_return_if_fail(pos); + g_return_if_fail(vel); + g_return_if_fail(acc); + LocationWpsPrivate* priv = GET_PRIVATE(self); + + if (!priv->enabled && enabled) { + if (!priv->pos_timer) priv->pos_timer = g_timeout_add_seconds (priv->pos_interval, _position_timeout_cb, self); + if (!priv->vel_timer) priv->vel_timer = g_timeout_add_seconds (priv->vel_interval, _velocity_timeout_cb, self); + } + + enable_signaling(self, signals, &(priv->enabled), enabled, pos->status); + position_signaling(self, signals, &(priv->enabled), priv->pos_interval, FALSE, &(priv->pos_updated_timestamp), &(priv->pos), &(priv->acc), priv->boundary_list, pos, acc); + velocity_signaling(self, signals, &(priv->enabled), priv->vel_interval, FALSE, &(priv->vel_updated_timestamp), &(priv->vel), vel, acc); +} + +static void +location_setting_wps_cb(keynode_t *key, + gpointer self) +{ + LOCATION_LOGD("location_setting_wps_cb"); + g_return_if_fail(key); + g_return_if_fail(self); + LocationWpsPrivate* priv = GET_PRIVATE(self); + g_return_if_fail (priv->mod); + g_return_if_fail (priv->mod->handler); + + int ret = LOCATION_ERROR_NONE; + + if (location_setting_get_key_val(key) == 0) { + if (priv->mod->ops.stop && priv->is_started) { + ret = priv->mod->ops.stop(priv->mod->handler); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = FALSE; + __reset_pos_data_from_priv(priv); + } + } + } + else { + if (1 == location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED) && priv->mod->ops.start && !priv->is_started) { + LOCATION_LOGD("location resumed by setting"); + ret = priv->mod->ops.start (priv->mod->handler, wps_status_cb, wps_position_ext_cb, NULL, self); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = TRUE; + } + } + } + +} + +static int +location_wps_start (LocationWps *self) +{ + LOCATION_LOGD("location_wps_start"); + LocationWpsPrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.start, LOCATION_ERROR_NOT_AVAILABLE); + + if (priv->is_started == TRUE) return LOCATION_ERROR_NONE; + + int ret = LOCATION_ERROR_NONE; + + if (!location_setting_get_int(VCONFKEY_LOCATION_NETWORK_ENABLED)) { + ret = LOCATION_ERROR_SETTING_OFF; + } + else { + ret = priv->mod->ops.start (priv->mod->handler, wps_status_cb, wps_position_ext_cb, NULL, self); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = TRUE; + } + else { + return ret; + } + } + + if (priv->set_noti == FALSE) { + location_setting_add_notify (VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_wps_cb, self); + priv->set_noti = TRUE; + } + + return ret; +} + +static int +location_wps_stop (LocationWps *self) +{ + LOCATION_LOGD("location_wps_stop"); + LocationWpsPrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.stop, LOCATION_ERROR_NOT_AVAILABLE); + + int ret = LOCATION_ERROR_NONE; + + if (priv->is_started == TRUE) { + ret = priv->mod->ops.stop (priv->mod->handler); + if (ret == LOCATION_ERROR_NONE) { + priv->is_started = FALSE; + } + else { + LOCATION_LOGD("Failed to stop. Error[%d]", ret); + } + } + + if (priv->set_noti == TRUE) { + location_setting_ignore_notify (VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_wps_cb); + priv->set_noti = FALSE; + } + __reset_pos_data_from_priv(priv); + + return ret; +} + +static void +location_wps_dispose (GObject *gobject) +{ + LOCATION_LOGD("location_wps_dispose"); + + LocationWpsPrivate* priv = GET_PRIVATE(gobject); + if (priv->set_noti == TRUE) { + location_setting_ignore_notify (VCONFKEY_LOCATION_NETWORK_ENABLED, location_setting_wps_cb); + priv->set_noti = FALSE; + + if (priv->pos_timer) { + g_source_remove (priv->pos_timer); + priv->pos_timer = 0; + } + if (priv->vel_timer) { + g_source_remove (priv->vel_timer); + priv->vel_timer = 0; + } + + } + + G_OBJECT_CLASS (location_wps_parent_class)->dispose (gobject); +} + +static void +location_wps_finalize (GObject *gobject) +{ + LOCATION_LOGD("location_wps_finalize"); + LocationWpsPrivate* priv = GET_PRIVATE(gobject); + module_free(priv->mod, "wps"); + + if (priv->boundary_list) { + g_list_free_full (priv->boundary_list, free_boundary_list); + priv->boundary_list = NULL; + } + + if (priv->pos) { + location_position_free(priv->pos); + priv->pos = NULL; + } + + if (priv->vel) { + location_velocity_free(priv->vel); + priv->vel = NULL; + } + + if (priv->acc) { + location_accuracy_free(priv->acc); + priv->acc = NULL; + } + G_OBJECT_CLASS (location_wps_parent_class)->finalize (gobject); +} + +static void +location_wps_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + LocationWpsPrivate* priv = GET_PRIVATE(object); + int ret = 0; + + switch (property_id){ + case PROP_BOUNDARY:{ + GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value)); + ret = set_prop_boundary(&priv->boundary_list, boundary_list); + if(ret != 0) LOCATION_LOGD("Set boundary. Error[%d]", ret); + break; + } + case PROP_REMOVAL_BOUNDARY: { + LocationBoundary *req_boundary = (LocationBoundary*) g_value_dup_boxed(value); + ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary); + if(ret != 0) LOCATION_LOGD("Set removal boundary. Error[%d]", ret); + break; + } + case PROP_POS_INTERVAL: { + guint interval = g_value_get_uint(value); + if(interval > 0) { + if(interval < LOCATION_UPDATE_INTERVAL_MAX) + priv->pos_interval = interval; + else + priv->pos_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX; + } + else + priv->pos_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT; + + if (priv->pos_timer) { + g_source_remove (priv->pos_timer); + priv->pos_timer = g_timeout_add_seconds (priv->pos_interval, _position_timeout_cb, object); + } + + break; + } + case PROP_VEL_INTERVAL: { + guint interval = g_value_get_uint(value); + if(interval > 0) { + if(interval < LOCATION_UPDATE_INTERVAL_MAX) + priv->vel_interval = interval; + else + priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_MAX; + } + else + priv->vel_interval = (guint)LOCATION_UPDATE_INTERVAL_DEFAULT; + + if (priv->vel_timer) { + g_source_remove (priv->vel_timer); + priv->vel_timer = g_timeout_add_seconds (priv->vel_interval, _velocity_timeout_cb, object); + } + + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +location_wps_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + LocationWpsPrivate *priv = GET_PRIVATE (object); + + switch (property_id){ + case PROP_METHOD_TYPE: + g_value_set_int(value, LOCATION_METHOD_WPS); + break; + case PROP_LAST_POSITION: + g_value_set_boxed (value, priv->pos); + break; + case PROP_BOUNDARY: + g_value_set_pointer(value, g_list_first(priv->boundary_list)); + break; + case PROP_POS_INTERVAL: + g_value_set_uint(value, priv->pos_interval); + break; + case PROP_VEL_INTERVAL: + g_value_set_uint(value, priv->vel_interval); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static int +location_wps_get_position (LocationWps *self, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + int ret = LOCATION_ERROR_NOT_AVAILABLE; + LOCATION_LOGD("location_wps_get_position"); + + LocationWpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED); + + if (priv->is_started != TRUE) { + LOCATION_LOGD("location is not started"); + return LOCATION_ERROR_NOT_AVAILABLE; + } + + if (priv->pos) { + *position = location_position_copy (priv->pos); + if (priv->acc) *accuracy = location_accuracy_copy(priv->acc); + else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + ret = LOCATION_ERROR_NONE; + } + + return ret; +} + +static int +location_wps_get_position_ext (LocationWps *self, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + int ret = LOCATION_ERROR_NOT_AVAILABLE; + LOCATION_LOGD("location_wps_get_position_ext"); + + LocationWpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED); + + if (priv->is_started != TRUE) { + LOCATION_LOGD("location is not started"); + return LOCATION_ERROR_NOT_AVAILABLE; + } + + if (priv->pos && priv->vel) { + *position = location_position_copy (priv->pos); + *velocity = location_velocity_copy (priv->vel); + if (priv->acc) *accuracy = location_accuracy_copy(priv->acc); + else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + ret = LOCATION_ERROR_NONE; + } + + return ret; +} + + +static int +location_wps_get_last_position (LocationWps *self, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_wps_get_last_position"); + + /* Do not need to check VCONFKEY_LOCATION_ENABLED and VCONFKEY_LOCATION_NETWORK_ENABLED */ + + LocationWpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + + LocationError ret = LOCATION_ERROR_NONE; + LocationVelocity *_velocity = NULL; + + LocModWpsOps ops = priv->mod->ops; + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (ops.get_last_position, LOCATION_ERROR_NOT_AVAILABLE); + + ret = ops.get_last_position(priv->mod->handler, position, &_velocity, accuracy); + if (!_velocity) location_velocity_free (_velocity); + + return ret; +} + +static int +location_wps_get_last_position_ext (LocationWps *self, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_wps_get_last_position_ext"); + + /* Do not need to check VCONFKEY_LOCATION_ENABLED and VCONFKEY_LOCATION_NETWORK_ENABLED */ + + LocationWpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + + LocModWpsOps ops = priv->mod->ops; + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (ops.get_last_position, LOCATION_ERROR_NOT_AVAILABLE); + + return ops.get_last_position(priv->mod->handler, position, velocity, accuracy); + +} + + +static int +location_wps_get_velocity (LocationWps *self, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + int ret = LOCATION_ERROR_NOT_AVAILABLE; + LOCATION_LOGD("location_wps_get_velocity"); + + LocationWpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + setting_retval_if_fail(VCONFKEY_LOCATION_NETWORK_ENABLED); + + if (priv->is_started != TRUE) { + LOCATION_LOGD("location is not started"); + return LOCATION_ERROR_NOT_AVAILABLE; + } + + if (priv->vel) { + *velocity = location_velocity_copy (priv->vel); + if (priv->acc) *accuracy = location_accuracy_copy(priv->acc); + else *accuracy = location_accuracy_new(LOCATION_ACCURACY_LEVEL_NONE, 0.0, 0.0); + ret = LOCATION_ERROR_NONE; + } + + return ret; +} + +static int +location_wps_get_last_velocity (LocationWps *self, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("location_wps_get_last_velocity"); + + /* Do not need to check VCONFKEY_LOCATION_ENABLED and VCONFKEY_LOCATION_NETWORK_ENABLED */ + + LocationWpsPrivate *priv = GET_PRIVATE (self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + + LocationError ret = LOCATION_ERROR_NONE; + LocationPosition *_position = NULL; + + LocModWpsOps ops = priv->mod->ops; + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + ret = ops.get_last_position(priv->mod->handler, &_position, velocity, accuracy); + if (!_position) location_position_free(_position); + + return ret; +} + +static int +location_wps_get_satellite (LocationWps *self, + LocationSatellite **satellite) +{ + LOCATION_LOGD("location_wps_get_satellite"); + return LOCATION_ERROR_NOT_SUPPORTED; +} + +static int +location_wps_get_last_satellite (LocationWps *self, + LocationSatellite **satellite) +{ + LOCATION_LOGD("location_wps_get_last_satellite"); + return LOCATION_ERROR_NOT_SUPPORTED; +} + +static void +location_ielement_interface_init (LocationIElementInterface *iface) +{ + iface->start = (TYPE_START_FUNC)location_wps_start; + iface->stop = (TYPE_STOP_FUNC)location_wps_stop; + iface->get_position = (TYPE_GET_POSITION)location_wps_get_position; + iface->get_position_ext = (TYPE_GET_POSITION_EXT)location_wps_get_position_ext; + iface->get_last_position = (TYPE_GET_POSITION)location_wps_get_last_position; + iface->get_last_position_ext = (TYPE_GET_POSITION_EXT)location_wps_get_last_position_ext; + iface->get_velocity = (TYPE_GET_VELOCITY)location_wps_get_velocity; + iface->get_last_velocity = (TYPE_GET_VELOCITY)location_wps_get_last_velocity; + iface->get_satellite = (TYPE_GET_SATELLITE)location_wps_get_satellite; + iface->get_last_satellite = (TYPE_GET_SATELLITE)location_wps_get_last_satellite; +} + +static void +location_wps_init (LocationWps *self) +{ + LOCATION_LOGD("location_wps_init"); + LocationWpsPrivate* priv = GET_PRIVATE(self); + + priv->mod = (LocationWpsMod*)module_new("wps"); + if(!priv->mod) LOCATION_LOGW("module loading failed"); + + priv->is_started = FALSE; + priv->set_noti = FALSE; + priv->enabled= FALSE; + + priv->pos_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + priv->vel_interval = LOCATION_UPDATE_INTERVAL_DEFAULT; + + priv->pos_updated_timestamp = 0; + priv->vel_updated_timestamp = 0; + + priv->pos = NULL; + priv->vel = NULL; + priv->acc = NULL; + priv->boundary_list = NULL; + + priv->pos_timer = 0; + priv->vel_timer = 0; +} + +static void +location_wps_class_init (LocationWpsClass *klass) +{ + LOCATION_LOGD("location_wps_class_init"); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = location_wps_set_property; + gobject_class->get_property = location_wps_get_property; + + gobject_class->dispose = location_wps_dispose; + gobject_class->finalize = location_wps_finalize; + + g_type_class_add_private (klass, sizeof (LocationWpsPrivate)); + + signals[SERVICE_ENABLED] = g_signal_new ("service-enabled", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationWpsClass, enabled), + NULL, NULL, + location_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[SERVICE_DISABLED] = g_signal_new ("service-disabled", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationWpsClass, disabled), + NULL, NULL, + location_VOID__UINT, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[SERVICE_UPDATED] = g_signal_new ("service-updated", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationWpsClass, updated), + NULL, NULL, + location_VOID__UINT_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_UINT, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[ZONE_IN] = g_signal_new ("zone-in", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationWpsClass, zone_in), + NULL, NULL, + location_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_POINTER, + G_TYPE_POINTER, + G_TYPE_POINTER); + + signals[ZONE_OUT] = g_signal_new ("zone-out", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (LocationWpsClass, zone_out), + NULL, NULL, + location_VOID__POINTER_POINTER_POINTER, + G_TYPE_NONE, 3, + G_TYPE_POINTER, + G_TYPE_POINTER, + G_TYPE_POINTER); + + properties[PROP_METHOD_TYPE] = g_param_spec_int ("method", + "method type", + "location method type name", + LOCATION_METHOD_WPS, + LOCATION_METHOD_WPS, + LOCATION_METHOD_WPS, + G_PARAM_READABLE); + + properties[PROP_LAST_POSITION] = g_param_spec_boxed ("last-position", + "wps last position prop", + "wps last position data", + LOCATION_TYPE_POSITION, + G_PARAM_READABLE); + + properties[PROP_POS_INTERVAL] = g_param_spec_uint ("pos-interval", + "wps position interval prop", + "wps position interval data", + LOCATION_UPDATE_INTERVAL_MIN, + LOCATION_UPDATE_INTERVAL_MAX, + LOCATION_UPDATE_INTERVAL_DEFAULT, + G_PARAM_READWRITE); + + properties[PROP_VEL_INTERVAL] = g_param_spec_uint ("vel-interval", + "wps velocity interval prop", + "wps velocity interval data", + LOCATION_UPDATE_INTERVAL_MIN, + LOCATION_UPDATE_INTERVAL_MAX, + LOCATION_UPDATE_INTERVAL_DEFAULT, + G_PARAM_READWRITE); + + properties[PROP_BOUNDARY] = g_param_spec_pointer ("boundary", + "wps boundary prop", + "wps boundary data", + G_PARAM_READWRITE); + + properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary", + "wps removal boundary prop", + "wps removal boundary data", + LOCATION_TYPE_BOUNDARY, + G_PARAM_READWRITE); + + g_object_class_install_properties (gobject_class, + PROP_MAX, + properties); +} + diff --git a/location/manager/location-wps.h b/location/manager/location-wps.h new file mode 100644 index 0000000..49afbaf --- /dev/null +++ b/location/manager/location-wps.h @@ -0,0 +1,64 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_WPS_H__ +#define __LOCATION_WPS_H__ + +#include + +/** + * @file location-wps.h + * @brief This file contains the internal definitions and structures related to WPS. + */ + +G_BEGIN_DECLS + +#define LOCATION_TYPE_WPS (location_wps_get_type ()) +#define LOCATION_WPS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOCATION_TYPE_WPS, LocationWps)) +#define LOCATION_IS_WPS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LOCATION_TYPE_WPS)) +#define LOCATION_WPS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LOCATION_TYPE_WPS, LocationWpsClass)) +#define LOCATION_IS_WPS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LOCATION_TYPE_WPS)) +#define LOCATION_WPS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LOCATION_TYPE_WPS, LocationWpsClass)) + +typedef struct _LocationWps LocationWps; +typedef struct _LocationWpsClass LocationWpsClass; + +struct _LocationWps +{ + GObject parent_instance; +}; + +struct _LocationWpsClass +{ + GObjectClass parent_class; + + void (* enabled) (guint type); + void (* disabled) (guint type); + void (* updated) (guint type, gpointer data, gpointer accuracy); + void (* zone_in) (gpointer boundary, gpointer position, gpointer accuracy); + void (* zone_out) (gpointer boundary, gpointer position, gpointer accuracy); +}; + +GType location_wps_get_type (void); + +G_END_DECLS + +#endif diff --git a/location/manager/location.c b/location/manager/location.c new file mode 100644 index 0000000..7155d7e --- /dev/null +++ b/location/manager/location.c @@ -0,0 +1,370 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "location.h" +#include "location-log.h" +#include "location-setting.h" +#include "location-ielement.h" +#include "location-hybrid.h" +#include "location-gps.h" +#include "location-wps.h" +#include "location-cps.h" +#include "location-position.h" +#include "map-service.h" +#include "module-internal.h" +#include "location-common-util.h" + +EXPORT_API +int location_init (void) +{ + LOCATION_LOGD("location_init"); + g_type_init (); + +#if !GLIB_CHECK_VERSION (2, 31, 0) + if (!g_thread_supported()) g_thread_init (NULL); +#endif + dbus_g_thread_init (); + if( FALSE == module_init() ) + return LOCATION_ERROR_NOT_AVAILABLE; + + return LOCATION_ERROR_NONE; +} + +EXPORT_API LocationObject* +location_new (LocationMethod method) +{ + LocationObject *self = NULL; + + switch (method) { + case LOCATION_METHOD_HYBRID: + self = g_object_new (LOCATION_TYPE_HYBRID, NULL); + break; + case LOCATION_METHOD_GPS: + self = g_object_new (LOCATION_TYPE_GPS, NULL); + break; + case LOCATION_METHOD_WPS: + self = g_object_new (LOCATION_TYPE_WPS, NULL); + break; + case LOCATION_METHOD_CPS: + self = g_object_new (LOCATION_TYPE_CPS, NULL); + break; + default: + break; + } + + if (!self) LOCATION_LOGD("Fail to create location object. Method [%d]", method); + return self; +} + +EXPORT_API int +location_free (LocationObject *obj) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + + g_object_unref (obj); + return LOCATION_ERROR_NONE; +} + +EXPORT_API int +location_start (LocationObject *obj) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) != MAP_TYPE_SERVICE, LOCATION_ERROR_PARAMETER); + + int ret = LOCATION_ERROR_NONE; + if (location_application_enabled() == FALSE) { + LOCATION_LOGD("Application does not have permission"); + return LOCATION_ERROR_NOT_ALLOWED; + } + ret = location_ielement_start (LOCATION_IELEMENT(obj)); + if (ret != LOCATION_ERROR_NONE) LOCATION_LOGD("Fail to start. Error [%d]", ret); + + return ret; +} + +EXPORT_API int +location_stop (LocationObject *obj) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) != MAP_TYPE_SERVICE, LOCATION_ERROR_PARAMETER); + int ret = LOCATION_ERROR_NONE; + ret = location_ielement_stop (LOCATION_IELEMENT(obj)); + if (ret != LOCATION_ERROR_NONE) LOCATION_LOGD("Fail to stop. Error [%d]", ret); + + return ret; +} + +EXPORT_API gboolean +location_is_supported_method(LocationMethod method) +{ + gboolean is_supported = FALSE; + + switch(method) { + case LOCATION_METHOD_HYBRID: + if(module_is_supported("gps") || module_is_supported("wps")) + is_supported = TRUE; + break; + case LOCATION_METHOD_GPS: + is_supported = module_is_supported("gps"); + break; + case LOCATION_METHOD_WPS: + is_supported = module_is_supported("wps"); + break; + case LOCATION_METHOD_CPS: + is_supported = module_is_supported("cps"); + break; + default: + break; + } + + return is_supported; +} + +EXPORT_API gboolean +location_is_enabled_gps(LocationObject *obj) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) != MAP_TYPE_SERVICE, LOCATION_ERROR_PARAMETER); + + return (gboolean) location_setting_get_int(VCONFKEY_LOCATION_ENABLED); +} + +EXPORT_API int +location_get_position (LocationObject *obj, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) != MAP_TYPE_SERVICE, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (accuracy, LOCATION_ERROR_PARAMETER); + + int ret = LOCATION_ERROR_NONE; + ret = location_ielement_get_position (LOCATION_IELEMENT(obj), position, accuracy); + if (ret != LOCATION_ERROR_NONE) LOCATION_LOGD("Fail to get_position. Error [%d]", ret); + + return ret; +} + +EXPORT_API int +location_get_position_ext (LocationObject *obj, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) != MAP_TYPE_SERVICE, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (velocity, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (accuracy, LOCATION_ERROR_PARAMETER); + + int ret = LOCATION_ERROR_NONE; + ret = location_ielement_get_position_ext (LOCATION_IELEMENT(obj), position, velocity, accuracy); + if (ret != LOCATION_ERROR_NONE) LOCATION_LOGD("Fail to get_position_ext. Error [%d]", ret); + + return ret; +} + +EXPORT_API int +location_get_last_position (LocationObject *obj, + LocationPosition **position, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) != MAP_TYPE_SERVICE, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (accuracy, LOCATION_ERROR_PARAMETER); + + int ret = LOCATION_ERROR_NONE; + ret = location_ielement_get_last_position (LOCATION_IELEMENT(obj), position, accuracy); + if (ret != LOCATION_ERROR_NONE) LOCATION_LOGD("Fail to get_last_position. Error [%d]", ret); + + return ret; +} + +EXPORT_API int +location_get_last_position_ext (LocationObject *obj, + LocationPosition **position, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) != MAP_TYPE_SERVICE, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (velocity, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (accuracy, LOCATION_ERROR_PARAMETER); + + int ret = LOCATION_ERROR_NONE; + ret = location_ielement_get_last_position_ext (LOCATION_IELEMENT(obj), position, accuracy); + if (ret != LOCATION_ERROR_NONE) LOCATION_LOGD("Fail to get_last_position_ext. Error [%d]", ret); + + return ret; +} + +EXPORT_API int +location_get_satellite (LocationObject *obj, LocationSatellite **satellite) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) != MAP_TYPE_SERVICE, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (satellite, LOCATION_ERROR_PARAMETER); + + int ret = LOCATION_ERROR_NONE; + + ret = location_ielement_get_satellite (LOCATION_IELEMENT(obj), satellite); + if (ret != LOCATION_ERROR_NONE) LOCATION_LOGD("Fail to get_satellite. Error [%d]", ret); + + return ret; +} + +EXPORT_API int +location_get_last_satellite (LocationObject *obj, LocationSatellite **satellite) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) != MAP_TYPE_SERVICE, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (satellite, LOCATION_ERROR_PARAMETER); + + int ret = LOCATION_ERROR_NONE; + ret = location_ielement_get_last_satellite (LOCATION_IELEMENT(obj), satellite); + if (ret != LOCATION_ERROR_NONE) LOCATION_LOGD("Fail to get_last_satellite. Error [%d]", ret); + + return ret; +} + +EXPORT_API int +location_get_velocity (LocationObject *obj, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) != MAP_TYPE_SERVICE, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (velocity, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (accuracy, LOCATION_ERROR_PARAMETER); + + int ret = LOCATION_ERROR_NONE; + ret = location_ielement_get_velocity (LOCATION_IELEMENT(obj), velocity, accuracy); + if (ret != LOCATION_ERROR_NONE) LOCATION_LOGD("Fail to get_velocity. Error [%d]", ret); + + return ret; +} + +EXPORT_API int +location_get_last_velocity (LocationObject *obj, + LocationVelocity **velocity, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) != MAP_TYPE_SERVICE, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (velocity, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (accuracy, LOCATION_ERROR_PARAMETER); + + int ret = LOCATION_ERROR_NONE; + ret = location_ielement_get_last_velocity (LOCATION_IELEMENT(obj), velocity, accuracy); + if (ret != LOCATION_ERROR_NONE) LOCATION_LOGD("Fail to get_last_velocity. Error [%d]", ret); + + return ret; +} + +EXPORT_API int +location_get_accessibility_state (LocationAccessState *state) +{ + int auth = location_application_get_authority (); + switch (auth) { + case LOCATION_APP_OFF: + *state = LOCATION_ACCESS_DENIED; + break; + case LOCATION_APP_ON: + *state = LOCATION_ACCESS_ALLOWED; + break; + case LOCATION_APP_NOT_FOUND: + *state = LOCATION_ACCESS_NONE; + break; + default: + return LOCATION_ERROR_UNKNOWN; + } + + LOCATION_LOGD("get_accessibility_state [%d]", auth); + return LOCATION_ERROR_NONE; +} + +EXPORT_API int +location_set_accessibility_state (LocationAccessState state) +{ + int auth = LOCATION_APP_NOT_FOUND; + int ret = LOCATION_ERROR_NONE; + + switch (state) { + case LOCATION_ACCESS_DENIED: + auth = LOCATION_APP_OFF; + break; + case LOCATION_ACCESS_ALLOWED: + auth = LOCATION_APP_ON; + break; + case LOCATION_ACCESS_NONE: + default: + return LOCATION_ERROR_PARAMETER; + } + + ret = location_application_set_authority(auth); + LOCATION_LOGD("set_accessibility_state [%d], Error[%d]", auth, ret); + return ret; +} + + +EXPORT_API int +location_send_command(const char *cmd) +{ + g_return_val_if_fail (cmd, LOCATION_ERROR_PARAMETER); + int ret = 0; + + if (0 == g_strcmp0(cmd, "ADD_APPLIST")) { + ret = location_application_add_app_to_applist (); + if (ret == FALSE) { + LOCATION_LOGD("Fail to add to applist"); + return LOCATION_ERROR_UNKNOWN; + } + } else if (0 == g_strcmp0(cmd, "ACCESSIBILITY:1")) { + ret = location_set_accessibility_state(LOCATION_ACCESS_ALLOWED); + if (ret != LOCATION_ERROR_NONE) { + LOCATION_LOGD("Fail to set ACCESSIBILITY:1 [ret = %d]", ret); + return ret; + } + } else if (0 == g_strcmp0(cmd, "ACCESSIBILITY:0")) { + ret = location_set_accessibility_state(LOCATION_ACCESS_DENIED); + if (ret != LOCATION_ERROR_NONE) { + LOCATION_LOGD("Fail to set ACCESSIBILITY:0 [ret = %d]", ret); + return ret; + } + } else { + LOCATION_LOGD("Invalid CMD[%s]", cmd); + } + + return LOCATION_ERROR_NONE; +} + diff --git a/location/manager/location.h b/location/manager/location.h new file mode 100644 index 0000000..2a0c947 --- /dev/null +++ b/location/manager/location.h @@ -0,0 +1,879 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __LOCATION_H__ +#define __LOCATION_H__ + + +#include +#include +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +/** + * @file location.h + * @brief This file contains the Location API and related structure and enumeration. + */ +/** + * @defgroup LocationFW LocationFW + * @brief This is a Location Framework for providing location based services. + * @addtogroup LocationFW + * @{ + * @defgroup LocationAPI Location API + * @brief This sub module provides the Location API. + * @addtogroup LocationAPI + * @{ + */ + +/** + * @brief + * Initialize location sub module. + * @remarks None. + * This API should be called before any other Location APIs. + * @pre None. + * @post None. + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see None. + */ +int location_init (void); + +/** + * @brief + * Create a new #LocationObject by using given #LocationMethod. + * @remarks + * Returned object is necessary for other APIs. + * @pre + * #location_init should be called before. + * @post None. + * @param [in] + * method - Location method to be used. + * @return a new #LocationObject + * @retval NULL if error occured + * @see location_free + */ +LocationObject *location_new (LocationMethod method); + +/** + * @brief + * Free memory of given #LocationObject. + * @remarks None. + * @pre + * #location_init should be called before. + * @post None. + * @param [in] + * obj - a #LocationObject created by #location_new. + * @return int + * @retval 0 Success. + * + * Please refer #LocationError for more information. + * @see location_new + * @par Example + * @code +#include +int main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + location_init (); + loc = location_new (LOCATION_METHOD_GPS); + if(!loc) + return -1; + + // ... Implement your code + + location_free (loc); + // You must free LocationObject when you don't need to use anymore. + return 0; +} + * @endcode + */ +int location_free (LocationObject *obj); + +/** + * @brief + * Start the location service by using given #LocationObject. + * @remarks + * If you want to recieve signals, you should use this API. + * @pre + * #location_init should be called before. + * @post None. + * @param [in] + * obj - a #LocationObject created by #location_new + * @return int + * @retval 0 Success. + * + * Please refer #LocationError for more information. + * @see location_stop + * @par Example + * @code +#include +static GMainLoop *loop = NULL; + +static void cb_service_enabled (GObject *self, guint status, gpointer userdata) +{ + LocationObject *loc = (LocationObject*)userdata; + LocationAccuracy *acc = NULL; + LocationPosition *pos = NULL; + LocationVelocity *vel = NULL; + LocationAddress *addr = NULL; + LocationMethod method; + + g_object_get(loc, "method", &method, NULL); + g_debug("Get property>> method:%d", method); + + if (LOCATION_ERROR_NONE == location_get_position (loc, &pos, &acc)) { + g_debug ("SYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_position_free(pos); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current position> failed"); + + if (LOCATION_ERROR_NONE == location_get_velocity (loc, &vel, &acc)) { + g_debug ("SYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_velocity_free(vel); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current velocity> failed"); + + if (LOCATION_ERROR_NONE == location_get_address(loc, &addr, &acc)) { + g_debug ("SYNC>> Current address> %s %s %s %s %s %s %s", + addr->building_number, addr->street, addr->district, addr->city, addr->state, addr->postal_code, addr->country_code); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_address_free(addr); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current address> failed"); +} + +static void +cb_service_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + switch (type) { + case POSITION_UPDATED: { + LocationPosition *pos = (LocationPosition*) data; + g_debug ("ASYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + break; + case VELOCITY_UPDATED: { + LocationVelocity *vel = (LocationVelocity*) data; + g_debug ("ASYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + break; + case SATELLITE_UPDATED: { + int idx = 0; + guint prn; + gboolean used; + guint elevation; + guint azimuth; + gint snr; + + LocationSatellite *sat = (LocationSatellite *)data; + g_debug ("ASYNC>> Current Satellite> time: %d, satellite in view = %d, satellite in used = %d", sat->timestamp, sat->num_of_sat_inview, sat->num_of_sat_used); + g_debug ("\tinview satellite information = "); + for (idx=0; idxnum_of_sat_inview; idx++) { + location_satellite_get_satellite_details(sat, idx, &prn, &used, &elevation, &azimuth, &snr); + g_debug ("\t\t[%02d] used: %d, prn: %d, elevation: %d, azimuth: %d, snr: %d", idx, used, prn, elevation, azimuth, snr); + } + } + break; + + default: + g_warning ("ASYNC>> Undefined update type"); + break; + } +} + + +int main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + int interval = 6; //seconds + location_init (); + + loc = location_new (LOCATION_METHOD_GPS); + if(!loc) + return -1; + + g_object_set(loc, "update-interval", interval, NULL); + + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + g_signal_connect (loc, "service-updated", G_CALLBACK(cb_service_updated), loc); + + location_start(loc); + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); // GMainLoop is needed for receiving signals. + + // ... + return 0; +} + * @endcode + */ +int location_start (LocationObject *obj); + +/** + * @brief + * Stop the location service by using given #LocationObject. + * @remarks + * After call this API, you can not recieve signals. + * @pre + * #location_init should be called before.\n + * #location_start should be called before. + * @post None. + * @param [in] + * obj - a #LocationObject created by #location_new + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see location_start + * @par Example + * @code +#include +static GMainLoop *loop = NULL; + +int main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + location_init (); + loc = location_new (LOCATION_METHOD_GPS); + if(!loc) + return -1; + + location_start(loc); + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); + + // .... + + location_stop (loc); + // you can not receive signals anymore. + return 0; +} + * @endcode + */ +int location_stop (LocationObject *obj); + +/** + * @brief + * Check wheither a method is available. + * @remarks + * @pre + * #location_init should be called before.\n + * @post None. + * @param [in] method - a #LocationMethod + * @return int + * @retval True Supported + * False Not supported + * @par Example + #include +static GMainLoop *loop = NULL; + +int main (int argc, char *argv[]) +{ + gboolean is_supported = FALSE; + + // .... + + is_supported = location_is_supported_method(LOCATION_METHOD_HYBRID); + if(is_supported == TRUE) + g_printf("Hybrid Method is supported.\n"); + else + g_printf("Hybrid Method is not supported.\n"); + + return 0; +}* @code + * @endcode + */ +gboolean location_is_supported_method(LocationMethod method); + +/** + * @brief + * Check wheither GPS is turned on or off. + * @remarks + * @pre + * #location_init should be called before.\n + * @post None. + * @param [in] method - a #LocationMethod + * @return int + * @retval True Turned on + * False Turned off + * @par Example + #include +static GMainLoop *loop = NULL; + +int main (int argc, char *argv[]) +{ + gboolean is_enabled = FALSE; + + // .... + + is_enabled = location_is_enabled_gps(loc); + if(is_enable == TRUE) + g_printf("GPS is turned on.\n"); + else + g_printf("GPS is turned off.\n"); + + return 0; +}* @code + * @endcode + */ +gboolean location_is_enabled_gps(LocationObject *obj); + +/** + * @brief + * Get current position information with estimate of the accuracy. + * @remarks Out parameters are should be freed. + * @pre + * #location_init should be called before.\n + * #location_start should be called before. + * @post None. + * @param [in] + * obj - a #LocationObject created by #location_new + * @param [out] + * position - a new #LocationPosition + * @param [out] + * accuracy - a new #LocationAccuracy + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see location_get_velocity + * @par Example + * @code +#include +static GMainLoop *loop = NULL; + +static void cb_service_enabled (GObject *self, guint status, gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); + + LocationObject *loc = (LocationObject*)userdata; + LocationAccuracy *acc = NULL; + LocationPosition *pos = NULL; + + // This function works properly after service is enabled. + if (LOCATION_ERROR_NONE == location_get_position (loc, &pos, &acc)) { + g_debug ("SYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_position_free(pos); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current position> failed"); +} + +int main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + gulong handler_id = 0; + + location_init (); + loop = g_main_loop_new (NULL, TRUE); + loc = location_new (LOCATION_METHOD_GPS); + if(!loc){ + g_debug("location_new failed"); + return -1; + } + + handler_id = g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + location_start (loc); + g_main_loop_run (loop); + + g_signal_handler_disconnect(loc, handler_id); + location_stop (loc); + location_free (loc); + + return 0; +} + * @endcode + */ +int location_get_position (LocationObject *obj, LocationPosition **position, LocationAccuracy **accuracy); + +/** + * @brief + * Get current position & velocity information with estimate of the accuracy. + * @remarks Out parameters are should be freed. + * @pre + * #location_init should be called before.\n + * #location_start should be called before. + * @post None. + * @param [in] obj - a #LocationObject created by #location_new + * @param [out] position - a new #LocationPosition + * @param [out] velocity - a new #LocationVelocity + * @param [out] accuracy - a new #LocationAccuracy + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see location_get_position + * @par Example + * @code +#include +static GMainLoop *loop = NULL; + +static void cb_service_enabled (GObject *self, guint status, gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); + + LocationObject *loc = (LocationObject*)userdata; + + LocationPosition *pos = NULL; + LocationVelocity *vel = NULL; + LocationAccuracy *acc = NULL; + + // This function works properly after service is enabled. + if (LOCATION_ERROR_NONE == location_get_position_ext (loc, &pos, &vel, &acc)) { + g_debug ("SYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d, speed: %f, direction: %f", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status, vel->speed, vel->direction); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_position_free(pos); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current position_ext > failed"); +} + +int main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + gulong handler_id = 0; + + location_init (); + loop = g_main_loop_new (NULL, TRUE); + loc = location_new (LOCATION_METHOD_GPS); + if(!loc){ + g_debug("location_new failed"); + return -1; + } + + handler_id = g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + location_start (loc); + g_main_loop_run (loop); + + g_signal_handler_disconnect(loc, handler_id); + location_stop (loc); + location_free (loc); + + return 0; +} + * @endcode + */ +int location_get_position_ext (LocationObject *obj, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy); + +/** + * @brief + * Get last position information with estimate of the accuracy. + * @remarks Out parameters are should be freed. + * @pre #location_init should be called before. + * @post None. + * @param [in] + * obj - a #LocationObject created by #location_new + * @param [out] position - a new #LocationPosition + * @param [out] accuracy - a new #LocationAccuracy + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see location_get_position + * @par Example + * @code +#include + +int main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + int ret = 0; + LocationPosition *last_pos = NULL; + LocationAccuracy *last_acc = NULL; + + location_init (); + loc = location_new (LOCATION_METHOD_GPS); + if(!loc){ + g_debug("location_new failed"); + return -1; + } + + if (LOCATION_ERROR_NONE == location_get_last_position (loc, &last_pos, &last_acc)) { + g_debug ("SYNC>> Last position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + last_pos->timestamp, last_pos->latitude, last_pos->longitude, last_pos->altitude, last_pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + last_acc->level, last_acc->horizontal_accuracy, last_acc->vertical_accuracy); + location_position_free(last_pos); + location_accuracy_free(last_acc); + } else g_warning ("SYNC>> Last position> failed"); + + location_free (loc); + + return 0; +} + * @endcode + */ +int location_get_last_position (LocationObject *obj, LocationPosition **position, LocationAccuracy **accuracy); + +/** + * @brief + * Get last position & velocity information with estimate of the accuracy. + * @remarks Out parameters are should be freed. + * @pre #location_init should be called before. + * @post None. + * @param [in] obj - a #LocationObject created by #location_new + * @param [out] position - a new #LocationPosition + * @param [out] velocity - a new #LocationVelocity + * @param [out] accuracy - a new #LocationAccuracy + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see location_get_position_ext + * @par Example + * @code +#include + +int main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + int ret = 0; + LocationPosition *last_pos = NULL; + LocationVelocity *last_vel = NULL; + LocationAccuracy *last_acc = NULL; + + location_init (); + loc = location_new (LOCATION_METHOD_GPS); + if(!loc){ + g_debug("location_new failed"); + return -1; + } + + if (LOCATION_ERROR_NONE == location_get_last_position_ext (loc, &last_pos, &last_vel, &last_acc)) { + g_debug ("SYNC>> Last position> time: %d, lat: %f, long: %f, alt: %f, status: %d, speed: %f, direction: %f", + last_pos->timestamp, last_pos->latitude, last_pos->longitude, last_pos->altitude, last_pos->status, last_vel->speed, last_vel->direction); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + last_acc->level, last_acc->horizontal_accuracy, last_acc->vertical_accuracy); + location_position_free(last_pos); + location_velocity_free(last_vel); + location_accuracy_free(last_acc); + } else g_warning ("SYNC>> Last position_ext > failed"); + + location_free (loc); + + return 0; +} + * @endcode + */ +int location_get_last_position_ext (LocationObject *obj, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy); +/** + * @brief + * Get last satellite information. + * @remarks This API is not implemented now. \n + * Out parameters are should be freed. + * @pre + * #location_init should be called before. + * @post None. + * @param [in] + * obj - a #LocationObject created by #location_new + * @param [out] satellite - a new #LocationSatellite + * @return int + * @retval 0 Success + * Please refer #LocationError for more information. + * @see location_get_last_satellite + * @par Example + * @code +#include + +int main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + int ret = 0, idx = 0; + LocationSatellite *sat = NULL; + guint prn; + gboolean used; + guint elevation; + guint azimuth; + gint snr; + + location_init (); + loc = location_new (LOCATION_METHOD_GPS); + if(!loc){ + g_debug("location_new failed"); + return -1; + } + + if (LOCATION_ERROR_NONE == location_get_satellite (loc, &sat)) { + g_debug ("SYNC>> Current Sattelite> satellite in view = %d, satellite in used = %d", sat->num_of_sat_inview, sat->num_of_sat_used); + g_debug ("\tinview satellite information = "); + for (idx=0; idxnum_of_sat_inview; idx++) { + location_satellite_get_satellite_details(sat, idx, &prn, &used, &elevation, &azimuth, &snr); + g_debug ("\t\t[%02d] used: %d, prn: %d, elevation: %d, azimuth: %d, snr: %d", idx, used, prn, elevation, azimuth, snr); + } + location_satellite_free (sat); + } else g_warning ("SYNC>> Current satellite> failed"); + + location_free (loc); + + return 0; +} + * @endcode + */ +int location_get_satellite (LocationObject *obj, LocationSatellite **satellite); + +/** + * @brief + * Get last satellite information. + * @remarks This API is not implemented now. \n + * Out parameters are should be freed. + * @pre + * #location_init should be called before. + * @post None. + * @param [in] + * obj - a #LocationObject created by #location_new + * @param [out] + * satellite - a new #LocationSatellite + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @par Example + * @code +#include + +int main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + int ret = 0, idx = 0; + LocationSatellite *last_sat = NULL; + guint prn; + gboolean used; + guint elevation; + guint azimuth; + gint snr; + + location_init (); + loc = location_new (LOCATION_METHOD_GPS); + if(!loc){ + g_debug("location_new failed"); + return -1; + } + + if (LOCATION_ERROR_NONE == location_get_last_satellite (loc, &last_sat)) { + g_debug ("SYNC>> Last Sattelite> satellite in view = %d, satellite in used = %d", last_sat->num_of_sat_inview, last_sat->num_of_sat_used); + g_debug ("\tinview satellite information = "); + for (idx=0; idxnum_of_sat_inview; idx++) { + location_satellite_get_satellite_details(last_sat, idx, &prn, &used, &elevation, &azimuth, &snr); + g_debug ("\t\t[%02d] used: %d, prn: %d, elevation: %d, azimuth: %d, snr: %d", idx, used, prn, elevation, azimuth, snr); + } + location_satellite_free (last_sat); + } else g_warning ("SYNC>> Last satellite> failed"); + + location_free (loc); + + return 0; +} + * @endcode + */ +int location_get_last_satellite (LocationObject *obj, LocationSatellite **satellite); + +/** + * @brief + * Get current velocity information with estimate of the accuracy. + * @remarks Out parameters are should be freed. + * @pre + * #location_init should be called before.\n + * #location_start should be called before. + * @post None. + * @param [in] + * obj - a #LocationObject created by #location_new + * @param [out] + * velocity - a new #LocationVelocity + * @param [out] + * accuracy - a new #LocationAccuracy + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see location_get_position + * @par Example + * @code +#include +static GMainLoop *loop = NULL; + +static void cb_service_enabled (GObject *self, guint status, gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); + + LocationObject *loc = (LocationObject*)userdata; + LocationAccuracy *acc = NULL; + LocationVelocity *vel = NULL; + + if (LOCATION_ERROR_NONE == location_get_velocity (loc, &vel, &acc)) { + g_debug ("SYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_velocity_free(vel); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current velocity> failed"); +} + +int main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + gulong hander_id = 0; + location_init (); + + loop = g_main_loop_new (NULL, TRUE); + + loc = location_new (LOCATION_METHOD_GPS); + if(!loc){ + g_debug("location_new failed"); + return -1; + } + + handler_id = g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + location_start (loc); + g_main_loop_run (loop); + + g_signal_handler_disconnect(loc, handler_id); + location_stop (loc); + location_free (loc); + + return 0; +} + + * @endcode + */ +int location_get_velocity (LocationObject *obj, LocationVelocity **velocity, LocationAccuracy **accuracy); + +/** + * @brief + * Get last velocity information with estimate of the accuracy. + * @remarks Out parameters are should be freed. + * @pre + * #location_init should be called before. + * @post None. + * @param [in] + * obj - a #LocationObject created by #location_new + * @param [out] + * velocity - a new #LocationVelocity + * @param [out] + * accuracy - a new #LocationAccuracy + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see location_get_position + * @par Example + * @code +#include + +int main (int argc, char *argv[]) +{ + int ret = 0; + LocationObject *loc = NULL; + LocationVelocity *vel = NULL; + LocationAccuracy *acc = NULL; + gulong hander_id = 0; + + location_init (); + + loc = location_new (LOCATION_METHOD_GPS); + if(!loc){ + g_debug("location_new failed"); + return -1; + } + + ret = location_get_last_velocity (loc, &vel, &acc); + if (ret == LOCATION_ERROR_NONE) { + g_debug ("SYNC>> Last velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_velocity_free(vel); + location_accuracy_free(acc); + } + + location_free (loc); + return 0; +} + * @endcode + */ +int location_get_last_velocity (LocationObject *obj, LocationVelocity **velocity, LocationAccuracy **accuracy); + +/** + * @brief + * Get the accessibility state of an application + * @remarks None. + * @pre + * #location_init should be called before.\n + * @post None. + * @param [out] state - a #LocationAccessState + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + */ +int location_get_accessibility_state (LocationAccessState *state); + +/** + * @brief + * Send command to the server. + * @remarks This functions is not implemneted yet. + * @pre + * #location_init should be called before.\n + * Calling application must have glib or ecore main loop.\n + * Calling application must have an active data connection. + * @post None. + * @param [in] cmd - a #char + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + */ +int location_send_command(const char *cmd); + +/** + * @} @} + */ + +G_END_DECLS + +#endif /* __LOCATION_H__ */ diff --git a/location/map-service/Makefile.am b/location/map-service/Makefile.am new file mode 100644 index 0000000..ce4aeca --- /dev/null +++ b/location/map-service/Makefile.am @@ -0,0 +1,28 @@ +noinst_LTLIBRARIES = liblocation-map-service.la + +COMMON_HEADER_DIR = include +MANAGER_DIR = manager +MAP_SERVICE_DIR = map-service +MODULE_DIR = module + +liblocation_map_service_la_SOURCES = \ + location-map-pref.c \ + location-map-ielement.c \ + location-address.c \ + location-geocode.c \ + location-poi.c \ + location-landmark.c \ + location-route.c \ + map-service.c \ + map-internal.c + +liblocation_map_service_la_CFLAGS = \ + -fPIC\ + -I${srcdir} \ + -I${srcdir}/.. \ + -I${srcdir}/../include \ + -I${srcdir}/../${MANAGER_DIR} \ + -I${srcdir}/../${MODULE_DIR} \ + -I${srcdir}/../${MAP_SERVICE_DIR} \ + $(LOCATION_CFLAGS) + diff --git a/location/map-service/location-address.c b/location/map-service/location-address.c new file mode 100644 index 0000000..4366220 --- /dev/null +++ b/location/map-service/location-address.c @@ -0,0 +1,104 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-address.h" +#include "location-log.h" + +GType +location_address_get_type (void) +{ + static volatile gsize type_volatile = 0; + if(g_once_init_enter(&type_volatile)) { + GType type = g_boxed_type_register_static ( + g_intern_static_string ("LocationAddress"), + (GBoxedCopyFunc) location_address_copy, + (GBoxedFreeFunc) location_address_free); + g_once_init_leave(&type_volatile, type); + } + return type_volatile; +} + +EXPORT_API LocationAddress* +location_address_new (const gchar *building_number, + const gchar *street, + const gchar *district, + const gchar *city, + const gchar *state, + const gchar *country_code, + const gchar *postal_code, + const gchar *text, + const gchar *country, + const gchar *county) +{ + LocationAddress* address = g_slice_new0(LocationAddress); + g_return_val_if_fail (address, NULL); + + if (building_number) address->building_number = g_strdup(building_number); + if (street) address->street = g_strdup(street); + if (district) address->district = g_strdup(district); + if (city) address->city = g_strdup(city); + if (state) address->state = g_strdup(state); + if (country_code) address->country_code = g_strdup(country_code); + if (postal_code) address->postal_code = g_strdup(postal_code); + if (text) address->text = g_strdup(text); + if (country) address->country = g_strdup(country); + if (county) address->county = g_strdup(county); + + return address; +} + +EXPORT_API void +location_address_free (LocationAddress* address) +{ + g_return_if_fail(address); + if (address->building_number) g_free(address->building_number); + if (address->street) g_free(address->street); + if (address->district) g_free(address->district); + if (address->city) g_free(address->city); + if (address->state) g_free(address->state); + if (address->country_code) g_free(address->country_code); + if (address->postal_code) g_free(address->postal_code); + if (address->text) g_free(address->text); + if (address->country) g_free(address->country); + if (address->county) g_free(address->county); + g_slice_free(LocationAddress, address); +} + +EXPORT_API LocationAddress* +location_address_copy (const LocationAddress *address) +{ + g_return_val_if_fail(address, NULL); + return location_address_new(address->building_number, + address->street, + address->district, + address->city, + address->state, + address->country_code, + address->postal_code, + address->text, + address->country, + address->county + ); +} diff --git a/location/map-service/location-address.h b/location/map-service/location-address.h new file mode 100644 index 0000000..bb90617 --- /dev/null +++ b/location/map-service/location-address.h @@ -0,0 +1,108 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_ADDRESS_H_ +#define __LOCATION_ADDRESS_H_ + +#include + +G_BEGIN_DECLS + +GType location_address_get_type(void); +#define LOCATION_TYPE_ADDRESS (location_address_get_type()) + +/** + * @file location-address.h + * @brief This file contains the definitions, structures, and functions related to address information. + * @addtogroup LocationMapService + * @{ + * @defgroup LocationMapServiceGeocode Location Geocode + * @brief This sub module provides structure, enumeration, and asynchronous function definitions. + * @addtogroup LocationMapServiceGeocode + * @{ + */ + +/** + * @brief This represents address information such as building number, street name, etc. + */ +struct _LocationAddress +{ + gchar *building_number; ///< Building number. + gchar *street; ///< Full street name. + gchar *district; ///< Municipal district name. + gchar *city; ///< City name. + gchar *state; ///< State or province region of a nation. + gchar *country_code; ///< Country name. + gchar *postal_code; ///< Postal delivery code. + + gchar *text; ///, Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-log.h" + diff --git a/location/map-service/location-geocode.h b/location/map-service/location-geocode.h new file mode 100644 index 0000000..348a79b --- /dev/null +++ b/location/map-service/location-geocode.h @@ -0,0 +1,39 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_GEOCODE_H__ +#define __LOCATION_GEOCODE_H__ + +#include + +G_BEGIN_DECLS + +/** + * @file location-geocode.h + * @brief This file contains the internal definitions and structures related to geocode. + * @addtogroup LocationMapService + * @{ + * @} + */ + +G_END_DECLS + +#endif diff --git a/location/map-service/location-landmark-ext.h b/location/map-service/location-landmark-ext.h new file mode 100644 index 0000000..69e0c5f --- /dev/null +++ b/location/map-service/location-landmark-ext.h @@ -0,0 +1,247 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_LANDMARK_EXT_H__ +#define __LOCATION_LANDMARK_EXT_H__ + +#include + +G_BEGIN_DECLS + +/** + * @file location-landmark-ext.h + * @brief This file contains the extensional definitions and structures related to Landmark. + */ + +/** + * @addtogroup LocationMapServicePOI + * @{ + * @defgroup LocationMapServiceLandmarkExt Location Landmark Ext + * @brief This provides Location Landmark Ext APIs + * @addtogroup LocationMapServiceLandmarkExt + * @{ + */ + +/** + * @brief Set the ID of the given #LocationLandmark + * @remarks None. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] id - a guint + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_id + */ +gboolean location_landmark_set_id (LocationLandmark *landmark, guint id); + +/** + * @brief Set the name of the given #LocationLandmark + * @remarks The previous name of the #LocationLandmark will be removed if a name is NULL. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] name - a gchar + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_name + */ +gboolean location_landmark_set_name (LocationLandmark *landmark, const gchar *name); + +/** + * @brief Set the position in the given #LocationLandmark + * @remarks The previous position of the #LocationLandmark will be removed if a position is NULL. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] position - a #LocationPosition + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_position + */ +gboolean location_landmark_set_position (LocationLandmark *landmark, const LocationPosition *position); + +/** + * @brief Set the address of the given #LocationLandmark + * @remarks The previous address of the #LocationLandmark will be removed if an addr is NULL. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] addr - a #LocationAddress + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_address + */ +gboolean location_landmark_set_address (LocationLandmark *landmark, const LocationAddress *addr); + +/** + * @brief Set the description of the given #LocationLandmark + * @remarks The previous description of the #LocationLandmark will be removed if a desc is NULL. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] desc - a gchar + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_description + */ +gboolean location_landmark_set_description (LocationLandmark *landmark, const gchar *desc); + +/** + * @brief Set the timestamp of the given #LocationLandmark + * @remarks None. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] timestamp - a guint + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_timestamp + */ +gboolean location_landmark_set_timestamp (LocationLandmark *landmark, guint timestamp); + +/** + * @brief Set the priority of the given #LocationLandmark + * @remarks None. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] priority - a guint + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_priority + */ +gboolean location_landmark_set_priority (LocationLandmark *landmark, guint priority); + +/** + * @brief Set the boundary of the given #LocationLandmark + * @remarks The previous bounding box of the #LocationLandmark will be removed if a bbox is NULL. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] bbox - a #LocationBoundary + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_bounding_box + */ +gboolean location_landmark_set_bounding_box (LocationLandmark *landmark, const LocationBoundary *bbox); + +/** + * @brief Set the author of the given #LocationLandmark + * @remarks The previous author of the #LocationLandmark will be removed if a author is NULL. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] author - a gchar + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_author + */ +gboolean location_landmark_set_author (LocationLandmark *landmark, const gchar *author); + +/** + * @brief Set the urls of the given #LocationLandmark + * @remarks The previous url of the #LocationLandmark will be removed if an url is NULL. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] url - a GList + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_url + */ +gboolean location_landmark_set_url (LocationLandmark *landmark, GList *url); + +/** + * @brief Set the categories of the given #LocationLandmark + * @remarks The previous categories of the #LocationLandmark will be removed if a category is NULL. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] category - a GList + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_category + */ +gboolean location_landmark_set_category (const LocationLandmark *landmark, GList *category); + +/** + * @brief Set the phone number of the given #LocationLandmark + * @remarks The previous phone number of the #LocationLandmark will be removed if a number is NULL. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] number - a gchar + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_phone_number + */ +gboolean location_landmark_set_phone_number (const LocationLandmark *landmark, const gchar *number); + +/** + * @brief Set the property data of the given #LocationLandmark + * @remarks The previous value of the #LocationLandmark matching to key will be removed if a value is NULL. + * @pre None. + * @post None. + * @param [in] landmark - a #LocationLandmark + * @param [in] key - a gconstpointer + * @param [in] value - a gconstpointer + * @return gboolean + * @retval TRUE if success + * @see location_landmark_get_property + */ +gboolean location_landmark_set_property (const LocationLandmark *landmark, gconstpointer key, gconstpointer value); + +/** + * @brief Set url of the given #LocationLandmarkUrl + * @remarks The previous url path of the #LocationLandmarkUrl will be removed if a path is NULL. + * @pre None. + * @post None. + * @param [in] url - a #LocationLandmarkUrl + * @param [in] path - a gchar + * @return gboolean + * @retval TRUE if success + * @see location_landmark_url_get_url_path + */ +gboolean location_landmark_url_set_url_path (LocationLandmarkUrl *url, const gchar *path); + +/** + * @brief Set the description of the given #LocationLandmarkUrl + * @remarks The previous description of the #LocationLandmarkUrl will be removed if a desc is NULL. + * @pre None. + * @post None. + * @param [in] url - a #LocationLandmarkUrl + * @param [in] desc - a gchar + * @return gboolean + * @retval TRUE if success + * @see location_landmark_url_get_description + */ +gboolean location_landmark_url_set_description (LocationLandmarkUrl *url, const gchar *desc); + +/** + * @} @} + */ + +G_END_DECLS + +#endif + + diff --git a/location/map-service/location-landmark.c b/location/map-service/location-landmark.c new file mode 100644 index 0000000..89b2794 --- /dev/null +++ b/location/map-service/location-landmark.c @@ -0,0 +1,528 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-log.h" +#include "location.h" +#include "location-types.h" +#include "map-service.h" + +struct _LocationLandmark { + + guint id; ///< Unique identifier of the landmark + guint priority; ///< Degree of importance of the landmark (Between HIGHEST_LANDMARK_PRIORITY and LOWEST_LANDMARK_PRIORITY) + gchar *name; ///< Name of landmark + LocationPosition *position; ///< Positon of the landmark, may be null if not known + LocationAddress *addr; ///< Textual address information of the landmark, may be null if not + LocationBoundary *bbox; ///< Coverage area of the landmark, may be null if not available + guint timestamp; ///< Time when the landmark data was last updated (updated by system and used to facilitate tracking) + + gchar *author; ///< Provider of the landmark data, may be null + gchar *store; ///< Name of landmark store that the landmark belongs to + gchar *phone_number; ///< Nhone number of the landmark, may be null + GList *category; ///< Categories to which the landmark belongs to + GList *url; ///< Url to additional content (Optional) + gchar *desc; ///< Description of the landmark, may be null if not available + + GHashTable *properties; ///< Extra info of the landmark + +}; + +struct _LocationLandmarkUrl { + gchar *path; ///< Url of landmark url info + gchar *desc; ///< Description of landmark url info +}; + +EXPORT_API guint +location_landmark_get_id (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, 0); + + return landmark->id; +} + + +EXPORT_API gchar * +location_landmark_get_name (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, NULL); + + return landmark->name; +} + +EXPORT_API LocationPosition * +location_landmark_get_position (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, NULL); + + return landmark->position; +} + +EXPORT_API LocationAddress * +location_landmark_get_address (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, NULL); + + return landmark->addr; +} + +EXPORT_API gchar * +location_landmark_get_description (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, NULL); + + return landmark->desc; +} + +EXPORT_API guint +location_landmark_get_timestamp (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, 0); + + return landmark->timestamp; +} + +EXPORT_API guint +location_landmark_get_priority (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, 0); + + return landmark->priority; +} + +EXPORT_API LocationBoundary * +location_landmark_get_bounding_box (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, NULL); + + return landmark->bbox; +} + +EXPORT_API gchar * +location_landmark_get_author (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, NULL); + + return landmark->author; +} + +EXPORT_API GList * +location_landmark_get_url (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, NULL); + + return landmark->url; +} + +EXPORT_API GList * +location_landmark_get_category (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, NULL); + + return landmark->category; +} + +EXPORT_API gchar * +location_landmark_get_phone_number (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, NULL); + + return landmark->phone_number; +} + +EXPORT_API GList * +location_landmark_get_property_key (const LocationLandmark *landmark) +{ + g_return_val_if_fail(landmark, NULL); + + return g_hash_table_get_keys (landmark->properties); +} + +EXPORT_API gconstpointer +location_landmark_get_property (const LocationLandmark *landmark, gconstpointer key) +{ + g_return_val_if_fail(landmark, NULL); + g_return_val_if_fail(key, NULL); + if (!landmark->properties) return NULL; + + return g_hash_table_lookup (landmark->properties, key); +} + +EXPORT_API gboolean +location_landmark_set_id (LocationLandmark *landmark, guint id) +{ + g_return_val_if_fail(landmark, FALSE); + + landmark->id = id; + + return TRUE; +} + +EXPORT_API gboolean +location_landmark_set_name (LocationLandmark *landmark, const gchar *name) +{ + g_return_val_if_fail(landmark, FALSE); + + if (landmark->name) { + g_free(landmark->name); + landmark->name = NULL; + } + if (name) landmark->name = g_strdup (name); + + return TRUE; +} + +EXPORT_API gboolean +location_landmark_set_position (LocationLandmark *landmark, const LocationPosition *position) +{ + g_return_val_if_fail(landmark, FALSE); + + if (landmark->position) { + location_position_free(landmark->position); + landmark->position = NULL; + } + + if (position) landmark->position = location_position_copy (position); + + return TRUE; + +} + +EXPORT_API gboolean +location_landmark_set_address (LocationLandmark *landmark, const LocationAddress *addr) +{ + g_return_val_if_fail(landmark, FALSE); + + if (landmark->addr) { + location_address_free (landmark->addr); + landmark->addr = NULL; + } + + if (addr) landmark->addr = location_address_copy (addr); + + return TRUE; + +} + +EXPORT_API gboolean +location_landmark_set_description (LocationLandmark *landmark, const gchar *desc) +{ + g_return_val_if_fail(landmark, FALSE); + + if (landmark->desc) { + g_free(landmark->desc); + landmark->desc = NULL; + } + + if (desc) landmark->desc = g_strdup (desc); + + return TRUE; +} + +EXPORT_API gboolean +location_landmark_set_timestamp (LocationLandmark *landmark, guint timestamp) +{ + g_return_val_if_fail(landmark, FALSE); + + landmark->timestamp = timestamp; + + return TRUE; + +} + +EXPORT_API gboolean +location_landmark_set_priority (LocationLandmark *landmark, guint priority) +{ + g_return_val_if_fail(landmark, FALSE); + + landmark->priority = priority; + + return TRUE; +} + +EXPORT_API gboolean +location_landmark_set_bounding_box (LocationLandmark *landmark, const LocationBoundary *bbox) +{ + g_return_val_if_fail(landmark, FALSE); + + if (landmark->bbox) { + location_boundary_free(landmark->bbox); + landmark->bbox = NULL; + } + + if (bbox) landmark->bbox = location_boundary_copy (bbox); + + return TRUE; +} + +EXPORT_API gboolean +location_landmark_set_author (LocationLandmark *landmark, const gchar *author) +{ + g_return_val_if_fail(landmark, FALSE); + + if (landmark->author) { + g_free(landmark->author); + landmark->author = NULL; + } + if (author) landmark->author = g_strdup (author); + + return TRUE; +} + +static void landmark_url_foreach_free (gpointer data) +{ + g_return_if_fail(data); + + LocationLandmarkUrl *url = (LocationLandmarkUrl *)data; + + location_landmark_url_free (url); +} + +static void landmark_foreach_url_copy (gpointer data, gpointer user_data) +{ + g_return_if_fail(data); + g_return_if_fail(user_data); + + LocationLandmarkUrl *url = (LocationLandmarkUrl *)data; + LocationLandmark *landmark = (LocationLandmark *) user_data; + + if(!url || !landmark) return; + + landmark->url = g_list_append(landmark->url, url); +} + +EXPORT_API gboolean +location_landmark_set_url (LocationLandmark *landmark, GList *url) +{ + g_return_val_if_fail(landmark, FALSE); + + if (landmark->url) { + g_list_free_full(landmark->url, landmark_url_foreach_free); + landmark->url = NULL; + } + + if (url) g_list_foreach (url, landmark_foreach_url_copy, landmark); + + return TRUE; +} + +static void landmark_foreach_copy_category (gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + g_return_if_fail (user_data); + + gchar *category_name = (gchar *)data; + LocationLandmark *landmark = (LocationLandmark *) user_data; + + landmark->category = g_list_append (landmark->category, g_strdup(category_name)); +} + +static void landmark_free_category (gpointer data) +{ + g_return_if_fail (data); + + gchar * category_name = (gchar *)data; + + g_free (category_name); +} + +EXPORT_API gboolean +location_landmark_set_category (LocationLandmark *landmark, GList *category) +{ + g_return_val_if_fail(landmark, FALSE); + + if (landmark->category) { + g_list_free_full(landmark->category, landmark_free_category); + landmark->category = NULL; + } + + if (category) g_list_foreach ((GList*) category, landmark_foreach_copy_category, landmark); + + return TRUE; +} + +EXPORT_API gboolean +location_landmark_set_phone_number (LocationLandmark *landmark, const gchar *number) +{ + g_return_val_if_fail(landmark, FALSE); + g_return_val_if_fail(number, FALSE); + + if (landmark->phone_number) { + g_free(landmark->phone_number); + landmark->phone_number = NULL; + } + if (number) landmark->phone_number = g_strdup (number); + + return TRUE; +} + +EXPORT_API gboolean +location_landmark_set_property(LocationLandmark *landmark, gconstpointer key, gconstpointer value) +{ + g_return_val_if_fail(landmark, FALSE); + g_return_val_if_fail(key, FALSE); + if (!landmark->properties) return FALSE; + + if (value) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert(landmark->properties, re_key, re_val); + } + else g_hash_table_remove (landmark->properties, key); + + return TRUE; +} + +EXPORT_API gchar * +location_landmark_url_get_url_path (const LocationLandmarkUrl *url) +{ + g_return_val_if_fail (url, NULL); + + return url->path; +} + +EXPORT_API gchar * +location_landmark_url_get_description (const LocationLandmarkUrl *url) +{ + g_return_val_if_fail (url, NULL); + + return url->desc; +} + +EXPORT_API gboolean +location_landmark_url_set_url_path (LocationLandmarkUrl *url, const gchar *path) +{ + g_return_val_if_fail (url, FALSE); + + if (url->path) { + g_free(url->path); + url->path = NULL; + } + + if (path) url->path = g_strdup (path); + + return TRUE; +} + +EXPORT_API gboolean +location_landmark_url_set_description (LocationLandmarkUrl *url, const gchar *desc) +{ + g_return_val_if_fail (url, FALSE); + + if (url->desc) { + g_free(url->desc); + url->desc = NULL; + } + + if (desc) url->desc = g_strdup (desc); + + return TRUE; +} + +EXPORT_API LocationLandmarkUrl * +location_landmark_url_new (void) +{ + LocationLandmarkUrl *url = g_slice_new0 (LocationLandmarkUrl); + if(!url) return NULL; + + + return url; +} + +EXPORT_API void +location_landmark_url_free (LocationLandmarkUrl * url) +{ + g_return_if_fail (url); + + + location_landmark_url_set_url_path(url, NULL); + location_landmark_url_set_description(url, NULL); + + g_slice_free(LocationLandmarkUrl, url); +} + +EXPORT_API LocationLandmarkUrl * +location_landmark_url_copy (const LocationLandmarkUrl *url) +{ + g_return_val_if_fail(url, NULL); + + LocationLandmarkUrl *new_url = location_landmark_url_new(); + + location_landmark_url_set_url_path(new_url, location_landmark_url_get_url_path(url)); + location_landmark_url_set_description(new_url, location_landmark_url_get_description(url)); + + return new_url; +} + +EXPORT_API LocationLandmark * +location_landmark_new (void) +{ + LocationLandmark *landmark = g_slice_new0 (LocationLandmark); + if (!landmark) return NULL; + + landmark->properties = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + + return landmark; +} + +EXPORT_API LocationLandmark * +location_landmark_copy (const LocationLandmark *landmark) +{ + g_return_val_if_fail (landmark, NULL); + + LocationLandmark *new_landmark = location_landmark_new(); + if (!new_landmark) return NULL; + + location_landmark_set_id(new_landmark, location_landmark_get_id(landmark)); + location_landmark_set_name (new_landmark, location_landmark_get_name (landmark)); + location_landmark_set_position (new_landmark, location_landmark_get_position(landmark)); + location_landmark_set_address (new_landmark, location_landmark_get_address (landmark)); + location_landmark_set_description (new_landmark, location_landmark_get_description(landmark)); + location_landmark_set_timestamp (new_landmark, location_landmark_get_timestamp(landmark)); + location_landmark_set_priority (new_landmark, location_landmark_get_priority(landmark)); + location_landmark_set_bounding_box (new_landmark, location_landmark_get_bounding_box(landmark)); + location_landmark_set_author (new_landmark, location_landmark_get_author(landmark)); + location_landmark_set_url(new_landmark, location_landmark_get_url(landmark)); + + return new_landmark; +} + +EXPORT_API void +location_landmark_free (LocationLandmark *landmark) +{ + g_return_if_fail (landmark); + + location_landmark_set_id(landmark, 0); + location_landmark_set_name (landmark, NULL); + location_landmark_set_position (landmark, NULL); + location_landmark_set_address (landmark, NULL); + location_landmark_set_description (landmark, NULL); + location_landmark_set_timestamp (landmark, 0); + location_landmark_set_priority (landmark, 0); + location_landmark_set_bounding_box (landmark, NULL); + location_landmark_set_author (landmark, NULL); + location_landmark_set_url(landmark, NULL); + + g_slice_free (LocationLandmark, landmark); +} diff --git a/location/map-service/location-landmark.h b/location/map-service/location-landmark.h new file mode 100644 index 0000000..44c0754 --- /dev/null +++ b/location/map-service/location-landmark.h @@ -0,0 +1,147 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_LANDMARK_H__ +#define __LOCATION_LANDMARK_H__ + +#include + +G_BEGIN_DECLS + +/** + * @file location-landmark.h + * @brief This file contains the internal definitions and structures related to Landmark. + */ + +/** + * @addtogroup LocationMapServicePOI + * @{ + * @defgroup LocationMapServiceLandmark Location Landmark + * @brief This provides structure, enumeration and APIs for Landmark + * @addtogroup LocationMapServiceLandmark + * @{ + */ + +/** + * @brief Create a new Landmark + */ +LocationLandmark *location_landmark_new (void); + +/** + * @brief Copy the given Landmark + */ +LocationLandmark *location_landmark_copy (const LocationLandmark *landmark); + +/** + * @brief Free the given Landmark + */ +void location_landmark_free (LocationLandmark *landmark); + +/** + * @brief Get the ID of the given landmark + */ +guint location_landmark_get_id (const LocationLandmark *landmark); + +/** + * @brief Get the name of the given landmark + */ +gchar *location_landmark_get_name (const LocationLandmark *landmark); +/** + * @brief Get the position in the given landmark + */ +LocationPosition *location_landmark_get_position (const LocationLandmark *landmark); +/** + * @brief Get the address of the given landmark + */ +LocationAddress *location_landmark_get_address (const LocationLandmark *landmark); +/** + * @brief Get the description of the given landmark + */ +gchar *location_landmark_get_description (const LocationLandmark *landmark); +/** + * @brief Get the timestamp of the given landmark + */ +guint location_landmark_get_timestamp (const LocationLandmark *landmark); +/** + * @brief Get the priority of the given landmark + */ +guint location_landmark_get_priority (const LocationLandmark *landmark); +/** + * @brief Get the bounding box of the given landmark + */ +LocationBoundary *location_landmark_get_bounding_box (const LocationLandmark *landmark); +/** + * @brief Get the author of the given landmark + */ +gchar *location_landmark_get_author (const LocationLandmark *landmark); +/** + * @brief Get the list of urls of the given landmark + */ +GList *location_landmark_get_url (const LocationLandmark *landmark); +/** + * @brief Get the categories of the given landmark + */ +GList *location_landmark_get_category (const LocationLandmark *landmark); +/** + * @brief Get the phone number of the given landmark + */ +gchar *location_landmark_get_phone_number (const LocationLandmark *landmark); +/** + * @brief Get the property keys of the given landmark + */ +GList *location_landmark_get_property_key (const LocationLandmark *landmark); + +/** + * @brief Get the property data of the given landmark + */ +gconstpointer location_landmark_get_property (const LocationLandmark *landmark, gconstpointer key); + +/** + * @brief Create a new #LocationLandmarkUrl + */ +LocationLandmarkUrl * location_landmark_url_new (void); + +/** + * @brief Free a #LocationLandmarkUrl + */ +void location_landmark_url_free (LocationLandmarkUrl *url); + +/** + * @brief Copy a #LocationLandmarkUrl + */ +LocationLandmarkUrl *location_landmark_url_copy (const LocationLandmarkUrl *url); + +/** + * @brief Get the url path of the given #LocationLandmarkUrl + */ +gchar *location_landmark_url_get_url_path (const LocationLandmarkUrl *url); +/** + * @brief Get the url's description of the given #LocationLandmarkUrl + */ +gchar *location_landmark_url_get_description (const LocationLandmarkUrl *url); + +/** + * @} @} + */ + +G_END_DECLS + +#endif diff --git a/location/map-service/location-map-ielement.c b/location/map-service/location-map-ielement.c new file mode 100644 index 0000000..147936e --- /dev/null +++ b/location/map-service/location-map-ielement.c @@ -0,0 +1,265 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-log.h" +#include "location-map-ielement.h" + +static void +location_map_ielement_base_init (gpointer g_class) +{ + static gboolean is_initialized = FALSE; + + if (is_initialized){ + /* add properties and signals to the interface here */ + + is_initialized = TRUE; + } +} + +GType +location_map_ielement_get_type (void) +{ + static GType iface_type = 0; + + if (iface_type == 0) { + static const GTypeInfo info = { + sizeof (LocationMapIElementInterface), + location_map_ielement_base_init, /* base_init */ + NULL /* base_finalize */ + }; + + iface_type = g_type_register_static (G_TYPE_INTERFACE, "LocationMapIElement", + &info, 0); + } + + return iface_type; +} + +int +location_map_ielement_get_geocode (LocationMapIElement *self, + const LocationAddress *address, + const LocationMapPref *svc_pref, + GList **position_list, + GList **accuracy_list) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (address, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_geocode, LOCATION_ERROR_NOT_AVAILABLE); + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_geocode (self, address, svc_pref, position_list, accuracy_list); +} + +int +location_map_ielement_get_geocode_freeform (LocationMapIElement *self, + const gchar *address, + const LocationMapPref *svc_pref, + GList **position_list, + GList **accuracy_list) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (address, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_geocode_freeform, LOCATION_ERROR_NOT_AVAILABLE); + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_geocode_freeform (self, address, svc_pref, position_list, accuracy_list); +} + +int +location_map_ielement_get_reversegeocode (LocationMapIElement *self, + const LocationPosition *position, + const LocationMapPref *svc_pref, + LocationAddress **address, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (address, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (accuracy, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_reversegeocode, LOCATION_ERROR_NOT_AVAILABLE); + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_reversegeocode (self, position, svc_pref, address, accuracy); +} + +int +location_map_ielement_get_geocode_async (LocationMapIElement *self, + const LocationAddress *address, + const LocationMapPref *svc_pref, + LocationPositionCB callback, + gpointer userdata) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (address, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (callback, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_geocode_async, LOCATION_ERROR_NOT_AVAILABLE); + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_geocode_async (self, address, svc_pref, callback, userdata); +} + +int +location_map_ielement_get_geocode_freeform_async (LocationMapIElement *self, + const gchar *address, + const LocationMapPref *svc_pref, + LocationPositionCB callback, + gpointer userdata) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (address, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (callback, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_geocode_freeform_async, LOCATION_ERROR_NOT_AVAILABLE); + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_geocode_freeform_async (self, address, svc_pref, callback, userdata); +} + +int +location_map_ielement_get_reversegeocode_async (LocationMapIElement *self, + const LocationPosition *position, + const LocationMapPref *svc_pref, + LocationAddressCB callback, + gpointer userdata) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (callback, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_reversegeocode_async, LOCATION_ERROR_NOT_AVAILABLE); + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_reversegeocode_async (self, position, svc_pref, callback, userdata); +} + +int +location_map_ielement_search_poi (LocationMapIElement *self, + const LocationPOIFilter * filter, const LocationPosition *position, + const LocationMapPref *svc_pref, const LocationPOIPreference * pref, + LocationPOICB cb, const gpointer user_data, guint * req_id) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->search_poi, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->search_poi(self, + filter, position, svc_pref, pref, cb, user_data, req_id); +} + +int +location_map_ielement_search_poi_by_area (LocationMapIElement *self, + const LocationPOIFilter * filter, const LocationBoundary * boundary, + const LocationMapPref *svc_pref, const LocationPOIPreference * pref, + LocationPOICB cb, const gpointer user_data, guint * req_id) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (boundary, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->search_poi_by_area, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->search_poi_by_area (self, + filter, boundary, svc_pref, pref, cb, user_data, req_id); +} + +int +location_map_ielement_search_poi_by_address (LocationMapIElement *self, + const LocationPOIFilter * filter, const LocationAddress * address, + const LocationMapPref *svc_pref, const LocationPOIPreference * pref, + LocationPOICB cb, const gpointer user_data, guint * req_id) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (address, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->search_poi_by_address, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->search_poi_by_address (self, + filter, address, svc_pref, pref, cb, user_data, req_id); +} + +int +location_map_ielement_search_poi_by_freeform (LocationMapIElement *self, const LocationPOIFilter * filter, + const gchar *freeform, const LocationMapPref *svc_pref, const LocationPOIPreference *pref, LocationPOICB cb, + const gpointer user_data, guint * req_id) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (freeform, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->search_poi_by_freeform, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->search_poi_by_freeform (self, + filter, freeform, svc_pref, pref, cb, user_data, req_id); +} + +int +location_map_ielement_cancel_poi_request (LocationMapIElement *self, guint req_id) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->cancel_poi_request, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->cancel_poi_request (self, req_id); +} + +int +location_map_ielement_request_route (LocationMapIElement *self, const LocationPosition *origin, + const LocationPosition *destination, GList *waypoint, + const LocationMapPref *svc_pref, const LocationRoutePreference *pref, LocationRouteCB cb, const gpointer user_data, guint *req_id) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (origin, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (destination, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->request_route, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->request_route (self, + origin, destination, waypoint, svc_pref, pref, cb, user_data, req_id); +} + +int +location_map_ielement_cancel_route_request (LocationMapIElement *self, guint req_id) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->cancel_route_request, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->cancel_route_request (self, req_id); +} + +gboolean +location_map_ielement_is_supported_provider_capability (LocationMapIElement *self, LocationMapServiceType type) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->is_supported_provider_capability, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->is_supported_provider_capability (self, type); +} + +int +location_map_ielement_get_provider_capability_key (LocationMapIElement *self, LocationMapServiceType type, GList **key) +{ + g_return_val_if_fail (LOCATION_MAP_IS_IELEMENT (self), LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_provider_capability_key, LOCATION_ERROR_NOT_AVAILABLE); + + return LOCATION_MAP_IELEMENT_GET_INTERFACE (self)->get_provider_capability_key (self, type, key); +} diff --git a/location/map-service/location-map-ielement.h b/location/map-service/location-map-ielement.h new file mode 100644 index 0000000..36f17d1 --- /dev/null +++ b/location/map-service/location-map-ielement.h @@ -0,0 +1,101 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_MAP_IELEMENT_H__ +#define __LOCATION_MAP_IELEMENT_H__ + +#include +#include +#include + +/** + * @file location-map-ielement.h + * @brief This file contains the internal definitions and structures related to location interface. + */ + +G_BEGIN_DECLS + +#define LOCATION_MAP_TYPE_IELEMENT (location_map_ielement_get_type ()) +#define LOCATION_MAP_IELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOCATION_MAP_TYPE_IELEMENT, LocationMapIElement)) +#define LOCATION_MAP_IS_IELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LOCATION_MAP_TYPE_IELEMENT)) +#define LOCATION_MAP_IELEMENT_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), LOCATION_MAP_TYPE_IELEMENT, LocationMapIElementInterface)) + +typedef struct _LocationMapIElement LocationMapIElement; +typedef struct _LocationMapIElementInterface LocationMapIElementInterface; + +typedef int (*TYPE_GET_GEOCODE)(LocationMapIElement *self, const LocationAddress *address, const LocationMapPref *svc_pref, GList **position_list, GList **accuracy_list); +typedef int (*TYPE_GET_GEOCODE_FREEFORM)(LocationMapIElement *self, const gchar *address, const LocationMapPref *svc_pref, GList **position_list, GList **accuracy_list); +typedef int (*TYPE_GET_REVERSEGEOCODE)(LocationMapIElement *self, const LocationPosition *position, const LocationMapPref *svc_pref, LocationAddress **address, LocationAccuracy **accuracy); +typedef int (*TYPE_GET_GEOCODE_ASYNC)(LocationMapIElement *self, const LocationAddress *address, const LocationMapPref *svc_pref, LocationPositionCB callback, gpointer userdata); +typedef int (*TYPE_GET_GEOCODE_FREEFORM_ASYNC)(LocationMapIElement *self, const gchar *address, const LocationMapPref *svc_pref, LocationPositionCB callback, gpointer userdata); +typedef int (*TYPE_GET_REVERSEGEOCODE_ASYNC)(LocationMapIElement *self, const LocationPosition *position, const LocationMapPref *svc_pref, LocationAddressCB callback, gpointer userdata); +typedef int (*TYPE_SEARCH_POI) (LocationMapIElement *self, const LocationPOIFilter * filter, const LocationPosition *position, const LocationMapPref *svc_pref, const LocationPOIPreference * pref, LocationPOICB cb, const gpointer user_data, guint *req_id); +typedef int (*TYPE_SEARCH_POI_BY_AREA) (LocationMapIElement *self, const LocationPOIFilter *filter, const LocationBoundary * boundary, const LocationMapPref *svc_pref, const LocationPOIPreference * pref, LocationPOICB cb, const gpointer user_data, guint *req_id); +typedef int (*TYPE_SEARCH_POI_BY_ADDR) (LocationMapIElement *self, const LocationPOIFilter *filter, const LocationAddress * address, const LocationMapPref *svc_pref, const LocationPOIPreference * pref, LocationPOICB cb, const gpointer user_data, guint *req_id); +typedef int (*TYPE_SEARCH_POI_BY_FREEFORM) (LocationMapIElement *self, const LocationPOIFilter *filter, const gchar *freeform, const LocationMapPref *svc_pref, const LocationPOIPreference * pref, LocationPOICB cb, const gpointer user_data, guint *req_id); +typedef int (*TYPE_CANCEL_POI_REQUEST) (LocationMapIElement *self, guint req_id); +typedef int (*TYPE_REQUEST_ROUTE) (LocationMapIElement *self, const LocationPosition *origin, const LocationPosition *destination, GList *waypoint, const LocationMapPref *svc_pref, const LocationRoutePreference *pref, LocationRouteCB cb, const gpointer user_data, guint *req_id); +typedef int (*TYPE_CANCEL_ROUTE_REQUEST) (LocationMapIElement *self, guint req_id); +typedef gboolean (*TYPE_IS_SUPPORTED_PROVIDER_CAPABILITY) (LocationMapIElement *self, LocationMapServiceType type); +typedef int (*TYPE_GET_PROVIDER_CAPABILITY_KEY)(LocationMapIElement *self, LocationMapServiceType type, GList **key); + +struct _LocationMapIElementInterface +{ + GTypeInterface parent_iface; + + TYPE_GET_GEOCODE get_geocode; + TYPE_GET_GEOCODE_FREEFORM get_geocode_freeform; + TYPE_GET_REVERSEGEOCODE get_reversegeocode; + TYPE_GET_GEOCODE_ASYNC get_geocode_async; + TYPE_GET_GEOCODE_FREEFORM_ASYNC get_geocode_freeform_async; + TYPE_GET_REVERSEGEOCODE_ASYNC get_reversegeocode_async; + TYPE_SEARCH_POI search_poi; + TYPE_SEARCH_POI_BY_AREA search_poi_by_area; + TYPE_SEARCH_POI_BY_ADDR search_poi_by_address; + TYPE_SEARCH_POI_BY_FREEFORM search_poi_by_freeform; + TYPE_CANCEL_POI_REQUEST cancel_poi_request; + TYPE_REQUEST_ROUTE request_route; + TYPE_CANCEL_ROUTE_REQUEST cancel_route_request; + TYPE_IS_SUPPORTED_PROVIDER_CAPABILITY is_supported_provider_capability; + TYPE_GET_PROVIDER_CAPABILITY_KEY get_provider_capability_key; +}; + +GType location_map_ielement_get_type (void); + +int location_map_ielement_get_geocode (LocationMapIElement *self, const LocationAddress *address, const LocationMapPref *svc_pref, GList **position_list, GList **accuracy_list); +int location_map_ielement_get_geocode_freeform (LocationMapIElement *self, const gchar *address, const LocationMapPref *svc_pref, GList **position_list, GList **accuracy_list); +int location_map_ielement_get_reversegeocode (LocationMapIElement *self, const LocationPosition *position, const LocationMapPref *svc_pref, LocationAddress **address, LocationAccuracy **accuracy); +int location_map_ielement_get_geocode_async (LocationMapIElement *self, const LocationAddress *address, const LocationMapPref *svc_pref, LocationPositionCB callback, gpointer userdata); +int location_map_ielement_get_geocode_freeform_async (LocationMapIElement *self, const gchar *address, const LocationMapPref *svc_pref, LocationPositionCB callback, gpointer userdata); +int location_map_ielement_get_reversegeocode_async (LocationMapIElement *self, const LocationPosition *position, const LocationMapPref *svc_pref, LocationAddressCB callback, gpointer userdata); +int location_map_ielement_search_poi (LocationMapIElement *self, const LocationPOIFilter * filter, const LocationPosition *position, const LocationMapPref *svc_pref, const LocationPOIPreference * pref, LocationPOICB cb, const gpointer user_data, guint * req_id); +int location_map_ielement_search_poi_by_area (LocationMapIElement *self, const LocationPOIFilter * filter, const LocationBoundary * boundary, const LocationMapPref *svc_pref, const LocationPOIPreference * pref, LocationPOICB cb, const gpointer user_data, guint * req_id); +int location_map_ielement_search_poi_by_address (LocationMapIElement *self, const LocationPOIFilter * filter, const LocationAddress * address, const LocationMapPref *svc_pref, const LocationPOIPreference * pref, LocationPOICB cb, const gpointer user_data, guint * req_id); +int location_map_ielement_search_poi_by_freeform (LocationMapIElement *self, const LocationPOIFilter * filter, const gchar * freeform, const LocationMapPref *svc_pref, const LocationPOIPreference * pref, LocationPOICB cb, const gpointer user_data, guint * req_id); +int location_map_ielement_cancel_poi_request (LocationMapIElement *self, guint req_id); +int location_map_ielement_request_route (LocationMapIElement *self, const LocationPosition *origin, const LocationPosition *destination, GList *waypoint, const LocationMapPref *svc_pref, const LocationRoutePreference * pref, LocationRouteCB cb, const gpointer user_data, guint * req_id); +int location_map_ielement_cancel_route_request (LocationMapIElement *self, guint req_id); +gboolean location_map_ielement_is_supported_provider_capability (LocationMapIElement *self, LocationMapServiceType type); +int location_map_ielement_get_provider_capability_key (LocationMapIElement *self, LocationMapServiceType type, GList **key); + +G_END_DECLS + +#endif diff --git a/location/map-service/location-map-pref.c b/location/map-service/location-map-pref.c new file mode 100644 index 0000000..ac46346 --- /dev/null +++ b/location/map-service/location-map-pref.c @@ -0,0 +1,222 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "location-map-types.h" +#include "map-service.h" +#include "location-map-pref.h" + +struct _LocationMapPref { + gchar *provider_name; ///< Name of the service provier + gchar *language; ///< Language of the service preference. + gchar *country; ///< Country of the service preference. + gchar *distance_unit; ///< Distance unit of the service preference. + GHashTable *properties; ///< properties of the service preference. +}; + +EXPORT_API GList * +location_map_pref_get_property_key (const LocationMapPref *pref) +{ + g_return_val_if_fail (pref, NULL); + + if (!pref->properties) return NULL; + + return g_hash_table_get_keys (pref->properties); +} + +EXPORT_API gchar * +location_map_pref_get_language (const LocationMapPref *pref) +{ + g_return_val_if_fail (pref, NULL); + + return pref->language; +} + +EXPORT_API gchar * +location_map_pref_get_country (const LocationMapPref *pref) +{ + g_return_val_if_fail (pref, NULL); + + return pref->country; +} + +EXPORT_API gchar * +location_map_pref_get_distance_unit (const LocationMapPref *pref) +{ + g_return_val_if_fail (pref, NULL); + + return pref->distance_unit; +} + +EXPORT_API gconstpointer +location_map_pref_get_property (const LocationMapPref *pref, gconstpointer key) +{ + g_return_val_if_fail (pref, NULL); + g_return_val_if_fail (key, NULL); + if (!pref->properties) return NULL; + + return (gconstpointer) g_hash_table_lookup (pref->properties, key); +} + +EXPORT_API gchar * +location_map_pref_get_provider_name (const LocationMapPref *pref) +{ + g_return_val_if_fail (pref, NULL); + + return pref->provider_name; +} + +EXPORT_API gboolean +location_map_pref_set_provider_name (LocationMapPref *pref, const gchar *name) +{ + g_return_val_if_fail (pref, FALSE); + + if (pref->provider_name) { + g_free (pref->provider_name); + pref->provider_name = NULL; + } + + if (name) pref->provider_name = g_strdup ((gchar *)name); + + return TRUE; +} + +EXPORT_API gboolean +location_map_pref_set_language (LocationMapPref *pref, const gchar * language) +{ + g_return_val_if_fail (pref, FALSE); + + if (pref->language) { + g_free (pref->language); + pref->language = NULL; + } + + if (language) pref->language = g_strdup(language); + + return TRUE; +} + +EXPORT_API gboolean +location_map_pref_set_country (LocationMapPref *pref, const gchar *country) +{ + g_return_val_if_fail (pref, FALSE); + + if (pref->country) { + g_free (pref->country); + pref->country = NULL; + } + + if (country) pref->country = g_strdup(country); + + return TRUE; +} + + +EXPORT_API gboolean +location_map_pref_set_distance_unit (LocationMapPref *pref, const gchar * unit) +{ + g_return_val_if_fail (pref, FALSE); + + if (pref->distance_unit) { + g_free (pref->distance_unit); + pref->distance_unit = NULL; + } + + if (unit) pref->distance_unit = g_strdup (unit); + + return TRUE; +} + +EXPORT_API gboolean +location_map_pref_set_property (LocationMapPref *pref, gconstpointer key, gconstpointer value) +{ + g_return_val_if_fail (pref, FALSE); + g_return_val_if_fail (key, FALSE); + if (!pref->properties) return FALSE; + + if (value) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert (pref->properties, re_key, re_val); + } else g_hash_table_remove (pref->properties, key); + + return TRUE; +} + +EXPORT_API LocationMapPref * +location_map_pref_new (void) +{ + LocationMapPref *pref = g_slice_new0(LocationMapPref); + if (!pref) return NULL; + + pref->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + return pref; +} + +static void property_copy (gpointer key, gpointer value, gpointer user_data) +{ + g_return_if_fail (key); + g_return_if_fail (value); + g_return_if_fail (user_data); + + GHashTable *properties = (GHashTable *) user_data; + + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert (properties, re_key, re_val); +} + +EXPORT_API LocationMapPref * +location_map_pref_copy (LocationMapPref *pref) +{ + g_return_val_if_fail (pref, NULL); + + LocationMapPref *new_pref = location_map_pref_new(); + if (!new_pref) return NULL; + + location_map_pref_set_provider_name (new_pref, location_map_pref_get_provider_name(pref)); + location_map_pref_set_language (new_pref, location_map_pref_get_language(pref)); + location_map_pref_set_distance_unit (new_pref, location_map_pref_get_distance_unit(pref)); + + + g_hash_table_foreach (pref->properties, property_copy, new_pref->properties); + + return new_pref; +} + +EXPORT_API void +location_map_pref_free (LocationMapPref * pref) +{ + g_return_if_fail(pref); + + location_map_pref_set_provider_name (pref, NULL); + location_map_pref_set_language (pref, NULL); + location_map_pref_set_distance_unit (pref, NULL); + g_hash_table_destroy (pref->properties); + + g_slice_free (LocationMapPref, pref); + pref = NULL; +} diff --git a/location/map-service/location-map-pref.h b/location/map-service/location-map-pref.h new file mode 100644 index 0000000..bf2da81 --- /dev/null +++ b/location/map-service/location-map-pref.h @@ -0,0 +1,116 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_MAP_PREF_H__ +#define __LOCATION_MAP_PREF_H__ + +#include + +G_BEGIN_DECLS + +/** + * @file location-map-pref.h + * @brief This file contains the internal definitions and structures related to a service provider. + * @addtogroup LocationMapService + * @{ + * @defgroup LocationMapServiceProvider Service Provider + * @brief This represents preference and capability of Service providers + * @addtogroup LocationMapServiceProvider + * @{ + */ + +/** + * @brief Get provider name to be used in the service request + */ +gchar *location_map_pref_get_provider_name (const LocationMapPref *pref); + +/** + * @brief Get language to be used in the service request. + */ +gchar *location_map_pref_get_language (const LocationMapPref *pref); + +/** + * @brief Get country to be used in the service request. + */ +gchar *location_map_pref_get_country (const LocationMapPref *pref); + +/** + * @brief Get the preferred length unit to be used in the service request. + */ +gchar *location_map_pref_get_distance_unit (const LocationMapPref *pref); + +/** + * @brief Get available service of the service provider. + */ +GList *location_map_pref_get_property_key (const LocationMapPref *pref); + +/** + * @brief Get property to be used in the service request. + */ +gconstpointer location_map_pref_get_property (const LocationMapPref *pref, gconstpointer key); + +/** + * @brief Set provider's name to be used in the service request. + */ +gboolean location_map_pref_set_provider_name (LocationMapPref *pref, const gchar *name); + +/** + * @brief Set language to be used in the service request. + */ +gboolean location_map_pref_set_language (LocationMapPref *pref, const gchar *language); + +/** + * @brief Set country to be used in the service request. + */ +gboolean location_map_pref_set_country (LocationMapPref *pref, const gchar *country); + +/** + * @brief Get the preferred length unit to be used in the service request. + */ +gboolean location_map_pref_set_distance_unit (LocationMapPref *pref, const gchar * unit); + +/** + * @brief Set property to be used in the service request. + */ +gboolean location_map_pref_set_property (LocationMapPref *pref, gconstpointer key, gconstpointer value); + +/** + * @brief Create a new LocationMapPref. + */ +LocationMapPref * location_map_pref_new (void); + +/** + * @brief Copy a new LocationMapPref. + */ +LocationMapPref * location_map_pref_copy (LocationMapPref *pref); + +/** + * @brief Free a LocationMapPref. + */ +void location_map_pref_free (LocationMapPref *pref); + +/** + * @} @} + */ + +G_END_DECLS + +#endif /* __LOCATION_MAP_PREF_H__ */ diff --git a/location/map-service/location-map-service-ext.h b/location/map-service/location-map-service-ext.h new file mode 100644 index 0000000..0064d66 --- /dev/null +++ b/location/map-service/location-map-service-ext.h @@ -0,0 +1,40 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __LOCATION_MAP_SERVICE_EXT_H__ +#define __LOCATION_MAP_SERVICE_EXT_H__ + + +#include +#include +#include + +G_BEGIN_DECLS + +/** + * @file location-map-service-ext.h + * @brief This file contains the extensional headers. + */ + +G_END_DECLS + +#endif /* __LOCATION_MAP_SERVICE_EXT_H__ */ diff --git a/location/map-service/location-map-service.c b/location/map-service/location-map-service.c new file mode 100644 index 0000000..1b35f31 --- /dev/null +++ b/location/map-service/location-map-service.c @@ -0,0 +1,384 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "location.h" +#include "location-log.h" +#include "location-setting.h" +#include "location-map-ielement.h" +#include "location-map-pref.h" +#include "location-map-service.h" +#include "map-service.h" + +EXPORT_API LocationMapObject * +location_map_new (const char * provider) +{ + + LocationMapObject *self = NULL; + self = g_object_new (MAP_TYPE_SERVICE, "provider", provider, NULL); + return self; +} + +EXPORT_API int +location_map_free (LocationMapObject *obj) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + + g_object_unref (obj); + + return LOCATION_ERROR_NONE; +} + +static gboolean +is_connected_network() +{ + gboolean is_connected = TRUE; + int net_state = 0; + + net_state = location_setting_get_int(VCONFKEY_NETWORK_STATUS); + + LOCATION_LOGW("net_state[%d]", net_state); + if(net_state == VCONFKEY_NETWORK_OFF) { + is_connected = FALSE; + } + + return is_connected; + +} + +EXPORT_API int +location_map_get_position_from_address (LocationMapObject *obj, + const LocationAddress *address, + GList **position_list, + GList **accuracy_list) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + int ret = LOCATION_ERROR_NONE; + LocationMapPref *svc_pref = location_map_get_service_pref (obj); + + ret = location_map_ielement_get_geocode (LOCATION_MAP_IELEMENT(obj), address, svc_pref, position_list, accuracy_list); + location_map_pref_free(svc_pref); + + return ret; +} + +EXPORT_API int +location_map_get_position_from_freeformed_address (LocationMapObject *obj, + const gchar *address, + GList **position_list, + GList **accuracy_list) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + int ret = LOCATION_ERROR_NONE; + LocationMapPref *svc_pref = location_map_get_service_pref (obj); + + ret = location_map_ielement_get_geocode_freeform (LOCATION_MAP_IELEMENT(obj), address, svc_pref, position_list, accuracy_list); + location_map_pref_free(svc_pref); + + return ret; +} + +EXPORT_API int +location_map_get_address (LocationMapObject *obj, + LocationAddress **address, + LocationAccuracy **accuracy) +{ + return LOCATION_ERROR_NOT_SUPPORTED; +} + +EXPORT_API int +location_map_get_address_from_position (LocationMapObject *obj, + const LocationPosition *position, + LocationAddress **address, + LocationAccuracy **accuracy) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + int ret = LOCATION_ERROR_NONE; + LocationMapPref *svc_pref = location_map_get_service_pref (obj); + + ret = location_map_ielement_get_reversegeocode (LOCATION_MAP_IELEMENT(obj), position, svc_pref, address, accuracy); + location_map_pref_free(svc_pref); + + return ret; +} + +EXPORT_API int +location_map_get_position_from_address_async (LocationMapObject *obj, + const LocationAddress *address, + LocationPositionCB callback, + gpointer userdata) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + int ret = LOCATION_ERROR_NONE; + LocationMapPref *svc_pref = location_map_get_service_pref (obj); + + ret = location_map_ielement_get_geocode_async (LOCATION_MAP_IELEMENT(obj), address, svc_pref, callback, userdata); + location_map_pref_free(svc_pref); + + return ret; +} + + +EXPORT_API int +location_map_get_position_from_freeformed_address_async (LocationMapObject *obj, + const gchar *address, + LocationPositionCB callback, + gpointer userdata) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + int ret = LOCATION_ERROR_NONE; + LocationMapPref *svc_pref = location_map_get_service_pref (obj); + + ret = location_map_ielement_get_geocode_freeform_async (LOCATION_MAP_IELEMENT(obj), address, svc_pref, callback, userdata); + location_map_pref_free(svc_pref); + + return ret; +} + +EXPORT_API int +location_map_get_address_from_position_async (LocationMapObject *obj, + const LocationPosition *position, + LocationAddressCB callback, + gpointer userdata) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + int ret = LOCATION_ERROR_NONE; + LocationMapPref *svc_pref = location_map_get_service_pref (obj); + + ret = location_map_ielement_get_reversegeocode_async (LOCATION_MAP_IELEMENT(obj), position, svc_pref, callback, userdata); + location_map_pref_free(svc_pref); + + return ret; +} + +EXPORT_API int +location_map_search_poi (LocationMapObject *obj, + const LocationPOIFilter *filter, + const LocationPosition *position, + const LocationPOIPreference *pref, + LocationPOICB cb, gpointer user_data, guint * req_id) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (position, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + LocationMapPref *svc_pref = location_map_get_service_pref (obj); + + return location_map_ielement_search_poi (LOCATION_MAP_IELEMENT(obj), filter, position, svc_pref, pref, cb, user_data, req_id); +} + +EXPORT_API int +location_map_search_poi_by_area (LocationMapObject *obj, + const LocationPOIFilter *filter, + const LocationBoundary *boundary, + const LocationPOIPreference *pref, + LocationPOICB cb, gpointer user_data, guint * req_id) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (boundary, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + LocationMapPref *svc_pref = location_map_get_service_pref (obj); + + return location_map_ielement_search_poi_by_area (LOCATION_MAP_IELEMENT(obj), filter, boundary, svc_pref, pref, cb, user_data, req_id); +} + +EXPORT_API int +location_map_search_poi_by_address (LocationMapObject *obj, const LocationPOIFilter * filter, + const LocationAddress * address, const LocationPOIPreference * pref, + LocationPOICB cb, gpointer user_data, guint * req_id) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (address, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + LocationMapPref *svc_pref = location_map_get_service_pref (obj); + + return location_map_ielement_search_poi_by_address (LOCATION_MAP_IELEMENT(obj), filter, address, svc_pref, pref, cb, user_data, req_id); +} + +EXPORT_API int +location_map_search_poi_by_freeformed_address (LocationMapObject *obj, + const LocationPOIFilter *filter, + const gchar *address, + const LocationPOIPreference *pref, + LocationPOICB cb, gpointer user_data, guint *req_id) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (filter, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (address, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + LocationMapPref *svc_pref = location_map_get_service_pref (obj); + + return location_map_ielement_search_poi_by_freeform (LOCATION_MAP_IELEMENT(obj), filter, address, svc_pref, pref, cb, user_data, req_id); +} + +EXPORT_API int +location_map_cancel_poi_request (LocationMapObject *obj, guint req_id) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + return location_map_ielement_cancel_poi_request (LOCATION_MAP_IELEMENT(obj), req_id); +} + +EXPORT_API int +location_map_request_route (LocationMapObject *obj, LocationPosition *origin, LocationPosition *destination, + GList *waypoint, const LocationRoutePreference * pref, + LocationRouteCB cb, gpointer user_data, guint * req_id) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (origin, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (destination, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (pref, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (cb, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (req_id, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + LocationMapPref *svc_pref = location_map_get_service_pref (obj); + + return location_map_ielement_request_route (LOCATION_MAP_IELEMENT(obj), origin, destination, + waypoint, svc_pref, pref, cb, user_data, req_id); +} + +EXPORT_API int +location_map_cancel_route_request (LocationMapObject *obj, guint req_id) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + return location_map_ielement_cancel_route_request (LOCATION_MAP_IELEMENT(obj), req_id); +} + +EXPORT_API gboolean +location_map_is_supported_provider_capability (LocationMapObject *obj, LocationMapServiceType type) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + return location_map_ielement_is_supported_provider_capability (LOCATION_MAP_IELEMENT(obj), type); +} + +EXPORT_API int +location_map_get_provider_capability_key (LocationMapObject *obj, LocationMapServiceType type, GList **key) +{ + g_return_val_if_fail (obj, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (key, LOCATION_ERROR_PARAMETER); + g_return_val_if_fail (is_connected_network(), LOCATION_ERROR_NETWORK_NOT_CONNECTED); + + return location_map_ielement_get_provider_capability_key (LOCATION_MAP_IELEMENT(obj), type, key); +} + +EXPORT_API LocationMapPref * +location_map_get_service_pref (LocationMapObject *obj) +{ + g_return_val_if_fail (obj, NULL); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, NULL); + + return map_service_get_pref (obj); +} + +EXPORT_API gboolean +location_map_set_service_pref (LocationMapObject *obj, LocationMapPref *pref) +{ + g_return_val_if_fail (obj, FALSE); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (pref, FALSE); + + return map_service_set_pref (obj, pref); +} + +EXPORT_API GList * +location_map_get_supported_providers (LocationMapObject *obj) +{ + g_return_val_if_fail (obj, NULL); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + + return map_service_get_supported_providers (obj); +} + +EXPORT_API gchar * +location_map_get_default_provider (LocationMapObject *obj) +{ + g_return_val_if_fail (obj, NULL); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + + return map_service_get_default_provider(obj); +} + +EXPORT_API gboolean +location_map_set_provider (LocationMapObject *obj, gchar *provider) +{ + g_return_val_if_fail (obj, NULL); + g_return_val_if_fail (G_OBJECT_TYPE(obj) == MAP_TYPE_SERVICE, LOCATION_ERROR_NOT_AVAILABLE); + + return map_service_set_provider (obj, provider); +} + diff --git a/location/map-service/location-map-service.h b/location/map-service/location-map-service.h new file mode 100644 index 0000000..be1f701 --- /dev/null +++ b/location/map-service/location-map-service.h @@ -0,0 +1,1287 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __LOCATION_MAP_SERVICE_H__ +#define __LOCATION_MAP_SERVICE_H__ + + +#include +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +/** + * @file location-map-service.h + * @brief This file contains the Location API and related structure and enumeration. + */ +/** + * @addtogroup LocationFW + * @{ + * @defgroup LocationMapService Location Map Service API + * @brief This sub module provides the Location Map Service API. + * @addtogroup LocationMapService + * @{ + */ + +/** +* @brief +* Create Map Object. +* @remarks location_init should be called before. +* @pre None. +* @post None. +* @param [in] +* provider - map provider. A default provider will be provided if NULL. +*/ +LocationMapObject *location_map_new (const char *provider); + +/** +* @brief +* Free Map Object. +* @remarks location_map_new should be called before. +*/ +int location_map_free (LocationMapObject *obj); + +/** + * @brief + * Get current position information with estimate of the accuracy by using given address information. + * @remarks Out parameters are should be freed. + * @pre + * #location_init should be called before.\n + * Calling application must have an active data connection. + * @post None. + * @param [in] + * obj - a #LocationMapObject created by #location_map_new + * @param [in] + * address - a #LocationAddress + * @param [out] + * position_list - a list of #LocationPosition + * @param [out] + * accuracy_list - a list of #LocationAccuracy + * @return int + * @retval 0 Success. + * + * Please refer #LocationError for more information. + * @see + * location_map_get_position_from_address_async\n + * @par Example + * @code +#include +#include + +static void PrintPos (gpointer data, gpointer user_data) +{ + LocationPosition *pos = (LocationPosition *)data; + + if (pos) { + g_debug("time: [%d], latitude: [%f], longitude: [%f], altitude: [%f]\n", pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + location_position_free (pos); + } +} + +static void PrintAcc (gpointer data, gpointer user_data) +{ + LocationAccuracy *acc = (LocationAccuracy *)data; + + if (acc) { + g_debug("level: [%d], horizontal_accuracy: [%f], vertical_accuracy: [%f]\n", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_accuracy_free (acc); + } + +} + +static void PrintPos (gpointer data, gpointer user_data) +{ + LocationPosition *pos = (LocationPosition *)data; + + if (pos) { + g_debug("time: [%d], latitude: [%f], longitude: [%f], altitude: [%f]\n", pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + location_position_free (pos); + } +} + +static void PrintAcc (gpointer data, gpointer user_data) +{ + LocationAccuracy *acc = (LocationAccuracy *)data; + + if (acc) { + g_debug("level: [%d], horizontal_accuracy: [%f], vertical_accuracy: [%f]\n", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_accuracy_free (acc); + } +} + +int main (int argc, char *argv[]) +{ + LocationMapObject *loc = NULL; + int ret = LOCATION_ERROR_NONE; + + location_init (); + loc = location_map_new (NULL); + if(!loc){ + g_debug("location_map_new failed"); + return -1; + } + + GList *pos_list = NULL; + GList *acc_list = NULL; + LocationAddress *addr = NULL; + + addr = location_address_new ("1", "Post Street", NULL, "san jose", "ca", NULL, "95113"); + if (LOCATION_ERROR_NONE == location_map_get_position_from_address(loc, addr, &pos_list, &acc_list)) { + + } else g_warning ("SYNC>> position from address> failed"); + location_address_free (addr); + g_list_foreach (pos_list, PrintPos, NULL); + g_list_foreach (acc_list, PrintAcc, NULL); + g_list_free (pos_list); + g_list_free (acc_list); + location_map_free (loc); + return 0; +} + * @endcode + */ +int location_map_get_position_from_address (LocationMapObject *obj, const LocationAddress *address, GList **position_list, GList **accuracy_list); + +/** + * @brief + * Get current position information asynchronously with estimate of the accuracy by using given address information. + * @remarks None. + * @pre + * #location_init should be called before.\n + * Calling application must have glib or ecore main loop.\n + * Calling application must have an active data connection. + * @post None. + * @param [in] + * obj - a #LocationMapObject created by #location_map_new + * @param [in] + * address - a #LocationAddress + * @param [in] + * callback - A pointer of function which will be called after position is gained or when an error occurs. + * @param [in] + * userdata - data to pass to function + * @return int + * @retval 0 Success. + * + * Please refer #LocationError for more information. + * @see + * location_map_get_position_from_address\n + * @par Example + * @code +#include + +static void PrintPos (gpointer data, gpointer user_data) +{ + LocationPosition *pos = (LocationPosition *)data; + + if (pos) { + g_debug("time: [%d], latitude: [%f], longitude: [%f], altitude: [%f]\n", pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + } +} + +static void PrintAcc (gpointer data, gpointer user_data) +{ + LocationAccuracy *acc = (LocationAccuracy *)data; + + if (acc) { + g_debug("level: [%d], horizontal_accuracy: [%f], vertical_accuracy: [%f]\n", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } +} +static void +cb_position_from_address (LocationError error, GList *position_list, GList *accuracy_list, gpointer userdata) +{ + if (position_list && accuracy_list) { + g_list_foreach (position_list, PrintPos); + g_list_foreach (accuracy_list, PrintAcc); + } +} + +void get_position_from_address(LocationMapObject* loc) +{ + LocationAddress *addr = location_address_new ("1", "Post Street", NULL, "san jose", "ca", NULL, "95113"); + //Calling application must have an active data connection before using this function. + if (LOCATION_ERROR_NONE == location_map_get_position_from_address_async(loc, addr, cb_position_from_address, loc)) + g_debug("location_map_get_position_from_address_async() success"); + else g_warning ("location_map_get_position_from_address_async() failed"); + location_address_free (addr); +} + * @endcode + */ +int location_map_get_position_from_address_async (LocationMapObject *obj, const LocationAddress *address, LocationPositionCB callback, gpointer userdata); + +/** + * @brief + * Get current position information with estimate of the accuracy by using given free-formed address string. + * @remarks Out parameters are should be freed. + * @pre + * #location_init should be called before.\n + * Calling application must have an active data connection. + * @post None. + * @param [in] + * obj - a #LocationMapObject created by #location_map_new + * @param [in] + * address - Free-formed address string to be used + * @param [out] + * position_list - a list of #LocationPosition + * @param [out] + * accuracy_list - a list of #LocationAccuracy + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see + * location_map_get_position_from_freeformed_address_async\n + * @par Example + * @code +#include +#include + +static void PrintPos (gpointer data, gpointer user_data) +{ + LocationPosition *pos = (LocationPosition *)data; + + if (pos) { + g_debug("time: [%d], latitude: [%f], longitude: [%f], altitude: [%f]\n", pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + location_position_free (pos); + } +} + +static void PrintAcc (gpointer data, gpointer user_data) +{ + LocationAccuracy *acc = (LocationAccuracy *)data; + + if (acc) { + g_debug("level: [%d], horizontal_accuracy: [%f], vertical_accuracy: [%f]\n", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_accuracy_free (acc); + } +} + +static void PrintPos (gpointer data, gpointer user_data) +{ + LocationPosition *pos = (LocationPosition *)data; + + if (pos) { + g_debug("time: [%d], latitude: [%f], longitude: [%f], altitude: [%f]\n", pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + location_position_free (pos); + } +} + +static void PrintAcc (gpointer data, gpointer user_data) +{ + LocationAccuracy *acc = (LocationAccuracy *)data; + + if (acc) { + g_debug("level: [%d], horizontal_accuracy: [%f], vertical_accuracy: [%f]\n", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_accuracy_free (acc); + } +} + +int main (int argc, char *argv[]) +{ + LocationMapObject *loc = NULL; + int ret = LOCATION_ERROR_NONE; + + location_init (); + loc = location_map_new (NULL); + if(!loc){ + g_debug("location_map_new failed"); + return -1; + } + + GList *pos_list = NULL; + GList *acc_list = NULL; + char* addr_str = g_strdup("4 N 2nd Street 95113"); + + //Calling application must have an active data connection before using this function. + if (LOCATION_ERROR_NONE == location_map_get_position_from_freeformed_address(loc, addr_str, &pos_list, &acc_list)) { + g_list_foreach (pos_list, PrintPos, NULL); + g_list_foreach (acc_list, PrintAcc, NULL); + g_list_free (pos_list); + g_list_free (acc_list); + } else g_warning ("SYNC>> position from freeformed address> failed"); + g_free(addr_str); + + location_free (loc); + return 0; +} + * @endcode + */ +int location_map_get_position_from_freeformed_address (LocationMapObject *obj, const gchar *address, GList **position_list, GList **accuracy_list); + +/** + * @brief + * Get current position information asynchronously with estimate of the accuracy by using given free-formed address string. + * @remarks None. + * @pre + * #location_init should be called before.\n + * Calling application must have glib or ecore main loop.\n + * Calling application must have an active data connection. + * @post None. + * @param [in] + * obj - a #LocationMapObject created by #location_map_new + * @param [in] + * address - Free-formed address string to be used + * @param [in] + * callback - A pointer of function which will be called after position is gained or when an error occurs. + * @param [in] + * userdata - data to pass to function + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see + * location_map_get_position_from_freeformed_address\n + * @par Example + * @code +#include +#include + +static void PrintPos (gpointer data, gpointer user_data) +{ + LocationPosition *pos = (LocationPosition *)data; + + if (pos) { + g_debug("time: [%d], latitude: [%f], longitude: [%f], altitude: [%f]\n", pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + } +} + +static void PrintAcc (gpointer data, gpointer user_data) +{ + LocationAccuracy *acc = (LocationAccuracy *)data; + + if (acc) { + g_debug("level: [%d], horizontal_accuracy: [%f], vertical_accuracy: [%f]\n", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } +} + +static void +cb_position_from_freeformed_address (LocationError error, GList *position_list, GList *accuracy_list, gpointer userdata) +{ + if (position_list && accuracy_list) { + g_list_foreach (position_list, PrintPos); + g_list_foreach (accuracy_list, PrintAcc); + } +} + +void get_position_from_address(LocationMapObject* loc) +{ + gchar *addr_str = g_strdup("4 N 2nd Street 95113"); + //Calling application must have an active data connection before using this function. + if (LOCATION_ERROR_NONE == location_map_get_position_from_freeformed_address_async(loc, addr_str, cb_position_from_freeformed_address, loc)) + g_debug("location_map_get_position_from_freeformed_address_async() success"); + else g_warning ("location_map_get_position_from_freeformed_address_async() failed"); + g_free(addr_str); + +} + * @endcode + */ +int location_map_get_position_from_freeformed_address_async (LocationMapObject *obj, const gchar *address, LocationPositionCB callback, gpointer userdata); + +/** + * @brief + * Get current address information with estimate of the accuracy by using given position information. + * @remarks Out parameters are should be freed. + * @pre + * #location_init should be called before.\n + * Calling application must have an active data connection. + * @post None. + * @param [in] + * obj - a #LocationMapObject created by #location_map_new + * @param [in] + * position - a #LocationPosition + * @param [out] + * address - a new #LocationAddress + * @param [out] + * accuracy - a new #LocationAccuracy + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see + * location_map_get_address_from_position_async\n + * @par Example + * @code +#include +#include +static GMainLoop *loop = NULL; + +int +main (int argc, char *argv[]) +{ + LocationMapObject *loc = NULL; + int ret = LOCATION_ERROR_NONE; + + location_init (); + + loop = g_main_loop_new (NULL, TRUE); + + loc = location_map_new (NULL); + if(!loc){ + g_debug("location_map_new failed"); + return -1; + } + + LocationPosition *pos = NULL; + LocationAccuracy *acc = NULL; + LocationAddress *addr = NULL; + + //Calling application must have an active data connection before using this function. + pos = location_position_new (0, 37.257809, 127.056383, 0, LOCATION_STATUS_2D_FIX); + if (LOCATION_ERROR_NONE == location_map_get_address_from_position(loc, pos, &addr, &acc)) { + g_debug ("SYNC>> address from position> %s %s %s %s %s %s %s", + addr->building_number, addr->street, addr->district, addr->city, addr->state, addr->postal_code, addr->country_code); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_address_free(addr); + location_accuracy_free(acc); + } else g_warning ("SYNC>> address from position> failed"); + location_position_free (pos); + location_map_free (loc); +} + * @endcode + */ +int location_map_get_address_from_position (LocationMapObject *obj, const LocationPosition *position, LocationAddress **address, LocationAccuracy **accuracy); + +/** + * @brief + * Get current address information asynchronously with estimate of the accuracy by using given position information. + * @remarks None. + * @pre + * #location_init should be called before.\n + * Calling application must have glib or ecore main loop.\n + * Calling application must have an active data connection. + * @post None. + * @param [in] + * obj - a #LocationMapObject created by #location_map_new + * @param [in] + * position - a #LocationPosition + * @param [in] + * callback - A pointer of function which will be called after address is gained or when an error occurs. + * @param [in] + * userdata - data to pass to function + * @return int + * @retval 0 Success + * + * Please refer #LocationError for more information. + * @see + * location_map_get_address_from_position\n + * @par Example + * @code +#include +#include +static GMainLoop *loop = NULL; + +static void +cb_address_from_position (LocationError error, LocationAddress *addr, LocationAccuracy *acc, gpointer userdata) +{ + g_debug ("ASYNC>> location_map_get_address_from_position_async> %s %s %s %s %s %s %s", + addr->building_number, addr->street, addr->district, addr->city, addr->state, addr->postal_code, addr->country_code); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +void get_address_from_position(LocationMapObject* loc) +{ + LocationPosition *pos = location_position_new (0, 37.257809, 127.056383, 0, LOCATION_STATUS_2D_FIX); + //Calling application must have an active data connection before using this function. + if (LOCATION_ERROR_NONE == location_map_get_address_from_position_async(loc, pos, cb_address_from_position, loc)) + g_debug("location_map_get_address_from_position_async() success"); + else g_warning ("location_map_get_address_from_position_async() failed"); + location_position_free (pos); +} + * @endcode + */ +int location_map_get_address_from_position_async (LocationMapObject *obj, const LocationPosition *position, LocationAddressCB callback, gpointer userdata); + +/** + * @brief Request a search service from service provider. + * @remarks refer #LocationLandmark + * @pre #location_init should be called before.\n + * #location_poi_pref_new should be set before. + * @post None. + * @param [in] obj - a #LocationMapObject created by #location_map_new + * @param [in] filter - a #LocaitonPOIFilter created by #location_poi_filter_new + * @param [in] position - a #LocationPosition + * @param [in] pref - a #LocationPOIPreference created by #location_poi_pref_new + * @param [in] cb - #LocationPOICB + * @param [in] user_data - data to pass to function + * @param [out] req_id - a guint + * @return int + * @retval 0 Success + * Please refer #LocationError for more information. + * @par Example + * @code +#include +#include + +static GMainLoop *loop = NULL; + +void PrintLandmarkCb (gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + + LocationLandmark *landmark = (LocationLandmark *)data; + + g_debug ("id[%d], Priority[%d], Name:[%s], Author[%s], Phone[%s], Category[%s]\n", location_landmark_get_id (landmark), + location_landmark_get_priority(landmark), + location_landmark_get_name(landmark), + location_landmark_get_author(landmark), + location_landmark_get_phone_number(landmark), + location_landmark_get_category(landmark)); +} + +static void poi_cb(LocationError error, guint req_id, GList * landmark_list, gchar * error_code, gchar * error_msg, gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE || landmark_list == NULL) { + g_debug ("Fail to get poi. Error[%d], ErrCode[%s], ErrMsg[%s]", error, error_code, error_msg); + return; + } + g_list_foreach (landmark_list, PrintLandmarkCb, NULL); +} + +void search_poi(LocationMapObject* loc) +{ + int ret = 0; + guint req_id = 0; + LocationPosition *pos = location_position_new (0, 37.257809, 127.056383, 0, LOCATION_STATUS_2D_FIX); + LocationPOIFilter *filter = location_poi_filter_new(); + LocationPOIPreference *pref = location_poi_pref_new(); + + location_poi_filter_set(filter, "CATEGORY", "restaurant"); + + location_poi_pref_set_max_result(pref, 5); + location_poi_pref_set_sort_by(pref, "name"); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_map_search_poi (loc, filter, pos, pref, poi_cb, loc, &req_id); + if (ret != LOCATION_ERROR_NONE) { + g_debug("Fail to get poi. Error[%d]", ret); + } + + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_position_free(pos); + +} + * @endcode + */ +int location_map_search_poi (LocationMapObject *obj, const LocationPOIFilter * filter, const LocationPosition *position, const LocationPOIPreference * pref, LocationPOICB cb, gpointer user_data, guint * req_id); + +/** + * @brief Request a search service with area filter from service provider. + * @remarks refer #LocationLandmark + * @pre #location_init should be called before.\n + * #location_poi_pref_new should be set before. + * @post None. + * @param [in] obj - a #LocationMapObject created by #location_map_new + * @param [in] filter - a #LocaitonPOIFilter created by #location_poi_filter_new + * @param [in] boundary - a #LocationBoundary + * @param [in] pref - a #LocationPOIPreference created by #location_poi_pref_new + * @param [in] cb - #LocationPOICB + * @param [in] user_data - data to pass to function + * @param [out] req_id - a guint + * @return int + * @retval 0 Success + * Please refer #LocationError for more information. + * @par Example + * @code +#include +#include + +static GMainLoop *loop = NULL; + +void PrintLandmarkCb (gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + + LocationLandmark *landmark = (LocationLandmark *)data; + + g_debug ("id[%d], Priority[%d], Name:[%s], Author[%s], Phone[%s], Category[%s]\n", location_landmark_get_id (landmark), + location_landmark_get_priority(landmark), + location_landmark_get_name(landmark), + location_landmark_get_author(landmark), + location_landmark_get_phone_number(landmark), + location_landmark_get_category(landmark)); +} + +static void poi_cb(LocationError error, guint req_id, GList * landmark_list, gchar * error_code, gchar * error_msg, gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE || landmark_list == NULL) { + g_debug ("Fail to get poi. Error[%d], ErrCode[%s], ErrMsg[%s]", error, error_code, error_msg); + return; + } + g_list_foreach (landmark_list, PrintLandmarkCb, NULL); +} + +void search_poi(LocationMapObject* loc) +{ + int ret = 0; + guint req_id = 0; + + LocationPosition* rb = location_position_new (0, 37.300, -121.86, 0, LOCATION_STATUS_2D_FIX); + LocationPosition* lt = location_position_new (0, 37.360, -121.92, 0, LOCATION_STATUS_2D_FIX); + LocationBoundary *bbox = location_boundary_new_for_rect (lt, rb); + LocationPOIFilter *filter = location_poi_filter_new(); + LocationPOIPreference *pref = location_poi_pref_new(); + + location_poi_filter_set(filter, "CATEGORY", "restaurant"); + + location_poi_pref_set_max_result(pref, 5); + location_poi_pref_set_sort_by(pref, "name"); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_map_search_poi_by_area (loc, filter, bbox, pref, poi_cb, loc, &req_id); + if (ret != LOCATION_ERROR_NONE) { + g_debug("Fail to get poi. Error[%d]", ret); + } + + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_boundary_free (bbox); +} + * @endcode + */ +int location_map_search_poi_by_area (LocationMapObject *obj, const LocationPOIFilter * filter, const LocationBoundary * boundary, const LocationPOIPreference * pref, LocationPOICB cb, gpointer user_data, guint * req_id); + +/** + * @brief Request a search service with address filter from service provider. + * @remarks refer #LocationLandmark + * @pre #location_init should be called before.\n + * #location_poi_pref_new should be set before. + * @post None. + * @param [in] obj - a #LocationMapObject created by #location_map_new + * @param [in] filter - a #LocaitonPOIFilter created by #location_poi_filter_new + * @param [in] address - a #LocationAddress + * @param [in] pref - a #LocationPOIPreference created by #location_poi_pref_new + * @param [in] cb - #LocationPOICB + * @param [in] user_data - data to pass to function + * @param [out] req_id - a guint + * @return int + * @retval 0 Success + * Please refer #LocationError for more information. + * @par Example + * @code +#include +#include + +static GMainLoop *loop = NULL; + +void PrintLandmarkCb (gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + + LocationLandmark *landmark = (LocationLandmark *)data; + + g_debug ("id[%d], Priority[%d], Name:[%s], Author[%s], Phone[%s], Category[%s]\n", location_landmark_get_id (landmark), + location_landmark_get_priority(landmark), + location_landmark_get_name(landmark), + location_landmark_get_author(landmark), + location_landmark_get_phone_number(landmark), + location_landmark_get_category(landmark)); +} + +static void poi_cb(LocationError error, guint req_id, GList * landmark_list, gchar * error_code, gchar * error_msg, gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE || landmark_list == NULL) { + g_debug ("Fail to get poi. Error[%d], ErrCode[%s], ErrMsg[%s]", error, error_code, error_msg); + return; + } + g_list_foreach (landmark_list, PrintLandmarkCb, NULL); +} + +void search_poi(LocationMapObject* loc) +{ + int ret = 0; + guint req_id = 0; + + LocationAddress *addr = location_address_new ("1", "Post Street", NULL, "san jose", "ca", NULL, "95113"); + LocationPOIFilter *filter = location_poi_filter_new(); + LocationPOIPreference *pref = location_poi_pref_new(); + + location_poi_filter_set(filter, "CATEGORY", "restaurant"); + + location_poi_pref_set_max_result(pref, 5); + location_poi_pref_set_sort_by(pref, "name"); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_map_search_poi_by_address (loc, filter, addr, pref, poi_cb, loc, &req_id); + if (ret != LOCATION_ERROR_NONE) { + g_debug("Fail to get poi. Error[%d]", ret); + } + + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_address_free (addr); +} + * @endcode + */ +int location_map_search_poi_by_address (LocationMapObject *obj, const LocationPOIFilter * filter, const LocationAddress * addr, const LocationPOIPreference * pref, LocationPOICB cb, gpointer user_data, guint * req_id); + +/** + * @brief Request a search service with area filter from service provider. + * @remarks refer #LocationLandmark + * @pre #location_init should be called before.\n + * #location_poi_pref_new should be set before. + * @post None. + * @param [in] obj - a #LocationMapObject created by #location_map_new + * @param [in] filter - a #LocaitonPOIFilter created by #location_poi_filter_new + * @param [in] address - a freeformed address + * @param [in] pref - a #LocationPOIPreference created by #location_poi_pref_new + * @param [in] cb - #LocationPOICB + * @param [in] user_data - data to pass to function + * @param [out] req_id - a guint + * @return int + * @retval 0 Success + * Please refer #LocationError for more information. + * @par Example + * @code +#include +#include + +static GMainLoop *loop = NULL; + +void PrintLandmarkCb (gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + + LocationLandmark *landmark = (LocationLandmark *)data; + + g_debug ("id[%d], Priority[%d], Name:[%s], Author[%s], Phone[%s], Category[%s]\n", location_landmark_get_id (landmark), + location_landmark_get_priority(landmark), + location_landmark_get_name(landmark), + location_landmark_get_author(landmark), + location_landmark_get_phone_number(landmark), + location_landmark_get_category(landmark)); +} + +static void poi_cb(LocationError error, guint req_id, GList * landmark_list, gchar * error_code, gchar * error_msg, gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE || landmark_list == NULL) { + g_debug ("Fail to get poi. Error[%d], ErrCode[%s], ErrMsg[%s]", error, error_code, error_msg); + return; + } + g_list_foreach (landmark_list, PrintLandmarkCb, NULL); +} + +void search_poi(LocationMapObject* loc) +{ + int ret = 0; + guint req_id = 0; + + gchar *addr = g_strdup("4 N 2nd Street 95113"); + LocationPOIFilter *filter = location_poi_filter_new(); + LocationPOIPreference *pref = location_poi_pref_new(); + + location_poi_filter_set(filter, "CATEGORY", "restaurant"); + + location_poi_pref_set_max_result(pref, 5); + location_poi_pref_set_sort_by(pref, "name"); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_map_search_poi_by_freeformed_address (loc, filter, addr, pref, poi_cb, loc, &req_id); + if (ret != LOCATION_ERROR_NONE) { + g_debug("Fail to get poi. Error[%d]", ret); + } + + location_poi_filter_free(filter); + location_poi_pref_free(pref); + g_free (addr); +} + * @endcode + */ +int location_map_search_poi_by_freeformed_address (LocationMapObject *obj, const LocationPOIFilter * filter, const gchar * address, const LocationPOIPreference * pref, LocationPOICB cb, gpointer user_data, guint * req_id); + +/** + * @brief Cancel the previous poi search. + * @remarks refer #LocationLandmark + * @pre #location_map_search_poi should be called before. + * @post None. + * @param [in] obj - a #LocationMapObject created by #location_map_new + * @param [in] req_id - a poi request id returned by location_map_search_poi + * @return int + * @retval 0 Success + * Please refer #LocationError for more information. + * @par Example + * @code +#include +#include + +static GMainLoop *loop = NULL; + +void PrintLandmarkCb (gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + + LocationLandmark *landmark = (LocationLandmark *)data; + + g_debug ("id[%d], Priority[%d], Name:[%s], Author[%s], Phone[%s], Category[%s]\n", location_landmark_get_id (landmark), + location_landmark_get_priority(landmark), + location_landmark_get_name(landmark), + location_landmark_get_author(landmark), + location_landmark_get_phone_number(landmark), + location_landmark_get_category(landmark)); +} + +static void poi_cb(LocationError error, guint req_id, GList * landmark_list, gchar * error_code, gchar * error_msg, gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE || landmark_list == NULL) { + g_debug ("Fail to get poi. Error[%d], ErrCode[%s], ErrMsg[%s]", error, error_code, error_msg); + return; + } + g_list_foreach (landmark_list, PrintLandmarkCb, NULL); +} + +void search_poi(LocationMapObject* loc) +{ + int ret = 0; + guint req_id = 0; + + gchar *addr = g_strdup("4 N 2nd Street 95113"); + LocationPOIFilter *filter = location_poi_filter_new(); + LocationPOIPreference *pref = location_poi_pref_new(); + + location_poi_filter_set(filter, "CATEGORY", "restaurant"); + + location_poi_pref_set_max_result(pref, 5); + location_poi_pref_set_sort_by(pref, "name"); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_map_search_poi (loc, filter, addr, pref, poi_cb, loc, &req_id); + if (ret != LOCATION_ERROR_NONE) { + g_debug("Fail to get poi. Error[%d]", ret); + } + + ret = location_map_cancel_poi_request (loc, req_id); + if (ret != LOCATION_ERROR_NONE) { + g_debug("Fail to cancel poi request. Err[%d]", ret); + } + + location_poi_filter_free(filter); + location_poi_pref_free(pref); + g_free (addr); +} + * @endcode + */ +int location_map_cancel_poi_request (LocationMapObject *obj, guint req_id); + +/** + * @brief Request a route service from service provider. + * @remarks refer #LocationRoute, #LocationRouteSegment and #LocationRouteStep + * @pre #location_map_new should be called before. + * @post None. + * @param [in] obj - a #LocationMapObject created by #location_map_new + * @param [in] origin - a #LocationPosition + * @param [in] destination - a #LocationPosition + * @param [in] waypoint - a list of #LocationPosition + * const LocationRoutePreference * pref, LocationRouteCB cb, gpointer user_data, guint * req_id); + * @param [in] pref - a #LocationRoutePreference created by #location_route_pref_new + * @param [in] cb - a #LocationRouteCB + * @param [in] user_data - a gpointer + * @param [out] req_id - a guint + * @return int + * @retval 0 Success + * Please refer #LocationError for more information. + * @par Example + * @code +#include +#include + +static void free_waypoint (gpointer data) +{ + LocationPosition *pos = (LocationPosition *)data; + + if (pos) location_position_free(pos); +} + +static void __print_route_step (gpointer data, gpointer user_data) +{ + g_printf("+++Step begin\n"); + LocationRouteStep *step = (LocationRouteStep *)data; + + const LocationPosition *start = location_route_step_get_start_point(step); + gdouble start_lat = 0; + gdouble start_lon = 0; + if (start) { + start_lat = start->latitude; + start_lon = start->longitude; + } else { + g_printf("Step start position NULL\n"); + } + const LocationPosition *end = location_route_step_get_end_point(step); + gdouble end_lat = 0; + gdouble end_lon = 0; + if (end) { + end_lat = end->latitude; + end_lon = end->longitude; + } else { + g_printf("Step end postion NULL\n"); + } + const gchar *inst = location_route_step_get_instruction(step); + + g_printf("Step: start(%f/%f), end(%f/%f), instruction(%s)\n", start_lat, start_lon, end_lat, end_lon, inst); + + g_printf("---Step end\n"); +} + +static void print_route_segment (gpointer data, gpointer user_data) +{ + g_printf("++Segment begin\n"); + LocationRouteSegment *seg = (LocationRouteSegment *)data; + gdouble seg_dist = location_route_segment_get_distance(seg); + glong seg_duration = location_route_segment_get_duration(seg); + const LocationPosition *start = location_route_segment_get_start_point(seg); + gdouble start_lat = 0; + gdouble start_lon = 0; + if (start) { + start_lat = start->latitude; + start_lon = start->longitude; + } else { + g_printf("Segment start postion NULL\n"); + } + const LocationPosition *end = location_route_segment_get_end_point(seg); + gdouble end_lat = 0; + gdouble end_lon = 0; + if (end) { + end_lat = end->latitude; + end_lon = end->longitude; + } else { + g_printf("Segment end postion NULL\n"); + } + g_printf("Segment info: Distance[%f], Duration[%ld], start(%f/%f), end(%f/%f)\n", seg_dist, seg_duration, + start_lat, start_lon, end_lat, end_lon); + + GList *step_list = location_route_segment_get_route_step(seg); + GList *tmp_list = (GList *)step_list; + if (tmp_list) { + g_list_foreach(tmp_list, print_route_step, NULL); + } + g_printf("--Segment end\n"); +} + + +static void print_route_list (gpointer data, gpointer user_data) +{ + g_printf("+Route begin\n"); + LocationRoute *route = (LocationRoute *)data; + + const LocationPosition *start = location_route_get_origin(route); + gdouble start_lat = 0; + gdouble start_lon = 0; + if (start) { + start_lat = start->latitude; + start_lon = start->longitude; + } else { + g_printf("Route start position NULL\n"); + } + const LocationPosition *end = location_route_get_destination(route); + gdouble end_lat = 0; + gdouble end_lon = 0; + if (end) { + end_lat = end->latitude; + end_lon = end->longitude; + } else { + g_printf("Route end position NULL\n"); + } + g_printf("Route: start(%f/%f), end(%f/%f)\n", start_lat, start_lon, end_lat, end_lon); + + gdouble distance = location_route_get_total_distance(route); + const gchar *dis_unit = location_route_get_distance_unit(route); + glong duration = location_route_get_total_duration(route); + const LocationBoundary *bound = location_route_get_bounding_box(route); + if (bound && bound->type == LOCATION_BOUNDARY_RECT) { + g_printf("RECT left top[%f-%f], right bottom[%f-%f]\n", bound->rect.left_top->latitude, bound->rect.left_top->longitude, + bound->rect.right_bottom->latitude, bound->rect.right_bottom->longitude); + } else { + g_printf("route boundary not exist, or not RECT\n"); + } + g_printf ("Distance[%f], Distance unit[%s], Duration[%ld]\n", distance, dis_unit, duration); + + GList *seg_list = location_route_get_route_segment(route); + if (seg_list) { + g_list_foreach(seg_list, print_route_segment, NULL); + } + + g_printf("-Route end\n"); +} + +static void cb_route(LocationError error, guint req_id, GList * route_list, gchar * error_code, gchar * error_msg, gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE) { + g_printf("Failed :%d\n", error); + return; + } + + g_printf("Success, poi_list[0x%x] user_data[0x%x] req_id[%d]\n", (unsigned int)route_list, (unsigned int)userdata, req_id); + g_list_foreach (route_list, print_route_list, NULL); + + if (error_code && error_msg) { + g_printf("cb_route: error_code[%s], error_msg[%s]\n", error_code, error_msg); + } +} + +int request_route(LocationMapObject *loc) +{ + int ret = 0; + LocationPosition *origin = location_position_new(0, 37.564263, 126.974676, 0, LOCATION_STATUS_2D_FIX); // Seoul city hall + LocationPosition *destination = location_position_new(0, 37.557120, 126.992410, 0, LOCATION_STATUS_2D_FIX); // NamSan + + GList *waypoint = NULL; + LocationPosition *via_pos = location_position_new(0, 37.560950, 126.986240, 0, LOCATION_STATUS_2D_FIX); // Wangsimli + waypoint = g_list_append (waypoint, (gpointer)via_pos); + + LocationRoutePreference *pref = location_route_pref_new(); + gchar *type = g_strdup("FASTEST"); + location_route_pref_set_route_type(pref, type); + + ret = location_request_route(loc, origin, destination, waypoint, pref, cb_route, NULL, &req_id); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search route by address. Error[%d]\n", ret); + } else { + g_printf("Search Route successfully, req_id %d\n", req_id); + } + + g_free(type); + g_list_free_full (waypoint, free_waypoint); + location_position_free(origin); + location_position_free(destination); + location_route_pref_free(pref); + + return ret; + } + * @endcode + */ +int location_map_request_route (LocationMapObject *obj, LocationPosition *origin, LocationPosition *destination, GList *waypoint, const LocationRoutePreference * pref, LocationRouteCB cb, gpointer user_data, guint * req_id); + +/** + * @brief Cancel the previous route request. + * @remarks None + * @pre #location_map_request_route should be called before. + * @post None. + * @param [in] obj - a #LocationMapObject created by #location_map_new + * @param [in] req_id - a route request id returned by location_map_search_route + * @return int + * @retval 0 Success + * Please refer #LocationError for more information. + * @par Example + * @code +#include +#include + +int cancel_route_request (LocationMapObject *loc, guint req_id) +{ + g_printf("cancel_route_request\n"); + + int ret = LOCATION_ERROR_NONE; + + ret = location_map_cancel_route_request(loc, req_id); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to cancel route request. Error[%d]\n", ret); + } + else { + g_printf("location_map_cancel_route_request, req_id %d\n", req_id); + } +} + * @endcode + */ +int location_map_cancel_route_request (LocationMapObject *obj, guint req_id); + +/** + * @brief Check wheither a map service is available on a service provider + * @remarks None + * @pre #location_map_new should be called before. + * @post None. + * @param [in] obj - a #LocationMapObject created by #location_map_new + * @param [in] type - a #LocationMapService + * @return gboolean + * @retval TRUE if supported + * @par Example + * @code +#include +#include + +int check_map_service (LocationMapObject *loc) +{ + g_printf("check_map_service\n"); + + gboolean is_supported = FALSE; + + is_supported = location_map_is_supported_provider_capability(loc, MAP_SERVICE_ROUTE_REQUEST_FEATURE_TO_AVOID); + if (is_supported == TRUE) { + g_printf("Map Service(MAP_SERVICE_ROUTE_REQUEST_FEATURE_TO_AVOID) is supported.\n"); + } + else { + g_printf("Map Service(MAP_SERVICE_ROUTE_REQUEST_FEATURE_TO_AVOID) is not supported.\n"); + } +} + * @endcode + */ +gboolean location_map_is_supported_provider_capability (LocationMapObject *obj, LocationMapServiceType type); + +/** + * @brief Get Map service key on a service provider + * @remarks None + * @pre #location_map_new should be called before. + * @post None. + * @param [in] obj - a #LocationMapObject created by #location_map_new + * @param [in] type - a #LocationMapService + * @return GList + * @retval a list of keys + * @par Example + * @code +#include +#include + +static void _print_keys(gpointer data) +{ + g_return_if_fail(data); + gchar *key = (gchar *)data; + + g_printf("Key[%s] is available now\n", key); +} + +int get_map_service_key (LocationMapObject *loc) +{ + g_printf("check_map_service\n"); + + GList *keys = NULL; + + keys = location_map_get_provider_capability_key(loc, MAP_SERVICE_ROUTE_REQUEST_FEATURE_TO_AVOID); + if (keys) { + g_list_foreach (keys, _print_keys, NULL); + g_list_free_full (keys, g_free); + } + else { + g_printf("Map Service(MAP_SERVICE_ROUTE_REQUEST_FEATURE_TO_AVOID) does not have keys. Need to check whether its service is supported.\n"); + } +} + * @endcode + */ +int location_map_get_provider_capability_key (LocationMapObject *obj, LocationMapServiceType type, GList **key); + +/** + * @brief Get Map service Preference on a service provider + * @remarks None + * @pre #location_map_new should be called before. + * @post None. + * @param [in] obj - a #LocationMapObject created by #location_map_new + * @return #LocationMapPref + * @retval a preference + * @par Example + * @code +#include +#include + int get_map_service_pref (LocationMapObject loc) + { + if (!loc) return -1; + + LocationMapPref *svc_pref = location_map_get_service_pref (loc); + if (!svc_pref) return -1; + + gchar *name = location_map_pref_get_provider (svc_pref); + gchar *unit = location_map_pref_get_distance_unit (svc_pref); + gchar *language = location_map_pref_get_language (svc_pref); + + g_printf("provider [%s]: distance unit [%s], languange [%s]\n", name, unit, language); + + return 0; + } + + * @endcode + */ +LocationMapPref *location_map_get_service_pref (LocationMapObject *obj); + +/** + * @brief Set Map service preference on a service provider + * @remarks None + * @pre #location_map_new should be called before. + * @post None. + * @param [in] obj - a #LocationMapObject created by #location_map_new + * @param [in] pref = a #LocationMapPref + * @return gboolean + * @retval TRUE if success + * @par Example + * @code +#include +#include + +int set_map_service_pref (LocationMapObject *loc) +{ + if (!loc) return -1; + + LocationMapPref *svc_pref = location_map_pref_new(); + location_map_pref_set_language (svc_pref, "en"); + location_map_pref_set_distance_unit (svc_pref, "MI"); + + gboolean ret = location_map_set_service_pref (loc, svc_pref); + if (!ret) { + location_map_pref_pref (svc_pref); + return -1; + } + location_map_pref_pref (svc_pref); + return 0; +} + * @endcode + */ +gboolean location_map_set_service_pref (LocationMapObject *obj, LocationMapPref *pref); + +/** + * @brief Get supported map providers + * @remarks LocationMapObject should be created before. + * @pre None. + * @post None. + * @param [in] obj - #LocationMapObject + * @return Glist + * @retval a list of providers +*/ +GList *location_map_get_supported_providers (LocationMapObject *obj); + +/** + * @brief Get current default provider + * @remarks LocationMapObject should be created before. + * @pre None. + * @post None. + * @param [in] obj - LocationMapObject + * @return gchar + * @retval provider name + */ +gchar *location_map_get_default_provider (LocationMapObject *obj); + +/** + * @brief Set current provider + * @remarks LocationMapObject should be created before. + * @pre None. + * @post None. + * @param [in] obj - LocationMapObject + * @param [in] provider - gchar + * @return gboolean + * @retval TRUE if success + */ +gboolean location_map_set_provider (LocationMapObject *obj, gchar *provider); + +/** + * @} @} + */ + +G_END_DECLS + +#endif /* __LOCATION_MAP_SERVICE_H__ */ diff --git a/location/map-service/location-poi.c b/location/map-service/location-poi.c new file mode 100644 index 0000000..200913d --- /dev/null +++ b/location/map-service/location-poi.c @@ -0,0 +1,289 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-log.h" +#include "location-types.h" +#include "location-map-pref.h" + +#include "map-service.h" + +#include "location-poi.h" + +struct _LocationPOIPreference { + guint max_result_cnt; ///< Maximum number of results + LocationPOIPrefSortOrder sort_order; ///< Sort order + gchar* item; ///< Sory by item + GHashTable *properties; +}; + +struct _LocationPOIFilter { + // "CATEGORY", "KEYWORD", "POINAME" + GHashTable *properties; +}; + +EXPORT_API guint +location_poi_pref_get_max_result (const LocationPOIPreference *pref) +{ + g_return_val_if_fail(pref, 0); + + return pref->max_result_cnt; +} + +EXPORT_API gchar * +location_poi_pref_get_sort_by (const LocationPOIPreference *pref) +{ + g_return_val_if_fail(pref, NULL); + + return pref->item; +} + +EXPORT_API LocationPOIPrefSortOrder +location_poi_pref_get_sort_order (const LocationPOIPreference *pref) +{ + g_return_val_if_fail(pref, LOCATION_POI_PRE_SO_NONE); + + return pref->sort_order; +} + +EXPORT_API GList * +location_poi_pref_get_property_key (const LocationPOIPreference *pref) +{ + g_return_val_if_fail (pref, NULL); + if (!pref->properties) return NULL; + + return g_hash_table_get_keys (pref->properties); +} + +EXPORT_API gpointer +location_poi_pref_get_property (const LocationPOIPreference *pref, gconstpointer key) +{ + g_return_val_if_fail (pref, NULL); + g_return_val_if_fail (key, NULL); + + if (!pref->properties) return NULL; + + return g_hash_table_lookup (pref->properties, key); +} + + +EXPORT_API gboolean +location_poi_pref_set_max_result (LocationPOIPreference *pref, guint max_num) +{ + g_return_val_if_fail(pref, FALSE); + g_return_val_if_fail(max_num > 0, FALSE); + + pref->max_result_cnt = max_num; + + return TRUE; +} + +EXPORT_API gboolean +location_poi_pref_set_sort_by(LocationPOIPreference * pref, const gchar * item) +{ + g_return_val_if_fail(pref, FALSE); + + if (pref->item) { + g_free(pref->item); + pref->item = NULL; + } + + if (item) pref->item = g_strdup(item); + + return TRUE; +} + +EXPORT_API gboolean +location_poi_pref_set_sort_order (LocationPOIPreference *pref, LocationPOIPrefSortOrder sort_order) +{ + g_return_val_if_fail(pref, FALSE); + + if (sort_order < LOCATION_POI_PREF_SO_ASC || sort_order > LOCATION_POI_PREF_SO_DESC) return FALSE; + + pref->sort_order = sort_order; + + return TRUE; +} + +EXPORT_API gboolean +location_poi_pref_set_property (LocationPOIPreference *pref, gconstpointer key, gconstpointer value) +{ + g_return_val_if_fail(pref, FALSE); + g_return_val_if_fail(key, FALSE); + g_return_val_if_fail(pref->properties, FALSE); + + if (value) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert (pref->properties, re_key, re_val); + } else g_hash_table_remove (pref->properties, key); + + return TRUE; +} + +EXPORT_API LocationPOIPreference * +location_poi_pref_new (void) +{ + LocationPOIPreference *pref = g_slice_new0 (LocationPOIPreference); + g_return_val_if_fail(pref, NULL); + + pref->sort_order = LOCATION_POI_PREF_SO_ASC; + pref->max_result_cnt = 25; + pref->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + return pref; +} + +static void poi_pref_property_copy_cb (gpointer key, gpointer value, gpointer user_data) +{ + g_return_if_fail (key); + g_return_if_fail (value); + g_return_if_fail (user_data); + + LocationPOIPreference *pref = (LocationPOIPreference *) user_data; + if (pref->properties) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert (pref->properties, re_key, re_val); + } +} + +EXPORT_API LocationPOIPreference * +location_poi_pref_copy (LocationPOIPreference *pref) +{ + LocationPOIPreference *new_pref = location_poi_pref_new(); + g_return_val_if_fail (new_pref, NULL); + + location_poi_pref_set_sort_by(new_pref, location_poi_pref_get_sort_by(pref)); + location_poi_pref_set_sort_order(new_pref, location_poi_pref_get_sort_order(pref)); + location_poi_pref_set_max_result(new_pref, location_poi_pref_get_max_result(pref)); + + g_hash_table_foreach (pref->properties, poi_pref_property_copy_cb ,new_pref); + + return new_pref; +} + +EXPORT_API void +location_poi_pref_free (LocationPOIPreference * pref) +{ + g_return_if_fail(pref); + + location_poi_pref_set_sort_by(pref, NULL); + if (pref->properties) g_hash_table_destroy (pref->properties); + + g_slice_free(LocationPOIPreference, pref); +} + +EXPORT_API gboolean +location_poi_filter_set (const LocationPOIFilter *filter, gconstpointer key, gconstpointer value) +{ + g_return_val_if_fail(filter, FALSE); + g_return_val_if_fail(key, FALSE); + + if (filter->properties) { + if (value) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert (filter->properties, re_key, re_val); + } else g_hash_table_remove (filter->properties, key); + } + else + return FALSE; + + return TRUE; +} + +EXPORT_API gpointer +location_poi_filter_get (const LocationPOIFilter *filter, gconstpointer key) +{ + g_return_val_if_fail(filter, NULL); + g_return_val_if_fail(key, NULL); + + if (filter->properties) { + return g_hash_table_lookup (filter->properties, key); + } + return NULL; +} + +EXPORT_API GList * +location_poi_filter_get_key (const LocationPOIFilter *filter) +{ + g_return_val_if_fail(filter, NULL); + + if (filter->properties) { + return g_hash_table_get_keys (filter->properties); + } + + return NULL; +} + +EXPORT_API LocationPOIFilter * +location_poi_filter_new (void) +{ + LocationPOIFilter *filter = g_slice_new0(LocationPOIFilter); + g_return_val_if_fail (filter, NULL); + + filter->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + return filter; +} + +static void poi_filter_copy_cb (gpointer key, gpointer value, gpointer user_data) +{ + g_return_if_fail (key); + g_return_if_fail (value); + g_return_if_fail (user_data); + + LocationPOIFilter *filter = (LocationPOIFilter *) user_data; + if (filter->properties) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert (filter->properties, re_key, re_val); + } +} + +EXPORT_API LocationPOIFilter * +location_poi_filter_copy (LocationPOIFilter *filter) +{ + g_return_val_if_fail (filter, NULL); + + LocationPOIFilter * new_filter = location_poi_filter_new(); + g_return_val_if_fail (new_filter, NULL); + + if (new_filter->properties) g_hash_table_foreach (filter->properties, poi_filter_copy_cb, new_filter); + + return new_filter; +} + +EXPORT_API void +location_poi_filter_free (LocationPOIFilter *filter) +{ + g_return_if_fail(filter); + + if (filter->properties) { + g_hash_table_destroy (filter->properties); + filter->properties = NULL; + } + g_slice_free(LocationPOIFilter, filter); +} diff --git a/location/map-service/location-poi.h b/location/map-service/location-poi.h new file mode 100644 index 0000000..89c1f9d --- /dev/null +++ b/location/map-service/location-poi.h @@ -0,0 +1,282 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_POI_H__ +#define __LOCATION_POI_H__ + +#include + +G_BEGIN_DECLS + +/** + * @file location-poi.h + * @brief This file contains the internal definitions and structures related to POI. + */ + +/** + * @addtogroup LocationMapService + * @{ + * @defgroup LocationMapServicePOI Location POI + * @brief This is a location POI for providing location map services. + * @addtogroup LocationMapServicePOI + * @{ + */ + +typedef enum { + LOCATION_POI_PRE_SO_NONE, ///< None of sorting the results in order. + LOCATION_POI_PREF_SO_ASC, ///< A constant for sorting the results in ascending order + LOCATION_POI_PREF_SO_DESC ///< A constant for sorting the results in descending order +} LocationPOIPrefSortOrder; + +/** + * @brief Retrive LocationPreperence that the given LocationPOIPreference inherits. + */ + +/** + * @brief Create a new LocationPOIPreference + * @remarks None. + * @pre None + * @post None. + * @return #LocationPOIPreference + * @retval NULL if error occured + * @see location_location_poi_pref_free + * + */ +LocationPOIPreference *location_poi_pref_new (void); + +/** + * @brief Copy a LocationPOIPreference + * @remarks None. + * @pre None + * @post None. + * @return #LocationPOIPreference + * @retval NULL if error occured + * @see location_location_poi_pref_free + * + */ +LocationPOIPreference *location_poi_pref_copy (LocationPOIPreference *pref); + +/** + * @brief Free a LocationPOIPreference + * @remarks None. + * @pre #location_poi_pref_new should be called before. + * @post None. + * @param [in] pref - #LocationPOIPreference + * @return void + * @retval NULL if error occured + * @see location_location_poi_pref_set_pref + */ +void location_poi_pref_free (LocationPOIPreference * pref); + +/** + * @brief Get the maximum number of results for poi service. + * @remarks None. + * @pre #location_poi_pref_new should be called before. + * @post None. + * @param [in] pref - #LocationPOIPreference + * @return guint + * @retval 0 if error occured + * @see location_poi_pref_set_max_result + */ +guint location_poi_pref_get_max_result (const LocationPOIPreference * pref); + +/** + * @brief Get the sort criterion for poi service. + * @remarks None. + * @pre #location_poi_pref_new should be called before. + * @post None. + * @param [in] pref - #LocationPOIPreference + * @return gchar + * @retval sorting item + * @see location_poi_pref_set_sort_by + */ +gchar *location_poi_pref_get_sort_by (const LocationPOIPreference * pref); + +/** + * @brief Get the sort order for poi service. + * @remarks None. + * @pre #location_poi_pref_new should be called before. + * @post None. + * @param [in] pref - #LocationPOIPreference + * @return LocationPOIPrefSortOrder + * @retval sort order + * @see location_poi_pref_set_sort_order + */ +LocationPOIPrefSortOrder location_poi_pref_get_sort_order (const LocationPOIPreference * pref); + +/** + * @brief Get the property keys of poi preference + * @remarks None. + * @pre #location_poi_pref_new should be called before. + * @post None. + * @param [in] pref - #LocationPOIPreference + * @return GList + * @retval list of property key + * @see location_poi_pref_set_property + */ +GList *location_poi_pref_get_property_key (const LocationPOIPreference *pref); + +/** + * @brief Get the property of poi preference + * @remarks None. + * @pre #location_poi_pref_new should be called before. + * @post None. + * @param [in] pref - #LocationPOIPreference + * @param [in] key - gconstpointer + * @return gconstpointer + * @retval property value + * @see location_poi_pref_set_property + */ +gpointer location_poi_pref_get_property (const LocationPOIPreference *pref, gconstpointer key); + + +/** + * @brief Set the maximum number of results for poi service. + * @remarks None. + * @pre #location_poi_pref_new should be called before. + * @post None. + * @param [in] pref - #LocationPOIPreference + * @return gboolean + * @retval TRUE if success + * @see location_poi_pref_get_max_result + */ +gboolean location_poi_pref_set_max_result (LocationPOIPreference * pref, guint max_num); + +/** + * @brief Set the sort criterion for poi service. + * @remarks The previous item of the #LocationPOIPreference will be removed if an item is NULL. + * @pre #location_poi_pref_new should be called before. + * @post None. + * @param [in] pref - #LocationPOIPreference + * @param [in] item - gchar or NULL if reset + * @return gboolean + * @retval TRUE if success + * @see location_poi_pref_get_sort_by + */ +gboolean location_poi_pref_set_sort_by (LocationPOIPreference * pref, const gchar * item); + +/** + * @brief Set the sort order for poi service. + * @remarks None. + * @pre #location_poi_pref_new should be called before. + * @post None. + * @param [in] pref - #LocationPOIPreference + * @param [in] sort_order - #LocationPOIPrefSortOrder + * @return gboolean + * @retval TRUE if success + * @see location_poi_pref_get_sort_order + */ +gboolean location_poi_pref_set_sort_order (LocationPOIPreference *pref, LocationPOIPrefSortOrder sort_order); + +/** + * @brief Set property of poi preference. + * @remarks The previous value of the #LocationPOIPreference matching to key will be removed if an value is NULL. + * @pre #location_poi_pref_new should be called before. + * @post None. + * @param [in] pref - #LocationPOIPreference + * @param [in] key - gconstpoiner + * @param [in] value - gconstpointer or NULL if reset + * @return gboolean + * @retval TRUE if success + * @see location_poi_pref_get_property + */ +gboolean location_poi_pref_set_property (LocationPOIPreference *pref, gconstpointer key, gconstpointer value); + +/** + * @brief Create a new LocationPOIFilter + * @remarks None + * @pre #location_init should be called before. + * @post None. + * @return a new #LocationPOIFilter + * @retval NULL if error occured + * @see location_poi_filter_free + */ +LocationPOIFilter *location_poi_filter_new (void); + +/** + * @brief Copy a LocationPOIFilter + * @remarks None + * @pre #location_init should be called before. + * @post None. + * @return a #LocationPOIFilter + * @retval NULL if error occured + * @see location_poi_filter_new + */ +LocationPOIFilter *location_poi_filter_copy (LocationPOIFilter *filter); + +/** + * @brief Free a LocationPOIFilter + * @remarks None + * @pre #location_new should be called before. + * @post None. + * @param [in] filter - #LocationPOIFilter + * @return None + * @see location_poi_filter_new + */ +void location_poi_filter_free (LocationPOIFilter *filter); + +/** + * @brief Set filter for poi service + * @remarks The previous value of the #LocationPOIFilter matching to key will be removed if an value is NULL. + * @pre #location_poi_filter_new should be called before. + * @post None. + * @param [in] filter - #LocationPOIFilter + * @param [in] key - gconstpointer + * @param [in] value - gconstpointer or NULL if reset + * @return gboolean + * @retval TRUE if success + * @see location_poi_filter_get + */ +gboolean location_poi_filter_set (const LocationPOIFilter *filter, gconstpointer key, gconstpointer value); + +/** + * @brief Get filter for poi service + * @remarks None + * @pre #location_poi_filter_new should be called before. + * @post None. + * @param [in] filter - #LocationPOIFilter + * @param [in] key - gconstpointer + * @return gconstpointer + * @retval Filter property key + * @see location_poi_filter_set + */ +gpointer location_poi_filter_get (const LocationPOIFilter *filter, gconstpointer key); + +/** + * @brief Get keys in the given filter + * @remarks The content of returned list is owned by the poi filter and should not be modified or freed. \n + * Use g_list_free when done using the returned. + * @pre #location_poi_filter_new should be called before. + * @post None. + * @param [in] filter - #LocationPOIFilter + * @return GList + * @retval Filter key + * @see None + */ +GList *location_poi_filter_get_key (const LocationPOIFilter *filter); + +/** + * @} @} + */ + +G_END_DECLS + +#endif diff --git a/location/map-service/location-route-ext.h b/location/map-service/location-route-ext.h new file mode 100644 index 0000000..55c2b3a --- /dev/null +++ b/location/map-service/location-route-ext.h @@ -0,0 +1,877 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_ROUTE_EXT_H__ +#define __LOCATION_ROUTE_EXT_H__ + +#include + +G_BEGIN_DECLS + +/** + * @file location-route-ext.h + * @brief This file contains the extensional definitions and structures related to Route. + */ +/** + * @addtogroup LocationMapServiceRoute + * @{ + * @defgroup LocationMapServiceRouteExt Location Route Ext + * @brief This provides Location Route Ext APIs. + * @addtogroup LocationMapServiceRouteExt + * @{ + */ + +/** + * @brief Set the origin #LocationPosition of #LocationRoute + * @remarks The service provider should support route service.\n + * The previous origin of the #LocationRoute will be removed if an origin is NULL. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @param [in] origin - a #LocationPosition + * @return gboolean + * @retval TRUE if success + * @see location_route_get_origin + */ +gboolean location_route_set_origin (LocationRoute *route, const LocationPosition* origin); + +/** + * @brief Set the destication #LocationPosition of #LocationRoute + * @remarks The service provider should support route service.\n + * The previous destination of the #LocationRoute will be removed if an destination is NULL. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @param [in] destination - a #LocationPosition + * @return gboolean + * @retval TRUE if success + * @see location_route_get_destination + */ +gboolean location_route_set_destination (LocationRoute *route, const LocationPosition* destination); + +/** + * @brief Set the bounding box #LocationBoundary of #LocationRoute + * @remarks The service provider should support route service.\n + * The previous bbox of the #LocationRoute will be removed if an bbox is NULL. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @param [in] bbox - a #LocationBoundary + * @return gboolean + * @retval TRUE if success + * @see location_route_get_bounding_box + */ +gboolean location_route_set_bounding_box (LocationRoute *route, const LocationBoundary* bbox); +/** + * @brief Set the distance of #LocationRoute + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @param [in] total_distance - gdouble + * @return gboolean + * @retval TRUE if success + * @see location_route_get_total_distance + */ +gboolean location_route_set_total_distance (LocationRoute *route, gdouble total_distance); + +/** + * @brief Set the distance unit of #LocationRoute + * @remarks The service provider should support route service.\n + * The previous distance unit of the #LocationRoute will be removed if an distance_unit is NULL. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @param [in] distance_unit - gchar + * @return gboolean + * @retval TRUE if success + * @see location_route_get_distance_unit + */ +gboolean location_route_set_distance_unit (LocationRoute *route, const gchar* distance_unit); + +/** + * @brief Set the duration of #LocationRoute + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @param [in] total_duration - glong + * @return gboolean + * @retval TRUE if success + * @see location_route_get_total_duration + */ +gboolean location_route_set_total_duration (LocationRoute *route, glong total_duration); + +/** + * @brief Set the propery value of #LocationRoute + * @remarks The service provider should support route service.\n + * The previous value of the #LocationRoute matching to key will be removed if an value is NULL. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @param [in] key - gconstpointer + * @param [in] value - gconstpointer + * @return gboolean + * @retval TRUE if success + * @see location_route_get_property + */ +gboolean location_route_set_property (LocationRoute *route, gconstpointer key, gconstpointer value); + +/** + * @brief Set the list of segments #LocationRouteSegment of #LocationRoute + * @remarks The service provider should support route service.\n + * The previous route segment of the #LocationRoute will be removed if an segment is NULL. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @param [in] segment - a list of #LocationRouteSegment + * @return gboolean + * @retval TRUE if success + * @see location_route_get_route_segment + */ +gboolean location_route_set_route_segment (LocationRoute *route, GList* segment); + +/** + * @brief Set the start point #LocationPosition of #LocationRouteSegment + * @remarks The service provider should support route service.\n + * The previous start point of the #LocationRouteSegment will be removed if a start is NULL. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @param [in] start - a #LocationPosition + * @return gboolean + * @retval TRUE if success + * @see location_route_segment_get_start_point + */ +gboolean location_route_segment_set_start_point (LocationRouteSegment *segment, const LocationPosition *start); + +/** + * @brief Set the end point #LocationPosition of #LocationRouteSegment + * @remarks The service provider should support route service.\n + * The previous end point of the #LocationRouteSegment will be removed if an end is NULL. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @param [in] end - a #LocationPosition + * @return gboolean + * @retval TRUE if success + * @see location_route_segment_get_end_point + */ +gboolean location_route_segment_set_end_point (LocationRouteSegment *segment, const LocationPosition *end); + +/** + * @brief Set the bounding box #LocationBoundary of #LocationRouteSegment + * @remarks The service provider should support route service.\n + * The previous bbox of the #LocationRouteSegment will be removed if a bbox is NULL. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @param [in] bbox - a #LocationBoundary + * @return gboolean + * @retval TRUE if success + * @see location_route_segment_get_bounding_box + */ +gboolean location_route_segment_set_bounding_box (LocationRouteSegment *segment, const LocationBoundary *bbox); + +/** + * @brief Set the distance of #LocationRouteSegment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @param [in] distance - gdouble + * @return gboolean + * @retval TRUE if success + * @see location_route_segment_get_distance + */ +gboolean location_route_segment_set_distance (LocationRouteSegment *segment, gdouble distance); + +/** + * @brief Set the duration of #LocationRouteSegment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @param [in] duration - glong + * @return gboolean + * @retval TRUE if success + * @see location_route_segment_get_duration + */ +gboolean location_route_segment_set_duration (LocationRouteSegment *segment, glong duration); + +/** + * @brief Set the property value of #LocationRouteSegment + * @remarks The service provider should support route service.\n + * The previous value of the LocationRouteSegment matching to key will be removed if a value is NULL. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @param [in] key - gconstpointer + * @param [in] value - gconstpointer + * @return gboolean + * @retval TRUE if success + * @see location_route_segment_get_property + */ +gboolean location_route_segment_set_property (LocationRouteSegment *segment, gconstpointer key, gconstpointer value); + +/** + * @brief Set the list of route steps #LocationRouteStep in #LocationRouteSegment + * @remarks The service provider should support route service.\n + * The previous route step of the #LocationRouteSegment will be removed if a step is NULL. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @param [in] step - a list of #locationRouteStep + * @return gboolean + * @retval TRUE if success + * @see location_route_segment_get_route_step + */ +gboolean location_route_segment_set_route_step (LocationRouteSegment *segment, GList* step); + +/** + * @brief Set the start point #LocationPosition of #LocationRouteStep + * @remarks The service provider should support route service.\n + * The previous start point of the #LocationRouteStep will be removed if a start is NULL. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @param [in] start - a #LocationPosition + * @return gboolean + * @retval TRUE if success + * @see location_route_step_get_start_point + */ +gboolean location_route_step_set_start_point (LocationRouteStep *step, const LocationPosition *start); + +/** + * @brief Set the end point #LocationPosition of #LocationRouteStep + * @remarks The service provider should support route service.\n + * The previous end point of the #LocationRouteStep will be removed if an end is NULL. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @param [in] end - a #LocationPosition + * @return gboolean + * @retval TRUE if success + * @see location_route_step_get_end_point + */ +gboolean location_route_step_set_end_point (LocationRouteStep *step, const LocationPosition *end); + +/** + * @brief Set the bounding box #LocationBoundary of #LocationRouteStep + * @remarks The service provider should support route service.\n + * The previous bbox of the #LocationRouteStep will be removed if a bbox is NULL. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @param [in] bbox - a #LocationBoundary + * @return gboolean + * @retval TRUE if success + * @see location_route_step_get_bounding_box + */ +gboolean location_route_step_set_bounding_box (LocationRouteStep *step, const LocationBoundary *bbox); + +/** + * @brief Set the distance of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @param [in] distance - gdouble + * @return gboolean + * @retval TRUE if success + * @see location_route_step_get_distance + */ +gboolean location_route_step_set_distance (LocationRouteStep *step, gdouble distance); + +/** + * @brief Set the duration of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @param [in] duration - glong + * @return gboolean + * @retval TRUE if success + * @see location_route_step_get_duration + */ +gboolean location_route_step_set_duration (LocationRouteStep *step, glong duration); + +/** + * @brief Set the transport mode of #LocationRouteStep + * @remarks The service provider should support route service.\n + * The previous transport mode of the #LocationRouteStep will be removed if a transport_mode is NULL. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @param [in] transport_mode - gchar + * @return gboolean + * @retval TRUE if success + * @see location_route_step_get_transport_mode + */ +gboolean location_route_step_set_transport_mode (LocationRouteStep *step, const gchar *transport_mode); + +/** + * @brief Set the instruction of #LocationRouteStep + * @remarks The service provider should support route service.\n + * The previous instruction of the #LocationRouteStep will be removed if an instruction is NULL. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @param [in] instruction - gchar + * @return gboolean + * @retval TRUE if success + * @see location_route_step_get_instruction + */ +gboolean location_route_step_set_instruction (LocationRouteStep *step, const gchar *instruction); + +/** + * @brief Set the list of geometry #LocationPosition in #LocationRouteStep + * @remarks The service provider should support route service.\n + * The previous geometry of the #LocationRouteStep will be removed if a geometry is NULL. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @param [in] geometry - a list of #LocationPosition + * @return gboolean + * @retval TRUE if success + * @see location_route_step_get_geometry + */ +gboolean location_route_step_set_geometry (LocationRouteStep *step, GList *geometry); + +/** + * @brief Set the property value of #LocationRouteStep + * @remarks The service provider should support route service.\n + * The previous value of the #LocationRouteStep will be removed if a value is NULL. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @param [in] key - gconstpointer + * @param [in] value - gconstpointer + * @return gboolean + * @retval TRUE if success + * @see location_route_step_get_property + */ +gboolean location_route_step_set_property (LocationRouteStep *step, gconstpointer key, gconstpointer value); + +/** + * @brief Set the distance from start of the route to the maneuver#LocationRouteManeuver + * @remarks The service provider should support route service. + * @pre #location_route_maneuver_new should be called before. + * @post None. + * @param [in] distance - a #guint + * @param [in] maneuver - a #LocationRouteManeuver + * @return gboolean + * @retval TRUE if success + * @see location_route_maneuver_get_distance_from_start + */ +gboolean location_route_maneuver_set_distance_from_start(LocationRouteManeuver *maneuver, guint distance); + +/** + * @brief Set the distance from previous_maneuver + * @remarks The service provider should support route service. + * @pre #location_route_maneuver_new should be called before. + * @post None. + * @param [in] distance - a #guint + * @param [in] maneuver - a #LocationRouteManeuver + * @return gboolean + * @retval TRUE if success + * @see location_route_maneuver_get_distance_from_prev_maneuver + */ +gboolean location_route_maneuver_set_distance_from_prev_maneuver(LocationRouteManeuver *maneuver, guint distance); + +/** + * @brief Set Name of the road this maneuver leads to. + * @remarks The service provider should support route service. + * @pre #location_route_maneuver_new should be called before. + * @post None. + * @param [in] road_name - a #road name + * @param [in] maneuver - a #LocationRouteManeuver + * @return gboolean + * @retval TRUE if success + * @see location_route_maneuver_get_next_road_name + */ +gboolean location_route_maneuver_set_next_road_name(LocationRouteManeuver *maneuver, const gchar *road_name); + +/** + * @brief Set action to take on the maneuver. + * @remarks The service provider should support route service. + * @pre #location_route_maneuver_new should be called before. + * @post None. + * @param [in] action - a #action + * @param [in] maneuver - a #LocationRouteManeuver + * @return gboolean + * @retval TRUE if success + * @see location_route_maneuver_get_action + */ +gboolean location_route_maneuver_set_action(LocationRouteManeuver *maneuver, const gchar *action); + +/** + * @brief Set turn to make on the maneuver. + * @remarks The service provider should support route service. + * @pre #location_route_maneuver_new should be called before. + * @post None. + * @param [in] turn - a #turn to + * @param [in] maneuver - a #LocationRouteManeuver + * @return gboolean + * @retval TRUE if success + * @see location_route_maneuver_get_turn + */ +gboolean location_route_maneuver_set_turn(LocationRouteManeuver *maneuver, const gchar *turn); + +/** + * @brief Set traffic direction on the maneuver. + * @remarks The service provider should support route service. + * @pre #location_route_maneuver_new should be called before. + * @post None. + * @param [in] direction - a #TrafficDirection + * @param [in] maneuver - a #LocationRouteManeuver + * @return gboolean + * @retval TRUE if success + * @see location_route_maneuver_get_traffic_direction + */ +gboolean location_route_maneuver_set_traffic_direction(LocationRouteManeuver *maneuver, TrafficDirection direction); + +/** + * @brief Set the angle of the maneuver. + * @remarks The service provider should support route service. + * @pre #location_route_maneuver_new should be called before. + * @post None. + * @param [in] angle - a #angle + * @param [in] maneuver - a #LocationRouteManeuver + * @return gboolean + * @retval TRUE if success + * @see location_route_maneuver_get_angle + */ +gboolean location_route_maneuver_set_angle(LocationRouteManeuver *maneuver, guint angle); + +/** + * @brief Set the angle at the start of the maneuver. + * @remarks The service provider should support route service. + * @pre #location_route_maneuver_new should be called before. + * @post None. + * @param [in] start_angle - a #start angle + * @param [in] maneuver - a #LocationRouteManeuver + * @return gboolean + * @retval TRUE if success + * @see location_route_maneuver_get_start_angle + */ +gboolean location_route_maneuver_set_start_angle(LocationRouteManeuver *maneuver, guint start_angle); + +/** + * @brief Set the time at which the maneuver started. + * @remarks The service provider should support route service. + * @pre #location_route_maneuver_new should be called before. + * @post None. + * @param [in] time - a #time + * @param [in] maneuver - a #LocationRouteManeuver + * @return gboolean + * @retval TRUE if success + * @see location_route_maneuver_get_start_time + */ +gboolean location_route_maneuver_set_start_time(LocationRouteManeuver *maneuver, guint time); + +/** + * @brief set if maneuver starts on a sliproad. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @param [in] starts_from_sliproad - a #gboolean + * @return gboolean + * @retval TRUE if success + * @see + */ +gboolean location_route_maneuver_set_starts_from_sliproad(LocationRouteManeuver *maneuver, gboolean starts_from_sliproad); + +/** + * @brief set if maneuver leads to a slip road. Sliproad is a road connecting highways to + * normal roads. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @param [in] next_is_sliproad - a #gboolean + * @return gboolean + * @retval TRUE if success + * @see + */ +gboolean location_route_maneuver_set_next_is_sliproad(LocationRouteManeuver *maneuver, gboolean next_is_sliproad); + +/** + * @brief set if this maneuver is a roundabout taken in the direction opposite to the + * normal vehicle traffic. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @param [in] counter_roundabout - a #gboolean + * @return gboolean + * @retval TRUE if success + * @see + */ +gboolean location_route_maneuver_set_counter_roundabout(LocationRouteManeuver *maneuver, gboolean counter_roundabout); + +/** + * @brief Set the station name in location route Maneuver. + * @remarks The service provider should support route service. + * @pre #location_route_transit_stop_new should be called before. + * @post None. + * @param [in] station_name - a #station name + * @param [in] stop - a #LocationRouteTransitStop + * @return gboolean + * @retval TRUE if success + * @see location_route_transit_get_station_name + */ +gboolean location_route_transit_set_station_name(LocationRouteTransitStop *stop, const gchar *station_name); + +/** + * @brief Set the platform level in Location Route TransitStop. + * @remarks The service provider should support route service. + * @pre #location_route_transit_stop_new should be called before. + * @post None. + * @param [in] level - a #platform level + * @param [in] stop - a #LocationRouteTransitStop + * @return gboolean + * @retval TRUE if success + * @see location_route_transit_get_platform_level + */ +gboolean location_route_transit_set_platform_level(LocationRouteTransitStop *stop, gint level); + +/** + * @brief Set the coordinates of the platform. + * @remarks The service provider should support route service. + * @pre #location_route_transit_stop_new should be called before. + * @post None. + * @param [in] coordinates - a #LocationPosition + * @param [in] stop - a #LocationRouteTransitStop + * @return gboolean + * @retval TRUE if success + * @see location_route_transit_get_platform_coordinates + */ +gboolean location_route_transit_set_platform_coordinates(LocationRouteTransitStop *stop, const LocationPosition *coordinates); + +/** + * @brief Set the coordinates of the station entry/exit. + * @remarks The service provider should support route service. + * @pre #location_route_transit_stop_new should be called before. + * @post None. + * @param [in] eg_coordinates - a #LocationPosition + * @param [in] stop - a #LocationRouteTransitStop + * @return gboolean + * @retval TRUE if success + * @see location_route_transit_get_egress_coordinates + */ +gboolean location_route_transit_set_egress_coordinates(LocationRouteTransitStop *stop, const LocationPosition *eg_coordinates); + +/** + * @brief Set the a member of the enumeration form of way . + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] form - a #FormOfWay + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_form_of_way + */ +gboolean location_route_element_set_form_of_way(LocationRoadElement *step, FormOfWay form); + +/** + * @brief Set if the road element is plural, otherwise. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @param [in] plural - a #gboolean + * @return gboolean + * @retval TRUE if success + * @see None + */ +gboolean location_route_element_set_plural(LocationRoadElement *element, gboolean plural); + +/** + * @brief Set the name of the road . + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] road_name - a road name + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_road_name + */ +gboolean location_route_element_set_road_name(LocationRoadElement *step, const gchar *road_name); + +/** + * @brief Set the name of the route to which the given road element belongs. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] road_name - a road name + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_route_name + */ +gboolean location_route_element_set_route_name(LocationRoadElement *step, const gchar *route_name); + +/** + * @brief Set the name of the route to which the given road element belongs. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] speed_limit - speed limit + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_speed_limit + */ +gboolean location_route_element_set_speed_limit(LocationRoadElement *step, gfloat speed_limit); + +/** + * @brief Set the average speed in m/s. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] average_speed - average speed + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_average_speed_m_s + */ +gboolean location_route_element_set_average_speed_m_s(LocationRoadElement *step, guint average_speed); + +/** + * @brief Set the value indicating the number of lanes in the given road element. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] num_of_lanes - num of lanes + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_number_of_lanes + */ +gboolean location_route_element_set_number_of_lanes(LocationRoadElement *step, const guint num_of_lanes); + +/** + * @brief set if the road is allowed only for pedestrians. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @param [in] pedestrian - a #gboolean + * @return gboolean + * @retval + * @see None + */ +gboolean location_route_element_road_element_set_pedestrian(LocationRoadElement *element, gboolean pedestrian); + +/** + * @brief Set if this road element is valid. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @param [in] valid - a #gboolean + * @return gboolean + * @retval + * @see None + */ +gboolean location_route_element_road_element_set_valid(LocationRoadElement *element, gboolean valid); + +/** + * @brief Set the start time of the road element. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] start_time - start time + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_element_start_time + */ +gboolean location_route_element_set_element_start_time(LocationRoadElement *step, guint start_time); + +/** + * @brief Set the start time of the road element. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] travel_time -travel time + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_element_travel_time + */ +gboolean location_route_element_set_element_travel_time(LocationRoadElement *step, guint travel_time); + +/** + * @brief Set the destination of this run. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] transit_dest -transit dest + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_transit_destination + */ +gboolean location_route_element_set_transit_destination(LocationRoadElement *step, const gchar *transit_dest); + +/** + * @brief Set the line name. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] line_name -line name + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_transit_line_name + */ +gboolean location_route_element_set_transit_line_name(LocationRoadElement *step, const gchar *line_name); + +/** + * @brief Set name of the operator. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] official_name -official name + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_system_official_name + */ +gboolean location_route_element_set_system_official_name(LocationRoadElement *step, const gchar *official_name); + +/** + * @brief Set the name of the operator in a shorter or abbreviated version. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] short_name + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_system_short_name + */ +gboolean location_route_element_set_system_short_name(LocationRoadElement *step, const gchar *short_name); + +/** + * @brief Set the type of the line. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] type - a #TransitType + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_transit_type + */ +gboolean location_route_element_set_transit_type(LocationRoadElement *step, TransitType type); + +/** + * @brief Set the type of the line as a string in the public transit + * operator's vocabulary. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] type_name - a #TransitType + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_transit_type_name + */ +gboolean location_route_element_set_transit_type_name(LocationRoadElement *step, const gchar *type_name); + +/** + * @brief Set the absolute departure time from the station. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] departure_time - departure time + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_transit_departure_time + */ +gboolean location_route_element_set_transit_departure_time(LocationRoadElement *step, guint departure_time); + +/** + * @brief Set the absolute arrival time at the destination. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] arrival_time - arrival time + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_transit_arrival_time + */ +gboolean location_route_element_set_transit_arrival_time(LocationRoadElement *step, guint arrival_time); + +/** + * @brief Set departure station. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] departure_stop - a #LocationRouteTransitStop + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_transit_departure_station + */ +gboolean location_route_element_set_transit_departure_station(LocationRoadElement *step, const LocationRouteTransitStop *departure_stop); + +/** + * @brief Set departure station. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] arrival_stop - a #LocationRouteTransitStop + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_transit_arrival_station + */ +gboolean location_route_element_set_transit_arrival_station(LocationRoadElement *step, const LocationRouteTransitStop *arrival_stop); + +/** + * @brief Set this lane if the lane is on the route. + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] lane - a #LocationRouteLaneInfo + * @param [in] pref - a boolean #on_route + * @see None. + * @return None + * @retval None + */ +gboolean location_route_lane_set_is_on_route(LocationRouteLaneInfo *lane, gboolean on_route); + +/** + * @} @} + */ + +G_END_DECLS + +#endif diff --git a/location/map-service/location-route.c b/location/map-service/location-route.c new file mode 100644 index 0000000..7fe92ad --- /dev/null +++ b/location/map-service/location-route.c @@ -0,0 +1,2823 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-types.h" +#include "location-route.h" +#include "location-route-ext.h" +#include "location-boundary.h" +#include "map-service.h" + + +struct _LocationRoute { +// gint req_id; //< Request id : for expandability + LocationPosition *origin; //< Coordinate StartCoord + LocationPosition *destination; //< Coordinates destCoord + LocationBoundary *bbox; //< a rectangular geographical area + gdouble total_distance; //< Total distance + gchar *distance_unit; //< Distance Unit + glong total_duration; //< Total duration + GHashTable *properties; // + GList *segment; +}; + +// lane-related infomation, used for instruction(maneuver) +struct _LocationRouteLaneInfo { + gboolean is_on_route; ///< is the lane is on the route + DIRECTION travel_direction; ///< enum indicators applicable to the given lane +}; + +struct _LocationRouteManeuver { + guint distance_from_start; ///< the distance from start of the route to the maneuver(segment) + guint distance_from_prev_maneuver; ///< distance from previous maneuver on the route to the maneuver(segment) + gchar *next_road_name; ///< Name of the road this maneuver(segment) leads to + gchar *action_string; ///< Action to take on the maneuver(segment) + gchar *turn_string; ///< Turn to make on the maneuver(segment) + TrafficDirection traffic_direction; ///< traffic direction + guint angle; ///< The angle of the maneuve(segment) + guint start_angle; ///< The angle at the start of the maneuver(segment) + guint start_time; ///< Time at which the maneuver(segment) started + gboolean starts_from_sliproad; ///< True if maneuver(segment) starts on a sliproad. + gboolean next_is_sliproad; ///< True if maneuver(segment) leads to a slip road. + gboolean is_counter_roundabout; ///< True if this maneuver(segment) is a roundabout + + GList *lanes_info; ///< lanes info list on this maneuver +}; + +//Waypoints +struct _LocationRouteSegment { + LocationPosition *start; //< Coordinate StartCoord; + LocationPosition *end; //< Coordinates destCoord; + LocationBoundary *bbox; //< a rectangular geographical area + gdouble distance; + glong duration; + GHashTable *properties; // + GList *step; +}; + +struct _LocationRouteTransitStop { + gchar *station_name; ///< the stations names. + gint platform_level; ///< the platform level. 0 is ground level -1 the first underground level and 1 the first + LocationPosition *platform_coordinates; ///< the coordinates of the platform. + LocationPosition *egress_coordinates; ///< the coordinates of the station entry/exit. +}; + +struct _LocationRoadElement { + FormOfWay form_of_way; ///< the form of way + gboolean is_plural; ///< checks if the road element is plural + gchar *road_name; ///< the name of the given road element. + gchar *route_name; ///< the name of the route + gfloat speed_limit; ///< the speed limit in meters per second + guint average_speed; ///< the average speed of the road element, m/s + guint number_of_lanes; ///< number of lanes in the given step (road element) + gboolean is_pedestrian; ///< if the road is allowed only for pedestrians. + gboolean is_valid; ///< if this road element is valid. + guint start_time; ///< the start time of the road element. + guint travel_time; ///< the travel time along the element, default speed is used. + RouteETAValidity ETA_validity; ///< the estimated time of arrival (ETA) and suggested departure time for the route + + gchar *transit_destination; ///< the destination of this public transit + gchar *transit_line_name; ///< the public transit line name + gchar *system_official_name; ///< the name of the operator + gchar *system_short_name; ///< the name of the operator in a shorter or abbreviated version + TransitType transit_type; ///< the type of the line. + gchar *transit_type_name; ///< the type of the line as a string in the public transit operator's vocabulary + guint transit_departure_time; ///< the absolute departure time from the station, if available + guint transit_arrival_time; ///< the absolute arrival time at the destination, if available + LocationRouteTransitStop *transit_departure_station; ///< the departure station. + LocationRouteTransitStop *transit_arrival_station; ///< the arrival station. +}; + +// Each instruction +struct _LocationRouteStep { + LocationPosition *start; //< Coordinate StartCoord; + LocationPosition *end; //< Coordinates destCoord; + LocationBoundary *bbox; //< a rectangular geographical area + gdouble distance; + glong duration; + gchar *transport_mode; + gchar *instruction; + GList *geometry; + + GHashTable *properties; + + LocationRoadElement *road_element; ///< route road or public transit element, only one element for each step + LocationRouteManeuver *maneuver; ///< location route maneuver infomation +}; + +struct _LocationRoadElementPenalty { + gint id; ///< road element penalty's id + DrivingDirection direction; ///< road direction + guint penalty; ///< road element penalty + guint speed; ///< the limit speed in kilometers per hour + guint validity_start_time; ///< validity start time + guint validity_end_time; ///< validity end time +}; + +struct _LocationRouteOptions { + GList *road_element_penalty_list; ///< a list of struct LocationRoadElementPenalty indicators the traffic penalty for the route + + // route type: FASTEST, SHORTEST, ECONOMIC + // RoutingMode: CAR, PEDESTRIAN, PEDESTRIAN_WITH_TRANSIT, TRACK, + // FeatureType: HIGHWAY, TOLL_ROAD, FERRY, TUNNEL, DIRT_ROAD, RAIL_FERRY, PARK, + guint start_direction; ///< The direction routing should start in degrees + gfloat walk_time_multiplier; ///< Sets a multiplier to use for walking times, a higher number means a slower walking speed + guint minimum_change_time; ///< Sets the minimum connection time, in minutes. + int transit_type_allowed[TRANSIT_TYPE_COUNT]; ///< Sets whether a transit type is allowed. 1-allowed, 0-not + guint maximum_changes; ///< the maximum number of vehicle changes allowed during the trip + guint departure_time; ///< time of departure + guint arrival_time; ///< time of arrival +}; + +struct _LocationRoutePreference { + GList* addr_to_avoid; + GList* area_to_avoid; + GList* feature_to_avoid; + GList* freeformed_addr_to_avoid; + LocationBoundary* bbox; + guint max_matches_count; + gchar *distance_unit; + + gchar *route_type; + gchar *transport_mode; + gboolean is_geometry_used; + gboolean is_instruction_bounding_box_used; + gboolean is_instruction_geometry_used; + gboolean is_instruction_used; + gboolean is_traffic_data_used; + + // AvoidFreeways, Easy, Fastest, MoreFreeways, NoFreeways, Pedestrian, Shortest + GHashTable *properties; + + LocationRouteOptions *options; + +}; + +static void route_pref_addr_to_avoid_copy_cb (gpointer data, gpointer user_data) +{ + g_return_if_fail(data); + g_return_if_fail(user_data); + + LocationAddress *address = (LocationAddress *)data; + LocationRoutePreference *pref = (LocationRoutePreference *)user_data; + + pref->addr_to_avoid = g_list_append (pref->addr_to_avoid, location_address_copy(address)); +} + +static void addr_to_avoid_free_cb (gpointer data) +{ + g_return_if_fail (data); + + LocationAddress *addr = (LocationAddress *)data; + + location_address_free (addr); +} + +EXPORT_API gboolean +location_route_pref_set_addr_to_avoid (LocationRoutePreference *pref, GList *addr) +{ + g_return_val_if_fail(pref, FALSE); + + if (pref->addr_to_avoid) { + g_list_free_full (pref->addr_to_avoid, addr_to_avoid_free_cb); + pref->addr_to_avoid = NULL; + } + + if (addr) g_list_foreach (addr, route_pref_addr_to_avoid_copy_cb, pref); + + return TRUE; +} + +static void route_pref_area_to_avoid_copy_cb (gpointer data, gpointer user_data) +{ + g_return_if_fail(data); + g_return_if_fail(user_data); + + LocationBoundary *area = (LocationBoundary *)data; + LocationRoutePreference *pref = (LocationRoutePreference *)user_data; + + pref->area_to_avoid = g_list_append (pref->area_to_avoid, location_boundary_copy((const LocationBoundary *)area)); +} + +static void route_pref_area_to_avoid_free_cb (gpointer data) +{ + g_return_if_fail (data); + + LocationBoundary *boundary = (LocationBoundary *)data; + + location_boundary_free (boundary); +} + +EXPORT_API gboolean +location_route_pref_set_area_to_avoid (LocationRoutePreference *pref, GList *area) +{ + g_return_val_if_fail(pref, FALSE); + + if (pref->area_to_avoid) { + g_list_free_full (pref->area_to_avoid, route_pref_area_to_avoid_free_cb); + pref->area_to_avoid = NULL; + } + + if (area) g_list_foreach (area, route_pref_area_to_avoid_copy_cb, pref); + + return TRUE; +} + +static void route_pref_feature_to_avoid_copy_cb (gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + g_return_if_fail (user_data); + + gchar *feature = (gchar *)data; + LocationRoutePreference *pref = (LocationRoutePreference *) user_data; + + pref->feature_to_avoid = g_list_append (pref->feature_to_avoid, g_strdup (feature)); +} + +EXPORT_API gboolean +location_route_pref_set_feature_to_avoid (LocationRoutePreference *pref, GList * feature) +{ + g_return_val_if_fail(pref, FALSE); + + if (pref->feature_to_avoid) { + g_list_free_full (pref->feature_to_avoid, g_free); + pref->feature_to_avoid = NULL; + } + + g_list_foreach (feature, route_pref_feature_to_avoid_copy_cb, pref); + + return TRUE; +} + +static void route_pref_freeforemd_addr_to_avoid_foreach_copy (gpointer data, gpointer user_data) +{ + g_return_if_fail(data); + g_return_if_fail(user_data); + + gchar *freeformed_addr = (gchar *)data; + LocationRoutePreference *pref = (LocationRoutePreference *)user_data; + + pref->freeformed_addr_to_avoid = g_list_append (pref->freeformed_addr_to_avoid, g_strdup(freeformed_addr)); +} + +EXPORT_API gboolean +location_route_pref_set_freeformed_addr_to_avoid (LocationRoutePreference *pref, GList *freeformed_addr) +{ + g_return_val_if_fail(pref, FALSE); + + if (pref->freeformed_addr_to_avoid) { + g_list_free_full (pref->freeformed_addr_to_avoid, g_free); + pref->freeformed_addr_to_avoid = NULL; + } + + if (freeformed_addr) g_list_foreach (freeformed_addr, route_pref_freeforemd_addr_to_avoid_foreach_copy, pref); + + return TRUE; +} + +EXPORT_API gboolean +location_route_pref_set_bounding_box (LocationRoutePreference *pref, const LocationBoundary *bbox) +{ + g_return_val_if_fail(pref, FALSE); + + if (pref->bbox) { + location_boundary_free (pref->bbox); + pref->bbox = NULL; + } + + if (bbox) pref->bbox = location_boundary_copy (bbox); + + return TRUE; +} + +EXPORT_API gboolean +location_route_pref_set_max_result (LocationRoutePreference *pref, guint max_num) +{ + g_return_val_if_fail(pref, FALSE); + g_return_val_if_fail(max_num > 0, FALSE); + + pref->max_matches_count = max_num; + + return TRUE; +} + +EXPORT_API gboolean +location_route_pref_set_route_type (LocationRoutePreference *pref, const gchar *type) +{ + g_return_val_if_fail(pref, FALSE); + + if (pref->route_type) { + g_free(pref->route_type); + pref->route_type = NULL; + } + + if (type) pref->route_type = g_strdup (type); + + return TRUE; +} + +EXPORT_API gboolean +location_route_pref_set_transport_mode (LocationRoutePreference *pref, const gchar *mode) +{ + g_return_val_if_fail(pref, FALSE); + + if (pref->transport_mode) { + g_free(pref->transport_mode); + pref->transport_mode = NULL; + } + + if (mode) pref->transport_mode = g_strdup (mode); + + return TRUE; +} + +EXPORT_API gboolean +location_route_pref_set_geometry_used (LocationRoutePreference *pref, gboolean is_used) +{ + g_return_val_if_fail(pref, FALSE); + + pref->is_geometry_used = is_used; + + return TRUE; +} + +EXPORT_API gboolean +location_route_pref_set_instruction_bounding_box_used (LocationRoutePreference *pref, gboolean is_used) +{ + g_return_val_if_fail(pref, FALSE); + + pref->is_instruction_bounding_box_used = is_used; + + return TRUE; +} + +EXPORT_API gboolean +location_route_pref_set_instruction_geometry_used (LocationRoutePreference *pref, gboolean is_used) +{ + g_return_val_if_fail(pref, FALSE); + + pref->is_instruction_geometry_used = is_used; + + return TRUE; +} + +EXPORT_API gboolean +location_route_pref_set_instruction_used (LocationRoutePreference *pref, gboolean is_used) +{ + g_return_val_if_fail(pref, FALSE); + + pref->is_instruction_used = is_used; + + return TRUE; +} + +EXPORT_API gboolean +location_route_pref_set_traffic_data_used (LocationRoutePreference *pref, gboolean is_used) +{ + g_return_val_if_fail(pref, FALSE); + + pref->is_traffic_data_used = is_used; + + return TRUE; +} + +EXPORT_API gboolean +location_route_pref_set_property (LocationRoutePreference *pref, gconstpointer key, gconstpointer value) +{ + g_return_val_if_fail(pref, FALSE); + g_return_val_if_fail(key, FALSE); + + if (value) { + gchar *re_key = g_strdup(key); + gchar *re_val = g_strdup(value); + g_hash_table_insert (pref->properties, re_key, re_val); + } else g_hash_table_remove (pref->properties, key); + + return TRUE; +} + +EXPORT_API GList * +location_route_pref_get_addr_to_avoid (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, NULL); + + return pref->addr_to_avoid; +} + +EXPORT_API GList * +location_route_pref_get_area_to_avoid (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, NULL); + + return pref->area_to_avoid; +} + +EXPORT_API GList * +location_route_pref_get_feature_to_avoid (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, NULL); + + return pref->feature_to_avoid; +} + +EXPORT_API GList * +location_route_pref_get_freeformed_addr_to_avoid (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, NULL); + + return pref->freeformed_addr_to_avoid; +} + +EXPORT_API LocationBoundary * +location_route_pref_get_bounding_box (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, NULL); + + return pref->bbox; +} + +EXPORT_API guint +location_route_pref_get_max_result (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, 0); + + return pref->max_matches_count; +} + +EXPORT_API gchar * +location_route_pref_get_route_type (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, NULL); + + return pref->route_type; +} + +EXPORT_API gchar * +location_route_pref_get_transport_mode (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, NULL); + + return pref->transport_mode; +} + +EXPORT_API gboolean +location_route_pref_get_geometry_used (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, FALSE); + + return pref->is_geometry_used; +} + +EXPORT_API gboolean +location_route_pref_get_instruction_bounding_box_used (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, FALSE); + + return pref->is_instruction_bounding_box_used; +} + +EXPORT_API gboolean +location_route_pref_get_instruction_geometry_used (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, FALSE); + + return pref->is_instruction_geometry_used; +} + +EXPORT_API gboolean +location_route_pref_get_instruction_used (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, FALSE); + + return pref->is_instruction_used; +} + +EXPORT_API gboolean +location_route_pref_get_traffic_data_used (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, FALSE); + + return pref->is_traffic_data_used; +} + +EXPORT_API GList* +location_route_pref_get_property_key (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, NULL); + + return g_hash_table_get_keys(pref->properties); +} + +EXPORT_API gpointer +location_route_pref_get_property (const LocationRoutePreference *pref, gconstpointer key) +{ + g_return_val_if_fail(pref, NULL); + g_return_val_if_fail(key, NULL); + + return g_hash_table_lookup(pref->properties, key); +} + +EXPORT_API LocationRoutePreference * +location_route_pref_new (void) +{ + LocationRoutePreference *pref = g_slice_new0(LocationRoutePreference); + g_return_val_if_fail (pref, NULL); + + pref->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + return pref; +} + +static void route_pref_property_copy_cb (gpointer key, gpointer value, gpointer user_data) +{ + g_return_if_fail(key); + g_return_if_fail(value); + g_return_if_fail(user_data); + + LocationRoutePreference *pref = (LocationRoutePreference *)user_data; + + if (pref->properties) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert (pref->properties, re_key, re_val); + } +} + +EXPORT_API LocationRoutePreference * +location_route_pref_copy (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, NULL); + + LocationRoutePreference *new_pref = location_route_pref_new(); + g_return_val_if_fail (new_pref, NULL); + + location_route_pref_set_addr_to_avoid(new_pref, location_route_pref_get_addr_to_avoid (pref)); + location_route_pref_set_area_to_avoid(new_pref, location_route_pref_get_area_to_avoid (pref)); + location_route_pref_set_feature_to_avoid(new_pref, location_route_pref_get_feature_to_avoid (pref)); + location_route_pref_set_freeformed_addr_to_avoid(new_pref, location_route_pref_get_freeformed_addr_to_avoid (pref)); + location_route_pref_set_bounding_box(new_pref, location_route_pref_get_bounding_box (pref)); + location_route_pref_set_max_result(new_pref, location_route_pref_get_max_result (pref)); + location_route_pref_set_route_type(new_pref, location_route_pref_get_route_type (pref)); + location_route_pref_set_transport_mode(new_pref, location_route_pref_get_transport_mode (pref)); + location_route_pref_set_geometry_used(new_pref, location_route_pref_get_geometry_used (pref)); + location_route_pref_set_instruction_bounding_box_used(new_pref, location_route_pref_get_instruction_bounding_box_used (pref)); + location_route_pref_set_instruction_geometry_used(new_pref, location_route_pref_get_instruction_geometry_used (pref)); + location_route_pref_set_instruction_used(new_pref, location_route_pref_get_instruction_used (pref)); + location_route_pref_set_traffic_data_used(new_pref, location_route_pref_get_traffic_data_used (pref)); + location_route_pref_set_traffic_data_used(new_pref, location_route_pref_get_traffic_data_used (pref)); + + location_route_pref_set_options(new_pref, location_route_pref_get_options(pref)); + + if (new_pref->properties) g_hash_table_foreach (pref->properties, route_pref_property_copy_cb, new_pref); + + return new_pref; +} + + +EXPORT_API void +location_route_pref_free (LocationRoutePreference *pref) +{ + g_return_if_fail(pref); + + location_route_pref_set_addr_to_avoid(pref, NULL); + location_route_pref_set_area_to_avoid(pref, NULL); + location_route_pref_set_feature_to_avoid(pref, NULL); + location_route_pref_set_freeformed_addr_to_avoid(pref, NULL); + location_route_pref_set_bounding_box(pref, NULL); + location_route_pref_set_route_type(pref, NULL); + location_route_pref_set_transport_mode(pref, NULL); + + location_route_pref_set_options(pref, NULL); + + if (pref->properties) { + g_hash_table_destroy (pref->properties); + pref->properties = NULL; + } + + g_slice_free (LocationRoutePreference, pref); +} + +/* for expandability +EXPORT_API gint +location_route_get_req_id (const LocationRoute *route) +{ + g_return_val_if_fail(route, 0); + + return route->req_id; +} +*/ + +EXPORT_API LocationPosition * +location_route_get_origin (const LocationRoute *route) +{ + g_return_val_if_fail(route, NULL); + + return route->origin; +} + +EXPORT_API LocationPosition * +location_route_get_destination (const LocationRoute *route) +{ + g_return_val_if_fail(route, NULL); + + return route->destination; +} + +EXPORT_API LocationBoundary * +location_route_get_bounding_box (const LocationRoute *route) +{ + g_return_val_if_fail(route, NULL); + + return route->bbox; +} + +EXPORT_API gdouble +location_route_get_total_distance (const LocationRoute *route) +{ + g_return_val_if_fail(route, 0.0); + + return route->total_distance; +} + +EXPORT_API gchar * +location_route_get_distance_unit (const LocationRoute *route) +{ + g_return_val_if_fail(route, NULL); + + return route->distance_unit; +} + +EXPORT_API glong +location_route_get_total_duration (const LocationRoute *route) +{ + g_return_val_if_fail(route, 0); + + return route->total_duration; +} + +EXPORT_API GList * +location_route_get_property_key (const LocationRoute *route) +{ + g_return_val_if_fail(route, NULL); + + return g_hash_table_get_keys(route->properties); +} + +EXPORT_API gpointer +location_route_get_property (const LocationRoute *route, gconstpointer key) +{ + g_return_val_if_fail(route, NULL); + g_return_val_if_fail(key, NULL); + + return g_hash_table_lookup(route->properties, key); +} + +EXPORT_API GList * +location_route_get_route_segment (const LocationRoute *route) +{ + g_return_val_if_fail(route, NULL); + + return route->segment; +} + +/* for expandability +EXPORT_API gboolean +location_route_set_req_id (LocationRoute *route, gint req_id) +{ + g_return_val_if_fail(route, FALSE); + + route->req_id = req_id; + + return TRUE; +} +*/ + +EXPORT_API gboolean +location_route_set_origin (LocationRoute *route, const LocationPosition* origin) +{ + g_return_val_if_fail(route, FALSE); + + if (route->origin) { + location_position_free(route->origin); + route->origin = NULL; + } + + if (origin) route->origin = location_position_copy(origin); + + return TRUE; +} + +EXPORT_API gboolean +location_route_set_destination (LocationRoute *route, const LocationPosition* destination) +{ + g_return_val_if_fail(route, FALSE); + + if (route->destination) { + location_position_free(route->destination); + route->destination = NULL; + } + + if (destination) route->destination = location_position_copy(destination); + + return TRUE; +} + +EXPORT_API gboolean +location_route_set_bounding_box (LocationRoute *route, const LocationBoundary* bbox) +{ + g_return_val_if_fail(route, FALSE); + + if (route->bbox) { + location_boundary_free(route->bbox); + route->bbox = NULL; + } + + if (bbox) route->bbox = location_boundary_copy(bbox); + + return TRUE; +} + +EXPORT_API +gboolean location_route_set_total_distance (LocationRoute *route, gdouble total_distance) +{ + g_return_val_if_fail(route, FALSE); + + route->total_distance = total_distance; + + return TRUE; +} + +EXPORT_API +gboolean location_route_set_distance_unit (LocationRoute *route, const gchar* distance_unit) +{ + g_return_val_if_fail(route, FALSE); + + if (route->distance_unit) { + g_free(route->distance_unit); + route->distance_unit = NULL; + } + + if (distance_unit) route->distance_unit = g_strdup(distance_unit); + + return TRUE; +} + +EXPORT_API gboolean +location_route_set_total_duration (LocationRoute *route, glong total_duration) +{ + g_return_val_if_fail(route, FALSE); + + route->total_duration = total_duration; + + return TRUE; +} + +EXPORT_API gboolean +location_route_set_property (LocationRoute *route, gconstpointer key, gconstpointer value) +{ + g_return_val_if_fail(route, FALSE); + g_return_val_if_fail(key, FALSE); + if (!route->properties) return FALSE; + + if (value) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert(route->properties, re_key, re_val); + } else g_hash_table_remove (route->properties, key); + + return TRUE; +} + +static void route_segment_foreach_copy (gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + + LocationRouteSegment *segment = (LocationRouteSegment *) data; + LocationRoute *route = (LocationRoute *) user_data; + + route->segment = g_list_append (route->segment, location_route_segment_copy (segment)); +} + +static void route_segment_foreach_free (gpointer data) +{ + g_return_if_fail (data); + + LocationRouteSegment *segment = (LocationRouteSegment *)data; + + location_route_segment_free(segment); +} + + +EXPORT_API gboolean +location_route_set_route_segment (LocationRoute *route, GList* segment) +{ + g_return_val_if_fail(route, FALSE); + + if (route->segment) { + g_list_free_full (route->segment, route_segment_foreach_free); + route->segment = NULL; + } + + if (segment) g_list_foreach (segment, route_segment_foreach_copy, route); + + return TRUE; +} + +EXPORT_API LocationRoute * +location_route_new (void) +{ + LocationRoute *route = g_slice_new0(LocationRoute); + g_return_val_if_fail (route, NULL); + + route->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + return route; +} + +static void route_property_copy_cb (gpointer key, gpointer value, gpointer user_data) +{ + g_return_if_fail (key); + g_return_if_fail (value); + g_return_if_fail (user_data); + + LocationRoute *route = (LocationRoute *)user_data; + + if (route->properties) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert (route->properties, re_key, re_val); + } +} + +EXPORT_API LocationRoute * +location_route_copy (const LocationRoute *route) +{ + g_return_val_if_fail(route, NULL); + LocationRoute *new_route = location_route_new(); + g_return_val_if_fail(new_route, NULL); + + location_route_set_origin (new_route, location_route_get_origin(route)); + location_route_set_destination (new_route, location_route_get_destination(route)); + location_route_set_bounding_box (new_route, location_route_get_bounding_box(route)); + location_route_set_total_distance (new_route, location_route_get_total_distance(route)); + location_route_set_distance_unit (new_route, location_route_get_distance_unit(route)); + location_route_set_total_duration (new_route, location_route_get_total_duration(route)); + + g_list_foreach(route->segment, route_segment_foreach_copy, new_route); + + if (route->properties) g_hash_table_foreach (route->properties, route_property_copy_cb, new_route); + + return new_route; +} + +EXPORT_API void +location_route_free (LocationRoute *route) +{ + g_return_if_fail (route); + + location_route_set_origin (route, NULL); + location_route_set_destination (route, NULL); + location_route_set_bounding_box (route, NULL); + location_route_set_distance_unit (route, NULL); + location_route_set_route_segment (route, NULL); + + if (route->properties) { + g_hash_table_destroy (route->properties); + route->properties = NULL; + } + + g_slice_free (LocationRoute, route); +} + +EXPORT_API LocationPosition * +location_route_segment_get_start_point (const LocationRouteSegment *segment) +{ + g_return_val_if_fail(segment, NULL); + + return segment->start; +} + +EXPORT_API LocationPosition * +location_route_segment_get_end_point (const LocationRouteSegment *segment) +{ + g_return_val_if_fail(segment, NULL); + + return segment->end; +} + +EXPORT_API LocationBoundary * +location_route_segment_get_bounding_box (const LocationRouteSegment *segment) +{ + g_return_val_if_fail(segment, NULL); + + return segment->bbox; +} + +EXPORT_API gdouble +location_route_segment_get_distance (const LocationRouteSegment *segment) +{ + g_return_val_if_fail(segment, 0.0); + + return segment->distance; +} + +EXPORT_API glong +location_route_segment_get_duration (const LocationRouteSegment *segment) +{ + g_return_val_if_fail(segment, 0); + + return segment->duration; +} + +EXPORT_API GList* +location_route_segment_get_property_key (const LocationRouteSegment *segment) +{ + g_return_val_if_fail(segment, NULL); + + return g_hash_table_get_keys(segment->properties); +} + +EXPORT_API gpointer +location_route_segment_get_property (const LocationRouteSegment *segment, gconstpointer key) +{ + g_return_val_if_fail(segment, NULL); + g_return_val_if_fail(key, NULL); + + return g_hash_table_lookup(segment->properties, (gpointer) key); +} + +EXPORT_API GList* +location_route_segment_get_route_step (const LocationRouteSegment *segment) +{ + g_return_val_if_fail(segment, NULL); + + return segment->step; +} + +EXPORT_API gboolean +location_route_segment_set_start_point (LocationRouteSegment *segment, const LocationPosition *start) +{ + g_return_val_if_fail (segment, FALSE); + + if (segment->start) { + location_position_free(segment->start); + segment->start = NULL; + } + + if (start) segment->start = location_position_copy (start); + + return TRUE; +} + +EXPORT_API gboolean +location_route_segment_set_end_point (LocationRouteSegment *segment, const LocationPosition *end) +{ + g_return_val_if_fail (segment, FALSE); + + if (segment->end) { + location_position_free(segment->end); + segment->end = NULL; + } + + if (end) segment->end = location_position_copy (end); + + return TRUE; + +} + +EXPORT_API gboolean +location_route_segment_set_bounding_box (LocationRouteSegment *segment, const LocationBoundary *bbox) +{ + g_return_val_if_fail (segment, FALSE); + + if (segment->bbox) { + location_boundary_free(segment->bbox); + segment->bbox = NULL; + } + + if (bbox) segment->bbox = location_boundary_copy (bbox); + + return TRUE; +} + +EXPORT_API gboolean +location_route_segment_set_distance (LocationRouteSegment *segment, gdouble distance) +{ + g_return_val_if_fail (segment, FALSE); + + segment->distance = distance; + + return TRUE; +} + +EXPORT_API gboolean +location_route_segment_set_duration (LocationRouteSegment *segment, glong duration) +{ + g_return_val_if_fail (segment, FALSE); + + segment->duration = duration; + + return TRUE; +} + +EXPORT_API gboolean +location_route_segment_set_property (LocationRouteSegment *segment, gconstpointer key, gconstpointer value) +{ + g_return_val_if_fail (segment, FALSE); + g_return_val_if_fail (key, FALSE); + if (!segment->properties) return FALSE; + + if (value) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert(segment->properties, re_key, re_val); + } else g_hash_table_remove (segment->properties, key); + + return TRUE; +} + +static void route_step_foreach_free (gpointer data) +{ + g_return_if_fail (data); + + LocationRouteStep *step = (LocationRouteStep *) data; + + location_route_step_free(step); +} + +static void route_step_foreach_copy (gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + g_return_if_fail (user_data); + + LocationRouteStep *step = (LocationRouteStep *) data; + LocationRouteSegment *segment = (LocationRouteSegment *) user_data; + + LocationRouteStep *step_new = location_route_step_copy(step); + segment->step = g_list_append(segment->step, step_new); + +} + +EXPORT_API gboolean +location_route_segment_set_route_step (LocationRouteSegment *segment, GList* step) +{ + g_return_val_if_fail (segment, FALSE); + + if (segment->step) { + g_list_free_full (segment->step, route_step_foreach_free); + segment->step = NULL; + } + + if (step) g_list_foreach (step, route_step_foreach_copy, segment); + + return TRUE; + +} + +EXPORT_API LocationRouteSegment * +location_route_segment_new (void) +{ + LocationRouteSegment *segment = g_slice_new0 (LocationRouteSegment); + g_return_val_if_fail (segment, NULL); + + segment->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + return segment; +} + +static void segment_property_copy_cb (gpointer key, gpointer value, gpointer user_data) +{ + g_return_if_fail (key); + g_return_if_fail (value); + g_return_if_fail (user_data); + + LocationRouteSegment *segment = (LocationRouteSegment *)user_data; + + if (segment->properties) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert (segment->properties, re_key, re_val); + } +} + +EXPORT_API LocationRouteSegment * +location_route_segment_copy (LocationRouteSegment *segment) +{ + g_return_val_if_fail(segment, NULL); + + LocationRouteSegment *new_segment = location_route_segment_new(); + g_return_val_if_fail(new_segment, NULL); + + location_route_segment_set_start_point(new_segment, location_route_segment_get_start_point(segment)); + location_route_segment_set_end_point(new_segment, location_route_segment_get_end_point(segment)); + location_route_segment_set_bounding_box(new_segment, location_route_segment_get_bounding_box(segment)); + location_route_segment_set_distance(new_segment, location_route_segment_get_distance(segment)); + location_route_segment_set_duration(new_segment, location_route_segment_get_duration(segment)); + location_route_segment_set_route_step(new_segment, location_route_segment_get_route_step(segment)); + + if (segment->properties) g_hash_table_foreach (segment->properties, segment_property_copy_cb, new_segment); + + return new_segment; +} + +EXPORT_API void +location_route_segment_free (LocationRouteSegment *segment) +{ + g_return_if_fail(segment); + + location_route_segment_set_start_point(segment, NULL); + location_route_segment_set_end_point(segment, NULL); + location_route_segment_set_bounding_box(segment, NULL); + location_route_segment_set_distance(segment, 0.0); + location_route_segment_set_duration(segment, 0); + location_route_segment_set_route_step(segment, NULL); + + if (segment->properties) { + g_hash_table_destroy (segment->properties); + segment->properties = NULL; + } + + g_slice_free(LocationRouteSegment, segment); +} + +EXPORT_API LocationPosition* +location_route_step_get_start_point (const LocationRouteStep *step) +{ + g_return_val_if_fail(step, NULL); + + return step->start; +} + +EXPORT_API LocationPosition* +location_route_step_get_end_point (const LocationRouteStep *step) +{ + g_return_val_if_fail(step, NULL); + + return step->end; +} + +EXPORT_API LocationBoundary* +location_route_step_get_bounding_box (const LocationRouteStep *step) +{ + g_return_val_if_fail(step, NULL); + + return step->bbox; +} + +EXPORT_API gdouble +location_route_step_get_distance (const LocationRouteStep *step) +{ + g_return_val_if_fail(step, 0.0); + + return step->distance; +} + +EXPORT_API glong +location_route_step_get_duration (const LocationRouteStep *step) +{ + g_return_val_if_fail(step, 0); + + return step->duration; +} + +EXPORT_API gchar* +location_route_step_get_transport_mode (const LocationRouteStep *step) +{ + g_return_val_if_fail(step, NULL); + + return step->transport_mode; +} + +EXPORT_API gchar* +location_route_step_get_instruction (const LocationRouteStep *step) +{ + g_return_val_if_fail(step, NULL); + + return step->instruction; +} + +EXPORT_API GList * +location_route_step_get_geometry (const LocationRouteStep *step) +{ + g_return_val_if_fail(step, NULL); + + return step->geometry; +} + +EXPORT_API GList* +location_route_step_get_property_key (const LocationRouteStep *step) +{ + g_return_val_if_fail(step, NULL); + + return g_hash_table_get_keys (step->properties); +} + +EXPORT_API gpointer +location_route_step_get_property (const LocationRouteStep *step, gconstpointer key) +{ + g_return_val_if_fail(step, NULL); + g_return_val_if_fail(key, NULL); + + return g_hash_table_lookup (step->properties, key); +} + +EXPORT_API gboolean +location_route_step_set_start_point (LocationRouteStep *step, const LocationPosition *start) +{ + g_return_val_if_fail (step, FALSE); + + if (step->start) { + location_position_free (step->start); + step->start = NULL; + } + + if (start) step->start = location_position_copy (start); + + return TRUE; +} + +EXPORT_API gboolean +location_route_step_set_end_point (LocationRouteStep *step, const LocationPosition *end) +{ + g_return_val_if_fail (step, FALSE); + + if (step->end) { + location_position_free (step->end); + step->end = NULL; + } + + if (end) step->end = location_position_copy (end); + + return TRUE; +} + +EXPORT_API gboolean +location_route_step_set_bounding_box (LocationRouteStep *step, const LocationBoundary *bbox) +{ + g_return_val_if_fail (step, FALSE); + + if (step->bbox) { + location_boundary_free (step->bbox); + step->bbox = NULL; + } + + if (bbox) step->bbox = location_boundary_copy (bbox); + + return TRUE; +} + +EXPORT_API gboolean +location_route_step_set_distance (LocationRouteStep *step, gdouble distance) +{ + g_return_val_if_fail (step, FALSE); + + step->distance = distance; + + return TRUE; + +} + +EXPORT_API gboolean +location_route_step_set_duration (LocationRouteStep *step, glong duration) +{ + g_return_val_if_fail (step, FALSE); + + step->duration = duration; + + return TRUE; +} + +EXPORT_API gboolean +location_route_step_set_transport_mode (LocationRouteStep *step, const gchar *transport_mode) +{ + g_return_val_if_fail (step, FALSE); + + if (step->transport_mode) { + g_free(step->transport_mode); + step->transport_mode = NULL; + } + + if (transport_mode) step->transport_mode = g_strdup(transport_mode); + + return TRUE; + +} + +EXPORT_API gboolean +location_route_step_set_instruction (LocationRouteStep *step, const gchar *instruction) +{ + g_return_val_if_fail (step, FALSE); + + if (step->instruction) { + g_free(step->instruction); + step->instruction = NULL; + } + + if (instruction) step->instruction = g_strdup(instruction); + + return TRUE; + +} + +static void route_step_geometry_foreach_copy (gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + g_return_if_fail (user_data); + + LocationPosition *pos = (LocationPosition *)data; + LocationRouteStep *step = (LocationRouteStep *)user_data; + + step->geometry = g_list_append (step->geometry, location_position_copy (pos)); +} + +static void route_step_geometry_free (gpointer data) +{ + g_return_if_fail (data); + + LocationPosition *pos = (LocationPosition *)data; + + location_position_free(pos); +} + +EXPORT_API gboolean +location_route_step_set_geometry (LocationRouteStep *step, GList *geometry) +{ + g_return_val_if_fail (step, FALSE); + + if (step->geometry) { + g_list_free_full (step->geometry, route_step_geometry_free); + step->geometry = NULL; + } + + if (geometry) g_list_foreach (geometry, route_step_geometry_foreach_copy, step); + + return TRUE; + +} + +EXPORT_API gboolean +location_route_step_set_property (LocationRouteStep *step, gconstpointer key, gconstpointer value) +{ + g_return_val_if_fail(step, FALSE); + g_return_val_if_fail(key, FALSE); + + if (!step->properties) return FALSE; + + if (value) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert (step->properties, re_key, re_val); + } + else g_hash_table_remove (step->properties, key); + + return TRUE; +} + +EXPORT_API LocationRouteStep * +location_route_step_new (void) +{ + LocationRouteStep *step = g_slice_new0 (LocationRouteStep); + g_return_val_if_fail(step, NULL); + + step->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + return step; +} + +static void step_property_copy_cb (gpointer key, gpointer value, gpointer user_data) +{ + g_return_if_fail (key); + g_return_if_fail (value); + g_return_if_fail (user_data); + + LocationRouteStep *step = (LocationRouteStep *) user_data; + + if (step->properties) { + gchar *re_key = g_strdup (key); + gchar *re_val = g_strdup (value); + g_hash_table_insert (step->properties, re_key, re_val); + } +} + + +EXPORT_API LocationRouteStep * +location_route_step_copy (LocationRouteStep *step) +{ + g_return_val_if_fail(step, NULL); + + LocationRouteStep *new_step = location_route_step_new (); + g_return_val_if_fail (new_step, NULL); + + location_route_step_set_start_point (new_step, location_route_step_get_start_point(step)); + location_route_step_set_end_point (new_step, location_route_step_get_end_point(step)); + location_route_step_set_bounding_box (new_step, location_route_step_get_bounding_box(step)); + location_route_step_set_distance (new_step, location_route_step_get_distance(step)); + location_route_step_set_duration (new_step, location_route_step_get_duration(step)); + location_route_step_set_instruction (new_step, location_route_step_get_instruction(step)); + location_route_step_set_geometry (new_step, location_route_step_get_geometry(step)); + location_route_step_set_road_element(new_step, location_route_step_get_road_element(step)); + location_route_step_set_maneuver(new_step, location_route_step_get_maneuver(step)); + + if (step->properties) g_hash_table_foreach (step->properties, step_property_copy_cb, new_step); + return new_step; +} + +EXPORT_API void +location_route_step_free (LocationRouteStep *step) +{ + g_return_if_fail(step); + + location_route_step_set_start_point (step, NULL); + location_route_step_set_end_point (step, NULL); + location_route_step_set_bounding_box (step, NULL); + location_route_step_set_distance (step, 0.0); + location_route_step_set_duration (step, 0); + location_route_step_set_instruction (step, NULL); + location_route_step_set_geometry (step, NULL); + location_route_step_set_road_element(step, NULL); + location_route_step_set_maneuver(step, NULL); + + if (step->properties) { + g_hash_table_destroy (step->properties); + step->properties = NULL; + } + g_slice_free(LocationRouteStep, step); +} + +EXPORT_API LocationRouteLaneInfo *location_route_lane_info_new (void) +{ + LocationRouteLaneInfo *lane = g_slice_new0(LocationRouteLaneInfo); + g_return_val_if_fail (lane, NULL); + + return lane; +} + +EXPORT_API LocationRouteLaneInfo *location_route_lane_info_copy (const LocationRouteLaneInfo *lane) +{ + g_return_val_if_fail(lane, NULL); + + LocationRouteLaneInfo *new_lane = location_route_lane_info_new(); + g_return_val_if_fail (new_lane, NULL); + + new_lane->is_on_route = lane->is_on_route; + location_route_lane_set_directions(new_lane, location_route_lane_get_directions(lane)); + + return new_lane; +} + +EXPORT_API void location_route_lane_info_free (LocationRouteLaneInfo *lane) +{ + g_return_if_fail(lane); + + g_slice_free (LocationRouteLaneInfo, lane); +} + +EXPORT_API LocationRouteManeuver *location_route_maneuver_new (void) +{ + LocationRouteManeuver *maneuver = g_slice_new0(LocationRouteManeuver); + g_return_val_if_fail (maneuver, NULL); + + return maneuver; +} + +EXPORT_API LocationRouteManeuver *location_route_maneuver_copy (const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail(maneuver, NULL); + + LocationRouteManeuver *new_maneuver = location_route_maneuver_new(); + g_return_val_if_fail (new_maneuver, NULL); + + new_maneuver->distance_from_start = maneuver->distance_from_start; + new_maneuver->distance_from_prev_maneuver = maneuver->distance_from_prev_maneuver; + new_maneuver->next_road_name = g_strdup(maneuver->next_road_name); + new_maneuver->action_string = g_strdup(maneuver->action_string); + new_maneuver->turn_string = g_strdup(maneuver->turn_string); + new_maneuver->traffic_direction = maneuver->traffic_direction; + new_maneuver->angle = maneuver->angle; + new_maneuver->start_angle = maneuver->start_angle; + new_maneuver->start_time = maneuver->start_time; + new_maneuver->starts_from_sliproad = maneuver->starts_from_sliproad; + new_maneuver->next_is_sliproad = maneuver->next_is_sliproad; + new_maneuver->is_counter_roundabout = maneuver->is_counter_roundabout; + location_route_maneuver_set_lanes(new_maneuver, location_route_maneuver_get_lanes(maneuver)); + + return new_maneuver; +} + + +EXPORT_API void location_route_maneuver_free (LocationRouteManeuver *maneuver) +{ + g_return_if_fail(maneuver); + + if (maneuver->next_road_name) { + g_free(maneuver->next_road_name); + maneuver->next_road_name = NULL; + } + if (maneuver->action_string) { + g_free(maneuver->action_string); + maneuver->action_string = NULL; + } + if (maneuver->turn_string) { + g_free(maneuver->turn_string); + maneuver->turn_string = NULL; + } + + location_route_maneuver_set_lanes(maneuver, NULL); + + g_slice_free (LocationRouteManeuver, maneuver); +} + +EXPORT_API LocationRouteTransitStop *location_route_transit_stop_new (void) +{ + LocationRouteTransitStop *stop = g_slice_new0(LocationRouteTransitStop); + g_return_val_if_fail (stop, NULL); + + return stop; +} + +EXPORT_API LocationRouteTransitStop *location_route_transit_stop_copy (const LocationRouteTransitStop *stop) +{ + g_return_val_if_fail(stop, NULL); + + LocationRouteTransitStop *new_stop = location_route_transit_stop_new(); + g_return_val_if_fail(new_stop, NULL); + + new_stop->station_name = g_strdup(stop->station_name); + new_stop->platform_level = stop->platform_level; + new_stop->platform_coordinates = location_position_copy(stop->platform_coordinates); + new_stop->egress_coordinates = location_position_copy(stop->egress_coordinates); + + return new_stop; +} + + +EXPORT_API void location_route_transit_stop_free (LocationRouteTransitStop *stop) +{ + g_return_if_fail(stop); + + if (stop->station_name) { + g_free(stop->station_name); + stop->station_name = NULL; + } + if (stop->platform_coordinates) { + location_position_free(stop->platform_coordinates); + } + if (stop->egress_coordinates) { + location_position_free(stop->egress_coordinates); + } + + g_slice_free (LocationRouteTransitStop, stop); +} + +EXPORT_API LocationRoadElement *location_route_road_element_new (void) +{ + LocationRoadElement *road = g_slice_new0(LocationRoadElement); + g_return_val_if_fail(road, NULL); + + return road; +} + +EXPORT_API LocationRoadElement *location_route_road_element_copy (const LocationRoadElement *road) +{ + g_return_val_if_fail(road, NULL); + + LocationRoadElement *new_road = location_route_road_element_new(); + g_return_val_if_fail(new_road, NULL); + + new_road->form_of_way = road->form_of_way; + new_road->is_plural = road->is_plural; + new_road->road_name = g_strdup(road->road_name); + new_road->route_name = g_strdup(road->route_name); + new_road->speed_limit = road->speed_limit; + new_road->average_speed = road->average_speed; + new_road->number_of_lanes = road->number_of_lanes; + new_road->is_pedestrian = road->is_pedestrian; + new_road->is_valid = road->is_valid; + new_road->start_time = road->start_time; + new_road->travel_time = road->travel_time; + new_road->ETA_validity = road->ETA_validity; + + new_road->transit_destination = g_strdup(road->transit_destination); + new_road->transit_line_name = g_strdup(road->transit_line_name); + new_road->system_official_name = g_strdup(road->system_official_name); + new_road->system_short_name = g_strdup(road->system_short_name); + new_road->transit_type = road->transit_type; + new_road->transit_type_name = g_strdup(road->transit_type_name); + new_road->transit_departure_time = road->transit_departure_time; + new_road->transit_arrival_time = road->transit_arrival_time; + new_road->transit_departure_station = location_route_transit_stop_copy(road->transit_departure_station); + new_road->transit_arrival_station = location_route_transit_stop_copy(road->transit_arrival_station); + + return new_road; +} + + +EXPORT_API void location_route_road_element_free (LocationRoadElement *road) +{ + g_return_if_fail(road); + + if (road->road_name) { + g_free(road->road_name); + road->road_name = NULL; + } + if (road->route_name) { + g_free(road->route_name); + road->route_name = NULL; + } + if (road->transit_destination) { + g_free(road->transit_destination); + road->transit_destination = NULL; + } + if (road->transit_line_name) { + g_free(road->transit_line_name); + road->transit_line_name = NULL; + } + if (road->system_official_name) { + g_free(road->system_official_name); + road->system_official_name = NULL; + } + if (road->system_short_name) { + g_free(road->system_short_name); + road->system_short_name = NULL; + } + if (road->transit_type_name) { + g_free(road->transit_type_name); + road->transit_type_name = NULL; + } + if (road->transit_departure_station) { + location_route_transit_stop_free(road->transit_departure_station); + } + if (road->transit_arrival_station) { + location_route_transit_stop_free(road->transit_arrival_station); + } + + g_slice_free (LocationRoadElement, road); +} + +EXPORT_API LocationRoadElementPenalty *location_route_element_penalty_new (void) +{ + LocationRoadElementPenalty *penalty = g_slice_new0(LocationRoadElementPenalty); + g_return_val_if_fail (penalty, NULL); + + return penalty; +} + + +EXPORT_API LocationRoadElementPenalty *location_route_element_penalty_copy (const LocationRoadElementPenalty *penalty) +{ + g_return_val_if_fail(penalty, NULL); + + LocationRoadElementPenalty *new_penalty = location_route_element_penalty_new(); + g_return_val_if_fail (penalty, NULL); + + new_penalty->id = penalty->id; + new_penalty->direction = penalty->direction; + new_penalty->penalty = penalty->penalty; + new_penalty->speed = penalty->speed; + new_penalty->validity_start_time = penalty->validity_start_time; + new_penalty->validity_end_time = penalty->validity_end_time; + + return new_penalty; +} + + +EXPORT_API void location_route_element_penalty_free (LocationRoadElementPenalty *penalty) +{ + g_return_if_fail(penalty); + + g_slice_free (LocationRoadElementPenalty, penalty); +} + +EXPORT_API LocationRouteOptions *location_route_options_new (void) +{ + + LocationRouteOptions *options = g_slice_new0(LocationRouteOptions); + g_return_val_if_fail (options, NULL); + + memset(options->transit_type_allowed, 0x00, TRANSIT_TYPE_COUNT * sizeof(int)); + + return options; +} + +EXPORT_API LocationRouteOptions *location_route_options_copy (const LocationRouteOptions *options) +{ + g_return_val_if_fail(options, NULL); + + LocationRouteOptions *new_options = location_route_options_new(); + g_return_val_if_fail (new_options, NULL); + + new_options->start_direction = options->start_direction; + new_options->walk_time_multiplier = options->walk_time_multiplier; + new_options->minimum_change_time = options->minimum_change_time; + new_options->maximum_changes = options->maximum_changes; + new_options->departure_time = options->departure_time; + new_options->arrival_time = options->arrival_time; + + location_route_options_set_road_element_penalty(new_options, location_route_options_get_road_element_penalty(options)); + memmove(new_options->transit_type_allowed, options->transit_type_allowed, TRANSIT_TYPE_COUNT*sizeof(int)); + + return new_options; +} + +EXPORT_API void location_route_options_free (LocationRouteOptions *options) +{ + g_return_if_fail(options); + + location_route_options_set_road_element_penalty(options, NULL); + + g_slice_free (LocationRouteOptions, options); +} + +EXPORT_API LocationRouteManeuver *location_route_step_get_maneuver (const LocationRouteStep *step) +{ + g_return_val_if_fail(step, NULL); + + return step->maneuver; +} + +EXPORT_API gboolean location_route_step_set_maneuver (LocationRouteStep *step, const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail(step, FALSE); + + if (step->maneuver) { + location_route_maneuver_free(step->maneuver); + step->maneuver = NULL; + } + + if (maneuver) { + step->maneuver = location_route_maneuver_copy(maneuver); + } + + return TRUE; +} + +EXPORT_API guint location_route_maneuver_get_distance_from_start(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, 0); + + return maneuver->distance_from_start ; +} + +EXPORT_API gboolean location_route_maneuver_set_distance_from_start(LocationRouteManeuver *maneuver, guint distance) +{ + g_return_val_if_fail (maneuver, FALSE); + + maneuver->distance_from_start = distance; + + return TRUE; +} + +EXPORT_API guint location_route_maneuver_get_distance_from_previous_maneuver(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail(maneuver, 0); + + return maneuver->distance_from_prev_maneuver; +} + +EXPORT_API gboolean location_route_maneuver_set_distance_from_prev_maneuver(LocationRouteManeuver *maneuver, guint distance) +{ + g_return_val_if_fail (maneuver, FALSE); + + maneuver->distance_from_prev_maneuver = distance; + + return TRUE; +} + +EXPORT_API gchar *location_route_maneuver_get_next_road_name(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, NULL); + + return maneuver->next_road_name; +} + +EXPORT_API gboolean location_route_maneuver_set_next_road_name(LocationRouteManeuver *maneuver, const gchar *road_name) +{ + g_return_val_if_fail (maneuver, FALSE); + + if (maneuver->next_road_name) { + g_free(maneuver->next_road_name); + maneuver->next_road_name = NULL; + } + + if(road_name) { + maneuver->next_road_name = g_strdup(road_name); + } + + return TRUE; +} + +EXPORT_API gchar *location_route_maneuver_get_action(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, NULL); + + return maneuver->action_string; + +} + +EXPORT_API gboolean location_route_maneuver_set_action(LocationRouteManeuver *maneuver, const gchar *action) +{ + g_return_val_if_fail (maneuver, FALSE); + + if (maneuver->action_string) { + g_free(maneuver->action_string); + maneuver->action_string = NULL; + } + + if(action) { + maneuver->action_string = g_strdup(action); + } + + return TRUE; +} + +EXPORT_API gchar *location_route_maneuver_get_turn(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, NULL); + + return maneuver->turn_string; +} + +EXPORT_API gboolean location_route_maneuver_set_turn(LocationRouteManeuver *maneuver, const gchar *turn) +{ + g_return_val_if_fail (maneuver, FALSE); + + if (maneuver->turn_string) { + g_free(maneuver->turn_string); + maneuver->turn_string = NULL; + } + + if(turn) { + maneuver->turn_string = g_strdup(turn); + } + + return TRUE; +} + +EXPORT_API TrafficDirection location_route_maneuver_get_traffic_direction(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, 0); + + return maneuver->traffic_direction; +} + +EXPORT_API gboolean location_route_maneuver_set_traffic_direction(LocationRouteManeuver *maneuver, TrafficDirection direction) +{ + g_return_val_if_fail (maneuver, FALSE); + + maneuver->traffic_direction = direction; + + return TRUE; +} + +EXPORT_API guint location_route_maneuver_get_angle(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, 0); + + return maneuver->angle; +} + +EXPORT_API gboolean location_route_maneuver_set_angle(LocationRouteManeuver *maneuver, guint angle) +{ + g_return_val_if_fail (maneuver, FALSE); + g_return_val_if_fail ((angle >= 0 && angle <= 360), FALSE); + + maneuver->angle = angle; + + return TRUE; +} + +EXPORT_API guint location_route_maneuver_get_start_angle(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, 0); + + return maneuver->start_angle; +} + +EXPORT_API gboolean location_route_maneuver_set_start_angle(LocationRouteManeuver *maneuver, guint start_angle) +{ + g_return_val_if_fail (maneuver, FALSE); + g_return_val_if_fail ((start_angle >= 0 && start_angle <= 360), FALSE); + + maneuver->start_angle = start_angle; + + return TRUE; +} + +EXPORT_API guint location_route_maneuver_get_start_time(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, 0); + + return maneuver->start_time; +} + +EXPORT_API gboolean location_route_maneuver_set_start_time(LocationRouteManeuver *maneuver, guint time) +{ + g_return_val_if_fail (maneuver, FALSE); + g_return_val_if_fail (time >= 0, FALSE); + + maneuver->start_time = time; + + return TRUE; +} + +EXPORT_API gboolean location_route_maneuver_is_starts_from_sliproad(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, FALSE); + + return maneuver->starts_from_sliproad; +} + +EXPORT_API gboolean location_route_maneuver_set_starts_from_sliproad(LocationRouteManeuver *maneuver, gboolean starts_from_sliproad) +{ + g_return_val_if_fail (maneuver, FALSE); + + maneuver->starts_from_sliproad = starts_from_sliproad; + return TRUE; +} + +EXPORT_API gboolean location_route_maneuver_is_next_is_sliproad(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, FALSE); + + return maneuver->next_is_sliproad; +} + +EXPORT_API gboolean location_route_maneuver_set_next_is_sliproad(LocationRouteManeuver *maneuver, gboolean next_is_sliproad) +{ + g_return_val_if_fail (maneuver, FALSE); + + maneuver->next_is_sliproad = next_is_sliproad; + return TRUE; +} + + +EXPORT_API gboolean location_route_maneuver_is_counter_roundabout(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, FALSE); + + return maneuver->is_counter_roundabout; +} + +EXPORT_API gboolean location_route_maneuver_set_counter_roundabout(LocationRouteManeuver *maneuver, gboolean counter_roundabout) +{ + g_return_val_if_fail (maneuver, FALSE); + + maneuver->is_counter_roundabout = counter_roundabout; + return TRUE; +} + + +EXPORT_API GList *location_route_maneuver_get_lanes(const LocationRouteManeuver *maneuver) +{ + g_return_val_if_fail (maneuver, NULL); + + return maneuver->lanes_info; +} + +static void route_maneuver_lanes_foreach_copy (gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + g_return_if_fail (user_data); + + LocationRouteLaneInfo *laneinfo = (LocationRouteLaneInfo *)data; + LocationRouteManeuver *maneuver = (LocationRouteManeuver *)user_data; + + maneuver->lanes_info = g_list_append (maneuver->lanes_info, location_route_lane_info_copy(laneinfo)); +} + +static void route_maneuver_lanes_free (gpointer data) +{ + g_return_if_fail (data); + + LocationRouteLaneInfo *laneinfo = (LocationRouteLaneInfo *)data; + + location_route_lane_info_free(laneinfo); +} + + +EXPORT_API gboolean location_route_maneuver_set_lanes(LocationRouteManeuver *maneuver, GList *lanes) +{ + g_return_val_if_fail (maneuver, FALSE); + + if (maneuver->lanes_info) { + g_list_free_full (maneuver->lanes_info, route_maneuver_lanes_free); + maneuver->lanes_info = NULL; + } + + if (lanes) { + g_list_foreach (lanes, route_maneuver_lanes_foreach_copy, maneuver); + } + + return TRUE; +} + +EXPORT_API gchar *location_route_transit_get_station_name(const LocationRouteTransitStop *stop) +{ + g_return_val_if_fail (stop, NULL); + + return stop->station_name; +} + +EXPORT_API gboolean location_route_transit_set_station_name(LocationRouteTransitStop *stop, const gchar *station_name) +{ + g_return_val_if_fail (stop, FALSE); + + if (stop->station_name) { + g_free(stop->station_name); + stop->station_name = NULL; + } + + if (station_name) { + stop->station_name = g_strdup(station_name); + } + + return TRUE; +} + +EXPORT_API gint location_route_transit_get_platform_level(const LocationRouteTransitStop *stop) +{ + g_return_val_if_fail (stop, 0); + + return stop->platform_level; +} + +EXPORT_API gboolean location_route_transit_set_platform_level(LocationRouteTransitStop *stop, gint level) +{ + g_return_val_if_fail (stop, FALSE); + + stop->platform_level = level; + + return TRUE; +} + +EXPORT_API LocationPosition *location_route_transit_get_platform_coordinates(const LocationRouteTransitStop *stop) +{ + g_return_val_if_fail (stop, NULL); + + return stop->platform_coordinates; +} + +EXPORT_API gboolean location_route_transit_set_platform_coordinates(LocationRouteTransitStop *stop, const LocationPosition *coordinates) +{ + g_return_val_if_fail (stop, FALSE); + + if (stop->platform_coordinates) { + location_position_free(stop->platform_coordinates); + } + + if (coordinates) { + stop->platform_coordinates = location_position_copy(coordinates); + } + + return TRUE; +} + +EXPORT_API LocationPosition *location_route_transit_get_egress_coordinates(const LocationRouteTransitStop *stop) +{ + g_return_val_if_fail (stop, NULL); + + return stop->egress_coordinates; +} + +EXPORT_API gboolean location_route_transit_set_egress_coordinates(LocationRouteTransitStop *stop, const LocationPosition *eg_coordinates) +{ + g_return_val_if_fail (stop, FALSE); + + if (stop->egress_coordinates) { + location_position_free(stop->egress_coordinates); + } + + if (eg_coordinates) { + stop->egress_coordinates = location_position_copy(eg_coordinates); + } + + return TRUE; +} + +EXPORT_API LocationRoadElement* location_route_step_get_road_element (const LocationRouteStep *step) +{ + g_return_val_if_fail(step, NULL); + + return step->road_element; +} + +EXPORT_API gboolean location_route_step_set_road_element (LocationRouteStep *step, const LocationRoadElement *element) +{ + g_return_val_if_fail(step, FALSE); + + if (step->road_element) { + location_route_road_element_free(step->road_element); + step->road_element = NULL; + } + + if (element) { + step->road_element = location_route_road_element_copy(element); + } + + return TRUE; +} + +EXPORT_API FormOfWay location_route_element_get_form_of_way(const LocationRoadElement *element) +{ + g_return_val_if_fail(element, 0); + + return element->form_of_way; +} + +EXPORT_API gboolean location_route_element_set_form_of_way(LocationRoadElement *element, FormOfWay form) +{ + g_return_val_if_fail(element, FALSE); + + element->form_of_way = form; + + return TRUE; +} + +EXPORT_API gboolean location_route_element_is_plural(const LocationRoadElement *element) +{ + g_return_val_if_fail(element, FALSE); + + return element->is_plural; +} + +EXPORT_API gboolean location_route_element_set_plural(LocationRoadElement *element, gboolean plural) +{ + g_return_val_if_fail(element, FALSE); + + element->is_plural = plural; + return TRUE; +} + +EXPORT_API gchar *location_route_element_get_road_name(const LocationRoadElement *element) +{ + g_return_val_if_fail(element, NULL); + + return element->road_name; +} + +EXPORT_API gboolean location_route_element_set_road_name(LocationRoadElement *element, const gchar *road_name) +{ + g_return_val_if_fail (element, FALSE); + + if (element->road_name) { + g_free(element->road_name); + element->road_name = NULL; + } + + if (road_name) { + element->road_name = g_strdup (road_name); + } + + return TRUE; +} + +EXPORT_API gchar *location_route_element_get_route_name(const LocationRoadElement *element) +{ + g_return_val_if_fail(element, NULL); + + return element->route_name; +} + +EXPORT_API gboolean location_route_element_set_route_name(LocationRoadElement *element, const gchar *route_name) +{ + g_return_val_if_fail (element, FALSE); + + if (element->route_name) { + g_free(element->route_name); + element->route_name = NULL; + } + + if (route_name) { + element->route_name = g_strdup(route_name); + } + + return TRUE; +} + +EXPORT_API gfloat location_route_element_get_speed_limit(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, 0.0); + + return element->speed_limit; +} + +EXPORT_API gboolean location_route_element_set_speed_limit(LocationRoadElement *element, gfloat speed_limit) +{ + g_return_val_if_fail (element, FALSE); + + element->speed_limit = speed_limit; + + return TRUE; +} + +EXPORT_API guint location_route_element_get_average_speed_m_s(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, 0); + + return element->average_speed; +} + +EXPORT_API gboolean location_route_element_set_average_speed_m_s(LocationRoadElement *element, guint average_speed) +{ + g_return_val_if_fail (element, FALSE); + + element->average_speed = average_speed; + + return TRUE; +} + +EXPORT_API guint location_route_element_get_number_of_lanes(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, 0); + + return element->number_of_lanes; +} + +EXPORT_API gboolean location_route_element_set_number_of_lanes(LocationRoadElement *element, const guint num_of_lanes) +{ + g_return_val_if_fail (element, FALSE); + + element->number_of_lanes = num_of_lanes; + + return TRUE; +} + +EXPORT_API gboolean location_route_element_road_element_is_pedestrian(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, FALSE); + + return element->is_pedestrian; +} + +EXPORT_API gboolean location_route_element_road_element_set_pedestrian(LocationRoadElement *element, gboolean pedestrian) +{ + g_return_val_if_fail (element, FALSE); + + element->is_pedestrian = pedestrian; + return TRUE; +} + +EXPORT_API gboolean location_route_element_road_element_is_valid(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, FALSE); + + return element->is_valid; +} + +EXPORT_API gboolean location_route_element_road_element_set_valid(LocationRoadElement *element, gboolean valid) +{ + g_return_val_if_fail (element, FALSE); + + element->is_valid = valid; + return TRUE; +} + +EXPORT_API guint location_route_element_get_element_start_time(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, 0); + + return element->start_time; +} + +EXPORT_API gboolean location_route_element_set_element_start_time(LocationRoadElement *element, guint start_time) +{ + g_return_val_if_fail (element, FALSE); + + element->start_time = start_time; + + return TRUE; +} + +EXPORT_API guint location_route_element_get_element_travel_time(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, 0); + + return element->travel_time; +} + +EXPORT_API gboolean location_route_element_set_element_travel_time(LocationRoadElement *element, guint travel_time) +{ + g_return_val_if_fail (element, FALSE); + + element->travel_time = travel_time; + return TRUE; +} + +EXPORT_API gchar *location_route_element_get_transit_destination(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, NULL); + + return element->transit_destination; +} + +EXPORT_API gboolean location_route_element_set_transit_destination(LocationRoadElement *element, const gchar *transit_dest) +{ + g_return_val_if_fail (element, FALSE); + + if (element->transit_destination) { + g_free(element->transit_destination); + element->transit_destination = NULL; + } + + if (transit_dest) { + element->transit_destination = g_strdup(transit_dest); + } + + return TRUE; +} + +EXPORT_API gchar *location_route_element_get_transit_line_name(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, NULL); + + return element->transit_line_name; +} + +EXPORT_API gboolean location_route_element_set_transit_line_name(LocationRoadElement *element, const gchar *line_name) +{ + g_return_val_if_fail (element, FALSE); + + if (element->transit_line_name) { + g_free(element->transit_line_name); + element->transit_line_name = NULL; + } + + if (line_name) { + element->transit_line_name = g_strdup(line_name); + } + + return TRUE; +} + +EXPORT_API gchar *location_route_element_get_system_official_name(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, NULL); + + return element->system_official_name; +} + +EXPORT_API gboolean location_route_element_set_system_official_name(LocationRoadElement *element, const gchar *official_name) +{ + g_return_val_if_fail (element, FALSE); + + if (element->system_official_name) { + g_free(element->system_official_name); + element->system_official_name = NULL; + } + + if (official_name) { + element->system_official_name = g_strdup(official_name); + } + + return TRUE; +} + +EXPORT_API gchar *location_route_element_get_system_short_name(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, NULL); + + return element->system_short_name; +} + +EXPORT_API gboolean location_route_element_set_system_short_name(LocationRoadElement *element, const gchar *short_name) +{ + g_return_val_if_fail (element, FALSE); + + if (element->system_short_name) { + g_free(element->system_short_name); + element->system_short_name = NULL; + } + + if (short_name) { + element->system_short_name = g_strdup(short_name); + } + + return TRUE; +} + +EXPORT_API TransitType location_route_element_get_transit_type(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, 0); + + return element->transit_type; +} + +EXPORT_API gboolean location_route_element_set_transit_type(LocationRoadElement *element, TransitType type) +{ + g_return_val_if_fail (element, FALSE); + + element->transit_type = type; + + return TRUE; +} + +EXPORT_API gchar *location_route_element_get_transit_type_name(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, NULL); + + return element->transit_type_name; +} + +EXPORT_API gboolean location_route_element_set_transit_type_name(LocationRoadElement *element, const gchar *type_name) +{ + g_return_val_if_fail (element, FALSE); + + if (element->transit_type_name) { + g_free(element->transit_type_name); + element->transit_type_name = NULL; + } + + if (type_name) { + element->transit_type_name = g_strdup(type_name); + } + + return TRUE; +} + +EXPORT_API guint location_route_element_get_transit_departure_time(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, 0); + + return element->transit_departure_time; +} + +EXPORT_API gboolean location_route_element_set_transit_departure_time(LocationRoadElement *element, guint departure_time) +{ + g_return_val_if_fail (element, FALSE); + g_return_val_if_fail (departure_time >= 0, FALSE); + + element->transit_departure_time = departure_time; + + return TRUE; +} + +EXPORT_API guint location_route_element_get_transit_arrival_time(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, 0); + + return element->transit_arrival_time; +} + +EXPORT_API gboolean location_route_element_set_transit_arrival_time(LocationRoadElement *element, guint arrival_time) +{ + g_return_val_if_fail (element, FALSE); + g_return_val_if_fail (arrival_time >= 0, FALSE); + + element->transit_arrival_time = arrival_time; + + return TRUE; +} + +EXPORT_API LocationRouteTransitStop *location_route_element_get_transit_departure_station(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, NULL); + + return element->transit_departure_station; +} + +EXPORT_API gboolean location_route_element_set_transit_departure_station(LocationRoadElement *element, const LocationRouteTransitStop *departure_stop) +{ + g_return_val_if_fail (element, FALSE); + + if (element->transit_departure_station) { + location_route_transit_stop_free(element->transit_departure_station); + } + + if (departure_stop) { + element->transit_departure_station = location_route_transit_stop_copy(departure_stop); + } + + return TRUE; +} + +EXPORT_API LocationRouteTransitStop *location_route_element_get_transit_arrival_station(const LocationRoadElement *element) +{ + g_return_val_if_fail (element, NULL); + + return element->transit_arrival_station; +} + +EXPORT_API gboolean location_route_element_set_transit_arrival_station(LocationRoadElement *element, const LocationRouteTransitStop *arrival_stop) +{ + g_return_val_if_fail (element, NULL); + + if (element->transit_arrival_station) { + location_route_transit_stop_free(element->transit_arrival_station); + } + + if (arrival_stop) { + element->transit_arrival_station = location_route_transit_stop_copy(arrival_stop); + } + + return TRUE; +} + +EXPORT_API gint location_route_element_penalty_get_id(const LocationRoadElementPenalty *penalty) +{ + g_return_val_if_fail(penalty, 0); + + return penalty->id; +} + +EXPORT_API gboolean location_route_element_penalty_set_id(LocationRoadElementPenalty *penalty, gint id) +{ + g_return_val_if_fail(penalty, FALSE); + + penalty->id = id; + return TRUE; +} + +EXPORT_API DrivingDirection location_route_element_penalty_get_direction(const LocationRoadElementPenalty *penalty) +{ + g_return_val_if_fail(penalty, 0); + + return penalty->direction; +} + +EXPORT_API gboolean location_route_element_penalty_set_direction(LocationRoadElementPenalty *penalty, DrivingDirection direction) +{ + g_return_val_if_fail(penalty, FALSE); + + penalty->direction = direction; + return TRUE; +} + +EXPORT_API guint location_route_element_penalty_get_penalty(const LocationRoadElementPenalty *penalty) +{ + g_return_val_if_fail(penalty, 0); + + return penalty->penalty; +} + +EXPORT_API gboolean location_route_element_penalty_set_penalty(LocationRoadElementPenalty *penalty, guint penalty_value) +{ + g_return_val_if_fail(penalty, FALSE); + + penalty->penalty = penalty_value; + return TRUE; +} + +EXPORT_API guint location_route_element_penalty_get_speed(const LocationRoadElementPenalty *penalty) +{ + g_return_val_if_fail(penalty, 0); + + return penalty->speed; +} + +EXPORT_API gboolean location_route_element_penalty_set_speed(LocationRoadElementPenalty *penalty, guint speed) +{ + g_return_val_if_fail(penalty, FALSE); + + penalty->speed = speed; + return TRUE; +} + +EXPORT_API guint location_route_element_penalty_get_validity_start_time(const LocationRoadElementPenalty *penalty) +{ + g_return_val_if_fail(penalty, -1); + + return penalty->validity_start_time; +} + +EXPORT_API gboolean location_route_element_penalty_set_validity_start_time(LocationRoadElementPenalty *penalty, guint validity_start_time) +{ + g_return_val_if_fail(penalty, FALSE); + + penalty->validity_start_time = validity_start_time; + return TRUE; +} + +EXPORT_API guint location_route_element_penalty_get_validity_end_time(const LocationRoadElementPenalty *penalty) +{ + g_return_val_if_fail(penalty, -1); + + return penalty->validity_end_time; +} + +EXPORT_API gboolean location_route_element_penalty_set_validity_end_time(LocationRoadElementPenalty *penalty, guint validity_end_time) +{ + g_return_val_if_fail(penalty, FALSE); + + penalty->validity_end_time = validity_end_time; + return TRUE; +} + +EXPORT_API gboolean location_route_lane_is_on_route(const LocationRouteLaneInfo *lane) +{ + g_return_val_if_fail(lane, FALSE); + + return lane->is_on_route; +} + +EXPORT_API gboolean location_route_lane_set_is_on_route(LocationRouteLaneInfo *lane, gboolean on_route) +{ + g_return_val_if_fail(lane, FALSE); + + lane->is_on_route = on_route; + return TRUE; +} + +EXPORT_API DIRECTION location_route_lane_get_directions(const LocationRouteLaneInfo *lane) +{ + g_return_val_if_fail(lane, DIRECTION_UNKNOWN); + + return lane->travel_direction; +} + +EXPORT_API gboolean location_route_lane_set_directions(LocationRouteLaneInfo *lane, DIRECTION direction) +{ + g_return_val_if_fail(lane, FALSE); + + lane->travel_direction = direction; + return TRUE; +} + +EXPORT_API LocationRouteOptions *location_route_pref_get_options (const LocationRoutePreference *pref) +{ + g_return_val_if_fail(pref, NULL); + + return pref->options; +} + +EXPORT_API gboolean location_route_pref_set_options (LocationRoutePreference *pref, const LocationRouteOptions *options) +{ + g_return_val_if_fail(pref, FALSE); + + if (pref->options) { + location_route_options_free(pref->options); + pref->options = NULL; + } + + if (options) { + pref->options = location_route_options_copy(options); + } + + return TRUE; +} + +EXPORT_API GList *location_route_options_get_road_element_penalty(const LocationRouteOptions *options) +{ + g_return_val_if_fail(options, NULL); + + return options->road_element_penalty_list; +} +static void route_options_road_element_penalty_copy_cb(gpointer data, gpointer user_data) +{ + g_return_if_fail (data); + g_return_if_fail (user_data); + + LocationRoadElementPenalty *penalty = (LocationRoadElementPenalty *)data; + LocationRouteOptions *options = (LocationRouteOptions *) user_data; + + LocationRoadElementPenalty *penalty_copy = location_route_element_penalty_copy(penalty); + options->road_element_penalty_list = g_list_append (options->road_element_penalty_list, penalty_copy); +} + +EXPORT_API gboolean location_route_options_set_road_element_penalty(LocationRouteOptions *options, GList *penalty) +{ + g_return_val_if_fail(options, FALSE); + + if (options->road_element_penalty_list) { + g_list_free_full (options->road_element_penalty_list, (GDestroyNotify)location_route_element_penalty_free); + options->road_element_penalty_list = NULL; + } + + if (penalty) { + g_list_foreach (penalty, route_options_road_element_penalty_copy_cb, options); + } + + return TRUE; +} + +EXPORT_API gboolean location_route_options_set_start_direction(LocationRouteOptions *options, guint dirInDegrees) +{ + g_return_val_if_fail(options, FALSE); + + options->start_direction = dirInDegrees; + return TRUE; +} + +EXPORT_API guint location_route_options_get_start_direction(const LocationRouteOptions *options) +{ + g_return_val_if_fail(options, 0); + + return options->start_direction; +} + +EXPORT_API gboolean location_route_options_set_walk_time_multiplier(LocationRouteOptions *options, gfloat val) +{ + g_return_val_if_fail(options, FALSE); + + options->walk_time_multiplier = val; + return TRUE; +} + +EXPORT_API gfloat location_route_options_get_walk_time_multiplier(const LocationRouteOptions *options) +{ + g_return_val_if_fail(options, 0); + + return options->walk_time_multiplier; +} + +EXPORT_API gboolean location_route_options_set_minimum_change_time(LocationRouteOptions *options, guint minutes) +{ + g_return_val_if_fail(options, FALSE); + + options->minimum_change_time = minutes; + return TRUE; +} + +EXPORT_API guint location_route_options_get_minimum_change_time(const LocationRouteOptions *options) +{ + g_return_val_if_fail(options, 0); + + return options->minimum_change_time; +} + +EXPORT_API gboolean location_route_options_set_transit_type_allowed(LocationRouteOptions *options, TransitType type, gboolean allow) +{ + g_return_val_if_fail(options, FALSE); + + if (allow == TRUE) { + options->transit_type_allowed[type] = 1; + } else { + options->transit_type_allowed[type] = 0; + } + + return TRUE; +} + +EXPORT_API gboolean location_route_options_is_transit_type_allowed(const LocationRouteOptions *options, TransitType type) +{ + g_return_val_if_fail(options, FALSE); + + return options->transit_type_allowed[type]; +} + +EXPORT_API gboolean location_route_options_set_maximum_changes(LocationRouteOptions *options, guint changes) +{ + g_return_val_if_fail(options, FALSE); + + options->maximum_changes = changes; + return TRUE; +} + +EXPORT_API guint location_route_options_get_maximum_changes(const LocationRouteOptions *options) +{ + g_return_val_if_fail(options, 0); + + return options->maximum_changes; +} + +EXPORT_API gboolean location_route_options_set_departure_time(LocationRouteOptions *options, guint departure_time) +{ + g_return_val_if_fail(options, FALSE); + + options->departure_time = departure_time; + return TRUE; +} + +EXPORT_API guint location_route_options_get_departure_time(LocationRouteOptions *options) +{ + g_return_val_if_fail(options, 0); + + return options->departure_time; +} + +EXPORT_API gboolean location_route_options_set_arrival_time(LocationRouteOptions *options, guint arrival_time) +{ + g_return_val_if_fail(options, FALSE); + + options->arrival_time = arrival_time; + return TRUE; +} + +EXPORT_API guint location_route_options_get_arrival_time(LocationRouteOptions *options) +{ + g_return_val_if_fail(options, 0); + + return options->arrival_time; +} + diff --git a/location/map-service/location-route.h b/location/map-service/location-route.h new file mode 100644 index 0000000..69a9e5b --- /dev/null +++ b/location/map-service/location-route.h @@ -0,0 +1,2057 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_ROUTE_H__ +#define __LOCATION_ROUTE_H__ + +#include + +G_BEGIN_DECLS + +/** + * @file location-route.h + * @brief This file contains the internal definitions and structures related to Route. + */ + +/** + * @addtogroup LocationMapService + * @{ + * @defgroup LocationMapServiceRoute Location Route + * @brief This is a Location Route for providing location map services. + * @addtogroup LocationMapServiceRoute + * @{ + */ + +/** + * @brief Create a new Location route preference + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @return a #LocationRoutePreference + * @retval NULL if error occured + * @see location_route_pref_free + */ +LocationRoutePreference *location_route_pref_new (void); + +/** + * @brief Copy Location route preference + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return a new #LocationRoutePreference + * @retval NULL if error occured + */ +LocationRoutePreference *location_route_pref_copy (const LocationRoutePreference *pref); + +/** + * @brief Free Location route preference + * @remarks None. + * @pre #location_init should be called before.\n + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @see location_route_pref_new + * @return None + * @retval None + */ +void location_route_pref_free (LocationRoutePreference * pref); + +/** + * @brief Get a list of address structures to be avoided in Location route preference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return GList + * @retval list of #LocationAddress + * @see location_route_pref_set_addr_to_avoid + */ +GList *location_route_pref_get_addr_to_avoid (const LocationRoutePreference *pref); + +/** + * @brief Get a list of area to be avoided in Location route preference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return GList + * @retval list of #LocationBoundary + * @see location_route_pref_set_area_to_avoid + */ +GList *location_route_pref_get_area_to_avoid (const LocationRoutePreference *pref); + +/** + * @brief Get a list of features to be avoided in Location route preference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return GList + * @retval list of gchar + * @see location_route_pref_set_feature_to_avoid + */ +GList *location_route_pref_get_feature_to_avoid (const LocationRoutePreference *pref); + +/** + * @brief Get a list of freeformed address to be avoided in Location route preference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return GList + * @retval list of gchar + * @see location_route_pref_set_freeformed_to_avoid + */ +GList *location_route_pref_get_freeformed_addr_to_avoid (const LocationRoutePreference *pref); + +/** + * @brief Get a list of bounding box to be avoided in Location route preference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return #LocationBoundary + * @retval bounding box + * @see location_route_pref_set_addr_to_avoid + */ +LocationBoundary *location_route_pref_get_bounding_box (const LocationRoutePreference *pref); + +/** + * @brief Get a maximum number of matches returned from route service provider + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return guint + * @retval maximum number of matches + * @see location_route_pref_set_max_result + */ +guint location_route_pref_get_max_result (const LocationRoutePreference *pref); + +/** + * @brief Get a route type to be used in route service + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return gchar + * @retval route type + * @see location_route_pref_set_route_type + */ +gchar *location_route_pref_get_route_type (const LocationRoutePreference *pref); + +/** + * @brief Get a transport mode to be used in route service + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return gchar + * @retval transport mode + * @see location_route_pref_set_transport_mode + */ +gchar *location_route_pref_get_transport_mode (const LocationRoutePreference *pref); + +/** + * @brief Get whether the route service provider must provide the route geometry in the service requests + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return gboolean + * @retval TRUE if used + * @see location_route_pref_set_geometry_used + */ +gboolean location_route_pref_get_geometry_used (const LocationRoutePreference *pref); +/** + * @brief Get whether the route service provider must provide the route instruction bounding box in the service requests + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return gboolean + * @retval TRUE if used + * @see location_route_pref_set_instruction_bounding_box_used + */ +gboolean location_route_pref_get_instruction_bounding_box_used (const LocationRoutePreference *pref); +/** + * @brief Get whether the route service provider must provide the route geometry in the service requests + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return gboolean + * @retval TRUE if used + * @see location_route_pref_set_instruction_geometry_used + */ +gboolean location_route_pref_get_instruction_geometry_used (const LocationRoutePreference *pref); + +/** + * @brief Get whether the route service provider must provide the route instruction in the service requests + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return gboolean + * @retval TRUE if used + * @see location_route_pref_set_instruction_used + */ +gboolean location_route_pref_get_instruction_used (const LocationRoutePreference *pref); +/** + * @brief Get whether the route service provider must provide traffic data in the service requests + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return gboolean + * @retval TRUE if used + * @see location_route_pref_set_traffic_data_used + */ +gboolean location_route_pref_get_traffic_data_used (const LocationRoutePreference *pref); +/** + * @brief Get a list of Property Keys in #LocationRoutePreference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return GList + * @retval list of property key + */ +GList *location_route_pref_get_property_key (const LocationRoutePreference *pref); +/** + * @brief Get Property value in #LocationRoutePreference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @return GList + * @retval property value + * @see location_route_pref_set_property + */ +gpointer location_route_pref_get_property (const LocationRoutePreference *pref, gconstpointer key); + +/** + * @brief Set a list of address structures to be avoided in #LocationRoutePreference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] addr - a list of #LocationAddress + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_addr_to_avoid + */ +gboolean location_route_pref_set_addr_to_avoid (LocationRoutePreference * pref, GList *addr); + +/** + * @brief Set a list of area to be avoided in Location route preference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] area - a list of #LocationBoundary + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_area_to_avoid + */ +gboolean location_route_pref_set_area_to_avoid (LocationRoutePreference * pref, GList *area); + +/** + * @brief Set a list of features to be avoided in Location route preference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] feature - a list of features + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_feature_to_avoid + */ +gboolean location_route_pref_set_feature_to_avoid (LocationRoutePreference * pref, GList * feature); + +/** + * @brief Set a list of freeformed address to be avoided in Location route preference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] addr - a list of #gchar + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_freeformed_addr_to_avoid + */ +gboolean location_route_pref_set_freeformed_addr_to_avoid (LocationRoutePreference *pref, GList * freeformed_addr); + +/** + * @brief Set a bounding box #LocationBoundary in Location route preference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] bbox - a #LocationBoundary + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_bounding_box + */ +gboolean location_route_pref_set_bounding_box (LocationRoutePreference *pref, const LocationBoundary *boundary); + +/** + * @brief Set a maximum number of matches returned from route service provider + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] max_num - a #gint + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_set_max_result + */ +gboolean location_route_pref_set_max_result (LocationRoutePreference *pref, guint max_num); + +/** + * @brief Set a route type to be used in route service + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] type - a #gchar + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_route_type + */ +gboolean location_route_pref_set_route_type (LocationRoutePreference *pref, const gchar *type); + +/** + * @brief Set a transport mode to be used in route service + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] mode - a #gchar + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_transport_mode + */ +gboolean location_route_pref_set_transport_mode (LocationRoutePreference *pref, const gchar * mode); + +/** + * @brief Set whether the route service provider must provide the route geometry in the service requests + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] is_used - a #gboolean + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_geometry_used + */ +gboolean location_route_pref_set_geometry_used (LocationRoutePreference *pref, gboolean is_used); + +/** + * @brief Set whether the route service provider must provide the route instruction bounding box in the service requests + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] is_used - a #gboolean + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_instruction_bounding_box_used + */ +gboolean location_route_pref_set_instruction_bounding_box_used (LocationRoutePreference *pref, gboolean is_used); + +/** + * @brief Set whether the route service provider must provide the route geometry in the service requests + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] is_used - a #gboolean + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_instruction_geometry_used + */ +gboolean location_route_pref_set_instruction_geometry_used (LocationRoutePreference *pref, gboolean is_used); + +/** + * @brief Set whether the route service provider must provide the route instruction in the service requests + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] is_used - a #gboolean + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_instruction_used + */ +gboolean location_route_pref_set_instruction_used (LocationRoutePreference *pref, gboolean is_used); + +/** + * @brief Set whether the route service provider must provide traffic data in the service requests + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] is_used - a #gboolean + * @return #gboolean + * @retval TRUE if success + * @see location_route_pref_get_traffic_data_used + */ +gboolean location_route_pref_set_traffic_data_used (LocationRoutePreference *pref, gboolean is_used); + +/** + * @brief Set Property in Location route proference + * @remarks The service provider should support route service. + * @pre #location_route_pref_new should be called before. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] key - a #gconstpointer + * @param [in] value - a #gconstpointer + * @return gboolean + * @retval TRUE if success + * @see location_route_pref_get_property + */ +gboolean location_route_pref_set_property (LocationRoutePreference *pref, gconstpointer key, gconstpointer value); + +/** + * @defgroup LocationMapServiceRouteResult Location Route Result + * @brief This provides structure, enumeration and APIs for Route Result + * @addtogroup LocationMapServiceRouteResult + * @{ + */ +/** + * @brief Create a new Location route + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @return #LocationRoute + * @retval a new location route + * @see location_route_free + */ +LocationRoute *location_route_new (void); +/** + * @brief Copy Location route + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @return #LocationRoute + * @retval a copied location route + */ +LocationRoute *location_route_copy (const LocationRoute *route); + +/** + * @brief Free #LocationRoute + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @return void + * @retval None + */ +void location_route_free (LocationRoute *route); + +/** + * @brief Get the origin of Location route + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @return #Location position + * @retval origin + * @see location_route_set_origin + */ +LocationPosition *location_route_get_origin (const LocationRoute *route); + +/** + * @brief Get the destination of Location route + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @return #LocationPosition + * @retval destination + * @see location_route_set_destination + */ +LocationPosition *location_route_get_destination (const LocationRoute *route); + +/** + * @brief Get the bounding box of Location route + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @return #LocationBoundary + * @retval bounding box + * @see location_route_set_bounding box + */ +LocationBoundary *location_route_get_bounding_box (const LocationRoute *route); + +/** + * @brief Get the total distance of Location route + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @return gdouble + * @retval total distance + * @see location_route_set_total_distance + */ +gdouble location_route_get_total_distance (const LocationRoute *route); + +/** + * @brief Get the distance unit of Location route + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @return gchar + * @retval distance unit + * @see location_route_set_distance_unit + */ +gchar *location_route_get_distance_unit (const LocationRoute *route); + +/** + * @brief Get the total duration of location route + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @return glong + * @retval total duration + * @see location_route_set_total_duration + */ +glong location_route_get_total_duration (const LocationRoute *route); + +/** + * @brief Get the list of property key of Location route + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @return GList + * @retval list of property keys + * @see location_route_set_property + */ +GList *location_route_get_property_key (const LocationRoute *route); + +/** + * @brief Get the property value of Location route + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] route - a #LocationRoute + * @return gconstpointer + * @retval property + * @see location_route_set_property + */ +gpointer location_route_get_property (const LocationRoute *route, gconstpointer key); + +/** + * @brief Get the list of segments in Location route + * @remarks The service provider should support route service. + * @post None. + * @pre None. + * @param [in] route - a #LocationRoute + * @return GList + * @retval list of #LocationRouteSegment + * @see location_route_set_route_segment + */ +GList *location_route_get_route_segment (const LocationRoute *route); + +/** + * @brief Create a new Location route segment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @return #LocationPositionSegment + * @retval Location route segment + * @see location_route_segment_free + */ +LocationRouteSegment *location_route_segment_new (void); + +/** + * @brief Copy Location route segment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @return #LocationRouteSegment + * @retval copied Location route segment + */ +LocationRouteSegment *location_route_segment_copy (LocationRouteSegment *segment); + +/** + * @brief Free Location route segment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @return void + * @retval None. + * @see location_route_segment_new + */ +void location_route_segment_free (LocationRouteSegment *segment); + +/** + * @brief Get the start point #LocationPosition of #LocationRouteSegment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @return void + * @retval None. + * @see location_route_segment_set_start_point + */ +LocationPosition *location_route_segment_get_start_point (const LocationRouteSegment *segment); + +/** + * @brief Get the end point #LocationPosition of #LocationRouteSegment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @return void + * @retval None. + * @see location_route_segment_set_end_point + */ +LocationPosition *location_route_segment_get_end_point (const LocationRouteSegment *segment); + +/** + * @brief Get the bounding box #LocationBoundary of #LocationRouteSegment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @return void + * @retval None. + * @see location_route_segment_set_bounding_box + */ +LocationBoundary *location_route_segment_get_bounding_box (const LocationRouteSegment *segment); + +/** + * @brief Get the distance of #LocationRouteSegment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @return void + * @retval None. + * @see location_route_segment_set_distance + */ +gdouble location_route_segment_get_distance (const LocationRouteSegment *segment); + +/** + * @brief Get the duration #LocationRouteSegment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @return void + * @retval None. + * @see location_route_segment_set_duration + */ +glong location_route_segment_get_duration (const LocationRouteSegment *segment); + +/** + * @brief Get the list of property keys of #LocationRouteSegment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @return void + * @retval None. + * @see location_route_segment_set_property_key + */ +GList *location_route_segment_get_property_key (const LocationRouteSegment *segment); + +/** + * @brief Get the property value of #LocationRouteSegment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @return void + * @retval None. + * @see location_route_segment_set_property + */ +gpointer location_route_segment_get_property (const LocationRouteSegment *segment, gconstpointer key); + +/** + * @brief Get the list of route steps #LocationRouteStep in #LocationRouteSegment + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] segment - a #LocationRouteSegment + * @return void + * @retval None. + * @see location_route_segment_set_route_step + */ +GList *location_route_segment_get_route_step (const LocationRouteSegment *segment); + +/** + * @brief Create a new #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param None. + * @return #LocationRouteStep + * @retval route step + * @see location_route_step_free + */ +LocationRouteStep *location_route_step_new (void); + +/** + * @brief Copy #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return #LocationRouteStep + * @retval route step + * @see location_route_step_new + */ +LocationRouteStep *location_route_step_copy (LocationRouteStep *step); + +/** + * @brief Free #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return void + * @retval None + * @see location_route_step_new + */ +void location_route_step_free (LocationRouteStep *step); + +/** + * @brief Get the start point #LocationPosition of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return #LocationPosition + * @retval start point + * @see location_route_step_set_start_point + */ +LocationPosition *location_route_step_get_start_point (const LocationRouteStep *step); + +/** + * @brief Get the end point #LocationPosition of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return #LocationPosition + * @retval end point + * @see location_route_step_set_end_point + */ +LocationPosition *location_route_step_get_end_point (const LocationRouteStep *step); + +/** + * @brief Get the bounding box #LocationBoundary of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return #LocationBoundary + * @retval bounding box + * @see location_route_step_set_bounding_box + */ +LocationBoundary *location_route_step_get_bounding_box (const LocationRouteStep *step); + +/** + * @brief Get the distance of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return gboolean + * @retval distance + * @see location_route_step_set_distance + */ +gdouble location_route_step_get_distance (const LocationRouteStep *step); + +/** + * @brief Get the duration of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return glong + * @retval duration + * @see location_route_step_set_duration + */ +glong location_route_step_get_duration (const LocationRouteStep *step); + +/** + * @brief Get the transport mode of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return gchar + * @retval transport mode + * @see location_route_step_set_transport_mode + */ +gchar *location_route_step_get_transport_mode (const LocationRouteStep *step); + +/** + * @brief Get the instruction of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return gchar + * @retval instruction + * @see location_route_step_set_instruction + */ +gchar *location_route_step_get_instruction (const LocationRouteStep *step); + +/** + * @brief Get the list of geometry #LocationPosition of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return GList + * @retval a list of LocationPosition + * @see location_route_step_set_geometry + */ +GList *location_route_step_get_geometry (const LocationRouteStep *step); + +/** + * @brief Get the list of property key of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return GList + * @retval a list of property key + * @see location_route_step_set_property_key + */ +GList *location_route_step_get_property_key (const LocationRouteStep *step); + +/** + * @brief Get the property value of #LocationRouteStep + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @param [in] key - a gconstpointer + * @return gpointer + * @retval value + * @see location_route_step_set_property + */ +gpointer location_route_step_get_property (const LocationRouteStep *step, gconstpointer key); + + +/** + * @brief Create a new #LocationRouteLaneInfo + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param None. + * @return #LocationRouteLaneInfo + * @retval lane info + * @see location_route_lane_info_free + */ +LocationRouteLaneInfo *location_route_lane_info_new (void); + +/** + * @brief Copy #LocationRouteLaneInfo + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] lane - a #road element lane + * @return #LocationRouteLaneInfo + * @retval lane info + * @see location_route_lane_info_new + */ +LocationRouteLaneInfo *location_route_lane_info_copy (const LocationRouteLaneInfo *lane); + +/** + * @brief Free Location route lane info + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] lane - a #Location Route lone + * @return void + * @retval None. + * @see location_route_lane_info_new + */ +void location_route_lane_info_free (LocationRouteLaneInfo *lane); + +/** + * @brief Create a new #LocationRouteManeuver + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param None. + * @return #LocationRouteManeuver + * @retval route maneuver + * @see location_route_maneuver_free + */ +LocationRouteManeuver *location_route_maneuver_new (void); + +/** + * @brief Copy #LocationRouteManeuver + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #Maneuver on a route + * @return #LocationRouteLaneInfo + * @retval route maneuver + * @see location_route_maneuver_new + */ +LocationRouteManeuver *location_route_maneuver_copy (const LocationRouteManeuver *maneuver); + +/** + * @brief Free a maneuver on a route + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #Maneuver on a route + * @return void + * @retval None. + * @see location_route_lane_info_new + */ +void location_route_maneuver_free (LocationRouteManeuver *maneuver); + +/** + * @brief Create a new #LocationRouteTransitStop + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param None. + * @return #LocationRouteTransitStop + * @retval public transit + * @see location_route_transit_stop_free + */ +LocationRouteTransitStop *location_route_transit_stop_new (void); + +/** + * @brief Copy #LocationRouteTransitStop + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] stop - a #stop public transit + * @return #LocationRouteLaneInfo + * @retval route maneuver + * @see location_route_maneuver_new + */ +LocationRouteTransitStop *location_route_transit_stop_copy (const LocationRouteTransitStop *stop); + +/** + * @brief Free a stop on a public transit + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] stop - a #stop public transit + * @return void + * @retval None. + * @see location_route_transit_stop_new + */ +void location_route_transit_stop_free (LocationRouteTransitStop *stop); + + +/** + * @brief Create a new #LocationRoadElement + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param None. + * @return #LocationRoadElement + * @retval road element + * @see location_route_road_element_free + */ +LocationRoadElement *location_route_road_element_new (void); + +/** + * @brief Copy #LocationRoadElement + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] road - a #road element on route + * @return #LocationRouteLaneInfo + * @retval road element + * @see location_route_road_element_new + */ +LocationRoadElement *location_route_road_element_copy (const LocationRoadElement *road); + +/** + * @brief Free a stop on a road element + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] road - a #road element on route + * @return void + * @retval None. + * @see location_route_road_element_new + */ +void location_route_road_element_free (LocationRoadElement *road); + +/** + * @brief Create a new #LocationRoadElementPenalty + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param None. + * @return #LocationRoadElementPenalty + * @retval road element penalty + * @see location_route_element_penalty_free + */ +LocationRoadElementPenalty *location_route_element_penalty_new (void); + +/** + * @brief Copy #LocationRoadElementPenalty + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] penalty - a #penalty level about restricted roads and areas, traffic + * information, and other data that can affect the routing calculation. + * @return #LocationRouteLaneInfo + * @retval road element + * @see location_route_element_penalty_new + */ +LocationRoadElementPenalty *location_route_element_penalty_copy (const LocationRoadElementPenalty *penalty); + +/** + * @brief Free a stop on a road element + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] penalty - a #penalty level about restricted roads and areas, traffic + * information, and other data that can affect the routing calculation + * @return void + * @retval None. + * @see location_route_element_penalty_new + */ +void location_route_element_penalty_free (LocationRoadElementPenalty *penalty); + +/** + * @brief Create a new #location_route_options_new + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param None. + * @return #LocationRouteOptions + * @retval route options + * @see location_route_options_free + */ +LocationRouteOptions *location_route_options_new (void); + +/** + * @brief Copy #LocationRouteOptions + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] penalty - #options on route + * @return #LocationRouteOptions + * @retval route options + * @see location_route_element_penalty_new + */ +LocationRouteOptions *location_route_options_copy (const LocationRouteOptions *options); + +/** + * @brief Create a new #location_route_options_new + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param None. + * @return #LocationRouteOptions + * @retval route options + * @see location_route_options_free + */ +void location_route_options_free (LocationRouteOptions *options); + +/** + * @brief Get the maneuver value of #LocationRouteManeuver + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return gpointer + * @retval value + * @see location_route_step_set_maneuver + */ +LocationRouteManeuver *location_route_step_get_maneuver (const LocationRouteStep *step); + +/** + * @brief Set maneuver #LocationRouteManeuver in Location Route step + * @remarks The service provider should support route service. + * @pre #location_route_maneuver_new should be called before. + * @post None. + * @param [in] step - a #LocationRouteStep + * @param [in] maneuver - a #LocationRouteManeuver + * @return gboolean + * @retval TRUE if success + * @see location_route_step_get_maneuver + */ +gboolean location_route_step_set_maneuver (LocationRouteStep *step, const LocationRouteManeuver *maneuver); + +/** + * @brief Get the distance from start of the route to the maneuver #LocationRouteManeuver + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return guint + * @retval Distance from start in meters + * @see location_route_maneuver_set_distance_from_start + */ +guint location_route_maneuver_get_distance_from_start(const LocationRouteManeuver *maneuver); + +/** + * @brief Get distance from previous maneuver on the route to the maneuver. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return guint + * @retval Distance from previous maneuver in meters + * @see location_route_maneuver_set_distance_from_start + */ +guint location_route_maneuver_get_distance_from_previous_maneuver(const LocationRouteManeuver *maneuver); + +/** + * @brief Get Name of the road this maneuver leads to. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return gchar pointer + * @retval Name of the road + * @see location_route_maneuver_set_next_road_name + */ +gchar *location_route_maneuver_get_next_road_name(const LocationRouteManeuver *maneuver); + +/** + * @brief Get action to take on the maneuver. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return gchar pointer + * @retval Action to take on the maneuver + * @see location_route_maneuver_set_action + */ +gchar *location_route_maneuver_get_action(const LocationRouteManeuver *maneuver); + +/** + * @brief Get turn to make on the maneuver. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return gchar pointer + * @retval Turn to make on the maneuver + * @see location_route_maneuver_set_turn + */ +gchar *location_route_maneuver_get_turn(const LocationRouteManeuver *maneuver); + +/** + * @brief Get traffic direction on the maneuver. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return gchar pointer + * @retval TRAFFIC_DIR_LEFT, if left side traffic, TRAFFIC_DIR_RIGHT if right side traffic + * @see location_route_maneuver_set_traffic_direction + */ +TrafficDirection location_route_maneuver_get_traffic_direction(const LocationRouteManeuver *maneuver); + +/** + * @brief Get the angle of the maneuver. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return guint + * @retval the angle in degrees from end of the start road to the start of the end road + * remarks angle has a value from 0, 360, north is up, clockwise + * @see location_route_maneuver_set_angle + */ +guint location_route_maneuver_get_angle(const LocationRouteManeuver *maneuver); + +/** + * @brief Get the angle at the start of the maneuver. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return the angle in degrees. Zero is due north and angles increase clockwise + * remarks angle has a value from 0, 360, north is up, clockwise + * @retval guint + * @see location_route_maneuver_set_start_angle + */ +guint location_route_maneuver_get_start_angle(const LocationRouteManeuver *maneuver); + +/** + * @brief Get the time at which the maneuver started. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return the time at which the maneuver started + * @retval guint + * @see location_route_maneuver_set_start_time + */ +guint location_route_maneuver_get_start_time(const LocationRouteManeuver *maneuver); + +/** + * @brief true if maneuver starts on a sliproad. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return true if maneuver starts on a sliproad + * @retval TRUE if successmaneuver starts on a sliproad + * @see + */ +gboolean location_route_maneuver_is_starts_from_sliproad(const LocationRouteManeuver *maneuver); + +/** + * @brief true if maneuver leads to a slip road. Sliproad is a road connecting highways to + * normal roads. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return true if next road is sliproad + * @retval TRUE if next road is sliproad + * @see + */ +gboolean location_route_maneuver_is_next_is_sliproad(const LocationRouteManeuver *maneuver); + +/** + * @brief true if this maneuver is a roundabout taken in the direction opposite to the + * normal vehicle traffic. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return true if this maneuver is a roundabout taken in the direction opposite to the normal vehicle traffic + * @retval TRUE + * @see + */ +gboolean location_route_maneuver_is_counter_roundabout(const LocationRouteManeuver *maneuver); + +/** + * @brief Get the lanes in location route Maneuver. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] maneuver - a #LocationRouteManeuver + * @return GList + * @retval GList + * @see location_route_maneuver_set_lanes + */ +GList *location_route_maneuver_get_lanes(const LocationRouteManeuver *maneuver); + +/** + * @brief Set the lanes in location route Maneuver. + * @remarks The service provider should support route service. + * @pre #location_route_maneuver_new should be called before. + * @post None. + * @param [in] lanes - a #lanes list + * @param [in] maneuver - a #LocationRouteManeuver + * @return gboolean + * @retval TRUE if success + * @see location_route_maneuver_get_lanes + */ +gboolean location_route_maneuver_set_lanes(LocationRouteManeuver *maneuver, GList *lanes); + +/** + * @brief Get the station name in location route Maneuver. + * @remarks The service provider should support route service. + * @pre #location_route_transit_stop_new should be called before. + * @post None. + * @param [in] stop - a #LocationRouteTransitStop + * @return the stations names String e.g. "Potsdamer Platz". + * @retval + * @see location_route_transit_set_station_name + */ +gchar *location_route_transit_get_station_name(const LocationRouteTransitStop *stop); + +/** + * @brief Get the platform level in Location Route TransitStop. + * @remarks The service provider should support route service. + * @pre #location_route_transit_stop_new should be called before. + * @post None. + * @param [in] stop - a #LocationRouteTransitStop + * @return the platform level + * @retval Signed int e.g. <-1>. + * @see location_route_transit_set_platform_level + */ +gint location_route_transit_get_platform_level(const LocationRouteTransitStop *stop); + +/** + * @brief Get the coordinates of the platform. + * @remarks The service provider should support route service. + * @pre #location_route_transit_stop_new should be called before. + * @post None. + * @param [in] stop - a #LocationRouteTransitStop + * @return GeoCoordinates position of the platform + * @retval + * @see location_route_transit_set_platform_coordinates + */ +LocationPosition *location_route_transit_get_platform_coordinates(const LocationRouteTransitStop *stop); + +/** + * @brief Get the coordinates of the station entry/exit. + * @remarks The service provider should support route service. + * @pre #location_route_transit_stop_new should be called before. + * @post None. + * @param [in] stop - a #LocationRouteTransitStop + * @return GeoCoordinates position of the entrance + * @retval + * @see location_route_transit_set_egress_coordinates + */ +LocationPosition *location_route_transit_get_egress_coordinates(const LocationRouteTransitStop *stop); + +/** + * @brief Get the road element location route step. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRouteStep + * @return a #LocationRoadElement + * @retval + * @see location_route_step_set_road_element + */ +LocationRoadElement *location_route_step_get_road_element (const LocationRouteStep *step); + +/** + * @brief Set the road element location route step. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] element - a #LocationRoadElement + * @param [in] step - a #LocationRouteStep + * @return gboolean + * @retval TRUE if success + * @see location_route_step_get_road_element + */ +gboolean location_route_step_set_road_element (LocationRouteStep *step, const LocationRoadElement *element); + +/** + * @brief Get the a member of the enumeration form of way . + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return a #FormOfWay + * @retval + * @see location_route_element_set_form_of_way + */ +FormOfWay location_route_element_get_form_of_way(const LocationRoadElement *step); + +/** + * @brief Get the road element is plural, otherwise. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return true if the road element is plural, otherwise + * @retval + * @see None + */ +gboolean location_route_element_is_plural(const LocationRoadElement *step); + +/** + * @brief Get the name of the road . + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return name of the given road element + * @retval + * @see location_route_element_set_road_name + */ +gchar *location_route_element_get_road_name(const LocationRoadElement *step); + +/** + * @brief Get the name of the route to which the given road element belongs. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return the name of the route + * @retval + * @see location_route_element_set_route_name + */ +gchar *location_route_element_get_route_name(const LocationRoadElement *step); + +/** + * @brief Get the value indicating the speed limit in meters per +* second applicable to the given road element. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return the speed limit in meters per second or 0 if the information is + * not available. + * @retval + * @see location_route_element_set_speed_limit + */ +gfloat location_route_element_get_speed_limit(const LocationRoadElement *step); + +/** + * @brief Get the average speed in m/s . + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return average speed in m/s or 0 if the information is not available + * @retval + * @see location_route_element_set_average_speed_m_s + */ +guint location_route_element_get_average_speed_m_s(const LocationRoadElement *step); + +/** + * @brief Get the value indicating the number of lanes in the given road element. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return the number of lanes + * @retval + * @see location_route_element_set_number_of_lanes + */ +guint location_route_element_get_number_of_lanes(const LocationRoadElement *step); + +/** + * @brief checks the road is allowed only for pedestrians. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval + * @see None + */ +gboolean location_route_element_road_element_is_pedestrian(const LocationRoadElement *step); + +/** + * @brief checks if this road element is valid. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval + * @see None + */ +gboolean location_route_element_road_element_is_valid(const LocationRoadElement *step); + +/** + * @brief Get the start time of the road element. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return start time of the road element + * @retval + * @see location_route_element_set_element_start_time + */ +guint location_route_element_get_element_start_time(const LocationRoadElement *step); + +/** + * @brief Get the travel time along the element. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return travel time along the element, default speed is used. + * @retval + * @see location_route_element_set_element_travel_time + */ +guint location_route_element_get_element_travel_time(const LocationRoadElement *step); + +/** + * @brief Get the destination of this run. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return return String e.g. "Hermannplatz". + * @retval + * @see location_route_element_set_transit_destination + */ +gchar *location_route_element_get_transit_destination(const LocationRoadElement *step); + +/** + * @brief Get the line name. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return return String e.g. "U7". + * @retval + * @see location_route_element_set_transit_line_name + */ +gchar *location_route_element_get_transit_line_name(const LocationRoadElement *step); + +/** + * @brief Get name of the operator. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return string e.g. "Berliner Verkehrsbetriebe" + * @retval + * @see location_route_element_set_system_official_name + */ +gchar *location_route_element_get_system_official_name(const LocationRoadElement *step); + +/** + * @brief Get the name of the operator in a shorter or abbreviated version + * if available. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return String e.g. "BVG". + * @retval + * @see location_route_element_set_system_short_name + */ +gchar *location_route_element_get_system_short_name(const LocationRoadElement *step); + +/** + * @brief Get the type of the line. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return Enum e.g. + * @retval + * @see location_route_element_set_transit_type + */ +TransitType location_route_element_get_transit_type(const LocationRoadElement *step); + +/** + * @brief Get the type of the line as a string in the public transit + * operator's vocabulary. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return String e.g. "S-Bahn" + * @retval + * @see location_route_element_set_transit_type_name + */ +gchar *location_route_element_get_transit_type_name(const LocationRoadElement *step); + +/** + * @brief Get the absolute departure time from the station, if available; otherwise + * returns an invalid DateTime + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return time + * @retval + * @see location_route_element_set_transit_departure_time + */ +guint location_route_element_get_transit_departure_time(const LocationRoadElement *step); + +/** + * @brief Get the absolute arrival time at the destination, if available; otherwise + * returns an invalid DateTime. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return time + * @retval + * @see location_route_element_set_transit_arrival_time + */ +guint location_route_element_get_transit_arrival_time(const LocationRoadElement *step); + +/** + * @brief Get departure station. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return a #LocationRouteTransitStop + * @retval + * @see location_route_element_set_transit_departure_station + */ +LocationRouteTransitStop *location_route_element_get_transit_departure_station(const LocationRoadElement *step); + +/** + * @brief Get the arrival station. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] step - a #LocationRoadElement + * @return a #LocationRouteTransitStop + * @retval + * @see location_route_element_set_transit_arrival_station + */ +LocationRouteTransitStop *location_route_element_get_transit_arrival_station(const LocationRoadElement *step); + +/** + * @brief Set departure station. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] arrival_stop - a #LocationRouteTransitStop + * @param [in] step - a #LocationRoadElement + * @return gboolean + * @retval TRUE if success + * @see location_route_element_get_transit_arrival_station + */ +gboolean location_route_element_set_transit_arrival_station(LocationRoadElement *step, const LocationRouteTransitStop *arrival_stop); + +/** + * @brief Get the identifier of the penalty. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] penalty - a #LocationRoadElementPenalty + * @return the identifier of the penalty + * @retval + * @see location_route_element_penalty_set_id + */ +gint location_route_element_penalty_get_id(const LocationRoadElementPenalty *penalty); + +/** + * @brief Set the identifier for the given penalty. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] id + * @param [in] penalty - a #LocationRoadElementPenalty + * @return gboolean + * @retval TRUE if success + * @see location_route_element_penalty_get_id + */ +gboolean location_route_element_penalty_set_id(LocationRoadElementPenalty *penalty, gint id); + + +/** + * @brief Get the driving direction associated with the penalty. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] penalty - a #LocationRoadElementPenalty + * @return a #DrivingDirection + * @retval + * @see location_route_element_penalty_set_direction + */ +DrivingDirection location_route_element_penalty_get_direction(const LocationRoadElementPenalty *penalty); + +/** + * @brief Set the driving direction associated with the penalty. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] direction - a #DrivingDirection + * @param [in] penalty - a #LocationRoadElementPenalty + * @return gboolean + * @retval TRUE if success + * @see location_route_element_penalty_get_direction + */ +gboolean location_route_element_penalty_set_direction(LocationRoadElementPenalty *penalty, DrivingDirection direction); + +/** + * @brief Get value of the penalty level. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] penalty - a #LocationRoadElementPenalty + * @return an unsigned eight-bit integer value representing the penalty + * level or INVALID_PENALTY + * @retval + * @see location_route_element_penalty_set_penalty + */ +guint location_route_element_penalty_get_penalty(const LocationRoadElementPenalty *penalty); + +/** + * @brief Set the value of the penalty level. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] penalty_value - a penalty value + * @param [in] penalty - a #LocationRoadElementPenalty + * @return gboolean + * @retval TRUE if success + * @see location_route_element_penalty_get_penalty + */ +gboolean location_route_element_penalty_set_penalty(LocationRoadElementPenalty *penalty, guint penalty_value); + +/** + * @brief Get the speed. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] penalty - a #LocationRoadElementPenalty + * @return An unsigned eight-bit integer representing the speed + * @retval + * @see location_route_element_penalty_set_speed + */ +guint location_route_element_penalty_get_speed(const LocationRoadElementPenalty *penalty); + +/** + * @brief Set the the speed. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] speed + * @param [in] penalty - a #LocationRoadElementPenalty + * @return gboolean + * @retval TRUE if success + * @see location_route_element_penalty_get_speed + */ +gboolean location_route_element_penalty_set_speed(LocationRoadElementPenalty *penalty, guint speed); + +/** + * @brief Get timestamp indicating the time/date from which the penalty is in force. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] penalty - a #LocationRoadElementPenalty + * @return timestamp indicating the time/date + * @retval + * @see location_route_element_penalty_set_validity_start_time + */ +guint location_route_element_penalty_get_validity_start_time(const LocationRoadElementPenalty *penalty); + +/** + * @brief Set timestamp . + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] validity_start_time -validity start time + * @param [in] penalty - a #LocationRoadElementPenalty + * @return gboolean + * @retval TRUE if success + * @see location_route_element_penalty_get_validity_start_time + */ +gboolean location_route_element_penalty_set_validity_start_time(LocationRoadElementPenalty *penalty, guint validity_start_time); + +/** + * @brief Get value indicating the time/date on which the penalty expires. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] penalty - a #LocationRoadElementPenalty + * @return timestamp indicating the time/date + * @retval + * @see location_route_element_penalty_set_validity_end_time + */ +guint location_route_element_penalty_get_validity_end_time(const LocationRoadElementPenalty *penalty); + +/** + * @brief Set value indicating the time/date on which the penalty expires. + * @remarks The service provider should support route service. + * @pre None. + * @post None. + * @param [in] validity_end_time -validity end time + * @param [in] penalty - a #LocationRoadElementPenalty + * @return gboolean + * @retval TRUE if success + * @see location_route_element_penalty_get_validity_end_time + */ +gboolean location_route_element_penalty_set_validity_end_time(LocationRoadElementPenalty *penalty, guint validity_end_time); + + + +/** + * @brief This method retrieves a Boolean value indicating if the lane is on the route. + * @remarks None. + * @pre None. + * @post None. + * @param [in] lane - a #LocationRouteLaneInfo + * @see None. + * @return true - if he lane is on the route, otherwise false + * @retval None + */ +gboolean location_route_lane_is_on_route(const LocationRouteLaneInfo *lane); + +/** + * @brief This method retrieves a vector of elements of the enumeration DIRECTION with direction indicators applicable to the given + * @remarks None. + * @pre None. + * @post None. + * @param [in] lane - a #LocationRouteLaneInfo + * @see DIRECTION + * @return None + * @retval None + */ +DIRECTION location_route_lane_get_directions(const LocationRouteLaneInfo *lane); + +/** + * @brief This method set the lane's direction + * @remarks None. + * @pre None. + * @post None. + * @param [in] lane - a #LocationRouteLaneInfo + * @param [in] direction - a #DIRECTION + * @see DIRECTION + * @return gboolean + * @retval TRUE if sucess + */ +gboolean location_route_lane_set_directions(LocationRouteLaneInfo *lane, DIRECTION direction); + +/** + * @brief This method get the route options from preference + * @remarks None. + * @pre None. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @see None + * @return LocationRouteOptions + * @retval route options + */ +LocationRouteOptions *location_route_pref_get_options (const LocationRoutePreference *pref); + +/** + * @brief This method set the route options for preference + * @remarks None. + * @pre None. + * @post None. + * @param [in] pref - a #LocationRoutePreference + * @param [in] options - a #LocationRouteOptions + * @see None + * @return gboolean + * @retval TRUE if sucess + */ +gboolean location_route_pref_set_options (LocationRoutePreference *pref, const LocationRouteOptions *options); + +/** + * @brief This method get the route element penalty from options + * @remarks None. + * @pre None. + * @post None. + * @param [in] options - a #LocationRouteOptions + * @see None + * @return GList + * @retval Road element penalty list + */ +GList *location_route_options_get_road_element_penalty(const LocationRouteOptions *options); + +/** + * @brief This method set the route element penalty from options + * @remarks None. + * @pre None. + * @post None. + * @param [in] options - a #LocationRouteOptions + * @param [in] penalty - a list #LocationRoadElementPenalty + * @see None + * @return gboolean + * @retval TRUE if sucess + */ +gboolean location_route_options_set_road_element_penalty(LocationRouteOptions *options, GList *penalty); + +/** + * @brief This method set the route start direction. + * @remarks None. + * @pre None. + * @post None. + * @param [in] options - a #LocationRouteOptions + * @param [in] dirInDegrees - Start direction in degrees, values between 0-359. + * @see None + * @return gboolean + * @retval TRUE if sucess + */ +gboolean location_route_options_set_start_direction(LocationRouteOptions *options, guint dirInDegrees); + + +/** + * @brief This method returns the start direction. + * @remarks None. + * @pre None. + * @post None. + * @param [in] options - a #LocationRouteOptions + * @see None + * @return guint + * @retval The start direction in degrees. Value is between 0-359. + */ +guint location_route_options_get_start_direction(const LocationRouteOptions *options); + + +/** + * @brief Sets a multiplier to use for walking times. + * @remarks A higher number means a slower walking speed. The default is 1.0. + * @pre None + * @post None. + * @param [in] options - a #LocationRouteOptions + * @param [in] val - a #gfloat + * @see None + * @return gboolean + * @retval TRUE if sucess + */ +gboolean location_route_options_set_walk_time_multiplier(LocationRouteOptions *options, gfloat val); + +/** + * @brief Gets a multiplier to use for walking times. + * @remarks A higher number means a slower walking speed. The default is 1.0. + * @pre None + * @post None. + * @param [in] options - a #LocationRouteOptions + * @see None + * @return gfloat + * @retval a multiplier to use for walking times + */ +gfloat location_route_options_get_walk_time_multiplier(const LocationRouteOptions *options); + +/** + * @brief Sets the minimum connection time, in minutes. + * @remarks None. + * @pre None + * @post None. + * @param [in] options - a #LocationRouteOptions + * @param [in] minutes - a #guint + * @see None + * @return gboolean + * @retval the minimum connection time, in minutes. + */ +gboolean location_route_options_set_minimum_change_time(LocationRouteOptions *options, guint minutes); + + +/** Gets the minimum connection time, in minutes. */ +/** + * @brief Gets the minimum connection time, in minutes. + * @remarks None. + * @pre None. + * @post None. + * @param [in] options - a #LocationRouteOptions + * @see None + * @return guint + * @retval the minimum connection time, in minutes + */ +guint location_route_options_get_minimum_change_time(const LocationRouteOptions *options); + +/** + * @brief Sets whether a transit type is allowed. + * @remarks None. + * @pre None + * @post None. + * @param [in] options - a #LocationRouteOptions + * @param [in] type - a #TransitType + * @param [in] allow - a #gboolean + * @see None + * @return gboolean + * @retval TRUE if sucess + */ +gboolean location_route_options_set_transit_type_allowed(LocationRouteOptions *options, TransitType type, gboolean allow); + +/** + * @brief Checks whether a transit type is allowed + * @remarks None. + * @pre None. + * @post None. + * @param [in] options - a #LocationRouteOptions + * @param [in] type - a #TransitType + * @see None + * @return gboolean + * @retval TRUE if sucess + */ +gboolean location_route_options_is_transit_type_allowed(const LocationRouteOptions *options, TransitType type); + +/** + * @brief Sets the maximum number of vehicle changes allowed during the trip. + * @remarks None. + * @pre None. + * @post None. + * @param [in] options - a #LocationRouteOptions + * @param [in] changes - a #guint + * @see None + * @return gboolean + * @retval TRUE if sucess + */ +gboolean location_route_options_set_maximum_changes(LocationRouteOptions *options, guint changes); + +/** + * @brief Gets the maximum number of vehicle changes allowed during the trip. + * @remarks None. + * @pre None. + * @post None. + * @param [in] options - a #LocationRouteOptions + * @see None. + * @return guint + * @retval the maximum number + */ +guint location_route_options_get_maximum_changes(const LocationRouteOptions *options); + +/** + * @brief Sets time of arrival or departure. + * @remarks None. + * @pre None. + * @post None. + * @param [in] options - a #LocationRouteOptions + * @param [in] departure_time - a #guint + * @see None + * @return gboolean + * @retval TRUE if sucess + */ +gboolean location_route_options_set_departure_time(LocationRouteOptions *options, guint departure_time); + +/** + * @brief Returns the time + * @remarks None. + * @pre None. + * @post None. + * @param [in] options - a #LocationRouteOptions + * @see None + * @return guint + * @retval the time + */ +guint location_route_options_get_departure_time(LocationRouteOptions *options); + +/** + * @brief Sets time of arrival. + * @remarks None. + * @pre None. + * @post None. + * @param [in] options - a #LocationRouteOptions + * @param [in] arrival_time - a #guint + * @see None + * @return gboolean + * @retval TRUE if sucess + */ +gboolean location_route_options_set_arrival_time(LocationRouteOptions *options, guint arrival_time); + +/** + * @brief Returns the arrival time + * @remarks None. + * @pre None + * @post None. + * @param [in] options - a #LocationRouteOptions + * @see None + * @return None + * @retval None + */ +guint location_route_options_get_arrival_time(LocationRouteOptions *options); + +/** + * @} @} @} + */ + +G_END_DECLS + +#endif diff --git a/location/map-service/map-internal.c b/location/map-service/map-internal.c new file mode 100644 index 0000000..342ac30 --- /dev/null +++ b/location/map-service/map-internal.c @@ -0,0 +1,241 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "location-log.h" +#include "location-types.h" +#include "module-internal.h" +#include "location-route.h" +#include "location-map-ielement.h" +#include "map-service.h" + +int +map_service_get_geocode (LocationMapIElement *self, + const LocationAddress *address, + const LocationMapPref *svc_pref, + GList **position_list, + GList **accuracy_list) +{ + LOCATION_LOGD("map_service_get_geocode"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.get_geocode, LOCATION_ERROR_NOT_AVAILABLE); + return (priv->mod->ops.get_geocode)(priv->mod->handler, address, svc_pref, position_list, accuracy_list); +} + +int +map_service_get_geocode_freeform (LocationMapIElement *self, + const gchar *address, + const LocationMapPref *svc_pref, + GList **position_list, + GList **accuracy_list) +{ + LOCATION_LOGD("map_service_get_geocode_freeform"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.get_geocode_freetext, LOCATION_ERROR_NOT_AVAILABLE); + return (priv->mod->ops.get_geocode_freetext)(priv->mod->handler, address, svc_pref, position_list, accuracy_list); +} + +int +map_service_get_reversegeocode (LocationMapIElement *self, + const LocationPosition *position, + const LocationMapPref *svc_pref, + LocationAddress **address, + LocationAccuracy **accuracy) +{ + LOCATION_LOGD("map_service_get_reversegeocode"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.get_reverse_geocode, LOCATION_ERROR_NOT_AVAILABLE); + return (priv->mod->ops.get_reverse_geocode)(priv->mod->handler, position, svc_pref, address, accuracy); +} + +int +map_service_get_geocode_async (LocationMapIElement *self, + const LocationAddress *address, + const LocationMapPref *svc_pref, + LocationPositionCB callback, + gpointer userdata) +{ + LOCATION_LOGD("map_service_get_geocode_async"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.get_geocode_async, LOCATION_ERROR_NOT_AVAILABLE); + return (priv->mod->ops.get_geocode_async)(priv->mod->handler, address, svc_pref, callback, userdata); +} + +int +map_service_get_geocode_freeform_async (LocationMapIElement *self, + const gchar *address, + const LocationMapPref *svc_pref, + LocationPositionCB callback, + gpointer userdata) +{ + LOCATION_LOGD("map_service_get_geocode_freeform_async"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.get_geocode_freetext_async, LOCATION_ERROR_NOT_AVAILABLE); + return (priv->mod->ops.get_geocode_freetext_async)(priv->mod->handler, address, svc_pref, callback, userdata); +} + +int +map_service_get_reversegeocode_async (LocationMapIElement *self, + const LocationPosition *position, + const LocationMapPref *svc_pref, + LocationAddressCB callback, + gpointer userdata) +{ + LOCATION_LOGD("map_service_get_reversegeocode_async"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.get_reverse_geocode_async, LOCATION_ERROR_NOT_AVAILABLE); + return (priv->mod->ops.get_reverse_geocode_async)(priv->mod->handler, position, svc_pref, callback, userdata); +} + +int +map_service_search_poi (LocationMapIElement *self, + const LocationPOIFilter *filter, const LocationPosition *position, + const LocationMapPref *svc_pref, const LocationPOIPreference *pref, + LocationPOICB cb, const gpointer user_data, guint *req_id) +{ + LOCATION_LOGD("map_service_search_poi"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.search_poi, LOCATION_ERROR_NOT_AVAILABLE); + return (priv->mod->ops.search_poi)(priv->mod->handler, filter, position, svc_pref, pref, cb, user_data, req_id); +} + +int +map_service_search_poi_by_area (LocationMapIElement *self, + const LocationPOIFilter * filter, const LocationBoundary *boundary, + const LocationMapPref *svc_pref, const LocationPOIPreference * pref, + LocationPOICB cb, const gpointer user_data, guint *req_id) +{ + LOCATION_LOGD("map_service_search_poi_by_area"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.search_poi_by_area, LOCATION_ERROR_NOT_AVAILABLE); + return (priv->mod->ops.search_poi_by_area)(priv->mod->handler, filter, boundary, svc_pref, pref, cb, user_data, req_id); +} + +int +map_service_search_poi_by_address (LocationMapIElement *self, + const LocationPOIFilter *filter, const LocationAddress *address, + const LocationMapPref *svc_pref, const LocationPOIPreference *pref, + LocationPOICB cb, const gpointer user_data, guint *req_id) +{ + LOCATION_LOGD("map_service_search_poi_by_address"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.search_poi_by_address, LOCATION_ERROR_NOT_AVAILABLE); + return (priv->mod->ops.search_poi_by_address)(priv->mod->handler, filter, address, svc_pref, pref, cb, user_data, req_id); +} + +int +map_service_search_poi_by_freeform (LocationMapIElement *self, + const LocationPOIFilter *filter, const gchar *freeform, + const LocationMapPref *svc_pref, const LocationPOIPreference *pref, + LocationPOICB cb, const gpointer user_data, guint *req_id) +{ + LOCATION_LOGD("map_service_search_poi_by_freeform"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.search_poi_by_freeform, LOCATION_ERROR_NOT_AVAILABLE); + return (priv->mod->ops.search_poi_by_freeform)(priv->mod->handler, filter, freeform, svc_pref, pref, cb, user_data, req_id); +} + +int +map_service_cancel_poi_request (LocationMapIElement *self, guint req_id) +{ + LOCATION_LOGD("map_service_cancel_poi_request"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.cancel_poi_request, LOCATION_ERROR_NOT_AVAILABLE); + return (priv->mod->ops.cancel_poi_request)(priv->mod->handler, req_id); +} + + +int +map_service_request_route (LocationMapIElement *self, + const LocationPosition *origin, const LocationPosition *destination, GList *waypoint, + const LocationMapPref *svc_pref, const LocationRoutePreference * pref, + LocationRouteCB cb, const gpointer user_data, guint * req_id) +{ + LOCATION_LOGD("map_service_request_route"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.request_route, LOCATION_ERROR_NOT_AVAILABLE); + + return (priv->mod->ops.request_route)(priv->mod->handler, origin, destination, waypoint, svc_pref, pref, cb, user_data, req_id); +} + +int +map_service_cancel_route_request (LocationMapIElement *self, guint req_id) +{ + LOCATION_LOGD("map_service_cancel_route_request"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.cancel_route_request, LOCATION_ERROR_NOT_AVAILABLE); + + return (priv->mod->ops.cancel_route_request)(priv->mod->handler, req_id); +} + +gboolean +map_service_is_supported_provider_capability (LocationMapIElement *self, LocationMapServiceType type) +{ + LOCATION_LOGD("map_service_is_supported_provider_capability"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.is_supported_provider_capability, LOCATION_ERROR_NOT_AVAILABLE); + + return (priv->mod->ops.is_supported_provider_capability)(priv->mod->handler, type); +} + +int +map_service_get_provider_capability_key (LocationMapIElement *self, LocationMapServiceType type, GList **key) +{ + LOCATION_LOGD("map_service_get_provider_capability_key"); + MapServicePrivate* priv = GET_PRIVATE(self); + g_return_val_if_fail (priv->mod, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->handler, LOCATION_ERROR_NOT_AVAILABLE); + g_return_val_if_fail (priv->mod->ops.get_provider_capability_key, LOCATION_ERROR_NOT_AVAILABLE); + + return (priv->mod->ops.get_provider_capability_key)(priv->mod->handler, type, key); +} + diff --git a/location/map-service/map-internal.h b/location/map-service/map-internal.h new file mode 100644 index 0000000..b99a922 --- /dev/null +++ b/location/map-service/map-internal.h @@ -0,0 +1,82 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MAP_INTERNAL_H__ +#define __MAP_INTERNAL_H__ + +#include "location-map-types.h" +#include "location-map-ielement.h" + +/** + * @file map-internal.h + * @brief This file contains the internal definitions and structures related to geocode. + */ + +G_BEGIN_DECLS + +int map_service_get_geocode (LocationMapIElement *self, const LocationAddress *address, const LocationMapPref *svc_pref, GList **position_list, GList **accuracy_list); + +int map_service_get_geocode_freeform (LocationMapIElement *self, const gchar *address, const LocationMapPref *svc_pref, GList **position_list, GList **accuracy_list); + +int map_service_get_reversegeocode (LocationMapIElement *self, const LocationPosition *position, const LocationMapPref *svc_pref, LocationAddress **address, LocationAccuracy **accuracy); + +int map_service_get_geocode_async (LocationMapIElement *self, const LocationAddress *address, const LocationMapPref *svc_pref, LocationPositionCB callback, gpointer userdata); + +int map_service_get_geocode_freeform_async (LocationMapIElement *self, const gchar *address, const LocationMapPref *svc_pref, LocationPositionCB callback, gpointer userdata); + +int map_service_get_reversegeocode_async (LocationMapIElement *self, const LocationPosition *position, const LocationMapPref *svc_pref, LocationAddressCB callback, gpointer userdata); + +int map_service_search_poi (LocationMapIElement *self, + const LocationPOIFilter *filter, const LocationPosition *position, + const LocationMapPref *svc_pref, const LocationPOIPreference *pref, + LocationPOICB cb, const gpointer user_data, guint * req_id); + +int map_service_search_poi_by_area (LocationMapIElement *self, + const LocationPOIFilter *filter, const LocationBoundary *boundary, + const LocationMapPref *svc_pref, const LocationPOIPreference *pref, + LocationPOICB cb, const gpointer user_data, guint * req_id); + +int map_service_search_poi_by_address (LocationMapIElement *self, + const LocationPOIFilter *filter, const LocationAddress *address, + const LocationMapPref *svc_pref, const LocationPOIPreference *pref, + LocationPOICB cb, const gpointer user_data, guint * req_id); + +int map_service_search_poi_by_freeform (LocationMapIElement *self, + const LocationPOIFilter * filter, const gchar *freeform, + const LocationMapPref *svc_pref, const LocationPOIPreference *pref, + LocationPOICB cb, const gpointer user_data, guint *req_id); + +int map_service_cancel_poi_request (LocationMapIElement *self, guint req_id); + +int map_service_request_route (LocationMapIElement *self, + const LocationPosition *origin, const LocationPosition *destination, GList *waypoint, + const LocationMapPref *svc_pref, const LocationRoutePreference *pref, + LocationRouteCB cb, const gpointer user_data, guint * req_id); + +int map_service_cancel_route_request (LocationMapIElement *self, guint req_id); + +gboolean map_service_is_supported_provider_capability (LocationMapIElement *self, LocationMapServiceType type); + +int map_service_get_provider_capability_key (LocationMapIElement *self, LocationMapServiceType type, GList **key); + +G_END_DECLS + +#endif diff --git a/location/map-service/map-service.c b/location/map-service/map-service.c new file mode 100644 index 0000000..d578a1d --- /dev/null +++ b/location/map-service/map-service.c @@ -0,0 +1,340 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include "location-log.h" +#include "location-map-pref.h" + +#include "module-internal.h" + +#include "map-internal.h" +#include "map-service.h" +#include "location-map-ielement.h" + +#define MAP_SERVICE_PREFIX "map-service" + +gchar *provider_list[] = { + "decarta", + "osm", +}; + + +enum { + PROP_0, + PROP_PROVIDER, + PROP_MAX +}; + +static GParamSpec *pspec[PROP_MAX] = {NULL, }; + +static void map_service_ielement_interface_init (LocationMapIElementInterface *iface); +gchar *map_service_get_default_provider (GObject *obj); + +G_DEFINE_TYPE_WITH_CODE (MapService, map_service, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (LOCATION_MAP_TYPE_IELEMENT, map_service_ielement_interface_init)); + +static void +_get_lang (gchar country_code[3], gchar lang_code[3]) +{ + if (!country_code || !lang_code) return; + gchar* langset = vconf_get_str(VCONFKEY_LANGSET); + LOCATION_LOGD("getenv: %s", langset); + + if(langset == NULL){ + lang_code[0] = 'E'; + lang_code[1] = 'N'; + lang_code[2] = '\0'; + country_code[0] = 'U'; + country_code[1] = 'S'; + country_code[2] = '\0'; + }else{ + gchar* langset_upper = g_ascii_strup(langset, -1); + lang_code[0] = langset_upper[0]; + lang_code[1] = langset_upper[1]; + lang_code[2] = '\0'; + country_code[0] = langset_upper[3]; + country_code[1] = langset_upper[4]; + country_code[2] = '\0'; + g_free(langset_upper); + } + LOCATION_LOGD("Language: %s, Country: %s", lang_code, country_code); +} + + +static void +map_service_dispose (GObject *gobject) +{ + LOCATION_LOGD("map_service_dispose"); + + G_OBJECT_CLASS (map_service_parent_class)->dispose (gobject); +} + +static void +map_service_finalize (GObject *gobject) +{ + LOCATION_LOGD("map_service_finalize"); + MapServicePrivate* priv = GET_PRIVATE(gobject); + module_free(priv->mod, "map-service"); + priv->mod = NULL; + G_OBJECT_CLASS (map_service_parent_class)->finalize (gobject); +} + +static void +map_service_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + LOCATION_LOGD("Enter map_service_get_property"); + MapServicePrivate *priv = GET_PRIVATE (object); + + g_return_if_fail(priv->mod); + g_return_if_fail(priv->mod->handler); + switch (property_id){ + case PROP_PROVIDER:{ + char* service_name = NULL; + if(priv->mod->ops.get_service_name){ + if( LOCATION_ERROR_NONE != priv->mod->ops.get_service_name(priv->mod->handler, &service_name) ){ + service_name = NULL; + } + } + LOCATION_LOGD("Get prop>> Service name: %s", service_name); + g_value_set_string(value, service_name); + g_free(service_name); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +map_service_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + LOCATION_LOGD("map_service_set_property"); + MapServicePrivate *priv = GET_PRIVATE (object); + + switch (property_id) { + case PROP_PROVIDER: { + char buf[256] = {0, }; + gchar *service = g_value_dup_string(value); + + if (priv->mod && priv->pref) { + char *cur_provider = location_map_pref_get_provider_name (priv->pref); + if (g_strcmp0 (cur_provider, MAP_SERVICE_PREFIX) == 0) { + snprintf(buf, 255, "%s", cur_provider); + } + else { + snprintf(buf, 255, "%s-%s", MAP_SERVICE_PREFIX, cur_provider); + } + module_free(priv->mod, buf); + memset (buf, 0x0, 256); + priv->mod = NULL; + } + + if (service == NULL) { + snprintf (buf, 255, "%s", MAP_SERVICE_PREFIX); + service = map_service_get_default_provider(object); + } else { + snprintf (buf, 255, "%s-%s", MAP_SERVICE_PREFIX, service); + } + + priv->mod = (LocationServiceMod *)module_new (buf); + if (priv->mod == NULL) { + priv->mod = (LocationServiceMod *) module_new (MAP_SERVICE_PREFIX); + service = map_service_get_default_provider(object); + } + + if (priv->pref) { + location_map_pref_set_provider_name (priv->pref, service); + } + + g_free (service); + break; + } + } +} + +static void +map_service_ielement_interface_init (LocationMapIElementInterface *iface) +{ + iface->get_geocode = (TYPE_GET_GEOCODE)map_service_get_geocode; + iface->get_geocode_freeform = (TYPE_GET_GEOCODE_FREEFORM)map_service_get_geocode_freeform; + iface->get_reversegeocode = (TYPE_GET_REVERSEGEOCODE)map_service_get_reversegeocode; + iface->get_geocode_async = (TYPE_GET_GEOCODE_ASYNC)map_service_get_geocode_async; + iface->get_geocode_freeform_async = (TYPE_GET_GEOCODE_FREEFORM_ASYNC)map_service_get_geocode_freeform_async; + iface->get_reversegeocode_async = (TYPE_GET_REVERSEGEOCODE_ASYNC)map_service_get_reversegeocode_async; + iface->search_poi = (TYPE_SEARCH_POI) map_service_search_poi; + iface->search_poi_by_area = (TYPE_SEARCH_POI_BY_AREA) map_service_search_poi_by_area; + iface->search_poi_by_address = (TYPE_SEARCH_POI_BY_ADDR) map_service_search_poi_by_address; + iface->search_poi_by_freeform = (TYPE_SEARCH_POI_BY_FREEFORM) map_service_search_poi_by_freeform; + iface->cancel_poi_request = (TYPE_CANCEL_POI_REQUEST) map_service_cancel_poi_request; + iface->request_route = (TYPE_REQUEST_ROUTE) map_service_request_route; + iface->cancel_route_request = (TYPE_CANCEL_ROUTE_REQUEST) map_service_cancel_route_request; + iface->is_supported_provider_capability = (TYPE_IS_SUPPORTED_PROVIDER_CAPABILITY) map_service_is_supported_provider_capability; + iface->get_provider_capability_key = (TYPE_GET_PROVIDER_CAPABILITY_KEY) map_service_get_provider_capability_key; + +} + +static void +map_service_init (MapService *self) +{ + LOCATION_LOGD("map_service_init"); + MapServicePrivate* priv = GET_PRIVATE(self); + + priv->pref = location_map_pref_new (); + if(!priv->pref) LOCATION_LOGW("Service preference failed"); + + gchar country[3], lang[3]; + _get_lang (country, lang); + location_map_pref_set_language (priv->pref, lang); + location_map_pref_set_distance_unit (priv->pref, "MI"); + location_map_pref_set_provider_name (priv->pref, "decarta"); +} + +static void +map_service_class_init (MapServiceClass *klass) +{ + LOCATION_LOGD("map_service_class_init"); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->get_property = map_service_get_property; + gobject_class->set_property = map_service_set_property; + + gobject_class->dispose = map_service_dispose; + gobject_class->finalize = map_service_finalize; + + g_type_class_add_private (klass, sizeof (MapServicePrivate)); + + pspec[PROP_PROVIDER] = g_param_spec_string ("provider", + "map service provider name prop", + "map service provider name", + MAP_SERVICE_PREFIX, + G_PARAM_READWRITE); + g_object_class_install_properties (gobject_class, + PROP_MAX, + pspec); +} + +LocationMapPref * +map_service_get_pref(GObject *obj) +{ + LOCATION_LOGD("map_service_get_pref"); + MapServicePrivate* priv = GET_PRIVATE(obj); + if (!priv) return NULL; + if (!priv->pref) return NULL; + + LocationMapPref *pref = location_map_pref_copy(priv->pref); + + return pref; +} + +gboolean +map_service_set_pref (GObject *obj, LocationMapPref *pref) +{ + LOCATION_LOGD("map_service_set_pref"); + + gchar *provider = NULL; + MapServicePrivate* priv = GET_PRIVATE(obj); + if (!priv) return FALSE; + if (!priv->pref) location_map_pref_free(priv->pref); + + priv->pref = location_map_pref_copy (pref); + provider = location_map_pref_get_provider_name (pref); + if (provider) { + g_object_set (obj, "provider", provider, NULL); + } + + return TRUE; +} + +GList * +map_service_get_supported_providers (GObject *obj) +{ + LOCATION_LOGD("map_service_get_supported_providers"); + + int idx; + gchar buf[128] = {0, }; + GList *list = NULL; + + for (idx = 0; idx < sizeof(provider_list)/sizeof(gchar*); idx++) { + memset (buf, 0x0, 128); + snprintf(buf, 127, "%s-%s", MAP_SERVICE_PREFIX, provider_list[idx]); + if (module_is_supported(buf) == TRUE) { + list = g_list_append(list, g_strdup (provider_list[idx])); + } + } + + return list; +} + +gchar * +map_service_get_default_provider (GObject *obj) +{ + LOCATION_LOGD("map_service_get_default_provider"); + + int idx = 0; + gchar *path = mod_get_realpath (MAP_SERVICE_PREFIX); + if (!path) return NULL; + + for (idx = 0; idx < sizeof(provider_list)/sizeof(gchar*); idx++) { + if (strstr (path, provider_list[idx]) != NULL) { + break; + } + } + + if (idx == sizeof(provider_list)/sizeof(gchar*)) { + return NULL; + } + + g_free (path); + return g_strdup (provider_list[idx]); +} + +gboolean +map_service_set_provider (GObject *obj, gchar *provider) +{ + LOCATION_LOGD("map_service_get_default_provider"); + gchar *set_provider = NULL; + + g_object_set (obj, "provider", provider, NULL); + g_object_get (obj, "provider", &set_provider, NULL); + + if (set_provider && strcmp (provider, set_provider) != 0) { + LOCATION_LOGE("Requested [%s], but current provider [%s]", provider, set_provider); + g_free (set_provider); + return FALSE; + } + + g_free (set_provider); + return TRUE; +} diff --git a/location/map-service/map-service.h b/location/map-service/map-service.h new file mode 100644 index 0000000..98af02d --- /dev/null +++ b/location/map-service/map-service.h @@ -0,0 +1,71 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MAP_SERVICE_H__ +#define __MAP_SERVICE_H__ + +#include +#include + +/** + * @file map-service.h + * @brief This file contains the internal definitions and structures related to a service provider. + */ + +G_BEGIN_DECLS + +typedef struct _MapService MapService; +typedef struct _MapServiceClass MapServiceClass; +typedef struct _MapServicePrivate MapServicePrivate; + +#define MAP_TYPE_SERVICE (map_service_get_type ()) +#define MAP_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MAP_TYPE_SERVICE, MapService)) +#define MAP_IS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MAP_TYPE_SERVICE)) +#define MAP_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MAP_TYPE_SERVICE, MapServiceClass)) +#define MAP_IS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MAP_TYPE_SERVICE)) +#define MAP_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MAP_TYPE_SERVICE, MapServiceClass)) + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MAP_TYPE_SERVICE, MapServicePrivate)) + +struct _MapService +{ + GObject parent_instance; +}; + +struct _MapServiceClass +{ + GObjectClass parent_class; +}; + +struct _MapServicePrivate { + LocationServiceMod* mod; + LocationMapPref *pref; +}; + +GType map_service_get_type (void); + +LocationMapPref *map_service_get_pref(GObject *obj); + +gboolean map_service_set_pref (GObject *obj, LocationMapPref *pref); + +G_END_DECLS + +#endif /* __MAP_SERVICE_H__ */ diff --git a/location/module/Makefile.am b/location/module/Makefile.am new file mode 100644 index 0000000..d517f09 --- /dev/null +++ b/location/module/Makefile.am @@ -0,0 +1,20 @@ +noinst_LTLIBRARIES = liblocation-module.la + +COMMON_HEADER_DIR = include +MANAGER_DIR = manager +MAP_SERVICE_DIR = map-service +MODULE_DIR = module + +liblocation_module_la_SOURCES = \ + module-internal.c + +liblocation_module_la_CFLAGS = \ + -fPIC\ + -I${srcdir} \ + -I${srcdir}/.. \ + -I${srcdir}/../include \ + -I${srcdir}/../${MANAGER_DIR} \ + -I${srcdir}/../${MODULE_DIR} \ + -I${srcdir}/../${MAP_SERVICE_DIR} \ + $(LOCATION_CFLAGS) + diff --git a/location/module/location-module.h b/location/module/location-module.h new file mode 100644 index 0000000..d21dae9 --- /dev/null +++ b/location/module/location-module.h @@ -0,0 +1,148 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOCATION_MODULE_H__ +#define __LOCATION_MODULE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +/** + * @file location-module.h + * @brief This file contains the structure and enumeration for location plug-in development. + */ + +/** + * @addtogroup LocationFW + * @{ + * @defgroup LocationModules Location Modules + * @brief This sub module provides the definitions and structrues for 3rd party plugin modules. + * @addtogroup LocationModules + * @{ + */ + +/** + * @brief This represents APIs declared in a geocode plug-in for location geocode modules. + */ +typedef struct{ + int (*get_service_name)(gpointer handle, gchar **servicename); + ///< This is used for getting a service name from a plug-in. + int (*get_geocode)(gpointer handle, const LocationAddress *address, const LocationMapPref *svc_pref, GList **position_list, GList **accuracy_list); + ///< This is used for getting a geocode from a plug-in. + int (*get_geocode_freetext)(gpointer handle, const gchar *address, const LocationMapPref *svc_pref, GList **position_list, GList **accuracy_list); + ///< This is used for getting a geocode by using a free-fromed address from a plug-in. + int (*get_reverse_geocode)(gpointer handle, const LocationPosition *position, const LocationMapPref *svc_pref, LocationAddress **address, LocationAccuracy **accuracy); + ///< This is used for getting a reverse geocode from a plug-in. + int (*get_geocode_async)(gpointer handle, const LocationAddress *address, const LocationMapPref *svc_pref, LocationPositionCB callback, gpointer userdata); + ///< This is used for getting a geocode from a plug-in asynchronously. + int (*get_geocode_freetext_async)(gpointer handle, const gchar *address, const LocationMapPref *svc_pref, LocationPositionCB callback, gpointer userdata); + ///< This is used for getting a geocode by using a free-fromed address from a plug-in asynchronously. + int (*get_reverse_geocode_async)(gpointer handle, const LocationPosition *position, const LocationMapPref *svc_pref, LocationAddressCB callback, gpointer userdata); + ///< This is used for getting a reverse geocode from a plug-in asynchronously. + int (*search_poi) (gpointer handle, const LocationPOIFilter *filter, const LocationPosition *position, const LocationMapPref *svc_pref, const LocationPOIPreference *pref, LocationPOICB cb, const gpointer user_data, guint * req_id); + ///< This is used for searching poi with the position from a plug-in asynchronously. + int (*search_poi_by_area) (gpointer handle, const LocationPOIFilter *filter, const LocationBoundary *boundary, const LocationMapPref *svc_pref, const LocationPOIPreference *pref, LocationPOICB cb, const gpointer user_data, guint * req_id); + ///< This is used for searching poi with the boundary from a plug-in asynchronously. + int (*search_poi_by_address) (gpointer handle, const LocationPOIFilter *filter, const LocationAddress *address, const LocationMapPref *svc_pref, const LocationPOIPreference *pref, LocationPOICB cb, const gpointer user_data, guint * req_id); + ///< This is used for searching poi with the address from a plug-in asynchronously. + int (*search_poi_by_freeform) (gpointer handle, const LocationPOIFilter * filter, const gchar *freeform, const LocationMapPref *svc_pref, const LocationPOIPreference *pref, LocationPOICB cb, const gpointer user_data, guint *req_id); + ///< This is used for searching poi with the freeform address from a plug-in asynchronously. + int (*cancel_poi_request) (gpointer handle, guint req_id); + ///< This is used for cancel poi request from a plug-in. + int (*request_route) (gpointer handle, const LocationPosition *origin, const LocationPosition *destination, GList *waypoint, const LocationMapPref *svc_pref, const LocationRoutePreference * pref, LocationRouteCB cb, const gpointer user_data, guint * req_id); + ///< This is used for requesting route from a plug-in asynchronously. + int (*cancel_route_request) (gpointer handle, guint req_id); + ///< This is used for cancel route request from a plug-in. + gboolean (*is_supported_provider_capability) (gpointer handle, LocationMapServiceType type); + ///< This is used to check whether map service is supported on a plug-in. + int (*get_provider_capability_key) (gpointer handle, LocationMapServiceType type, GList **key); + ///< This is used to get map service keys on a plug-in. +} LocModServiceOps; + +/** +* @brief This represents a enabled/disabled callback function for a plug-in. +*/ +typedef void (*LocModStatusCB)(gboolean enabled, LocationStatus status, gpointer userdata); + +/** + * @brief This represents a position callback function for a plug-in. + */ +typedef void (*LocModPositionExtCB) (gboolean enabled, LocationPosition *position, LocationVelocity *velocity, LocationAccuracy *accuracy, gpointer userdata); + +/** + * @brief This represents a velocity callback function for a plug-in. + */ +typedef void (*LocModSatelliteCB) (gboolean enabled, LocationSatellite *satellite, gpointer userdata); + +/** + * @brief This represents APIs declared in a GPS plug-in for location GPS modules. + */ +typedef struct{ + int (*start)(gpointer handle, LocModStatusCB status_cb, LocModPositionExtCB pos_ext_cb, LocModSatelliteCB sat_cb, gpointer userdata); ///< This is used for starting a GPS device from a plug-in. #LocModStatusCB, #LocModPositionExtCB are given from a location framework to a plug-in for asynchronous signaling. + int (*stop)(gpointer handle); ///< This is used for stopping a GPS device name from a plug-in. + int (*get_position)(gpointer handle, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy); ///< This is used for getting a position from a plug-in. + int (*get_last_position)(gpointer handle, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy); ///< This is used for getting a last position from a plug-in. + int (*get_nmea)(gpointer handle, gchar** nmea_data); ///< This is used for getting a nmea string from a plug-in. + int (*get_satellite)(gpointer handle, LocationSatellite **satellite); ///< This is used for getting a satellite information from a plug-in. + int (*get_last_satellite)(gpointer handle, LocationSatellite **satellite); ///< This is used for getting a last satellite information from a plug-in. + int (*set_devname)(gpointer handle, const gchar *devname); ///< This is used for setting a device name from a plug-in. + int (*get_devname)(gpointer handle, gchar **devname); ///< This is used for getting a device name from a plug-in. +} LocModGpsOps; + +/** + * @brief This represents APIs declared in a WPS plug-in for location WPS modules. + */ +typedef struct{ + int (*start)(gpointer handle, LocModStatusCB status_cb, LocModPositionExtCB pos_ext_cb, LocModSatelliteCB sat_cb, gpointer userdata); ///< This is used for starting a WPS service from a plug-in. #LocModStatusCB, #LocModPositionExtCB and #LocModSatelliteCB(Not used) are given from a location framework to a plug-in for asynchronous signaling. + int (*stop)(gpointer handle); ///< This is used for stopping a WPS service from a plug-in. + int (*get_position)(gpointer handle, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy); ///< This is used for getting a position from a plug-in. + int (*get_last_position)(gpointer handle, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy); ///< This is used for getting a last position from a plug-in. +} LocModWpsOps; + +/** + * @brief This represents APIs declared in a CPS plug-in for location CPS modules. + */ +typedef struct{ + int (*start)(gpointer handle, LocModStatusCB status_cb, LocModPositionExtCB pos_ext_cb, LocModSatelliteCB sat_cb, gpointer userdata); ///< This is used for starting a WPS service from a plug-in. #LocModStatusCB, #LocModPositionExtCB and #LocModSatelliteCB(Not used) are given from a location framework to a plug-in for asynchronous signaling. + int (*stop)(gpointer handle); + int (*get_position)(gpointer handle, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy); ///< This is used for getting a position from a plug-in. + int (*get_last_position)(gpointer handle, LocationPosition **position, LocationVelocity **velocity, LocationAccuracy **accuracy); ///< This is used for getting a last position from a plug-in. +} LocModCpsOps; + +/** + * @brief This is used for exported APIs in a plug-in for a location framework. + */ +#define LOCATION_MODULE_API __attribute__((visibility("default"))) G_MODULE_EXPORT + +/** + * @} @} + */ +G_END_DECLS + +#endif diff --git a/location/module/module-internal.c b/location/module/module-internal.c new file mode 100644 index 0000000..164587d --- /dev/null +++ b/location/module/module-internal.c @@ -0,0 +1,348 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include "module-internal.h" +#include "location-log.h" + +#define MAX_MODULE_INDEX 3 +const char* MODULE_PATH_PREFIX = "/usr/lib/location/module"; + +static GMod* +gmod_new (const char* module_name, gboolean is_resident) +{ + if(!module_name) + return NULL; + + GMod* gmod = g_new0(GMod, 1); + gmod->name = g_strdup(module_name); + if(!gmod->name) { + g_free(gmod); + return NULL; + } + gmod->path = g_module_build_path (MODULE_PATH_PREFIX, gmod->name); + if(!gmod->path){ + g_free(gmod->name); + g_free(gmod); + gmod->name = NULL; + return NULL; + } + gmod->module = g_module_open(gmod->path, G_MODULE_BIND_LAZY); + if(!gmod->module){ + g_free(gmod->name); + g_free(gmod->path); + g_free(gmod); + gmod->name = NULL; + gmod->path = NULL; + + return NULL; + } + if(is_resident) + g_module_make_resident(gmod->module); + + return gmod; +} + +static void +gmod_free (GMod* gmod) +{ + if(gmod->name) + g_free(gmod->name); + if(gmod->path) + g_free(gmod->path); + if(gmod->module) + g_module_close(gmod->module); + g_free(gmod); +} + +static gboolean +gmod_find_sym (GMod* gmod, + gpointer* init_func, gpointer* shutdown_func) +{ + char sym[256]; + g_stpcpy(sym, "init"); + if ( !g_module_symbol (gmod->module, sym, init_func) ){ + LOCATION_LOGW("symbol not found: %s", sym); + return FALSE; + } + g_stpcpy(sym, "shutdown"); + if ( !g_module_symbol (gmod->module, sym, shutdown_func) ){ + LOCATION_LOGW("symbol not found: %s", sym); + return FALSE; + } + return TRUE; +} + +static gpointer +mod_new (const char* module_name) +{ + gpointer ret_mod = NULL; + if(!module_name) + return NULL; + + GMod* gmod = NULL; + gpointer init = NULL; + gpointer shutdown = NULL; + gmod = gmod_new(module_name, TRUE); + if(!gmod){ + LOCATION_LOGW("module(%s) new failed", module_name); + return NULL; + } + if( !gmod_find_sym(gmod, &init, &shutdown) ){ + LOCATION_LOGW("symbol (init, shutdown) finding failed"); + gmod_free(gmod); + return NULL; + } + if(!init || !shutdown){ + LOCATION_LOGW("init, shutdown symbol is NULL"); + gmod_free(gmod); + return NULL; + } + if(g_str_has_prefix(module_name, "map-service")){ + LocationServiceMod* _mod = g_new0(LocationServiceMod, 1); + _mod->gmod = gmod; + _mod->init = init; + _mod->shutdown= shutdown; + _mod->handler= _mod->init(&(_mod->ops)); + if(!_mod->handler){ + LOCATION_LOGW("module init failed"); + gmod_free(_mod->gmod); + ret_mod = NULL; + }else + ret_mod = (gpointer)_mod; + }else if(g_str_has_prefix(module_name, "gps")){ + LocationGpsMod* _mod = g_new0(LocationGpsMod, 1); + _mod->gmod = gmod; + _mod->init = init; + _mod->shutdown= shutdown; + _mod->handler= _mod->init(&(_mod->ops)); + if(!_mod->handler){ + LOCATION_LOGW("module init failed"); + gmod_free(_mod->gmod); + ret_mod = NULL; + }else + ret_mod = (gpointer)_mod; + }else if(g_str_has_prefix(module_name, "wps")){ + LocationWpsMod* _mod = g_new0(LocationWpsMod, 1); + _mod->gmod = gmod; + _mod->init = init; + _mod->shutdown= shutdown; + _mod->handler= _mod->init(&(_mod->ops)); + if(!_mod->handler){ + LOCATION_LOGW("module init failed"); + gmod_free(_mod->gmod); + ret_mod = NULL; + }else + ret_mod = (gpointer)_mod; + }else if(g_str_has_prefix(module_name, "cps")){ + LocationCpsMod* _mod = g_new0(LocationCpsMod, 1); + _mod->gmod = gmod; + _mod->init = init; + _mod->shutdown= shutdown; + _mod->handler= _mod->init(&(_mod->ops)); + if(!_mod->handler){ + LOCATION_LOGW("module init failed"); + gmod_free(_mod->gmod); + ret_mod = NULL; + }else + ret_mod = (gpointer)_mod; + }else{ + LOCATION_LOGW("module name (%s) is wrong", module_name); + ret_mod = NULL; + } + return ret_mod; +} + + +static void +mod_free (gpointer mod, + const char* module_name) +{ + if(!mod || !module_name) + return; + + if(g_str_has_prefix(module_name, "map-service")){ + LocationServiceMod* _mod = (LocationServiceMod*)mod; + if(_mod->shutdown && _mod->handler){ + _mod->shutdown(_mod->handler); + } + _mod->handler = NULL; + _mod->init = NULL; + _mod->shutdown= NULL; + gmod_free(_mod->gmod); + _mod->gmod = NULL; + }else if(0 == g_strcmp0(module_name, "gps")){ + LocationGpsMod* _mod = (LocationGpsMod*)mod; + if(_mod->shutdown && _mod->handler){ + _mod->shutdown(_mod->handler); + } + _mod->handler = NULL; + _mod->init = NULL; + _mod->shutdown= NULL; + gmod_free(_mod->gmod); + _mod->gmod = NULL; + }else if(0 == g_strcmp0(module_name, "wps")){ + LocationWpsMod* _mod = (LocationWpsMod*)mod; + if(_mod->shutdown && _mod->handler){ + _mod->shutdown(_mod->handler); + } + _mod->handler = NULL; + _mod->init = NULL; + _mod->shutdown= NULL; + gmod_free(_mod->gmod); + _mod->gmod = NULL; + }else if(0 == g_strcmp0(module_name, "cps")){ + LocationCpsMod* _mod = (LocationCpsMod*)mod; + if(_mod->shutdown && _mod->handler){ + _mod->shutdown(_mod->handler); + } + _mod->handler = NULL; + _mod->init = NULL; + _mod->shutdown= NULL; + gmod_free(_mod->gmod); + _mod->gmod = NULL; + }else + LOCATION_LOGW("module name (%s) is wrong", module_name); + + g_free(mod); +} + +static gboolean +mod_is_supported(const char *module_name) +{ + GMod * gmod = NULL; + gmod = gmod_new(module_name, FALSE); + if(!gmod) { + return FALSE; + } + gmod_free(gmod); + + return TRUE; +} + +gboolean module_init (void) +{ + if (!g_module_supported()) { + LOCATION_LOGW("module is not supported"); + return FALSE; + } + return TRUE; +} + +void +module_free (gpointer mod, + const char* module_name) +{ + if(!mod || !module_name) + return; + mod_free(mod, module_name); +} + +gpointer +module_new (const char* module_name) +{ + if(!module_name) + return NULL; + int index = 0; + char name[256]; + + gpointer mod = NULL; + for(index = -1 ; index < MAX_MODULE_INDEX ; index++){ + if(index >= 0){ + if( 0 >= g_snprintf(name, 256, "%s%d", module_name, index)){ + LOCATION_LOGW("module name(%s) is wrong", name); + continue; + } + }else{ + if( 0 >= g_snprintf(name, 256, "%s", module_name)){ + LOCATION_LOGW("module name(%s) is wrong", name); + continue; + } + } + mod = mod_new(name); + if(mod){ + LOCATION_LOGW("module (%s) open success", name); + break; + } + LOCATION_LOGW("module (%s) open failed", name); + } + return mod; +} + +gboolean +module_is_supported(const char *module_name) +{ + if(!module_name) + return FALSE; + + int index = 0; + gboolean ret = FALSE; + gboolean found = FALSE; + + char name[256] = {0, }; + + for(index = -1 ; index < MAX_MODULE_INDEX ; index++){ + if(index >= 0){ + g_snprintf(name, 256, "%s%d", module_name, index); + }else{ + g_snprintf(name, 256, "%s", module_name); + } + + ret = mod_is_supported(name); + if(ret == TRUE) { + found = TRUE; + LOCATION_LOGW("module name(%s) is found", name); + break; + } + } + + return found; +} + +gchar * +mod_get_realpath (const gchar *module_name) +{ + gchar origin_path[PATH_MAX] = {0, }; + gchar link_path[PATH_MAX] = {0, }; + gchar *path = NULL; + + snprintf (link_path, PATH_MAX, "%s/lib%s.so", MODULE_PATH_PREFIX, module_name); + + realpath (link_path, origin_path); + + if (strlen(origin_path) == 0) { + LOCATION_LOGE ("Fail to get real path of [%s]", module_name); + return NULL; + } + + path = strrchr(origin_path, '/'); + if (!path) return NULL; + + return g_strdup (path); +} diff --git a/location/module/module-internal.h b/location/module/module-internal.h new file mode 100644 index 0000000..a782062 --- /dev/null +++ b/location/module/module-internal.h @@ -0,0 +1,81 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MODULE_INTERNAL_H__ +#define __MODULE_INTERNAL_H__ + +#include +#include "location-module.h" + +/** + * @file module-internal.h + * @brief This file contains the internal definitions and structures related to module. + */ + +typedef struct{ + GModule* module; + char* name; + char* path; +} GMod; + +typedef struct{ + GMod* gmod; + gpointer handler; + gpointer (*init)(LocModServiceOps* ops); + void (*shutdown)(gpointer handle); + LocModServiceOps ops; +} LocationServiceMod; + +typedef struct{ + GMod* gmod; + gpointer handler; + gpointer (*init)(LocModGpsOps* ops); + void (*shutdown)(gpointer handle); + LocModGpsOps ops; +} LocationGpsMod; + +typedef struct{ + GMod* gmod; + gpointer handler; + gpointer (*init)(LocModWpsOps* ops); + void (*shutdown)(gpointer handle); + LocModWpsOps ops; +} LocationWpsMod; + +typedef struct{ + GMod* gmod; + gpointer handler; + gpointer (*init)(LocModCpsOps* ops); + void (*shutdown)(gpointer handle); + LocModCpsOps ops; +} LocationCpsMod; + +G_BEGIN_DECLS + +gboolean module_init(void); +gpointer module_new(const char* module_name); +void module_free(gpointer mod, const char* module_name); +gboolean module_is_supported(const char *module_name); +gchar *mod_get_realpath(const gchar *module_name); + +G_END_DECLS + +#endif diff --git a/packaging/libslp-location.spec b/packaging/libslp-location.spec new file mode 100755 index 0000000..98dee06 --- /dev/null +++ b/packaging/libslp-location.spec @@ -0,0 +1,94 @@ +Name: libslp-location +Summary: Location Based Service +Version: 0.4.4 +Release: 1 +Group: System/Libraries +License: Apache Licensc, Version 2.0 +Source0: %{name}-%{version}.tar.gz +Requires(post): /sbin/ldconfig +Requires(post): /usr/bin/vconftool +Requires(postun): /sbin/ldconfig +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gconf-2.0) +BuildRequires: pkgconfig(dbus-glib-1) +BuildRequires: pkgconfig(gmodule-2.0) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(location-appman) +BuildRequires: pkgconfig(json-glib-1.0) + + +%description +Location Based Service Libraries + + +%package devel +Summary: Location Based Service (Development files) +Group: System/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +Location Based Service Development Package + + +%prep +%setup -q -n %{name}-%{version} + + +%build + +./autogen.sh +./configure --prefix=%{_prefix} --enable-dlog --enable-debug + +# Call make instruction with smp support +make %{?jobs:-j%jobs} + + +%install +rm -rf %{buildroot} +%make_install + + +%clean +rm -rf %{buildroot} + + +%post +/sbin/ldconfig +vconftool set -t int db/location/last/gps/Timestamp "0" -f +vconftool set -t double db/location/last/gps/Latitude "0.0" -f +vconftool set -t double db/location/last/gps/Longitude "0.0" -f +vconftool set -t double db/location/last/gps/Altitude "0.0" -f +vconftool set -t double db/location/last/gps/HorAccuracy "0.0" -f +vconftool set -t double db/location/last/gps/VerAccuracy "0.0" -f +vconftool set -t double db/location/last/gps/Speed "0.0" -f +vconftool set -t double db/location/last/gps/Direction "0.0" -f +vconftool set -t int db/location/last/wps/Timestamp "0" -f +vconftool set -t double db/location/last/wps/Latitude "0.0" -f +vconftool set -t double db/location/last/wps/Longitude "0.0" -f +vconftool set -t double db/location/last/wps/Altitude "0.0" -f +vconftool set -t double db/location/last/wps/HorAccuracy "0.0" -f +vconftool set -t double db/location/last/wps/Speed "0.0" -f +vconftool set -t double db/location/last/wps/Direction "0.0" -f +vconftool set -t int db/location/last/cps/Timestamp "0" -f +vconftool set -t double db/location/last/cps/Latitude "0.0" -f +vconftool set -t double db/location/last/cps/Longitude "0.0" -f +vconftool set -t double db/location/last/cps/Altitude "0.0" -f +vconftool set -t double db/location/last/cps/HorAccuracy "0.0" -f +vconftool set -t int db/location/setting/GpsEnabled "0" -g 6514 -f +vconftool set -t int db/location/setting/AgpsEnabled "0" -g 6514 -f +vconftool set -t int db/location/setting/NetworkEnabled "0" -g 6514 -f +vconftool set -t int db/location/setting/SensorEnabled "0" -g 6514 -f + + +%postun -p /sbin/ldconfig + + +%files +%manifest libslp-location.manifest +%{_libdir}/lib*.so* + + +%files devel +%{_includedir}/location/*.h +%{_libdir}/pkgconfig/*.pc diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..6da5435 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,37 @@ +dir_location = $(top_srcdir)/location +noinst_PROGRAMS = location-api-test gps-test wps-test hybrid-test cps-test\ + position-sample-gps velocity-sample nmea-sample satellite-sample property-sample zone-sample address-sample map-service-test + +gps_test_SOURCES = gps-test.c +wps_test_SOURCES = wps-test.c +hybrid_test_SOURCES = hybrid-test.c +cps_test_SOURCES = cps-test.c +position_sample_gps_SOURCES = position-sample-gps.c +velocity_sample_SOURCES = velocity-sample.c +nmea_sample_SOURCES = nmea-sample.c +satellite_sample_SOURCES = satellite-sample.c +property_sample_SOURCES = property-sample.c +zone_sample_SOURCES = zone-sample.c +address_sample_SOURCES = address-sample.c +location_api_test_SOURCES = location-api-test.c location-api-test-util.c +map_service_test_SOURCES = map-service-test.c + +LDADD = \ + $(dir_location)/libSLP-location.la\ + $(TEST_LIBS) +AM_CFLAGS = \ + -I$(dir_location) \ + -I$(dir_location)/include \ + -I$(dir_location)/manager \ + -I$(dir_location)/map-service \ + $(TEST_CFLAGS) + +dir_tests = $(top_srcdir)/tests +dir_tests_exec = $(top_srcdir)/tests/.libs + +install-exec-hook: + cp $(dir_tests)/location-api-test.json $(dir_tests_exec)/location-api-test.json + chmod 644 $(dir_tests_exec)/location-api-test.json + +uninstall-hook: + rm -f $(dir_tests_exec)/location-api-test.json diff --git a/tests/address-sample.c b/tests/address-sample.c new file mode 100644 index 0000000..8b155fc --- /dev/null +++ b/tests/address-sample.c @@ -0,0 +1,213 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static GMainLoop *loop = NULL; + +static gboolean +exit_program (gpointer data) +{ + g_main_loop_quit (loop); + g_debug ("Quit g_main_loop"); + return FALSE; +} + +static void +print_pos (gpointer data, gpointer user_data) +{ + LocationPosition *pos = (LocationPosition *)data; + + if (pos) { + g_debug ("time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + location_position_free (pos); + } +} + +static void +print_acc (gpointer data, gpointer user_data) +{ + LocationAccuracy *acc = (LocationAccuracy *)data; + + if (acc) { + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_accuracy_free (acc); + } +} +static void +cb_address (LocationError error, + LocationAddress *addr, + LocationAccuracy *acc, + gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE) { + g_debug("cb_address failed: error=%d\n", error); + return; + } + g_debug ("ASYNC>> location_map_get_address_async> %s %s %s %s %s %s %s", + addr->building_number, addr->street, addr->district, addr->city, addr->state, addr->postal_code, addr->country_code); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +static void +cb_service_disabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_disabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +static void +cb_position_from_address (LocationError error, GList *pos_list, GList *acc_list, gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE) { + g_debug("cb_position_from_address failed: error=%d\n", error); + return; + } + + g_list_foreach (pos_list, print_pos, NULL); + g_list_foreach (acc_list, print_acc, NULL); +} + +static void +cb_position_from_freeformed_address (LocationError error, GList *pos_list, GList *acc_list, gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE) { + g_debug("cb_position_from_freeformed_address failed: error=%d\n", error); + return; + } + + g_list_foreach (pos_list, print_pos, NULL); + g_list_foreach (acc_list, print_acc, NULL); +} + +static void +cb_address_from_position (LocationError error, LocationAddress *addr, LocationAccuracy *acc, gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE) { + g_debug("cb_address_from_position failed: error=%d\n", error); + return; + } + g_debug ("ASYNC>> location_map_get_address_from_position_async> %s %s %s %s %s %s %s", + addr->building_number, addr->street, addr->district, addr->city, addr->state, addr->postal_code, addr->country_code); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +static void +cb_service_enabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +static gboolean +async_request (gpointer loc) +{ + LocationAddress *addr = location_address_new ("1", "Post Street", NULL, "san jose", "ca", NULL, "95113",NULL,NULL,NULL); + LocationError err = location_map_get_position_from_address_async(loc, addr, cb_position_from_address, loc); + if (LOCATION_ERROR_NONE == err) + g_debug("location_map_get_position_from_address_async() success"); + else g_warning ("location_map_get_position_from_address_async() failed> error code:%d", err); + location_address_free (addr); + + gchar *addr_str = g_strdup("4 N 2nd Street 95113"); + err = location_map_get_position_from_freeformed_address_async(loc, addr_str, cb_position_from_freeformed_address, loc); + if (LOCATION_ERROR_NONE == err) + g_debug("location_map_get_position_from_freeformed_address_async() success"); + else g_warning ("location_map_get_position_from_freeformed_address_async() failed> error code:%d", err); + g_free(addr_str); + + LocationPosition *pos = location_position_new (0, 37.3322, -121.8720, 0, LOCATION_STATUS_2D_FIX); + err = location_map_get_address_from_position_async(loc, pos, cb_address_from_position, loc); + if (LOCATION_ERROR_NONE == err) + g_debug("location_map_get_address_from_position_async() success"); + else g_warning ("location_map_get_address_from_position_async() failed> error code:%d", err); + location_position_free (pos); + return FALSE; +} + +int +main (int argc, char *argv[]) +{ + LocationMapObject *loc = NULL; + + // If application is executed by AUL, this is not needed. + g_setenv("PKG_NAME", "org.tizen.address-sample", 1); + + g_type_init(); + location_init (); + loop = g_main_loop_new (NULL, TRUE); + + loc = location_map_new (NULL); + if (!loc) { + g_warning("location_map_new failed"); + return -1; + } + + LocationPosition *pos = NULL; + LocationAccuracy *acc = NULL; + GList *pos_list = NULL; + GList *acc_list = NULL; + LocationAddress *addr = NULL; + + addr = location_address_new ("1", "Post Street", NULL, "san jose", "ca", NULL, "95113",NULL,NULL,NULL); + LocationError err = location_map_get_position_from_address(loc, addr, &pos_list, &acc_list); + if (LOCATION_ERROR_NONE == err) { + g_list_foreach (pos_list, print_pos, NULL); + g_list_foreach (acc_list, print_acc, NULL); + } else g_warning ("SYNC>>>location_map_get_position_from_address() failed> error code:%d", err); + location_address_free (addr); + + char* addr_str = g_strdup("4 N 2nd Street 95113"); + err = location_map_get_position_from_freeformed_address(loc, addr_str, &pos_list, &acc_list); + if (LOCATION_ERROR_NONE == err) { + g_list_foreach (pos_list, print_pos, NULL); + g_list_foreach (acc_list, print_acc, NULL); + } else g_warning ("SYNC>> location_map_get_position_from_freeformed_address() failed> error code:%d", err); + g_free(addr_str); + + pos = location_position_new (0, 37.3322, -121.8720, 0, LOCATION_STATUS_2D_FIX); + err = location_map_get_address_from_position(loc, pos, &addr, &acc); + if (LOCATION_ERROR_NONE == err) { + g_debug ("SYNC>> location_map_get_address_from_position() success> %s %s %s %s %s %s %s", + addr->building_number, addr->street, addr->district, addr->city, addr->state, addr->postal_code, addr->country_code); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_address_free(addr); + location_accuracy_free(acc); + } else g_warning ("SYNC>> location_map_get_address_from_position() failed> error code:%d", err); + location_position_free (pos); + + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + g_signal_connect (loc, "service-disabled", G_CALLBACK(cb_service_disabled), loc); + + g_timeout_add_seconds (3, async_request, loc); + + g_timeout_add_seconds (60, exit_program, NULL); + g_main_loop_run (loop); + + location_map_free (loc); + + return 0; +} diff --git a/tests/cps-test.c b/tests/cps-test.c new file mode 100644 index 0000000..1547fbb --- /dev/null +++ b/tests/cps-test.c @@ -0,0 +1,67 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +int +main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + + // If application is executed by AUL, this is not needed. + g_setenv("PKG_NAME", "org.tizen.cps-test", 1); + + location_init (); + + loc = location_new (LOCATION_METHOD_CPS); + if (!loc) { + g_debug("location_new failed"); + return -1; + } + + LocationMethod method = LOCATION_METHOD_NONE; + g_object_get(loc, "method", &method, NULL); + g_debug("Get property>> method:%d", method); + + LocationAccuracy *acc = NULL; + LocationPosition *pos = NULL; + + if (LOCATION_ERROR_NONE == location_get_position (loc, &pos, &acc)) { + g_debug ("SYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_position_free(pos); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current position> failed"); + + g_object_get(loc, "last-position", &pos, NULL); + if (pos) { + g_debug ("Get property>> last-position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + location_position_free(pos); + } else g_warning("failed to get property> last-position"); + + location_free (loc); + return 0; +} + diff --git a/tests/gps-test.c b/tests/gps-test.c new file mode 100644 index 0000000..b21f8fb --- /dev/null +++ b/tests/gps-test.c @@ -0,0 +1,243 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static GMainLoop *loop = NULL; + +static void +cb_service_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + g_debug("cb_service_updated: type(%d) userdata(0x%x)", type, (unsigned int)userdata); + + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + switch (type) { + case POSITION_UPDATED: { + LocationPosition *pos = (LocationPosition*) data; + g_debug ("ASYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + break; + case VELOCITY_UPDATED: { + LocationVelocity *vel = (LocationVelocity*) data; + g_debug ("ASYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + break; + default: + g_warning ("ASYNC>> Undefined update type"); + break; + } +} + + +static void +cb_service_enabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); + + LocationObject *loc = (LocationObject*)userdata; + LocationAccuracy *acc = NULL; + LocationPosition *pos = NULL; + LocationVelocity *vel = NULL; + LocationSatellite *sat = NULL; + gchar *nmea_data = NULL; + int idx = 0; + + if (LOCATION_ERROR_NONE == location_get_position (loc, &pos, &acc)) { + g_debug ("SYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_position_free(pos); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current position> failed"); + if (LOCATION_ERROR_NONE == location_get_velocity (loc, &vel, &acc)) { + g_debug ("SYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_velocity_free(vel); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current velocity> failed"); + + g_object_get (loc, "satellite", &sat, NULL); + if (sat) { + g_debug ("SYNC>> Current Sattelite> satellite in view = %d, satellite in used = %d", sat->num_of_sat_inview, sat->num_of_sat_used); + g_debug ("\tinview satellite information = "); + for (idx=0; idxnum_of_sat_inview; idx++) { + guint prn; + gboolean used; + guint elevation; + guint azimuth; + gint snr; + location_satellite_get_satellite_details(sat, idx, &prn, &used, &elevation, &azimuth, &snr); + g_debug ("\t\t[%02d] used: %d, prn: %d, elevation: %d, azimuth: %d, snr: %d", + idx, used, prn, elevation, azimuth, snr); + } + location_satellite_free (sat); + } else g_warning ("SYNC>> Current Sattelite> failed"); + + g_object_get(loc, "nmea", &nmea_data, NULL); + if (nmea_data) { + g_debug("SYNC>> Currnet NMEA> nmea_data:\n%s\n", nmea_data); + g_free(nmea_data); + } else g_warning("SYNC>> Current NMEA> failed"); +} + +static void +cb_service_disabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_disabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +static void +cb_zone_in (GObject *self, + gpointer boundary, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + + g_debug ("ASYNC>> ZoneIn> Current position: time: %d, lat: %f, long: %f, alt: %f", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +static void +cb_zone_out (GObject *self, + gpointer boundary, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + + g_debug ("ASYNC>> ZoneOut> Current position: time: %d, lat: %f, long: %f, alt: %f", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +int +main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + + // If application is executed by AUL, this is not needed. + g_setenv("PKG_NAME", "org.tizen.gps-test", 1); + + location_init (); + + loop = g_main_loop_new (NULL, TRUE); + + loc = location_new (LOCATION_METHOD_GPS); + if (!loc) { + g_debug("location_new failed"); + return -1; + } + + LocationMethod method = LOCATION_METHOD_NONE; + g_object_get(loc, "method", &method, NULL); + g_debug("Get property>> method:%d", method); + + char* devname = NULL; + g_object_get(loc, "dev-name", &devname, NULL); + if (devname) { + g_debug("Get property>> dev-name: %s", devname); + } else g_warning("failed to get property> dev-name"); + + devname = NULL; + g_object_set(loc, "dev-name", "/dev/test", NULL); + g_object_get(loc, "dev-name", &devname, NULL); + if (devname) { + g_debug("Get property>> dev-name: %s", devname); + g_free(devname); + } else g_warning("failed to set property> dev-name"); + + LocationBoundary *bound = NULL; + g_object_get(loc, "boundary", &bound, NULL); + if (bound) { + g_debug("Get property>> boundary> type: %d", bound->type); + } else g_warning("failed to get property> boundary"); + + bound = NULL; + LocationPosition *rb = location_position_new(0, 37.255, 127.056, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 37.260, 127.050, 0, LOCATION_STATUS_2D_FIX); + bound = location_boundary_new_for_rect(lt, rb); + location_position_free (rb); + location_position_free (lt); + if (bound) { + g_object_set(loc, "boundary", bound, NULL); + } else g_warning("failed to location_boundary_new_for_rect()"); + + bound = NULL; + g_object_get(loc, "boundary", &bound, NULL); + if (bound) { + g_debug("Set property>> boundary> type: %d, (%f,%f),(%f,%f)", + bound->type, + bound->rect.right_bottom->latitude, bound->rect.right_bottom->longitude, + bound->rect.left_top->latitude, bound->rect.left_top->longitude); + location_boundary_free (bound); + } else g_warning("failed to set property> boundary"); + + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + g_signal_connect (loc, "service-disabled", G_CALLBACK(cb_service_disabled), loc); + g_signal_connect (loc, "service-updated", G_CALLBACK(cb_service_updated), loc); + g_signal_connect (loc, "zone-in", G_CALLBACK(cb_zone_in), loc); + g_signal_connect (loc, "zone-out", G_CALLBACK(cb_zone_out), loc); + + if( LOCATION_ERROR_NONE != location_start (loc) ){ + g_debug("location_start failed"); + return -1; + } + + g_main_loop_run (loop); + + location_stop (loc); + + LocationPosition *pos = NULL; + g_object_get(loc, "last-position", &pos, NULL); + if (pos) { + g_debug ("Get property>> last-position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + location_position_free(pos); + } else g_warning("failed to get property> last-position"); + + location_free (loc); + + return 0; +} diff --git a/tests/hybrid-test.c b/tests/hybrid-test.c new file mode 100644 index 0000000..4146816 --- /dev/null +++ b/tests/hybrid-test.c @@ -0,0 +1,205 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static GMainLoop *loop = NULL; + +static void +cb_service_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + g_debug("cb_service_updated: type(%d) userdata(0x%x)", type, (unsigned int)userdata); + + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + switch (type) { + case POSITION_UPDATED: { + LocationPosition *pos = (LocationPosition*) data; + g_debug ("ASYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + break; + case VELOCITY_UPDATED: { + LocationVelocity *vel = (LocationVelocity*) data; + g_debug ("ASYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + break; + default: + g_warning ("ASYNC>> Undefined update type"); + break; + } +} + +static void +cb_service_enabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); + + LocationObject *loc = (LocationObject*)userdata; + LocationAccuracy *acc = NULL; + LocationPosition *pos = NULL; + LocationVelocity *vel = NULL; + LocationMethod method; + + g_object_get(loc, "method", &method, NULL); + g_debug("Get property>> method:%d", method); + + if (LOCATION_ERROR_NONE == location_get_position (loc, &pos, &acc)) { + g_debug ("SYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_position_free(pos); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current position> failed"); + if (LOCATION_ERROR_NONE == location_get_velocity (loc, &vel, &acc)) { + g_debug ("SYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_velocity_free(vel); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current velocity> failed"); + } + +static void +cb_service_disabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_disabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +static void +cb_zone_in (GObject *self, + gpointer boundary, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + + g_debug ("ASYNC>> ZoneIn> Current position: time: %d, lat: %f, long: %f, alt: %f", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +static void +cb_zone_out (GObject *self, + gpointer boundary, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + + g_debug ("ASYNC>> ZoneOut> Current position: time: %d, lat: %f, long: %f, alt: %f", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +int +main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + + // If application is executed by AUL, this is not needed. + g_setenv("PKG_NAME", "org.tizen.hybrid-test", 1); + + location_init (); + + loop = g_main_loop_new (NULL, TRUE); + + loc = location_new (LOCATION_METHOD_HYBRID); + if (!loc) { + g_debug("location_new failed"); + return -1; + } + + LocationMethod method = LOCATION_METHOD_NONE; + g_object_get(loc, "method", &method, NULL); + g_debug("Get property>> method:%d", method); + + LocationBoundary *bound = NULL; + g_object_get(loc, "boundary", &bound, NULL); + if (bound) { + g_debug("Get property>> boundary> type: %d", bound->type); + location_boundary_free (bound); + } else g_warning("failed to get property> boundary"); + + LocationPosition *rb = location_position_new(0, 37.258, 127.056, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 37.260, 127.054, 0, LOCATION_STATUS_2D_FIX); + bound = location_boundary_new_for_rect(lt, rb); + location_position_free (rb); + location_position_free (lt); + if (bound) { + g_object_set(loc, "boundary", bound, NULL); + location_boundary_free(bound); + } else g_warning("failed to location_boundary_new_for_rect()"); + g_object_get(loc, "boundary", &bound, NULL); + if (bound) { + g_debug("Set property>> boundary> type: %d, (%f,%f),(%f,%f)", + bound->type, + bound->rect.right_bottom->latitude, bound->rect.right_bottom->longitude, + bound->rect.left_top->latitude, bound->rect.left_top->longitude); + location_boundary_free (bound); + } else g_warning("failed to set property> boundary"); + + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + g_signal_connect (loc, "service-disabled", G_CALLBACK(cb_service_disabled), loc); + g_signal_connect (loc, "service-updated", G_CALLBACK(cb_service_updated), loc); + g_signal_connect (loc, "zone-in", G_CALLBACK(cb_zone_in), loc); + g_signal_connect (loc, "zone-out", G_CALLBACK(cb_zone_out), loc); + + if (LOCATION_ERROR_NONE != location_start (loc)) { + g_debug("location_start failed"); + return -1; + } + + g_main_loop_run (loop); + + location_stop (loc); + + LocationPosition *pos = NULL; + g_object_get(loc, "last-position", &pos, NULL); + if (pos) { + g_debug ("Get property>> last-position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + location_position_free(pos); + } else g_warning("failed to get property> last-position"); + + location_free (loc); + + return 0; +} diff --git a/tests/location-api-test-util.c b/tests/location-api-test-util.c new file mode 100644 index 0000000..55f7dc2 --- /dev/null +++ b/tests/location-api-test-util.c @@ -0,0 +1,205 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "location.h" + +JsonParser *parser; +JsonNode *root; + +static int _get_polygon_position_count(int polygon_index) +{ + if (parser == NULL || root == NULL) return 0; + + JsonObject* polygon_obj = json_array_get_object_element(json_node_get_array(root), polygon_index); + if (polygon_obj == NULL) return 0; + + JsonArray * positions = json_object_get_array_member (polygon_obj, "positions"); + if (positions == NULL) return 0; + + return json_array_get_length(positions); +} + +static LocationPosition* _get_position_from_polygon(int polygon_index, int pos_index) +{ + double latitude = 0.0; + double longitude = 0.0; + LocationPosition *position = NULL; + if (parser == NULL || root == NULL) return NULL; + + JsonObject *polygon_obj = json_array_get_object_element(json_node_get_array(root), polygon_index); + JsonArray * pos_array = json_object_get_array_member(polygon_obj, "positions"); + JsonObject* pos = json_array_get_object_element(pos_array, pos_index); + + latitude = json_object_get_double_member(pos, "latitude"); + longitude = json_object_get_double_member(pos, "longitude"); + + if (latitude == 0.0 || longitude == 0.0) return NULL; + + position = location_position_new(0, latitude, longitude, 0.0, LOCATION_STATUS_2D_FIX); + + return position; +} + +static LocationPosition* _get_marker_position_from_polygon(int polygon_index, int pos_index) +{ + double latitude = 0.0; + double longitude = 0.0; + LocationPosition *position = NULL; + if (parser == NULL || root == NULL) return NULL; + + JsonObject *polygon_obj = json_array_get_object_element(json_node_get_array(root), polygon_index); + JsonArray * pos_array = json_object_get_array_member(polygon_obj, "marker_position"); + JsonObject* pos = json_array_get_object_element(pos_array, pos_index); + + latitude = json_object_get_double_member(pos, "latitude"); + longitude = json_object_get_double_member(pos, "longitude"); + + if (latitude == 0.0 || longitude == 0.0) return NULL; + + position = location_position_new(0, latitude, longitude, 0.0, LOCATION_STATUS_2D_FIX); + + return position; +} + +static void _free_position_list(gpointer data) +{ + if (data == NULL) return; + + LocationPosition *position = (LocationPosition*) data; + + location_position_free(position); +} + + +LocationBoundary* json_util_get_polygon_boundary(int polygon_index) +{ + if (parser == NULL || root == NULL) { + g_printf("invalid param parser[%d], root[%d]\n", parser, root); + return NULL; + } + GList* position_list = NULL; + LocationBoundary *boundary = NULL; + int index = 0; + int pos_count = _get_polygon_position_count(polygon_index); + if (pos_count == 0) return NULL; + + for(index = 0; index < pos_count; index++) { + position_list = g_list_append(position_list, _get_position_from_polygon(polygon_index, index)); + } + + boundary = location_boundary_new_for_polygon(position_list); + + g_list_free_full(position_list, (GDestroyNotify)_free_position_list); + + return boundary; +} + + +/* Polygon boundary */ +int json_util_get_polygon_count(void) +{ + JsonArray * array = json_node_get_array(root); + + return json_array_get_length(array); +} + +char *json_util_get_polygon_name(int polygon_index) +{ + char *name = NULL; + JsonObject *polygon_obj = json_array_get_object_element(json_node_get_array(root), polygon_index); + + name = (char *)json_object_get_string_member(polygon_obj, "name"); + if (name == NULL) return NULL; + + return g_strdup(name); +} + +/* Test Marker */ +char * json_util_get_marker_name(int polygon_index, int pos_index) +{ + char *result = NULL; + if (parser == NULL || root == NULL) return NULL; + + JsonObject *polygon_obj = json_array_get_object_element(json_node_get_array(root), polygon_index); + JsonArray * pos_array = json_object_get_array_member(polygon_obj, "marker_position"); + JsonObject* pos = json_array_get_object_element(pos_array, pos_index); + + result = (char *)json_object_get_string_member(pos, "where"); + if (result == NULL) return NULL; + + return g_strdup(result); +} + +int json_util_get_marker_position_count(int polygon_index) +{ + if (parser == NULL || root == NULL) return 0; + + JsonObject* polygon_obj = json_array_get_object_element(json_node_get_array(root), polygon_index); + JsonArray * marker_position = json_object_get_array_member (polygon_obj, "marker_position"); + + return json_array_get_length(marker_position); +} + +LocationPosition *json_util_get_marker_position(int polygon_index, int marker_index) +{ + if (parser == NULL || root == NULL) return NULL; + + LocationPosition* position = NULL; + position = _get_marker_position_from_polygon(polygon_index, marker_index); + + return position; +} + +char* json_util_result_zone_test(int polygon_index, int marker_index) +{ + if (parser == NULL || root == NULL) return NULL; + + char *result = NULL; + JsonObject *polygon_obj = json_array_get_object_element(json_node_get_array(root), polygon_index); + JsonArray * pos_array = json_object_get_array_member(polygon_obj, "marker_position"); + JsonObject* pos = json_array_get_object_element(pos_array, marker_index); + + result = (char *)json_object_get_string_member(pos, "result"); + if (result == NULL) return NULL; + + return g_strdup(result); +} + +void json_util_init(const char * file_name) +{ + g_print("Enter init_json_parser"); + GError *error; + gboolean ret = FALSE; + if (parser != NULL) return; + + parser = json_parser_new(); + + error = NULL; + ret = json_parser_load_from_file(parser, file_name, &error); + if (ret == FALSE) { + g_print("Unable to parser[%s]:[%s]\n", file_name, error->message); + return ; + } + + root = json_parser_get_root(parser); +} diff --git a/tests/location-api-test-util.h b/tests/location-api-test-util.h new file mode 100644 index 0000000..f283e4e --- /dev/null +++ b/tests/location-api-test-util.h @@ -0,0 +1,42 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __LOCATION_API_TEST_UTIL_H__ +#define __LOCATION_API_TEST_UTIL_H__ + +#include "location.h" + +G_BEGIN_DECLS + +void json_util_init(const char *file_file); +char* json_util_result_zone_test(int polygon_index, int marker_index); +char* json_util_get_marker_name(int polygon_index, int marker_index); +int json_util_get_marker_position_count(int polygon_index); +LocationPosition *json_util_get_marker_position(int polygon_index, int marker_index); + +int json_util_get_polygon_count(void); +char* json_util_get_polygon_name(int polygon_index); +LocationBoundary* json_util_get_polygon_boundary(int polygon_index); + +G_END_DECLS + +#endif /* __LOCATION_H__ */ diff --git a/tests/location-api-test.c b/tests/location-api-test.c new file mode 100644 index 0000000..bc0ae94 --- /dev/null +++ b/tests/location-api-test.c @@ -0,0 +1,847 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "location-api-test-util.h" + +#define STR_MAX 128 +LocationObject* location_obj = NULL; +static GMainLoop *g_mainloop = NULL; + +#define LOCATION_API_TEST_JSON_FILE "/opt/data/location-api-test.json" + +static gpointer GmainThread(gpointer data) +{ + g_mainloop = g_main_loop_new (NULL, FALSE); + g_printf("\n...Entering GMain Loop to Receive Notifications....\n"); + g_main_loop_run (g_mainloop); + g_main_loop_unref (g_mainloop); + g_mainloop = NULL; + return NULL; +} + + +static void GetLocationError(char str[STR_MAX], int ret) +{ + switch(ret) + { + case LOCATION_ERROR_NONE: + g_utf8_strncpy(str, "LOCATION_ERROR_NONE", STR_MAX); + break; + case LOCATION_ERROR_NOT_ALLOWED: + g_utf8_strncpy(str, "LOCATION_ERROR_NOT_ALLOWED", STR_MAX); + break; + case LOCATION_ERROR_NOT_AVAILABLE: + g_utf8_strncpy(str, "LOCATION_ERROR_NOT_AVAILABLE", STR_MAX); + break; + case LOCATION_ERROR_NETWORK_FAILED: + g_utf8_strncpy(str, "LOCATION_ERROR_NETWORK_FAILED", STR_MAX); + break; + case LOCATION_ERROR_NETWORK_NOT_CONNECTED: + g_utf8_strncpy(str, "LOCATION_ERROR_NETWORK_NOT_CONNECTED", STR_MAX); + break; + case LOCATION_ERROR_CONFIGURATION: + g_utf8_strncpy(str, "LOCATION_ERROR_CONFIGURATION", STR_MAX); + break; + case LOCATION_ERROR_PARAMETER: + g_utf8_strncpy(str, "LOCATION_ERROR_PARAMETER", STR_MAX); + break; + case LOCATION_ERROR_UNKNOWN: + g_utf8_strncpy(str, "LOCATION_ERROR_UNKNOWN", STR_MAX); + break; + case LOCATION_ERROR_SETTING_OFF: + g_utf8_strncpy(str, "LOCATION_ERROR_SETTING_OFF", STR_MAX); + break; + case LOCATION_ERROR_SECURITY_DENIED: + g_utf8_strncpy(str, "LOCATION_ERROR_SECURITY_DENIED", STR_MAX); + break; + default: + g_utf8_strncpy(str, "Error: undefined error code", STR_MAX); + } +} + +static void GetStatus(char str[STR_MAX], LocationStatus acc_level) +{ + switch(acc_level) + { + case LOCATION_STATUS_NO_FIX: + g_utf8_strncpy(str, "LOCATION_STATUS_NO_FIX", STR_MAX); + break; + case LOCATION_STATUS_2D_FIX: + g_utf8_strncpy(str, "LOCATION_STATUS_2D_FIX", STR_MAX); + break; + case LOCATION_STATUS_3D_FIX: + g_utf8_strncpy(str, "LOCATION_STATUS_3D_FIX", STR_MAX); + break; + default: + g_utf8_strncpy(str, "Error: undefined status code", STR_MAX); + } +} + +static void GetMethod(char str[STR_MAX], LocationMethod method) +{ + switch(method) + { + case LOCATION_METHOD_HYBRID: + g_utf8_strncpy(str, "LOCATION_METHOD_HYBRID", STR_MAX); + break; + case LOCATION_METHOD_GPS: + g_utf8_strncpy(str, "LOCATION_METHOD_GPS", STR_MAX); + break; + case LOCATION_METHOD_CPS: + g_utf8_strncpy(str, "LOCATION_METHOD_CPS", STR_MAX); + break; + case LOCATION_METHOD_WPS: + g_utf8_strncpy(str, "LOCATION_METHOD_WPS", STR_MAX); + break; + default: + g_utf8_strncpy(str, "Error: undefined method", STR_MAX); + } +} + +static void GetAccuracyLevel(char str[STR_MAX], LocationAccuracyLevel acc_level) +{ + switch(acc_level) + { + case LOCATION_ACCURACY_LEVEL_NONE: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_NONE", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_COUNTRY: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_COUNTRY", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_REGION: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_REGION", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_LOCALITY: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_LOCALITY", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_POSTALCODE: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_POSTALCODE", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_STREET: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_STREET", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_DETAILED: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_DETAILED", STR_MAX); + break; + default: + g_utf8_strncpy(str, "Error: undefined accuracy level", STR_MAX); + } +} + + +static void SelectOpt(char* buf) +{ + int iLen = 0; + char *str = NULL; + str = fgets(buf, 255, stdin); + iLen = g_utf8_strlen(buf, -1); + buf[iLen-1] = '\0'; +} + +static int PromptInt() +{ + char buf[255]; + int ret; + char *str = NULL; + str = fgets(buf, 255, stdin); + buf[strlen(buf)-1]='\0'; + ret = g_ascii_strtoll(buf, NULL, 10); + return ret; +} + +gulong g_sig_enable = 0; +gulong g_sig_disable = 0; +gulong g_sig_update = 0; +gulong g_sig_zonein = 0; +gulong g_sig_zoneout = 0; + +static void PrintPolygonPosition(gpointer data, gpointer user_data) +{ + LocationPosition *position = (LocationPosition*) data; + g_printf("[%lf %lf %lf] ", position->latitude, position->longitude, position->altitude); +} + +static void PrintBoundary(LocationBoundary *boundary, void *user_data) +{ + if(boundary == NULL) return; + if (boundary->type == LOCATION_BOUNDARY_CIRCLE) { + g_printf("\n\tCIRCLE: center[%lf %lf %lf] radius[%lf]", + boundary->circle.center->latitude, boundary->circle.center->longitude, boundary->circle.center->altitude, boundary->circle.radius); + } else if (boundary->type == LOCATION_BOUNDARY_RECT) { + g_printf("\n\tRECT: left_top[%lf %lf %lf] right_bottom[%lf %lf %lf]", + boundary->rect.left_top->latitude, boundary->rect.left_top->longitude, boundary->rect.left_top->altitude, + boundary->rect.right_bottom->latitude, boundary->rect.right_bottom->longitude, boundary->rect.right_bottom->altitude); + } else if (boundary->type == LOCATION_BOUNDARY_POLYGON) { + g_printf("\n\tPOLYGON: "); + + GList *list = boundary->polygon.position_list; + + g_list_foreach(list, PrintPolygonPosition, NULL); + } +} + +static void RemoveBoundary(LocationBoundary *boundary, void *user_data) +{ + LocationObject * obj = (LocationObject *)user_data; + if(obj == NULL || boundary == NULL) return; + + location_boundary_remove(obj, boundary); +} + +static void PrintProperty (LocationObject* loc) +{ + if (!loc) return; + LocationMethod method = LOCATION_METHOD_NONE; + LocationPosition *pos = NULL; + LocationAccuracy *acc = NULL; + guint pos_interval = 0; + guint vel_interval = 0; + guint sat_interval = 0; + gchar method_str[STR_MAX] = {0, }; + gchar status_str[STR_MAX] = {0, }; + + gchar* devname = NULL; + + g_object_get(loc, "method", &method, NULL); + GetMethod(method_str, method); + g_printf("method[%s] ", method_str); + + if (LOCATION_METHOD_GPS == method) { + g_object_get(loc, "dev-name", &devname, NULL); + if (devname) { + g_printf("dev-name[%s] ", devname); + g_free(devname); + } + } + + int ret = location_get_last_position (loc, &pos, &acc); + if (ret == LOCATION_ERROR_NONE) { + GetStatus(status_str, pos->status); + g_printf("\nLast position [time(%d) lat(%f) long(%f) alt(%f) status(%s)]", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, status_str); + location_position_free (pos); + location_accuracy_free (acc); + } + + if (method == LOCATION_METHOD_HYBRID || method == LOCATION_METHOD_GPS) { + g_object_get(loc, "pos-interval", &pos_interval, NULL); + g_object_get(loc, "vel-interval", &vel_interval, NULL); + g_object_get(loc, "sat-interval", &sat_interval, NULL); + } + else if (method == LOCATION_METHOD_WPS) { + g_object_get(loc, "pos-interval", &pos_interval, NULL); + g_object_get(loc, "vel-interval", &vel_interval, NULL); + } + else if (method == LOCATION_METHOD_CPS) { + g_object_get(loc, "pos-interval", &pos_interval, NULL); + } + g_printf("Position interval : [%u], Velocity interval [%u], Satellite interval [%u]\n", pos_interval, vel_interval, sat_interval); + + g_printf("\nSignals: "); + if (g_sig_enable) g_printf("[service-enabled], "); + if (g_sig_disable) g_printf("[service-disabled], "); + if (g_sig_update) g_printf("[service-updated], "); + if (g_sig_zonein) g_printf("[zone-in], "); + if (g_sig_zoneout) g_printf("[zone-out]"); +} + +static void cb_service_enabled (GObject *self, guint status, gpointer userdata) +{ + g_printf("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); + + LocationObject *loc = (LocationObject*)userdata; + LocationAccuracy *acc = NULL; + LocationPosition *pos = NULL; + LocationVelocity *vel = NULL; + LocationMethod method; + + g_object_get(loc, "method", &method, NULL); + g_printf("Get property>> method:%d", method); + + if (LOCATION_ERROR_NONE == location_get_position (loc, &pos, &acc)) { + g_printf ("SYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d\n", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_printf ("\tAccuracy level %d (%.0f meters %.0f meters)\n", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_position_free(pos); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current position> failed"); + if (LOCATION_ERROR_NONE == location_get_velocity (loc, &vel, &acc)) { + g_printf ("SYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f\n", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_printf ("\tAccuracy level %d (%.0f meters %.0f meters)\n", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_velocity_free(vel); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current velocity> failed\n"); +} + +static void +cb_service_disabled (GObject *self, + guint status, + gpointer userdata) +{ + g_printf("cb_service_disabled: status(%d) userdata(0x%x)\n", status, (unsigned int)userdata); +} + +static void +cb_zone_in (GObject *self, + gpointer boundary, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + + g_printf ("ASYNC>> ZoneIn> Current position: time: %d, lat: %f, long: %f, alt: %f\n", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + g_printf ("\tAccuracy level %d (%.0f meters %.0f meters)\n", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +static void +cb_zone_out (GObject *self, + gpointer boundary, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + + g_printf ("ASYNC>> ZoneOut> Current position: time: %d, lat: %f, long: %f, alt: %f\n", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + g_printf ("\tAccuracy level %d (%.0f meters %.0f meters)\n", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +static void +cb_service_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + g_printf("cb_service_updated: type(%d) userdata(0x%x)", type, (unsigned int)userdata); + + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + switch (type) { + case POSITION_UPDATED: { + LocationPosition *pos = (LocationPosition*) data; + g_printf ("ASYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d\n", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_printf ("\tAccuracy level %d (%.0f meters %.0f meters)\n", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + break; + case VELOCITY_UPDATED: { + LocationVelocity *vel = (LocationVelocity*) data; + g_printf ("ASYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f\n", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_printf ("\tAccuracy level %d (%.0f meters %.0f meters)\n", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + break; + case SATELLITE_UPDATED: { + int idx = 0; + guint prn; + gboolean used; + guint elevation; + guint azimuth; + gint snr; + + LocationSatellite *sat = (LocationSatellite *)data; + g_printf ("SYNC>> Current Satellite> time: %d, satellite in view = %d, satellite in used = %d\n", sat->timestamp, sat->num_of_sat_inview, sat->num_of_sat_used); + g_printf ("\tinview satellite information = "); + for (idx=0; idxnum_of_sat_inview; idx++) { + location_satellite_get_satellite_details(sat, idx, &prn, &used, &elevation, &azimuth, &snr); + g_printf ("\t\t[%02d] used: %d, prn: %d, elevation: %d, azimuth: %d, snr: %d\n", idx, used, prn, elevation, azimuth, snr); + } + } + break; + default: + g_warning ("ASYNC>> Undefined update type"); + break; + } +} + +static void print_menu() +{ + g_printf("\n================================= Location API Test =================================\n"); + g_printf("q. Exit\n"); + g_printf("1. location_init\n"); + g_printf("2. location_new\n"); + g_printf("3. location_free\n"); + g_printf("4. location_start\n"); + g_printf("5. location_stop\n"); + g_printf("6. location_get_position\n"); + g_printf("6a. location_get_last_position\n"); + g_printf("7. location_get_velocity\n"); + g_printf("7a. location_get_last_velocity\n"); + g_printf("8. location_get_satellite\n"); + g_printf("8a. location_get_last_satellite\n"); + g_printf("9. location_get_distance\n"); + g_printf("10. location_is_supported_method\n"); + g_printf("11. location_is_enabled_gps\n"); + g_printf("99. location_send_command\n"); + g_printf("99a. location_send_command(get_auth)\n"); + g_printf("99b. location_send_command(add_to_list)\n"); + g_printf("a?. signals:(1)'service-enabled',(2)'service-disabled',(3)'service-updated',(4)'zone-in',(5)'zone-out'\n"); + g_printf("b?. disconnect signals:(1)'service-enabled',(2)'service-disabled',(3)'service-updated',(4)'zone-in',(5)'zone-out'\n"); + g_printf("c?. (1)Set boundary, (2)Get boundary, (3) Remove boundary, (4) Remove all boundaries, (5)Set device name, \n"); + g_printf(" (6)Set position interval (7) Set velocity interval (8) Set satellite interval\n"); + g_printf("==================================== Property ====================================\n"); + PrintProperty(location_obj); + g_printf("\n==================================================================================\n"); +} + +int main(int argc, char** argv) +{ + char strOpt[255]; + int ret; + char str[STR_MAX]; + GError *gerr = NULL; + + // If application is executed by AUL, this is not needed. + g_setenv("PKG_NAME", "org.tizen.location-api-test", 1); + + g_type_init(); + +#if !GLIB_CHECK_VERSION (2, 31, 0) + if( !g_thread_supported() ) + { + g_thread_init(NULL); + } +#endif + + GThread *g_main; + g_main = g_thread_create(GmainThread, NULL, TRUE, &gerr); + if (!g_main) { + g_printf("Error create gmain thread: Err domain[%d] Err code[%d] Err msg[%s]", + gerr->domain, gerr->code, gerr->message); + g_error_free(gerr); + return 0; + } + + json_util_init(LOCATION_API_TEST_JSON_FILE); + g_printf("--- Start LBS Test App ---\n"); + while(1) + { + print_menu(); + g_printf("Select option: "); + SelectOpt(strOpt); + g_printf("======================================================================================\n"); + if (0 == g_strcmp0 ("x", strOpt)) { + + } + else if (0 == g_strcmp0("1",strOpt)) { + ret = location_init(); + GetLocationError(str, ret); + g_printf("location_init: returned value [%s]\n", str); + } else if (0 == g_strcmp0("2",strOpt)) { + if (location_obj) { + g_printf("Location object already existed: [0x%x]", (unsigned int)location_obj); + continue; + } + g_printf("LOCATION_METHOD_HYBRID[0] LOCATION_METHOD_GPS[1] LOCATION_METHOD_WPS[2] LOCATION_METHOD_CPS[3]\n"); + g_printf("Select Location Method: "); + LocationMethod method = PromptInt(); + location_obj = location_new(method); + if(location_obj) g_printf("Success\n"); + else g_printf("Failed\n"); + } else if (0 == g_strcmp0("3",strOpt)) { + ret = location_free (location_obj); + location_obj = NULL; + + g_sig_enable = 0; + g_sig_disable = 0; + g_sig_update = 0; + g_sig_zonein = 0; + g_sig_zoneout = 0; + GetLocationError(str, ret); + g_printf("location_free: returned value [%s]\n", str); + } else if (0 == g_strcmp0("4",strOpt)) { + ret = location_start(location_obj); + GetLocationError(str, ret); + g_printf("location_start: returned value [%s]\n", str); + } else if (0 == g_strcmp0("5",strOpt)) { + ret = location_stop(location_obj); + GetLocationError(str, ret); + g_printf("location_stop: returned value [%s]\n", str); + } else if (0 == g_strcmp0("6",strOpt)) { + LocationPosition *pos = NULL; + LocationAccuracy *acc = NULL; + ret = location_get_position(location_obj, &pos, &acc); + GetLocationError(str, ret); + g_printf("location_get_position: returned value [%s]\n", str); + if (ret == LOCATION_ERROR_NONE) { + g_printf("time: [%d], latitude: [%f], longitude: [%f], altitude: [%f], status: [%d]\n", pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + GetAccuracyLevel(str, acc->level); + g_printf("level: [%s], horizontal_accuracy: [%f], vertical_accuracy: [%f]\n", str, acc->horizontal_accuracy, acc->vertical_accuracy); + } + if(pos) location_position_free(pos); + if(acc) location_accuracy_free(acc); + } else if (0 == g_strcmp0("6a",strOpt)) { + LocationPosition *last_pos; + LocationAccuracy *last_acc; + int ret = 0; + + ret = location_get_last_position (location_obj, &last_pos, &last_acc); + GetLocationError(str, ret); + g_printf("location_get_last_position: returned value [%s]\n", str); + if (ret == LOCATION_ERROR_NONE) { + g_printf ("SYNC>> Last position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + last_pos->timestamp, last_pos->latitude, last_pos->longitude, last_pos->altitude, last_pos->status); + g_printf ("\tAccuracy level %d (%.0f meters %.0f meters)", + last_acc->level, last_acc->horizontal_accuracy, last_acc->vertical_accuracy); + location_position_free(last_pos); + location_accuracy_free(last_acc); + } + + }else if(0 == g_strcmp0("7",strOpt) ){ + LocationVelocity *vel = NULL; + LocationAccuracy *acc = NULL; + ret = location_get_velocity(location_obj, &vel, &acc); + GetLocationError(str, ret); + g_printf("location_get_velocity: returned value [%s]\n", str); + if (ret == LOCATION_ERROR_NONE) { + g_printf("time: [%d], speed: [%f], direction: [%f], climb: [%f]\n", vel->timestamp, vel->speed, vel->direction, vel->climb); + GetAccuracyLevel(str, acc->level); + g_printf("level: [%s], horizontal_accuracy: [%f], vertical_accuracy: [%f]\n", str, acc->horizontal_accuracy, acc->vertical_accuracy); + } + if(vel) location_velocity_free(vel); + if(acc) location_accuracy_free(acc); + }else if(0 == g_strcmp0("7a",strOpt) ){ + LocationVelocity *last_vel = NULL; + LocationAccuracy *last_acc = NULL; + ret = location_get_last_velocity (location_obj, &last_vel, &last_acc); + GetLocationError(str, ret); + g_printf("location_get_last_velocity: returned value [%s]\n", str); + if (ret == LOCATION_ERROR_NONE) { + g_printf ("SYNC>> Last velocity> time: %d, speed: %f, direction:%f, climb:%f", + last_vel->timestamp, last_vel->speed, last_vel->direction, last_vel->climb); + g_printf ("\tAccuracy level %d (%.0f meters %.0f meters)", + last_acc->level, last_acc->horizontal_accuracy, last_acc->vertical_accuracy); + location_velocity_free(last_vel); + location_accuracy_free(last_acc); + } + }else if(0 == g_strcmp0("8",strOpt) ){ + int ret = 0, idx = 0; + LocationSatellite *sat = NULL; + guint prn; + gboolean used; + guint elevation; + guint azimuth; + gint snr; + + ret = location_get_satellite (location_obj, &sat); + GetLocationError(str, ret); + g_printf("location_get_satellite: returned value [%s]\n", str); + if (ret == LOCATION_ERROR_NONE) { + g_printf ("SYNC>> Current Sattelite> time = %d, satellite in view = %d, satellite in used = %d", sat->timestamp, sat->num_of_sat_inview, sat->num_of_sat_used); + g_printf ("\tinview satellite information = "); + for (idx=0; idxnum_of_sat_inview; idx++) { + location_satellite_get_satellite_details(sat, idx, &prn, &used, &elevation, &azimuth, &snr); + g_printf ("\t\t[%02d] used: %d, prn: %d, elevation: %d, azimuth: %d, snr: %d", idx, used, prn, elevation, azimuth, snr); + } + location_satellite_free (sat); + } + }else if(0 == g_strcmp0("8a",strOpt) ){ + int ret = 0, idx = 0; + LocationSatellite *last_sat = NULL; + guint prn; + gboolean used; + guint elevation; + guint azimuth; + gint snr; + + ret = location_get_last_satellite (location_obj, &last_sat); + GetLocationError(str, ret); + g_printf("location_get_last_satellite: returned value [%s]\n", str); + if (ret == LOCATION_ERROR_NONE) { + g_printf ("SYNC>> Last Sattelite> time = %d, satellite in view = %d, satellite in used = %d", last_sat->timestamp, last_sat->num_of_sat_inview, last_sat->num_of_sat_used); + g_printf ("\tinview satellite information = "); + for (idx=0; idxnum_of_sat_inview; idx++) { + location_satellite_get_satellite_details(last_sat, idx, &prn, &used, &elevation, &azimuth, &snr); + g_printf ("\t\t[%02d] used: %d, prn: %d, elevation: %d, azimuth: %d, snr: %d", idx, used, prn, elevation, azimuth, snr); + } + location_satellite_free (last_sat); + } + }else if(0 == g_strcmp0("9",strOpt) ) { + + gulong distance; + int ret = 0; + char str[STR_MAX]; + LocationPosition pos1, pos2; + + pos1.latitude = 50.0663222; + pos1.longitude = -5.71475; + + pos2.latitude = 58.6441; + pos2.longitude = -3.070094; + + ret = location_get_distance(&pos1, &pos2, &distance); + GetLocationError(str, ret); + if(ret != LOCATION_ERROR_NONE) { + g_printf("Fail to get position. Error[%s]\n", str); + } + else { + g_printf("The approximate distance is [%lu]\n", distance); + g_printf("cf.) It is approximately 969954.114 meter\n"); + } + }else if(0 == g_strcmp0("10", strOpt)) { + int method; + char method_str[STR_MAX] = {0, }; + char *str = NULL; + char input[8] = {0, }; + gboolean is_supported = FALSE; + + g_printf("0.Hybrid 1.GPS 2.WPS 3.CPS\n"); + g_printf("Select Method :"); + str = fgets(input, 8, stdin); + method = atoi(input); + switch(method) { + case LOCATION_METHOD_HYBRID: + is_supported = location_is_supported_method(LOCATION_METHOD_HYBRID); + break; + + case LOCATION_METHOD_GPS: + is_supported = location_is_supported_method(LOCATION_METHOD_GPS); + break; + + case LOCATION_METHOD_WPS: + is_supported = location_is_supported_method(LOCATION_METHOD_WPS); + break; + + case LOCATION_METHOD_CPS: + is_supported = location_is_supported_method(LOCATION_METHOD_CPS); + break; + + default: + break; + + } + GetMethod(method_str, method); + + g_printf("Method[%s] is %s.", method_str, is_supported ? "supported" : "not supported"); + + }else if(0 == g_strcmp0("11", strOpt)) { + gboolean is_enabled = FALSE; + is_enabled = location_is_enabled_gps(location_obj); + if(is_enabled == TRUE) g_printf("GPS is turned on"); + else g_printf("GPS is turned off"); + }else if(0 == g_strcmp0("99", strOpt)) { + int ret = 0; + const char *str = "command"; + ret = location_send_command(str); + if(ret == 0) + g_printf("Success to send command[%s]", str); + else + g_printf("Fail to send command[%s]. Error[%d]", str, ret); + }else if(0 == g_strcmp0("a1",strOpt)){ + if(location_obj && !g_sig_enable) { + g_sig_enable = g_signal_connect (location_obj, "service-enabled", G_CALLBACK(cb_service_enabled), location_obj); + } + }else if(0 == g_strcmp0("a2",strOpt)){ + if(location_obj && !g_sig_disable){ + g_sig_disable = g_signal_connect (location_obj, "service-disabled", G_CALLBACK(cb_service_disabled), location_obj); + } + }else if(0 == g_strcmp0("a3",strOpt)){ + if(location_obj && !g_sig_update){ + g_sig_update = g_signal_connect (location_obj, "service-updated", G_CALLBACK(cb_service_updated), location_obj); + } + }else if(0 == g_strcmp0("a4",strOpt)){ + if(location_obj && !g_sig_zonein){ + g_sig_zonein = g_signal_connect (location_obj, "zone-in", G_CALLBACK(cb_zone_in), location_obj); + } + }else if(0 == g_strcmp0("a5",strOpt)){ + if(location_obj && !g_sig_zoneout){ + g_sig_zoneout = g_signal_connect (location_obj, "zone-out", G_CALLBACK(cb_zone_out), location_obj); + } + }else if(0 == g_strcmp0("b1",strOpt)){ + if(location_obj && g_sig_enable) { + g_signal_handler_disconnect (location_obj, g_sig_enable); + g_sig_enable = 0; + } + }else if(0 == g_strcmp0("b2",strOpt)){ + if(location_obj && g_sig_disable){ + g_signal_handler_disconnect (location_obj, g_sig_disable); + g_sig_disable = 0; + } + }else if(0 == g_strcmp0("b3",strOpt)){ + if(location_obj && g_sig_update){ + g_signal_handler_disconnect (location_obj, g_sig_update); + g_sig_update = 0; + } + }else if(0 == g_strcmp0("b4",strOpt)){ + if(location_obj && g_sig_zonein){ + g_signal_handler_disconnect (location_obj, g_sig_zonein); + g_sig_zonein = 0; + } + }else if(0 == g_strcmp0("b5",strOpt)){ + if(location_obj && g_sig_zoneout){ + g_signal_handler_disconnect (location_obj, g_sig_zoneout); + g_sig_zoneout = 0; + } + }else if(0 == g_strcmp0("c1",strOpt)){ + LocationBoundary* bound = NULL; + int i = 0; + int polygon_count = json_util_get_polygon_count(); + + g_printf("[0].San jose(Rect) [1].Suwon HQ(Rect) [2].Seoul City(circle) "); + for(i = 0; i < polygon_count; i++) + g_printf("[%d].%s ", i + 3, json_util_get_polygon_name(i)); + + g_printf("\nSelect Boundary: "); + int opt = PromptInt(); + if (opt == 0) { + LocationPosition* rb = location_position_new (0, 37.300, -121.86, 0, LOCATION_STATUS_2D_FIX); + LocationPosition* lt = location_position_new (0, 37.360, -121.92, 0, LOCATION_STATUS_2D_FIX); + bound = location_boundary_new_for_rect (lt, rb); + location_position_free(rb); + location_position_free(lt); + + location_boundary_add(location_obj, bound); + + } else if(opt == 1) { + LocationPosition* rb = location_position_new (0, 37.255, 127.058, 0, LOCATION_STATUS_2D_FIX); + LocationPosition* lt = location_position_new (0, 37.260, 127.045, 0, LOCATION_STATUS_2D_FIX); + bound = location_boundary_new_for_rect (lt, rb); + location_position_free(rb); + location_position_free(lt); + + location_boundary_add(location_obj, bound); + } else if(opt == 2) { + LocationPosition *center = location_position_new(0, 37.566535, 126.977969, 0.0, LOCATION_STATUS_2D_FIX); + double radius = 10.0; + bound = location_boundary_new_for_circle(center, radius); + + location_boundary_add(location_obj, bound); + } else if (opt > 2 && opt < 3 + polygon_count) { + int index; + int polygon_index = opt - 3; + bound = json_util_get_polygon_boundary(polygon_index); + location_boundary_add(location_obj, bound); + + LocationPosition * check_pos = NULL; + gboolean ret = FALSE; + int count = json_util_get_marker_position_count(polygon_index); + for(index = 0; index < count; index++) { + check_pos = json_util_get_marker_position(polygon_index, index); + + ret = location_boundary_if_inside(bound, check_pos); + g_printf("[%s] is [%s] and the test result is [%s]\n", json_util_get_marker_name(polygon_index, index), json_util_result_zone_test(polygon_index, index), ret == TRUE? "inside": "outside"); + location_position_free(check_pos); + } + } else { + g_printf("boundary is not set\n"); + } + location_boundary_free(bound); + + }else if(0 == g_strcmp0("c2",strOpt)){ + g_printf("Get Boundary\n"); + location_boundary_foreach(location_obj, PrintBoundary, NULL); + + }else if(0 == g_strcmp0("c3",strOpt)){ + g_printf("Remove Boundary\n"); + LocationBoundary* bound = NULL; + + int i = 0; + int polygon_count = json_util_get_polygon_count(); + + g_printf("[0].San jose(Rect) [1].Suwon HQ(Rect) [2].Seoul City(circle) "); + for(i = 0; i < polygon_count; i++) + g_printf("[%d].%s ", i + 3, json_util_get_polygon_name(i)); + + g_printf("\nSelect Boundary: "); + int opt = PromptInt(); + if (opt == 0) { + LocationPosition* rb = location_position_new (0, 37.300, -121.86, 0, LOCATION_STATUS_2D_FIX); + LocationPosition* lt = location_position_new (0, 37.360, -121.92, 0, LOCATION_STATUS_2D_FIX); + bound = location_boundary_new_for_rect (lt, rb); + location_position_free(rb); + location_position_free(lt); + + } else if(opt == 1) { + LocationPosition* rb = location_position_new (0, 37.255, 127.058, 0, LOCATION_STATUS_2D_FIX); + LocationPosition* lt = location_position_new (0, 37.260, 127.045, 0, LOCATION_STATUS_2D_FIX); + bound = location_boundary_new_for_rect (lt, rb); + location_position_free(rb); + location_position_free(lt); + + } else if(opt == 2) { + LocationPosition *center = location_position_new(0, 37.566535, 126.977969, 0.0, LOCATION_STATUS_2D_FIX); + double radius = 10.0; + bound = location_boundary_new_for_circle(center, radius); + location_position_free(center); + + } else if (opt > 2 && opt < 3 + polygon_count) { + int polygon_index = opt - 3; + bound = json_util_get_polygon_boundary(polygon_index); + } else { + g_printf("Invalid value\n"); + } + + if(bound != NULL) location_boundary_remove(location_obj, bound); + + }else if(0 == g_strcmp0("c4",strOpt)){ + location_boundary_foreach(location_obj, RemoveBoundary, location_obj); + }else if(0 == g_strcmp0("c5",strOpt)){ + char buf[255]; + char *str = NULL; + g_printf("Input device name: "); + str = fgets(buf, 255, stdin); + buf[strlen(buf)-1]='\0'; + g_object_set(location_obj, "dev-name", buf, NULL); + } else if (0 == g_strcmp0("c6", strOpt)) { + guint interval = 1; + int len = 0; + g_printf("Input interval[1~120]:"); + len = scanf("%u", &interval); + g_printf("changed interval to [%u]\n", interval); + g_object_set(location_obj, "pos-interval", interval, NULL); + } else if (0 == g_strcmp0("c7", strOpt)) { + int len = 0; + guint interval = 1; + g_printf("Input interval[1~120]:"); + len = scanf("%u", &interval); + g_printf("changed interval to [%u]\n", interval); + g_object_set(location_obj, "vel-interval", interval, NULL); + } else if (0 == g_strcmp0("c8", strOpt)) { + guint interval = 1; + int len = 0; + g_printf("Input interval[1~120]:"); + len = scanf("%u", &interval); + g_printf("changed interval to [%u]\n", interval); + g_object_set(location_obj, "sat-interval", interval, NULL); + }else if(0 == g_strcmp0("q",strOpt) ){ + g_main_loop_quit(g_mainloop); + break; + } + } + g_thread_join(g_main); + g_printf("\n--- Exit LBS Test App ---\n"); + return 1; +} diff --git a/tests/location-api-test.json b/tests/location-api-test.json new file mode 100644 index 0000000..7d3cf9c --- /dev/null +++ b/tests/location-api-test.json @@ -0,0 +1,220 @@ +[ + { + "name": "Seoul city hall(poly)", + "positions": [ + { + "latitude": 37.285217, + "longitude": 127.015343 + }, + { + "latitude": 37.230975, + "longitude": 126.988735 + }, + { + "latitude": 37.21799, + "longitude": 127.087955 + }, + { + "latitude": 37.2859, + "longitude": 127.099457 + } + ], + "marker_position": [ + { + "where": "Youngtong ku office", + "latitude": 37.259246, + "longitude": 127.046948, + "result": "inside" + }, + { + "where": "Yongin", + "latitude": 37.271576, + "longitude": 127.328796, + "result": "outside" + } + ] + }, + { + "name" : "Suwon city hall(4pos)", + "positions": [ + { + "latitude": 43.068888, + "longitude": 158.378906 + }, + { + "latitude": -43.834527, + "longitude": 156.445313 + }, + { + "latitude": -53.852527, + "longitude": -101.953125 + }, + { + "latitude": 41.24472, + "longitude": -134.648437 + } + ], + "marker_position": [ + { + "where": "pos1", + "latitude": 21.289374, + "longitude": 78.398438, + "result": "outside" + }, + { + "where": "pos2", + "latitude": 20.303418, + "longitude": -159.609375, + "result": "inside" + } + ] + }, + { + "name" : "Suwon city hall(4pos_other_seq)", + "positions": [ + { + "latitude": -53.852527, + "longitude": -101.953125 + }, + { + "latitude": 41.24472, + "longitude": -134.648437 + }, + { + "latitude": 43.068888, + "longitude": 158.378906 + }, + { + "latitude": -43.834527, + "longitude": 156.445313 + } + + ], + "marker_position": [ + { + "where": "pos1", + "latitude": 21.289374, + "longitude": 78.398438, + "result": "outside" + }, + { + "where": "pos2", + "latitude": 20.303418, + "longitude": -159.609375, + "result": "inside" + } + ] + + }, + { + "name" : "India(7pos)", + "positions": [ + { + "latitude": 14.43468, + "longitude": 32.519531 + }, + { + "latitude": 22.593726, + "longitude": 40.078125 + }, + { + "latitude": 33.870416, + "longitude": 55.898438 + }, + { + "latitude": 32.249974, + "longitude": 82.96875 + }, + { + "latitude": 9.275622, + "longitude": 116.894531 + }, + { + "latitude": -9.622414, + "longitude": 85.957031 + }, + { + "latitude": 2.460181, + "longitude": 42.363281 + } + ], + "marker_position": [ + { + "where": "pos1", + "latitude": 12.039321, + "longitude": 58.535156, + "result": "inside" + }, + { + "where": "pos2", + "latitude": 8.233237, + "longitude": 71.542969, + "result": "inside" + }, + { + "where": "pos3", + "latitude": 12.039321, + "longitude": 96.679688, + "result": "inside" + }, + { + "where": "pos4", + "latitude": 2.284551, + "longitude": 173.320313, + "result": "outside" + }, + { + "where": "pos5", + "latitude": 20.0, + "longitude": -10.0, + "result": "outside" + } + ] + + }, + { + "name" : "Sydney(6pos)", + "positions": [ + { + "latitude": -34.0214, + "longitude": 151.009054 + }, + { + "latitude": -34.01987, + "longitude": 151.013389 + }, + { + "latitude": -34.021435, + "longitude": 151.0218 + }, + { + "latitude": -34.02581, + "longitude": 151.018109 + }, + { + "latitude": -34.028158, + "longitude": 151.010599 + }, + { + "latitude": -34.02421, + "longitude": 151.00811 + } + ], + "marker_position": [ + { + "where": "pos1", + "latitude": -34.023747, + "longitude": 151.017294, + "result": "inside" + }, + { + "where": "pos2", + "latitude": -34.028798, + "longitude": 71.542969, + "result": "outside" + } + ] + + } + +] diff --git a/tests/map-service-test.c b/tests/map-service-test.c new file mode 100755 index 0000000..22d8f3b --- /dev/null +++ b/tests/map-service-test.c @@ -0,0 +1,1585 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include "location-api-test-util.h" + +#define STR_MAX 128 +LocationMapObject* map_obj = NULL; +static GMainLoop *g_mainloop = NULL; + +#define LOCATION_API_TEST_JSON_FILE "/opt/data/location-api-test.json" + +static gpointer GmainThread(gpointer data) +{ + g_mainloop = g_main_loop_new (NULL, FALSE); + g_printf("\n...Entering GMain Loop to Receive Notifications....\n"); + g_main_loop_run (g_mainloop); + g_main_loop_unref (g_mainloop); + g_mainloop = NULL; + return NULL; +} + + +static void GetLocationError(char str[STR_MAX], int ret) +{ + switch(ret) + { + case LOCATION_ERROR_NONE: + g_utf8_strncpy(str, "LOCATION_ERROR_NONE", STR_MAX); + break; + case LOCATION_ERROR_NOT_ALLOWED: + g_utf8_strncpy(str, "LOCATION_ERROR_NOT_ALLOWED", STR_MAX); + break; + case LOCATION_ERROR_NOT_AVAILABLE: + g_utf8_strncpy(str, "LOCATION_ERROR_NOT_AVAILABLE", STR_MAX); + break; + case LOCATION_ERROR_NETWORK_FAILED: + g_utf8_strncpy(str, "LOCATION_ERROR_NETWORK_FAILED", STR_MAX); + break; + case LOCATION_ERROR_NETWORK_NOT_CONNECTED: + g_utf8_strncpy(str, "LOCATION_ERROR_NETWORK_NOT_CONNECTED", STR_MAX); + break; + case LOCATION_ERROR_CONFIGURATION: + g_utf8_strncpy(str, "LOCATION_ERROR_CONFIGURATION", STR_MAX); + break; + case LOCATION_ERROR_PARAMETER: + g_utf8_strncpy(str, "LOCATION_ERROR_PARAMETER", STR_MAX); + break; + case LOCATION_ERROR_UNKNOWN: + g_utf8_strncpy(str, "LOCATION_ERROR_UNKNOWN", STR_MAX); + break; + case LOCATION_ERROR_NOT_SUPPORTED: + g_utf8_strncpy(str, "LOCATION_ERROR_UNKNOWN", STR_MAX); + break; + case LOCATION_ERROR_SETTING_OFF: + g_utf8_strncpy(str, "LOCATION_ERROR_SETTING_OFF", STR_MAX); + break; + case LOCATION_ERROR_SECURITY_DENIED: + g_utf8_strncpy(str, "LOCATION_ERROR_SECURITY_DENIED", STR_MAX); + break; + default: + g_utf8_strncpy(str, "Error: undefined error code", STR_MAX); + } +} + +static void GetAccuracyLevel(char str[STR_MAX], LocationAccuracyLevel acc_level) +{ + switch (acc_level) { + case LOCATION_ACCURACY_LEVEL_NONE: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_NONE", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_COUNTRY: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_COUNTRY", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_REGION: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_REGION", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_LOCALITY: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_LOCALITY", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_POSTALCODE: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_POSTALCODE", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_STREET: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_STREET", STR_MAX); + break; + case LOCATION_ACCURACY_LEVEL_DETAILED: + g_utf8_strncpy(str, "LOCATION_ACCURACY_LEVEL_DETAILED", STR_MAX); + break; + default: + g_utf8_strncpy(str, "Error: undefined accuracy level", STR_MAX); + } +} + +static void SelectOpt(char* buf) +{ + int iLen = 0; + char *str = NULL; + str = fgets(buf, 255, stdin); + iLen = g_utf8_strlen(buf, -1); + buf[iLen-1] = '\0'; +} + +static int PromptInt() +{ + char buf[255]; + int ret; + char *str = NULL; + str = fgets(buf, 255, stdin); + buf[strlen(buf)-1]='\0'; + ret = g_ascii_strtoll(buf, NULL, 10); + return ret; +} + +static double PromptDB() +{ + char buf[255]; + double ret; + char *str = NULL; + str = fgets(buf, 255, stdin); + buf[strlen(buf)-1]='\0'; + ret = g_ascii_strtod(buf, NULL); + return ret; +} + +static void PrintPos (gpointer data, gpointer user_data) +{ + LocationPosition *pos = (LocationPosition *)data; + if (pos) { + g_printf("time: [%d], latitude: [%f], longitude: [%f], altitude: [%f]\n", pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + location_position_free (pos); + } +} + +static void PrintAcc (gpointer data, gpointer user_data) +{ + LocationAccuracy *acc = (LocationAccuracy *)data; + if (acc) { + g_printf("level: [%d], horizontal_accuracy: [%f], vertical_accuracy: [%f]\n", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_accuracy_free (acc); + } +} + + +static void PrintProperty (LocationObject* loc) +{ + if (!loc) return; +#if 0 + LocationMethod method = LOCATION_METHOD_NONE; + gchar method_str[STR_MAX] = {0, }; + + gchar* devname = NULL; + + g_object_get(loc, "method", &method, NULL); + GetMethod(method_str, method); + g_printf("method[%s] ", method_str); + + if (LOCATION_METHOD_GPS == method) { + g_object_get(loc, "dev-name", &devname, NULL); + if (devname) { + g_printf("dev-name[%s] ", devname); + g_free(devname); + } + } +#endif +} + +static void _print_property (gpointer data, gpointer user_data) +{ + LocationLandmark *landmark = (LocationLandmark *)user_data; + gpointer key = (gpointer)data; + gpointer value = NULL; + + if (key) { + value = (gpointer)location_landmark_get_property(landmark, key); + g_printf(", [%s:%s]", (gchar*) key, (gchar*) value); + } +} + +static void +__plugin_print_poi_list (gpointer data, gpointer user_data) +{ + LocationLandmark *landmark = (LocationLandmark *)data; + LocationPosition *pos = location_landmark_get_position (landmark); + LocationAddress *addr = location_landmark_get_address (landmark); + + g_printf ("[ID:%d], [NAME:%s], phone[%s],pos[%f:%f], addr[%s:%s:%s:%s:%s]", + location_landmark_get_id (landmark), + location_landmark_get_name(landmark), + location_landmark_get_phone_number (landmark), + pos->latitude, pos->longitude, + addr->building_number, addr->city, addr->country_code, addr->district, + addr->postal_code); + + GList *key_list = location_landmark_get_property_key(landmark); + if (key_list) { + g_list_foreach(key_list, _print_property, landmark); + } + + g_printf("\n"); +} + + +static void cb_poi(LocationError error, guint req_id, GList * landmark_list, gchar * error_code, gchar * error_msg, gpointer userdata) +{ + g_printf("\n===== __location_POI_cb ======\n"); + if (error != LOCATION_ERROR_NONE) { + g_printf("Failed :%d\n", error); + return; + } + g_printf("Success, poi_list[0x%x] user_data[0x%x] req_id[%d]\n", (unsigned int)landmark_list, (unsigned int)userdata, req_id); + g_list_foreach (landmark_list, __plugin_print_poi_list, NULL); + + if (error_code && error_msg) { + g_printf("__location_POI_cb: error_code[%s], error_msg[%s]\n", error_code, error_msg); + } +} +static void Print_step_info(const LocationRouteStep *step) +{ + const LocationPosition *start = location_route_step_get_start_point(step); + gdouble start_lat = 0; + gdouble start_lon = 0; + if (start) { + start_lat = start->latitude; + start_lon = start->longitude; + } else { + g_printf("Step start position NULL\n"); + } + const LocationPosition *end = location_route_step_get_end_point(step); + gdouble end_lat = 0; + gdouble end_lon = 0; + if (end) { + end_lat = end->latitude; + end_lon = end->longitude; + } else { + g_printf("Step end position NULL\n"); + } + const gchar *inst = location_route_step_get_instruction(step); + + g_printf("Step: start(%f/%f), end(%f/%f), instruction(%s)\n", start_lat, start_lon, end_lat, end_lon, inst); +} + +static void Print_form_of_way (LocationRoadElement* road_element) +{ + g_printf("+++Print form of way begin \n"); + + FormOfWay form = location_route_element_get_form_of_way(road_element); + + switch (form) { + case FOW_UNDEFINED: + g_printf("Indicates that the road or road type is undefined/unknown\n"); + break; + + case FOW_MOTORWAY: + g_printf("Identifies a road as a motorway \n"); + break; + + case FOW_MULTI_CARRIAGEWAY: + g_printf("Identifies a road as a multi-lane carriageway \n"); + break; + + case FOW_SINGLE_CARRIAGEWAY: + g_printf("Identifies a road as a single carriageway \n"); + break; + + case FOW_ROUNDABOUT: + g_printf("Identifies a road feature as a roundabout/rotary \n"); + break; + + case FOW_SPECIAL_TRAFFIC_FIGURE: + g_printf("Identifies a road features as a special traffic figure \n"); + break; + + case FOW_SLIPROAD: + g_printf(" Identifies a road as a slip road \n"); + break; + + case FOW_PEDESTRIAN_ZONE: + g_printf("Identifies an area or road section as a pedestrian zone \n"); + break; + + case FOW_PEDESTRIAN_WALKWAY: + g_printf(" Identifies a pedestrian walkway \n"); + break; + + case FOW_SERVICE_ACCESS_PARKING: + g_printf(" Identifies access to a parking facility \n"); + break; + + case FOW_SERVICE_ACCESS_OTHER: + g_printf(" Identifies access to an unspecified service or facility \n"); + break; + + case FOW_SERVICE_ROAD: + g_printf(" Identifies a road as a service road \n"); + break; + + case FOW_ETA_PARKING_PLACE: + g_printf(" Identifies a parking facility \n"); + break; + + case FOW_ETA_PARKING_BUILDING: + g_printf(" Identifies a parking house \n"); + break; + + case FOW_ETA_UNSTRUCTURED_TRAFFIC_SQUARE: + g_printf(" Identifies an unstructured traffic square \n"); + break; + + case FOW_ROAD_FOR_AUTHORITIES: + g_printf(" Identifies a road restricted for authorized access only \n"); + break; + + default: + g_warning ("ASYNC>> Undefined Form Of Way type"); + break; + } + g_printf("---Print form of way end\n"); +} + +static void Print_transit_type (LocationRoadElement* road_element) +{ + g_printf("+++Print transit type begin \n"); + + TransitType ttype = location_route_element_get_transit_type(road_element); + switch (ttype) { + case TRANSIT_TYPE_BUS_PUBLIC: + g_printf("Indicates transit type is bus public\n"); + break; + + case TRANSIT_TYPE_BUS_TOURISTIC: + g_printf("Indicates transit type is bus touristic\n"); + break; + + case TRANSIT_TYPE_BUS_INTERCITY: + g_printf("Indicates transit type is bus intercity \n"); + break; + + case TRANSIT_TYPE_BUS_EXPRESS: + g_printf("Indicates transit type is bus express \n"); + break; + + case TRANSIT_TYPE_RAIL_METRO: + g_printf("Indicates transit type is rail metro \n"); + break; + + case TRANSIT_TYPE_RAIL_LIGHT: + g_printf("Indicates transit type is rail light \n"); + break; + + case TRANSIT_TYPE_RAIL_REGIONAL: + g_printf("Indicates transit type is rail regional \n"); + break; + + case TRANSIT_TYPE_TRAIN_REGIONAL: + g_printf("Indicates transit type is train \n"); + break; + + case TRANSIT_TYPE_TRAIN_INTERCITY: + g_printf("Indicates transit type is bus regional \n"); + break; + + case TRANSIT_TYPE_TRAIN_HIGH_SPEED: + g_printf("Indicates transit type is high speed \n"); + break; + + case TRANSIT_TYPE_MONORAIL: + g_printf("Indicates transit type is monorall \n"); + break; + + case TRANSIT_TYPE_AERIAL: + g_printf("Indicates transit type is aerial \n"); + break; + + case TRANSIT_TYPE_INCLINED: + g_printf("Indicates transit type is inclined \n"); + break; + + case TRANSIT_TYPE_WATER: + g_printf("Indicates transit type is water \n"); + break; + + case TRANSIT_TYPE_AIRLINE: + g_printf("Indicates transit type is airline \n"); + break; + + case TRANSIT_TYPE_RESERVED: + g_printf("Indicates reserved for future usage \n"); + break; + + case TRANSIT_TYPE_COUNT: + g_printf("Indicates transit type's count \n"); + break; + + default: + g_warning ("ASYNC>> Undefined Transit Type \n"); + break; + } + g_printf("---Print transit type end\n"); +} + +static void Print_road_element(LocationRouteStep *step) +{ + g_printf("+++PrintRoadElement begin\n"); + LocationRoadElement* road_element = location_route_step_get_road_element(step); + + Print_transit_type(road_element); + Print_form_of_way( road_element); + + gboolean is_plural = location_route_element_is_plural(road_element); + if (is_plural) { + g_printf(" The road element is plural \n"); + } + else { + g_printf(" The road element is not plural \n"); + } + gchar *road_name = location_route_element_get_road_name(road_element); + gchar *route_name = location_route_element_get_route_name(road_element); + gfloat speed_l = location_route_element_get_speed_limit(road_element); + guint speed = location_route_element_get_average_speed_m_s(road_element); + guint nums = location_route_element_get_number_of_lanes(road_element); + guint s_time = location_route_element_get_element_start_time(road_element); + guint t_time = location_route_element_get_element_travel_time(road_element); + + g_printf("RoadElement: road_name(%s), route_name(%s), speed_l(%f), speed(%d), nums(%d), s_time(%d), t_time(%d)\n", + road_name, route_name, speed_l, speed, nums, s_time, t_time); + + gboolean is_pedestrain = location_route_element_road_element_is_pedestrian(road_element); + if (is_pedestrain) { + g_printf(" The road is allowed only for pedestrians \n"); + } + else { + g_printf(" The road is not only for pedestrians \n"); + } + + gboolean is_valid = location_route_element_road_element_is_valid(road_element); + if (is_valid) { + g_printf(" This road element is valid \n"); + } + else { + g_printf(" This road element is invalid \n"); + } + + gchar *t_dest = location_route_element_get_transit_destination(road_element); + gchar *t_line = location_route_element_get_transit_line_name(road_element); + gchar *official = location_route_element_get_system_official_name(road_element); + gchar *short_name = location_route_element_get_system_short_name(road_element); + + gchar *type_name = location_route_element_get_transit_type_name(road_element); + guint d_t = location_route_element_get_transit_departure_time(road_element); + guint a_t = location_route_element_get_transit_arrival_time(road_element); + LocationRouteTransitStop *d_s = location_route_element_get_transit_departure_station(road_element); + gchar *d_s_name = location_route_transit_get_station_name(d_s); + gint d_s_level = location_route_transit_get_platform_level(d_s); + LocationPosition *d_s_plat_pos = location_route_transit_get_platform_coordinates(d_s); + if (d_s_plat_pos) { + g_printf ("d_s_plat_pos: time: %d, lat: %f, long: %f, alt: %f, status: %d\n", + d_s_plat_pos->timestamp, d_s_plat_pos->latitude, d_s_plat_pos->longitude, d_s_plat_pos->altitude, d_s_plat_pos->status); + //location_position_free (d_s_plat_pos); + } + + LocationPosition *d_s_egr_pos = location_route_transit_get_egress_coordinates(d_s); + if (d_s_egr_pos) { + g_printf ("d_s_egr_pos: time: %d, lat: %f, long: %f, alt: %f, status: %d\n", + d_s_egr_pos->timestamp, d_s_egr_pos->latitude, d_s_egr_pos->longitude, d_s_egr_pos->altitude, d_s_egr_pos->status); + //location_position_free (d_s_egr_pos); + } + + g_printf("Transit: d_s_name(%s), d_s_level(%d)\n", d_s_name, d_s_level); + + g_printf("Transit: t_dest(%s), t_line(%s), official(%s), short(%s), type_name(%s), d_t(%d), a_t(%d)\n", + t_dest, t_line, official, short_name, type_name, d_t, a_t); + + LocationRouteTransitStop *a_s = location_route_element_get_transit_arrival_station(road_element); + gchar *a_s_name = location_route_transit_get_station_name(a_s); + gint a_s_level = location_route_transit_get_platform_level(a_s); + if (a_s) { + g_printf("Transit: a_s_name(%s), a_s_level(%d) \n",a_s_name, a_s_level); + } + + g_printf("---Print Road Element end\n"); +} + +static void print_route_maneuver(LocationRouteManeuver *maneuver) +{ + g_printf("+++print route maneuver begin\n"); + + TrafficDirection dirct = TRAFFIC_DIR_LEFT; + + guint dist_start = location_route_maneuver_get_distance_from_start(maneuver); + guint dist_prev = location_route_maneuver_get_distance_from_previous_maneuver(maneuver); + g_printf("maneuver: dist_start(%d), dist_prev(%d)\n", dist_start, dist_prev); + + gchar *next_road_name = location_route_maneuver_get_next_road_name(maneuver); + gchar *action = location_route_maneuver_get_action(maneuver); + gchar *turn =location_route_maneuver_get_turn(maneuver); + g_printf("maneuver: next_road_name(%s), action(%s), turn(%s)\n", next_road_name, action, turn); + + dirct = location_route_maneuver_get_traffic_direction(maneuver); + if (TRAFFIC_DIR_LEFT == dirct) { + g_printf("Traffic is left sided. \n"); + } + else if (TRAFFIC_DIR_RIGHT == dirct) { + g_printf("Traffic is right sided. \n"); + } + + guint angle = location_route_maneuver_get_angle(maneuver); + guint start_angle = location_route_maneuver_get_start_angle(maneuver); + guint s_time = location_route_maneuver_get_start_time(maneuver); + g_printf("maneuver: angle(%d), start_angle(%d), s_time(%d)\n", angle, start_angle, s_time); + + gboolean is_s_sliproad = location_route_maneuver_is_starts_from_sliproad(maneuver); + gboolean is_n_sliproad = location_route_maneuver_is_next_is_sliproad(maneuver); + gboolean is_round = location_route_maneuver_is_counter_roundabout(maneuver); + + if (is_n_sliproad) { + g_printf("Maneuver starts on a sliproad. \n"); + } + if (is_s_sliproad) { + g_printf("Next road is sliproad. \n"); + } + if (is_round) { + g_printf("This maneuver is a roundabout. \n"); + } + + g_printf("---print route maneuver end\n"); +} + +static void cb_print_maneuver_lanes (gpointer data, gpointer user_data) +{ + g_printf("+++lanes begin\n"); + LocationRouteLaneInfo *lane = (LocationRouteLaneInfo *)data; + + gboolean on_route = location_route_lane_is_on_route(lane); + if (on_route) { + g_printf("this lane is on the route\n"); + } else { + g_printf("this lane is NOT on the route\n"); + } + g_printf("---lanes end\n"); +} + +static void cb_print_route_step (gpointer data, gpointer user_data) +{ + g_printf("+++Step begin\n"); + LocationRouteStep *step = (LocationRouteStep *)data; + + Print_step_info(step); + g_printf("after Print Step Info\n"); + + /*****************NLP start now *********************/ + g_printf("*****************NLP step start now *********************\n"); + Print_road_element(step); + + LocationRouteManeuver *maneuver = location_route_step_get_maneuver(step); + print_route_maneuver(maneuver); + + GList *lanes = location_route_maneuver_get_lanes(maneuver); + if (lanes) { + g_list_foreach(lanes, cb_print_maneuver_lanes, NULL); + } + g_printf("---Step end\n"); +} + +static void print_pos_nokia (gpointer data, gpointer user_data) +{ + g_printf("+++print pos nokia begin. \n"); + + LocationPosition *pos = (LocationPosition *)data; + + if (pos) { + g_printf ("time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + //location_position_free (pos); + } + + g_printf("---print pos nokia end\n"); +} + +static void print_acc_nokia (gpointer data, gpointer user_data) +{ + g_printf("+++print acc nokia begin. \n"); + + LocationAccuracy *acc = (LocationAccuracy *)data; + + if (acc) { + g_printf ("\tAccuracy level %d (%.0f meters %.0f meters)", acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + //location_accuracy_free (acc); + } + + g_printf("---print acc nokia end. \n"); +} + +static void cb_position_from_address_nokia (LocationError error, GList *pos_list, GList *acc_list, gpointer userdata) +{ + g_printf("+++cb position from address nokia. \n"); + + if (error != LOCATION_ERROR_NONE) { + g_debug("cb_position_from_address failed: error=%d\n", error); + return; + } + + g_list_foreach (pos_list, print_pos_nokia, NULL); + g_list_foreach (pos_list, print_acc_nokia, NULL); + g_printf("---cb position from address nokia end. \n"); +} + +static void cb_print_route_segment (gpointer data, gpointer user_data) +{ + g_printf("++Segment begin\n"); + LocationRouteSegment *seg = (LocationRouteSegment *)data; + gdouble seg_dist = location_route_segment_get_distance(seg); + glong seg_duration = location_route_segment_get_duration(seg); + const LocationPosition *start = location_route_segment_get_start_point(seg); + gdouble start_lat = 0; + gdouble start_lon = 0; + if (start) { + start_lat = start->latitude; + start_lon = start->longitude; + } else { + g_printf("Segment start position NULL\n"); + } + const LocationPosition *end = location_route_segment_get_end_point(seg); + gdouble end_lat = 0; + gdouble end_lon = 0; + if (end) { + end_lat = end->latitude; + end_lon = end->longitude; + } else { + g_printf("Segment end postion NULL\n"); + } + g_printf("Segment info: Distance[%f], Duration[%ld], start(%f/%f), end(%f/%f)\n", seg_dist, seg_duration, + start_lat, start_lon, end_lat, end_lon); + + GList *step_list = location_route_segment_get_route_step(seg); + GList *tmp_list = (GList *)step_list; + if (tmp_list) { + g_list_foreach(tmp_list, cb_print_route_step, NULL); + } + g_printf("--Segment end\n"); +} + + +static void cb_print_route_list (gpointer data, gpointer user_data) +{ + g_printf("+Route begin\n"); + LocationRoute *route = (LocationRoute *)data; + + const LocationPosition *start = location_route_get_origin(route); + gdouble start_lat = 0; + gdouble start_lon = 0; + if (start) { + start_lat = start->latitude; + start_lon = start->longitude; + } else { + g_printf("Route start position NULL\n"); + } + const LocationPosition *end = location_route_get_destination(route); + gdouble end_lat = 0; + gdouble end_lon = 0; + if (end) { + end_lat = end->latitude; + end_lon = end->longitude; + } else { + g_printf("Route end position NULL\n"); + } + g_printf("Route: start(%f/%f), end(%f/%f)\n", start_lat, start_lon, end_lat, end_lon); + + gdouble distance = location_route_get_total_distance(route); + const gchar *dis_unit = location_route_get_distance_unit(route); + glong duration = location_route_get_total_duration(route); + const LocationBoundary *bound = location_route_get_bounding_box(route); + if (bound && bound->type == LOCATION_BOUNDARY_RECT) { + g_printf("RECT left top[%f-%f], right bottom[%f-%f]\n", bound->rect.left_top->latitude, bound->rect.left_top->longitude, + bound->rect.right_bottom->latitude, bound->rect.right_bottom->longitude); + } else { + g_printf("route boundary not exist, or not RECT\n"); + } + g_printf ("Distance[%f], Distance unit[%s], Duration[%ld]\n", distance, dis_unit, duration); + + GList *seg_list = location_route_get_route_segment(route); + if (seg_list) { + g_list_foreach(seg_list, cb_print_route_segment, NULL); + } + + g_printf("-Route end\n"); +} + +static void cb_route(LocationError error, guint req_id, GList * route_list, gchar * error_code, gchar * error_msg, gpointer userdata) +{ + g_printf("\n===== cb_route ======\n"); + if (error != LOCATION_ERROR_NONE) { + g_printf("Failed :%d\n", error); + return; + } + + g_printf("Success, poi_list[0x%x] user_data[0x%x] req_id[%d]\n", (unsigned int)route_list, (unsigned int)userdata, req_id); + + if (route_list) + g_list_foreach (route_list, cb_print_route_list, NULL); + + if (error_code && error_msg) { + g_printf("cb_route: error_code[%s], error_msg[%s]\n", error_code, error_msg); + } +} + +static void cb_address(LocationError error, LocationAddress *addr, LocationAccuracy *acc, gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE) { + g_printf("cb_address failed: error=%d\n", error); + return; + } + char str[STR_MAX]; + g_printf("userdata[0x%x] building number: [%s], street: [%s], state: [%s], country code: [%s], city: [%s], district: [%s], postal code: [%s]\n", + (unsigned int)userdata, addr->building_number, addr->street, addr->state, addr->country_code, addr->city, addr->district, addr->postal_code); + GetAccuracyLevel(str, acc->level); + g_printf("level: [%s], horizontal_accuracy: [%f], vertical_accuracy: [%f]\n", str, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +static void cb_position (LocationError error, + GList *pos_list, + GList *acc_list, + gpointer userdata) +{ + if (error != LOCATION_ERROR_NONE) { + g_printf("cb_position failed: error=%d\n", error); + return; + } + + g_list_foreach (pos_list, PrintPos, NULL); + g_list_foreach (acc_list, PrintAcc, NULL); +} + + +typedef struct { + LocationObject *obj; + LocationPosition *pos; + LocationAddress *addr; + gchar *str_addr; + LocationPositionCB pos_cb; + LocationAddressCB addr_cb; + gpointer user_data; +} IdleData; + +static gboolean idle_position_from_address_async(gpointer data) +{ + IdleData* idle_data = (IdleData*)data; + char str[STR_MAX]; + int ret = location_map_get_position_from_address_async(idle_data->obj, idle_data->addr, idle_data->pos_cb, idle_data->user_data); + GetLocationError(str, ret); + g_printf("location_get_position_from_address_async: returned value [%s]\n", str); + location_address_free(idle_data->addr); + g_free(idle_data); + return FALSE; +} + +static gboolean idle_position_from_freefromed_address_async(gpointer data) +{ + IdleData* idle_data = (IdleData*)data; + char str[STR_MAX]; + int ret = location_map_get_position_from_freeformed_address_async(idle_data->obj, idle_data->str_addr, idle_data->pos_cb, idle_data->user_data); + GetLocationError(str, ret); + g_printf("location_get_position_from_freeformed_address_async: returned value [%s]\n", str); + g_free(idle_data->str_addr); + g_free(idle_data); + return FALSE; +} + +static gboolean idle_address_from_position_async(gpointer data) +{ + IdleData* idle_data = (IdleData*)data; + char str[STR_MAX]; + int ret = location_map_get_address_from_position_async(idle_data->obj, idle_data->pos, idle_data->addr_cb, idle_data->user_data); + GetLocationError(str, ret); + g_printf("location_map_get_address_from_position_async: returned value [%s]\n", str); + location_position_free(idle_data->pos); + g_free(idle_data); + return FALSE; +} +static gboolean idle_location_map_get_position_from_address_async(gpointer data) +{ + g_printf("+++idle location map get position from address async begin\n"); + IdleData* idle_data = (IdleData*)data; + + LocationError err = location_map_get_position_from_address_async(idle_data->obj,idle_data->addr,idle_data->pos_cb,idle_data->user_data); + + if (LOCATION_ERROR_NONE == err){ + g_debug("location_map_get_position_from_address_async() success"); + } + else{ + g_warning ("location_map_get_position_from_address_async() failed> error code:%d", err); + } + g_free(idle_data); + g_printf("---idle location map get position from address async end\n"); + return FALSE; +} + +void _print_keys(gpointer data, gpointer user_data) +{ + g_printf(" %s ", (gchar*) data); +} + +static void print_map_service_keys (LocationObject *obj, int type) +{ + GList *key = NULL; + + location_map_get_provider_capability_key (obj, type, &key); + + if (key) { + g_list_foreach (key, (GFunc)_print_keys, NULL); + } + + g_list_free_full(key, g_free); +} + +void _print_provider (gpointer data, gpointer user_data) +{ + gchar *provider = (gchar *)data; + + g_printf("[%s] is supported\n", provider); +} + +static void print_menu() +{ + g_printf("\n================================= Location API Test =================================\n"); + g_printf("q. Exit\n"); + g_printf("1. location_init\n"); + g_printf("2. location_map_new for default \n"); + g_printf("2a. location_map_new for decarta \n"); + g_printf("2b. location_map_new for osm \n"); + g_printf("2c. location_map_new for nlp \n"); + g_printf("3. location_map_free\n"); + g_printf("4. location_map_get_address_from_position_async\n"); + g_printf("5. location_map_get_position_from_address_async\n"); + g_printf("6. location_map_get_position_from_freeformed_address_async\n"); + g_printf("7. location_map_search_poi_with_keyword\n"); + g_printf("7a. location_map_search_poi_with_category\n"); + g_printf("7b. location_map_search_poi_with_poi_name\n"); + g_printf("8. location_map_search_poi_by_area_with_keyword\n"); + g_printf("8a. location_map_search_poi_by_area_with_category\n"); + g_printf("8b. location_map_search_poi_by_area_with_poi_name\n"); + g_printf("9. location_map_search_poi_by_addr_with_keyword\n"); + g_printf("9a. location_map_search_poi_by_addr_with_category\n"); + g_printf("9b. location_map_search_poi_by_addr_with_poi_name\n"); + g_printf("10. location_map_search_poi_by_freeformed_address_with_keyword\n"); + g_printf("10a. location_map_search_poi_by_freeformed_address_with_category\n"); + g_printf("10b. location_map_search_poi_by_freeformed_address_with_poi_name\n"); + g_printf("11. location_map_cancel_poi_request\n"); + g_printf("12. location_map_request_route\n"); + g_printf("12a. location_map_request_route for a long distance\n"); + g_printf("13. location_map_cancel_route_request\n"); + g_printf("14. location_map_is_supported_provider_capability\n"); + g_printf("15. location_map_get_provider_capability_key\n"); + g_printf("16. location_map_get_supported_providers \n"); + g_printf("17. location_map_get_default_provider \n"); + g_printf("18. location_map_set_provider \n"); + g_printf("99. change map provider to default\n"); + g_printf("99a. change map provider to decarta\n"); + g_printf("99b. change map provider to osm\n"); + + g_printf("==================================== Property ====================================\n"); + PrintProperty(map_obj); + g_printf("\n==================================================================================\n"); +} + +int main(int argc, char** argv) +{ + char strOpt[255]; + int ret; + char str[STR_MAX]; + GError *gerr = NULL; + guint req_id = 0; + + // If application is executed by AUL, this is not needed. + g_setenv("PKG_NAME", "org.tizen.map-service-test", 1); + + g_type_init(); + +#if !GLIB_CHECK_VERSION (2, 31, 0) + if( !g_thread_supported() ) + { + g_thread_init(NULL); + } +#endif + + GThread *g_main; + g_main = g_thread_create(GmainThread, NULL, TRUE, &gerr); + if (!g_main) { + g_debug("Error create gmain thread: Err domain[%d] Err code[%d] Err msg[%s]", + gerr->domain, gerr->code, gerr->message); + g_error_free(gerr); + return 0; + } + + g_printf("--- Start LBS Test App ---\n"); + while(1) + { + print_menu(); + g_printf("Select option: "); + SelectOpt(strOpt); + g_printf("======================================================================================\n"); + if (0 == g_strcmp0 ("x", strOpt)) { + + } + else if (0 == g_strcmp0("1",strOpt)) { + ret = location_init(); + GetLocationError(str, ret); + g_printf("location_init: returned value [%s]\n", str); + } else if (0 == g_strcmp0("2",strOpt)) { + if (map_obj) { + g_printf("Location object already existed: [0x%x]", (unsigned int)map_obj); + continue; + } + map_obj = location_map_new(NULL); + if(map_obj) g_printf("Success\n"); + else g_printf("Failed\n"); + } else if (0 == g_strcmp0("2a",strOpt)) { + if (map_obj) { + g_printf("Location object already existed: [0x%x]", (unsigned int)map_obj); + continue; + } + map_obj = location_map_new("decarta"); + if(map_obj) g_printf("Success\n"); + else g_printf("Failed\n"); + } else if (0 == g_strcmp0("2b",strOpt)) { + if (map_obj) { + g_printf("Location object already existed: [0x%x]", (unsigned int)map_obj); + continue; + } + map_obj = location_map_new("osm"); + if(map_obj) g_printf("Success\n"); + else g_printf("Failed\n"); + } + else if (0 == g_strcmp0("2c",strOpt)) { + if (map_obj) { + g_printf("Location object already existed: [0x%x]", (unsigned int)map_obj); + continue; + } + map_obj = location_map_new("nlp"); + if(map_obj) { + g_printf("Success\n"); + } + else + { + g_printf("Failed\n"); + } + } else if (0 == g_strcmp0("3",strOpt)) { + ret = location_map_free (map_obj); + map_obj = NULL; + GetLocationError(str, ret); + g_printf("location_map_free: returned value [%s]\n", str); + }else if(0 == g_strcmp0("4",strOpt) ){ + IdleData* data = g_new0(IdleData, 1); + data->obj = map_obj; + data->addr_cb = cb_address; + data->user_data = map_obj; + + g_printf("[0].San jose [1].Suwon HQ [*].Custom\n"); + g_printf("Select Position: "); + int opt = PromptInt(); + if(opt == 0) data->pos = location_position_new(0, 37.335276, -121.890059, 0, LOCATION_STATUS_2D_FIX); + else if (opt == 1) data->pos = location_position_new(0, 37.257809, 127.056383, 0, LOCATION_STATUS_2D_FIX); + else { + g_printf("Input latitude: "); + gdouble lat = PromptDB(); + g_printf("Input longitude: "); + gdouble lon = PromptDB(); + data->pos = location_position_new(0, lat, lon, 0, LOCATION_STATUS_2D_FIX); + } + g_idle_add((GSourceFunc)idle_address_from_position_async, data); + } else if (0 == g_strcmp0("5", strOpt)) { + IdleData* data = g_new0(IdleData, 1); + data->obj = map_obj; + data->pos_cb = cb_position; + data->user_data = map_obj; + + g_printf("[0].San jose [1].수원 삼성 [2].Suwon HQ [*].Custom\n"); + g_printf("Select Address: "); + int opt = PromptInt(); + char *ret_str = NULL; + if (opt == 0) data->addr = location_address_new ("1", "Post Street", NULL, "san jose", "ca", NULL, "95113", NULL, NULL, NULL); + else if (opt == 1) data->addr = location_address_new (NULL, "삼성전자", "매탄3동", "수원시 영>통구", "경기도", NULL, NULL, NULL, NULL, NULL); + else if (opt == 2) data->addr = location_address_new (NULL, "Samsung Electro-Mechanics Co. LTD", "Maetan 3-dong", "Suwon Si Yeongtong-gu", "Gyeonggi-do", NULL, NULL, NULL, NULL, NULL); + else { + char building_number[255], street[255], state[255], country_code[255], city[255], district[255], postal_code[255]; + g_printf("Input building number: "); + ret_str = fgets(building_number, 255, stdin); + building_number[strlen(building_number)-1]='\0'; + g_printf("Input street: "); + ret_str = fgets(street, 255, stdin); + street[strlen(street)-1]='\0'; + g_printf("Input state: "); + ret_str = fgets(state, 255, stdin); + state[strlen(state)-1]='\0'; + g_printf("Input country code: "); + ret_str = fgets(country_code, 255, stdin); + country_code[strlen(country_code)-1]='\0'; + g_printf("Input city: "); + ret_str = fgets(city, 255, stdin); + city[strlen(city)-1]='\0'; + g_printf("Input district: "); + ret_str = fgets(district, 255, stdin); + district[strlen(district)-1]='\0'; + g_printf("Input postal code: "); + ret_str = fgets(postal_code, 255, stdin); + postal_code[strlen(postal_code)-1]='\0'; + data->addr = location_address_new(building_number, street, district, city, state, country_code, postal_code, NULL, NULL, NULL); + } + g_idle_add((GSourceFunc)idle_position_from_address_async, data); + }else if(0 == g_strcmp0("6",strOpt) ){ + IdleData* data = g_new0(IdleData, 1); + data->obj = map_obj; + data->pos_cb = cb_position; + data->user_data = map_obj; + g_printf("[0].San jose [1].수원 삼성 [2].Suwon HQ [*].Custom\n"); + g_printf("Select Address: "); + int opt = PromptInt(); + char *ret_str = NULL; + if(opt == 0){ + data->str_addr = g_strdup("4 N 2nd Street 95113"); + }else if(opt == 1){ + data->str_addr = g_strdup("경기도 수원시 영통구 매탄 3동 삼성전자"); + }else if(opt == 2){ + data->str_addr = g_strdup("Samsung Electronics Co. LTD Maetan 3-dong, Suwon Si Yeongtong-gu, Gyeonggi-Do (Seoul 443-742 Korea), Rep of KOREA"); + }else{ + char buf[255]; + g_printf("Input freeform address: "); + ret_str = fgets(buf, 255, stdin); + buf[strlen(buf)-1]='\0'; + data->str_addr = g_strdup(buf); + } + g_idle_add((GSourceFunc)idle_position_from_freefromed_address_async, data); + + }else if(0 == g_strcmp0("7", strOpt)) { + g_printf("location_map_search_poi\n"); + + LocationPOIFilter *filter = location_poi_filter_new(); + location_poi_filter_set(filter, "KEYWORD", "pizza"); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 2); + location_poi_pref_set_sort_by(pref, "Distance"); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_DESC); + + LocationPosition *position = location_position_new(0, 37.771008, -122.41175, 0, LOCATION_STATUS_2D_FIX); + + ret = location_map_search_poi(map_obj, filter, position, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if(ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI. Error[%s]\n", str); + } else { + g_printf("Seach POI success, req_id %d\n", req_id); + } + + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_position_free(position); + }else if(0 == g_strcmp0("7a", strOpt)) { + g_printf("location_map_search_poi_with_category\n"); + LocationPOIFilter *filter = location_poi_filter_new(); + location_poi_filter_set(filter, "CATEGORY", "restaurant"); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 5); + location_poi_pref_set_sort_by(pref, "Distance"); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + LocationPosition *position = location_position_new(0, 37.771008, -122.41175, 0, LOCATION_STATUS_2D_FIX); + + ret = location_map_search_poi(map_obj, filter, position, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if(ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI. Error[%s]\n", str); + } else { + g_printf("Seach POI success, req_id %d\n", req_id); + } + + location_poi_filter_free(filter);g_printf("location_search_poi_by_freeformed_address_with_poi_name\n"); + location_poi_pref_free(pref); + location_position_free(position); + + }else if(0 == g_strcmp0("7b", strOpt)) { + g_printf("location_map_search_poi_with_poi_name\n"); + + LocationPOIFilter *filter = location_poi_filter_new(); + location_poi_filter_set(filter, "POIName", "cafe"); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 10); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_DESC); + + LocationPosition *position = location_position_new(0, 37.771008, -122.41175, 0, LOCATION_STATUS_2D_FIX); + + ret = location_map_search_poi(map_obj, filter, position, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if(ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI. Error[%s]\n", str); + } else { + g_printf("Seach POI success, req_id %d\n", req_id); + } + + location_poi_filter_free(filter); + location_poi_pref_free(pref); + location_position_free(position); + + }else if(0 == g_strcmp0("8", strOpt)) { + g_printf("location_map_search_poi_by_area_with_keyword\n"); + + // only circle supported by decarta + LocationPosition *center = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + gdouble radius = 400; + LocationBoundary *bound = location_boundary_new_for_circle(center, radius); + + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("KEYWORD"); + gchar *value = g_strdup("cafe"); + location_poi_filter_set(filter, key, value); // same with Type ? CATEGORY, KEYWORD, POIName + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 10); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); // can't set const char* directly !! + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); //LOCATION_POI_PREF_SO_ASC + + + ret = location_map_search_poi_by_area(map_obj, filter, bound, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI by area. Error[%s]\n", str); + } else { + g_printf("Seach POI by area sucess, req_id %d\n", req_id); + } + + g_free(key); + g_free(value); + g_free(item); + location_position_free(center); + location_boundary_free(bound); + location_poi_filter_free(filter); + location_poi_pref_free(pref); + }else if(0 == g_strcmp0("8a", strOpt)) { + g_printf("location_map_search_poi_by_area_with_category\n"); + + // only circle supported by decarta + LocationPosition *center = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + gdouble radius = 400; + LocationBoundary *bound = location_boundary_new_for_circle(center, radius); + + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("CATEGORY"); + gchar *value = g_strdup("restaurant"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 5); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_map_search_poi_by_area(map_obj, filter, bound, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI by area. Error[%s]\n", str); + } else { + g_printf("Seach POI by area sucess, req_id %d\n", req_id); + } + + g_free(key); + g_free(value); + g_free(item); + location_position_free(center); + location_boundary_free(bound); + location_poi_filter_free(filter); + location_poi_pref_free(pref); + + }else if(0 == g_strcmp0("8b", strOpt)) { + g_printf("location_map_search_poi_by_area_with_poi_name\n"); + + // only circle supported by decarta + LocationPosition *center = location_position_new(0, 37.336723, -121.889555, 0, LOCATION_STATUS_2D_FIX); + gdouble radius = 400; + LocationBoundary *bound = location_boundary_new_for_circle(center, radius); + + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("POIName"); + gchar *value = g_strdup("cafe"); + location_poi_filter_set(filter, key, value); // same with Type ? CATEGORY, KEYWORD, POIName + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 10); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); // can't set const char* directly !! + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); //LOCATION_POI_PREF_SO_ASC + + + ret = location_map_search_poi_by_area(map_obj, filter, bound, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI by area. Error[%s]\n", str); + } else { + g_printf("Seach POI by area sucess, req_id %d\n", req_id); + } + + g_free(key); + g_free(value); + g_free(item); + location_position_free(center); + location_boundary_free(bound); + location_poi_filter_free(filter); + location_poi_pref_free(pref); + + }else if(0 == g_strcmp0("9", strOpt)) { + g_printf("location_map_search_poi_by_address_with_keyword\n"); + + LocationAddress *addr = location_address_new("51", "N SAN PEDRO ST", NULL, "SAN JOSE", "SANTA CLARA", "CA", "95110",NULL,NULL,NULL); + + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("KEYWORD"); + gchar *value = g_strdup("cafe"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 10); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_map_search_poi_by_address(map_obj, filter, addr, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if(ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI by address. Error[%s]\n", str); + } else { + g_printf("Seach POI by address sucess, req_id %d\n", req_id); + } + + g_free(key); + g_free(value); + g_free(item); + + location_address_free(addr); + location_poi_filter_free(filter); + location_poi_pref_free(pref); + }else if(0 == g_strcmp0("9a", strOpt)) { + g_printf("location_search_poi_by_address_with_category\n"); + + LocationAddress *addr = location_address_new("51", "N SAN PEDRO ST", NULL, "SAN JOSE", "SANTA CLARA", "CA", "95110",NULL,NULL,NULL); + + LocationPOIFilter *filter = location_poi_filter_new(); + location_poi_filter_set(filter, "CATEGORY", "restaurant"); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 10); + location_poi_pref_set_sort_by(pref, "Distance"); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_map_search_poi_by_address(map_obj, filter, addr, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if(ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI by address. Error[%s]\n", str); + } else { + g_printf("Seach POI by address sucess, req_id %d\n", req_id); + } + + location_address_free(addr); + location_poi_filter_free(filter); + location_poi_pref_free(pref); + }else if(0 == g_strcmp0("9b", strOpt)) { + g_printf("location_map_search_poi_by_address_with_poi_name\n"); + + LocationAddress *addr = location_address_new("51", "N SAN PEDRO ST", NULL, "SAN JOSE", "SANTA CLARA", "CA", "95110",NULL,NULL,NULL); + + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("POIName"); + gchar *value = g_strdup("cafe"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 10); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_map_search_poi_by_address(map_obj, filter, addr, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if(ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI by address. Error[%s]\n", str); + } else { + g_printf("Seach POI by address sucess, req_id %d\n", req_id); + } + + g_free(key); + g_free(value); + g_free(item); + + location_address_free(addr); + location_poi_filter_free(filter); + location_poi_pref_free(pref); + + }else if(0 == g_strcmp0("10", strOpt)) { + g_printf("location_map_search_poi_by_freeformed_address_with_keyword\n"); + + gchar *addr = g_strdup("North Second St."); + + LocationPOIFilter *filter = location_poi_filter_new(); + location_poi_filter_set(filter, "KEYWORD", "station"); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 10); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); // can't set const char* directly !! + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); //LOCATION_POI_PREF_SO_ASC + + ret = location_map_search_poi_by_freeformed_address(map_obj, filter, addr, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI by address. Error[%s]\n", str); + } else { + g_printf("Seach POI by address success, req_id %d\n", req_id); + } + + g_free(item); + + g_free(addr); + location_poi_filter_free(filter); + location_poi_pref_free(pref); + }else if(0 == g_strcmp0("10a", strOpt)) { + g_printf("location_map_search_poi_by_freeformed_address_with_category\n"); + + gchar *addr = g_strdup("North Second St."); + + LocationPOIFilter *filter = location_poi_filter_new(); + gchar *key = g_strdup("CATEGORY"); + gchar *value = g_strdup("restaurant"); + location_poi_filter_set(filter, key, value); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 10); + gchar *item = g_strdup("Distance"); + location_poi_pref_set_sort_by(pref, item); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_map_search_poi_by_freeformed_address(map_obj, filter, addr, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI by address. Error[%s]\n", str); + } else { + g_printf("Seach POI by address success, req_id %d\n", req_id); + } + + g_free(key); + g_free(value); + g_free(item); + + g_free(addr); + location_poi_filter_free(filter); + location_poi_pref_free(pref); + }else if(0 == g_strcmp0("10b", strOpt)) { + g_printf("location_map_search_poi_by_freeformed_address_with_poi_name\n"); + + gchar *addr = g_strdup("North Second St."); + + LocationPOIFilter *filter = location_poi_filter_new(); + location_poi_filter_set(filter, "POIName", "pizza"); + + LocationPOIPreference *pref = location_poi_pref_new(); + location_poi_pref_set_max_result(pref, 10); + location_poi_pref_set_sort_by(pref, "Distance"); + location_poi_pref_set_sort_order(pref, LOCATION_POI_PREF_SO_ASC); + + ret = location_map_search_poi_by_freeformed_address(map_obj, filter, addr, pref, cb_poi, NULL, &req_id); + GetLocationError(str, ret); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search POI by address. Error[%s]\n", str); + } else { + g_printf("Seach POI by address success, req_id %d\n", req_id); + } + + g_free(addr); + location_poi_filter_free(filter); + location_poi_pref_free(pref); + + }else if(0 == g_strcmp0("11", strOpt)) { + int req_id; + int len = 0; + + g_printf("Input ReqID : "); + len = scanf("%d", &req_id); + + ret = location_map_cancel_poi_request(map_obj, req_id); + GetLocationError(str, ret); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to cancel POI request. Error[%s]\n", str); + } + else + g_printf("location_map_cancel_poi_request, req_id %d\n", req_id); + }else if(0 == g_strcmp0("12", strOpt)) { + g_printf("location_map_request_route\n\n"); + + LocationPosition *origin = location_position_new(0, 37.564263, 126.974676, 0, LOCATION_STATUS_2D_FIX); // Seoul city hall + LocationPosition *destination = location_position_new(0, 37.557120, 126.992410, 0, LOCATION_STATUS_2D_FIX); // NamSan + + GList *waypoint = NULL; + LocationPosition *via_pos = location_position_new(0, 37.560950, 126.986240, 0, LOCATION_STATUS_2D_FIX); // Wangsimli + waypoint = g_list_append (waypoint, (gpointer)via_pos); + + LocationRoutePreference *pref = location_route_pref_new(); + location_route_pref_set_route_type(pref, "FASTEST"); + + LocationRoadElementPenalty *penalty = NULL; + penalty = location_route_element_penalty_new (); + + location_route_element_penalty_set_id(penalty, 100); + location_route_element_penalty_set_direction(penalty, DIR_BOTH); + location_route_element_penalty_set_penalty(penalty, 8); + location_route_element_penalty_set_speed(penalty, 90); + location_route_element_penalty_set_validity_start_time(penalty, 146); + location_route_element_penalty_set_validity_end_time(penalty, 244); + + LocationRouteOptions *options = location_route_options_new (); + if (NULL == options) { + g_printf("\n ERROR: options is NULL \n"); + } + GList *penalty_list = NULL; + penalty_list = g_list_append (penalty_list, penalty); + if (NULL == penalty_list) { + g_printf("\n ERROR: penalty_list is NULL \n"); + } + location_route_options_set_road_element_penalty(options, penalty_list); + location_route_options_set_start_direction(options, 45); + location_route_options_set_walk_time_multiplier(options, (gfloat)10); + location_route_options_set_minimum_change_time(options, 30); + location_route_options_set_transit_type_allowed(options, TRANSIT_TYPE_RAIL_LIGHT, TRUE); + location_route_options_set_maximum_changes(options, 2); + location_route_options_set_departure_time(options, 188); + location_route_options_set_arrival_time(options, 244); + + location_route_pref_set_options(pref, options); + location_route_options_free(options); + + ret = location_map_request_route(map_obj, origin, destination, waypoint, pref, cb_route, NULL, &req_id); + GetLocationError(str, ret); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search route by address. Error[%s]\n", str); + } else { + g_printf("Search Route successfully, req_id %d\n", req_id); + } + }else if(0 == g_strcmp0("12a", strOpt)) { + g_printf("location_map_request_route for a long distance\n"); + + LocationPosition *origin = location_position_new(0, 29.783449,-95.373688, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *destination = location_position_new(0, 39.749962,-104.984665, 0, LOCATION_STATUS_2D_FIX); + + GList *waypoint = NULL; + + LocationRoutePreference *pref = location_route_pref_new(); + location_route_pref_set_route_type(pref, "FASTEST"); + + ret = location_map_request_route(map_obj, origin, destination, waypoint, pref, cb_route, NULL, &req_id); + GetLocationError(str, ret); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to search route by address. Error[%s]\n", str); + } else { + g_printf("Search Route successfully, req_id %d\n", req_id); + } + + + }else if(0 == g_strcmp0("13", strOpt)) { + g_printf("location_map_cancel_route_request\n"); + + int req_id; + int len; + g_printf("Input ReqID : "); + len = scanf("%d", &req_id); + + ret = location_map_cancel_route_request(map_obj, req_id); + GetLocationError(str, ret); + if (ret != LOCATION_ERROR_NONE) { + g_printf("Fail to cancel route request. Error[%s]\n", str); + } + else { + g_printf("location_map_cancel_route_request, req_id %d\n", req_id); + } + + }else if (0 == g_strcmp0 ("14", strOpt)) { + int idx = 0; + for (idx = 0; idx < MAP_SERVICE_TYPE_MAX; idx++) { + g_printf("[%d:%d], ", idx, location_map_is_supported_provider_capability (map_obj, idx)); + } + }else if (0 == g_strcmp0 ("15", strOpt)) { + int idx = 0; + for (idx = 0; idx < MAP_SERVICE_TYPE_MAX; idx++) { + g_printf("[%d:", idx); + print_map_service_keys(map_obj, idx); + g_printf("]\n"); + } + }else if (0 == g_strcmp0 ("16", strOpt)) { + GList *list = location_map_get_supported_providers (map_obj); + if (list) { + g_list_foreach (list, _print_provider, NULL); + g_list_free_full (list, g_free); + } + else { + g_printf("Fail to get supported_providers\n"); + } + }else if (0 == g_strcmp0 ("17", strOpt)) { + gchar *default_provider = location_map_get_default_provider (map_obj); + if (default_provider) { + g_printf("Defaut : [%s]\n", default_provider); + g_free (default_provider); + } + else { + g_printf("Fail to get default provider\n"); + } + }else if (0 == g_strcmp0 ("18", strOpt)) { + g_printf("[0].default [1].decarta [2].osm\n"); + g_printf("Select provider: "); + int opt = PromptInt(); + gboolean ret = FALSE; + switch (opt) + { + case 0: + ret = location_map_set_provider (map_obj, NULL); + break; + case 1: + ret = location_map_set_provider (map_obj, "decarta"); + break; + case 2: + ret = location_map_set_provider (map_obj, "osm"); + break; + default: + break; + } + + if (ret == TRUE) { + g_printf ("Success to set provider [%d]\n", opt); + } + else { + g_printf ("Fail to set provider [%d]\n", opt); + } + }else if (0 == g_strcmp0 ("99", strOpt)) { + if (map_obj) { + g_object_set (map_obj, "provider", NULL, NULL); + } + }else if (0 == g_strcmp0 ("99a", strOpt)) { + if (map_obj) { + g_object_set (map_obj, "provider", "decarta", NULL); + } + }else if (0 == g_strcmp0 ("99b", strOpt)) { + if (map_obj) { + g_object_set (map_obj, "provider", "osm", NULL); + } + }else if(0 == g_strcmp0("q",strOpt) ){ + g_main_loop_quit(g_mainloop); + break; + } + } + g_thread_join(g_main); + g_printf("\n--- Exit LBS Test App ---\n"); + return 1; +} diff --git a/tests/nmea-sample.c b/tests/nmea-sample.c new file mode 100644 index 0000000..53aaf25 --- /dev/null +++ b/tests/nmea-sample.c @@ -0,0 +1,100 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static GMainLoop *loop = NULL; +GSource* nmea_src = NULL; + +static gboolean +exit_program (gpointer data) +{ + g_main_loop_quit (loop); + g_debug ("Quit g_main_loop"); + return FALSE; +} + +static void +cb_service_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + g_debug("cb_service_updated: type(%d) userdata(0x%x)", type, (unsigned int)userdata); + + gchar *nmea_data = NULL; + g_object_get(self, "nmea", &nmea_data, NULL); + if (nmea_data) { + g_debug("SYNC>> Currnet NMEA> nmea_data:\n%s\n", nmea_data); + g_free(nmea_data); + } else g_warning("SYNC>> Current NMEA> failed"); +} + +static void +cb_service_enabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +static void +cb_service_disabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_disabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +int +main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + + location_init (); + + loop = g_main_loop_new (NULL, TRUE); + + loc = location_new (LOCATION_METHOD_GPS); + if (!loc) { + g_debug("location_new failed"); + return -1; + } + + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + g_signal_connect (loc, "service-disabled", G_CALLBACK(cb_service_disabled), loc); + g_signal_connect (loc, "service-updated", G_CALLBACK(cb_service_updated), loc); + + if( LOCATION_ERROR_NONE != location_start (loc) ){ + g_debug("location_start failed"); + return -1; + } + + g_timeout_add_seconds(60, exit_program, NULL); + g_main_loop_run (loop); + + location_stop (loc); + location_free (loc); + + return 0; +} diff --git a/tests/position-sample-gps.c b/tests/position-sample-gps.c new file mode 100644 index 0000000..3e7c698 --- /dev/null +++ b/tests/position-sample-gps.c @@ -0,0 +1,126 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static GMainLoop *loop = NULL; + +static gboolean +exit_program (gpointer data) +{ + g_main_loop_quit (loop); + g_debug ("Quit g_main_loop"); + return FALSE; +} + +static void +cb_service_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + g_debug("cb_service_updated: type(%d) userdata(0x%x)", type, (unsigned int)userdata); + + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + switch (type) { + case POSITION_UPDATED: { + LocationPosition *pos = (LocationPosition*) data; + g_debug ("ASYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + } +} + + +static void +cb_service_enabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); + + LocationObject *loc = (LocationObject*)userdata; + LocationAccuracy *acc = NULL; + LocationPosition *pos = NULL; + + if (LOCATION_ERROR_NONE == location_get_position (loc, &pos, &acc)) { + g_debug ("SYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_position_free(pos); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current position> failed"); +} + +static void +cb_service_disabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_disabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +int +main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + + location_init (); + + loop = g_main_loop_new (NULL, TRUE); + + loc = location_new (LOCATION_METHOD_GPS); + if (!loc) { + g_debug("location_new failed"); + return -1; + } + + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + g_signal_connect (loc, "service-disabled", G_CALLBACK(cb_service_disabled), loc); + g_signal_connect (loc, "service-updated", G_CALLBACK(cb_service_updated), loc); + + if( LOCATION_ERROR_NONE != location_start (loc) ){ + g_debug("location_start failed"); + return -1; + } + + g_timeout_add_seconds(60, exit_program, NULL); + g_main_loop_run (loop); + + location_stop (loc); + + LocationPosition *pos = NULL; + g_object_get(loc, "last-position", &pos, NULL); + if (pos) { + g_debug ("Get property>> last-position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + location_position_free(pos); + } else g_warning("failed to get property> last-position"); + + location_free (loc); + + return 0; +} diff --git a/tests/property-sample.c b/tests/property-sample.c new file mode 100644 index 0000000..ab7fd22 --- /dev/null +++ b/tests/property-sample.c @@ -0,0 +1,119 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static GMainLoop *loop = NULL; + +static gboolean +exit_program (gpointer data) +{ + g_main_loop_quit (loop); + g_debug ("Quit g_main_loop"); + return FALSE; +} + +static void +cb_service_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + g_debug("cb_service_updated: type(%d) userdata(0x%x)", type, (unsigned int)userdata); +} + +static void +cb_service_enabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +static void +cb_service_disabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_disabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +int +main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + + location_init (); + + loop = g_main_loop_new (NULL, TRUE); + + loc = location_new (LOCATION_METHOD_GPS); + if (!loc) { + g_debug("location_new failed"); + return -1; + } + + LocationMethod method = LOCATION_METHOD_NONE; + g_object_get(loc, "method", &method, NULL); + g_debug("Get property>> method:%d", method); + + char* devname = NULL; + g_object_get(loc, "dev-name", &devname, NULL); + if (devname) { + g_debug("Get property>> dev-name: %s", devname); + g_free(devname); + } else g_warning("failed to get property> dev-name"); + + g_object_set(loc, "dev-name", "/dev/test", NULL); + g_object_get(loc, "dev-name", &devname, NULL); + if (devname) { + g_debug("Get property>> dev-name: %s", devname); + g_free(devname); + } else g_warning("failed to set property> dev-name"); + + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + g_signal_connect (loc, "service-disabled", G_CALLBACK(cb_service_disabled), loc); + g_signal_connect (loc, "service-updated", G_CALLBACK(cb_service_updated), loc); + + if( LOCATION_ERROR_NONE != location_start (loc) ){ + g_debug("location_start failed"); + return -1; + } + + g_timeout_add_seconds (60, exit_program, NULL); + g_main_loop_run (loop); + + location_stop (loc); + + LocationPosition *pos = NULL; + g_object_get(loc, "last-position", &pos, NULL); + if (pos) { + g_debug ("Get property>> last-position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + location_position_free(pos); + } else g_warning("failed to get property> last-position"); + + location_free (loc); + + return 0; +} diff --git a/tests/satellite-sample.c b/tests/satellite-sample.c new file mode 100644 index 0000000..8ee56dd --- /dev/null +++ b/tests/satellite-sample.c @@ -0,0 +1,114 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static GMainLoop *loop = NULL; +GSource* sat_src = NULL; + +static gboolean +exit_program (gpointer data) +{ + g_main_loop_quit (loop); + g_debug ("Quit g_main_loop"); + return FALSE; +} + +static void +cb_service_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + g_debug("cb_service_updated: type(%d) userdata(0x%x)", type, (unsigned int)userdata); + + LocationObject *loc = (LocationObject*)userdata; + LocationSatellite *sat = NULL; + int idx = 0; + + g_object_get (loc, "satellite", &sat, NULL); + if (sat) { + g_debug ("SYNC>> Current Sattelite> satellite in view = %d, satellite in used = %d", sat->num_of_sat_inview, sat->num_of_sat_used); + g_debug ("\tinview satellite information = "); + for (idx=0; idxnum_of_sat_inview; idx++) { + guint prn; + gboolean used; + guint elevation; + guint azimuth; + gint snr; + location_satellite_get_satellite_details(sat, idx, &prn, &used, &elevation, &azimuth, &snr); + g_debug ("\t\t[%02d] used: %d, prn: %d, elevation: %d, azimuth: %d, snr: %d", + idx, used, prn, elevation, azimuth, snr); + } + location_satellite_free (sat); + } else g_warning ("SYNC>> Current Sattelite> failed"); +} + +static void +cb_service_enabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +static void +cb_service_disabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_disabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +int +main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + + location_init (); + + loop = g_main_loop_new (NULL, TRUE); + + loc = location_new (LOCATION_METHOD_GPS); + if (!loc) { + g_debug("location_new failed"); + return -1; + } + + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + g_signal_connect (loc, "service-disabled", G_CALLBACK(cb_service_disabled), loc); + g_signal_connect (loc, "service-updated", G_CALLBACK(cb_service_updated), loc); + + if( LOCATION_ERROR_NONE != location_start (loc) ){ + g_debug("location_start failed"); + return -1; + } + + g_timeout_add_seconds(60, exit_program, NULL); + g_main_loop_run (loop); + + location_stop (loc); + location_free (loc); + + return 0; +} diff --git a/tests/velocity-sample.c b/tests/velocity-sample.c new file mode 100644 index 0000000..407fd2b --- /dev/null +++ b/tests/velocity-sample.c @@ -0,0 +1,117 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static GMainLoop *loop = NULL; + +static gboolean +exit_program (gpointer data) +{ + g_main_loop_quit (loop); + g_debug ("Quit g_main_loop"); + return FALSE; +} + +static void +cb_service_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + g_debug("cb_service_updated: type(%d) userdata(0x%x)", type, (unsigned int)userdata); + + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + switch (type) { + case VELOCITY_UPDATED: { + LocationVelocity *vel = (LocationVelocity*) data; + g_debug ("ASYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + } +} + +static void +cb_service_enabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); + + LocationObject *loc = (LocationObject*)userdata; + LocationAccuracy *acc = NULL; + LocationVelocity *vel = NULL; + + if (LOCATION_ERROR_NONE == location_get_velocity (loc, &vel, &acc)) { + g_debug ("SYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_velocity_free(vel); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current velocity> failed"); +} + +static void +cb_service_disabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_disabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +int +main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + + location_init (); + + loop = g_main_loop_new (NULL, TRUE); + + loc = location_new (LOCATION_METHOD_GPS); + if (!loc) { + g_debug("location_new failed"); + return -1; + } + + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + g_signal_connect (loc, "service-disabled", G_CALLBACK(cb_service_disabled), loc); + g_signal_connect (loc, "service-updated", G_CALLBACK(cb_service_updated), loc); + + if( LOCATION_ERROR_NONE != location_start (loc) ){ + g_debug("location_start failed"); + return -1; + } + + g_timeout_add_seconds(60, exit_program, NULL); + g_main_loop_run (loop); + + location_stop (loc); + location_free (loc); + + return 0; +} + diff --git a/tests/wps-test.c b/tests/wps-test.c new file mode 100644 index 0000000..280f833 --- /dev/null +++ b/tests/wps-test.c @@ -0,0 +1,201 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static GMainLoop *loop = NULL; + +static void +cb_service_updated (GObject *self, + guint type, + gpointer data, + gpointer accuracy, + gpointer userdata) +{ + g_debug("cb_service_updated: type(%d) userdata(0x%x)", type, (unsigned int)userdata); + + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + switch (type) { + case POSITION_UPDATED: { + LocationPosition *pos = (LocationPosition*) data; + g_debug ("ASYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + break; + case VELOCITY_UPDATED: { + LocationVelocity *vel = (LocationVelocity*) data; + g_debug ("ASYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + } + break; + default: + g_warning ("ASYNC>> Undefined update type"); + break; + } +} + +static void +cb_service_enabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); + + LocationObject *loc = (LocationObject*)userdata; + LocationAccuracy *acc = NULL; + LocationPosition *pos = NULL; + LocationVelocity *vel = NULL; + + if (LOCATION_ERROR_NONE == location_get_position (loc, &pos, &acc)) { + g_debug ("SYNC>> Current position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_position_free(pos); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current position> failed"); + if (LOCATION_ERROR_NONE == location_get_velocity (loc, &vel, &acc)) { + g_debug ("SYNC>> Current velocity> time: %d, speed: %f, direction:%f, climb:%f", + vel->timestamp, vel->speed, vel->direction, vel->climb); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); + location_velocity_free(vel); + location_accuracy_free(acc); + } else g_warning ("SYNC>> Current velocity> failed"); +} + +static void +cb_service_disabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_disabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +static void +cb_zone_in (GObject *self, + gpointer boundary, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + + g_debug ("ASYNC>> ZoneIn> Current position: time: %d, lat: %f, long: %f, alt: %f", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +static void +cb_zone_out (GObject *self, + gpointer boundary, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + + g_debug ("ASYNC>> ZoneOut> Current position: time: %d, lat: %f, long: %f, alt: %f", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +int +main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + + // If application is executed by AUL, this is not needed. + g_setenv("PKG_NAME", "org.tizen.wps-test", 1); + + location_init (); + + loop = g_main_loop_new (NULL, TRUE); + + loc = location_new (LOCATION_METHOD_WPS); + if (!loc) { + g_debug("location_new failed"); + return -1; + } + + LocationMethod method = LOCATION_METHOD_NONE; + g_object_get(loc, "method", &method, NULL); + g_debug("Get property>> method:%d", method); + + LocationBoundary *bound = NULL; + g_object_get(loc, "boundary", &bound, NULL); + if (bound) { + g_debug("Get property>> boundary> type: %d", bound->type); + location_boundary_free (bound); + } else g_warning("failed to get property> boundary"); + + LocationPosition *rb = location_position_new(0, 37.255, 127.056, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 37.260, 127.050, 0, LOCATION_STATUS_2D_FIX); + bound = location_boundary_new_for_rect(lt, rb); + location_position_free (rb); + location_position_free (lt); + if (bound) { + g_object_set(loc, "boundary", bound, NULL); + location_boundary_free(bound); + } else g_warning("failed to location_boundary_new_for_rect()"); + g_object_get(loc, "boundary", &bound, NULL); + if (bound) { + g_debug("Set property>> boundary> type: %d, (%f,%f),(%f,%f)", + bound->type, + bound->rect.right_bottom->latitude, bound->rect.right_bottom->longitude, + bound->rect.left_top->latitude, bound->rect.left_top->longitude); + location_boundary_free (bound); + } else g_warning("failed to set property> boundary"); + + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + g_signal_connect (loc, "service-disabled", G_CALLBACK(cb_service_disabled), loc); + g_signal_connect (loc, "service-updated", G_CALLBACK(cb_service_updated), loc); + g_signal_connect (loc, "zone-in", G_CALLBACK(cb_zone_in), loc); + g_signal_connect (loc, "zone-out", G_CALLBACK(cb_zone_out), loc); + + if (LOCATION_ERROR_NONE != location_start (loc)) { + g_debug("location_start failed"); + return -1; + } + + g_main_loop_run (loop); + + location_stop (loc); + + LocationPosition *pos = NULL; + g_object_get(loc, "last-position", &pos, NULL); + if (pos) { + g_debug ("Get property>> last-position> time: %d, lat: %f, long: %f, alt: %f, status: %d", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status); + location_position_free(pos); + } else g_warning("failed to get property> last-position"); + + location_free (loc); + + return 0; +} diff --git a/tests/zone-sample.c b/tests/zone-sample.c new file mode 100644 index 0000000..fd6a731 --- /dev/null +++ b/tests/zone-sample.c @@ -0,0 +1,131 @@ +/* + * libslp-location + * + * Copyright (c) 2010-2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Youngae Kang , Minjune Kim + * Genie Kim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +static GMainLoop *loop = NULL; + +static gboolean +exit_program (gpointer data) +{ + g_main_loop_quit (loop); + g_debug ("Quit g_main_loop"); + return FALSE; +} + +static void +cb_service_enabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_enabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +static void +cb_service_disabled (GObject *self, + guint status, + gpointer userdata) +{ + g_debug("cb_service_disabled: status(%d) userdata(0x%x)", status, (unsigned int)userdata); +} + +static void +cb_zone_in (GObject *self, + gpointer boundary, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + + g_debug ("ASYNC>> ZoneIn> Current position: time: %d, lat: %f, long: %f, alt: %f", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +static void +cb_zone_out (GObject *self, + gpointer boundary, + gpointer position, + gpointer accuracy) +{ + LocationPosition *pos = (LocationPosition*) position; + LocationAccuracy *acc = (LocationAccuracy*) accuracy; + + g_debug ("ASYNC>> ZoneOut> Current position: time: %d, lat: %f, long: %f, alt: %f", + pos->timestamp, pos->latitude, pos->longitude, pos->altitude); + g_debug ("\tAccuracy level %d (%.0f meters %.0f meters)", + acc->level, acc->horizontal_accuracy, acc->vertical_accuracy); +} + +int +main (int argc, char *argv[]) +{ + LocationObject *loc = NULL; + + location_init (); + + loop = g_main_loop_new (NULL, TRUE); + + loc = location_new (LOCATION_METHOD_GPS); + if (!loc) { + g_debug("location_new failed"); + return -1; + } + + LocationPosition *rb = location_position_new(0, 37.258, 127.056, 0, LOCATION_STATUS_2D_FIX); + LocationPosition *lt = location_position_new(0, 37.260, 127.054, 0, LOCATION_STATUS_2D_FIX); + LocationBoundary *bound = location_boundary_new_for_rect(lt, rb); + location_position_free (rb); + location_position_free (lt); + if (bound) { + g_object_set(loc, "boundary", bound, NULL); + location_boundary_free(bound); + } else g_warning("failed to location_boundary_new_for_rect()"); + g_object_get(loc, "boundary", &bound, NULL); + if (bound) { + g_debug("Set property>> boundary> type: %d, (%f,%f),(%f,%f)", + bound->type, + bound->rect.right_bottom->latitude, bound->rect.right_bottom->longitude, + bound->rect.left_top->latitude, bound->rect.left_top->longitude); + location_boundary_free (bound); + } else g_warning("failed to set property> boundary"); + + g_signal_connect (loc, "service-enabled", G_CALLBACK(cb_service_enabled), loc); + g_signal_connect (loc, "service-disabled", G_CALLBACK(cb_service_disabled), loc); + g_signal_connect (loc, "zone-in", G_CALLBACK(cb_zone_in), loc); + g_signal_connect (loc, "zone-out", G_CALLBACK(cb_zone_out), loc); + + if( LOCATION_ERROR_NONE != location_start (loc) ){ + g_debug("location_start failed"); + return -1; + } + + g_timeout_add_seconds (60, exit_program, NULL); + g_main_loop_run (loop); + + location_stop (loc); + location_free (loc); + + return 0; +} -- 2.7.4