add location manager for setting location tag to images 53/48553/2
authorMinkyu Kang <mk7.kang@samsung.com>
Wed, 23 Sep 2015 02:06:27 +0000 (11:06 +0900)
committerMinkyu Kang <mk7.kang@samsung.com>
Thu, 24 Sep 2015 05:28:11 +0000 (14:28 +0900)
Change-Id: I4729dd89321abd90bb349d34a68b87f4ff67b77d
Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
CMakeLists.txt
include/util/locmgr.h [new file with mode: 0644]
org.tizen.mediahub.xml.in
packaging/org.tizen.mediahub.spec
src/layout/gallery.c
src/util/locmgr.c [new file with mode: 0644]

index 2bacbfd..8d9e4da 100644 (file)
@@ -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 (file)
index 0000000..8b409e4
--- /dev/null
@@ -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
index a9118bf..c7f48bc 100644 (file)
@@ -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>
index 902e8d8..978ad20 100644 (file)
@@ -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}
index 2d90802..f383829 100644 (file)
@@ -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 (file)
index 0000000..0f6bead
--- /dev/null
@@ -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);
+}