2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "content/content_manager.h"
19 #include <media_content_internal.h>
20 #include <metadata_extractor.h>
30 #include "common/converter.h"
31 #include "common/filesystem/filesystem_provider.h"
32 #include "common/logger.h"
33 #include "common/scope_exit.h"
34 #include "common/tools.h"
36 #include "content/content_filter.h"
39 using namespace common;
41 using common::tools::ReportSuccess;
42 using common::tools::ReportError;
48 static const std::string uri_prefix = "file://";
49 static const std::string uri_absolute_prefix = "file:///";
52 std::string get_date(char* tmpStr) {
55 struct tm* result = (struct tm*)calloc(1, sizeof(struct tm));
56 if (nullptr != result) {
57 if (strptime(tmpStr, "%Y:%m:%d %H:%M:%S", result) == NULL) {
61 time_t t = mktime(result); // + get_utc_offset() * 3600;
62 std::stringstream str_date;
65 return str_date.str();
72 void ContentToJson(media_info_h info, picojson::object& o) {
80 long long unsigned int tmpLong;
81 media_content_type_e type;
83 ret = media_info_get_media_type(info, &type);
85 if (ret != MEDIA_CONTENT_ERROR_NONE) {
86 LoggerE("Get media type failed: %d", ret);
87 type = MEDIA_CONTENT_TYPE_OTHERS;
90 if (type == MEDIA_CONTENT_TYPE_IMAGE) {
91 o["type"] = picojson::value(std::string("IMAGE"));
93 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_image(info, &img)) {
94 std::unique_ptr<std::remove_pointer<image_meta_h>::type, int (*)(image_meta_h)> img_ptr(
95 img, &image_meta_destroy); // automatically release the memory
96 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_date_taken(img, &tmpStr)) {
98 o["releaseDate"] = picojson::value(get_date(tmpStr));
103 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_width(img, &tmpInt)) {
104 o["width"] = picojson::value(static_cast<double>(tmpInt));
106 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_height(img, &tmpInt)) {
107 o["height"] = picojson::value(static_cast<double>(tmpInt));
109 picojson::object geo;
110 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_latitude(info, &tmpDouble)) {
111 geo["latitude"] = picojson::value(tmpDouble);
113 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_longitude(info, &tmpDouble)) {
114 geo["longitude"] = picojson::value(tmpDouble);
116 o["geolocation"] = picojson::value(geo);
118 media_content_orientation_e orientation;
119 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_orientation(img, &orientation)) {
120 switch (orientation) {
121 case MEDIA_CONTENT_ORIENTATION_NOT_AVAILABLE:
122 case MEDIA_CONTENT_ORIENTATION_NORMAL:
125 case MEDIA_CONTENT_ORIENTATION_HFLIP:
126 ori = "FLIP_HORIZONTAL";
128 case MEDIA_CONTENT_ORIENTATION_ROT_180:
131 case MEDIA_CONTENT_ORIENTATION_VFLIP:
132 ori = "FLIP_VERTICAL";
134 case MEDIA_CONTENT_ORIENTATION_TRANSPOSE:
137 case MEDIA_CONTENT_ORIENTATION_ROT_90:
140 case MEDIA_CONTENT_ORIENTATION_TRANSVERSE:
143 case MEDIA_CONTENT_ORIENTATION_ROT_270:
147 o["orientation"] = picojson::value(ori);
150 } else if (type == MEDIA_CONTENT_TYPE_VIDEO) {
151 o["type"] = picojson::value(std::string("VIDEO"));
153 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_video(info, &video)) {
154 std::unique_ptr<std::remove_pointer<video_meta_h>::type, int (*)(video_meta_h)> video_ptr(
155 video, &video_meta_destroy); // automatically release the memory
156 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_width(video, &tmpInt)) {
157 o["width"] = picojson::value(static_cast<double>(tmpInt));
160 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_height(video, &tmpInt)) {
161 o["height"] = picojson::value(static_cast<double>(tmpInt));
163 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_artist(video, &tmpStr)) {
164 picojson::array artists;
166 artists.push_back(picojson::value(std::string(tmpStr)));
170 o["artists"] = picojson::value(artists);
172 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_album(video, &tmpStr)) {
174 o["album"] = picojson::value(tmpStr);
179 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_duration(video, &tmpInt)) {
180 o["duration"] = picojson::value(static_cast<double>(tmpInt));
182 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_recorded_date(video, &tmpStr)) {
184 o["releaseDate"] = picojson::value(get_date(tmpStr));
190 picojson::object geo;
191 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_latitude(info, &tmpDouble)) {
192 geo["latitude"] = picojson::value(tmpDouble);
194 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_longitude(info, &tmpDouble)) {
195 geo["longitude"] = picojson::value(tmpDouble);
197 o["geolocation"] = picojson::value(geo);
198 } else if (type == MEDIA_CONTENT_TYPE_SOUND || type == MEDIA_CONTENT_TYPE_MUSIC) {
199 o["type"] = picojson::value(std::string("AUDIO"));
201 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_audio(info, &audio)) {
202 std::unique_ptr<std::remove_pointer<audio_meta_h>::type, int (*)(audio_meta_h)> audio_ptr(
203 audio, &audio_meta_destroy); // automatically release the memory
204 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_recorded_date(audio, &tmpStr)) {
206 o["releaseDate"] = picojson::value(get_date(tmpStr));
211 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_album(audio, &tmpStr)) {
213 o["album"] = picojson::value(std::string(tmpStr));
218 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_artist(audio, &tmpStr)) {
220 picojson::array artists;
221 artists.push_back(picojson::value(std::string(tmpStr)));
222 o["artists"] = picojson::value(artists);
227 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_genre(audio, &tmpStr)) {
229 picojson::array genres;
230 genres.push_back(picojson::value(std::string(tmpStr)));
231 o["genres"] = picojson::value(genres);
236 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_composer(audio, &tmpStr)) {
238 picojson::array composers;
239 composers.push_back(picojson::value(std::string(tmpStr)));
240 o["composers"] = picojson::value(composers);
245 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_copyright(audio, &tmpStr)) {
247 o["copyright"] = picojson::value(std::string(tmpStr));
252 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_bit_rate(audio, &tmpInt)) {
253 o["bitrate"] = picojson::value(static_cast<double>(tmpInt));
255 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_track_num(audio, &tmpStr)) {
257 o["trackNumber"] = picojson::value(static_cast<double>(std::atoi(tmpStr)));
261 o["trackNumber"] = picojson::value();
264 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_duration(audio, &tmpInt)) {
265 o["duration"] = picojson::value(static_cast<double>(tmpInt));
269 o["type"] = picojson::value(std::string("OTHER"));
272 ret = media_info_get_media_id(info, &tmpStr);
273 if (ret == MEDIA_CONTENT_ERROR_NONE) {
275 o["id"] = picojson::value(std::string(tmpStr));
280 ret = media_info_get_display_name(info, &tmpStr);
281 if (ret == MEDIA_CONTENT_ERROR_NONE) {
283 o["name"] = picojson::value(std::string(tmpStr));
289 ret = media_info_get_mime_type(info, &tmpStr);
290 if (ret == MEDIA_CONTENT_ERROR_NONE) {
292 o["mimeType"] = picojson::value(std::string(tmpStr));
297 ret = media_info_get_title(info, &tmpStr);
298 if (ret == MEDIA_CONTENT_ERROR_NONE) {
300 o["title"] = picojson::value(std::string(tmpStr));
305 ret = media_info_get_file_path(info, &tmpStr);
306 if (ret == MEDIA_CONTENT_ERROR_NONE) {
308 o["contentURI"] = picojson::value(std::string(tmpStr));
313 ret = media_info_get_thumbnail_path(info, &tmpStr);
314 if (ret == MEDIA_CONTENT_ERROR_NONE) {
316 picojson::array thumbnails;
317 thumbnails.push_back(picojson::value(std::string(tmpStr)));
318 o["thumbnailURIs"] = picojson::value(thumbnails);
323 ret = media_info_get_description(info, &tmpStr);
324 if (ret == MEDIA_CONTENT_ERROR_NONE) {
326 o["description"] = picojson::value(std::string(tmpStr));
331 ret = media_info_get_rating(info, &tmpInt);
332 if (ret == MEDIA_CONTENT_ERROR_NONE) {
333 o["rating"] = picojson::value(static_cast<double>(tmpInt));
335 ret = media_info_get_size(info, &tmpLong);
336 if (ret == MEDIA_CONTENT_ERROR_NONE) {
337 o["size"] = picojson::value(static_cast<double>(tmpLong));
339 ret = media_info_get_favorite(info, &tmpBool);
340 if (ret == MEDIA_CONTENT_ERROR_NONE) {
341 o["isFavorite"] = picojson::value(tmpBool);
343 ret = media_info_get_modified_time(info, &tmpDate);
344 if (ret == MEDIA_CONTENT_ERROR_NONE) {
345 o["modifiedDate"] = picojson::value(static_cast<double>(tmpDate));
349 void ContentDirToJson(media_folder_h folder, picojson::object& o) {
353 media_content_storage_e storage_type;
356 ret = media_folder_get_folder_id(folder, &tmpStr);
357 if (ret == MEDIA_CONTENT_ERROR_NONE) {
359 o["id"] = picojson::value(std::string(tmpStr));
366 std::string folder_path;
367 ret = media_folder_get_path(folder, &tmpStr);
368 if (ret == MEDIA_CONTENT_ERROR_NONE) {
370 o["directoryURI"] = picojson::value(std::string(tmpStr));
371 // folder_path value kept for modifiedDate property gathering
372 folder_path = tmpStr;
379 ret = media_folder_get_name(folder, &tmpStr);
380 if (ret == MEDIA_CONTENT_ERROR_NONE) {
382 o["title"] = picojson::value(std::string(tmpStr));
389 ret = media_folder_get_storage_type(folder, &storage_type);
390 // TODO: The function media_folder_get_storage_type is marked as deprecated since 5.0.
391 // As an alternative, it is recommended to use storage_get_type_dev function. However,
392 // this function does not work with internal storages. The media_folder_get_storage_type
393 // function should be kept or moved to internal header by Native API.
394 if (ret == MEDIA_CONTENT_ERROR_NONE) {
395 if (storage_type == MEDIA_CONTENT_STORAGE_INTERNAL) {
396 o["storageType"] = picojson::value(std::string("INTERNAL"));
398 LoggerD("storageType = %d, assuming EXTERNAL as storage type", storage_type);
399 o["storageType"] = picojson::value(std::string("EXTERNAL"));
404 struct stat stat_res;
405 if (stat(folder_path.c_str(), &stat_res) == 0) {
406 auto mod_time = stat_res.st_mtime;
407 o["modifiedDate"] = picojson::value(static_cast<double>(mod_time));
411 static int setContent(media_info_h media, const picojson::value& content) {
414 int ret = MEDIA_CONTENT_ERROR_NONE;
415 bool is_fav = content.get("isFavorite").get<bool>();
418 LoggerE("MEDIA_CONTENT_ERROR_DB_FAILED");
419 return MEDIA_CONTENT_ERROR_DB_FAILED;
422 media_content_type_e type;
423 ret = media_info_get_media_type(media, &type);
424 if (ret != MEDIA_CONTENT_ERROR_NONE) {
425 LoggerE("Failed: media_info_get_media_type()");
429 ret = media_info_set_favorite(media, is_fav);
430 if (ret != MEDIA_CONTENT_ERROR_NONE) {
431 LoggerE("Updating isFavorite failed.");
434 if (ret != MEDIA_CONTENT_ERROR_NONE) {
435 LoggerE("Updating favorite failed.");
438 return MEDIA_CONTENT_ERROR_NONE;
441 static int updateContent(const picojson::value& content) {
444 int ret = MEDIA_CONTENT_ERROR_NONE;
445 std::string id = content.get("id").to_str();
446 media_info_h media = nullptr;
449 media_info_destroy(media);
453 ret = media_info_get_media_from_db(id.c_str(), &media);
454 if (ret != MEDIA_CONTENT_ERROR_NONE) {
455 LoggerE("media_info_get_media_from_db failed: %d", ret);
458 ret = setContent(media, content);
459 if (ret != MEDIA_CONTENT_ERROR_NONE) {
460 LoggerE("setContent failed: %d", ret);
463 ret = media_info_update_to_db(media);
464 if (ret != MEDIA_CONTENT_ERROR_NONE) {
465 LoggerE("media_info_update_to_db failed: %d", ret);
472 static void FolderToJson(media_folder_h folder, picojson::object* out) {
479 media_content_storage_e storageType;
483 ret = media_folder_get_folder_id(folder, &id);
484 if (ret != MEDIA_CONTENT_ERROR_NONE) {
485 LogAndReportError(ContentManager::convertError(ret), out,
486 ("Failed: media_folder_get_folder_id"));
489 std::unique_ptr<char, decltype(&free)> id_ptr(id, &free);
491 ret = media_folder_get_name(folder, &name);
492 if (ret != MEDIA_CONTENT_ERROR_NONE) {
493 LogAndReportError(ContentManager::convertError(ret), out, ("Failed: media_folder_get_name"));
496 std::unique_ptr<char, decltype(&free)> name_ptr(name, &free);
498 ret = media_folder_get_path(folder, &path);
499 if (ret != MEDIA_CONTENT_ERROR_NONE) {
500 LogAndReportError(ContentManager::convertError(ret), out, ("Failed: media_folder_get_path"));
503 std::unique_ptr<char, decltype(&free)> path_ptr(path, &free);
505 struct stat stat_res;
506 ret = stat(path, &stat_res);
508 LogAndReportError(ContentManager::convertError(errno), out, ("Failed: stat"));
511 date = stat_res.st_mtime;
513 ret = media_folder_get_storage_type(folder, &storageType);
514 // TODO: The function media_folder_get_storage_type is marked as deprecated since 5.0.
515 // As an alternative, it is recommended to use storage_get_type_dev function. However,
516 // this function does not work with internal storages. The media_folder_get_storage_type
517 // function should be kept or moved to internal header by Native API.
518 if (ret != MEDIA_CONTENT_ERROR_NONE) {
519 LogAndReportError(ContentManager::convertError(ret), out,
520 ("Failed: media_folder_get_storage_type"));
524 (*out)["id"] = picojson::value(std::string(id));
525 (*out)["directoryURI"] = picojson::value(std::string(path));
526 (*out)["title"] = picojson::value(std::string(name));
528 if (storageType == MEDIA_CONTENT_STORAGE_INTERNAL) {
529 (*out)["storageType"] = picojson::value(std::string("INTERNAL"));
530 } else if (storageType == MEDIA_CONTENT_STORAGE_EXTERNAL) {
531 (*out)["storageType"] = picojson::value(std::string("EXTERNAL"));
534 (*out)["modifiedDate"] = picojson::value(static_cast<double>(date));
537 static bool media_foreach_directory_cb(media_folder_h folder, void* user_data) {
539 picojson::array* array = static_cast<picojson::array*>(user_data);
540 picojson::object json;
541 FolderToJson(folder, &json);
542 array->push_back(picojson::value(json));
546 static bool media_foreach_content_cb(media_info_h media, void* user_data) {
548 picojson::value::array* contents = static_cast<picojson::value::array*>(user_data);
549 picojson::value::object o;
550 ContentToJson(media, o);
551 contents->push_back(picojson::value(o));
555 static bool playlist_foreach_cb(media_playlist_h playlist, void* user_data) {
557 picojson::value::array* playlists = static_cast<picojson::value::array*>(user_data);
558 picojson::value::object o;
559 if (playlist != NULL) {
561 char* thumb_path = NULL;
563 filter_h filter = NULL;
564 if (media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
565 std::stringstream str_id;
567 o["id"] = picojson::value(std::to_string(id));
569 LoggerD("Invalid ID for playlist.");
571 if (media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
572 if (thumb_path != NULL) {
573 std::string thumbnail_uri(thumb_path);
574 if (thumbnail_uri != " ") {
575 thumbnail_uri = uri_prefix + thumbnail_uri;
577 o["thumbnailURI"] = picojson::value(thumbnail_uri);
580 o["thumbnailURI"] = picojson::value(); // picojson::value(std::string(""));
583 LoggerD("Invalid thumbnail path for playlist.");
585 if (media_playlist_get_name(playlist, &name) == MEDIA_CONTENT_ERROR_NONE) {
586 o["name"] = picojson::value(std::string(name));
589 LoggerD("Invalid name for playlist.");
592 media_filter_create(&filter);
593 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
594 filter, &media_filter_destroy); // automatically release the memory
595 if (media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
596 o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
598 LoggerE("Invalid count for playlist.");
600 playlists->push_back(picojson::value(o));
605 static bool playlist_content_member_cb(int playlist_member_id, media_info_h media,
608 picojson::value::array* contents = static_cast<picojson::value::array*>(user_data);
609 picojson::value::object o;
611 o["playlist_member_id"] = picojson::value(static_cast<double>(playlist_member_id));
612 ContentToJson(media, o);
613 contents->push_back(picojson::value(o));
617 ContentManager::ContentManager() {
618 ScopeLogger("ContentManager called");
619 if (media_content_connect() == MEDIA_CONTENT_ERROR_NONE) {
620 m_dbConnected = true;
622 m_dbConnected = false;
624 m_contentInstance = nullptr;
627 ContentManager::~ContentManager() {
630 if (media_content_disconnect() == MEDIA_CONTENT_ERROR_NONE) {
631 m_dbConnected = false;
636 ContentManager* ContentManager::getInstance() {
638 static ContentManager instance;
642 ContentInstance* ContentManager::getContentInstance() {
644 return m_contentInstance;
647 void ContentManager::setContentInstance(ContentInstance* const content_instance) {
649 m_contentInstance = content_instance;
652 bool ContentManager::isConnected() {
654 return m_dbConnected;
657 void ContentManager::getDirectories(const std::shared_ptr<ReplyCallbackData>& user_data) {
660 filter_h filter = NULL;
661 ret = media_filter_create(&filter);
662 if (ret != MEDIA_CONTENT_ERROR_NONE) {
663 LoggerE("Failed: media_filter_create failed");
668 media_filter_destroy(filter);
671 std::string condition = "(FOLDER_STORAGE_TYPE = 0 OR FOLDER_STORAGE_TYPE = 1)";
672 media_filter_set_condition(filter, condition.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
674 picojson::array pico_dirs;
675 ret = media_folder_foreach_folder_from_db(filter, media_foreach_directory_cb, &pico_dirs);
676 if (ret != MEDIA_CONTENT_ERROR_NONE) {
677 PlatformResult err = LogAndCreateResult(
678 ErrorCode::UNKNOWN_ERR, "Getting the directories failed.",
679 ("Failed: Getting the directories failed %d (%s)", ret, get_error_message(ret)));
680 user_data->isSuccess = err;
684 user_data->result = picojson::value(pico_dirs);
687 void ContentManager::find(const std::shared_ptr<ReplyCallbackData>& user_data) {
694 picojson::value::array arrayContent;
695 filter_h filter = nullptr;
696 media_filter_create(&filter);
699 media_filter_destroy(filter);
703 if (!IsNull(user_data->args.get("filter"))) {
704 ContentFilter filterMechanism;
706 picojson::object argsObject = JsonCast<picojson::object>(user_data->args);
707 if (filterMechanism.BuildQuery(FromJson<picojson::object>(argsObject, "filter"), &query)) {
708 LoggerD("Filter query: %s", query.c_str());
709 ret = media_filter_set_condition(filter, query.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
710 if (MEDIA_CONTENT_ERROR_NONE != ret) {
711 LoggerE("Platform filter setting failed, error %d", ret);
716 if (user_data->args.contains("sortMode")) {
717 picojson::value vSortMode = user_data->args.get("sortMode");
719 if (vSortMode.is<picojson::object>()) {
720 std::string sortModeName, sortModeOrder;
722 ContentFilter::MapField(vSortMode.get("attributeName").to_str(), &sortModeName);
724 sortModeOrder = vSortMode.get("order").to_str();
725 if (!sortModeOrder.empty()) {
726 media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
728 if (sortModeOrder == "ASC") {
729 order = MEDIA_CONTENT_ORDER_ASC;
730 } else if (sortModeOrder == "DESC") {
731 order = MEDIA_CONTENT_ORDER_DESC;
734 ret = media_filter_set_order(filter, order, sortModeName.c_str(),
735 MEDIA_CONTENT_COLLATE_DEFAULT);
736 if (MEDIA_CONTENT_ERROR_NONE != ret) {
737 LoggerE("Platform SortMode setting failed, error: %d", ret);
743 if (!IsNull(user_data->args.get("count"))) {
744 count = static_cast<int>(user_data->args.get("count").get<double>());
748 if (!IsNull(user_data->args.get("offset"))) {
749 offset = static_cast<int>(user_data->args.get("offset").get<double>());
753 ret = media_filter_set_offset(filter, offset, count);
754 if (MEDIA_CONTENT_ERROR_NONE != ret) {
755 LoggerE("A platform error occurs in media_filter_set_offset: %d", ret);
757 if (!IsNull(user_data->args.get("directoryId"))) {
758 dirId = user_data->args.get("directoryId").get<std::string>();
759 ret = media_folder_foreach_media_from_db(dirId.c_str(), filter, media_foreach_content_cb,
760 static_cast<void*>(&arrayContent));
762 ret = media_info_foreach_media_from_db(filter, media_foreach_content_cb,
763 static_cast<void*>(&arrayContent));
766 if (ret == MEDIA_CONTENT_ERROR_NONE) {
767 user_data->result = picojson::value(arrayContent);
769 PlatformResult err = LogAndCreateResult(
770 ErrorCode::UNKNOWN_ERR, "The iteration failed in platform",
771 ("The iteration failed in platform: %d (%s)", ret, get_error_message(ret)));
772 user_data->isSuccess = err;
776 int ContentManager::scanFile(std::string& uri) {
778 return media_content_scan_file(uri.c_str());
781 PlatformResult ContentManager::scanDirectory(media_scan_completed_cb callback,
782 ReplyCallbackData* cbData) {
784 const std::string& contentDirURI = cbData->args.get("contentDirURI").get<std::string>();
785 std::string real_path = common::FilesystemProvider::Create().GetRealPath(contentDirURI);
786 const bool recursive = cbData->args.get("recursive").get<bool>();
788 int ret = media_content_scan_folder(real_path.c_str(), recursive, callback, (void*)cbData);
790 if (ret != MEDIA_CONTENT_ERROR_NONE) {
791 if (MEDIA_CONTENT_ERROR_INVALID_PARAMETER == ret) {
792 return LogAndCreateResult(
793 ErrorCode::INVALID_VALUES_ERR, "Scanning content directory failed",
794 ("Scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
797 return LogAndCreateResult(
798 ErrorCode::UNKNOWN_ERR, "Scanning content directory failed",
799 ("Scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
802 return PlatformResult(ErrorCode::NO_ERROR);
805 PlatformResult ContentManager::cancelScanDirectory(const std::string& content_dir_uri) {
808 int ret = media_content_cancel_scan_folder(content_dir_uri.c_str());
809 if (ret != MEDIA_CONTENT_ERROR_NONE) {
810 return LogAndCreateResult(
811 ErrorCode::UNKNOWN_ERR, "Cancel scan content directory failed",
812 ("Cancel scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
814 return PlatformResult(ErrorCode::NO_ERROR);
817 PlatformResult ContentManager::addChangeListener(media_content_noti_h* noti_handle,
818 media_content_db_update_cb callback,
822 int ret = media_content_add_db_updated_cb(callback, user_data, noti_handle);
824 if (MEDIA_CONTENT_ERROR_NONE != ret) {
825 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to add the listener.",
826 ("Failed to add the listener: %d (%s)", ret, get_error_message(ret)));
829 return PlatformResult(ErrorCode::NO_ERROR);
832 PlatformResult ContentManager::removeChangeListener(media_content_noti_h noti_handle) {
835 int ret = media_content_remove_db_updated_cb(noti_handle);
838 case MEDIA_CONTENT_ERROR_NONE:
839 return PlatformResult(ErrorCode::NO_ERROR);
840 case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
841 // Trying to remove non-existent listener, ignoring
842 LoggerI("Failed to remove the listener: %d (%s)", ret, get_error_message(ret));
843 return PlatformResult(ErrorCode::NO_ERROR);
845 return LogAndCreateResult(
846 ErrorCode::ABORT_ERR, "Failed to remove the listener.",
847 ("Failed to remove the listener: %d (%s)", ret, get_error_message(ret)));
851 void ContentManager::createPlaylist(std::string name,
852 const std::shared_ptr<ReplyCallbackData>& user_data) {
854 media_playlist_h playlist = NULL;
856 int ret = media_playlist_insert_to_db(name.c_str(), &playlist);
857 std::unique_ptr<std::remove_pointer<media_playlist_h>::type, int (*)(media_playlist_h)>
858 playlist_ptr(playlist, &media_playlist_destroy); // automatically release the memory
859 if (ret != MEDIA_CONTENT_ERROR_NONE) {
860 // MEDIA_CONTENT_ERROR_DB_FAILED means that playlist probably already exists
861 PlatformResult err = LogAndCreateResult(
862 MEDIA_CONTENT_ERROR_DB_FAILED == ret ? ErrorCode::INVALID_VALUES_ERR
863 : ErrorCode::UNKNOWN_ERR,
864 "Creation of playlist has failed.",
865 ("Failed: creation of playlist is failed: %d (%s)", ret, get_error_message(ret)));
866 user_data->isSuccess = err;
869 picojson::value::object o;
871 if (playlist != NULL) {
873 char* thumb_path = NULL;
874 char* name_playlist = NULL;
875 filter_h filter = NULL;
876 if (media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
877 o["id"] = picojson::value(std::to_string(id));
880 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "loading of playlist is failed.");
881 user_data->isSuccess = err;
884 if (media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
885 if (thumb_path != NULL) {
886 o["thumbnailURI"] = picojson::value(std::string(thumb_path));
889 o["thumbnailURI"] = picojson::value();
892 LoggerE("Invalid thumbnail path for playlist.");
894 if (media_playlist_get_name(playlist, &name_playlist) == MEDIA_CONTENT_ERROR_NONE) {
895 o["name"] = picojson::value(std::string(name_playlist));
898 LoggerE("Invalid name for playlist.");
900 media_filter_create(&filter);
901 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
902 filter, &media_filter_destroy); // automatically release the memory
904 if (media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
905 o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
907 LoggerE("Invalid count for playlist.");
911 user_data->result = picojson::value(o);
914 void ContentManager::getPlaylists(const std::shared_ptr<ReplyCallbackData>& user_data) {
917 filter_h filter = nullptr;
918 media_filter_create(&filter);
919 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
920 filter, &media_filter_destroy); // automatically release the memory
921 picojson::value::array playlists;
923 ret = media_playlist_foreach_playlist_from_db(filter, playlist_foreach_cb,
924 static_cast<void*>(&playlists));
926 if (ret != MEDIA_CONTENT_ERROR_NONE) {
927 PlatformResult err = LogAndCreateResult(
928 ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
929 ("Failed: Getting playlist is failed %d (%s)", ret, get_error_message(ret)));
930 user_data->isSuccess = err;
933 user_data->result = picojson::value(playlists);
936 void ContentManager::removePlaylist(std::string playlistId,
937 const std::shared_ptr<ReplyCallbackData>& user_data) {
939 int id = std::atoi(playlistId.c_str());
941 PlatformResult err = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "PlaylistId is wrong.");
942 user_data->isSuccess = err;
946 int ret = media_playlist_delete_from_db(id);
947 if (ret != MEDIA_CONTENT_ERROR_NONE) {
949 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Removal of playlist is failed.");
950 user_data->isSuccess = err;
954 int ContentManager::update(const picojson::value& args) {
956 const picojson::value content = args.get("content");
957 int ret = updateContent(content);
958 if (ret != MEDIA_CONTENT_ERROR_NONE) {
959 LoggerE("updateContent failed: %d", ret);
964 int ContentManager::updateBatch(const picojson::value& args) {
966 int ret = MEDIA_CONTENT_ERROR_NONE;
967 std::vector<picojson::value> contents = args.get("contents").get<picojson::array>();
969 for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
970 const picojson::value content = *it;
971 ret = updateContent(content);
972 if (ret != MEDIA_CONTENT_ERROR_NONE) {
973 LoggerE("updateContent failed: %d", ret);
980 int ContentManager::playlistAdd(std::string playlist_id, std::string content_id) {
983 media_playlist_h playlist = NULL;
984 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
986 if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
987 ret = media_playlist_add_media(playlist, content_id.c_str());
988 if (ret != MEDIA_CONTENT_ERROR_NONE) {
989 LoggerE("The content(id:%s) can't add to playlist", content_id.c_str());
992 ret = media_playlist_update_to_db(playlist);
993 if (ret != MEDIA_CONTENT_ERROR_NONE) {
994 LoggerE("The content(id:%s) can't add to playlist", content_id.c_str());
997 LoggerE("Playlist(id:%s) is not exist", playlist_id.c_str());
1000 media_playlist_destroy(playlist);
1004 int ContentManager::playlistRemove(std::string playlist_id, int member_id) {
1007 media_playlist_h playlist = NULL;
1008 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1009 if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1010 ret = media_playlist_remove_media(playlist, member_id);
1011 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1012 LoggerE("The content can't remove to playlist");
1015 ret = media_playlist_update_to_db(playlist);
1016 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1017 LoggerE("The content can't remove to playlist");
1020 LoggerE("Playlist(id:%s) is not exist", playlist_id.c_str());
1022 media_playlist_destroy(playlist);
1027 void ContentManager::playlistAddbatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
1029 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1031 media_playlist_h playlist = NULL;
1032 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1034 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1035 PlatformResult err =
1036 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1037 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1038 user_data->isSuccess = err;
1042 std::vector<picojson::value> contents = user_data->args.get("contents").get<picojson::array>();
1043 for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
1044 picojson::value content = *it;
1045 std::string id = content.get("id").to_str();
1046 ret = media_playlist_add_media(playlist, id.c_str());
1047 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1048 LoggerE("Adding Content(id:%s) is failed.", id.c_str());
1052 ret = media_playlist_update_to_db(playlist);
1053 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1054 PlatformResult err =
1055 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Adding playlist is failed.",
1056 ("Adding playlist is failed: %d (%s)", ret, get_error_message(ret)));
1057 user_data->isSuccess = err;
1059 media_playlist_destroy(playlist);
1062 void ContentManager::playlistGet(const std::shared_ptr<ReplyCallbackData>& user_data) {
1064 media_playlist_h playlist = NULL;
1065 media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
1066 const std::string playOrder("playlist_member_order");
1070 media_playlist_destroy(playlist);
1074 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1075 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1076 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1077 PlatformResult err =
1078 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1079 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1080 user_data->isSuccess = err;
1084 filter_h filter = NULL;
1085 ret = media_filter_create(&filter);
1086 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1087 PlatformResult err =
1088 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.",
1089 ("Creating a filter is failed: %d (%s)", ret, get_error_message(ret)));
1090 user_data->isSuccess = err;
1094 int count = user_data->args.get("count").get<double>();
1095 int offset = user_data->args.get("offset").get<double>();
1096 ret = media_filter_set_offset(filter, offset, count);
1097 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1098 LoggerD("Setting a offset/count is failed.");
1100 ret = media_filter_set_order(filter, order, playOrder.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
1101 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1102 LoggerD("Setting a offset/count is failed.");
1105 picojson::value::array arrayContent;
1106 ret = media_playlist_foreach_media_from_db(std::stoi(playlist_id), filter,
1107 playlist_content_member_cb,
1108 static_cast<void*>(&arrayContent));
1110 media_filter_destroy(filter);
1111 if (ret == MEDIA_CONTENT_ERROR_NONE) {
1112 user_data->result = picojson::value(arrayContent);
1114 PlatformResult err =
1115 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.",
1116 ("Creating a filter is failed: %d (%s)", ret, get_error_message(ret)));
1117 user_data->isSuccess = err;
1121 void ContentManager::playlistRemovebatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
1123 media_playlist_h playlist = NULL;
1127 media_playlist_destroy(playlist);
1131 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1132 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1133 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1134 PlatformResult err =
1135 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1136 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1137 user_data->isSuccess = err;
1141 std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
1142 std::size_t members_size = members.size();
1143 for (std::size_t i = 0; i < members_size; ++i) {
1144 int member_id = static_cast<int>(members.at(i).get<double>());
1145 ret = media_playlist_remove_media(playlist, member_id);
1147 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1148 LoggerD("Removing a content is failed.");
1152 ret = media_playlist_update_to_db(playlist);
1153 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1154 PlatformResult err = LogAndCreateResult(
1155 ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.",
1156 ("Removing the contents is failed: %d (%s)", ret, get_error_message(ret)));
1157 user_data->isSuccess = err;
1161 void ContentManager::playlistSetOrder(const std::shared_ptr<ReplyCallbackData>& user_data) {
1163 media_playlist_h playlist = NULL;
1167 media_playlist_destroy(playlist);
1171 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1172 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1173 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1174 PlatformResult err =
1175 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1176 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1177 user_data->isSuccess = err;
1182 std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
1184 ret = media_playlist_get_media_count_from_db(std::stoi(playlist_id), NULL, &cnt);
1185 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1186 LoggerE("Failed: media_playlist_get_media_count_from_db");
1187 PlatformResult err = convertError(ret);
1188 user_data->isSuccess = err;
1191 std::size_t members_size = members.size();
1192 if (cnt < 0 || static_cast<size_t>(cnt) != members_size) {
1193 PlatformResult err = LogAndCreateResult(
1194 ErrorCode::INVALID_VALUES_ERR,
1195 "The items array does not contain all items from the playlist.",
1196 ("Failed: The items array does not contain all items from the playlist: %d (%s)", ret,
1197 get_error_message(ret)));
1198 user_data->isSuccess = err;
1202 for (std::size_t i = 0; i < members_size; ++i) {
1203 int member_id = static_cast<int>(members.at(i).get<double>());
1204 ret = media_playlist_set_play_order(playlist, member_id, i);
1205 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1206 LoggerD("Removing a content is failed.");
1210 ret = media_playlist_update_to_db(playlist);
1211 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1212 PlatformResult err = LogAndCreateResult(
1213 ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.",
1214 ("Removing the contents is failed: %d (%s)", ret, get_error_message(ret)));
1215 user_data->isSuccess = err;
1219 void ContentManager::playlistMove(const std::shared_ptr<ReplyCallbackData>& user_data) {
1221 media_playlist_h playlist = NULL;
1225 media_playlist_destroy(playlist);
1229 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1230 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1231 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1232 PlatformResult err =
1233 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1234 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1235 user_data->isSuccess = err;
1239 double member_id = user_data->args.get("memberId").get<double>();
1240 double delta = user_data->args.get("delta").get<double>();
1241 ret = media_playlist_get_play_order(playlist, static_cast<int>(member_id), &old_order);
1242 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1243 PlatformResult err = LogAndCreateResult(
1244 ErrorCode::UNKNOWN_ERR, "The content can't find form playlist.",
1245 ("The content can't find form playlist: %d (%s)", ret, get_error_message(ret)));
1246 user_data->isSuccess = err;
1249 int new_order = static_cast<int>(old_order) + static_cast<int>(delta);
1250 ret = media_playlist_set_play_order(playlist, static_cast<int>(member_id), new_order);
1251 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1252 PlatformResult err = LogAndCreateResult(
1253 ErrorCode::UNKNOWN_ERR, "The content can't update play_order.",
1254 ("The content can't update play_order: %d (%s)", ret, get_error_message(ret)));
1255 user_data->isSuccess = err;
1258 ret = media_playlist_update_to_db(playlist);
1259 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1260 PlatformResult err = LogAndCreateResult(
1261 ErrorCode::UNKNOWN_ERR, "Updateing play_order is failed.",
1262 ("Updateing play_order is failed: %d (%s)", ret, get_error_message(ret)));
1263 user_data->isSuccess = err;
1267 int ContentManager::getLyrics(const picojson::value& args, picojson::object& result) {
1270 int ret = METADATA_EXTRACTOR_ERROR_NONE;
1271 const std::string& contentURI = args.get("contentURI").to_str();
1272 if (contentURI.empty()) {
1273 LoggerE("contentURI empty - skipping media extractor");
1277 metadata_extractor_h extractor;
1278 ret = metadata_extractor_create(&extractor);
1279 if (METADATA_EXTRACTOR_ERROR_NONE != ret) {
1280 LoggerE("metadata_extractor_create failed, error: %d", ret);
1282 std::unique_ptr<std::remove_pointer<metadata_extractor_h>::type, int (*)(metadata_extractor_h)>
1283 extractor_ptr(extractor, &metadata_extractor_destroy); // automatically release the memory
1285 ret = metadata_extractor_set_path(extractor, contentURI.c_str());
1286 if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
1287 LoggerE("metadata_extractor_set_path failed, error: %d", ret);
1290 picojson::array timestamps;
1291 picojson::array texts = picojson::array();
1292 char* strSyncTextNum = NULL;
1294 ret = metadata_extractor_get_metadata(extractor, METADATA_SYNCLYRICS_NUM, &strSyncTextNum);
1295 if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
1296 LoggerE("Media extractor error %d", ret);
1300 int nSyncTextNum = 0;
1301 if (strSyncTextNum) {
1302 nSyncTextNum = atoi(strSyncTextNum);
1303 free(strSyncTextNum);
1304 strSyncTextNum = NULL;
1306 if (nSyncTextNum > 0) {
1307 result["type"] = picojson::value(std::string("SYNCHRONIZED"));
1308 for (int i = 0; i < nSyncTextNum; i++) {
1309 unsigned long time_info = 0;
1310 char* lyrics = NULL;
1311 ret = metadata_extractor_get_synclyrics(extractor, i, &time_info, &lyrics);
1312 if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
1313 timestamps.push_back(picojson::value(static_cast<double>(time_info)));
1314 texts.push_back(picojson::value(std::string(lyrics)));
1318 result["texts"] = picojson::value(texts);
1319 result["timestamps"] = picojson::value(timestamps);
1320 ret = METADATA_EXTRACTOR_ERROR_NONE;
1322 char* unSyncText = nullptr;
1323 ret = metadata_extractor_get_metadata(extractor, METADATA_UNSYNCLYRICS, &unSyncText);
1324 if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
1325 result["type"] = picojson::value(std::string("UNSYNCHRONIZED"));
1326 if (nullptr == unSyncText) {
1327 LoggerE("Unsynchronized lyrics text is NULL");
1329 texts.push_back(picojson::value(unSyncText ? unSyncText : ""));
1330 result["texts"] = picojson::value(texts);
1338 media_playlist_h getPlaylistHandle(int id) {
1340 media_playlist_h playlist_handle = nullptr;
1341 int ret_code = media_playlist_get_playlist_from_db(id, &playlist_handle);
1342 if (MEDIA_CONTENT_ERROR_NONE != ret_code || playlist_handle == nullptr) {
1343 LoggerE("could not get playlist handle for id: %d", id);
1347 return playlist_handle;
1350 void destroyMediaPlaylistHandle(media_playlist_h playlist_handle) {
1352 if (playlist_handle) {
1353 int ret_code = media_playlist_destroy(playlist_handle);
1354 playlist_handle = nullptr;
1356 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1357 LoggerE("media_playlist_destroy failed");
1362 int ContentManager::getPlaylistName(int id, std::string* result) {
1364 media_playlist_h playlist_handle = getPlaylistHandle(id);
1365 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1367 char* tmp_playlist_name = nullptr;
1368 const int ret_code = media_playlist_get_name(playlist_handle, &tmp_playlist_name);
1370 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1371 LoggerE("media_playlist_get_name failed");
1372 return TIZEN_ERROR_UNKNOWN;
1375 std::string playlist_name;
1376 if (tmp_playlist_name) {
1377 playlist_name = tmp_playlist_name;
1378 free(tmp_playlist_name);
1379 tmp_playlist_name = nullptr;
1382 *result = playlist_name;
1383 return MEDIA_CONTENT_ERROR_NONE;
1386 int updatePlaylistInDB(media_playlist_h playlist_handle) {
1388 int ret_code = media_playlist_update_to_db(playlist_handle);
1389 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1390 LoggerE("media_playlist_update_to_db failed");
1393 return MEDIA_CONTENT_ERROR_NONE;
1396 int ContentManager::setPlaylistName(int id, const std::string& name) {
1399 LoggerE("Cannot set empty playlist name!");
1400 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1403 media_playlist_h playlist_handle = getPlaylistHandle(id);
1404 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1406 const int ret_code = media_playlist_set_name(playlist_handle, name.c_str());
1407 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1408 LoggerE("media_playlist_set_name failed");
1409 // Setting name that is used by other playlist does not return bad error code here.
1410 // MEDIA_CONTENT_ERROR_INVALID_OPERATION is being returned in updatePlaylistInDB
1411 return TIZEN_ERROR_UNKNOWN;
1414 int ret = updatePlaylistInDB(playlist_handle);
1415 if (MEDIA_CONTENT_ERROR_NONE != ret) {
1416 LoggerE("Error while updating playlist: %d", ret);
1417 if (MEDIA_CONTENT_ERROR_DB_FAILED == ret) {
1418 // We could fetch list of playlists and check if other playlist is using this
1419 // name, but that seems to be to much work in synchronous method
1420 LoggerE("Playlist name: %s is probably already used", name.c_str());
1421 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1425 return MEDIA_CONTENT_ERROR_NONE;
1428 int ContentManager::getThumbnailUri(int id, std::string* result) {
1430 media_playlist_h playlist_handle = getPlaylistHandle(id);
1431 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1433 char* tmp_playlist_thb_path = nullptr;
1434 const int ret_code = media_playlist_get_thumbnail_path(playlist_handle, &tmp_playlist_thb_path);
1436 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1437 LoggerE("media_playlist_get_name failed");
1438 return TIZEN_ERROR_UNKNOWN;
1441 std::string playlist_thb_path;
1442 if (tmp_playlist_thb_path) {
1443 playlist_thb_path = tmp_playlist_thb_path;
1444 free(tmp_playlist_thb_path);
1445 tmp_playlist_thb_path = nullptr;
1448 if (playlist_thb_path != " ") {
1449 playlist_thb_path = uri_prefix + playlist_thb_path;
1452 *result = playlist_thb_path;
1453 return MEDIA_CONTENT_ERROR_NONE;
1456 int ContentManager::setThumbnailUri(int id, const std::string& thb_uri) {
1459 // Allow setting empty URI, unfortunately Core API does not allow to set empty
1460 // path so we need to set one empty space. This is probably issue of Core API.
1461 if (!thb_uri.empty() && " " != thb_uri) {
1462 if (thb_uri.find(uri_absolute_prefix) != 0) {
1463 LoggerE("thumbnail URI is not valid: [%s]", thb_uri.c_str());
1464 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1468 media_playlist_h playlist_handle = getPlaylistHandle(id);
1469 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1471 std::string real_path = common::FilesystemProvider::Create().GetRealPath(thb_uri);
1472 const int ret_code = media_playlist_set_thumbnail_path(playlist_handle, real_path.c_str());
1473 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1474 LoggerE("media_playlist_set_thumbnail_path failed");
1475 return TIZEN_ERROR_UNKNOWN;
1478 int ret = updatePlaylistInDB(playlist_handle);
1482 int ContentManager::getNumberOfTracks(int id, int* result) {
1486 const int ret_code = media_playlist_get_media_count_from_db(id, nullptr, &count);
1488 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1489 LoggerE("media_playlist_get_media_count_from_db failed");
1490 return TIZEN_ERROR_UNKNOWN;
1494 return MEDIA_CONTENT_ERROR_NONE;
1497 common::PlatformResult ContentManager::createThumbnail(const std::string& id,
1498 picojson::object* obj) {
1501 media_info_h media_h = nullptr;
1502 int ret = media_info_get_media_from_db(id.c_str(), &media_h);
1503 if (MEDIA_CONTENT_ERROR_NONE != ret || nullptr == media_h) {
1504 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Getting media failed.",
1505 ("Getting media failed: %d (%s)", ret, get_error_message(ret)));
1508 media_info_destroy(media_h);
1511 ret = media_info_generate_thumbnail(media_h);
1512 if (MEDIA_CONTENT_ERROR_NONE != ret) {
1513 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Creating thumbnail failed.",
1514 ("Creating thumbnail failed: %d (%s)", ret, get_error_message(ret)));
1517 char* path = nullptr;
1518 ret = media_info_get_thumbnail_path(media_h, &path);
1519 if (MEDIA_CONTENT_ERROR_NONE != ret) {
1520 return LogAndCreateResult(
1521 ErrorCode::ABORT_ERR, "Creating thumbnail succeeded, but failed to get thumbnail path.",
1522 ("Getting thumbnail path failed: %d (%s)", ret, get_error_message(ret)));
1524 obj->emplace("result", picojson::value(path));
1525 std::unique_ptr<char[], decltype(&free)>(path, free);
1526 return PlatformResult(ErrorCode::NO_ERROR);
1529 PlatformResult ContentManager::convertError(int err) {
1530 char* error_msg = get_error_message(err);
1532 case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
1533 return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, error_msg);
1534 case MEDIA_CONTENT_ERROR_OUT_OF_MEMORY:
1535 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1536 case MEDIA_CONTENT_ERROR_INVALID_OPERATION:
1537 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1538 case MEDIA_CONTENT_FILE_NO_SPACE_ON_DEVICE:
1539 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1540 case MEDIA_CONTENT_ERROR_PERMISSION_DENIED:
1541 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1542 case MEDIA_CONTENT_ERROR_DB_FAILED:
1543 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1544 case MEDIA_CONTENT_ERROR_DB_BUSY:
1545 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1546 case MEDIA_CONTENT_ERROR_NETWORK:
1547 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1548 case MEDIA_CONTENT_ERROR_UNSUPPORTED_CONTENT:
1549 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1551 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
1555 } // namespace content
1556 } // namespace extension