diff options
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | include/util/locmgr.h | 28 | ||||
-rw-r--r-- | org.tizen.mediahub.xml.in | 2 | ||||
-rw-r--r-- | packaging/org.tizen.mediahub.spec | 2 | ||||
-rw-r--r-- | src/layout/gallery.c | 46 | ||||
-rw-r--r-- | src/util/locmgr.c | 457 |
6 files changed, 538 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bacbfd..8d9e4da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,8 @@ pkg_check_modules(PKGS REQUIRED capi-appfw-application capi-media-player capi-ui-efl-util + capi-maps-service + vconf app-utils) IF(NOT DEFINED PACKAGE_NAME) @@ -73,6 +75,7 @@ src/util/util.c src/util/playermgr.c src/util/ctxpopup.c src/util/progressbar.c +src/util/locmgr.c src/data/datamgr.c src/data/albumdata.c src/data/folderdata.c diff --git a/include/util/locmgr.h b/include/util/locmgr.h new file mode 100644 index 0000000..8b409e4 --- /dev/null +++ b/include/util/locmgr.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015 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 __AIR_MEDIAHUB_LOCMGR_H__ +#define __AIR_MEDIAHUB_LOCMGR_H__ + +struct locmgr; + +struct locmgr *locmgr_create(void); +void locmgr_destroy(struct locmgr *m); + +bool locmgr_set_location(struct locmgr *m, app_media *am); +bool locmgr_set_locations(struct locmgr *m, Eina_List *list); + +#endif diff --git a/org.tizen.mediahub.xml.in b/org.tizen.mediahub.xml.in index a9118bf..c7f48bc 100644 --- a/org.tizen.mediahub.xml.in +++ b/org.tizen.mediahub.xml.in @@ -11,5 +11,7 @@ <privilege>http://tizen.org/privilege/content.write</privilege> <privilege>http://tizen.org/privilege/mediastorage</privilege> <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + <privilege>http://tizen.org/privilege/mapservice</privilege> + <privilege>http://tizen.org/privilege/internet</privilege> </privileges> </manifest> diff --git a/packaging/org.tizen.mediahub.spec b/packaging/org.tizen.mediahub.spec index 902e8d8..978ad20 100644 --- a/packaging/org.tizen.mediahub.spec +++ b/packaging/org.tizen.mediahub.spec @@ -13,6 +13,8 @@ BuildRequires: pkgconfig(elementary) BuildRequires: pkgconfig(capi-appfw-application) BuildRequires: pkgconfig(capi-media-player) BuildRequires: pkgconfig(capi-ui-efl-util) +BuildRequires: pkgconfig(capi-maps-service) +BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(app-utils) %define _appdir /usr/apps/%{name} diff --git a/src/layout/gallery.c b/src/layout/gallery.c index 2d90802..f383829 100644 --- a/src/layout/gallery.c +++ b/src/layout/gallery.c @@ -30,6 +30,7 @@ #include "grid/grid.h" #include "util/listmgr.h" #include "util/util.h" +#include "util/locmgr.h" #define LIST_MEDIA_COND "media_type=0 OR (media_type=1 AND copyright=\"Unknown\")" @@ -42,6 +43,8 @@ #define BOX_PADDING (62 - GRID_PADDING) +#define JOB_INTERVAL 1.0 + struct _priv { Evas_Object *base; Evas_Object *layout; @@ -59,6 +62,8 @@ struct _priv { int view_mode; struct grid_data *gdata; + + struct locmgr *locmgr; }; static void _recent_item_selected(struct _priv *priv, app_media *am) @@ -175,12 +180,50 @@ static void _destroy_datamgr(struct _priv *priv) static void _destroy_utils(struct _priv *priv) { + locmgr_destroy(priv->locmgr); _destroy_datamgr(priv); listmgr_destroy(priv->listmgr); free(priv->ldata); } +static Eina_Bool _create_location(void *data) +{ + struct _priv *priv; + struct locmgr *locmgr; + struct datamgr *dmgr; + + if (!data) { + _ERR("invalid argument"); + return ECORE_CALLBACK_CANCEL; + } + + priv = data; + + if (!priv->dmgr) { + _ERR("failed to get datamgr"); + return ECORE_CALLBACK_CANCEL; + } + + dmgr = priv->dmgr[E_DATA_MEDIA]; + if (!dmgr) { + _ERR("failed to get datamgr"); + return ECORE_CALLBACK_CANCEL; + } + + locmgr = locmgr_create(); + if (!locmgr) { + _ERR("failed to create locmgr"); + return ECORE_CALLBACK_CANCEL; + } + + priv->locmgr = locmgr; + + locmgr_set_locations(locmgr, dmgr->ops->get_list(dmgr->handle)); + + return ECORE_CALLBACK_CANCEL; +} + static bool _create_utils(struct _priv *priv) { struct listmgr *listmgr; @@ -280,6 +323,9 @@ static bool _create(layoutmgr *lmgr, void *data) goto err3; } + /* add job for set location tag */ + ecore_timer_add(JOB_INTERVAL, _create_location, priv); + return true; err3: diff --git a/src/util/locmgr.c b/src/util/locmgr.c new file mode 100644 index 0000000..0f6bead --- /dev/null +++ b/src/util/locmgr.c @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2015 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 <Elementary.h> +#include <media_content.h> +#include <maps_service.h> +#include <app_debug.h> +#include <app_media.h> +#include <vconf.h> + +#define MAP_LANG "en-US" +#define MAP_MAX_RES 1 +#define MAP_MAX_REQ 100 + +#define LOC_TAG_DEFAULT "Unknown" +#define LOC_INVALID -200 + +#define KEY_LOC_PLUGIN "db/app/mediahub/loc_plugin" +#define KEY_LOC_ID "db/app/mediahub/loc_id" +#define KEY_LOC_CODE "db/app/mediahub/loc_code" + +struct locmgr { + maps_service_h maps; + maps_preference_h preference; + bool supported; + int queue; + Eina_List *list; + char *plugin; + char *key; +}; + +struct _cb_data { + struct locmgr *m; + app_media *am; +}; + +static void _add_queue(struct locmgr *m); + +static void _set_location_tag(app_media *am, const char *str) +{ + media_info_h media; + int r; + + if (!str) + return; + + media = app_media_get_media_handle(am); + if (!media) { + _ERR("failed to getting media handle"); + return; + } + + r = media_info_set_location_tag(media, str); + if (r != MEDIA_CONTENT_ERROR_NONE) { + _ERR("failed to set location tag"); + return; + } + + r = media_info_update_to_db(media); + if (r != MEDIA_CONTENT_ERROR_NONE) { + _ERR("failed to update db"); + return; + } + + app_media_update(am); +} + +static void _reverse_geocode_cb(maps_error_e result, int request_id, + int index, int total, maps_address_h address, void *data) +{ + struct _cb_data *cdata; + struct locmgr *m; + app_media *am; + char *country; + char *city; + char str[1024]; + int r; + + if (!data) { + _ERR("invalid parameter"); + return; + } + + cdata = data; + + m = cdata->m; + m->queue--; + + if (!m->queue) + _add_queue(m); + + am = cdata->am; + if (!am) { + _ERR("failed to get app media"); + goto out; + } + + if (result != MAPS_ERROR_NONE) { + _ERR("failed to get reverse geocode (%d)", result); + goto out; + } + + if (!address) { + _ERR("failed to get address"); + goto out; + } + + r = maps_address_get_country(address, &country); + if (r != MAPS_ERROR_NONE || !country) { + _ERR("failed to get country (%d)", r); + maps_address_destroy(address); + goto out; + } + + r = maps_address_get_city(address, &city); + if (r != MAPS_ERROR_NONE || !city) { + _ERR("failed to get city (%d)", r); + maps_address_destroy(address); + free(country); + goto out; + } + + snprintf(str, sizeof(str), "%s/%s", city, country); + _set_location_tag(am, str); + + maps_address_destroy(address); + + free(country); + free(city); + +out: + free(cdata); +} + +static void _reverse_geocode_req(struct locmgr *m, app_media *am) +{ + app_media_info *mi; + struct _cb_data *cdata; + int r; + int id; + + if (!m || !am) { + _ERR("invalid argument"); + return; + } + + mi = app_media_get_info(am); + if (!mi) { + _ERR("failed to get media info"); + return; + } + + if (mi->location_tag) + return; + + if ((mi->latitude == LOC_INVALID && mi->longitude == LOC_INVALID) || + (mi->latitude == 0 && mi->longitude == 0)) { + _set_location_tag(am, LOC_TAG_DEFAULT); + return; + } + + cdata = calloc(1, sizeof(*cdata)); + if (!cdata) { + _ERR("failed to allocate"); + return; + } + + cdata->m = m; + cdata->am = am; + + r = maps_service_reverse_geocode(m->maps, mi->latitude, mi->longitude, + m->preference, _reverse_geocode_cb, cdata, &id); + if (r != MAPS_ERROR_NONE) { + _ERR("failed to get geocode"); + return; + } + + m->queue++; +} + +static void _add_queue(struct locmgr *m) +{ + app_media *am; + Eina_List *l; + + EINA_LIST_FOREACH(m->list, l, am) { + if (m->queue >= MAP_MAX_REQ) + break; + + _reverse_geocode_req(m, am); + m->list = eina_list_remove_list(m->list, l); + } +} + +bool locmgr_set_location(struct locmgr *m, app_media *am) +{ + if (!m || !am) { + _ERR("invalid argument"); + return false; + } + + if (m->queue) { + /* service is busy, add to the list */ + m->list = eina_list_append(m->list, am); + return true; + } + + _reverse_geocode_req(m, am); + + return true; +} + +bool locmgr_set_locations(struct locmgr *m, Eina_List *list) +{ + Eina_List *l; + + if (!m || !list) { + _ERR("invalid argument"); + return false; + } + + l = eina_list_clone(list); + + if (m->queue) { + /* service is busy, add to the list */ + m->list = eina_list_merge(m->list, l); + return true; + } + + m->list = l; + + _add_queue(m); + + return true; +} + +static bool _maps_provider_cb(char *provider, void *data) +{ + struct locmgr *m; + + if (!data) + return false; + + m = data; + + if (!strcmp(provider, m->plugin)) + m->supported = true; + + return true; +} + +static int _set_preference(maps_preference_h *preference) +{ + int r; + + r = maps_preference_create(preference); + if (r != MAPS_ERROR_NONE) { + _ERR("failed to create preference"); + return r; + } + + r = maps_preference_set_language(*preference, MAP_LANG); + if (r != MAPS_ERROR_NONE) { + _ERR("failed to set language"); + maps_preference_destroy(*preference); + return r; + } + + r = maps_preference_set_max_results(*preference, MAP_MAX_RES); + if (r != MAPS_ERROR_NONE) { + _ERR("failed to set max result"); + maps_preference_destroy(*preference); + return r; + } + + return MAPS_ERROR_NONE; +} + +static bool _set_plugin(struct locmgr *m) +{ + char str[1024]; + char *id; + char *code; + + /* + * NOTE: + * map service need to set one of map providers + * and provider demand a security key for using it. + * + * mediahub was tested with "HERE" plugin. + * You can get app_id and app_code for "HERE" plugin at below website + * https://developer.here.com + * + * please set those 3 vconf values. + * plugin: db/app/mediahub/loc_plugin + * app_id: db/app/mediahub/loc_id + * app_code: db/app/mediahub/loc_code + */ + + m->plugin = vconf_get_str(KEY_LOC_PLUGIN); + if (!m->plugin) { + _ERR("Please set plugin to %s", KEY_LOC_PLUGIN); + return false; + } + + id = vconf_get_str(KEY_LOC_ID); + if (!id) { + _ERR("Please set app_id to %s", KEY_LOC_ID); + goto err_id; + } + + code = vconf_get_str(KEY_LOC_CODE); + if (!id) { + _ERR("Please set app_code to %s", KEY_LOC_CODE); + goto err_code; + } + + snprintf(str, sizeof(str), "%s/%s", id, code); + m->key = strdup(str); + + return true; + +err_code: + free(id); +err_id: + free(m->plugin); + return false; +} + +struct locmgr *locmgr_create(void) +{ + struct locmgr *m; + maps_service_h maps; + maps_preference_h preference; + int r; + bool s; + + m = calloc(1, sizeof(*m)); + if (!m) { + _ERR("failed to allocate"); + return false; + } + + s = _set_plugin(m); + if (!s) { + _ERR("can't get location information"); + goto err; + } + + r = maps_service_foreach_provider(_maps_provider_cb, m); + if (r != MAPS_ERROR_NONE) { + _ERR("failed to create maps service"); + goto err_plugin; + } + + if (!m->supported) { + _ERR("%s does not support", m->plugin); + goto err_plugin; + } + + r = maps_service_create(m->plugin, &maps); + if (r != MAPS_ERROR_NONE) { + _ERR("failed to create maps service"); + goto err_plugin; + } + + r = maps_service_set_provider_key(maps, m->key); + if (r != MAPS_ERROR_NONE) { + _ERR("failed to set provider key"); + goto err_maps; + } + + r = maps_service_provider_is_service_supported(maps, + MAPS_SERVICE_REVERSE_GEOCODE, &s); + if (r != MAPS_ERROR_NONE || !s) { + _ERR("not support reverse geocode"); + goto err_maps; + } + + r = _set_preference(&preference); + if (r != MAPS_ERROR_NONE) { + _ERR("failed to create preference"); + goto err_maps; + } + + r = maps_service_set_preference(maps, preference); + if (r != MAPS_ERROR_NONE) { + _ERR("failed to set preference"); + goto err_preference; + } + + media_content_connect(); + + m->maps = maps; + m->preference = preference; + m->queue = 0; + + return m; + +err_preference: + maps_preference_destroy(preference); +err_maps: + maps_service_destroy(maps); +err_plugin: + free(m->plugin); + free(m->key); +err: + free(m); + return NULL; +} + +void locmgr_destroy(struct locmgr *m) +{ + if (!m) { + _ERR("invalid argument"); + return; + } + + media_content_disconnect(); + + if (m->preference) { + maps_preference_destroy(m->preference); + m->preference = NULL; + } + + if (m->maps) { + /* + * FIXME: + * because maps_service_destroy function have a problem, + * disable calling this function temporary + */ + /*maps_service_destroy(m->maps);*/ + m->maps = NULL; + } + + if (m->list) { + eina_list_free(m->list); + m->list = NULL; + } + + free(m->plugin); + free(m->key); + free(m); +} |