Git init
[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 int _convert_error_code(int code, char* func_name)
43 {
44         int ret;
45         char* msg = "GEOCODER_ERROR_NONE";
46         switch(code)
47         {
48                 case LOCATION_ERROR_NONE:
49                         ret = GEOCODER_ERROR_NONE;
50                         msg = "GEOCODER_ERROR_NONE";
51                         break;
52                 case LOCATION_ERROR_NETWORK_FAILED:
53                         ret = GEOCODER_ERROR_NETWORK_FAILED;
54                         msg = "GEOCODER_ERROR_NETWORK_FAILED";
55                         break;
56                 case LOCATION_ERROR_PARAMETER:
57                         ret = GEOCODER_ERROR_INVALID_PARAMETER;
58                         msg = "GEOCODER_ERROR_INVALID_PARAMETER";
59                         break;
60                 case LOCATION_ERROR_NOT_ALLOWED:
61                 case LOCATION_ERROR_NOT_AVAILABLE:
62                 case LOCATION_ERROR_CONFIGURATION:
63                 case LOCATION_ERROR_UNKNOWN:
64                 default:
65                         msg = "GEOCODER_ERROR_SERVICE_NOT_AVAILABLE";
66                         ret = GEOCODER_ERROR_SERVICE_NOT_AVAILABLE;     
67         }
68         LOGE("[%s] %s(0x%08x) : core fw error(0x%x)",func_name,msg, ret, code);
69         return ret;     
70 }
71
72 static void cb_address_from_position (LocationError error, LocationAddress *addr, LocationAccuracy *acc, gpointer userdata)
73 {
74         geocoder_s * handle = (geocoder_s*)userdata;
75         if(handle->user_cb[_GEOCODER_CB_ADDRESS_FROM_POSITION])
76         {
77                 if(error != LOCATION_ERROR_NONE || addr == NULL)
78                 {
79                         _convert_error_code(error,(char*)__FUNCTION__);
80                         ((geocoder_get_address_cb)handle->user_cb[_GEOCODER_CB_ADDRESS_FROM_POSITION])(NULL,  NULL,  NULL,  NULL,  NULL,  NULL,  NULL, handle->user_data[_GEOCODER_CB_ADDRESS_FROM_POSITION]);                  
81                 }
82                 else
83                 {
84                          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);
85                         ((geocoder_get_address_cb)handle->user_cb[_GEOCODER_CB_ADDRESS_FROM_POSITION])(addr->building_number, addr->postal_code, addr->street, addr->city, addr->district, addr->state, addr->country_code, handle->user_data[_GEOCODER_CB_ADDRESS_FROM_POSITION]);
86                 }
87         }
88         else
89         {
90                 LOGI("[%s] callback is NULL )",__FUNCTION__);
91         }
92 }
93
94 static void cb_position_from_address (LocationError error, LocationPosition *pos, LocationAccuracy *acc, gpointer userdata)
95 {
96         geocoder_s * handle = (geocoder_s*)userdata;
97         if(handle->user_cb[_GEOCODER_CB_POSITION_FROM_ADDRESS])
98         {
99                 if(error != LOCATION_ERROR_NONE || pos == NULL)
100                 {
101                         _convert_error_code(error,(char*)__FUNCTION__);
102                 }
103                 else
104                 {
105                         int i;
106                         int temp_max = 1;
107                         for( i=0 ; i < temp_max ; i++)
108                         {
109                                  LOGI("[%s] Position[%d] - time: %d, lat: %f, long: %f, alt: %f, status: %d", __FUNCTION__, (i+1), pos->timestamp, pos->latitude, pos->longitude, pos->altitude, pos->status);
110                                 if ( ((geocoder_get_position_cb)handle->user_cb[_GEOCODER_CB_POSITION_FROM_ADDRESS])(pos->latitude, pos->longitude, handle->user_data[_GEOCODER_CB_POSITION_FROM_ADDRESS]) != TRUE )
111                                 {
112                                          LOGI("[%s] User quit the loop [count : %d]",  __FUNCTION__, (i+1));
113                                         break;
114                                 }
115                         }
116                 }
117         }
118         else
119         {
120                 LOGI("[%s] callback is NULL )",__FUNCTION__);
121         }
122 }
123
124 /*
125 * Public Implementation
126 */
127 int     geocoder_create(geocoder_h* geocoder)
128 {
129         GEOCODER_NULL_ARG_CHECK(geocoder);
130         if(location_init()!=LOCATION_ERROR_NONE)
131         {
132                 LOGE("[%s] GEOCODER_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : fail to location_init", __FUNCTION__, GEOCODER_ERROR_SERVICE_NOT_AVAILABLE);
133                 return GEOCODER_ERROR_SERVICE_NOT_AVAILABLE;
134         }
135
136         geocoder_s *handle = (geocoder_s*)malloc(sizeof(geocoder_s));
137         if(handle==NULL)
138         {
139                 LOGE("[%s] OUT_OF_MEMORY(0x%08x)", __FUNCTION__, GEOCODER_ERROR_OUT_OF_MEMORY);
140                 return GEOCODER_ERROR_OUT_OF_MEMORY;
141         }
142
143         memset(handle, 0 , sizeof(geocoder_s));
144         
145         handle->object = location_new(LOCATION_METHOD_HYBRID);
146         if(handle->object  == NULL)
147         {
148                 free(handle);
149                 LOGE("[%s] GEOCODER_ERROR_SERVICE_NOT_AVAILABLE(0x%08x) : fail to location_new", __FUNCTION__, GEOCODER_ERROR_SERVICE_NOT_AVAILABLE);
150                 return GEOCODER_ERROR_SERVICE_NOT_AVAILABLE;
151         }
152
153         *geocoder = (geocoder_h)handle;
154         return GEOCODER_ERROR_NONE;
155 }
156
157 int     geocoder_destroy(geocoder_h geocoder)
158 {
159         GEOCODER_NULL_ARG_CHECK(geocoder);
160         geocoder_s *handle = (geocoder_s*)geocoder;
161
162         int ret = location_free(handle->object);
163         if(ret!=GEOCODER_ERROR_NONE)
164         {
165                 return _convert_error_code(ret,(char*)__FUNCTION__);
166         }
167         free(handle);
168         return GEOCODER_ERROR_NONE;
169 }
170
171 int     geocoder_get_address_from_position(geocoder_h geocoder, double latitude, double longitude, geocoder_get_address_cb callback, void *user_data)
172 {
173         GEOCODER_NULL_ARG_CHECK(geocoder);
174         GEOCODER_NULL_ARG_CHECK(callback);
175         GEOCODER_CHECK_CONDITION(latitude>=-90 && latitude<=90 ,GEOCODER_ERROR_INVALID_PARAMETER,"GEOCODER_ERROR_INVALID_PARAMETER");
176         GEOCODER_CHECK_CONDITION(longitude>=-180 && longitude<=180,GEOCODER_ERROR_INVALID_PARAMETER,"GEOCODER_ERROR_INVALID_PARAMETER");
177         
178         geocoder_s *handle = (geocoder_s*)geocoder;
179         int ret;
180         LocationPosition *pos = NULL;
181         pos = location_position_new (0, latitude, longitude, 0, LOCATION_STATUS_2D_FIX);
182
183         handle->user_cb[_GEOCODER_CB_ADDRESS_FROM_POSITION] = callback;
184         handle->user_data[_GEOCODER_CB_ADDRESS_FROM_POSITION] = user_data;
185         
186         ret = location_get_address_from_position_async(handle->object, pos, cb_address_from_position, handle);
187         if( ret != LOCATION_ERROR_NONE)
188         {
189                 return _convert_error_code(ret,(char*)__FUNCTION__);
190         }
191         location_position_free(pos);
192         return GEOCODER_ERROR_NONE;
193 }
194
195 int geocoder_get_address_from_position_sync(geocoder_h geocoder, double latitude, double longitude, char **building_number, char **postal_code, char **street, char **city, char **district, char **state, char **country_code)
196 {
197         GEOCODER_NULL_ARG_CHECK(geocoder);
198         GEOCODER_CHECK_CONDITION(latitude>=-90 && latitude<=90 ,GEOCODER_ERROR_INVALID_PARAMETER,"GEOCODER_ERROR_INVALID_PARAMETER");
199         GEOCODER_CHECK_CONDITION(longitude>=-180 && longitude<=180,GEOCODER_ERROR_INVALID_PARAMETER,"GEOCODER_ERROR_INVALID_PARAMETER");
200         
201         geocoder_s *handle = (geocoder_s*)geocoder;
202         int ret;
203         LocationAddress *addr = NULL;
204         LocationPosition *pos = NULL;
205         LocationAccuracy *acc = NULL;
206
207         pos = location_position_new (0, latitude, longitude, 0, LOCATION_STATUS_2D_FIX);
208         ret = location_get_address_from_position(handle->object, pos, &addr, &acc);
209         if( ret != LOCATION_ERROR_NONE)
210         {
211                 return _convert_error_code(ret,(char*)__FUNCTION__);
212         }
213
214         if(building_number)
215         {
216                 *building_number = NULL;
217                 if(addr->building_number)
218                         *building_number = strdup(addr->building_number);
219         }
220
221         if(postal_code)
222         {
223                 *postal_code = NULL;
224                 if(addr->postal_code)
225                         *postal_code = strdup(addr->postal_code);
226         }
227
228         if(street)
229         {
230                 *street = NULL;
231                 if(addr->street)
232                         *street = strdup(addr->street);
233         }
234
235         if(city)
236         {
237                 *city = NULL;
238                 if(addr->city)
239                         *city = strdup(addr->city);
240         }
241
242         if(state)
243         {
244                 *state = NULL;
245                 if(addr->state)
246                         *state = strdup(addr->state);
247         }
248
249         if(district)
250         {
251                 *district = NULL;
252                 if(addr->district)
253                         *district = strdup(addr->district);
254         }
255
256         if(country_code)
257         {
258                 *country_code = NULL;
259                 if(addr->country_code)
260                         *country_code = strdup(addr->country_code);
261         }
262         
263         location_address_free(addr);
264         location_position_free(pos);
265         location_accuracy_free(acc);
266         return GEOCODER_ERROR_NONE;
267 }
268
269
270
271 int      geocoder_foreach_positions_from_address(geocoder_h geocoder,const char* address, geocoder_get_position_cb callback, void *user_data)
272 {
273         GEOCODER_NULL_ARG_CHECK(geocoder);
274         GEOCODER_NULL_ARG_CHECK(address);
275         GEOCODER_NULL_ARG_CHECK(callback);
276         geocoder_s *handle = (geocoder_s*)geocoder;
277
278         char* addr_str = g_strdup(address);
279         handle->user_cb[_GEOCODER_CB_POSITION_FROM_ADDRESS] = callback;
280         handle->user_data[_GEOCODER_CB_POSITION_FROM_ADDRESS] = user_data;
281
282         int ret;        
283         ret = location_get_position_from_freeformed_address_async(handle->object, addr_str,cb_position_from_address, handle);
284         if( ret != LOCATION_ERROR_NONE)
285         {
286                 g_free(addr_str);       
287                 return _convert_error_code(ret,(char*)__FUNCTION__);
288         }
289         return GEOCODER_ERROR_NONE;
290 }
291
292 int      geocoder_foreach_positions_from_address_sync(geocoder_h geocoder,const char* address, geocoder_get_position_cb callback, void *user_data)
293 {
294         GEOCODER_NULL_ARG_CHECK(geocoder);
295         GEOCODER_NULL_ARG_CHECK(address);
296         GEOCODER_NULL_ARG_CHECK(callback);
297         geocoder_s *handle = (geocoder_s*)geocoder;
298
299         int ret;
300         LocationPosition *pos = NULL;
301         LocationAccuracy *acc = NULL;
302         char* addr_str = g_strdup(address);
303                          
304         ret = location_get_position_from_freeformed_address(handle->object, addr_str, &pos, &acc);
305         if( ret != LOCATION_ERROR_NONE)
306         {
307                 g_free(addr_str);       
308                 return _convert_error_code(ret,(char*)__FUNCTION__);
309         }
310                  
311         int i;
312         int temp_max = 1;
313         for( i=0 ; i < temp_max ; i++)
314         {
315                 if ( callback(pos->latitude, pos->longitude, user_data) != TRUE )
316                 {
317                          LOGI("[%s] User quit the loop [count : %d]",  __FUNCTION__, (i+1));
318                         break;
319                 }
320         }
321         g_free(addr_str);
322         location_position_free(pos);
323         location_accuracy_free(acc);
324         return GEOCODER_ERROR_NONE;
325 }