/* * 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 #include #include #include #include "data/datamgr.h" struct albumdata; typedef bool (*get_album_list)(struct albumdata *ad, const char *cond); typedef int (*media_compare)(struct group_info *gi, struct album_info *ai); typedef void *(*media_compare_data_get)(struct album_info *ai); typedef char *(*group_name_get)(struct album_info *ai); static bool _get_name_list(struct albumdata *ad, const char *cond); static int _compare_name(struct group_info *, struct album_info *); static void *_get_data_name(struct album_info *); static char *_get_name(struct album_info *); static bool _get_artist_list(struct albumdata *ad, const char *cond); static int _compare_artist(struct group_info *, struct album_info *); static void *_get_data_artist(struct album_info *); static char *_get_artist(struct album_info *); enum _filter_type { E_FILTER_ALBUM = 0, E_FILTER_MEDIA }; struct albumdata { Eina_List *album_list; Eina_List *media_list; int group_type; const char *media_type; int source_type; }; struct _group_info { const char *sort_keyword; get_album_list get_list; media_compare media_cmp; media_compare_data_get data_get; group_name_get name_get; }; static struct _group_info g_group_info[E_GROUP_ALBUM_MAX] = { [E_GROUP_ALBUM_NAME] = { .sort_keyword = MEDIA_ALBUM, .get_list = _get_name_list, .media_cmp = _compare_name, .data_get = _get_data_name, .name_get = _get_name, }, [E_GROUP_ALBUM_ARTIST] = { .sort_keyword = MEDIA_ALBUM_ARTIST, .get_list = _get_artist_list, .media_cmp = _compare_artist, .data_get = _get_data_artist, .name_get = _get_artist }, }; static bool _create_filter(struct albumdata *ad, filter_h *filter, const char *cond, int filter_type) { filter_h tmp_filter; int ret; char buf[1024]; ret = media_filter_create(&tmp_filter); if (ret != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to create media filter"); return false; } snprintf(buf, sizeof(buf), "%s", ad->media_type); if (ad->source_type != E_SOURCE_ALL) { char s1[64]; snprintf(s1, sizeof(s1), " AND MEDIA_STORAGE_TYPE=%d", ad->source_type); strncat(buf, s1, strlen(s1)); } if (cond) { char s2[64]; snprintf(s2, sizeof(s2), " AND %s", cond); strncat(buf, s2, strlen(s2)); } media_filter_set_condition(tmp_filter, buf, MEDIA_CONTENT_COLLATE_DEFAULT); if (filter_type == E_FILTER_ALBUM) { media_filter_set_order(tmp_filter, MEDIA_CONTENT_ORDER_ASC, g_group_info[ad->group_type].sort_keyword, MEDIA_CONTENT_COLLATE_DEFAULT); } else if (filter_type == E_FILTER_MEDIA) { media_filter_set_order(tmp_filter, MEDIA_CONTENT_ORDER_ASC, MEDIA_TITLE, MEDIA_CONTENT_COLLATE_DEFAULT); } *filter = tmp_filter; return true; } static int _compare_name(struct group_info *gi, struct album_info *ai) { if (!gi->data || !ai->name) return -1; return strncasecmp(gi->data, ai->name, 1); } static void *_get_data_name(struct album_info *ai) { if (!ai->name) return NULL; return strdup(ai->name); } static char *_get_name(struct album_info *ai) { if (!ai->name) return NULL; return strndup(ai->name, 1); } static int _compare_artist(struct group_info *gi, struct album_info *ai) { if (!gi->data || !ai->artist) return -1; return strncasecmp(gi->data, ai->artist, 1); } static void *_get_data_artist(struct album_info *ai) { if (!ai->artist) return NULL; return strdup(ai->artist); } static char *_get_artist(struct album_info *ai) { if (!ai->artist) return NULL; return strndup(ai->artist, 1); } static void _destroy_media_list(Eina_List *list) { app_media *am; EINA_LIST_FREE(list, am) app_media_destroy(am); } static void _destroy_album_info(struct album_info *ai) { free(ai->name); free(ai->artist); free(ai->album_art); free(ai); } static void _destroy_album_list(Eina_List *list) { struct album_info *ai; EINA_LIST_FREE(list, ai) _destroy_album_info(ai); } static bool _get_each_media_info(media_info_h media_h, void *data) { app_media *am; struct albumdata *ad; if (!data) return false; ad = data; am = app_media_create(media_h); if (!am) { _ERR("failed to create app media"); return false; } ad->media_list = eina_list_append(ad->media_list, am); return true; } static bool _get_each_album_info(media_album_h album, void *data) { filter_h filter; struct albumdata *ad; struct album_info *ai; if (!data) return false; ad = data; ai = calloc(1, sizeof(*ai)); if (!ai) { _ERR("failed to allocate memory"); return false; } if (!_create_filter(ad, &filter, NULL, E_FILTER_ALBUM)) { _ERR("failed to create filter"); free(ai); return false; } if (media_album_get_album_id(album, &(ai->id)) != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to fetch album id"); goto err; } if (media_album_get_name(album, &(ai->name)) != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to fetch album name"); goto err; } if (media_album_get_artist(album, &(ai->artist)) != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to fetch album artist"); goto err; } if (media_album_get_album_art(album, &(ai->album_art)) != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to fetch album art"); goto err; } if (media_album_get_media_count_from_db(ai->id, filter, &(ai->media_count)) != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to get album media count"); goto err; } ad->album_list = eina_list_append(ad->album_list, ai); media_filter_destroy(filter); return true; err: media_filter_destroy(filter); _destroy_album_info(ai); return false; } static bool _get_each_group_info(const char *group_name, void *data) { filter_h filter; struct albumdata *ad; int ret; char buf[1024]; if (!data || !group_name) return false; ad = data; snprintf(buf, sizeof(buf), "MEDIA_ALBUM_ARTIST=\"%s\"", group_name); if (!_create_filter(ad, &filter, buf, E_FILTER_ALBUM)) { _ERR("failed to create filter"); return false; } /* only one album info for the artist */ media_filter_set_offset(filter, 0, 1); ret = media_album_foreach_album_from_db(filter, _get_each_album_info, ad); if (ret != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to get album info"); media_filter_destroy(filter); return false; } media_filter_destroy(filter); return true; } static bool _get_media_list(struct albumdata *ad, int album_id) { filter_h filter; int ret; ret = media_content_connect(); if (ret != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to connect to media content"); return false; } if (!_create_filter(ad, &filter, NULL, E_FILTER_MEDIA)) { _ERR("failed to create filter"); media_content_disconnect(); return false; } ret = media_album_foreach_media_from_db(album_id, filter, _get_each_media_info, ad); if (ret != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to get media info"); _destroy_media_list(ad->media_list); media_filter_destroy(filter); media_content_disconnect(); return false; } media_filter_destroy(filter); media_content_disconnect(); return true; } static bool _get_name_list(struct albumdata *ad, const char *cond) { filter_h filter; int ret; ret = media_content_connect(); if (ret != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to connect to media content"); return false; } if (!_create_filter(ad, &filter, cond, E_FILTER_ALBUM)) { _ERR("failed to create filter"); media_content_disconnect(); return false; } ret = media_album_foreach_album_from_db(filter, _get_each_album_info, ad); if (ret != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to get album info"); _destroy_album_list(ad->album_list); media_filter_destroy(filter); media_content_disconnect(); return false; } media_filter_destroy(filter); media_content_disconnect(); return true; } static bool _get_artist_list(struct albumdata *ad, const char *cond) { filter_h filter; int ret; ret = media_content_connect(); if (ret != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to connect to media content"); return false; } if (!_create_filter(ad, &filter, NULL, E_FILTER_ALBUM)) { _ERR("failed to create filter"); media_content_disconnect(); return false; } ret = media_group_foreach_group_from_db(filter, MEDIA_CONTENT_GROUP_ALBUM_ARTIST, _get_each_group_info, ad); if (ret != MEDIA_CONTENT_ERROR_NONE) { _ERR("failed to get group info"); _destroy_album_list(ad->album_list); media_filter_destroy(filter); media_content_disconnect(); return false; } media_filter_destroy(filter); media_content_disconnect(); return true; } static void *_create(const char *media_type, int source_type) { struct albumdata *ad; if (!media_type || source_type < 0 || source_type >= E_SOURCE_MAX) { _ERR("invalid argument"); return NULL; } ad = calloc(1, sizeof(*ad)); if (!ad) { _ERR("failed to allocate ad"); return NULL; } ad->media_type = media_type; ad->source_type = source_type; return (void *)ad; } static void _destroy(void *handle) { struct albumdata *ad; if (!handle) { _ERR("failed to get albumdata handle"); return; } ad = handle; _destroy_album_list(ad->album_list); _destroy_media_list(ad->media_list); free(ad); } static Eina_List *_get_list(void *handle, int type, void *data) { struct albumdata *ad; int *album_id; char *artist; char buf[64]; if (!handle) { _ERR("failed to get albumdata handle"); return NULL; } if (!data) { _ERR("invalid argument"); return NULL; } ad = handle; switch (type) { case E_LIST_ALBUM_MEDIA: if (ad->media_list) { _destroy_media_list(ad->media_list); ad->media_list = NULL; } album_id = data; _get_media_list(ad, *album_id); return ad->media_list; case E_LIST_ARTIST_ALBUM: if (ad->album_list) { _destroy_album_list(ad->album_list); ad->album_list = NULL; } ad->group_type = E_GROUP_ALBUM_NAME; artist = data; snprintf(buf, sizeof(buf), "MEDIA_ALBUM_ARTIST=\"%s\"", artist); _get_name_list(ad, buf); return ad->album_list; default: break; } return NULL; } static int _get_count(void *handle, int type) { struct albumdata *ad; if (!handle) { _ERR("failed to get albumdata handle"); return -1; } ad = handle; return eina_list_count(ad->album_list); } static void _free_group_list(Eina_List *list) { struct group_info *gi; EINA_LIST_FREE(list, gi) { free(gi->name); free(gi->data); _destroy_album_list(gi->list); free(gi); } } static void _free_group(Eina_List *list) { _free_group_list(list); } static Eina_List *_get_group(void *handle, int type, void *data) { Eina_List *list, *l; struct albumdata *ad; struct group_info *gi; struct album_info *ai; if (!handle) { _ERR("failed to get albumdata handle"); return NULL; } if (type < 0 || type >= E_GROUP_ALBUM_MAX) { _ERR("invalid argument"); return NULL; } ad = handle; ad->group_type = type; if (ad->album_list) { _destroy_album_list(ad->album_list); ad->album_list = NULL; } if (!g_group_info[type].get_list(ad, NULL)) { _ERR("failed to get album list"); return NULL; } gi = NULL; list = NULL; EINA_LIST_FOREACH(ad->album_list, l, ai) { if (!gi || g_group_info[type].media_cmp(gi, ai)) { gi = calloc(1, sizeof(*gi)); if (!gi) { _ERR("failed to create group info"); _free_group_list(list); return NULL; } gi->name = g_group_info[type].name_get(ai); gi->data = g_group_info[type].data_get(ai); list = eina_list_append(list, gi); } gi->list = eina_list_append(gi->list, ai); } eina_list_free(ad->album_list); ad->album_list = NULL; return list; } static struct data_ops _ops = { .create = _create, .destroy = _destroy, .get_list = _get_list, .get_count = _get_count, .get_group = _get_group, .free_group = _free_group, }; struct data_ops *albumdata_get_ops(void) { return &_ops; };