summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mapquest/mapquest_api.c75
-rw-r--r--src/mapquest/mapquest_api.h68
-rw-r--r--src/mapquest/mapquest_debug.h38
-rw-r--r--src/mapquest/mapquest_geocode.c77
-rw-r--r--src/mapquest/mapquest_geocode.h26
-rw-r--r--src/mapquest/mapquest_jsonparser.c1124
-rw-r--r--src/mapquest/mapquest_jsonparser.h24
-rw-r--r--src/mapquest/mapquest_place.c87
-rw-r--r--src/mapquest/mapquest_place.h25
-rw-r--r--src/mapquest/mapquest_queue.c1263
-rw-r--r--src/mapquest/mapquest_queue.h72
-rw-r--r--src/mapquest/mapquest_restcurl.c671
-rw-r--r--src/mapquest/mapquest_restcurl.h34
-rw-r--r--src/mapquest/mapquest_revgeocode.c47
-rw-r--r--src/mapquest/mapquest_revgeocode.h25
-rw-r--r--src/mapquest/mapquest_route.c106
-rw-r--r--src/mapquest/mapquest_route.h25
-rw-r--r--src/mapquest/mapquest_server_private.h102
-rw-r--r--src/mapquest/mapquest_types.h193
-rw-r--r--src/mapquest/mapquest_util.c45
-rw-r--r--src/mapquest/mapquest_util.h24
-rw-r--r--src/mapquest_plugin.c1394
22 files changed, 5545 insertions, 0 deletions
diff --git a/src/mapquest/mapquest_api.c b/src/mapquest/mapquest_api.c
new file mode 100644
index 0000000..88f1da9
--- /dev/null
+++ b/src/mapquest/mapquest_api.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include "mapquest_api.h"
+#include "mapquest_server_private.h"
+#include "mapquest_queue.h"
+#include "mapquest_debug.h"
+
+EXPORT_API int mapquest_init()
+{
+ int ret = mapquest_init_queue();
+
+ return ret;
+}
+
+EXPORT_API int mapquest_shutdown()
+{
+ int ret = mapquest_deinit_queue();
+
+ return ret;
+}
+
+EXPORT_API int mapquest_geocode(mapquest_geocode_req_s *req_details, mapquest_geocode_cb callback, int request_id, void *user_data)
+{
+ int ret = MAPQUEST_ERROR_NONE;
+ ret = start_geocode_service(req_details, callback, request_id, user_data);
+
+ return ret;
+}
+
+EXPORT_API int mapquest_cancel_request(int request_id)
+{
+ int ret = remove_from_request_list(request_id);
+
+ return ret;
+}
+
+EXPORT_API int mapquest_reverse_geocode(mapquest_revgeocode_req_s *req_details, mapquest_reverse_geocode_cb callback, int request_id, void *user_data)
+{
+ int ret = MAPQUEST_ERROR_NONE;
+ ret = start_reversegeocode_service(req_details, callback, request_id, user_data);
+
+ return ret;
+}
+
+EXPORT_API int mapquest_search_place(mapquest_search_req_s *req_details, mapquest_place_search_cb callback, int request_id, void *user_data)
+{
+ int ret = MAPQUEST_ERROR_NONE;
+ ret = start_places_service(req_details, callback, request_id, user_data);
+
+ return ret;
+}
+
+EXPORT_API int mapquest_start_route(mapquest_route_req_s *req_details, mapquest_route_cb callback, int request_id, void *user_data)
+{
+ int ret = MAPQUEST_ERROR_NONE;
+ ret = start_route_service(req_details, callback, request_id, user_data);
+
+ return ret;
+}
diff --git a/src/mapquest/mapquest_api.h b/src/mapquest/mapquest_api.h
new file mode 100644
index 0000000..479e306
--- /dev/null
+++ b/src/mapquest/mapquest_api.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_API_H_
+#define _MAPQUEST_API_H_
+
+#include "mapquest_types.h"
+#include <tizen_type.h>
+
+/**
+ * @ingroup MAPQUEST_ENGINE_MODULE
+ * @defgroup MAPQUEST_ENGINE_API_MODULE
+ *
+ * @file mapquest_api.h
+ * @brief This file contains the MapQuest engine API's that should be called by the plugin
+ *
+ * @addtogroup MAPQUEST_ENGINE_MODULE
+ * @{
+ * @brief This provides APIs related to MapQuest engine.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /* Callbacks */
+typedef void (*mapquest_geocode_cb) (mapquest_error_e result, int request_id, GList *co_ordinates, void *user_data);
+
+typedef void (*mapquest_reverse_geocode_cb) (mapquest_error_e result, int request_id, mapquest_address_resp_s *address, void *user_data);
+
+typedef void (*mapquest_place_search_cb) (mapquest_error_e result, int request_id, GList *places, void *user_data);
+
+typedef void (*mapquest_route_cb) (mapquest_error_e result, int request_id, mapquest_route_resp_s *route_info, void *user_data);
+
+typedef void (*mapquest_maptile_cb) (mapquest_error_e result, int request_id, char *buffer, void *user_data);
+
+int mapquest_init();
+
+int mapquest_shutdown();
+
+int mapquest_geocode(mapquest_geocode_req_s *req_details, mapquest_geocode_cb callback, int request_id, void *user_data);
+
+int mapquest_cancel_request(int request_id);
+
+int mapquest_reverse_geocode(mapquest_revgeocode_req_s *req_details, mapquest_reverse_geocode_cb callback, int request_id, void *user_data);
+
+int mapquest_search_place(mapquest_search_req_s *req_details, mapquest_place_search_cb callback, int request_id, void *user_data);
+
+int mapquest_start_route(mapquest_route_req_s *req_details, mapquest_route_cb callback, int request_id, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MAPQUEST_API_H_ */
diff --git a/src/mapquest/mapquest_debug.h b/src/mapquest/mapquest_debug.h
new file mode 100644
index 0000000..8bdec35
--- /dev/null
+++ b/src/mapquest/mapquest_debug.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_DEBUG_H_
+#define _MAPQUEST_DEBUG_H_
+
+#include <dlog.h>
+#include <string.h>
+#include <assert.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define EXPORT_API __attribute__((visibility("default")))
+
+#define LOG_TAG "MAPQUEST_ENGINE"
+
+/* normal log */
+#define MAP_DEBUG(fmt, args...) LOGD(fmt, ##args)
+#define MAP_ENTER() LOGD(WCOLOR_GREEN "BEGIN >>>>" WCOLOR_END)
+#define MAP_LEAVE() LOGD(WCOLOR_GREEN "END <<<<" WCOLOR_END)
+
+#endif /* _MAPQUEST_DEBUG_H_ */
diff --git a/src/mapquest/mapquest_geocode.c b/src/mapquest/mapquest_geocode.c
new file mode 100644
index 0000000..553dce2
--- /dev/null
+++ b/src/mapquest/mapquest_geocode.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <stdio.h>
+#include <glib.h>
+#include <pthread.h>
+#include "mapquest_geocode.h"
+#include "mapquest_types.h"
+#include "mapquest_server_private.h"
+#include "mapquest_debug.h"
+#include "mapquest_queue.h"
+#include "mapquest_restcurl.h"
+
+#define GEOCODE_URL "https://open.mapquestapi.com/geocoding/v1/address?key=%s&inFormat=kvp&outFormat=json"
+
+int query_geocode_within_bounds(gchar *maps_key, char *address, coords_s top_left, coords_s bottom_right, int num_results, gpointer user_data)
+{
+ char url[1024];
+ char tmpStr[512];
+
+ if (maps_key != NULL)
+ snprintf(tmpStr, sizeof(tmpStr), GEOCODE_URL, maps_key);
+ else
+ snprintf(tmpStr, sizeof(tmpStr), GEOCODE_URL, "null");
+
+ strcpy(url, tmpStr);
+
+ snprintf(tmpStr, sizeof(tmpStr), "&boundingBox=%f,%f,%f,%f", top_left.latitude, top_left.longitude, bottom_right.latitude, bottom_right.longitude);
+ strcat(url, tmpStr);
+
+ snprintf(tmpStr, sizeof(tmpStr), "&maxResults=%d", num_results);
+ strcat(url, tmpStr);
+
+ snprintf(tmpStr, sizeof(tmpStr), "&location=%s", address);
+ strcat(url, tmpStr);
+
+ add_handle(url, REQ_TYPE_GEOCODE, user_data);
+
+ return 0;
+}
+
+int query_geocode(gchar *maps_key, char *address, int num_results, gpointer user_data)
+{
+ MAP_DEBUG("geocode address : %s", address);
+ char url[1024];
+ char tmpStr[512];
+
+ if (maps_key != NULL)
+ snprintf(tmpStr, sizeof(tmpStr), GEOCODE_URL, maps_key);
+ else
+ snprintf(tmpStr, sizeof(tmpStr), GEOCODE_URL, "null");
+
+ strcpy(url, tmpStr);
+
+ snprintf(tmpStr, sizeof(tmpStr), "&maxResults=%d", num_results);
+ strcat(url, tmpStr);
+
+ snprintf(tmpStr, sizeof(tmpStr), "&location=%s", address);
+ strcat(url, tmpStr);
+
+ add_handle(url, REQ_TYPE_GEOCODE, user_data);
+
+ return 0;
+}
diff --git a/src/mapquest/mapquest_geocode.h b/src/mapquest/mapquest_geocode.h
new file mode 100644
index 0000000..85c689e
--- /dev/null
+++ b/src/mapquest/mapquest_geocode.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_GEOCODE_H_
+#define _MAPQUEST_GEOCODE_H_
+
+#include "mapquest_api.h"
+#include "mapquest_types.h"
+
+int query_geocode(gchar *maps_key, char *address, int num_results, gpointer user_data);
+int query_geocode_within_bounds(gchar *maps_key, char *address, coords_s top_left, coords_s bottom_right, int num_results, gpointer user_data);
+
+#endif /* MAPQUEST_GEOCODE_H_ */
diff --git a/src/mapquest/mapquest_jsonparser.c b/src/mapquest/mapquest_jsonparser.c
new file mode 100644
index 0000000..e549a5c
--- /dev/null
+++ b/src/mapquest/mapquest_jsonparser.c
@@ -0,0 +1,1124 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <stdlib.h>
+#include <json-glib/json-glib.h>
+#include "mapquest_jsonparser.h"
+#include "mapquest_queue.h"
+#include "mapquest_debug.h"
+
+#define ROUTE_UNIT_CONVERSION_MILE_TO_M(x) (1609.34 * (x))
+#define ROUTE_UNIT_CONVERSION_MILE_TO_KM(x) (1.60934 * (x))
+#define ROUTE_UNIT_CONVERSION_MILE_TO_FT(x) (5280 * (x))
+#define ROUTE_UNIT_CONVERSION_MILE_TO_YD(x) (1760 * (x))
+
+static route_unit __route_unit = ROUTE_UNIT_M;
+static int __maneuver_index = 0;
+static coords_s __destination_point;
+
+static mapquest_error_e __convert_status(int status)
+{
+ mapquest_error_e error = MAPQUEST_ERROR_UNKNOWN;
+ switch (status) {
+ case 0:
+ {
+ /* Successful Geocode call */
+ error = MAPQUEST_ERROR_NONE;
+ break;
+ }
+ case 400:
+ {
+ /* Error with input - Illegal argument from request */
+ error = MAPQUEST_ERROR_INVALID_PARAMETER;
+ break;
+ }
+ case 403:
+ {
+ /* Key related error - Invalid key */
+ error = MAPQUEST_ERROR_KEY_NOT_AVAILABLE;
+ break;
+ }
+ case 500:
+ {
+ /* Unknown error */
+ error = MAPQUEST_ERROR_UNKNOWN;
+ break;
+ }
+ case -1:
+ {
+ /* Network error */
+ error = MAPQUEST_ERROR_NETWORK_UNREACHABLE;
+ break;
+ }
+ }
+
+ return error;
+}
+
+/************ GEOCODE ***************/
+
+static void __parse_lat_lng(JsonNode *node, GList **coordsList)
+{
+ if (!node || !coordsList) return;
+
+ gdouble latitude = 0.0;
+ gdouble longitude = 0.0;
+ JsonObject *resultObj = json_node_get_object(node);
+
+ if (resultObj) {
+ JsonNode *latNode = json_object_get_member(resultObj, "lat");
+
+ if (latNode) {
+ latitude = json_node_get_double(latNode);
+ MAP_DEBUG("Latitude :: >>> %f", latitude);
+ }
+
+ JsonNode *lngNode = json_object_get_member(resultObj, "lng");
+
+ if (lngNode) {
+ longitude = json_node_get_double(lngNode);
+ MAP_DEBUG("Longitude :: >>> %f", longitude);
+ }
+
+ coords_s *coords = (coords_s *)g_malloc0(sizeof(coords_s));
+ if (coords != NULL) {
+ MAP_DEBUG("Storing the latitude and longitude data..");
+ coords->latitude = latitude;
+ coords->longitude = longitude;
+ }
+
+ if (*coordsList == NULL)
+ *coordsList = g_list_append(*coordsList, coords);
+ else
+ *coordsList = g_list_insert_before(*coordsList, NULL, coords);
+ }
+}
+
+static void __parse_locations(JsonNode *node, GList **coordsList)
+{
+ if (!node || !coordsList) return;
+
+ JsonArray *resultArray = json_node_get_array(node);
+
+ int length = json_array_get_length(resultArray);
+
+ int index = 0;
+ for (index = 0; index < length; index++) {
+
+ JsonObject *obj = json_array_get_object_element(resultArray, index);
+
+ if (obj) {
+ JsonNode *latLngNode = json_object_get_member(obj, "latLng");
+
+ if (latLngNode)
+ __parse_lat_lng(latLngNode, coordsList);
+ }
+ }
+}
+
+static void __parse_geocode_response(char *response, int size, int *status, GList **coordsList)
+{
+ if (!response || !status || !coordsList) return;
+
+ *coordsList = NULL;
+
+ JsonParser *parser = NULL;
+ JsonNode *root = NULL;
+ JsonNode *node = NULL;
+ JsonObject *object = NULL;
+ GError *error = NULL;
+ char data[size + 1];
+
+ parser = json_parser_new();
+
+ strncpy(data, response, size);
+ data[size] = '\0';
+
+ if (!json_parser_load_from_data(parser, data, -1, &error)) {
+ MAP_DEBUG("Error in file parsing JSON..");
+ g_error_free(error);
+ g_object_unref(parser);
+ return;
+ }
+
+ root = json_parser_get_root(parser);
+
+ object = json_node_get_object(root);
+
+ node = json_object_get_member(object, "info");
+ JsonObject *infoObj = json_node_get_object(node);
+ if (infoObj) {
+ JsonNode *statusNode = json_object_get_member(infoObj, "statuscode");
+
+ if (statusNode) {
+ *status = json_node_get_int(statusNode);
+ MAP_DEBUG("status :: >>> %d", *status);
+ }
+ }
+
+ if (*status != 0) { /* SUCCESS */
+ *coordsList = NULL;
+ return;
+ }
+
+ node = json_object_get_member(object, "results");
+ JsonArray *resultArray = json_node_get_array(node);
+
+ int length = json_array_get_length(resultArray);
+
+ int index = 0;
+ for (index = 0; index < length; index++) {
+
+ JsonObject *obj = json_array_get_object_element(resultArray, index);
+
+ if (obj) {
+ JsonNode *locNode = json_object_get_member(obj, "locations");
+
+ if (locNode)
+ __parse_locations(locNode, coordsList);
+ }
+ }
+
+ g_object_unref(parser);
+}
+
+/****************** REVERSE GEOCODE *********************/
+
+static void __parse_revgeocode_address(JsonNode *node, mapquest_address_resp_s **respAddr)
+{
+ if (!node || !respAddr) return;
+
+ char *streetAddr = NULL;
+ char *neighbourhood = NULL;
+ char *city = NULL;
+ char *county = NULL;
+ char *state = NULL;
+ char *country = NULL;
+ char *postalCode = NULL;
+
+ JsonArray *resultArray = json_node_get_array(node);
+
+ int length = json_array_get_length(resultArray);
+
+ int index = 0;
+ for (index = 0; index < length; index++) {
+
+ JsonObject *obj = json_array_get_object_element(resultArray, index);
+
+ if (obj) {
+ JsonNode *tmp = NULL;
+
+ /* Street */
+ tmp = json_object_get_member(obj, "street");
+ if (tmp) {
+ streetAddr = (char *) json_node_get_string(tmp);
+ if (streetAddr && strlen(streetAddr) <= 0)
+ streetAddr = NULL;
+ } else {
+ streetAddr = NULL;
+ }
+
+ /* Neighborhood */
+ tmp = json_object_get_member(obj, "adminArea6");
+ if (tmp) {
+ neighbourhood = (char *) json_node_get_string(tmp);
+ if (neighbourhood && strlen(neighbourhood) <= 0)
+ neighbourhood = NULL;
+ } else {
+ neighbourhood = NULL;
+ }
+
+ /* City */
+ tmp = json_object_get_member(obj, "adminArea5");
+ if (tmp) {
+ city = (char *) json_node_get_string(tmp);
+ if (city && strlen(city) <= 0)
+ city = NULL;
+ } else {
+ city = NULL;
+ }
+
+ /* State */
+ tmp = json_object_get_member(obj, "adminArea3");
+ if (tmp) {
+ state = (char *) json_node_get_string(tmp);
+ if (state && strlen(state) <= 0)
+ state = NULL;
+ } else {
+ state = NULL;
+ }
+
+ /* County */
+ tmp = json_object_get_member(obj, "adminArea4");
+ if (tmp) {
+ county = (char *) json_node_get_string(tmp);
+ if (county && strlen(county) <= 0)
+ county = NULL;
+ } else {
+ county = NULL;
+ }
+
+ /* Country */
+ tmp = json_object_get_member(obj, "adminArea1");
+ if (tmp) {
+ country = (char *) json_node_get_string(tmp);
+ if (country && strlen(country) <= 0)
+ country = NULL;
+ } else {
+ country = NULL;
+ }
+
+ /* Postal Code */
+ tmp = json_object_get_member(obj, "postalCode");
+ if (tmp) {
+ postalCode = (char *) json_node_get_string(tmp);
+ if (postalCode && strlen(postalCode) <= 0)
+ postalCode = NULL;
+ } else {
+ postalCode = NULL;
+ }
+
+ if (!streetAddr && !neighbourhood && !city && !state && !county && !country && !postalCode)
+ continue;
+
+ *respAddr = (mapquest_address_resp_s *)g_malloc(sizeof(mapquest_address_resp_s));
+
+ if (*respAddr != NULL) {
+ /* Street Address */
+ if (streetAddr != NULL) {
+ (*respAddr)->street_add = (gchar *)g_malloc(strlen((char *)streetAddr) + 1);
+ strcpy((*respAddr)->street_add, (char *) streetAddr);
+ } else {
+ MAP_DEBUG("street is NULL");
+ (*respAddr)->street_add = NULL;
+ }
+
+ /* Neighbourhood */
+ if (neighbourhood != NULL) {
+ (*respAddr)->neighbourhood = (gchar *)g_malloc(strlen((char *)neighbourhood) + 1);
+ strcpy((*respAddr)->neighbourhood, (char *) neighbourhood);
+ } else {
+ MAP_DEBUG("neighbourhood is NULL");
+ (*respAddr)->neighbourhood = NULL;
+ }
+
+ /* City */
+ if (city != NULL) {
+ (*respAddr)->city = (gchar *)g_malloc(strlen((char *)city) + 1);
+ strcpy((*respAddr)->city, (char *) city);
+ } else {
+ MAP_DEBUG("city is NULL");
+ (*respAddr)->city = NULL;
+ }
+
+ /* County */
+ if (county != NULL) {
+ (*respAddr)->county = (gchar *)g_malloc(strlen((char *)county) + 1);
+ strcpy((*respAddr)->county, (char *) county);
+ } else {
+ MAP_DEBUG("county is NULL");
+ (*respAddr)->county = NULL;
+ }
+
+ /* State */
+ if (state != NULL) {
+ (*respAddr)->state = (gchar *)g_malloc(strlen((char *)state) + 1);
+ strcpy((*respAddr)->state, (char *) state);
+ } else {
+ MAP_DEBUG("state is NULL");
+ (*respAddr)->state = NULL;
+ }
+
+ /* Country */
+ if (country != NULL) {
+ (*respAddr)->country = (gchar *)g_malloc(strlen((char *)country) + 1);
+ strcpy((*respAddr)->country, (char *) country);
+ } else {
+ MAP_DEBUG("country is NULL");
+ (*respAddr)->country = NULL;
+ }
+
+ /* Country code */
+ MAP_DEBUG("country code is NULL");
+ (*respAddr)->country_code = NULL;
+
+ /* Postal Code */
+ if (postalCode != NULL) {
+ (*respAddr)->postal_code = (gchar *)g_malloc(strlen((char *)postalCode) + 1);
+ strcpy((*respAddr)->postal_code, (char *) postalCode);
+ } else {
+ MAP_DEBUG("postal_code is NULL");
+ (*respAddr)->postal_code = NULL;
+ }
+ }
+ }
+ }
+}
+
+static void __parse_revgeocode_response(char *response, int size, int *status, mapquest_address_resp_s **respAddr)
+{
+ if (!response || !status || !respAddr) return;
+
+ *respAddr = NULL;
+
+ JsonParser *parser;
+ JsonNode *root;
+ JsonNode *node;
+ JsonObject *object;
+ GError *error = NULL;
+ char data[size + 1];
+
+ parser = json_parser_new();
+
+ strncpy(data, response, size);
+ data[size] = '\0';
+
+ if (!json_parser_load_from_data(parser, data, -1, &error)) {
+ MAP_DEBUG("Error in file parsing JSON..");
+ g_error_free(error);
+ g_object_unref(parser);
+ return;
+ }
+
+ root = json_parser_get_root(parser);
+
+ object = json_node_get_object(root);
+
+ node = json_object_get_member(object, "info");
+ JsonObject *infoObj = json_node_get_object(node);
+ if (infoObj) {
+ JsonNode *statusNode = json_object_get_member(infoObj, "statuscode");
+
+ if (statusNode) {
+ *status = json_node_get_int(statusNode);
+ MAP_DEBUG("status :: >>> %d", *status);
+ }
+ }
+
+ if (*status != 0) { /* SUCCESS */
+ *respAddr = NULL;
+ return;
+ }
+
+ node = json_object_get_member(object, "results");
+ JsonArray *resultArray = json_node_get_array(node);
+
+ int length = json_array_get_length(resultArray);
+
+ int index = 0;
+ for (index = 0; index < length; index++) {
+
+ JsonObject *obj = json_array_get_object_element(resultArray, index);
+
+ if (obj) {
+ JsonNode *locNode = json_object_get_member(obj, "locations");
+
+ if (locNode)
+ __parse_revgeocode_address(locNode, respAddr);
+ }
+ }
+
+ g_object_unref(parser);
+}
+
+/**************** PLACE SEARCH ********************/
+
+static void __place_address_foreach(JsonObject *object, const gchar *member_name, JsonNode *member_node, gpointer user_data)
+{
+ if (!object || !member_name || !member_node || !user_data) return;
+
+ mapquest_address_resp_s **respAddr = (mapquest_address_resp_s **) user_data;
+
+ if (*respAddr) {
+ JsonNode *tmp = json_object_get_member(object, member_name);
+
+ if (!strcmp(member_name, "road"))
+ (*respAddr)->street_add = (char *) json_node_dup_string(tmp);
+ else if (!strcmp(member_name, "neighbourhood"))
+ (*respAddr)->neighbourhood = (char *) json_node_dup_string(tmp);
+ else if (!strcmp(member_name, "house_number"))
+ (*respAddr)->building_number = (char *) json_node_dup_string(tmp);
+ else if (!strcmp(member_name, "city"))
+ (*respAddr)->city = (char *) json_node_dup_string(tmp);
+ else if (!strcmp(member_name, "county"))
+ (*respAddr)->county = (char *) json_node_dup_string(tmp);
+ else if (!strcmp(member_name, "state"))
+ (*respAddr)->state = (char *) json_node_dup_string(tmp);
+ else if (!strcmp(member_name, "country"))
+ (*respAddr)->country = (char *) json_node_dup_string(tmp);
+ else if (!strcmp(member_name, "country_code"))
+ (*respAddr)->country_code = (char *) json_node_dup_string(tmp);
+ else if (!strcmp(member_name, "postcode"))
+ (*respAddr)->postal_code = (char *) json_node_dup_string(tmp);
+ } else {
+ *respAddr = NULL;
+ }
+}
+
+static void __place_foreach(JsonObject *object, const gchar *member_name, JsonNode *member_node, gpointer user_data)
+{
+ if (!object || !member_name || !member_node || !user_data) return;
+
+ mapquest_place_resp_s **respPlaces = (mapquest_place_resp_s **) user_data;
+
+ JsonNode *tmp = json_object_get_member(object, member_name);
+ char *str;
+
+ if (!strcmp(member_name, "place_id")) {
+ (*respPlaces)->place_id = (char *) json_node_get_string(tmp);
+ } else if (!strcmp(member_name, "lat")) {
+ str = (char *) json_node_get_string(tmp);
+ ((*respPlaces)->coordinates).latitude = (str ? atof(str) : 0);
+ } else if (!strcmp(member_name, "lon")) {
+ str = (char *) json_node_get_string(tmp);
+ ((*respPlaces)->coordinates).longitude = (str ? atof(str) : 0);
+ } else if (!strcmp(member_name, "class")) {
+ (*respPlaces)->category = (char *) json_node_dup_string(tmp);
+ } else if (!strcmp(member_name, "type")) {
+ (*respPlaces)->subcategory = (char *) json_node_dup_string(tmp);
+ } else if (!strcmp(member_name, "display_name")) {
+ (*respPlaces)->display_name = (char *) json_node_dup_string(tmp);
+ } else if (!strcmp(member_name, "address")) {
+ JsonObject *obj = json_node_get_object(member_node);
+
+ (*respPlaces)->address = (mapquest_address_resp_s *)g_malloc(sizeof(mapquest_address_resp_s));
+ if ((*respPlaces)->address) {
+ (*respPlaces)->address->street_add = NULL;
+ (*respPlaces)->address->neighbourhood = NULL;
+ (*respPlaces)->address->building_number = NULL;
+ (*respPlaces)->address->city = NULL;
+ (*respPlaces)->address->county = NULL;
+ (*respPlaces)->address->state = NULL;
+ (*respPlaces)->address->country = NULL;
+ (*respPlaces)->address->country_code = NULL;
+ (*respPlaces)->address->postal_code = NULL;
+ }
+
+ json_object_foreach_member(obj, __place_address_foreach, &((*respPlaces)->address));
+ } else if (!strcmp(member_name, "icon")) {
+ (*respPlaces)->icon_url = (char *) json_node_get_string(tmp);
+ }
+}
+
+static void __parse_place_response(char *response, int size, GList **placeList)
+{
+ if (!response || !placeList) return;
+
+ *placeList = NULL;
+
+ JsonParser *parser;
+ JsonNode *root;
+ GError *error = NULL;
+ char data[size + 1];
+
+ parser = json_parser_new();
+ if (!parser) return;
+
+ strncpy(data, response, size);
+ data[size] = '\0';
+
+ if (!json_parser_load_from_data(parser, data, -1, &error)) {
+ MAP_DEBUG("Error in file parsing JSON..");
+ g_error_free(error);
+ g_object_unref(parser);
+ return;
+ }
+
+ root = json_parser_get_root(parser);
+
+ JsonArray *placeArray = json_node_get_array(root);
+
+ int length = json_array_get_length(placeArray);
+ MAP_DEBUG("Places result count :: %d", length);
+
+ int index = 0;
+ for (index = 0; index < length; index++) {
+
+ JsonObject *obj = json_array_get_object_element(placeArray, index);
+
+ if (obj) {
+ mapquest_place_resp_s *respPlaces = (mapquest_place_resp_s *)g_malloc(sizeof(mapquest_place_resp_s));
+
+ if (respPlaces) {
+ respPlaces->place_id = NULL;
+ respPlaces->category = NULL;
+ respPlaces->subcategory = NULL;
+ respPlaces->display_name = NULL;
+ respPlaces->address = NULL;
+ respPlaces->icon_url = NULL;
+
+ json_object_foreach_member(obj, __place_foreach, &respPlaces);
+
+ if (*placeList == NULL)
+ *placeList = g_list_append(*placeList, respPlaces);
+ else
+ *placeList = g_list_insert_before(*placeList, NULL, respPlaces);
+ }
+ }
+ }
+
+ g_object_unref(parser);
+}
+
+/********************* ROUTE RESPONSE ***********************/
+
+static double __convert_distance_unit(double distance)
+{
+ double val = 0.0;
+ switch (__route_unit) {
+ case ROUTE_UNIT_M:
+ val = ROUTE_UNIT_CONVERSION_MILE_TO_M(distance);
+ break;
+ case ROUTE_UNIT_KM:
+ val = ROUTE_UNIT_CONVERSION_MILE_TO_KM(distance);
+ break;
+ case ROUTE_UNIT_FT:
+ val = ROUTE_UNIT_CONVERSION_MILE_TO_FT(distance);
+ break;
+ case ROUTE_UNIT_YD:
+ val = ROUTE_UNIT_CONVERSION_MILE_TO_YD(distance);
+ break;
+ }
+
+ return val;
+}
+
+static void __maneuver_foreach(JsonObject *object, const gchar *member_name, JsonNode *member_node, gpointer user_data)
+{
+ if (!object || !member_name || !member_node || !user_data) return;
+
+ mapquest_route_maneuver **maneuver = (mapquest_route_maneuver **) user_data;
+
+ JsonNode *tmp = json_object_get_member(object, member_name);
+
+ if (!strcmp(member_name, "startPoint")) {
+ JsonObject *coordsObj = json_node_get_object(tmp);
+
+ if (coordsObj) {
+ double latitude = 0.0;
+ double longitude = 0.0;
+ JsonNode *latNode = json_object_get_member(coordsObj, "lat");
+
+ if (latNode)
+ latitude = json_node_get_double(latNode);
+
+ JsonNode *lngNode = json_object_get_member(coordsObj, "lng");
+
+ if (lngNode)
+ longitude = json_node_get_double(lngNode);
+
+ coords_s start_point;
+ start_point.latitude = latitude;
+ start_point.longitude = longitude;
+
+ (*maneuver)->start_point = start_point;
+ }
+ } else if (!strcmp(member_name, "narrative")) {
+ (*maneuver)->instruction = (char *) json_node_dup_string(tmp);
+ } else if (!strcmp(member_name, "distance")) {
+ double dist = json_node_get_double(tmp);
+ (*maneuver)->distance = __convert_distance_unit(dist);
+ } else if (!strcmp(member_name, "time")) {
+ (*maneuver)->time = json_node_get_int(tmp);
+ } else if (!strcmp(member_name, "formattedTime")) {
+ (*maneuver)->formatted_time = (char *) json_node_dup_string(tmp);
+ } else if (!strcmp(member_name, "attributes")) {
+ (*maneuver)->attribute = json_node_get_int(tmp);
+ } else if (!strcmp(member_name, "turnType")) {
+ (*maneuver)->turn_type = json_node_get_int(tmp);
+ } else if (!strcmp(member_name, "direction")) {
+ (*maneuver)->direction = json_node_get_int(tmp);
+ } else if (!strcmp(member_name, "directionName")) {
+ (*maneuver)->direction_name = (char *) json_node_dup_string(tmp);
+ } else if (!strcmp(member_name, "index")) {
+ (*maneuver)->index = json_node_get_int(tmp);
+ } else if (!strcmp(member_name, "streets")) {
+ JsonArray *streetsArray = json_node_get_array(tmp);
+
+ int length = json_array_get_length(streetsArray);
+
+ char street_name[512];
+ strcpy(street_name, "");
+ int index = 0;
+ for (index = 0; index < length; index++) {
+ char *name = (char *) json_array_get_string_element(streetsArray, index);
+ if (name) {
+ if (index == 0) {
+ strncpy(street_name, name, sizeof(street_name)-1);
+ } else {
+ strcat(street_name, "/");
+ strncat(street_name, name, sizeof(street_name)-strlen(street_name)-1);
+ }
+ }
+ }
+
+ if (strlen(street_name) > 0) {
+ (*maneuver)->street_name = (gchar *)g_malloc0((strlen((char *)street_name)) + 1);
+ if ((*maneuver)->street_name)
+ strcpy((*maneuver)->street_name, (char *) street_name);
+ } else {
+ (*maneuver)->street_name = NULL;
+ }
+ }
+}
+
+static void __parse_maneuvers(JsonNode *node, mapquest_route_resp_s **routeResp)
+{
+ if (!node || !routeResp) return;
+
+ JsonArray *resultArray = json_node_get_array(node);
+
+ int length = json_array_get_length(resultArray);
+
+ int index = 0;
+ for (index = 0; index < length; index++) {
+
+ JsonObject *obj = json_array_get_object_element(resultArray, index);
+
+ if (obj) {
+ mapquest_route_maneuver *maneuver = (mapquest_route_maneuver *)g_malloc(sizeof(mapquest_route_maneuver));
+
+ if (maneuver) {
+ json_object_foreach_member(obj, __maneuver_foreach, &maneuver);
+
+ if (__maneuver_index != 0) {
+ if (maneuver->distance == 0.0 && maneuver->time == 0) {
+ maneuver->start_point = __destination_point;
+ maneuver->end_point = __destination_point;
+ } else {
+
+ }
+
+ GList *list = NULL;
+ list = g_list_last((*routeResp)->maneuvers);
+ if (list) {
+ mapquest_route_maneuver *tmp = (mapquest_route_maneuver *)list->data;
+ tmp->end_point = maneuver->start_point;
+ }
+ }
+
+ if ((*routeResp)->maneuvers == NULL)
+ (*routeResp)->maneuvers = g_list_append((*routeResp)->maneuvers, (gpointer)maneuver);
+ else
+ (*routeResp)->maneuvers = g_list_insert_before((*routeResp)->maneuvers, NULL, (gpointer)maneuver);
+ }
+ __maneuver_index++;
+ }
+ }
+}
+
+static void __shape_foreach(JsonObject *object, const gchar *member_name, JsonNode *member_node, gpointer user_data)
+{
+ if (!object || !member_name || !member_node || !user_data) return;
+
+ mapquest_route_resp_s **routeResp = (mapquest_route_resp_s **) user_data;
+
+ JsonNode *tmp = json_object_get_member(object, member_name);
+
+ if (!strcmp(member_name, "shapePoints")) {
+ JsonArray *shapePointsArray = json_node_get_array(tmp);
+
+ int length = json_array_get_length(shapePointsArray);
+
+ int index = 0;
+ double val = 0.0;
+ coords_s *coords = NULL;
+ for (index = 0; index < length; index++) {
+
+ val = (double) json_array_get_double_element(shapePointsArray, index);
+
+ if ((index % 2) == 0) {
+ /* Lat */
+ coords = (coords_s *)g_malloc0(sizeof(coords_s));
+ if (coords)
+ coords->latitude = val;
+ } else {
+ /* Lon */
+ if (coords) {
+ coords->longitude = val;
+ if ((*routeResp)->shapePoints == NULL)
+ (*routeResp)->shapePoints = g_list_append((*routeResp)->shapePoints, (gpointer)coords);
+ else
+ (*routeResp)->shapePoints = g_list_insert_before((*routeResp)->shapePoints, NULL, (gpointer)coords);
+ }
+ }
+ }
+ }
+
+}
+
+static void __bbox_foreach(JsonObject *object, const gchar *member_name, JsonNode *member_node, gpointer user_data)
+{
+ if (!object || !member_name || !member_node || !user_data) return;
+
+ mapquest_route_resp_s **routeResp = (mapquest_route_resp_s **) user_data;
+
+ JsonNode *tmp = json_object_get_member(object, member_name);
+
+ JsonObject *coordsObj = json_node_get_object(tmp);
+ double latitude = 0.0;
+ double longitude = 0.0;
+
+ if (coordsObj) {
+ JsonNode *latNode = json_object_get_member(coordsObj, "lat");
+
+ if (latNode)
+ latitude = json_node_get_double(latNode);
+
+ JsonNode *lngNode = json_object_get_member(coordsObj, "lng");
+
+ if (lngNode)
+ longitude = json_node_get_double(lngNode);
+ }
+
+ if (!strcmp(member_name, "ul")) {
+ ((*routeResp)->bounding_box).top_left.latitude = latitude;
+ ((*routeResp)->bounding_box).top_left.longitude = longitude;
+ } else if (!strcmp(member_name, "lr")) {
+ ((*routeResp)->bounding_box).bottom_right.latitude = latitude;
+ ((*routeResp)->bounding_box).bottom_right.longitude = longitude;
+ }
+}
+
+static void __parse_route_response(char *response, int size, int *status, mapquest_route_resp_s **routeResp)
+{
+ if (!response || !status || !routeResp) return;
+
+ *routeResp = NULL;
+
+ JsonParser *parser;
+ JsonNode *root;
+ JsonNode *node;
+ JsonObject *object;
+ GError *error = NULL;
+ char data[size + 1];
+
+ parser = json_parser_new();
+
+ strncpy(data, response, size);
+ data[size] = '\0';
+
+ if (!json_parser_load_from_data(parser, data, -1, &error)) {
+ MAP_DEBUG("Error in file parsing JSON..");
+ g_error_free(error);
+ g_object_unref(parser);
+ return;
+ }
+
+ root = json_parser_get_root(parser);
+
+ object = json_node_get_object(root);
+
+ node = json_object_get_member(object, "info");
+ JsonObject *infoObj = json_node_get_object(node);
+ if (infoObj) {
+ JsonNode *statusNode = json_object_get_member(infoObj, "statuscode");
+
+ if (statusNode) {
+ *status = json_node_get_int(statusNode);
+ MAP_DEBUG("status :: >>> %d", *status);
+ }
+ }
+
+ if (*status != 0) { /* SUCCESS */
+ *routeResp = NULL;
+ return;
+ }
+
+ *routeResp = (mapquest_route_resp_s *)g_malloc(sizeof(mapquest_route_resp_s));
+
+ if (!(*routeResp))
+ return;
+
+ (*routeResp)->maneuvers = NULL;
+ (*routeResp)->shapePoints = NULL;
+
+ node = json_object_get_member(object, "route");
+
+ if (!node)
+ return;
+
+ JsonObject *routeObject = json_node_get_object(node);
+
+ JsonNode *tmp = json_object_get_member(routeObject, "distance");
+
+ if (tmp) {
+ double dist = json_node_get_double(tmp);
+ (*routeResp)->distance = __convert_distance_unit(dist);
+ (*routeResp)->distance_unit = __route_unit;
+ }
+
+ tmp = json_object_get_member(routeObject, "boundingBox");
+
+ if (tmp) {
+ JsonObject *bbox = json_node_get_object(tmp);
+
+ json_object_foreach_member(bbox, __bbox_foreach, routeResp);
+ }
+
+ tmp = json_object_get_member(routeObject, "formattedTime");
+
+ if (tmp)
+ (*routeResp)->formatted_time = (char *) json_node_dup_string(tmp);
+
+ tmp = json_object_get_member(routeObject, "routeType");
+ if (tmp) {
+ (*routeResp)->type = ROUTE_TYPE_BICYCLE;
+
+ char *type = (char *) json_node_get_string(tmp);
+ if (type) {
+ if (!strcmp(type, "FASTEST"))
+ (*routeResp)->type = ROUTE_TYPE_FASTEST;
+ else if (!strcmp(type, "SHORTEST"))
+ (*routeResp)->type = ROUTE_TYPE_SHORTEST;
+ else if (!strcmp(type, "PEDESTRIAN"))
+ (*routeResp)->type = ROUTE_TYPE_PEDESTRIAN;
+ else if (!strcmp(type, "MULTIMODAL"))
+ (*routeResp)->type = ROUTE_TYPE_MULTIMODAL;
+ }
+ }
+
+ tmp = json_object_get_member(routeObject, "time");
+
+ if (tmp) {
+ int time = json_node_get_int(tmp);
+ (*routeResp)->time = time;
+ }
+
+ tmp = json_object_get_member(routeObject, "legs");
+
+ if (tmp) {
+ JsonArray *legsArray = json_node_get_array(tmp);
+
+ int length = json_array_get_length(legsArray);
+
+ int index = 0;
+ for (index = 0; index < length; index++) {
+
+ JsonObject *obj = json_array_get_object_element(legsArray, index);
+
+ if (obj) {
+ JsonNode *maneuversNode = json_object_get_member(obj, "maneuvers");
+
+ if (maneuversNode)
+ __parse_maneuvers(maneuversNode, routeResp);
+ }
+ }
+ }
+
+ tmp = json_object_get_member(routeObject, "shape");
+
+ if (tmp) {
+ JsonObject *shape = json_node_get_object(tmp);
+
+ json_object_foreach_member(shape, __shape_foreach, routeResp);
+ }
+
+ g_object_unref(parser);
+}
+
+void post_curl_response(char *response, int size, mapquest_resp_type type, void *user_data)
+{
+ if (!response) return;
+
+ if (!user_data) {
+ MAP_DEBUG("Response data is NULL");
+ return;
+ }
+
+ MAP_DEBUG("Response received from Curl. [Size=%d]", size);
+ switch (type) {
+ case RESP_TYPE_GEOCODE:
+ {
+ MAP_DEBUG("Inside Geocode JSON Parsing..");
+ int status = -1;
+ MapquestGeocodeQueryData *queryData = (MapquestGeocodeQueryData *)user_data;
+ MapquestGeocodeResponseData *responseData = (MapquestGeocodeResponseData *)g_malloc(sizeof(MapquestGeocodeResponseData));
+
+ if (responseData) {
+ responseData->requestId = queryData->requestId;
+ responseData->geocode_cb = queryData->geocode_cb;
+ responseData->user_data = queryData->user_data;
+
+ if (response && (size > 0)) {
+ GList *coordsList = NULL;
+ __parse_geocode_response(response, size, &status, &coordsList);
+
+ if (coordsList != NULL) {
+ /* Put the response in queue */
+ responseData->error = __convert_status(status);
+ responseData->coords = coordsList;
+ } else {
+ /* Response parsing failure */
+ responseData->error = __convert_status(status);
+ responseData->coords = NULL;
+ }
+ } else {
+ responseData->error = __convert_status(status);
+ responseData->coords = NULL;
+ }
+
+ mapquest_push_to_queue(type, (gpointer)responseData);
+ }
+
+ if (queryData) {
+ g_free(queryData);
+ queryData = NULL;
+ }
+ break;
+ }
+ case RESP_TYPE_REVGEOCODE:
+ {
+ MAP_DEBUG("Inside Rev Geocode JSON Parsing..");
+ int status = -1;
+ MapquestRevGeocodeQueryData *queryData = (MapquestRevGeocodeQueryData *)user_data;
+ MapquestRevGeocodeResponseData *responseData = (MapquestRevGeocodeResponseData *)g_malloc(sizeof(MapquestRevGeocodeResponseData));
+
+ if (responseData) {
+ responseData->requestId = queryData->requestId;
+ responseData->reverse_geocode_cb = queryData->reverse_geocode_cb;
+ responseData->user_data = queryData->user_data;
+
+ if (response && (size > 0)) {
+ /* Coords Result GList */
+ mapquest_address_resp_s *addrResponse = NULL;
+
+ MAP_DEBUG("Rev Geocode :- Parsing json Response");
+ __parse_revgeocode_response(response, size, &status, &addrResponse);
+
+ if (addrResponse != NULL) {
+ /* Put the response in queue */
+ responseData->error = __convert_status(status);
+ responseData->addressDetails = addrResponse;
+ } else {
+ /* REPSONSE PARSING FAILURE */
+ MAP_DEBUG("addr Response is NULL");
+ responseData->error = __convert_status(status);
+ responseData->addressDetails = NULL;
+ }
+ } else {
+ MAP_DEBUG("JSON Response is NULL..");
+ responseData->error = __convert_status(status);
+ responseData->addressDetails = NULL;
+ }
+
+ mapquest_push_to_queue(type, (gpointer)responseData);
+ }
+
+ if (queryData) {
+ g_free(queryData);
+ queryData = NULL;
+ }
+ break;
+ }
+ case RESP_TYPE_PLACES:
+ {
+ MAP_DEBUG("Inside Places JSON Parsing..");
+ MapquestPlaceQueryData *queryData = (MapquestPlaceQueryData *)user_data;
+ MapquestPlaceResponseData *responseData = (MapquestPlaceResponseData *)g_malloc(sizeof(MapquestPlaceResponseData));
+
+ if (responseData) {
+ responseData->requestId = queryData->requestId;
+ responseData->place_search_cb = queryData->place_search_cb;
+ responseData->user_data = queryData->user_data;
+
+ if (response && (size > 0)) {
+ /* Coords Result GList */
+ GList *placeList = NULL;
+
+ MAP_DEBUG("Search Places :- Parsing Json Response");
+ __parse_place_response(response, size, &placeList);
+
+ if (placeList != NULL) {
+ /* Put the response in queue */
+ responseData->error = MAPQUEST_ERROR_NONE;
+ responseData->places = placeList;
+ } else {
+ /* REPSONSE PARSING FAILURE */
+ MAP_DEBUG("addr Response is NULL");
+ responseData->error = MAPQUEST_ERROR_UNKNOWN;
+ responseData->places = NULL;
+ }
+ } else {
+ responseData->error = MAPQUEST_ERROR_UNKNOWN;
+ responseData->places = NULL;
+ }
+
+ mapquest_push_to_queue(type, (gpointer)responseData);
+ }
+
+ if (queryData) {
+ g_free(queryData);
+ queryData = NULL;
+ }
+
+ break;
+ }
+ case RESP_TYPE_ROUTE:
+ {
+ MAP_DEBUG("Inside Route JSON Parsing..");
+ int status = -1;
+ MapquestRouteQueryData *queryData = (MapquestRouteQueryData *)user_data;
+ __route_unit = queryData->unit;
+ __maneuver_index = 0;
+ __destination_point = queryData->destination;
+
+ MapquestRouteResponseData *responseData = (MapquestRouteResponseData *)g_malloc(sizeof(MapquestRouteResponseData));
+
+ if (responseData) {
+ responseData->requestId = queryData->requestId;
+ responseData->route_cb = queryData->route_cb;
+ responseData->user_data = queryData->user_data;
+
+ if (response && (size > 0)) {
+ /* Coords Result GList */
+ mapquest_route_resp_s *routeResponse = NULL;
+
+ MAP_DEBUG("Route :- Parsing Response");
+ __parse_route_response(response, size, &status, &routeResponse);
+
+ if (routeResponse != NULL) {
+ /* Put the response in queue */
+ responseData->error = __convert_status(status);
+ responseData->routeResponse = routeResponse;
+ } else {
+ /* REPSONSE PARSING FAILURE */
+ MAP_DEBUG("route Response is NULL");
+ responseData->error = __convert_status(status);
+ responseData->routeResponse = NULL;
+ }
+ } else {
+ responseData->error = __convert_status(status);
+ responseData->routeResponse = NULL;
+ }
+
+ mapquest_push_to_queue(type, (gpointer)responseData);
+ }
+
+ if (queryData) {
+ g_free(queryData);
+ queryData = NULL;
+ }
+
+ break;
+ }
+ default:
+ {
+ MAP_DEBUG("Inside default JSON Parsing..");
+ break;
+ }
+ }
+}
diff --git a/src/mapquest/mapquest_jsonparser.h b/src/mapquest/mapquest_jsonparser.h
new file mode 100644
index 0000000..19e4f1e
--- /dev/null
+++ b/src/mapquest/mapquest_jsonparser.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_JSONPARSER_H_
+#define _MAPQUEST_JSONPARSER_H_
+
+#include "mapquest_server_private.h"
+
+void post_curl_response(char *response, int size, mapquest_resp_type type, void *user_data);
+
+#endif /* _MAPQUEST_JSONPARSER_H_ */
diff --git a/src/mapquest/mapquest_place.c b/src/mapquest/mapquest_place.c
new file mode 100644
index 0000000..52a05bc
--- /dev/null
+++ b/src/mapquest/mapquest_place.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <pthread.h>
+#include "mapquest_place.h"
+#include "mapquest_types.h"
+#include "mapquest_server_private.h"
+#include "mapquest_debug.h"
+#include "mapquest_queue.h"
+#include "mapquest_restcurl.h"
+#include "mapquest_util.h"
+
+#define PLACES_URL "https://open.mapquestapi.com/nominatim/v1/search.php?format=json"
+
+int query_places(gchar *maps_key, gchar *search_str, mapquest_boundary_s *boundary, int num_res, gpointer user_data)
+{
+ char url[1024];
+ char tmpStr[512];
+
+ strcpy(url, PLACES_URL);
+
+ if (search_str != NULL) {
+ snprintf(tmpStr, sizeof(tmpStr), "&q=%s", search_str);
+ strncat(url, tmpStr, sizeof(url)-strlen(url)-1);
+ }
+
+ if (boundary != NULL) {
+ if (boundary->type == MAPQUEST_BOUNDARY_RECT) {
+ snprintf(tmpStr, sizeof(tmpStr), "&viewbox=%f,%f,%f,%f", boundary->rect.top_left.longitude, boundary->rect.top_left.latitude, boundary->rect.bottom_right.longitude, boundary->rect.bottom_right.latitude);
+
+ strncat(url, tmpStr, sizeof(url)-strlen(url)-1);
+ } else if (boundary->type == MAPQUEST_BOUNDARY_CIRCLE) {
+ coords_s *top_left = NULL, *bottom_right = NULL;
+ coords_s circle = boundary->circle.center;
+ gdouble radius = (boundary->circle.radius) * 0.001;
+
+ /* Calculate the top left coordinate of bounding box. */
+ calculate_point(circle.latitude, circle.longitude, 315, radius, &top_left);
+
+ /* Calculate the bottom right coordinate of bounding box. */
+ calculate_point(circle.latitude, circle.longitude, 135, radius, &bottom_right);
+
+ if (top_left && bottom_right) {
+ snprintf(tmpStr, sizeof(tmpStr), "&viewbox=%f,%f,%f,%f", top_left->longitude, top_left->latitude, bottom_right->longitude, bottom_right->latitude);
+ strncat(url, tmpStr, sizeof(url)-strlen(url)-1);
+ }
+
+ if (top_left) {
+ g_free(top_left);
+ top_left = NULL;
+ }
+ if (bottom_right) {
+ g_free(bottom_right);
+ bottom_right = NULL;
+ }
+ }
+
+ strcat(url, "&bounded=1");
+ }
+
+ strcat(url, "&addressdetails=1");
+
+ if (num_res > 0) {
+ snprintf(tmpStr, sizeof(tmpStr), "&limit=%d", num_res);
+ strcat(url, tmpStr);
+ }
+
+ add_handle(url, REQ_TYPE_PLACES, user_data);
+
+ return 0;
+}
diff --git a/src/mapquest/mapquest_place.h b/src/mapquest/mapquest_place.h
new file mode 100644
index 0000000..40812a5
--- /dev/null
+++ b/src/mapquest/mapquest_place.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_PLACES_H_
+#define _MAPQUEST_PLACES_H_
+
+#include "mapquest_api.h"
+#include "mapquest_types.h"
+
+int query_places(gchar *maps_key, gchar *search_str, mapquest_boundary_s *boundary, int num_res, gpointer user_data);
+
+#endif /* _MAPQUEST_PLACES_H_ */
diff --git a/src/mapquest/mapquest_queue.c b/src/mapquest/mapquest_queue.c
new file mode 100644
index 0000000..c64ad8b
--- /dev/null
+++ b/src/mapquest/mapquest_queue.c
@@ -0,0 +1,1263 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <stdio.h>
+#include<stdlib.h>
+#include "mapquest_queue.h"
+#include "mapquest_geocode.h"
+#include "mapquest_revgeocode.h"
+#include "mapquest_route.h"
+#include "mapquest_place.h"
+#include "mapquest_restcurl.h"
+#include "mapquest_util.h"
+#include "mapquest_debug.h"
+#include <json-glib/json-glib.h>
+
+pthread_mutex_t __requestLock;
+static GAsyncQueue *responseQueue = NULL;
+int __ResponseQueueLen = 0;
+bool __response_timer_running = false;
+
+/* Request List */
+GList *requestList = NULL;
+
+/* Request Cancel List */
+GList *reqCancelList = NULL;
+
+static void __free_geocode_response(void *ptr);
+static void __free_revgeocode_response(void *ptr);
+static void __free_place_response(void *ptr);
+static void __free_route_response(void *ptr);
+
+int add_to_geocode_list(mapquest_geocode_req_s *req_details, mapquest_geocode_cb callback, int request_id, void *user_data)
+{
+ mapquest_request_s *req = (mapquest_request_s *)g_malloc0(sizeof(mapquest_request_s));
+
+ if (req != NULL) {
+
+ req->type = REQ_TYPE_GEOCODE;
+
+ mapquest_geocode_req *data = (mapquest_geocode_req *)g_malloc0(sizeof(mapquest_geocode_req));
+
+ if (data != NULL) {
+ data->req_details = req_details;
+ data->requestId = request_id;
+ data->geocode_cb = callback;
+ data->user_data = user_data;
+
+ req->request = data;
+
+ MAP_DEBUG("Added GEOCODE REQUEST to geocode List");
+
+ pthread_mutex_lock(&__requestLock);
+ if (requestList == NULL)
+ requestList = g_list_append(requestList, (gpointer)req);
+ else
+ requestList = g_list_insert_before(requestList, NULL, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+ }
+ }
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+int add_to_revgeocode_list(mapquest_revgeocode_req_s *req_details, mapquest_reverse_geocode_cb callback, int request_id, void *user_data)
+{
+ mapquest_request_s *req = (mapquest_request_s *)g_malloc0(sizeof(mapquest_request_s));
+
+ if (req != NULL) {
+
+ req->type = REQ_TYPE_REVGEOCODE;
+
+ mapquest_revgeocode_req *data = (mapquest_revgeocode_req *)g_malloc0(sizeof(mapquest_revgeocode_req));
+
+ if (data != NULL) {
+ data->req_details = req_details;
+ data->requestId = request_id;
+ data->revgeocode_cb = callback;
+ data->user_data = user_data;
+
+ req->request = data;
+
+ MAP_DEBUG("Added REVERSE GEOCODE request to geocode List");
+
+ pthread_mutex_lock(&__requestLock);
+ if (requestList == NULL)
+ requestList = g_list_append(requestList, (gpointer)req);
+ else
+ requestList = g_list_insert_before(requestList, NULL, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+ }
+ }
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+int add_to_places_list(mapquest_search_req_s *req_details, mapquest_place_search_cb callback, int request_id, void *user_data)
+{
+ mapquest_request_s *req = (mapquest_request_s *)g_malloc0(sizeof(mapquest_request_s));
+
+ if (req != NULL) {
+
+ req->type = REQ_TYPE_PLACES;
+
+ mapquest_search_place_req *data = (mapquest_search_place_req *)g_malloc0(sizeof(mapquest_search_place_req));
+
+ if (data != NULL) {
+ data->req_details = req_details;
+ data->requestId = request_id;
+ data->search_place_cb = callback;
+ data->user_data = user_data;
+
+ req->request = data;
+
+ MAP_DEBUG("Added PLACE request to places List");
+
+ pthread_mutex_lock(&__requestLock);
+ if (requestList == NULL)
+ requestList = g_list_append(requestList, (gpointer)req);
+ else
+ requestList = g_list_insert_before(requestList, NULL, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+ }
+ }
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+int add_to_route_list(mapquest_route_req_s *req_details, mapquest_route_cb callback, int request_id, void *user_data)
+{
+ mapquest_request_s *req = (mapquest_request_s *)g_malloc0(sizeof(mapquest_request_s));
+
+ if (req != NULL) {
+
+ req->type = REQ_TYPE_ROUTE;
+
+ mapquest_route_req *data = (mapquest_route_req *)g_malloc0(sizeof(mapquest_route_req));
+
+ if (data != NULL) {
+ data->req_details = req_details;
+ data->requestId = request_id;
+ data->route_cb = callback;
+ data->user_data = user_data;
+
+ req->request = data;
+
+ MAP_DEBUG("Added request to route List");
+
+ pthread_mutex_lock(&__requestLock);
+ if (requestList == NULL)
+ requestList = g_list_append(requestList, (gpointer)req);
+ else
+ requestList = g_list_insert_before(requestList, NULL, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+ }
+
+ }
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+static int __add_to_cancel_list(int request_id)
+{
+ if (reqCancelList == NULL)
+ reqCancelList = g_list_append(reqCancelList, (gpointer)request_id);
+ else
+ reqCancelList = g_list_insert_before(reqCancelList, NULL, (gpointer)request_id);
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+static int __remove_from_cancel_list(int request_id)
+{
+ if (g_list_length(reqCancelList) != 0)
+ reqCancelList = g_list_remove(reqCancelList, (gpointer)request_id);
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+int remove_from_request_list(int request_id)
+{
+ bool is_request_cancelled = false;
+ GList *list = NULL;
+ pthread_mutex_lock(&__requestLock);
+ list = g_list_first(requestList);
+ pthread_mutex_unlock(&__requestLock);
+ mapquest_request_s *req = NULL;
+
+ while (list != NULL) {
+ req = (mapquest_request_s *) list->data;
+
+ if (req != NULL) {
+ if (req->type == REQ_TYPE_GEOCODE) {
+ mapquest_geocode_req *geocode_req = (mapquest_geocode_req *) req->request;
+
+ if (geocode_req->requestId == request_id) {
+ /* Means the request is pending in queue. Not started yet */
+ /* Deleting the request from the request queue */
+ pthread_mutex_lock(&__requestLock);
+ requestList = g_list_remove(requestList, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+ mapquest_geocode_req_s *geocode_req_details = (mapquest_geocode_req_s *)geocode_req->req_details;
+
+ if (geocode_req_details)
+ g_free(geocode_req_details);
+ geocode_req_details = NULL;
+
+ g_free(geocode_req);
+ geocode_req = NULL;
+
+ g_free(req);
+ req = NULL;
+
+ __remove_from_cancel_list(request_id);
+
+ is_request_cancelled = true;
+ break;
+ }
+ } else if (req->type == REQ_TYPE_REVGEOCODE) {
+ mapquest_revgeocode_req *revgeocode_req = (mapquest_revgeocode_req *)req->request;
+
+ if (revgeocode_req->requestId == request_id) {
+ /* Means the request is pending in queue. Not started yet */
+ /* Deleting the request from the request queue */
+ pthread_mutex_lock(&__requestLock);
+ requestList = g_list_remove(requestList, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+ mapquest_revgeocode_req_s *reverse_geocode_req_details = (mapquest_revgeocode_req_s *)revgeocode_req->req_details;
+
+ if (reverse_geocode_req_details)
+ g_free(reverse_geocode_req_details);
+ reverse_geocode_req_details = NULL;
+
+ g_free(revgeocode_req);
+ revgeocode_req = NULL;
+
+ g_free(req);
+ req = NULL;
+
+ __remove_from_cancel_list(request_id);
+
+ is_request_cancelled = true;
+ break;
+ }
+ } else if (req->type == REQ_TYPE_ROUTE) {
+ mapquest_route_req *route_req = (mapquest_route_req *) req->request;
+
+ if (route_req->requestId == request_id) {
+ /* Means the request is pending in queue. Not started yet */
+ /* Deleting the request from the request queue */
+ pthread_mutex_lock(&__requestLock);
+ requestList = g_list_remove(requestList, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+ mapquest_route_req_s *route_req_details = (mapquest_route_req_s *)route_req->req_details;
+
+ if (route_req_details)
+ g_free(route_req_details);
+ route_req_details = NULL;
+
+ g_free(route_req);
+ route_req = NULL;
+
+ g_free(req);
+ req = NULL;
+
+ __remove_from_cancel_list(request_id);
+
+ is_request_cancelled = true;
+ break;
+ }
+ } else if (req->type == REQ_TYPE_PLACES) {
+ mapquest_search_place_req *places_req = (mapquest_search_place_req *) req->request;
+
+ if (places_req->requestId == request_id) {
+ /* Means the request is pending in queue. Not started yet */
+ /* Deleting the request from the request queue */
+ pthread_mutex_lock(&__requestLock);
+ requestList = g_list_remove(requestList, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+ mapquest_search_req_s *place_req_details = (mapquest_search_req_s *)places_req->req_details;
+
+ if (place_req_details)
+ g_free(place_req_details);
+ place_req_details = NULL;
+
+ g_free(places_req);
+ places_req = NULL;
+
+ g_free(req);
+ req = NULL;
+
+ __remove_from_cancel_list(request_id);
+
+ is_request_cancelled = true;
+ break;
+ }
+ }
+ }
+
+ list = g_list_next(list);
+ }
+
+ if (!is_request_cancelled) {
+ /* Means it is currently running. */
+ /* Cancel the request */
+ cancel_request(request_id);
+ /* add to cancel list */
+ __add_to_cancel_list(request_id);
+ }
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+static bool __is_request_in_cancel_list(int requestId)
+{
+ bool match_id = false;
+
+ GList *list = NULL;
+ list = g_list_first(reqCancelList);
+
+ while (list != NULL) {
+
+ int id = (int) list->data;
+
+ if (id == requestId) {
+ match_id = true;
+ break;
+ }
+
+ list = g_list_next(list);
+ }
+
+ return match_id;
+}
+
+mapquest_request_s *get_next_request()
+{
+ if (g_list_length(requestList) > 0) {
+ pthread_mutex_lock(&__requestLock);
+ GList *list = g_list_first(requestList);
+ pthread_mutex_unlock(&__requestLock);
+
+ if (list) {
+ mapquest_request_s *req = (mapquest_request_s *) list->data;
+ return req;
+ } else {
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static gboolean __timeout_cb(gpointer data)
+{
+ MAP_DEBUG("timeout_cb");
+ __response_timer_running = true;
+ g_async_queue_ref(responseQueue);
+
+ __ResponseQueueLen = g_async_queue_length(responseQueue);
+ MAP_DEBUG("Queue Len :: [%d]", __ResponseQueueLen);
+ while (__ResponseQueueLen > 0) {
+ gpointer data = g_async_queue_try_pop(responseQueue);
+ if (!data)
+ continue;
+
+ MapquestQueueData *response = (MapquestQueueData *) data;
+
+ switch (response->type) {
+ case RESP_TYPE_GEOCODE:
+ {
+ MAP_DEBUG("Got geocode response..");
+ MapquestGeocodeResponseData *geocodeData = (MapquestGeocodeResponseData *) (response->data);
+ if (geocodeData) {
+ if (__is_request_in_cancel_list(geocodeData->requestId) == false) {
+ /* Deliver results to consumer */
+ geocodeData->geocode_cb(geocodeData->error, geocodeData->requestId, geocodeData->coords, geocodeData->user_data);
+ } else {
+ /* If present in cancel list, dont trigger the response. */
+ /* Remove the requestId from cancel list. */
+ __remove_from_cancel_list(geocodeData->requestId);
+ }
+ __free_geocode_response(geocodeData);
+
+ g_free(geocodeData);
+ geocodeData = NULL;
+ }
+
+ /* Start the Next valid request */
+ if (get_num_running_requests() < CURL_MAX_CONNECTS) {
+ MAP_DEBUG("Fetching the next request from the request list....");
+ mapquest_request_s *req = get_next_request();
+ if (req) {
+ pthread_mutex_lock(&__requestLock);
+ requestList = g_list_remove(requestList, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+
+ if (req->type == REQ_TYPE_GEOCODE) {
+ mapquest_geocode_req *geocode_req = (mapquest_geocode_req *) req->request;
+ if (geocode_req != NULL) {
+ start_geocode_service(geocode_req->req_details, geocode_req->geocode_cb, geocode_req->requestId, geocode_req->user_data);
+
+ g_free(geocode_req);
+ geocode_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_REVGEOCODE) {
+ mapquest_revgeocode_req *revgeocode_req = (mapquest_revgeocode_req *) req->request;
+ if (revgeocode_req != NULL) {
+ start_reversegeocode_service(revgeocode_req->req_details, revgeocode_req->revgeocode_cb, revgeocode_req->requestId, revgeocode_req->user_data);
+
+ g_free(revgeocode_req);
+ revgeocode_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_PLACES) {
+ mapquest_search_place_req *places_req = (mapquest_search_place_req *) req->request;
+ if (places_req) {
+ start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+ g_free(places_req);
+ places_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_ROUTE) {
+ mapquest_route_req *route_req = (mapquest_route_req *) req->request;
+ if (route_req) {
+ start_route_service(route_req->req_details, route_req->route_cb, route_req->requestId, route_req->user_data);
+
+ g_free(route_req);
+ route_req = NULL;
+ }
+ }
+
+ g_free(req);
+ req = NULL;
+ } else {
+ MAP_DEBUG("No request in queue or request type is wrong");
+ }
+ } else {
+ MAP_DEBUG("Libcurl request queue is FULL..");
+ }
+ }
+ break;
+
+ case RESP_TYPE_REVGEOCODE:
+ {
+ MapquestRevGeocodeResponseData *revGeocodeData = (MapquestRevGeocodeResponseData *) (response->data);
+ if (revGeocodeData) {
+ if (__is_request_in_cancel_list(revGeocodeData->requestId) == false) {
+ /* Deliver results to consumer */
+ revGeocodeData->reverse_geocode_cb(revGeocodeData->error, revGeocodeData->requestId, revGeocodeData->addressDetails, revGeocodeData->user_data);
+ } else {
+ /* If present in cancel list, dont trigger the response. */
+ /* Remove the requestId from cancel list. */
+ __remove_from_cancel_list(revGeocodeData->requestId);
+ }
+ __free_revgeocode_response(revGeocodeData);
+
+ g_free(revGeocodeData);
+ revGeocodeData = NULL;
+ }
+
+ /* Start the Next valid request */
+ MAP_DEBUG(">> Condition Check <<");
+ if (get_num_running_requests() < CURL_MAX_CONNECTS) {
+ MAP_DEBUG("Fetching the next request from the request list....");
+ mapquest_request_s *req = get_next_request();
+ if (req) {
+ pthread_mutex_lock(&__requestLock);
+ requestList = g_list_remove(requestList, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+
+ if (req->type == REQ_TYPE_GEOCODE) {
+ mapquest_geocode_req *geocode_req = (mapquest_geocode_req *) req->request;
+ if (geocode_req != NULL) {
+ start_geocode_service(geocode_req->req_details, geocode_req->geocode_cb, geocode_req->requestId, geocode_req->user_data);
+
+ g_free(geocode_req);
+ geocode_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_REVGEOCODE) {
+ mapquest_revgeocode_req *revgeocode_req = (mapquest_revgeocode_req *) req->request;
+ if (revgeocode_req != NULL) {
+ start_reversegeocode_service(revgeocode_req->req_details, revgeocode_req->revgeocode_cb, revgeocode_req->requestId, revgeocode_req->user_data);
+
+ g_free(revgeocode_req);
+ revgeocode_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_PLACES) {
+ mapquest_search_place_req *places_req = (mapquest_search_place_req *) req->request;
+ if (places_req) {
+ start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+ g_free(places_req);
+ places_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_ROUTE) {
+ mapquest_route_req *route_req = (mapquest_route_req *) req->request;
+ if (route_req) {
+ start_route_service(route_req->req_details, route_req->route_cb, route_req->requestId, route_req->user_data);
+
+ g_free(route_req);
+ route_req = NULL;
+ }
+ }
+
+ g_free(req);
+ req = NULL;
+ } else {
+ MAP_DEBUG("No request in queue or request type is wrong");
+ }
+ } else {
+ MAP_DEBUG("Libcurl request queue is FULL..");
+ }
+ }
+ break;
+
+ case RESP_TYPE_ROUTE:
+ {
+ MapquestRouteResponseData *routeData = (MapquestRouteResponseData *) (response->data);
+ if (routeData != NULL) {
+ if (__is_request_in_cancel_list(routeData->requestId) == false) {
+ /* Deliver results to consumer */
+ routeData->route_cb(routeData->error, routeData->requestId, routeData->routeResponse, routeData->user_data);
+ } else {
+ /* If present in cancel list, dont trigger the response. */
+ /* Remove the requestId from cancel list. */
+ __remove_from_cancel_list(routeData->requestId);
+ }
+ __free_route_response(routeData);
+
+ g_free(routeData);
+ routeData = NULL;
+ }
+
+ /* Start the Next valid request */
+ if (get_num_running_requests() < CURL_MAX_CONNECTS) {
+ MAP_DEBUG("Fetching the next request from the request list....");
+ mapquest_request_s *req = get_next_request();
+ if (req) {
+ pthread_mutex_lock(&__requestLock);
+ requestList = g_list_remove(requestList, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+
+ if (req->type == REQ_TYPE_GEOCODE) {
+ mapquest_geocode_req *geocode_req = (mapquest_geocode_req *) req->request;
+ if (geocode_req != NULL) {
+ start_geocode_service(geocode_req->req_details, geocode_req->geocode_cb, geocode_req->requestId, geocode_req->user_data);
+
+ g_free(geocode_req);
+ geocode_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_REVGEOCODE) {
+ mapquest_revgeocode_req *revgeocode_req = (mapquest_revgeocode_req *) req->request;
+ if (revgeocode_req != NULL) {
+ start_reversegeocode_service(revgeocode_req->req_details, revgeocode_req->revgeocode_cb, revgeocode_req->requestId, revgeocode_req->user_data);
+
+ g_free(revgeocode_req);
+ revgeocode_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_PLACES) {
+ mapquest_search_place_req *places_req = (mapquest_search_place_req *) req->request;
+ if (places_req) {
+ start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+ g_free(places_req);
+ places_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_ROUTE) {
+ mapquest_route_req *route_req = (mapquest_route_req *) req->request;
+ if (route_req) {
+ start_route_service(route_req->req_details, route_req->route_cb, route_req->requestId, route_req->user_data);
+
+ g_free(route_req);
+ route_req = NULL;
+ }
+ }
+
+ g_free(req);
+ req = NULL;
+ } else {
+ MAP_DEBUG("No request in queue or request type is wrong");
+ }
+ } else {
+ MAP_DEBUG("Libcurl request queue is FULL..");
+ }
+ }
+ break;
+
+ case RESP_TYPE_PLACES:
+ {
+ MapquestPlaceResponseData *placesData = (MapquestPlaceResponseData *) (response->data);
+ if (placesData != NULL) {
+ MAP_DEBUG("Sending places result..");
+ if (__is_request_in_cancel_list(placesData->requestId) == false) {
+ /* Deliver results to consumer */
+ placesData->place_search_cb(placesData->error, placesData->requestId, placesData->places, placesData->user_data);
+ } else {
+ /* If present in cancel list, dont trigger the response. */
+ /* Remove the requestId from cancel list. */
+ __remove_from_cancel_list(placesData->requestId);
+ }
+ __free_place_response(placesData);
+
+ g_free(placesData);
+ placesData = NULL;
+ }
+
+ /* Start the Next valid request */
+ if (get_num_running_requests() < CURL_MAX_CONNECTS) {
+ MAP_DEBUG("Fetching the next request from the request list....");
+ mapquest_request_s *req = get_next_request();
+ if (req) {
+ pthread_mutex_lock(&__requestLock);
+ requestList = g_list_remove(requestList, (gpointer)req);
+ pthread_mutex_unlock(&__requestLock);
+
+ if (req->type == REQ_TYPE_GEOCODE) {
+ mapquest_geocode_req *geocode_req = (mapquest_geocode_req *) req->request;
+ if (geocode_req != NULL) {
+ start_geocode_service(geocode_req->req_details, geocode_req->geocode_cb, geocode_req->requestId, geocode_req->user_data);
+
+ g_free(geocode_req);
+ geocode_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_REVGEOCODE) {
+ mapquest_revgeocode_req *revgeocode_req = (mapquest_revgeocode_req *) req->request;
+ if (revgeocode_req != NULL) {
+ start_reversegeocode_service(revgeocode_req->req_details, revgeocode_req->revgeocode_cb, revgeocode_req->requestId, revgeocode_req->user_data);
+
+ g_free(revgeocode_req);
+ revgeocode_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_PLACES) {
+ mapquest_search_place_req *places_req = (mapquest_search_place_req *) req->request;
+ if (places_req) {
+ start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+ g_free(places_req);
+ places_req = NULL;
+ }
+ } else if (req->type == REQ_TYPE_ROUTE) {
+ mapquest_route_req *route_req = (mapquest_route_req *) req->request;
+ if (route_req) {
+ start_route_service(route_req->req_details, route_req->route_cb, route_req->requestId, route_req->user_data);
+
+ g_free(route_req);
+ route_req = NULL;
+ }
+ }
+
+ g_free(req);
+ req = NULL;
+ } else {
+ MAP_DEBUG("No request in queue or request type is wrong");
+ }
+ } else {
+ MAP_DEBUG("Libcurl request queue is FULL..");
+ }
+ }
+ break;
+
+ default:
+ MAP_DEBUG("UNKNOWN RESPONSE TYPE");
+ break;
+ }
+
+ __ResponseQueueLen = g_async_queue_length(responseQueue);
+
+ if (response) {
+ g_free(response);
+ response = NULL;
+ }
+ };
+
+ g_async_queue_unref(responseQueue);
+
+ __response_timer_running = false;
+
+ return false;
+}
+
+static void __free_geocode_response(void *ptr)
+{
+ MapquestGeocodeResponseData *geocodeData = (MapquestGeocodeResponseData *) (ptr);
+
+ if (geocodeData) {
+ GList *coords = NULL;
+ coords = g_list_first(geocodeData->coords);
+
+ while (coords) {
+ coords_s *data = (coords_s *) coords->data;
+
+ if (data) {
+ geocodeData->coords = g_list_remove(geocodeData->coords, (gpointer)data);
+
+ g_free(data);
+ data = NULL;
+ }
+ coords = g_list_first(geocodeData->coords);
+ }
+
+ g_list_free(geocodeData->coords);
+ geocodeData->coords = NULL;
+
+ if (geocodeData->user_data) {
+ g_free(geocodeData->user_data);
+ geocodeData->user_data = NULL;
+ }
+ }
+}
+
+static void __free_revgeocode_response(void *ptr)
+{
+ MapquestRevGeocodeResponseData *revGeocodeData = (MapquestRevGeocodeResponseData *) (ptr);
+ if (revGeocodeData) {
+ if (revGeocodeData->addressDetails) {
+ if (revGeocodeData->addressDetails->street_add) {
+ g_free(revGeocodeData->addressDetails->street_add);
+ revGeocodeData->addressDetails->street_add = NULL;
+ }
+ if (revGeocodeData->addressDetails->neighbourhood) {
+ g_free(revGeocodeData->addressDetails->neighbourhood);
+ revGeocodeData->addressDetails->neighbourhood = NULL;
+ }
+ if (revGeocodeData->addressDetails->city) {
+ g_free(revGeocodeData->addressDetails->city);
+ revGeocodeData->addressDetails->city = NULL;
+ }
+ if (revGeocodeData->addressDetails->county) {
+ g_free(revGeocodeData->addressDetails->county);
+ revGeocodeData->addressDetails->county = NULL;
+ }
+ if (revGeocodeData->addressDetails->state) {
+ g_free(revGeocodeData->addressDetails->state);
+ revGeocodeData->addressDetails->state = NULL;
+ }
+ if (revGeocodeData->addressDetails->country) {
+ g_free(revGeocodeData->addressDetails->country);
+ revGeocodeData->addressDetails->country = NULL;
+ }
+ if (revGeocodeData->addressDetails->country_code) {
+ g_free(revGeocodeData->addressDetails->country_code);
+ revGeocodeData->addressDetails->country_code = NULL;
+ }
+ if (revGeocodeData->addressDetails->postal_code) {
+ g_free(revGeocodeData->addressDetails->postal_code);
+ revGeocodeData->addressDetails->postal_code = NULL;
+ }
+
+ g_free(revGeocodeData->addressDetails);
+ revGeocodeData->addressDetails = NULL;
+ }
+
+ if (revGeocodeData->user_data) {
+ g_free(revGeocodeData->user_data);
+ revGeocodeData->user_data = NULL;
+ }
+ }
+}
+
+static void __free_place_response(void *ptr)
+{
+ MapquestPlaceResponseData *placeData = (MapquestPlaceResponseData *) (ptr);
+ if (placeData) {
+ GList *place = NULL;
+ place = g_list_first(placeData->places);
+
+ while (place) {
+ mapquest_place_resp_s *mapquest_place = (mapquest_place_resp_s *) place->data;
+
+ if (mapquest_place->address) {
+ if (mapquest_place->address->street_add) {
+ g_free(mapquest_place->address->street_add);
+ mapquest_place->address->street_add = NULL;
+ }
+ if (mapquest_place->address->neighbourhood) {
+ g_free(mapquest_place->address->neighbourhood);
+ mapquest_place->address->neighbourhood = NULL;
+ }
+ if (mapquest_place->address->building_number) {
+ g_free(mapquest_place->address->building_number);
+ mapquest_place->address->building_number = NULL;
+ }
+ if (mapquest_place->address->city) {
+ g_free(mapquest_place->address->city);
+ mapquest_place->address->city = NULL;
+ }
+ if (mapquest_place->address->county) {
+ g_free(mapquest_place->address->county);
+ mapquest_place->address->county = NULL;
+ }
+ if (mapquest_place->address->state) {
+ g_free(mapquest_place->address->state);
+ mapquest_place->address->state = NULL;
+ }
+ if (mapquest_place->address->country) {
+ g_free(mapquest_place->address->country);
+ mapquest_place->address->country = NULL;
+ }
+ if (mapquest_place->address->country_code) {
+ g_free(mapquest_place->address->country_code);
+ mapquest_place->address->country_code = NULL;
+ }
+ if (mapquest_place->address->postal_code) {
+ g_free(mapquest_place->address->postal_code);
+ mapquest_place->address->postal_code = NULL;
+ }
+ g_free(mapquest_place->address);
+ mapquest_place->address = NULL;
+ }
+
+ if (mapquest_place->category) {
+ g_free(mapquest_place->category);
+ mapquest_place->category = NULL;
+ }
+ if (mapquest_place->subcategory) {
+ g_free(mapquest_place->subcategory);
+ mapquest_place->subcategory = NULL;
+ }
+ if (mapquest_place->display_name) {
+ g_free(mapquest_place->display_name);
+ mapquest_place->display_name = NULL;
+ }
+
+ placeData->places = g_list_remove(placeData->places, (gpointer)mapquest_place);
+
+ g_free(mapquest_place);
+ mapquest_place = NULL;
+
+ place = g_list_first(placeData->places);
+ }
+ g_list_free(placeData->places);
+ placeData->places = NULL;
+
+ if (placeData->user_data) {
+ g_free(placeData->user_data);
+ placeData->user_data = NULL;
+ }
+ }
+}
+
+static void __free_route_response(void *ptr)
+{
+ MapquestRouteResponseData *routeData = (MapquestRouteResponseData *) (ptr);
+ if (routeData) {
+ mapquest_route_resp_s *route_info = routeData->routeResponse;
+ if (route_info) {
+ GList *maneuver_data = NULL;
+ maneuver_data = g_list_first(route_info->maneuvers);
+ while (maneuver_data) {
+ mapquest_route_maneuver *maneuver = (mapquest_route_maneuver *) maneuver_data->data;
+
+ if (maneuver->instruction) {
+ g_free(maneuver->instruction);
+ maneuver->instruction = NULL;
+ }
+ if (maneuver->formatted_time) {
+ g_free(maneuver->formatted_time);
+ maneuver->formatted_time = NULL;
+ }
+ if (maneuver->direction_name) {
+ g_free(maneuver->direction_name);
+ maneuver->direction_name = NULL;
+ }
+ if (maneuver->street_name) {
+ g_free(maneuver->street_name);
+ maneuver->street_name = NULL;
+ }
+
+ route_info->maneuvers = g_list_remove(route_info->maneuvers, (gpointer)maneuver);
+
+ g_free(maneuver);
+ maneuver = NULL;
+
+ /* Fetching the next item from Maneuver/Segment list */
+ maneuver_data = g_list_first(route_info->maneuvers);
+ }
+ g_list_free(route_info->maneuvers);
+ route_info->maneuvers = NULL;
+
+ GList *shapePoints = NULL;
+ shapePoints = g_list_first(route_info->shapePoints);
+ while (shapePoints) {
+ coords_s *data = (coords_s *) shapePoints->data;
+
+ route_info->shapePoints = g_list_remove(route_info->shapePoints, (gpointer)data);
+
+ g_free(data);
+ data = NULL;
+
+ shapePoints = g_list_first(route_info->shapePoints);
+ }
+ g_list_free(route_info->shapePoints);
+ route_info->shapePoints = NULL;
+
+ if (route_info->formatted_time) {
+ g_free(route_info->formatted_time);
+ route_info->formatted_time = NULL;
+ }
+ g_free(route_info);
+ route_info = NULL;
+ }
+ if (routeData->user_data) {
+ g_free(routeData->user_data);
+ routeData->user_data = NULL;
+ }
+ }
+}
+
+int mapquest_init_queue()
+{
+#if !GLIB_CHECK_VERSION(2, 35, 0)
+ g_type_init(); /* Needed for using json in Emulator */
+#endif
+
+ pthread_mutex_init(&__requestLock, NULL);
+
+ /* Queue initialize */
+ responseQueue = g_async_queue_new();
+
+ /* Initialise Curl Service */
+ int ret = init_curl();
+
+ if (ret != MAPQUEST_ERROR_NONE)
+ return MAPQUEST_ERROR_UNKNOWN;
+
+ pthread_mutex_lock(&__requestLock);
+ requestList = NULL;
+ pthread_mutex_unlock(&__requestLock);
+ reqCancelList = NULL;
+ __ResponseQueueLen = 0;
+ __response_timer_running = false;
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+int mapquest_deinit_queue()
+{
+ deinit_curl();
+
+ g_list_free(reqCancelList);
+ reqCancelList = NULL;
+
+ pthread_mutex_destroy(&__requestLock);
+
+ /* Free the queue */
+ if (responseQueue) {
+ g_async_queue_ref(responseQueue);
+ __ResponseQueueLen = g_async_queue_length(responseQueue);
+ MAP_DEBUG("Queue len : %d", __ResponseQueueLen);
+
+ while (__ResponseQueueLen > 0) {
+ gpointer data = g_async_queue_try_pop(responseQueue);
+ if (!data) {
+ __ResponseQueueLen = g_async_queue_length(responseQueue);
+ continue;
+ }
+
+ MapquestQueueData *response = (MapquestQueueData *) data;
+
+ switch (response->type) {
+ case RESP_TYPE_GEOCODE:
+ {
+ MapquestGeocodeResponseData *geocodeData = (MapquestGeocodeResponseData *) (response->data);
+ if (geocodeData) {
+ __free_geocode_response(geocodeData);
+
+ g_free(geocodeData);
+ geocodeData = NULL;
+ }
+ }
+ break;
+ case RESP_TYPE_REVGEOCODE:
+ {
+ MapquestRevGeocodeResponseData *revGeocodeData = (MapquestRevGeocodeResponseData *) (response->data);
+ if (revGeocodeData) {
+ __free_revgeocode_response(revGeocodeData);
+
+ g_free(revGeocodeData);
+ revGeocodeData = NULL;
+ }
+ }
+ break;
+ case RESP_TYPE_PLACES:
+ {
+ MapquestPlaceResponseData *placeData = (MapquestPlaceResponseData *) (response->data);
+ if (placeData != NULL) {
+ __free_place_response(placeData);
+
+ g_free(placeData);
+ placeData = NULL;
+ }
+ }
+ break;
+ case RESP_TYPE_ROUTE:
+ {
+ MapquestRouteResponseData *routeData = (MapquestRouteResponseData *) (response->data);
+ if (routeData != NULL) {
+ __free_route_response(routeData);
+
+ g_free(routeData);
+ routeData = NULL;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ __ResponseQueueLen = g_async_queue_length(responseQueue);
+
+ if (response) {
+ g_free(response);
+ response = NULL;
+ }
+ }
+ g_async_queue_unref(responseQueue);
+ responseQueue = NULL;
+ }
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+int mapquest_push_to_queue(mapquest_resp_type type, gpointer data)
+{
+ MAP_DEBUG("Pushing to Queue....");
+
+ MapquestQueueData *queueData = (MapquestQueueData *)g_malloc0(sizeof(MapquestQueueData));
+ if (!queueData) return MAPQUEST_ERROR_OUT_OF_MEMORY;
+
+ queueData->type = type;
+ queueData->data = data;
+
+ g_async_queue_ref(responseQueue);
+ g_async_queue_push(responseQueue, (gpointer)queueData);
+ g_async_queue_unref(responseQueue);
+
+ if (!__response_timer_running) {
+ MAP_DEBUG(">>>>>>>>>>>>>>>>>>>>>>> TRIGGER RESPONSE TIMER <<<<<<<<<<<<<<<<<<<<<<<<<");
+ g_timeout_add_seconds(1, __timeout_cb, NULL); /* timeout : 1 sec */
+ } else {
+ __ResponseQueueLen = g_async_queue_length(responseQueue);
+ MAP_DEBUG(">>>>>>>>>>>>>>>>>> Timer already running. Response Queue Len [%d] <<<<<<<<<<<<<<<<<", __ResponseQueueLen);
+ }
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+int start_geocode_service(mapquest_geocode_req_s *req_details, mapquest_geocode_cb callback, int request_id, void *user_data)
+{
+ int num_running_req = get_num_running_requests();
+
+ if (num_running_req >= CURL_MAX_CONNECTS) {
+ /* Add the request to queue */
+ add_to_geocode_list(req_details, callback, request_id, user_data);
+ } else {
+ MapquestGeocodeQueryData *queryData = (MapquestGeocodeQueryData *)g_malloc0(sizeof(MapquestGeocodeQueryData));
+
+ if (queryData != NULL) {
+ queryData->requestId = request_id;
+ queryData->geocode_cb = callback;
+ queryData->user_data = user_data;
+
+ if (req_details->boundary != NULL) {
+ if (req_details->boundary->type == MAPQUEST_BOUNDARY_RECT) {
+ MAP_DEBUG("TOP LEFT >>><<< LATITUDE : %f, LONGITUDE : %f", req_details->boundary->rect.top_left.latitude, req_details->boundary->rect.top_left.longitude);
+ MAP_DEBUG("BOTTOM RIGHT >>><<< LATITUDE : %f, LONGITUDE : %f", req_details->boundary->rect.bottom_right.latitude, req_details->boundary->rect.bottom_right.longitude);
+
+ query_geocode_within_bounds(req_details->maps_key, req_details->address, req_details->boundary->rect.top_left, req_details->boundary->rect.bottom_right, req_details->num_res, queryData);
+
+ } else if (req_details->boundary->type == MAPQUEST_BOUNDARY_CIRCLE) {
+
+ coords_s *top_left = NULL, *bottom_right = NULL;
+ coords_s circle = req_details->boundary->circle.center;
+ gdouble radius = (req_details->boundary->circle.radius) * 0.001;
+
+ MAP_DEBUG("User input LATITUDE : %f, LONGITUDE : %f", circle.latitude, circle.longitude);
+
+ /* Calculate the top left coordinate of bounding box. */
+ calculate_point(circle.latitude, circle.longitude, 315, radius, &top_left);
+
+ /* Calculate the bottom right coordinate of bounding box. */
+ calculate_point(circle.latitude, circle.longitude, 135, radius, &bottom_right);
+
+ if ((top_left != NULL) && (bottom_right != NULL)) {
+ MAP_DEBUG("Top Left LATITUDE : %f, LONGITUDE : %f", top_left->latitude, top_left->longitude);
+ MAP_DEBUG("Bottom Right LATITUDE : %f, LONGITUDE : %f", bottom_right->latitude, bottom_right->longitude);
+
+ query_geocode_within_bounds(req_details->maps_key, req_details->address, *top_left, *bottom_right, req_details->num_res, queryData);
+
+ g_free(top_left);
+ top_left = NULL;
+
+ g_free(bottom_right);
+ bottom_right = NULL;
+ }
+
+ } else {
+ query_geocode(req_details->maps_key, req_details->address, req_details->num_res, queryData);
+ }
+
+ } else {
+ MAP_DEBUG("BOUNDARY is NULL.. NORMAL GEOCODE QUERY WITHOUT BOUNDS");
+
+ query_geocode(req_details->maps_key, req_details->address, req_details->num_res, queryData);
+ }
+ }
+
+ if (req_details) {
+ if (req_details->address) {
+ g_free(req_details->address);
+ req_details->address = NULL;
+ }
+ if (req_details->maps_key) {
+ g_free(req_details->maps_key);
+ req_details->maps_key = NULL;
+ }
+ if (req_details->boundary) {
+ g_free(req_details->boundary);
+ req_details->boundary = NULL;
+ }
+ g_free(req_details);
+ req_details = NULL;
+ }
+ }
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+int start_reversegeocode_service(mapquest_revgeocode_req_s *req_details, mapquest_reverse_geocode_cb callback, int request_id, void *user_data)
+{
+ int num_running_req = get_num_running_requests();
+
+ if (num_running_req >= CURL_MAX_CONNECTS) {
+ /* Add the request to queue */
+ add_to_revgeocode_list(req_details, callback, request_id, user_data);
+ } else {
+ MapquestRevGeocodeQueryData *queryData = (MapquestRevGeocodeQueryData *)g_malloc0(sizeof(MapquestRevGeocodeQueryData));
+
+ if (queryData != NULL) {
+ queryData->requestId = request_id;
+ queryData->reverse_geocode_cb = callback;
+ queryData->user_data = user_data;
+
+ coords_s coords = req_details->coordinates;
+
+ query_revgeocode(req_details->maps_key, coords.latitude, coords.longitude, queryData);
+ }
+
+ if (req_details) {
+ if (req_details->maps_key) {
+ g_free(req_details->maps_key);
+ req_details->maps_key = NULL;
+ }
+ g_free(req_details);
+ req_details = NULL;
+ }
+ }
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+int start_route_service(mapquest_route_req_s *req_details, mapquest_route_cb callback, int request_id, void *user_data)
+{
+ int num_running_req = get_num_running_requests();
+
+ if (num_running_req >= CURL_MAX_CONNECTS) {
+ /* Add the request to queue */
+ add_to_route_list(req_details, callback, request_id, user_data);
+ } else {
+ MapquestRouteQueryData *queryData = (MapquestRouteQueryData *)g_malloc0(sizeof(MapquestRouteQueryData));
+
+ if (queryData != NULL) {
+ queryData->requestId = request_id;
+ queryData->route_cb = callback;
+ queryData->origin = req_details->from;
+ queryData->destination = req_details->to;
+ queryData->unit = req_details->unit;
+ queryData->user_data = user_data;
+
+ query_route(req_details->maps_key, req_details->from, req_details->to, req_details->type, req_details->avoids, req_details->driving_style, req_details->way_points, queryData);
+ }
+
+ if (req_details) {
+ if (req_details->maps_key) {
+ g_free(req_details->maps_key);
+ req_details->maps_key = NULL;
+ }
+ if (req_details->way_points) {
+ if (g_list_length(req_details->way_points) > 0) {
+ GList *list = NULL;
+ list = g_list_first(req_details->way_points);
+ while (list) {
+ coords_s *data = (coords_s *)list->data;
+ if (data) {
+ req_details->way_points = g_list_remove(req_details->way_points, (gpointer)data);
+
+ g_free(data);
+ data = NULL;
+ }
+ list = g_list_first(req_details->way_points);
+ }
+ }
+ g_list_free(req_details->way_points);
+ req_details->way_points = NULL;
+ }
+ g_free(req_details);
+ req_details = NULL;
+ }
+ }
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+int start_places_service(mapquest_search_req_s *req_details, mapquest_place_search_cb callback, int request_id, void *user_data)
+{
+ int num_running_req = get_num_running_requests();
+
+ if (num_running_req >= CURL_MAX_CONNECTS) {
+ /* Add the request to queue */
+ add_to_places_list(req_details, callback, request_id, user_data);
+ } else {
+ MapquestPlaceQueryData *queryData = (MapquestPlaceQueryData *)g_malloc0(sizeof(MapquestPlaceQueryData));
+
+ if (queryData != NULL) {
+ queryData->requestId = request_id;
+ queryData->place_search_cb = callback;
+ queryData->user_data = user_data;
+
+ query_places(req_details->maps_key, req_details->search_string, req_details->boundary, req_details->num_res, queryData);
+ }
+
+ if (req_details) {
+ if (req_details->maps_key) {
+ g_free(req_details->maps_key);
+ req_details->maps_key = NULL;
+ }
+ if (req_details->boundary) {
+ g_free(req_details->boundary);
+ req_details->boundary = NULL;
+ }
+ if (req_details->search_string) {
+ g_free(req_details->search_string);
+ req_details->search_string = NULL;
+ }
+ g_free(req_details);
+ req_details = NULL;
+ }
+ }
+
+ return MAPQUEST_ERROR_NONE;
+}
diff --git a/src/mapquest/mapquest_queue.h b/src/mapquest/mapquest_queue.h
new file mode 100644
index 0000000..587dbb6
--- /dev/null
+++ b/src/mapquest/mapquest_queue.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_QUEUE_H_
+#define _MAPQUEST_QUEUE_H_
+
+#include <glib.h>
+#include "mapquest_server_private.h"
+
+typedef struct {
+ mapquest_req_type type;
+ void *request;
+} mapquest_request_s;
+
+typedef struct {
+ mapquest_geocode_req_s *req_details;
+ int requestId;
+ mapquest_geocode_cb geocode_cb;
+ void *user_data;
+} mapquest_geocode_req;
+
+typedef struct {
+ mapquest_revgeocode_req_s *req_details;
+ int requestId;
+ mapquest_reverse_geocode_cb revgeocode_cb;
+ void *user_data;
+} mapquest_revgeocode_req;
+
+typedef struct {
+ mapquest_route_req_s *req_details;
+ mapquest_route_cb route_cb;
+ int requestId;
+ void *user_data;
+} mapquest_route_req;
+
+typedef struct {
+ mapquest_search_req_s *req_details;
+ mapquest_place_search_cb search_place_cb;
+ int requestId;
+ void *user_data;
+} mapquest_search_place_req;
+
+int add_to_geocode_list(mapquest_geocode_req_s *req_details, mapquest_geocode_cb callback, int request_id, void *user_data);
+int add_to_revgeocode_list(mapquest_revgeocode_req_s *req_details, mapquest_reverse_geocode_cb callback, int request_id, void *user_data);
+int add_to_route_list(mapquest_route_req_s *req_details, mapquest_route_cb callback, int request_id, void *user_data);
+int add_to_places_list(mapquest_search_req_s *req_details, mapquest_place_search_cb callback, int request_id, void *user_data);
+
+int remove_from_request_list(int request_id);
+
+int start_geocode_service(mapquest_geocode_req_s *req_details, mapquest_geocode_cb callback, int request_id, void *user_data);
+int start_reversegeocode_service(mapquest_revgeocode_req_s *req_details, mapquest_reverse_geocode_cb callback, int request_id, void *user_data);
+int start_route_service(mapquest_route_req_s *req_details, mapquest_route_cb callback, int request_id, void *user_data);
+int start_places_service(mapquest_search_req_s *req_details, mapquest_place_search_cb callback, int request_id, void *user_data);
+
+int mapquest_init_queue();
+int mapquest_deinit_queue();
+int mapquest_push_to_queue(mapquest_resp_type type, gpointer data);
+
+#endif /* _MAPQUEST_QUEUE_H_ */
diff --git a/src/mapquest/mapquest_restcurl.c b/src/mapquest/mapquest_restcurl.c
new file mode 100644
index 0000000..a8fccd3
--- /dev/null
+++ b/src/mapquest/mapquest_restcurl.c
@@ -0,0 +1,671 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <stdlib.h>
+#include <curl/curl.h>
+#include <curl/easy.h>
+#include <pthread.h>
+#include <network/net_connection.h>
+#include "mapquest_restcurl.h"
+#include "mapquest_types.h"
+#include "mapquest_jsonparser.h"
+#include "mapquest_debug.h"
+
+#define RESTCURL_USE_MULTI_CURL
+
+CURLM *__cm_handle;
+pthread_t __CurlThread;
+pthread_mutex_t __MultiCurlArgsLock;
+pthread_mutex_t __CmHandleLock;
+static bool __thread_running_for_curlmulti = false;
+static int __MultiCurlArgsRemain = 0;
+pthread_cond_t __curl_delivered_cond;
+pthread_mutex_t __curl_deliver_mutex;
+static char *__proxy_address = NULL;
+GList *__cancel_req_list = NULL;
+
+typedef struct {
+ char *memory;
+ size_t size;
+} MemoryStruct_s;
+
+struct MultiCurlArg {
+ MemoryStruct_s m_chunk;
+ CURL *curl_handle;
+ mapquest_req_type req_type;
+ int request_id;
+ void *user_data;
+ char url[1024];
+};
+
+/****************** LIST for maintaining easy curl related data *******************/
+
+struct MultiCurlArg_List {
+ struct MultiCurlArg *mcArg;
+ struct MultiCurlArg_List *next;
+};
+
+struct MultiCurlArg_List *head = NULL;
+struct MultiCurlArg_List *curr = NULL;
+
+static struct MultiCurlArg_List *__create_list(struct MultiCurlArg *mcArg)
+{
+ MAP_DEBUG("\n creating list with headnode as [%p]\n", mcArg);
+ struct MultiCurlArg_List *ptr = (struct MultiCurlArg_List *)g_malloc0(sizeof(struct MultiCurlArg_List));
+ if (NULL == ptr) {
+ MAP_DEBUG("\n Node creation failed \n");
+ return NULL;
+ }
+ ptr->mcArg = mcArg;
+ ptr->next = NULL;
+
+ head = curr = ptr;
+ return ptr;
+}
+
+static struct MultiCurlArg_List *__add_to_list(struct MultiCurlArg *mcArg, bool add_to_end)
+{
+ if (NULL == head)
+ return (__create_list(mcArg));
+
+ struct MultiCurlArg_List *ptr = (struct MultiCurlArg_List *)g_malloc0(sizeof(struct MultiCurlArg_List));
+ if (NULL == ptr) {
+ MAP_DEBUG("\n Node creation failed \n");
+ return NULL;
+ }
+ ptr->mcArg = mcArg;
+ ptr->next = NULL;
+
+ if (add_to_end) {
+ curr->next = ptr;
+ curr = ptr;
+ } else {
+ ptr->next = head;
+ head = ptr;
+ }
+ return ptr;
+}
+
+static struct MultiCurlArg_List *__search_in_list(CURL * handle, struct MultiCurlArg_List **prev)
+{
+ struct MultiCurlArg_List *ptr = head;
+ struct MultiCurlArg_List *tmp = NULL;
+ bool found = false;
+
+ MAP_DEBUG("\n Searching the list for value\n");
+
+ while (ptr != NULL) {
+ if (ptr->mcArg->curl_handle == handle) {
+ found = true;
+ break;
+ } else {
+ tmp = ptr;
+ ptr = ptr->next;
+ }
+ }
+
+ if (true == found) {
+ if (prev)
+ *prev = tmp;
+ return ptr;
+ } else {
+ return NULL;
+ }
+}
+
+static struct MultiCurlArg_List *__delete_from_list(CURL *handle)
+{
+ struct MultiCurlArg_List *prev = NULL;
+ struct MultiCurlArg_List *del = NULL;
+
+ MAP_DEBUG("\n Deleting value handle from list\n");
+
+ del = __search_in_list(handle, &prev);
+ if (del == NULL) {
+ return NULL;
+ } else {
+ if (prev != NULL)
+ prev->next = del->next;
+
+ if (del == curr) {
+ curr = prev;
+ if (prev == NULL)
+ head = NULL;
+ } else if (del == head) {
+ head = del->next;
+ }
+ }
+
+ del->next = NULL;
+
+ return del;
+}
+
+/*****************************************/
+
+mapquest_error_e __get_proxy_address()
+{
+ mapquest_error_e err = MAPQUEST_ERROR_NONE;
+
+ connection_h con = NULL;
+ int errorCode = CONNECTION_ERROR_NOT_SUPPORTED;
+ char *address = NULL;
+
+ errorCode = connection_create(&con);
+
+ if (errorCode == CONNECTION_ERROR_NONE)
+ errorCode = connection_get_proxy(con, CONNECTION_ADDRESS_FAMILY_IPV4, &address);
+
+ if (errorCode != CONNECTION_ERROR_NONE) {
+ err = MAPQUEST_ERROR_UNKNOWN;
+ switch (errorCode) {
+ case CONNECTION_ERROR_INVALID_PARAMETER:
+ MAP_DEBUG("Invalid parameter");
+ err = MAPQUEST_ERROR_INVALID_PARAMETER;
+ break;
+ case CONNECTION_ERROR_OUT_OF_MEMORY:
+ MAP_DEBUG("Out of memory error");
+ err = MAPQUEST_ERROR_OUT_OF_MEMORY;
+ break;
+ case CONNECTION_ERROR_INVALID_OPERATION:
+ MAP_DEBUG("Invalid Operation");
+ err = MAPQUEST_ERROR_INVALID_OPERATION;
+ break;
+ case CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
+ MAP_DEBUG("Address family not supported");
+ err = MAPQUEST_ERROR_NOT_SUPPORTED;
+ break;
+ /*
+ case CONNECTION_ERROR_PERMISSION_DENIED:
+ MAP_DEBUG("Permission denied");
+ err = MAPQUEST_ERROR_PERMISSION_DENIED;
+ break;
+ */
+ case CONNECTION_ERROR_OPERATION_FAILED:
+ MAP_DEBUG("Operation failed");
+ err = MAPQUEST_ERROR_INVALID_OPERATION;
+ break;
+ case CONNECTION_ERROR_ITERATOR_END:
+ MAP_DEBUG("End of iteration");
+ break;
+ case CONNECTION_ERROR_NO_CONNECTION:
+ MAP_DEBUG("There is no connection");
+ err = MAPQUEST_ERROR_NETWORK_UNREACHABLE;
+ break;
+ case CONNECTION_ERROR_NOW_IN_PROGRESS:
+ MAP_DEBUG("Now in progress");
+ err = MAPQUEST_ERROR_RESOURCE_BUSY;
+ break;
+ case CONNECTION_ERROR_ALREADY_EXISTS:
+ MAP_DEBUG("Already exists");
+ break;
+ case CONNECTION_ERROR_OPERATION_ABORTED:
+ MAP_DEBUG("Operation is aborted");
+ err = MAPQUEST_ERROR_CANCELED;
+ break;
+ case CONNECTION_ERROR_DHCP_FAILED:
+ MAP_DEBUG("DHCP failed");
+ break;
+ case CONNECTION_ERROR_INVALID_KEY:
+ MAP_DEBUG("Invalid key");
+ err = MAPQUEST_ERROR_KEY_NOT_AVAILABLE;
+ break;
+ case CONNECTION_ERROR_NO_REPLY:
+ MAP_DEBUG("No reply");
+ err = MAPQUEST_ERROR_RESOURCE_BUSY;
+ break;
+ case CONNECTION_ERROR_NOT_SUPPORTED:
+ MAP_DEBUG("Not Supported");
+ err = MAPQUEST_ERROR_NOT_SUPPORTED;
+ break;
+ default:
+ MAP_DEBUG("Unknown");
+ break;
+ }
+ MAP_DEBUG("errorCode = %ld", (long)errorCode);
+ }
+
+ if (con)
+ connection_destroy(con);
+
+ if (err != MAPQUEST_ERROR_NONE)
+ return err;
+
+ if (address) {
+ int len = strlen(address);
+ if (len > 0) {
+ __proxy_address = (char *)g_malloc0(len+1);
+ strncpy(__proxy_address, address, len);
+ __proxy_address[len] = '\0';
+ }
+ g_free(address);
+ address = NULL;
+ }
+
+ MAP_DEBUG("Proxy = %s", (__proxy_address ? __proxy_address : "(null)"));
+
+ return MAPQUEST_ERROR_NONE;
+}
+
+static size_t __write_memory_callback(void *contents, size_t size, size_t nmemb, void *userp)
+{
+ size_t realsize = size * nmemb;
+#ifdef RESTCURL_USE_MULTI_CURL
+ MemoryStruct_s *mem = &(((struct MultiCurlArg *) userp)->m_chunk);
+#else
+ MemoryStruct_s *mem = (MemoryStruct_s *) userp;
+#endif
+
+ if (mem->memory == NULL)
+ mem->memory = g_malloc(realsize);
+ else
+ mem->memory = g_realloc(mem->memory, mem->size + realsize);
+
+ if (mem->memory == NULL)
+ return 0;
+
+ memcpy(mem->memory + mem->size, contents, realsize);
+
+ mem->size += realsize;
+
+ MAP_DEBUG("REal size : %d", realsize);
+ MAP_DEBUG("response size :: %d", strlen(mem->memory));
+
+ return realsize;
+}
+
+static int __xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
+{
+ struct MultiCurlArg *pMultiCurlArg = (struct MultiCurlArg *) p;
+
+ GList *list = NULL;
+ list = g_list_first(__cancel_req_list);
+ int req_id_to_be_cancelled = -1;
+ bool cancel_request = false;
+
+ while (list) {
+ req_id_to_be_cancelled = (int) list->data;
+ MAP_DEBUG("Req id in the list waiting to get cancelled [%d]", req_id_to_be_cancelled);
+ if (pMultiCurlArg->request_id == req_id_to_be_cancelled) {
+ MAP_DEBUG(">>>>>>>>>>>> Req id matched :: To be cancelled [%d]", req_id_to_be_cancelled);
+ cancel_request = true;
+ break;
+ }
+ list = list->next;
+ }
+
+ if (cancel_request) {
+ MAP_DEBUG(">>>>>>>> Req Id to be aborted :: [%d] <<<<<<<<<<<<<", req_id_to_be_cancelled);
+ /* Remove the request id from cancel list */
+ __cancel_req_list = g_list_remove(__cancel_req_list, (gpointer)req_id_to_be_cancelled);
+ MAP_DEBUG(">>>>>>>>>> Request removed from cancel list <<<<<<<<");
+ return 1; /* Returning Non-Zero value will abort the transfer */
+ }
+
+ return 0;
+}
+
+static int __progress_info(void *p, double dltotal, double dlnow, double ultotal, double ulnow)
+{
+ return __xferinfo(p, (curl_off_t)dltotal, (curl_off_t)dlnow, (curl_off_t)ultotal, (curl_off_t)ulnow);
+}
+
+int add_handle(char *url, mapquest_req_type type, void *user_data)
+{
+ if (!url || !user_data) return -1;
+
+ int req_id = -1;
+
+ switch (type) {
+ case REQ_TYPE_GEOCODE:
+ req_id = ((MapquestGeocodeQueryData *) user_data)->requestId;
+ break;
+ case REQ_TYPE_REVGEOCODE:
+ req_id = ((MapquestRevGeocodeQueryData *) user_data)->requestId;
+ break;
+ case REQ_TYPE_PLACES:
+ req_id = ((MapquestRouteQueryData *) user_data)->requestId;
+ break;
+ case REQ_TYPE_ROUTE:
+ req_id = ((MapquestPlaceQueryData *) user_data)->requestId;
+ break;
+ default:
+ break;
+ }
+
+#ifdef RESTCURL_USE_MULTI_CURL
+ MAP_DEBUG("HTTP Req URL [%s]", url);
+ CURL *curl_handle;
+
+ struct MultiCurlArg *pMultiCurlArg = (struct MultiCurlArg *)g_malloc0(sizeof(struct MultiCurlArg));
+
+ if (!pMultiCurlArg) return -1;
+
+ (pMultiCurlArg->m_chunk).memory = (char *) g_malloc0(1); /* will be grown as needed by the realloc above */
+ (pMultiCurlArg->m_chunk).size = 0; /* no data at this point */
+
+ /* init the curl session */
+ curl_handle = curl_easy_init();
+
+ /* set URL to get */
+ curl_easy_setopt(curl_handle, CURLOPT_URL, url);
+
+ curl_easy_setopt(curl_handle, CURLOPT_PROGRESSFUNCTION, __progress_info);
+ curl_easy_setopt(curl_handle, CURLOPT_PROGRESSDATA, NULL);
+
+#if LIBCURL_VERSION_NUM >= 0x72000
+ curl_easy_setopt(curl_handle, CURLOPT_XFERINFOFUNCTION, __xferinfo);
+ curl_easy_setopt(curl_handle, CURLOPT_XFERINFODATA, (void *)pMultiCurlArg);
+#endif
+
+ curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 0L);
+
+ curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
+
+ curl_easy_setopt(curl_handle, CURLOPT_PROXY , __proxy_address);
+
+ /* send all data to this function */
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, __write_memory_callback);
+
+ /* we want the headers to this file handle */
+ curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)pMultiCurlArg);
+
+ /* some servers don't like requests that are made without a user-agent field, so we provide one */
+ curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
+
+ pMultiCurlArg->curl_handle = curl_handle;
+ pMultiCurlArg->req_type = type;
+ pMultiCurlArg->request_id = req_id;
+ pMultiCurlArg->user_data = user_data;
+ strncpy(pMultiCurlArg->url, url, sizeof(pMultiCurlArg->url)-1);
+
+ pthread_mutex_lock(&__MultiCurlArgsLock);
+ __MultiCurlArgsRemain++;
+ __add_to_list(pMultiCurlArg, true);
+ pthread_mutex_unlock(&__MultiCurlArgsLock);
+
+ pthread_mutex_lock(&__CmHandleLock);
+ curl_multi_add_handle(__cm_handle, curl_handle);
+ pthread_mutex_unlock(&__CmHandleLock);
+
+ pthread_mutex_lock(&__curl_deliver_mutex);
+ pthread_cond_signal(&__curl_delivered_cond);
+ pthread_mutex_unlock(&__curl_deliver_mutex);
+#endif
+ return 0;
+}
+
+static void __post_curl(mapquest_req_type type, MemoryStruct_s *m_chunk, void *user_data)
+{
+ mapquest_resp_type resp_type = RESP_TYPE_NONE;
+ switch (type) {
+ case REQ_TYPE_GEOCODE:
+ resp_type = RESP_TYPE_GEOCODE;
+ break;
+ case REQ_TYPE_REVGEOCODE:
+ resp_type = RESP_TYPE_REVGEOCODE;
+ break;
+ case REQ_TYPE_PLACES:
+ resp_type = RESP_TYPE_PLACES;
+ break;
+ case REQ_TYPE_ROUTE:
+ resp_type = RESP_TYPE_ROUTE;
+ break;
+ default:
+ resp_type = RESP_TYPE_NONE;
+ break;
+ }
+
+ post_curl_response(m_chunk->memory, m_chunk->size, resp_type, user_data);
+}
+
+static void *__curl_thread_handler(void *user_data)
+{
+ __thread_running_for_curlmulti = true;
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+
+#ifdef RESTCURL_USE_MULTI_CURL
+ CURLMsg *msg;
+ int Q;
+ int still_running = -1;
+
+ while (__thread_running_for_curlmulti || __MultiCurlArgsRemain) {
+ while (__MultiCurlArgsRemain) {
+ pthread_mutex_lock(&__CmHandleLock);
+ curl_multi_perform(__cm_handle, &still_running);
+ pthread_mutex_unlock(&__CmHandleLock);
+
+ if (still_running != __MultiCurlArgsRemain) {
+ pthread_mutex_lock(&__CmHandleLock);
+ msg = curl_multi_info_read(__cm_handle, &Q);
+ pthread_mutex_unlock(&__CmHandleLock);
+
+ if (msg == 0)
+ break;
+
+ if (msg->msg == CURLMSG_DONE) {
+ MAP_DEBUG("Transfer completed for one handle");
+ CURL *e = msg->easy_handle;
+
+ pthread_mutex_lock(&__MultiCurlArgsLock);
+ struct MultiCurlArg_List *del = NULL;
+ if ((del = __delete_from_list(e)) != NULL) {
+ MAP_DEBUG("Decrementing the handle counter in multiCurl..");
+ __MultiCurlArgsRemain--;
+ }
+ pthread_mutex_unlock(&__MultiCurlArgsLock);
+
+ if (del && del->mcArg) {
+ MAP_DEBUG("HTTP Url [%s]", del->mcArg->url);
+ MAP_DEBUG("Posting the result..");
+ __post_curl(del->mcArg->req_type, &(del->mcArg->m_chunk), del->mcArg->user_data);
+
+ if ((del->mcArg->m_chunk).memory) {
+ g_free((del->mcArg->m_chunk).memory);
+ (del->mcArg->m_chunk).memory = NULL;
+ }
+
+ pthread_mutex_lock(&__CmHandleLock);
+ curl_multi_remove_handle(__cm_handle, del->mcArg->curl_handle);
+ pthread_mutex_unlock(&__CmHandleLock);
+
+ curl_easy_cleanup(del->mcArg->curl_handle);
+
+ g_free(del->mcArg);
+ del->mcArg = NULL;
+
+ g_free(del);
+ del = NULL;
+ }
+ } else {
+ MAP_DEBUG("E: CURLMsg (%d)\n", msg->msg);
+ }
+ }
+ }
+
+ if (__thread_running_for_curlmulti && !__MultiCurlArgsRemain) {
+ pthread_mutex_lock(&__curl_deliver_mutex);
+ pthread_cond_wait(&__curl_delivered_cond, &__curl_deliver_mutex);
+ pthread_mutex_unlock(&__curl_deliver_mutex);
+ }
+ }
+
+#else
+ /* curl_easy_perform */
+#endif
+ pthread_exit(NULL);
+
+ return 0;
+}
+
+void cancel_request(int request_id)
+{
+ if (__cancel_req_list == NULL)
+ __cancel_req_list = g_list_append(__cancel_req_list, (gpointer)request_id);
+ else
+ __cancel_req_list = g_list_insert_before(__cancel_req_list, NULL, (gpointer)request_id);
+}
+
+int get_num_running_requests()
+{
+ MAP_DEBUG("Num of running requests :: >>>> [%d]", __MultiCurlArgsRemain);
+ return __MultiCurlArgsRemain;
+}
+
+int init_curl()
+{
+ __cancel_req_list = NULL;
+
+ head = NULL;
+ curr = NULL;
+
+ __get_proxy_address();
+
+#ifdef RESTCURL_USE_MULTI_CURL
+ pthread_mutex_init(&__MultiCurlArgsLock, NULL);
+ pthread_mutex_init(&__CmHandleLock, NULL);
+ pthread_mutex_init(&__curl_deliver_mutex, NULL);
+ pthread_cond_init(&__curl_delivered_cond, NULL);
+
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ __cm_handle = curl_multi_init();
+ curl_multi_setopt(__cm_handle, CURLMOPT_MAXCONNECTS, (long)CURL_MAX_CONNECTS);
+
+ __MultiCurlArgsRemain = 0;
+ int ret = pthread_create(&__CurlThread, NULL, &__curl_thread_handler, NULL);
+ __thread_running_for_curlmulti = true;
+#endif
+
+ return ret;
+}
+
+int deinit_curl()
+{
+#ifdef RESTCURL_USE_MULTI_CURL
+ __thread_running_for_curlmulti = false;
+ __MultiCurlArgsRemain = 0;
+
+ pthread_mutex_lock(&__curl_deliver_mutex);
+ pthread_cond_signal(&__curl_delivered_cond);
+ pthread_mutex_unlock(&__curl_deliver_mutex);
+
+ pthread_cancel(__CurlThread);
+
+ pthread_join(__CurlThread, NULL);
+
+ curl_multi_cleanup(__cm_handle);
+ curl_global_cleanup();
+
+ pthread_mutex_destroy(&__MultiCurlArgsLock);
+ pthread_mutex_destroy(&__CmHandleLock);
+ pthread_cond_destroy(&__curl_delivered_cond);
+ pthread_mutex_destroy(&__curl_deliver_mutex);
+#endif
+
+ if (__proxy_address) {
+ g_free(__proxy_address);
+ __proxy_address = NULL;
+ }
+
+ struct MultiCurlArg_List *temp = head;
+ struct MultiCurlArg_List *next;
+
+ while (temp) {
+ next = temp->next;
+ struct MultiCurlArg *curlArg = temp->mcArg;
+
+ if (curlArg) {
+ if ((curlArg->m_chunk).memory) {
+ g_free((curlArg->m_chunk).memory);
+ (curlArg->m_chunk).memory = NULL;
+ }
+
+ if (curlArg->user_data) {
+ switch (curlArg->req_type) {
+ case REQ_TYPE_GEOCODE:
+ {
+ MapquestGeocodeQueryData *queryData = (MapquestGeocodeQueryData *)curlArg->user_data;
+ if (queryData) {
+ if (queryData->user_data) {
+ g_free(queryData->user_data);
+ queryData->user_data = NULL;
+ }
+ g_free(queryData);
+ queryData = NULL;
+ }
+ }
+ break;
+ case REQ_TYPE_REVGEOCODE:
+ {
+ MapquestRevGeocodeQueryData *queryData = (MapquestRevGeocodeQueryData *)curlArg->user_data;
+ if (queryData) {
+ if (queryData->user_data) {
+ g_free(queryData->user_data);
+ queryData->user_data = NULL;
+ }
+ g_free(queryData);
+ queryData = NULL;
+ }
+ }
+ break;
+ case REQ_TYPE_PLACES:
+ {
+ MapquestPlaceQueryData *queryData = (MapquestPlaceQueryData *)curlArg->user_data;
+ if (queryData) {
+ if (queryData->user_data) {
+ g_free(queryData->user_data);
+ queryData->user_data = NULL;
+ }
+ g_free(queryData);
+ queryData = NULL;
+ }
+ }
+ break;
+ case REQ_TYPE_ROUTE:
+ {
+ MapquestRouteQueryData *queryData = (MapquestRouteQueryData *)curlArg->user_data;
+ if (queryData) {
+ if (queryData->user_data) {
+ g_free(queryData->user_data);
+ queryData->user_data = NULL;
+ }
+ g_free(queryData);
+ queryData = NULL;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ curl_easy_cleanup(curlArg->curl_handle);
+
+ g_free(curlArg);
+ curlArg = NULL;
+ }
+ g_free(temp);
+
+ temp = next;
+ }
+ head = NULL;
+
+ g_list_free(__cancel_req_list);
+ __cancel_req_list = NULL;
+
+ return 0;
+}
diff --git a/src/mapquest/mapquest_restcurl.h b/src/mapquest/mapquest_restcurl.h
new file mode 100644
index 0000000..b1d5a2a
--- /dev/null
+++ b/src/mapquest/mapquest_restcurl.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_RESTCURL_H_
+#define _MAPQUEST_RESTCURL_H_
+
+#include "mapquest_server_private.h"
+
+#define CURL_MAX_CONNECTS 30
+
+int init_curl();
+
+int deinit_curl();
+
+int get_num_running_requests();
+
+int add_handle(char *url, mapquest_req_type type, void *user_data);
+
+void cancel_request(int request_id);
+
+#endif /* _MAPQUEST_RESTCURL_H_ */
diff --git a/src/mapquest/mapquest_revgeocode.c b/src/mapquest/mapquest_revgeocode.c
new file mode 100644
index 0000000..246bee6
--- /dev/null
+++ b/src/mapquest/mapquest_revgeocode.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <stdio.h>
+#include <glib.h>
+#include <pthread.h>
+#include "mapquest_revgeocode.h"
+#include "mapquest_types.h"
+#include "mapquest_server_private.h"
+#include "mapquest_debug.h"
+#include "mapquest_queue.h"
+#include "mapquest_restcurl.h"
+
+#define REVERSE_GEOCODE_URL "https://open.mapquestapi.com/geocoding/v1/reverse?key=%s&outFormat=json"
+
+int query_revgeocode(gchar *maps_key, gdouble latitude, gdouble longitude, gpointer user_data)
+{
+ char url[1024];
+ char tmpStr[512];
+
+ if (maps_key != NULL)
+ snprintf(tmpStr, sizeof(tmpStr), REVERSE_GEOCODE_URL, maps_key);
+ else
+ snprintf(tmpStr, sizeof(tmpStr), REVERSE_GEOCODE_URL, "null");
+
+ strcpy(url, tmpStr);
+
+ snprintf(tmpStr, sizeof(tmpStr), "&location=%f,%f", latitude, longitude);
+ strcat(url, tmpStr);
+
+ add_handle(url, REQ_TYPE_REVGEOCODE, user_data);
+
+ return 0;
+}
diff --git a/src/mapquest/mapquest_revgeocode.h b/src/mapquest/mapquest_revgeocode.h
new file mode 100644
index 0000000..d337733
--- /dev/null
+++ b/src/mapquest/mapquest_revgeocode.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_REVGEOCODE_H_
+#define _MAPQUEST_REVGEOCODE_H_
+
+#include "mapquest_api.h"
+#include "mapquest_types.h"
+
+int query_revgeocode(gchar *maps_key, gdouble latitude, gdouble longitude, gpointer user_data);
+
+#endif /* _MAPQUEST_REVGEOCODE_H_ */
diff --git a/src/mapquest/mapquest_route.c b/src/mapquest/mapquest_route.c
new file mode 100644
index 0000000..a4ec225
--- /dev/null
+++ b/src/mapquest/mapquest_route.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <stdio.h>
+#include <glib.h>
+#include <pthread.h>
+#include "mapquest_route.h"
+#include "mapquest_types.h"
+#include "mapquest_server_private.h"
+#include "mapquest_debug.h"
+#include "mapquest_queue.h"
+#include "mapquest_restcurl.h"
+
+#define ROUTE_URL "https://open.mapquestapi.com/directions/v2/route?key=%s&ambiguities=ignore&outFormat=json&shapeFormat=raw&generalize=0"
+
+int query_route(gchar *maps_key, coords_s startPoint, coords_s endPoint, route_type type, route_feature_avoids avoids, route_driving_style style, GList *waypoints, gpointer user_data)
+{
+ char url[1024];
+ char tmpStr[512];
+
+ if (maps_key != NULL)
+ snprintf(tmpStr, sizeof(tmpStr), ROUTE_URL, maps_key);
+ else
+ snprintf(tmpStr, sizeof(tmpStr), ROUTE_URL, "null");
+
+ strcpy(url, tmpStr);
+
+ strcat(url, "&unit=m"); /* Keeping default as miles and conversion will be done later */
+
+ if (type == ROUTE_TYPE_FASTEST)
+ strcat(url, "&routeType=fastest");
+ else if (type == ROUTE_TYPE_SHORTEST)
+ strcat(url, "&routeType=shortest");
+ else if (type == ROUTE_TYPE_PEDESTRIAN)
+ strcat(url, "&routeType=pedestrian");
+ else if (type == ROUTE_TYPE_MULTIMODAL)
+ strcat(url, "&routeType=multimodal");
+ else if (type == ROUTE_TYPE_BICYCLE)
+ strcat(url, "&routeType=bicycle");
+
+ if (avoids == ROUTE_AVOID_LIMITED_ACCESS)
+ strcat(url, "&avoids=Limited Access");
+ else if (avoids == ROUTE_AVOID_TOLL_ROAD)
+ strcat(url, "&avoids=Tollroad");
+ else if (avoids == ROUTE_AVOID_FERRY)
+ strcat(url, "&avoids=Ferry");
+ else if (avoids == ROUTE_AVOID_UNPAVED)
+ strcat(url, "&avoids=Unpaved");
+ else if (avoids == ROUTE_AVOID_SEASONAL_CLOSURE)
+ strcat(url, "&avoids=Approximate Seasonal Closure");
+ else if (avoids == ROUTE_AVOID_COUNTRY_BORDER_CROSSING)
+ strcat(url, "&avoids=Country border crossing");
+
+ if (style == DRIVING_STYLE_NORMAL)
+ strcat(url, "&drivingStyle=2");
+ else if (style == DRIVING_STYLE_CAUTIOUS)
+ strcat(url, "&drivingStyle=1");
+ else if (style == DRIVING_STYLE_AGGRESSIVE)
+ strcat(url, "&drivingStyle=3");
+
+ int length = g_list_length(waypoints);
+ if (length != 0) {
+ int index = 0;
+ GList *waypoints_list = NULL;
+ waypoints_list = g_list_first(waypoints);
+
+ while (waypoints_list) {
+
+ coords_s *data = (coords_s *) waypoints_list->data;
+
+ if (data) {
+ if (index == 0)
+ snprintf(tmpStr, sizeof(tmpStr), "&from=%f,%f", data->latitude, data->longitude);
+ else
+ snprintf(tmpStr, sizeof(tmpStr), "&to=%f,%f", data->latitude, data->longitude);
+ strcat(url, tmpStr);
+ }
+
+ waypoints_list = g_list_next(waypoints_list);
+ index++;
+ }
+ } else {
+ snprintf(tmpStr, sizeof(tmpStr), "&from=%f,%f", startPoint.latitude, startPoint.longitude);
+ strcat(url, tmpStr);
+
+ snprintf(tmpStr, sizeof(tmpStr), "&to=%f,%f", endPoint.latitude, endPoint.longitude);
+ strcat(url, tmpStr);
+ }
+
+ add_handle(url, REQ_TYPE_ROUTE, user_data);
+
+ return 0;
+}
diff --git a/src/mapquest/mapquest_route.h b/src/mapquest/mapquest_route.h
new file mode 100644
index 0000000..8a71d07
--- /dev/null
+++ b/src/mapquest/mapquest_route.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_ROUTE_H_
+#define _MAPQUEST_ROUTE_H_
+
+#include "mapquest_api.h"
+#include "mapquest_types.h"
+
+int query_route(gchar *maps_key, coords_s startPoint, coords_s endPoint, route_type type, route_feature_avoids avoids, route_driving_style style, GList *waypoints, gpointer user_data);
+
+#endif /* _MAPQUEST_ROUTE_H_ */
diff --git a/src/mapquest/mapquest_server_private.h b/src/mapquest/mapquest_server_private.h
new file mode 100644
index 0000000..cba948f
--- /dev/null
+++ b/src/mapquest/mapquest_server_private.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_PRIVATE_H_
+#define _MAPQUEST_PRIVATE_H_
+
+#include "mapquest_api.h"
+
+typedef enum {
+ REQ_TYPE_GEOCODE = 0,
+ REQ_TYPE_REVGEOCODE,
+ REQ_TYPE_PLACES,
+ REQ_TYPE_ROUTE,
+ REQ_TYPE_NONE
+} mapquest_req_type;
+
+typedef enum {
+ RESP_TYPE_GEOCODE = 0,
+ RESP_TYPE_REVGEOCODE,
+ RESP_TYPE_PLACES,
+ RESP_TYPE_ROUTE,
+ RESP_TYPE_NONE
+} mapquest_resp_type;
+
+typedef struct {
+ int requestId;
+ mapquest_geocode_cb geocode_cb;
+ void *user_data;
+} MapquestGeocodeQueryData;
+
+typedef struct {
+ int requestId;
+ mapquest_reverse_geocode_cb reverse_geocode_cb;
+ void *user_data;
+} MapquestRevGeocodeQueryData;
+
+typedef struct {
+ int requestId;
+ mapquest_route_cb route_cb;
+ coords_s origin;
+ coords_s destination;
+ route_unit unit;
+ void *user_data;
+} MapquestRouteQueryData;
+
+typedef struct {
+ int requestId;
+ mapquest_place_search_cb place_search_cb;
+ void *user_data;
+} MapquestPlaceQueryData;
+
+typedef struct {
+ mapquest_error_e error;
+ int requestId;
+ mapquest_geocode_cb geocode_cb;
+ GList *coords;
+ void *user_data;
+} MapquestGeocodeResponseData;
+
+typedef struct {
+ mapquest_error_e error;
+ int requestId;
+ mapquest_reverse_geocode_cb reverse_geocode_cb;
+ mapquest_address_resp_s *addressDetails;
+ void *user_data;
+} MapquestRevGeocodeResponseData;
+
+typedef struct {
+ mapquest_error_e error;
+ int requestId;
+ mapquest_route_cb route_cb;
+ mapquest_route_resp_s *routeResponse;
+ void *user_data;
+} MapquestRouteResponseData;
+
+typedef struct {
+ mapquest_error_e error;
+ int requestId;
+ mapquest_place_search_cb place_search_cb;
+ GList *places;
+ void *user_data;
+} MapquestPlaceResponseData;
+
+typedef struct {
+ mapquest_resp_type type;
+ void *data;
+} MapquestQueueData;
+
+#endif /* _MAPQUEST_PRIVATE_H_ */
diff --git a/src/mapquest/mapquest_types.h b/src/mapquest/mapquest_types.h
new file mode 100644
index 0000000..79ce1fc
--- /dev/null
+++ b/src/mapquest/mapquest_types.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_TYPES_H_
+#define _MAPQUEST_TYPES_H_
+
+#include <glib.h>
+
+typedef enum {
+ MAPQUEST_ERROR_NONE = 0, /**< Successful */
+ MAPQUEST_ERROR_PERMISSION_DENIED, /**< Permission Denied */
+ MAPQUEST_ERROR_OUT_OF_MEMORY, /**< Out of memory */
+ MAPQUEST_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+ MAPQUEST_ERROR_NOT_SUPPORTED, /**< Not supported */
+ MAPQUEST_ERROR_CONNECTION_TIMED_OUT, /**< Timeout error, no answer */
+ MAPQUEST_ERROR_NETWORK_UNREACHABLE, /**< Network unavailable */
+ MAPQUEST_ERROR_INVALID_OPERATION, /**< Opeartion is not valid */
+ MAPQUEST_ERROR_KEY_NOT_AVAILABLE, /**< Invalid key */
+ MAPQUEST_ERROR_RESOURCE_BUSY, /**< Resource busy */
+ MAPQUEST_ERROR_CANCELED, /**< Service canceled */
+ MAPQUEST_ERROR_UNKNOWN, /**< Unknown error */
+ MAPQUEST_ERROR_SERVICE_NOT_AVAILABLE, /**< Service unavailabe*/
+ MAPQUEST_ERROR_NOT_FOUND, /**< Result not found */
+} mapquest_error_e;
+
+typedef enum {
+ MAPQUEST_BOUNDARY_NONE = 0, /* Undefined geographical area type. */
+ MAPQUEST_BOUNDARY_RECT, /* Rectangular geographical area type. */
+ MAPQUEST_BOUNDARY_CIRCLE, /* Circle geographical area type. */
+} boundary_type;
+
+typedef enum {
+ ROUTE_TYPE_FASTEST = 0,
+ ROUTE_TYPE_SHORTEST,
+ ROUTE_TYPE_PEDESTRIAN,
+ ROUTE_TYPE_MULTIMODAL,
+ ROUTE_TYPE_BICYCLE
+} route_type;
+
+typedef enum {
+ ROUTE_UNIT_M = 0, /* for Meter */
+ ROUTE_UNIT_KM, /* for Kilometer */
+ ROUTE_UNIT_FT, /* for Foot */
+ ROUTE_UNIT_YD /*for Yard */
+} route_unit;
+
+typedef enum {
+ ROUTE_AVOID_NONE = 0,
+ ROUTE_AVOID_LIMITED_ACCESS,
+ ROUTE_AVOID_TOLL_ROAD,
+ ROUTE_AVOID_FERRY,
+ ROUTE_AVOID_UNPAVED,
+ ROUTE_AVOID_SEASONAL_CLOSURE,
+ ROUTE_AVOID_COUNTRY_BORDER_CROSSING
+} route_feature_avoids;
+
+typedef enum {
+ DRIVING_STYLE_NORMAL = 0,
+ DRIVING_STYLE_CAUTIOUS,
+ DRIVING_STYLE_AGGRESSIVE
+} route_driving_style;
+
+typedef struct {
+ gdouble latitude;
+ gdouble longitude;
+} coords_s;
+
+typedef struct {
+ coords_s top_left;
+ coords_s bottom_right;
+} rectangle_s;
+
+typedef struct {
+ coords_s center;
+ gdouble radius;
+} circle_s;
+
+typedef struct {
+ boundary_type type;
+ union {
+ rectangle_s rect;
+ circle_s circle;
+ };
+} mapquest_boundary_s;
+
+typedef struct {
+ gchar *maps_key;
+ gchar *address;
+ mapquest_boundary_s *boundary;
+ gint num_res;
+} mapquest_geocode_req_s;
+
+typedef struct {
+ gchar *maps_key;
+ gint num_res;
+ coords_s coordinates;
+} mapquest_revgeocode_req_s;
+
+typedef struct {
+ gchar *maps_key;
+ gchar *search_string;
+ gint num_res;
+ gchar *country_code;
+ mapquest_boundary_s *boundary;
+ GList *excludes;
+} mapquest_search_req_s;
+
+typedef struct {
+ gchar *maps_key;
+ coords_s from;
+ coords_s to;
+ route_unit unit;
+ route_type type;
+ route_feature_avoids avoids; /* List of type strings. (Limited Access, Toll Road, Ferry, Unpaved, Seasonal Closure, Country Crossing) */
+ route_driving_style driving_style; /* (1 - cautious, 2 - normal, 3 - aggressive) */
+ GList *way_points; /* List of type coords_s */
+} mapquest_route_req_s;
+
+typedef struct {
+ gint zoom_level;
+ coords_s center_coords;
+} mapquest_tiledata_req_s;
+
+typedef struct {
+ gchar *street_add;
+ gchar *neighbourhood;
+ gchar *building_number;
+ gchar *city;
+ gchar *county;
+ gchar *state;
+ gchar *country;
+ gchar *country_code;
+ gchar *postal_code;
+} mapquest_address_resp_s;
+
+typedef struct {
+ gchar *place_id;
+ gchar *display_name;
+ mapquest_address_resp_s *address;
+ rectangle_s bounding_box;
+ coords_s coordinates;
+ gchar *category;
+ gchar *subcategory;
+ gchar *icon_url;
+} mapquest_place_resp_s;
+
+typedef struct {
+ guint type;
+ guint direction;
+ guint text;
+ gchar *icon_url;
+} mapquest_route_maneuver_signs;
+
+typedef struct {
+ coords_s start_point;
+ coords_s end_point;
+ gdouble distance;
+ guint time;
+ gchar *formatted_time;
+ guint attribute;
+ guint turn_type;
+ guint direction;
+ gchar *instruction;
+ gchar *direction_name;
+ guint index;
+ gchar *street_name;
+} mapquest_route_maneuver;
+
+typedef struct {
+ rectangle_s bounding_box;
+ gdouble distance;
+ route_unit distance_unit;
+ guint time;
+ gchar *formatted_time;
+ route_type type;
+ GList *maneuvers; /* List of type mapquest_route_maneuver */
+ GList *shapePoints;
+} mapquest_route_resp_s;
+
+#endif /* _MAPQUEST_TYPES_H_ */
diff --git a/src/mapquest/mapquest_util.c b/src/mapquest/mapquest_util.c
new file mode 100644
index 0000000..fc71d12
--- /dev/null
+++ b/src/mapquest/mapquest_util.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 "mapquest_util.h"
+#include "mapquest_debug.h"
+#include <math.h>
+
+#define PI 3.14159265359
+#define EARTH_RADIUS 6371
+
+void calculate_point(gdouble Lat1, gdouble Lon1, int dBearing, gdouble dist, coords_s **coord)
+{
+ Lat1 = (Lat1 / 180.0) * PI;
+ Lon1 = (Lon1 / 180.0) * PI;
+
+ gdouble dLat = asin(sin(Lat1) * cos(dist / EARTH_RADIUS) + (cos(Lat1) * sin(dist / EARTH_RADIUS) * cos(dBearing)));
+
+ dLat = (180.0 * dLat) / PI;
+
+ gdouble dLon = Lon1 + atan2(sin(dBearing) * sin(dist / EARTH_RADIUS) * cos(Lat1), cos(dist / EARTH_RADIUS) - sin(Lat1) * sin((dLat / 180.0) * PI));
+
+ dLon = (180.0 * dLon) / PI;
+
+ if (*coord == NULL)
+ *coord = (coords_s *)g_malloc0(sizeof(coords_s));
+
+ if (*coord) {
+ (*coord)->latitude = dLat;
+ (*coord)->longitude = dLon;
+ }
+}
+
diff --git a/src/mapquest/mapquest_util.h b/src/mapquest/mapquest_util.h
new file mode 100644
index 0000000..b62a3d5
--- /dev/null
+++ b/src/mapquest/mapquest_util.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 _MAPQUEST_UTIL_H_
+#define _MAPQUEST_UTIL_H_
+
+#include "mapquest_types.h"
+
+void calculate_point(gdouble Lat1, gdouble Lon1, int dBearing, gdouble dist, coords_s **coord);
+
+#endif /* _MAPQUEST_UTIL_H_ */
diff --git a/src/mapquest_plugin.c b/src/mapquest_plugin.c
new file mode 100644
index 0000000..9b119f2
--- /dev/null
+++ b/src/mapquest_plugin.c
@@ -0,0 +1,1394 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include "mapquest_plugin.h"
+#include "mapquest_plugin_internal.h"
+#include "mapquest_api.h"
+#include <maps_error.h>
+#include <maps_route_plugin.h>
+#include <maps_route_segment_plugin.h>
+#include <maps_route_maneuver_plugin.h>
+#include <maps_place_plugin.h>
+#include <maps_place_category.h>
+#include <maps_place_image_plugin.h>
+#include <maps_place_rating_plugin.h>
+
+#define DEFAULT_NUM_RESULTS 10
+#define _PROVIDER_KEY_MAX_SIZE 1024
+
+static const double LATITUDE_RANGE = 85.05113;
+static const double LONGITUDE_RANGE = 180.0;
+
+static int __request_id = 0;
+static maps_plugin_h __plugin = NULL;
+static char __provider_key[_PROVIDER_KEY_MAX_SIZE] = { 0 };
+
+static maps_item_hashtable_h preference_plugin = NULL;
+
+int __maps_service_instance_count = 0;
+
+static int __convert_to_maps_error(int ret)
+{
+ switch (ret) {
+ case MAPQUEST_ERROR_NONE:
+ return MAPS_ERROR_NONE;
+ case MAPQUEST_ERROR_PERMISSION_DENIED:
+ return MAPS_ERROR_PERMISSION_DENIED;
+ case MAPQUEST_ERROR_OUT_OF_MEMORY:
+ return MAPS_ERROR_OUT_OF_MEMORY;
+ case MAPQUEST_ERROR_INVALID_PARAMETER:
+ return MAPS_ERROR_INVALID_PARAMETER;
+ case MAPQUEST_ERROR_NOT_SUPPORTED:
+ return MAPS_ERROR_NOT_SUPPORTED;
+ case MAPQUEST_ERROR_CONNECTION_TIMED_OUT:
+ return MAPS_ERROR_CONNECTION_TIME_OUT;
+ case MAPQUEST_ERROR_NETWORK_UNREACHABLE:
+ return MAPS_ERROR_NETWORK_UNREACHABLE;
+ case MAPQUEST_ERROR_INVALID_OPERATION:
+ return MAPS_ERROR_INVALID_OPERATION;
+ case MAPQUEST_ERROR_KEY_NOT_AVAILABLE:
+ return MAPS_ERROR_KEY_NOT_AVAILABLE;
+ case MAPQUEST_ERROR_RESOURCE_BUSY:
+ return MAPS_ERROR_RESOURCE_BUSY;
+ case MAPQUEST_ERROR_CANCELED:
+ return MAPS_ERROR_CANCELED;
+ case MAPQUEST_ERROR_UNKNOWN:
+ return MAPS_ERROR_UNKNOWN;
+ case MAPQUEST_ERROR_SERVICE_NOT_AVAILABLE:
+ return MAPS_ERROR_SERVICE_NOT_AVAILABLE;
+ case MAPQUEST_ERROR_NOT_FOUND:
+ return MAPS_ERROR_NOT_FOUND;
+ default:
+ return MAPS_ERROR_UNKNOWN;
+ }
+}
+
+static maps_route_turn_type_e __convert_route_turn_type(int index)
+{
+ maps_route_turn_type_e type = MAPS_ROUTE_TURN_TYPE_NONE;
+
+ if (index == 0)
+ type = MAPS_ROUTE_TURN_TYPE_STRAIGHT;
+ else if (index == 1)
+ type = MAPS_ROUTE_TURN_TYPE_LIGHT_RIGHT;
+ else if (index == 2)
+ type = MAPS_ROUTE_TURN_TYPE_RIGHT;
+ else if (index == 3)
+ type = MAPS_ROUTE_TURN_TYPE_HARD_RIGHT;
+ else if (index == 5)
+ type = MAPS_ROUTE_TURN_TYPE_HARD_LEFT;
+ else if (index == 6)
+ type = MAPS_ROUTE_TURN_TYPE_LIGHT_LEFT;
+ else if (index == 7)
+ type = MAPS_ROUTE_TURN_TYPE_LIGHT_LEFT;
+ else if (index == 8)
+ type = MAPS_ROUTE_TURN_TYPE_UTURN_RIGHT;
+ else if (index == 9)
+ type = MAPS_ROUTE_TURN_TYPE_UTURN_LEFT;
+ else if (index == 16)
+ type = MAPS_ROUTE_TURN_TYPE_RIGHT_FORK;
+ else if (index == 17)
+ type = MAPS_ROUTE_TURN_TYPE_LEFT_FORK;
+ else if (index == 18)
+ type = MAPS_ROUTE_TURN_TYPE_STRAIGHT_FORK;
+ else
+ type = MAPS_ROUTE_TURN_TYPE_NONE;
+
+ return type;
+}
+
+static bool __replace_space(char *place_name, char **modified_place_name)
+{
+ if (!place_name) return false;
+
+ int new_str_len = 0;
+ char *ch;
+ for (ch = place_name; *ch != '\0'; ch++) {
+ if (*ch == ' ')
+ new_str_len += 2;
+ new_str_len++;
+ }
+
+ if (strlen(place_name) < new_str_len) {
+ *modified_place_name = (char *)g_malloc((new_str_len + 1) * sizeof(char));
+ if (*modified_place_name) {
+ char *ch1, *ch2;
+ for (ch1 = place_name, ch2 = *modified_place_name; *ch1 != '\0'; ch1++) {
+ if (*ch1 == ' ') {
+ ch2[0] = '%';
+ ch2[1] = '2';
+ ch2[2] = '0';
+ ch2 += 3;
+ } else {
+ *ch2 = *ch1;
+ ch2++;
+ }
+ }
+ *ch2 = '\0';
+
+ return true;
+ }
+ }
+ return false;
+}
+
+EXPORT_API int maps_plugin_init(maps_plugin_h *plugin)
+{
+ if (!plugin)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ int ret = MAPS_ERROR_NONE;
+ if (!__plugin) {
+ ret = mapquest_init();
+ }
+
+ if (ret == MAPS_ERROR_NONE) {
+ __maps_service_instance_count++;
+ __plugin = plugin;
+ }
+
+ return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_shutdown(maps_plugin_h plugin)
+{
+ MAPS_LOGD("PLUGIN SHUTDOWN");
+ if (!plugin)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ __maps_service_instance_count--;
+
+ int ret = MAPS_ERROR_NONE;
+ if (__maps_service_instance_count == 0) {
+ ret = mapquest_shutdown();
+ __plugin = NULL;
+ }
+
+ return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_is_service_supported(maps_service_e service, bool *supported)
+{
+ if (!supported)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ switch (service) {
+ case MAPS_SERVICE_GEOCODE:
+ case MAPS_SERVICE_GEOCODE_INSIDE_AREA:
+ case MAPS_SERVICE_GEOCODE_BY_STRUCTURED_ADDRESS:
+ case MAPS_SERVICE_REVERSE_GEOCODE:
+ case MAPS_SERVICE_SEARCH_PLACE:
+ case MAPS_SERVICE_SEARCH_PLACE_BY_AREA:
+ case MAPS_SERVICE_SEARCH_PLACE_BY_ADDRESS:
+ case MAPS_SERVICE_SEARCH_ROUTE:
+ case MAPS_SERVICE_SEARCH_ROUTE_WAYPOINTS:
+ case MAPS_SERVICE_CANCEL_REQUEST:
+ *supported = true;
+ return MAPS_ERROR_NONE;
+ default:
+ *supported = false;
+ return MAPS_ERROR_NOT_SUPPORTED;
+ }
+}
+
+EXPORT_API int maps_plugin_is_data_supported(maps_service_data_e data, bool *supported)
+{
+ if (!supported)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ switch (data) {
+ case MAPS_PLACE_ADDRESS:
+ case MAPS_PLACE_CATEGORIES:
+ case MAPS_PLACE_IMAGE:
+ /* unsupported */
+ /* case MAPS_PLACE_RATING: */
+ /* case MAPS_PLACE_ATTRIBUTES: */
+ /* case MAPS_PLACE_CONTACTS: */
+ /* case MAPS_PLACE_EDITORIALS: */
+ /* case MAPS_PLACE_REVIEWS: */
+ /* case MAPS_PLACE_SUPPLIER: */
+ /* case MAPS_PLACE_RELATED: */
+
+ case MAPS_ROUTE_PATH:
+ case MAPS_ROUTE_SEGMENTS_PATH:
+ case MAPS_ROUTE_SEGMENTS_MANEUVERS:
+ *supported = true;
+ return MAPS_ERROR_NONE;
+ default:
+ *supported = false;
+ return MAPS_ERROR_NOT_SUPPORTED;
+ }
+}
+
+EXPORT_API int maps_plugin_get_info(maps_plugin_info_h *info)
+{
+ if (!info)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ maps_plugin_info_create(info);
+ maps_plugin_info_set_provider_name(*info, "MAPQUEST");
+
+ return MAPS_ERROR_NONE;
+}
+
+EXPORT_API int maps_plugin_set_provider_key(const char *provider_key)
+{
+ if (!provider_key)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ g_snprintf(__provider_key, _PROVIDER_KEY_MAX_SIZE, "%s", provider_key);
+
+ return MAPS_ERROR_NONE;
+}
+
+EXPORT_API int maps_plugin_get_provider_key(char **provider_key)
+{
+ if (!provider_key)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ *provider_key = g_strndup(__provider_key, _PROVIDER_KEY_MAX_SIZE);
+
+ return MAPS_ERROR_NONE;
+}
+
+EXPORT_API int maps_plugin_set_preference(maps_item_hashtable_h preference)
+{
+ if (!preference)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ maps_item_hashtable_clone(preference, &preference_plugin);
+ return MAPS_ERROR_NONE;
+}
+
+EXPORT_API int maps_plugin_get_preference(maps_item_hashtable_h *preference)
+{
+ if (!preference)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ maps_item_hashtable_clone(preference_plugin, preference);
+ return MAPS_ERROR_NONE;
+}
+
+static void __mapquest_geocode_cb(mapquest_error_e result, int request_id, GList *co_ordinates, void *user_data)
+{
+ MAPS_LOGD("Got GEOCODE callback from ENGINE");
+
+ callback_info_geocode *calldata_geocode = (callback_info_geocode *) user_data;
+
+ if ((result != MAPQUEST_ERROR_NONE) || (co_ordinates == NULL)) {
+ MAPS_LOGD(">>>>> Invalid GEOCODE result <<<<<");
+ calldata_geocode->callback((maps_error_e)__convert_to_maps_error(result), calldata_geocode->reqID, 0, 0, NULL, calldata_geocode->data);
+ } else {
+ int total_count = (int) g_list_length(co_ordinates);
+ int index = 0;
+
+ GList *coords = NULL;
+ coords = g_list_first(co_ordinates);
+
+ while (coords) {
+ MAPS_LOGD("coordinate %d", index);
+ coords_s *data = (coords_s *) coords->data;
+
+ if (data != NULL) {
+ maps_coordinates_h resultCoords;
+ maps_coordinates_create(data->latitude, data->longitude, &resultCoords);
+ bool b = calldata_geocode->callback(MAPS_ERROR_NONE, calldata_geocode->reqID, index, total_count, resultCoords, calldata_geocode->data);
+ if (!b)
+ return;
+ }
+ index++;
+ coords = coords->next;
+ }
+ }
+}
+
+EXPORT_API int maps_plugin_geocode(const char *address, const maps_preference_h preference, maps_service_geocode_cb callback, void *user_data, int *request_id)
+{
+ if (!address || !callback || !request_id)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ callback_info_geocode *calldata_geocode = (callback_info_geocode *)g_malloc0(sizeof(callback_info_geocode));
+ if (calldata_geocode == NULL)
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+ calldata_geocode->callback = callback;
+ calldata_geocode->data = user_data;
+
+ mapquest_geocode_req_s *geocode_req = (mapquest_geocode_req_s *)g_malloc0(sizeof(mapquest_geocode_req_s));
+ if (geocode_req == NULL) {
+ g_free(calldata_geocode);
+ calldata_geocode = NULL;
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+ }
+
+ char *modified_address = NULL;
+ bool b_isAddress_modified = false;
+ b_isAddress_modified = __replace_space((char *)address, &modified_address);
+
+ if (b_isAddress_modified)
+ geocode_req->address = g_strdup((gchar *) modified_address);
+ else
+ geocode_req->address = g_strdup((gchar *) address);
+
+ if (modified_address) {
+ g_free(modified_address);
+ modified_address = NULL;
+ }
+
+ geocode_req->maps_key = g_strdup((gchar *) __provider_key);
+ geocode_req->boundary = NULL;
+
+ int max_result = 0;
+ maps_preference_get_max_results(preference, &max_result);
+
+ if (max_result <= 0)
+ geocode_req->num_res = DEFAULT_NUM_RESULTS;
+ else
+ geocode_req->num_res = max_result;
+
+ *request_id = ++__request_id;
+ calldata_geocode->reqID = __request_id;
+
+ int ret = mapquest_geocode(geocode_req, __mapquest_geocode_cb, __request_id, (void *) calldata_geocode);
+
+ return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_geocode_inside_area(const char *address, const maps_area_h bounds, const maps_preference_h preference, maps_service_geocode_cb callback, void *user_data, int *request_id)
+{
+ if (!bounds || !address || !callback || !request_id)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ callback_info_geocode *calldata_geocode = (callback_info_geocode *)g_malloc0(sizeof(callback_info_geocode));
+ if (calldata_geocode == NULL)
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+ calldata_geocode->callback = callback;
+ calldata_geocode->data = user_data;
+
+ mapquest_geocode_req_s *geocode_req = (mapquest_geocode_req_s *)g_malloc0(sizeof(mapquest_geocode_req_s));
+ if (geocode_req == NULL) {
+ free(calldata_geocode);
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+ }
+
+ char *modified_address = NULL;
+ bool b_isAddress_modified = false;
+ b_isAddress_modified = __replace_space((char *)address, &modified_address);
+
+ if (b_isAddress_modified)
+ geocode_req->address = g_strdup((gchar *) modified_address);
+ else
+ geocode_req->address = g_strdup((gchar *) address);
+
+ if (modified_address) {
+ g_free(modified_address);
+ modified_address = NULL;
+ }
+
+ geocode_req->maps_key = g_strdup((gchar *) __provider_key);
+
+ int max_result = 0;
+ maps_preference_get_max_results(preference, &max_result);
+
+ if (max_result <= 0)
+ geocode_req->num_res = DEFAULT_NUM_RESULTS;
+ else
+ geocode_req->num_res = max_result;
+
+ geocode_req->boundary = NULL;
+ geocode_req->boundary = (mapquest_boundary_s *)g_malloc0(sizeof(mapquest_boundary_s));
+
+ maps_area_s *area = (maps_area_s *) bounds;
+
+ if (area && geocode_req->boundary) {
+ if (area->type == MAPS_AREA_RECTANGLE) {
+ geocode_req->boundary->type = MAPQUEST_BOUNDARY_RECT;
+ geocode_req->boundary->rect.top_left.latitude = area->rect.top_left.latitude;
+ geocode_req->boundary->rect.top_left.longitude = area->rect.top_left.longitude;
+ geocode_req->boundary->rect.bottom_right.latitude = area->rect.bottom_right.latitude;
+ geocode_req->boundary->rect.bottom_right.longitude = area->rect.bottom_right.longitude;
+ } else if (area->type == MAPS_AREA_CIRCLE) {
+ geocode_req->boundary->type = MAPQUEST_BOUNDARY_CIRCLE;
+ geocode_req->boundary->circle.center.latitude = area->circle.center.latitude;
+ geocode_req->boundary->circle.center.longitude = area->circle.center.longitude;
+ geocode_req->boundary->circle.radius = area->circle.radius;
+ }
+ }
+
+ *request_id = ++__request_id;
+ calldata_geocode->reqID = __request_id;
+
+ int ret = mapquest_geocode(geocode_req, __mapquest_geocode_cb, __request_id, (void *) calldata_geocode);
+
+ return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_geocode_by_structured_address(const maps_address_h address, const maps_preference_h preference, maps_service_geocode_cb callback, void *user_data, int *request_id)
+{
+ if (!address || !callback || !request_id)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ callback_info_geocode *calldata_geocode = (callback_info_geocode *)g_malloc0(sizeof(callback_info_geocode));
+ if (calldata_geocode == NULL)
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+ calldata_geocode->callback = callback;
+ calldata_geocode->data = user_data;
+
+ mapquest_geocode_req_s *geocode_req = (mapquest_geocode_req_s *)g_malloc0(sizeof(mapquest_geocode_req_s));
+ if (geocode_req == NULL) {
+ free(calldata_geocode);
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+ }
+
+ char resultAddressQuery[1024];
+ strcpy(resultAddressQuery, "");
+
+ char *street = NULL;
+ maps_address_get_street(address, &street);
+ if (street != NULL)
+ strcat(resultAddressQuery, street);
+
+ char *city = NULL;
+ maps_address_get_city(address, &city);
+ if ((strlen(resultAddressQuery) > 0) && (city != NULL)) {
+ strcat(resultAddressQuery, ",");
+ strcat(resultAddressQuery, city);
+ } else if (city != NULL) {
+ strcat(resultAddressQuery, city);
+ }
+
+ char *state = NULL;
+ maps_address_get_state(address, &state);
+ if ((strlen(resultAddressQuery) > 0) && (state != NULL)) {
+ strcat(resultAddressQuery, ",");
+ strcat(resultAddressQuery, state);
+ } else if (state != NULL) {
+ strcat(resultAddressQuery, state);
+ }
+
+#if 0
+ char *district = NULL;
+ maps_address_get_district(address, &district);
+ if ((strlen(resultAddressQuery) > 0) && (district != NULL)) {
+ strcat(resultAddressQuery, ", ");
+ strcat(resultAddressQuery, district);
+ }
+
+ char *country = NULL;
+ maps_address_get_country(address, &country);
+ if ((strlen(resultAddressQuery) > 0) && (country != NULL)) {
+ strcat(resultAddressQuery, ", ");
+ strcat(resultAddressQuery, country);
+ }
+
+ char *country_code = NULL;
+ maps_address_get_country_code(address, &country_code);
+ if ((strlen(resultAddressQuery) > 0) && (country_code != NULL)) {
+ strcat(resultAddressQuery, ", ");
+ strcat(resultAddressQuery, country_code);
+ } else if (country_code != NULL) {
+ strcat(resultAddressQuery, country_code);
+ }
+
+ char *county = NULL;
+ maps_address_get_county(address, &county);
+ if ((strlen(resultAddressQuery) > 0) && (county != NULL)) {
+ strcat(resultAddressQuery, ", ");
+ strcat(resultAddressQuery, county);
+ }
+#endif
+
+ char *postal_code = NULL;
+ maps_address_get_postal_code(address, &postal_code);
+ if ((strlen(resultAddressQuery) > 0) && (postal_code != NULL)) {
+ strcat(resultAddressQuery, ",");
+ strcat(resultAddressQuery, postal_code);
+ } else if (postal_code != NULL) {
+ strcat(resultAddressQuery, postal_code);
+ }
+
+ char *modified_address = NULL;
+ bool b_isAddress_modified = false;
+ b_isAddress_modified = __replace_space(resultAddressQuery, &modified_address);
+
+ if (b_isAddress_modified)
+ geocode_req->address = g_strdup((gchar *) modified_address);
+ else
+ geocode_req->address = g_strdup((gchar *) resultAddressQuery);
+
+ if (modified_address) {
+ g_free(modified_address);
+ modified_address = NULL;
+ }
+
+ geocode_req->maps_key = g_strdup((gchar *) __provider_key);
+ geocode_req->boundary = NULL;
+
+ int max_result = 0;
+ maps_preference_get_max_results(preference, &max_result);
+
+ if (max_result <= 0)
+ geocode_req->num_res = DEFAULT_NUM_RESULTS;
+ else
+ geocode_req->num_res = max_result;
+
+ *request_id = ++__request_id;
+ calldata_geocode->reqID = __request_id;
+
+ int ret = mapquest_geocode(geocode_req, __mapquest_geocode_cb, __request_id, (void *) calldata_geocode);
+
+ return __convert_to_maps_error(ret);
+}
+
+static void __mapquest_reverse_geocode_cb(mapquest_error_e result, int request_id, mapquest_address_resp_s *address, void *user_data)
+{
+ MAPS_LOGD("Got REV GEOCODE callback from ENGINE");
+ callback_info_reverse_geocode *calldata_reverse_geocode = (callback_info_reverse_geocode *) user_data;
+ if (result != MAPQUEST_ERROR_NONE || address == NULL) {
+ calldata_reverse_geocode->callback((maps_error_e) __convert_to_maps_error(result), calldata_reverse_geocode->reqID, 0, 0, NULL, calldata_reverse_geocode->data);
+ } else {
+ int total_count = 1;
+ int index = 0;
+
+ maps_address_h addr = NULL;
+ maps_address_create(&addr);
+
+ maps_address_set_street(addr, address->street_add);
+ maps_address_set_city(addr, address->city);
+ maps_address_set_county(addr, address->county);
+ maps_address_set_state(addr, address->state);
+ maps_address_set_country(addr, address->country);
+ maps_address_set_country_code(addr, address->country_code);
+ maps_address_set_postal_code(addr, address->postal_code);
+
+ calldata_reverse_geocode->callback(MAPS_ERROR_NONE, calldata_reverse_geocode->reqID, index, total_count, addr, calldata_reverse_geocode->data);
+ }
+}
+
+EXPORT_API int maps_plugin_reverse_geocode(double latitude, double longitude, const maps_preference_h preference, maps_service_reverse_geocode_cb callback, void *user_data, int *request_id)
+{
+ if (!callback || !request_id)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ if (latitude > LATITUDE_RANGE || latitude < -LATITUDE_RANGE)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ if (longitude > LONGITUDE_RANGE || longitude < -LONGITUDE_RANGE)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ callback_info_reverse_geocode *calldata_reverse_geocode = (callback_info_reverse_geocode *)g_malloc0(sizeof(callback_info_reverse_geocode));
+ if (calldata_reverse_geocode == NULL)
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+ calldata_reverse_geocode->callback = callback;
+ calldata_reverse_geocode->data = user_data;
+
+ mapquest_revgeocode_req_s *reverse_geocode_req = (mapquest_revgeocode_req_s *)g_malloc0(sizeof(mapquest_revgeocode_req_s));
+ if (reverse_geocode_req == NULL) {
+ g_free(calldata_reverse_geocode);
+ calldata_reverse_geocode = NULL;
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+ }
+
+ reverse_geocode_req->maps_key = g_strdup((gchar *) __provider_key);
+ reverse_geocode_req->coordinates.latitude = latitude;
+ reverse_geocode_req->coordinates.longitude = longitude;
+
+ *request_id = ++__request_id;
+ calldata_reverse_geocode->reqID = __request_id;
+
+ int ret = mapquest_reverse_geocode(reverse_geocode_req, __mapquest_reverse_geocode_cb, __request_id, (void *) calldata_reverse_geocode);
+
+ return __convert_to_maps_error(ret);
+}
+
+static void __mapquest_route_cb(mapquest_error_e result, int request_id, mapquest_route_resp_s *route_info, void *user_data)
+{
+ MAPS_LOGD("__mapquest_route_cb");
+ callback_info_route *calldata_route = (callback_info_route *) user_data;
+
+ if (route_info) {
+ maps_route_h route;
+ maps_route_create(&route);
+
+ maps_coordinates_h top_left;
+ maps_coordinates_create(route_info->bounding_box.top_left.latitude, route_info->bounding_box.top_left.longitude, &top_left);
+
+ maps_coordinates_h bottom_right;
+ maps_coordinates_create(route_info->bounding_box.bottom_right.latitude, route_info->bounding_box.bottom_right.longitude, &bottom_right);
+
+ maps_area_h bounds = NULL;
+ maps_area_create_rectangle(top_left, bottom_right, &bounds);
+ maps_route_set_bounding_box(route, bounds);
+ maps_area_destroy(bounds);
+
+ maps_coordinates_destroy(top_left);
+ maps_coordinates_destroy(bottom_right);
+
+ maps_distance_unit_e unit = MAPS_DISTANCE_UNIT_M;
+
+ switch (route_info->distance_unit) {
+ case ROUTE_UNIT_M:
+ unit = MAPS_DISTANCE_UNIT_M;
+ break;
+ case ROUTE_UNIT_KM:
+ unit = MAPS_DISTANCE_UNIT_KM;
+ break;
+ case ROUTE_UNIT_FT:
+ unit = MAPS_DISTANCE_UNIT_FT;
+ break;
+ case ROUTE_UNIT_YD:
+ unit = MAPS_DISTANCE_UNIT_YD;
+ break;
+ }
+
+ maps_route_set_distance_unit(route, unit);
+ maps_route_set_total_distance(route, route_info->distance);
+ maps_route_set_total_duration(route, (long) route_info->time);
+ if (route_info->type == ROUTE_TYPE_FASTEST)
+ maps_route_set_transport_mode(route, MAPS_ROUTE_TRANSPORT_MODE_CAR);
+ else if (route_info->type == ROUTE_TYPE_PEDESTRIAN)
+ maps_route_set_transport_mode(route, MAPS_ROUTE_TRANSPORT_MODE_PEDESTRIAN);
+ else if (route_info->type == ROUTE_TYPE_BICYCLE)
+ maps_route_set_transport_mode(route, MAPS_ROUTE_TRANSPORT_MODE_BICYCLE);
+ else if (route_info->type == ROUTE_TYPE_MULTIMODAL)
+ maps_route_set_transport_mode(route, MAPS_ROUTE_TRANSPORT_MODE_PUBLICTRANSIT);
+ else
+ maps_route_set_transport_mode(route, MAPS_ROUTE_TRANSPORT_MODE_CAR);
+
+ maps_item_list_h segment_list = NULL;
+ maps_item_list_create(&segment_list);
+
+ GList *maneuver_data = NULL;
+ maneuver_data = g_list_first(route_info->maneuvers);
+
+ while (maneuver_data) {
+ maps_route_segment_h segment = NULL;
+ maps_route_segment_create(&segment);
+
+ maps_route_maneuver_h man = NULL;
+ maps_route_maneuver_create(&man);
+ mapquest_route_maneuver *maneuver = (mapquest_route_maneuver *) maneuver_data->data;
+
+ /* Segment Origin and Destination */
+ maps_coordinates_h segmentStartPoint;
+ maps_coordinates_create(maneuver->start_point.latitude, maneuver->start_point.longitude, &segmentStartPoint);
+ maps_route_segment_set_origin(segment, segmentStartPoint); /* origin */
+ maps_coordinates_destroy(segmentStartPoint);
+
+ maps_coordinates_h segmentEndPoint;
+ maps_coordinates_create(maneuver->end_point.latitude, maneuver->end_point.longitude, &segmentEndPoint);
+
+ MAPS_LOGD(">>> Segment start : %f, %f <<<", maneuver->start_point.latitude, maneuver->start_point.longitude);
+ MAPS_LOGD(">>> Segment end : %f, %f <<<", maneuver->end_point.latitude, maneuver->end_point.longitude);
+
+ maps_route_segment_set_destination(segment, segmentEndPoint); /* destination */
+ maps_coordinates_destroy(segmentEndPoint);
+
+ /* Segment distance */
+ maps_route_segment_set_distance(segment, maneuver->distance);
+ maps_route_segment_set_duration(segment, maneuver->time);
+
+ /* Maneuver distance */
+ maps_route_maneuver_set_distance_to_next_instruction(man, maneuver->distance);
+ maps_route_maneuver_set_time_to_next_instruction(man, maneuver->time);
+
+ maps_route_maneuver_set_turn_type(man, __convert_route_turn_type(maneuver->turn_type));
+
+ /* maneuver_set_traffic_direction(man, (traffic_direction_e)action_id); */
+
+ /* Maneuver Instruction */
+ if (maneuver->instruction)
+ maps_route_maneuver_set_instruction_text(man, (char *) maneuver->instruction);
+
+ /* Maneuver Street Name */
+ if (maneuver->street_name) {
+ MAPS_LOGD("Street Name >>>> %s", maneuver->street_name);
+ maps_route_maneuver_set_road_name(man, (char *) maneuver->street_name);
+ } else {
+ MAPS_LOGD("Street Name >>>> NIL");
+ }
+
+ /* Maneuver start position */
+ maps_coordinates_h coord;
+ maps_coordinates_create(maneuver->start_point.latitude, maneuver->start_point.longitude, &coord);
+
+ maps_route_maneuver_set_position(man, coord);
+ maps_coordinates_destroy(coord);
+
+ maps_item_list_h maneuver_list = NULL;
+ maps_item_list_create(&maneuver_list);
+ maps_item_list_append(maneuver_list, (gpointer) man, maps_route_maneuver_clone);
+ maps_route_segment_set_maneuvers(segment, maneuver_list);
+
+ maps_item_list_destroy(maneuver_list);
+ maps_route_maneuver_destroy(man);
+
+ maps_item_list_append(segment_list, (gpointer) segment, maps_route_segment_clone);
+ maps_route_segment_destroy(segment);
+
+ /* Fetching the next item from Maneuver/Segment list */
+ maneuver_data = g_list_next(maneuver_data);
+ }
+ maps_route_set_segments(route, segment_list);
+ maps_item_list_destroy(segment_list);
+
+ /* Shape points - path */
+ maps_item_list_h path_list = NULL;
+ maps_item_list_create(&path_list);
+
+ GList *shapePoints = NULL;
+ shapePoints = g_list_first(route_info->shapePoints);
+
+ while (shapePoints) {
+ coords_s *data = (coords_s *) shapePoints->data;
+
+ maps_coordinates_h shapeCoords;
+ maps_coordinates_create(data->latitude, data->longitude, &shapeCoords);
+
+ maps_item_list_append(path_list, (gpointer) shapeCoords, maps_coordinates_clone);
+
+ maps_coordinates_destroy(shapeCoords);
+
+ shapePoints = g_list_next(shapePoints);
+ }
+ maps_route_set_path(route, path_list);
+ maps_item_list_destroy(path_list);
+
+ bool b = calldata_route->callback((maps_error_e)__convert_to_maps_error(result), calldata_route->reqID, 0, 1, route, calldata_route->data);
+ if (!b)
+ return;
+ } else {
+ calldata_route->callback((maps_error_e)__convert_to_maps_error(result), calldata_route->reqID, 0, 0, NULL, calldata_route->data);
+ }
+}
+
+EXPORT_API int maps_plugin_search_route(const maps_coordinates_h origin, const maps_coordinates_h destination, maps_preference_h preference, maps_service_search_route_cb callback, void *user_data, int *request_id)
+{
+ if (!origin || !destination || !callback || !request_id)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ callback_info_route *calldata_route = (callback_info_route *)g_malloc0(sizeof(callback_info_route));
+ if (calldata_route == NULL)
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+ calldata_route->callback = callback;
+ calldata_route->data = user_data;
+
+ mapquest_route_req_s *route_req = (mapquest_route_req_s *)g_malloc0(sizeof(mapquest_route_req_s));
+ if (route_req == NULL) {
+ g_free(calldata_route);
+ calldata_route = NULL;
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+ }
+
+ route_req->maps_key = g_strdup((gchar *) __provider_key);
+
+ double origin_lat, origin_lon;
+ double dest_lat, dest_lon;
+
+ maps_coordinates_get_latitude(origin, &origin_lat);
+ maps_coordinates_get_longitude(origin, &origin_lon);
+
+ maps_coordinates_get_latitude(destination, &dest_lat);
+ maps_coordinates_get_longitude(destination, &dest_lon);
+
+ route_req->from.latitude = origin_lat;
+ route_req->from.longitude = origin_lon;
+
+ route_req->to.latitude = dest_lat;
+ route_req->to.longitude = dest_lon;
+
+ MAPS_LOGD("getting transport mode..");
+ maps_route_transport_mode_e transport_mode;
+ maps_preference_get_route_transport_mode(preference, &transport_mode);
+
+ if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_CAR)
+ route_req->type = ROUTE_TYPE_FASTEST;
+ else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_PEDESTRIAN)
+ route_req->type = ROUTE_TYPE_PEDESTRIAN;
+ else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_BICYCLE)
+ route_req->type = ROUTE_TYPE_BICYCLE;
+ else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_PUBLICTRANSIT)
+ route_req->type = ROUTE_TYPE_MULTIMODAL;
+ else
+ route_req->type = ROUTE_TYPE_FASTEST; /* Keeping it as default */
+
+ route_req->driving_style = DRIVING_STYLE_NORMAL; /* Keeping it as default */
+
+ /* Unit */
+ maps_distance_unit_e unit;
+ maps_preference_get_distance_unit(preference, &unit);
+
+ switch (unit) {
+ case MAPS_DISTANCE_UNIT_M:
+ route_req->unit = ROUTE_UNIT_M;
+ break;
+ case MAPS_DISTANCE_UNIT_KM:
+ route_req->unit = ROUTE_UNIT_KM;
+ break;
+ case MAPS_DISTANCE_UNIT_FT:
+ route_req->unit = ROUTE_UNIT_FT;
+ break;
+ case MAPS_DISTANCE_UNIT_YD:
+ route_req->unit = ROUTE_UNIT_YD;
+ break;
+ }
+
+ route_req->avoids = ROUTE_AVOID_NONE;
+ maps_route_feature_weight_e routeWeight;
+ maps_preference_get_route_feature_weight(preference, &routeWeight);
+
+ if (routeWeight == MAPS_ROUTE_FEATURE_WEIGHT_AVOID) {
+ maps_route_feature_e routeFeature;
+ maps_preference_get_route_feature(preference, &routeFeature);
+
+ if (routeFeature == MAPS_ROUTE_FEATURE_TOLL)
+ route_req->avoids = ROUTE_AVOID_TOLL_ROAD;
+ else if (routeFeature == MAPS_ROUTE_FEATURE_MOTORWAY)
+ route_req->avoids = ROUTE_AVOID_LIMITED_ACCESS;
+ else if ((routeFeature == MAPS_ROUTE_FEATURE_BOATFERRY) || (routeFeature == MAPS_ROUTE_FEATURE_RAILFERRY))
+ route_req->avoids = ROUTE_AVOID_FERRY;
+ else if (routeFeature == MAPS_ROUTE_FEATURE_DIRTROAD)
+ route_req->avoids = ROUTE_AVOID_UNPAVED;
+ else
+ route_req->avoids = ROUTE_AVOID_NONE;
+ }
+
+ route_req->way_points = NULL;
+
+ *request_id = ++__request_id;
+ calldata_route->reqID = __request_id;
+
+ int ret = mapquest_start_route(route_req, __mapquest_route_cb, __request_id, (void *)calldata_route);
+
+ return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_search_route_waypoints(const maps_coordinates_h *waypoint_list, int waypoint_num, maps_preference_h preference, maps_service_search_route_cb callback, void *user_data, int *request_id)
+{
+ if (!waypoint_list || waypoint_num < 2 || !callback || !request_id)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ callback_info_route *calldata_route = (callback_info_route *)g_malloc0(sizeof(callback_info_route));
+ if (calldata_route == NULL)
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+ calldata_route->callback = callback;
+ calldata_route->data = user_data;
+
+ mapquest_route_req_s *route_req = (mapquest_route_req_s *)g_malloc0(sizeof(mapquest_route_req_s));
+ if (route_req == NULL) {
+ g_free(calldata_route);
+ calldata_route = NULL;
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+ }
+
+ route_req->maps_key = g_strdup((gchar *) __provider_key);
+
+ route_req->from.latitude = 0.0;
+ route_req->from.longitude = 0.0;
+
+ route_req->to.latitude = 0.0;
+ route_req->to.longitude = 0.0;
+
+ MAPS_LOGD("getting transport mode..");
+ maps_route_transport_mode_e transport_mode;
+ maps_preference_get_route_transport_mode(preference, &transport_mode);
+
+ if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_CAR)
+ route_req->type = ROUTE_TYPE_FASTEST;
+ else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_PEDESTRIAN)
+ route_req->type = ROUTE_TYPE_PEDESTRIAN;
+ else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_BICYCLE)
+ route_req->type = ROUTE_TYPE_BICYCLE;
+ else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_PUBLICTRANSIT)
+ route_req->type = ROUTE_TYPE_MULTIMODAL;
+ else
+ route_req->type = ROUTE_TYPE_FASTEST; /* Keeping it as default */
+
+ route_req->driving_style = DRIVING_STYLE_NORMAL; /* Keeping it as default */
+
+ /* Unit */
+ maps_distance_unit_e unit;
+ maps_preference_get_distance_unit(preference, &unit);
+
+ switch (unit) {
+ case MAPS_DISTANCE_UNIT_M:
+ route_req->unit = ROUTE_UNIT_M;
+ break;
+ case MAPS_DISTANCE_UNIT_KM:
+ route_req->unit = ROUTE_UNIT_KM;
+ break;
+ case MAPS_DISTANCE_UNIT_FT:
+ route_req->unit = ROUTE_UNIT_FT;
+ break;
+ case MAPS_DISTANCE_UNIT_YD:
+ route_req->unit = ROUTE_UNIT_YD;
+ break;
+ }
+
+ route_req->avoids = ROUTE_AVOID_NONE;
+ maps_route_feature_weight_e routeWeight;
+ maps_preference_get_route_feature_weight(preference, &routeWeight);
+
+ if (routeWeight == MAPS_ROUTE_FEATURE_WEIGHT_AVOID) {
+ maps_route_feature_e routeFeature;
+ maps_preference_get_route_feature(preference, &routeFeature);
+
+ if (routeFeature == MAPS_ROUTE_FEATURE_TOLL)
+ route_req->avoids = ROUTE_AVOID_TOLL_ROAD;
+ else if (routeFeature == MAPS_ROUTE_FEATURE_MOTORWAY)
+ route_req->avoids = ROUTE_AVOID_LIMITED_ACCESS;
+ else if ((routeFeature == MAPS_ROUTE_FEATURE_BOATFERRY) || (routeFeature == MAPS_ROUTE_FEATURE_RAILFERRY))
+ route_req->avoids = ROUTE_AVOID_FERRY;
+ else if (routeFeature == MAPS_ROUTE_FEATURE_DIRTROAD)
+ route_req->avoids = ROUTE_AVOID_UNPAVED;
+ else
+ route_req->avoids = ROUTE_AVOID_NONE;
+ }
+
+ /* Waypoints */
+ route_req->way_points = NULL;
+ if (waypoint_num != 0) {
+ int index = 0;
+ double latitude = 0.0, longitude = 0.0;
+ for (index = 0; index < waypoint_num; index++) {
+ if (waypoint_list[index] != NULL) {
+ maps_coordinates_get_latitude(waypoint_list[index], &latitude);
+ maps_coordinates_get_longitude(waypoint_list[index], &longitude);
+
+ coords_s *data = (coords_s *)g_malloc0(sizeof(coords_s));
+ if (data) {
+ data->latitude = latitude;
+ data->longitude = longitude;
+
+ if (route_req->way_points == NULL)
+ route_req->way_points = g_list_append(route_req->way_points, (gpointer) data);
+ else
+ route_req->way_points = g_list_insert_before(route_req->way_points, NULL, (gpointer) data);
+ }
+ }
+ }
+ }
+
+ *request_id = ++__request_id;
+ calldata_route->reqID = __request_id;
+
+ int ret = mapquest_start_route(route_req, __mapquest_route_cb, __request_id, (void *)calldata_route);
+
+ return __convert_to_maps_error(ret);
+}
+
+static void __mapquest_place_search_cb(mapquest_error_e result, int request_id, GList *places, void *user_data)
+{
+ MAPS_LOGD("Got places result from ENGINE...");
+
+ callback_info_place *calldata_place = (callback_info_place *) user_data;
+
+ if (result != MAPQUEST_ERROR_NONE || places == NULL) {
+ MAPS_LOGD("Got places result from ENGINE...result is NULL");
+ calldata_place->callback((maps_error_e) __convert_to_maps_error(result), calldata_place->reqID, 0, 0, NULL, calldata_place->data);
+ } else {
+ guint total_count = 0;
+ int index = 0;
+ total_count = g_list_length(places);
+ if (total_count > 0) {
+ maps_place_h place = NULL;
+ MAPS_LOGD("Got places result from ENGINE... count -> %d", total_count);
+
+ GList *temp_place = NULL;
+ temp_place = g_list_first(places);
+
+ while (temp_place) {
+ maps_place_create(&place);
+ mapquest_place_resp_s *mapquest_place = (mapquest_place_resp_s *) temp_place->data;
+ maps_place_set_id(place, mapquest_place->place_id);
+ maps_place_set_name(place, mapquest_place->display_name);
+
+ MAPS_LOGD("Before address..");
+ /* Address */
+ if (mapquest_place->address) {
+ maps_address_h addr = NULL;
+ maps_address_create(&addr);
+
+ maps_address_set_street(addr, mapquest_place->address->street_add);
+ maps_address_set_building_number(addr, mapquest_place->address->building_number);
+ maps_address_set_city(addr, mapquest_place->address->city);
+ maps_address_set_county(addr, mapquest_place->address->county);
+ maps_address_set_state(addr, mapquest_place->address->state);
+ maps_address_set_country(addr, mapquest_place->address->country);
+ maps_address_set_country_code(addr, mapquest_place->address->country_code);
+ maps_address_set_postal_code(addr, mapquest_place->address->postal_code);
+ maps_address_set_freetext(addr, mapquest_place->display_name);
+
+ maps_place_set_address(place, addr);
+ maps_address_destroy(addr);
+ } else {
+ maps_place_set_address(place, NULL);
+ }
+
+ maps_coordinates_h coord;
+ maps_coordinates_create(mapquest_place->coordinates.latitude, mapquest_place->coordinates.longitude, &coord);
+
+ maps_place_set_location(place, coord);
+ maps_coordinates_destroy(coord);
+
+ maps_place_category_h place_cat;
+ maps_place_category_create(&place_cat);
+ maps_place_category_set_name(place_cat, mapquest_place->category);
+
+ maps_item_list_h cat_list;
+ maps_item_list_create(&cat_list);
+ maps_item_list_append(cat_list, (void *) place_cat, maps_place_category_clone);
+ maps_place_set_categories(place, cat_list);
+
+ maps_place_category_destroy(place_cat);
+ maps_item_list_destroy(cat_list);
+
+ maps_place_image_h place_image;
+ maps_place_image_create(&place_image);
+ maps_place_image_set_url(place_image, mapquest_place->icon_url);
+ maps_item_list_h image_list;
+ maps_item_list_create(&image_list);
+ maps_item_list_append(image_list, (void *) place_image, maps_place_image_clone);
+ maps_place_set_images(place, image_list);
+
+ maps_place_image_destroy(place_image);
+ maps_item_list_destroy(image_list);
+
+ bool b = calldata_place->callback((maps_error_e)__convert_to_maps_error(result), calldata_place->reqID, index, total_count, place, calldata_place->data);
+ if (!b)
+ return;
+
+ index++;
+
+ temp_place = temp_place->next;
+ }
+ } else {
+ calldata_place->callback((maps_error_e)__convert_to_maps_error(result), calldata_place->reqID, index, total_count, NULL, calldata_place->data);
+ }
+ }
+}
+
+EXPORT_API int maps_plugin_search_place(const maps_coordinates_h position, int distance, const maps_place_filter_h filter, const maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id)
+{
+ if (!position || !filter || !callback || !request_id)
+ return MAPS_ERROR_INVALID_PARAMETER;
+ if (distance <= 0)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ callback_info_place *calldata_place = (callback_info_place *)g_malloc0(sizeof(callback_info_place));
+ if (calldata_place == NULL)
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+ calldata_place->callback = callback;
+ calldata_place->data = user_data;
+
+ mapquest_search_req_s *place_req = (mapquest_search_req_s *)g_malloc0(sizeof(mapquest_search_req_s));
+ if (place_req == NULL) {
+ g_free(calldata_place);
+ calldata_place = NULL;
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+ }
+
+ place_req->maps_key = g_strdup((gchar *) __provider_key);
+
+ int max_result;
+ maps_preference_get_max_results(preference, &max_result);
+
+ if (max_result == 0)
+ place_req->num_res = DEFAULT_NUM_RESULTS;
+ else
+ place_req->num_res = max_result;
+
+ MAPS_LOGD("Place Result limit :: %d", place_req->num_res);
+
+ char *categoryName = NULL;
+ char *place_name = NULL;
+
+ maps_place_category_h category = NULL;
+ maps_place_filter_get_category(filter, &category);
+
+ if (category)
+ maps_place_category_get_name(category, &categoryName);
+
+ maps_place_filter_get_place_name(filter, &place_name);
+
+ char *modified_place_name = NULL;
+ bool b_isPlaceName_modified = false;
+ if (place_name)
+ b_isPlaceName_modified = __replace_space(place_name, &modified_place_name);
+
+ MAPS_LOGD("Modified Place String.. ");
+ MAPS_LOGD(" >>>> %s", modified_place_name);
+
+ if (categoryName && place_name) {
+ if (b_isPlaceName_modified)
+ place_req->search_string = g_strdup_printf("%s[%s]", modified_place_name, categoryName);
+ else
+ place_req->search_string = g_strdup_printf("%s[%s]", place_name, categoryName);
+ } else if (categoryName) {
+ place_req->search_string = g_strdup_printf("[%s]", categoryName);
+ } else if (place_name) {
+ if (b_isPlaceName_modified)
+ place_req->search_string = g_strdup_printf("%s", modified_place_name);
+ else
+ place_req->search_string = g_strdup_printf("%s", place_name);
+ } else {
+ g_free(calldata_place);
+ calldata_place = NULL;
+ g_free(place_req);
+ place_req = NULL;
+ return MAPS_ERROR_INVALID_PARAMETER;
+ }
+
+ if (modified_place_name) {
+ g_free(modified_place_name);
+ modified_place_name = NULL;
+ }
+
+ MAPS_LOGD(">>>>>>>> Place search string :: %s <<<<<<<<<", place_req->search_string);
+
+ place_req->boundary = NULL;
+ place_req->boundary = (mapquest_boundary_s *)g_malloc0(sizeof(mapquest_boundary_s));
+
+ if (place_req->boundary) {
+ place_req->boundary->type = MAPQUEST_BOUNDARY_CIRCLE;
+ double lat, lon;
+ maps_coordinates_get_latitude(position, &lat);
+ maps_coordinates_get_longitude(position, &lon);
+ place_req->boundary->circle.center.latitude = lat;
+ place_req->boundary->circle.center.longitude = lon;
+ place_req->boundary->circle.radius = distance;
+ }
+
+ *request_id = ++__request_id;
+ calldata_place->reqID = __request_id;
+
+ int ret = mapquest_search_place(place_req, __mapquest_place_search_cb, __request_id, (void *) calldata_place);
+
+ return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_search_place_by_area(const maps_area_h boundary, const maps_place_filter_h filter, const maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id)
+{
+ if (!boundary || !filter || !callback || !request_id)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ callback_info_place *calldata_place = (callback_info_place *)g_malloc0(sizeof(callback_info_place));
+ if (calldata_place == NULL)
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+ calldata_place->callback = callback;
+ calldata_place->data = user_data;
+
+ mapquest_search_req_s *place_req = (mapquest_search_req_s *)g_malloc0(sizeof(mapquest_search_req_s));
+ if (place_req == NULL) {
+ g_free(calldata_place);
+ calldata_place = NULL;
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+ }
+
+ place_req->maps_key = g_strdup((gchar *) __provider_key);
+
+ int max_result;
+ maps_preference_get_max_results(preference, &max_result);
+
+ if (max_result == 0)
+ place_req->num_res = DEFAULT_NUM_RESULTS;
+ else
+ place_req->num_res = max_result;
+
+ MAPS_LOGD("Place Result limit :: %d", place_req->num_res);
+
+ char *categoryName = NULL;
+ char *place_name = NULL;
+
+ maps_place_category_h category = NULL;
+ maps_place_filter_get_category(filter, &category);
+
+ if (category)
+ maps_place_category_get_name(category, &categoryName);
+
+ maps_place_filter_get_place_name(filter, &place_name);
+
+ char *modified_place_name = NULL;
+ bool b_isPlaceName_modified = false;
+ if (place_name)
+ b_isPlaceName_modified = __replace_space(place_name, &modified_place_name);
+
+ if (categoryName && place_name) {
+ if (b_isPlaceName_modified)
+ place_req->search_string = g_strdup_printf("%s[%s]", modified_place_name, categoryName);
+ else
+ place_req->search_string = g_strdup_printf("%s[%s]", place_name, categoryName);
+ } else if (categoryName) {
+ place_req->search_string = g_strdup_printf("[%s]", categoryName);
+ } else if (place_name) {
+ if (b_isPlaceName_modified)
+ place_req->search_string = g_strdup_printf("%s", modified_place_name);
+ else
+ place_req->search_string = g_strdup_printf("%s", place_name);
+ } else {
+ g_free(calldata_place);
+ calldata_place = NULL;
+ g_free(place_req);
+ place_req = NULL;
+ return MAPS_ERROR_INVALID_PARAMETER;
+ }
+
+ if (modified_place_name) {
+ g_free(modified_place_name);
+ modified_place_name = NULL;
+ }
+
+ MAPS_LOGD(">>>>>>>> Place search string :: %s <<<<<<<<<", place_req->search_string);
+ place_req->boundary = NULL;
+ maps_area_s *bound = (maps_area_s *) boundary;
+
+ if (bound->type != MAPS_AREA_NONE) {
+ place_req->boundary = (mapquest_boundary_s *)g_malloc0(sizeof(mapquest_boundary_s));
+
+ if (place_req->boundary != NULL) {
+ if (bound->type == MAPS_AREA_CIRCLE) {
+ place_req->boundary->type = MAPQUEST_BOUNDARY_CIRCLE;
+ place_req->boundary->circle.center.latitude = bound->circle.center.latitude;
+ place_req->boundary->circle.center.longitude = bound->circle.center.longitude;
+ place_req->boundary->circle.radius = bound->circle.radius;
+ } else if (bound->type == MAPS_AREA_RECTANGLE) {
+ place_req->boundary->type = MAPQUEST_BOUNDARY_RECT;
+ place_req->boundary->rect.top_left.latitude = bound->rect.top_left.latitude;
+ place_req->boundary->rect.top_left.longitude = bound->rect.top_left.longitude;
+ place_req->boundary->rect.bottom_right.latitude = bound->rect.bottom_right.latitude;
+ place_req->boundary->rect.bottom_right.longitude = bound->rect.bottom_right.longitude;
+ }
+ }
+ }
+
+ *request_id = ++__request_id;
+ calldata_place->reqID = __request_id;
+
+ int ret = mapquest_search_place(place_req, __mapquest_place_search_cb, __request_id, (void *) calldata_place);
+
+ return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_search_place_by_address(const char *address, const maps_area_h boundary, const maps_place_filter_h filter, const maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id)
+{
+ if (!address || !boundary || !filter || !callback || !request_id)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ callback_info_place *calldata_place = (callback_info_place *)g_malloc0(sizeof(callback_info_place));
+ if (calldata_place == NULL)
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+ calldata_place->callback = callback;
+ calldata_place->data = user_data;
+
+ mapquest_search_req_s *place_req = (mapquest_search_req_s *)g_malloc0(sizeof(mapquest_search_req_s));
+ if (place_req == NULL) {
+ g_free(calldata_place);
+ calldata_place = NULL;
+ MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+ }
+
+ place_req->maps_key = g_strdup((gchar *) __provider_key);
+
+ int max_result;
+ maps_preference_get_max_results(preference, &max_result);
+
+ if (max_result == 0)
+ place_req->num_res = DEFAULT_NUM_RESULTS;
+ else
+ place_req->num_res = max_result;
+
+ MAPS_LOGD("Place Result limit :: %d", place_req->num_res);
+
+ char *categoryName = NULL;
+
+ maps_place_category_h category = NULL;
+ maps_place_filter_get_category(filter, &category);
+
+ if (category)
+ maps_place_category_get_name(category, &categoryName);
+
+ char *modified_address = NULL;
+ bool b_isAddress_modified = false;
+ if (address)
+ b_isAddress_modified = __replace_space((char *) address, &modified_address);
+
+ if (categoryName) {
+ if (b_isAddress_modified)
+ place_req->search_string = g_strdup_printf("%s[%s]", modified_address, categoryName);
+ else
+ place_req->search_string = g_strdup_printf("%s[%s]", address, categoryName);
+ } else {
+ if (b_isAddress_modified)
+ place_req->search_string = g_strdup_printf("%s", modified_address);
+ else
+ place_req->search_string = g_strdup_printf("%s", address);
+ }
+
+ if (modified_address) {
+ g_free(modified_address);
+ modified_address = NULL;
+ }
+
+ place_req->boundary = NULL;
+ maps_area_s *bound = (maps_area_s *) boundary;
+
+ if (bound->type != MAPS_AREA_NONE) {
+ place_req->boundary = (mapquest_boundary_s *)g_malloc0(sizeof(mapquest_boundary_s));
+
+ if (place_req->boundary != NULL) {
+ if (bound->type == MAPS_AREA_CIRCLE) {
+ place_req->boundary->type = MAPQUEST_BOUNDARY_CIRCLE;
+ place_req->boundary->circle.center.latitude = bound->circle.center.latitude;
+ place_req->boundary->circle.center.longitude = bound->circle.center.longitude;
+ place_req->boundary->circle.radius = bound->circle.radius;
+ } else if (bound->type == MAPS_AREA_RECTANGLE) {
+ place_req->boundary->type = MAPQUEST_BOUNDARY_RECT;
+ place_req->boundary->rect.top_left.latitude = bound->rect.top_left.latitude;
+ place_req->boundary->rect.top_left.longitude = bound->rect.top_left.longitude;
+ place_req->boundary->rect.bottom_right.latitude = bound->rect.bottom_right.latitude;
+ place_req->boundary->rect.bottom_right.longitude = bound->rect.bottom_right.longitude;
+ }
+ }
+ }
+
+ *request_id = ++__request_id;
+ calldata_place->reqID = __request_id;
+
+ int ret = mapquest_search_place(place_req, __mapquest_place_search_cb, __request_id, (void *) calldata_place);
+
+ return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_cancel_request(int request_id)
+{
+ MAPS_LOGD("Plugin_Cancel_Request...");
+ if (request_id < 0)
+ return MAPS_ERROR_INVALID_PARAMETER;
+
+ int ret = mapquest_cancel_request(request_id);
+
+ return __convert_to_maps_error(ret);
+}