Release Tizen2.0 beta
[framework/api/geocoder.git] / src / geocoder.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License. 
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <geocoder_private.h>
21 #include <dlog.h>
22
23 #ifdef LOG_TAG
24 #undef LOG_TAG
25 #endif
26 #define LOG_TAG "TIZEN_N_GEOCODER"
27
28 /*
29 * Internal Macros
30 */
31 #define GEOCODER_CHECK_CONDITION(condition,error,msg)   \
32                 if(condition) {} else \
33                 { LOGE("[%s] %s(0x%08x)",__FUNCTION__, msg,error); return error;}; \
34
35 #define GEOCODER_NULL_ARG_CHECK(arg)    \
36         GEOCODER_CHECK_CONDITION(arg != NULL,GEOCODER_ERROR_INVALID_PARAMETER,"GEOCODER_ERROR_INVALID_PARAMETER")
37
38 /*
39 * Internal Implementation
40 */
41
42 typedef struct {
43         void *data;
44         geocoder_get_address_cb callback;
45 }__addr_callback_data;
46
47 typedef struct {
48         void *data;
49         geocoder_get_position_cb callback;
50 }__pos_callback_data;
51
52 static int __convert_error_code(int code, char* func_name)
53 {
54         int ret;
55         char* msg = "GEOCODER_ERROR_NONE";
56         switch(code)
57         {
58                 case LOCATION_ERROR_NONE:
59                         ret = GEOCODER_ERROR_NONE;
60                         msg = "GEOCODER_ERROR_NONE";
61                         break;
62                 case LOCATION_ERROR_NETWORK_FAILED:
63                 case LOCATION_ERROR_NETWORK_NOT_CONNECTED:
64                         ret = GEOCODER_ERROR_NETWORK_FAILED;
65                         msg = "GEOCODER_ERROR_NETWORK_FAILED";
66                         break;
67                 case LOCATION_ERROR_PARAMETER:
68                         ret = GEOCODER_ERROR_INVALID_PARAMETER;
69                         msg = "GEOCODER_ERROR_INVALID_PARAMETER";
70                         break;
71                 case LOCATION_ERROR_NOT_FOUND:
72                         ret = GEOCODER_ERROR_NOT_FOUND;
73                         msg = "GEOCODER_ERROR_NOT_FOUND";
74                         break;
75                 case LOCATION_ERROR_NOT_ALLOWED:
76                 case LOCATION_ERROR_NOT_AVAILABLE:
77                 case LOCATION_ERROR_CONFIGURATION:
78                 case LOCATION_ERROR_UNKNOWN:
79                 default:
80                         msg = "GEOCODER_ERROR_SERVICE_NOT_AVAILABLE";
81                         ret = GEOCODER_ERROR_SERVICE_NOT_AVAILABLE;     
82         }
83         LOGE("[%s] %s(0x%08x) : core fw error(0x%x)",func_name,msg, ret, code);
84         return ret;     
85 }
86
87 static void __cb_address_from_position (LocationError error, LocationAddress *addr, LocationAccuracy *acc, gpointer userdata)
88 {
89         __addr_callback_data * callback = (__addr_callback_data*)userdata;
90         if( callback == NULL || callback->callback == NULL)
91         {
92                 LOGI("[%s] callback is NULL )",__FUNCTION__);
93                 return ;
94         }
95
96         if(error != LOCATION_ERROR_NONE || addr == NULL)
97         {
98                 callback->callback(__convert_error_code(error,(char*)__FUNCTION__), NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL, callback->data);
99         }
100         else
101         {
102                 LOGI("[%s] Address - building number: %s, postal code: %s, street: %s, city: %s, district:  %s, state: %s, country code: %s", __FUNCTION__ , addr->building_number, addr->postal_code, addr->street, addr->city, addr->district, addr->state, addr->country_code);
103                 callback->callback(GEOCODER_ERROR_NONE, addr->building_number, addr->postal_code, addr->street, addr->city, addr->district, addr->state, addr->country_code, callback->data);
104         }
105         free(callback);
106 }
107
108 static void __cb_position_from_address (LocationError error, GList *position_list, GList *accuracy_list, gpointer userdata)
109 {
110         __pos_callback_data * callback = (__pos_callback_data*)userdata;
111         if( callback == NULL || callback->callback == NULL)
112         {
113                 LOGI("[%s] callback is NULL )",__FUNCTION__);
114                 return ;
115         }
116
117         if(error != LOCATION_ERROR_NONE || position_list == NULL || position_list->data ==NULL || accuracy_list==NULL )
118         {
119                 callback->callback(__convert_error_code(error,(char*)__FUNCTION__), 0, 0, callback->data);
120         }
121         else
122         {
123                 while(position_list)
124                 {
125                         LocationPosition *pos = position_list->data;
126                         if ( callback->callback(GEOCODER_ERROR_NONE, pos->latitude, pos->longitude, callback->data) != TRUE )
127                         {
128                                 LOGI("[%s] User quit the loop ",  __FUNCTION__);
129                                 break;
130                         }
131                         position_list = g_list_next(position_list);
132                 }
133         }
134         free(callback);
135 }
136
137 /*
138 * Public Implementation
139 */
140 int     geocoder_create(geocoder_h* geocoder)
141 {
142         GEOCODER_NULL_ARG_CHECK(geocoder);
143         if(location_init()!=LOCATION_ERROR_NONE)
144         {
145                 LOGE("[%s] GEOCODER_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : fail to location_init", __FUNCTION__, GEOCODER_ERROR_SERVICE_NOT_AVAILABLE);
146                 return GEOCODER_ERROR_SERVICE_NOT_AVAILABLE;
147         }
148
149         geocoder_s *handle = (geocoder_s*)malloc(sizeof(geocoder_s));
150         if(handle==NULL)
151         {
152                 LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, GEOCODER_ERROR_OUT_OF_MEMORY);
153                 return GEOCODER_ERROR_OUT_OF_MEMORY;
154         }
155
156         memset(handle, 0 , sizeof(geocoder_s));
157         
158         handle->object = location_map_new(NULL);
159         if(handle->object  == NULL)
160         {
161                 free(handle);
162                 LOGE("[%s] GEOCODER_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : fail to location_map_new", __FUNCTION__, GEOCODER_ERROR_SERVICE_NOT_AVAILABLE);
163                 return GEOCODER_ERROR_SERVICE_NOT_AVAILABLE;
164         }
165
166         *geocoder = (geocoder_h)handle;
167         return GEOCODER_ERROR_NONE;
168 }
169
170 int     geocoder_destroy(geocoder_h geocoder)
171 {
172         GEOCODER_NULL_ARG_CHECK(geocoder);
173         geocoder_s *handle = (geocoder_s*)geocoder;
174
175         int ret = location_map_free(handle->object);
176         if(ret!=GEOCODER_ERROR_NONE)
177         {
178                 return __convert_error_code(ret,(char*)__FUNCTION__);
179         }
180         free(handle);
181         return GEOCODER_ERROR_NONE;
182 }
183
184 int     geocoder_get_address_from_position(geocoder_h geocoder, double latitude, double longitude, geocoder_get_address_cb callback, void *user_data)
185 {
186         GEOCODER_NULL_ARG_CHECK(geocoder);
187         GEOCODER_NULL_ARG_CHECK(callback);
188         GEOCODER_CHECK_CONDITION(latitude>=-90 && latitude<=90 ,GEOCODER_ERROR_INVALID_PARAMETER,"GEOCODER_ERROR_INVALID_PARAMETER");
189         GEOCODER_CHECK_CONDITION(longitude>=-180 && longitude<=180,GEOCODER_ERROR_INVALID_PARAMETER,"GEOCODER_ERROR_INVALID_PARAMETER");
190         
191         geocoder_s *handle = (geocoder_s*)geocoder;
192         int ret;
193         LocationPosition *pos = NULL;
194         pos = location_position_new (0, latitude, longitude, 0, LOCATION_STATUS_2D_FIX);
195
196         __addr_callback_data * calldata = (__addr_callback_data *)malloc(sizeof(__addr_callback_data));
197         if( calldata == NULL)
198         {
199                 LOGE("[%s] GEOCODER_ERROR_OUT_OF_MEMORY(0x%08x) : fail to create callback data", __FUNCTION__, GEOCODER_ERROR_OUT_OF_MEMORY);
200                 return GEOCODER_ERROR_OUT_OF_MEMORY;
201         }
202         calldata->callback = callback;
203         calldata->data = user_data;
204         
205         ret = location_map_get_address_from_position_async(handle->object, pos, __cb_address_from_position, calldata);
206         location_position_free(pos);
207         if( ret != LOCATION_ERROR_NONE)
208         {
209                 free(calldata);
210                 return __convert_error_code(ret,(char*)__FUNCTION__);
211         }
212         return GEOCODER_ERROR_NONE;
213 }
214
215 int      geocoder_foreach_positions_from_address(geocoder_h geocoder,const char* address, geocoder_get_position_cb callback, void *user_data)
216 {
217         GEOCODER_NULL_ARG_CHECK(geocoder);
218         GEOCODER_NULL_ARG_CHECK(address);
219         GEOCODER_NULL_ARG_CHECK(callback);
220         geocoder_s *handle = (geocoder_s*)geocoder;
221
222         char* addr_str = g_strdup(address);
223
224         __pos_callback_data * calldata = (__pos_callback_data *)malloc(sizeof(__pos_callback_data));
225         if( calldata == NULL)
226         {
227                 LOGE("[%s] GEOCODER_ERROR_OUT_OF_MEMORY(0x%08x) : fail to create callback data", __FUNCTION__, GEOCODER_ERROR_OUT_OF_MEMORY);
228                 return GEOCODER_ERROR_OUT_OF_MEMORY;
229         }
230         calldata->callback = callback;
231         calldata->data = user_data;
232
233         int ret;        
234         ret = location_map_get_position_from_freeformed_address_async(handle->object, addr_str,__cb_position_from_address, calldata);
235         g_free(addr_str);
236         if( ret != LOCATION_ERROR_NONE)
237         {
238                 return __convert_error_code(ret,(char*)__FUNCTION__);
239         }
240         return GEOCODER_ERROR_NONE;
241 }