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 const std::map<std::string, media_content_orientation_e> orientationMap = {
53 {"NORMAL", MEDIA_CONTENT_ORIENTATION_NORMAL},
54 {"FLIP_HORIZONTAL", MEDIA_CONTENT_ORIENTATION_HFLIP},
55 {"ROTATE_180", MEDIA_CONTENT_ORIENTATION_ROT_180},
56 {"FLIP_VERTICAL", MEDIA_CONTENT_ORIENTATION_VFLIP},
57 {"TRANSPOSE", MEDIA_CONTENT_ORIENTATION_TRANSPOSE},
58 {"ROTATE_90", MEDIA_CONTENT_ORIENTATION_ROT_90},
59 {"TRANSVERSE", MEDIA_CONTENT_ORIENTATION_TRANSVERSE},
60 {"ROTATE_270", MEDIA_CONTENT_ORIENTATION_ROT_270},
63 std::string get_date(char* tmpStr) {
66 struct tm* result = (struct tm*)calloc(1, sizeof(struct tm));
67 if (nullptr != result) {
68 if (strptime(tmpStr, "%Y:%m:%d %H:%M:%S", result) == NULL) {
72 time_t t = mktime(result); // + get_utc_offset() * 3600;
73 std::stringstream str_date;
76 return str_date.str();
83 void ContentToJson(media_info_h info, picojson::object& o) {
91 long long unsigned int tmpLong;
92 media_content_type_e type;
94 ret = media_info_get_media_type(info, &type);
96 if (ret != MEDIA_CONTENT_ERROR_NONE) {
97 LoggerE("Get media type failed: %d", ret);
98 type = MEDIA_CONTENT_TYPE_OTHERS;
101 if (type == MEDIA_CONTENT_TYPE_IMAGE) {
102 o["type"] = picojson::value(std::string("IMAGE"));
104 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_image(info, &img)) {
105 std::unique_ptr<std::remove_pointer<image_meta_h>::type, int (*)(image_meta_h)> img_ptr(
106 img, &image_meta_destroy); // automatically release the memory
107 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_date_taken(img, &tmpStr)) {
109 o["releaseDate"] = picojson::value(get_date(tmpStr));
114 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_width(img, &tmpInt)) {
115 o["width"] = picojson::value(static_cast<double>(tmpInt));
117 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_height(img, &tmpInt)) {
118 o["height"] = picojson::value(static_cast<double>(tmpInt));
120 picojson::object geo;
121 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_latitude(info, &tmpDouble)) {
122 geo["latitude"] = picojson::value(tmpDouble);
124 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_longitude(info, &tmpDouble)) {
125 geo["longitude"] = picojson::value(tmpDouble);
127 o["geolocation"] = picojson::value(geo);
129 media_content_orientation_e orientation;
130 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_orientation(img, &orientation)) {
131 switch (orientation) {
132 case MEDIA_CONTENT_ORIENTATION_NOT_AVAILABLE:
133 case MEDIA_CONTENT_ORIENTATION_NORMAL:
136 case MEDIA_CONTENT_ORIENTATION_HFLIP:
137 ori = "FLIP_HORIZONTAL";
139 case MEDIA_CONTENT_ORIENTATION_ROT_180:
142 case MEDIA_CONTENT_ORIENTATION_VFLIP:
143 ori = "FLIP_VERTICAL";
145 case MEDIA_CONTENT_ORIENTATION_TRANSPOSE:
148 case MEDIA_CONTENT_ORIENTATION_ROT_90:
151 case MEDIA_CONTENT_ORIENTATION_TRANSVERSE:
154 case MEDIA_CONTENT_ORIENTATION_ROT_270:
158 o["orientation"] = picojson::value(ori);
161 } else if (type == MEDIA_CONTENT_TYPE_VIDEO) {
162 o["type"] = picojson::value(std::string("VIDEO"));
164 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_video(info, &video)) {
165 std::unique_ptr<std::remove_pointer<video_meta_h>::type, int (*)(video_meta_h)> video_ptr(
166 video, &video_meta_destroy); // automatically release the memory
167 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_width(video, &tmpInt)) {
168 o["width"] = picojson::value(static_cast<double>(tmpInt));
171 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_height(video, &tmpInt)) {
172 o["height"] = picojson::value(static_cast<double>(tmpInt));
174 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_artist(video, &tmpStr)) {
175 picojson::array artists;
177 artists.push_back(picojson::value(std::string(tmpStr)));
181 o["artists"] = picojson::value(artists);
183 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_album(video, &tmpStr)) {
185 o["album"] = picojson::value(tmpStr);
190 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_duration(video, &tmpInt)) {
191 o["duration"] = picojson::value(static_cast<double>(tmpInt));
193 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_recorded_date(video, &tmpStr)) {
195 o["releaseDate"] = picojson::value(get_date(tmpStr));
201 picojson::object geo;
202 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_latitude(info, &tmpDouble)) {
203 geo["latitude"] = picojson::value(tmpDouble);
205 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_longitude(info, &tmpDouble)) {
206 geo["longitude"] = picojson::value(tmpDouble);
208 o["geolocation"] = picojson::value(geo);
209 } else if (type == MEDIA_CONTENT_TYPE_SOUND || type == MEDIA_CONTENT_TYPE_MUSIC) {
210 o["type"] = picojson::value(std::string("AUDIO"));
212 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_audio(info, &audio)) {
213 std::unique_ptr<std::remove_pointer<audio_meta_h>::type, int (*)(audio_meta_h)> audio_ptr(
214 audio, &audio_meta_destroy); // automatically release the memory
215 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_recorded_date(audio, &tmpStr)) {
217 o["releaseDate"] = picojson::value(get_date(tmpStr));
222 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_album(audio, &tmpStr)) {
224 o["album"] = picojson::value(std::string(tmpStr));
229 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_artist(audio, &tmpStr)) {
231 picojson::array artists;
232 artists.push_back(picojson::value(std::string(tmpStr)));
233 o["artists"] = picojson::value(artists);
238 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_genre(audio, &tmpStr)) {
240 picojson::array genres;
241 genres.push_back(picojson::value(std::string(tmpStr)));
242 o["genres"] = picojson::value(genres);
247 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_composer(audio, &tmpStr)) {
249 picojson::array composers;
250 composers.push_back(picojson::value(std::string(tmpStr)));
251 o["composers"] = picojson::value(composers);
256 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_copyright(audio, &tmpStr)) {
258 o["copyright"] = picojson::value(std::string(tmpStr));
263 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_bit_rate(audio, &tmpInt)) {
264 o["bitrate"] = picojson::value(static_cast<double>(tmpInt));
266 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_track_num(audio, &tmpStr)) {
268 o["trackNumber"] = picojson::value(static_cast<double>(std::atoi(tmpStr)));
272 o["trackNumber"] = picojson::value();
275 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_duration(audio, &tmpInt)) {
276 o["duration"] = picojson::value(static_cast<double>(tmpInt));
280 o["type"] = picojson::value(std::string("OTHER"));
283 ret = media_info_get_media_id(info, &tmpStr);
284 if (ret == MEDIA_CONTENT_ERROR_NONE) {
286 o["id"] = picojson::value(std::string(tmpStr));
291 ret = media_info_get_display_name(info, &tmpStr);
292 if (ret == MEDIA_CONTENT_ERROR_NONE) {
294 o["name"] = picojson::value(std::string(tmpStr));
300 ret = media_info_get_mime_type(info, &tmpStr);
301 if (ret == MEDIA_CONTENT_ERROR_NONE) {
303 o["mimeType"] = picojson::value(std::string(tmpStr));
308 ret = media_info_get_title(info, &tmpStr);
309 if (ret == MEDIA_CONTENT_ERROR_NONE) {
311 o["title"] = picojson::value(std::string(tmpStr));
316 ret = media_info_get_file_path(info, &tmpStr);
317 if (ret == MEDIA_CONTENT_ERROR_NONE) {
319 o["contentURI"] = picojson::value(std::string(tmpStr));
324 ret = media_info_get_thumbnail_path(info, &tmpStr);
325 if (ret == MEDIA_CONTENT_ERROR_NONE) {
327 picojson::array thumbnails;
328 thumbnails.push_back(picojson::value(std::string(tmpStr)));
329 o["thumbnailURIs"] = picojson::value(thumbnails);
334 ret = media_info_get_description(info, &tmpStr);
335 if (ret == MEDIA_CONTENT_ERROR_NONE) {
337 o["description"] = picojson::value(std::string(tmpStr));
342 ret = media_info_get_rating(info, &tmpInt);
343 if (ret == MEDIA_CONTENT_ERROR_NONE) {
344 o["rating"] = picojson::value(static_cast<double>(tmpInt));
346 ret = media_info_get_size(info, &tmpLong);
347 if (ret == MEDIA_CONTENT_ERROR_NONE) {
348 o["size"] = picojson::value(static_cast<double>(tmpLong));
350 ret = media_info_get_favorite(info, &tmpBool);
351 if (ret == MEDIA_CONTENT_ERROR_NONE) {
352 o["isFavorite"] = picojson::value(tmpBool);
354 ret = media_info_get_modified_time(info, &tmpDate);
355 if (ret == MEDIA_CONTENT_ERROR_NONE) {
356 o["modifiedDate"] = picojson::value(static_cast<double>(tmpDate));
360 void ContentDirToJson(media_folder_h folder, picojson::object& o) {
364 media_content_storage_e storage_type;
367 ret = media_folder_get_folder_id(folder, &tmpStr);
368 if (ret == MEDIA_CONTENT_ERROR_NONE) {
370 o["id"] = picojson::value(std::string(tmpStr));
377 std::string folder_path;
378 ret = media_folder_get_path(folder, &tmpStr);
379 if (ret == MEDIA_CONTENT_ERROR_NONE) {
381 o["directoryURI"] = picojson::value(std::string(tmpStr));
382 // folder_path value kept for modifiedDate property gathering
383 folder_path = tmpStr;
390 ret = media_folder_get_name(folder, &tmpStr);
391 if (ret == MEDIA_CONTENT_ERROR_NONE) {
393 o["title"] = picojson::value(std::string(tmpStr));
400 ret = media_folder_get_storage_type(folder, &storage_type);
401 if (ret == MEDIA_CONTENT_ERROR_NONE) {
402 if (storage_type == MEDIA_CONTENT_STORAGE_INTERNAL) {
403 o["storageType"] = picojson::value(std::string("INTERNAL"));
405 LoggerD("storageType = %d, assuming EXTERNAL as storage type", storage_type);
406 o["storageType"] = picojson::value(std::string("EXTERNAL"));
411 struct stat stat_res;
412 if (stat(folder_path.c_str(), &stat_res) == 0) {
413 auto mod_time = stat_res.st_mtime;
414 o["modifiedDate"] = picojson::value(static_cast<double>(mod_time));
418 static int setContent(media_info_h media, const picojson::value& content) {
422 std::string name = content.get("name").to_str();
423 std::string description = content.get("description").to_str();
424 int rating = std::stoi(content.get("rating").to_str());
425 bool is_fav = content.get("isFavorite").get<bool>();
428 LoggerE("MEDIA_CONTENT_ERROR_DB_FAILED");
429 return MEDIA_CONTENT_ERROR_DB_FAILED;
432 media_content_type_e type;
433 ret = media_info_get_media_type(media, &type);
434 if (ret != MEDIA_CONTENT_ERROR_NONE) {
435 LoggerE("Failed: media_info_get_media_type()");
439 ret = media_info_set_display_name(media, name.c_str());
440 if (ret != MEDIA_CONTENT_ERROR_NONE) {
441 LoggerE("Updating name failed.");
444 ret = media_info_set_description(media, description.c_str());
445 if (ret != MEDIA_CONTENT_ERROR_NONE) {
446 LoggerE("Updating description failed.");
449 ret = media_info_set_rating(media, rating);
450 if (ret != MEDIA_CONTENT_ERROR_NONE) {
451 LoggerE("Updating rating failed.");
454 ret = media_info_set_favorite(media, is_fav);
455 if (ret != MEDIA_CONTENT_ERROR_NONE) {
456 LoggerE("Updating isFavorite failed.");
459 if (ret != MEDIA_CONTENT_ERROR_NONE) {
460 LoggerE("Updating favorite failed.");
463 if (type == MEDIA_CONTENT_TYPE_IMAGE) {
464 std::string orientation = content.get("orientation").to_str();
465 auto orientationToSet = orientationMap.find(orientation);
467 if (orientationToSet != orientationMap.end()) {
469 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_image(media, &img) &&
470 MEDIA_CONTENT_ERROR_NONE == image_meta_set_orientation(img, orientationToSet->second) &&
471 MEDIA_CONTENT_ERROR_NONE == image_meta_update_to_db(img)) {
472 LoggerD("orientation update was successful");
474 LoggerE("orientation update failed");
476 image_meta_destroy(img);
480 if (type == MEDIA_CONTENT_TYPE_IMAGE || type == MEDIA_CONTENT_TYPE_VIDEO) {
481 picojson::value geo = content.get("geolocation");
482 if (geo.evaluate_as_boolean()) {
483 LoggerD("geolocation is not null");
484 double latitude = atof(geo.get("latitude").to_str().c_str());
485 double longitude = atof(geo.get("longitude").to_str().c_str());
486 ret = media_info_set_latitude(media, latitude);
487 if (ret != MEDIA_CONTENT_ERROR_NONE) {
488 LoggerE("Updating geolocation is failed.");
490 ret = media_info_set_longitude(media, longitude);
491 if (ret != MEDIA_CONTENT_ERROR_NONE) {
492 LoggerD("Updating geolocation is failed.");
495 LoggerD("geolocation is null");
499 return MEDIA_CONTENT_ERROR_NONE;
502 static void FolderToJson(media_folder_h folder, picojson::object* out) {
509 media_content_storage_e storageType;
513 ret = media_folder_get_folder_id(folder, &id);
514 if (ret != MEDIA_CONTENT_ERROR_NONE) {
515 LogAndReportError(ContentManager::convertError(ret), out,
516 ("Failed: media_folder_get_folder_id"));
519 std::unique_ptr<char, decltype(&free)> id_ptr(id, &free);
521 ret = media_folder_get_name(folder, &name);
522 if (ret != MEDIA_CONTENT_ERROR_NONE) {
523 LogAndReportError(ContentManager::convertError(ret), out, ("Failed: media_folder_get_name"));
526 std::unique_ptr<char, decltype(&free)> name_ptr(name, &free);
528 ret = media_folder_get_path(folder, &path);
529 if (ret != MEDIA_CONTENT_ERROR_NONE) {
530 LogAndReportError(ContentManager::convertError(ret), out, ("Failed: media_folder_get_path"));
533 std::unique_ptr<char, decltype(&free)> path_ptr(path, &free);
535 struct stat stat_res;
536 ret = stat(path, &stat_res);
538 LogAndReportError(ContentManager::convertError(errno), out, ("Failed: stat"));
541 date = stat_res.st_mtime;
543 ret = media_folder_get_storage_type(folder, &storageType);
544 if (ret != MEDIA_CONTENT_ERROR_NONE) {
545 LogAndReportError(ContentManager::convertError(ret), out,
546 ("Failed: media_folder_get_storage_type"));
550 (*out)["id"] = picojson::value(std::string(id));
551 (*out)["directoryURI"] = picojson::value(std::string(path));
552 (*out)["title"] = picojson::value(std::string(name));
554 if (storageType == MEDIA_CONTENT_STORAGE_INTERNAL) {
555 (*out)["storageType"] = picojson::value(std::string("INTERNAL"));
556 } else if (storageType == MEDIA_CONTENT_STORAGE_EXTERNAL) {
557 (*out)["storageType"] = picojson::value(std::string("EXTERNAL"));
560 (*out)["modifiedDate"] = picojson::value(static_cast<double>(date));
563 static bool media_foreach_directory_cb(media_folder_h folder, void* user_data) {
565 picojson::array* array = static_cast<picojson::array*>(user_data);
566 picojson::object json;
567 FolderToJson(folder, &json);
568 array->push_back(picojson::value(json));
572 static bool media_foreach_content_cb(media_info_h media, void* user_data) {
574 picojson::value::array* contents = static_cast<picojson::value::array*>(user_data);
575 picojson::value::object o;
576 ContentToJson(media, o);
577 contents->push_back(picojson::value(o));
581 static bool playlist_foreach_cb(media_playlist_h playlist, void* user_data) {
583 picojson::value::array* playlists = static_cast<picojson::value::array*>(user_data);
584 picojson::value::object o;
585 if (playlist != NULL) {
587 char* thumb_path = NULL;
589 filter_h filter = NULL;
590 if (media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
591 std::stringstream str_id;
593 o["id"] = picojson::value(std::to_string(id));
595 LoggerD("Invalid ID for playlist.");
597 if (media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
598 if (thumb_path != NULL) {
599 std::string thumbnail_uri(thumb_path);
600 if (thumbnail_uri != " ") {
601 thumbnail_uri = uri_prefix + thumbnail_uri;
603 o["thumbnailURI"] = picojson::value(thumbnail_uri);
606 o["thumbnailURI"] = picojson::value(); // picojson::value(std::string(""));
609 LoggerD("Invalid thumbnail path for playlist.");
611 if (media_playlist_get_name(playlist, &name) == MEDIA_CONTENT_ERROR_NONE) {
612 o["name"] = picojson::value(std::string(name));
615 LoggerD("Invalid name for playlist.");
618 media_filter_create(&filter);
619 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
620 filter, &media_filter_destroy); // automatically release the memory
621 if (media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
622 o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
624 LoggerE("Invalid count for playlist.");
626 playlists->push_back(picojson::value(o));
631 static bool playlist_content_member_cb(int playlist_member_id, media_info_h media,
634 picojson::value::array* contents = static_cast<picojson::value::array*>(user_data);
635 picojson::value::object o;
637 o["playlist_member_id"] = picojson::value(static_cast<double>(playlist_member_id));
638 ContentToJson(media, o);
639 contents->push_back(picojson::value(o));
643 ContentManager::ContentManager() {
644 ScopeLogger("ContentManager called");
645 if (media_content_connect() == MEDIA_CONTENT_ERROR_NONE) {
646 m_dbConnected = true;
648 m_dbConnected = false;
650 m_contentInstance = nullptr;
653 ContentManager::~ContentManager() {
656 if (media_content_disconnect() == MEDIA_CONTENT_ERROR_NONE) {
657 m_dbConnected = false;
662 ContentManager* ContentManager::getInstance() {
664 static ContentManager instance;
668 ContentInstance* ContentManager::getContentInstance() {
670 return m_contentInstance;
673 void ContentManager::setContentInstance(ContentInstance* const content_instance) {
675 m_contentInstance = content_instance;
678 bool ContentManager::isConnected() {
680 return m_dbConnected;
683 void ContentManager::getDirectories(const std::shared_ptr<ReplyCallbackData>& user_data) {
686 filter_h filter = NULL;
687 ret = media_filter_create(&filter);
688 if (ret != MEDIA_CONTENT_ERROR_NONE) {
689 LoggerE("Failed: media_filter_create failed");
694 media_filter_destroy(filter);
697 std::string condition = "(FOLDER_STORAGE_TYPE = 0 OR FOLDER_STORAGE_TYPE = 1)";
698 media_filter_set_condition(filter, condition.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
700 picojson::array pico_dirs;
701 ret = media_folder_foreach_folder_from_db(filter, media_foreach_directory_cb, &pico_dirs);
702 if (ret != MEDIA_CONTENT_ERROR_NONE) {
703 PlatformResult err = LogAndCreateResult(
704 ErrorCode::UNKNOWN_ERR, "Getting the directories failed.",
705 ("Failed: Getting the directories failed %d (%s)", ret, get_error_message(ret)));
706 user_data->isSuccess = err;
710 user_data->result = picojson::value(pico_dirs);
713 void ContentManager::find(const std::shared_ptr<ReplyCallbackData>& user_data) {
720 picojson::value::array arrayContent;
721 filter_h filter = nullptr;
722 media_filter_create(&filter);
725 media_filter_destroy(filter);
729 if (!IsNull(user_data->args.get("filter"))) {
730 ContentFilter filterMechanism;
732 picojson::object argsObject = JsonCast<picojson::object>(user_data->args);
733 if (filterMechanism.BuildQuery(FromJson<picojson::object>(argsObject, "filter"), &query)) {
734 LoggerD("Filter query: %s", query.c_str());
735 ret = media_filter_set_condition(filter, query.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
736 if (MEDIA_CONTENT_ERROR_NONE != ret) {
737 LoggerE("Platform filter setting failed, error %d", ret);
742 if (user_data->args.contains("sortMode")) {
743 picojson::value vSortMode = user_data->args.get("sortMode");
745 if (vSortMode.is<picojson::object>()) {
746 std::string sortModeName, sortModeOrder;
748 ContentFilter::MapField(vSortMode.get("attributeName").to_str(), &sortModeName);
750 sortModeOrder = vSortMode.get("order").to_str();
751 if (!sortModeOrder.empty()) {
752 media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
754 if (sortModeOrder == "ASC") {
755 order = MEDIA_CONTENT_ORDER_ASC;
756 } else if (sortModeOrder == "DESC") {
757 order = MEDIA_CONTENT_ORDER_DESC;
760 ret = media_filter_set_order(filter, order, sortModeName.c_str(),
761 MEDIA_CONTENT_COLLATE_DEFAULT);
762 if (MEDIA_CONTENT_ERROR_NONE != ret) {
763 LoggerE("Platform SortMode setting failed, error: %d", ret);
769 if (!IsNull(user_data->args.get("count"))) {
770 count = static_cast<int>(user_data->args.get("count").get<double>());
774 if (!IsNull(user_data->args.get("offset"))) {
775 offset = static_cast<int>(user_data->args.get("offset").get<double>());
779 ret = media_filter_set_offset(filter, offset, count);
780 if (MEDIA_CONTENT_ERROR_NONE != ret) {
781 LoggerE("A platform error occurs in media_filter_set_offset: %d", ret);
783 if (!IsNull(user_data->args.get("directoryId"))) {
784 dirId = user_data->args.get("directoryId").get<std::string>();
785 ret = media_folder_foreach_media_from_db(dirId.c_str(), filter, media_foreach_content_cb,
786 static_cast<void*>(&arrayContent));
788 ret = media_info_foreach_media_from_db(filter, media_foreach_content_cb,
789 static_cast<void*>(&arrayContent));
792 if (ret == MEDIA_CONTENT_ERROR_NONE) {
793 user_data->result = picojson::value(arrayContent);
795 PlatformResult err = LogAndCreateResult(
796 ErrorCode::UNKNOWN_ERR, "The iteration failed in platform",
797 ("The iteration failed in platform: %d (%s)", ret, get_error_message(ret)));
798 user_data->isSuccess = err;
802 int ContentManager::scanFile(std::string& uri) {
804 return media_content_scan_file(uri.c_str());
807 PlatformResult ContentManager::scanDirectory(media_scan_completed_cb callback,
808 ReplyCallbackData* cbData) {
810 const std::string& contentDirURI = cbData->args.get("contentDirURI").get<std::string>();
811 std::string real_path = common::FilesystemProvider::Create().GetRealPath(contentDirURI);
812 const bool recursive = cbData->args.get("recursive").get<bool>();
814 int ret = media_content_scan_folder(real_path.c_str(), recursive, callback, (void*)cbData);
816 if (ret != MEDIA_CONTENT_ERROR_NONE) {
817 if (MEDIA_CONTENT_ERROR_INVALID_PARAMETER == ret) {
818 return LogAndCreateResult(
819 ErrorCode::INVALID_VALUES_ERR, "Scanning content directory failed",
820 ("Scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
823 return LogAndCreateResult(
824 ErrorCode::UNKNOWN_ERR, "Scanning content directory failed",
825 ("Scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
828 return PlatformResult(ErrorCode::NO_ERROR);
831 PlatformResult ContentManager::cancelScanDirectory(const std::string& content_dir_uri) {
834 int ret = media_content_cancel_scan_folder(content_dir_uri.c_str());
835 if (ret != MEDIA_CONTENT_ERROR_NONE) {
836 return LogAndCreateResult(
837 ErrorCode::UNKNOWN_ERR, "Cancel scan content directory failed",
838 ("Cancel scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
840 return PlatformResult(ErrorCode::NO_ERROR);
843 PlatformResult ContentManager::addChangeListener(media_content_noti_h* noti_handle,
844 media_content_db_update_cb callback,
848 int ret = media_content_add_db_updated_cb(callback, user_data, noti_handle);
850 if (MEDIA_CONTENT_ERROR_NONE != ret) {
851 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to add the listener.",
852 ("Failed to add the listener: %d (%s)", ret, get_error_message(ret)));
855 return PlatformResult(ErrorCode::NO_ERROR);
858 PlatformResult ContentManager::removeChangeListener(media_content_noti_h noti_handle) {
861 int ret = media_content_remove_db_updated_cb(noti_handle);
864 case MEDIA_CONTENT_ERROR_NONE:
865 return PlatformResult(ErrorCode::NO_ERROR);
866 case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
867 // Trying to remove non-existent listener, ignoring
868 LoggerI("Failed to remove the listener: %d (%s)", ret, get_error_message(ret));
869 return PlatformResult(ErrorCode::NO_ERROR);
871 return LogAndCreateResult(
872 ErrorCode::ABORT_ERR, "Failed to remove the listener.",
873 ("Failed to remove the listener: %d (%s)", ret, get_error_message(ret)));
877 void ContentManager::createPlaylist(std::string name,
878 const std::shared_ptr<ReplyCallbackData>& user_data) {
880 media_playlist_h playlist = NULL;
882 int ret = media_playlist_insert_to_db(name.c_str(), &playlist);
883 std::unique_ptr<std::remove_pointer<media_playlist_h>::type, int (*)(media_playlist_h)>
884 playlist_ptr(playlist, &media_playlist_destroy); // automatically release the memory
885 if (ret != MEDIA_CONTENT_ERROR_NONE) {
886 // MEDIA_CONTENT_ERROR_DB_FAILED means that playlist probably already exists
887 PlatformResult err = LogAndCreateResult(
888 MEDIA_CONTENT_ERROR_DB_FAILED == ret ? ErrorCode::INVALID_VALUES_ERR
889 : ErrorCode::UNKNOWN_ERR,
890 "Creation of playlist has failed.",
891 ("Failed: creation of playlist is failed: %d (%s)", ret, get_error_message(ret)));
892 user_data->isSuccess = err;
895 picojson::value::object o;
897 if (playlist != NULL) {
899 char* thumb_path = NULL;
900 char* name_playlist = NULL;
901 filter_h filter = NULL;
902 if (media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
903 o["id"] = picojson::value(std::to_string(id));
906 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "loading of playlist is failed.");
907 user_data->isSuccess = err;
910 if (media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
911 if (thumb_path != NULL) {
912 o["thumbnailURI"] = picojson::value(std::string(thumb_path));
915 o["thumbnailURI"] = picojson::value();
918 LoggerE("Invalid thumbnail path for playlist.");
920 if (media_playlist_get_name(playlist, &name_playlist) == MEDIA_CONTENT_ERROR_NONE) {
921 o["name"] = picojson::value(std::string(name_playlist));
924 LoggerE("Invalid name for playlist.");
926 media_filter_create(&filter);
927 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
928 filter, &media_filter_destroy); // automatically release the memory
930 if (media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
931 o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
933 LoggerE("Invalid count for playlist.");
937 user_data->result = picojson::value(o);
940 void ContentManager::getPlaylists(const std::shared_ptr<ReplyCallbackData>& user_data) {
943 filter_h filter = nullptr;
944 media_filter_create(&filter);
945 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
946 filter, &media_filter_destroy); // automatically release the memory
947 picojson::value::array playlists;
949 ret = media_playlist_foreach_playlist_from_db(filter, playlist_foreach_cb,
950 static_cast<void*>(&playlists));
952 if (ret != MEDIA_CONTENT_ERROR_NONE) {
953 PlatformResult err = LogAndCreateResult(
954 ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
955 ("Failed: Getting playlist is failed %d (%s)", ret, get_error_message(ret)));
956 user_data->isSuccess = err;
959 user_data->result = picojson::value(playlists);
962 void ContentManager::removePlaylist(std::string playlistId,
963 const std::shared_ptr<ReplyCallbackData>& user_data) {
965 int id = std::atoi(playlistId.c_str());
967 PlatformResult err = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "PlaylistId is wrong.");
968 user_data->isSuccess = err;
972 int ret = media_playlist_delete_from_db(id);
973 if (ret != MEDIA_CONTENT_ERROR_NONE) {
975 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Removal of playlist is failed.");
976 user_data->isSuccess = err;
980 int ContentManager::update(const picojson::value& args) {
984 picojson::value content = args.get("content");
985 std::string id = content.get("id").to_str();
987 media_info_h media = NULL;
988 ret = media_info_get_media_from_db(id.c_str(), &media);
989 if (ret == MEDIA_CONTENT_ERROR_NONE) {
990 setContent(media, content);
991 ret = media_info_update_to_db(media);
992 media_info_destroy(media);
998 int ContentManager::updateBatch(const picojson::value& args) {
1001 std::vector<picojson::value> contents = args.get("contents").get<picojson::array>();
1003 for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
1004 picojson::value content = *it;
1005 std::string id = content.get("id").to_str();
1006 media_info_h media = NULL;
1007 ret = media_info_get_media_from_db(id.c_str(), &media);
1008 if (media != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1009 ret = setContent(media, content);
1010 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1011 LoggerE("setContent failed");
1015 ret = media_info_update_to_db(media);
1016 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1017 LoggerE("update to db failed");
1019 media_info_destroy(media);
1027 int ContentManager::playlistAdd(std::string playlist_id, std::string content_id) {
1030 media_playlist_h playlist = NULL;
1031 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1033 if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1034 ret = media_playlist_add_media(playlist, content_id.c_str());
1035 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1036 LoggerE("The content(id:%s) can't add to playlist", content_id.c_str());
1039 ret = media_playlist_update_to_db(playlist);
1040 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1041 LoggerE("The content(id:%s) can't add to playlist", content_id.c_str());
1044 LoggerE("Playlist(id:%s) is not exist", playlist_id.c_str());
1047 media_playlist_destroy(playlist);
1051 int ContentManager::playlistRemove(std::string playlist_id, int member_id) {
1054 media_playlist_h playlist = NULL;
1055 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1056 if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1057 ret = media_playlist_remove_media(playlist, member_id);
1058 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1059 LoggerE("The content can't remove to playlist");
1062 ret = media_playlist_update_to_db(playlist);
1063 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1064 LoggerE("The content can't remove to playlist");
1067 LoggerE("Playlist(id:%s) is not exist", playlist_id.c_str());
1069 media_playlist_destroy(playlist);
1074 void ContentManager::playlistAddbatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
1076 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1078 media_playlist_h playlist = NULL;
1079 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1081 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1082 PlatformResult err =
1083 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1084 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1085 user_data->isSuccess = err;
1089 std::vector<picojson::value> contents = user_data->args.get("contents").get<picojson::array>();
1090 for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
1091 picojson::value content = *it;
1092 std::string id = content.get("id").to_str();
1093 ret = media_playlist_add_media(playlist, id.c_str());
1094 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1095 LoggerE("Adding Content(id:%s) is failed.", id.c_str());
1099 ret = media_playlist_update_to_db(playlist);
1100 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1101 PlatformResult err =
1102 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Adding playlist is failed.",
1103 ("Adding playlist is failed: %d (%s)", ret, get_error_message(ret)));
1104 user_data->isSuccess = err;
1106 media_playlist_destroy(playlist);
1109 void ContentManager::playlistGet(const std::shared_ptr<ReplyCallbackData>& user_data) {
1111 media_playlist_h playlist = NULL;
1112 media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
1113 const std::string playOrder("play_order");
1117 media_playlist_destroy(playlist);
1121 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1122 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1123 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1124 PlatformResult err =
1125 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1126 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1127 user_data->isSuccess = err;
1131 filter_h filter = NULL;
1132 ret = media_filter_create(&filter);
1133 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1134 PlatformResult err =
1135 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.",
1136 ("Creating a filter is failed: %d (%s)", ret, get_error_message(ret)));
1137 user_data->isSuccess = err;
1141 int count = user_data->args.get("count").get<double>();
1142 int offset = user_data->args.get("offset").get<double>();
1143 ret = media_filter_set_offset(filter, offset, count);
1144 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1145 LoggerD("Setting a offset/count is failed.");
1147 ret = media_filter_set_order(filter, order, playOrder.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
1148 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1149 LoggerD("Setting a offset/count is failed.");
1152 picojson::value::array arrayContent;
1153 ret = media_playlist_foreach_media_from_db(std::stoi(playlist_id), filter,
1154 playlist_content_member_cb,
1155 static_cast<void*>(&arrayContent));
1157 media_filter_destroy(filter);
1158 if (ret == MEDIA_CONTENT_ERROR_NONE) {
1159 user_data->result = picojson::value(arrayContent);
1161 PlatformResult err =
1162 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.",
1163 ("Creating a filter is failed: %d (%s)", ret, get_error_message(ret)));
1164 user_data->isSuccess = err;
1168 void ContentManager::playlistRemovebatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
1170 media_playlist_h playlist = NULL;
1174 media_playlist_destroy(playlist);
1178 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1179 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1180 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1181 PlatformResult err =
1182 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1183 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1184 user_data->isSuccess = err;
1188 std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
1189 std::size_t members_size = members.size();
1190 for (std::size_t i = 0; i < members_size; ++i) {
1191 int member_id = static_cast<int>(members.at(i).get<double>());
1192 ret = media_playlist_remove_media(playlist, member_id);
1194 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1195 LoggerD("Removing a content is failed.");
1199 ret = media_playlist_update_to_db(playlist);
1200 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1201 PlatformResult err = LogAndCreateResult(
1202 ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.",
1203 ("Removing the contents is failed: %d (%s)", ret, get_error_message(ret)));
1204 user_data->isSuccess = err;
1208 void ContentManager::playlistSetOrder(const std::shared_ptr<ReplyCallbackData>& user_data) {
1210 media_playlist_h playlist = NULL;
1214 media_playlist_destroy(playlist);
1218 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1219 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1220 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1221 PlatformResult err =
1222 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1223 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1224 user_data->isSuccess = err;
1229 std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
1231 ret = media_playlist_get_media_count_from_db(std::stoi(playlist_id), NULL, &cnt);
1232 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1233 LoggerE("Failed: media_playlist_get_media_count_from_db");
1234 PlatformResult err = convertError(ret);
1235 user_data->isSuccess = err;
1238 std::size_t members_size = members.size();
1239 if (cnt < 0 || static_cast<size_t>(cnt) != members_size) {
1240 PlatformResult err = LogAndCreateResult(
1241 ErrorCode::INVALID_VALUES_ERR,
1242 "The items array does not contain all items from the playlist.",
1243 ("Failed: The items array does not contain all items from the playlist: %d (%s)", ret,
1244 get_error_message(ret)));
1245 user_data->isSuccess = err;
1249 for (std::size_t i = 0; i < members_size; ++i) {
1250 int member_id = static_cast<int>(members.at(i).get<double>());
1251 ret = media_playlist_set_play_order(playlist, member_id, i);
1252 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1253 LoggerD("Removing a content is failed.");
1257 ret = media_playlist_update_to_db(playlist);
1258 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1259 PlatformResult err = LogAndCreateResult(
1260 ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.",
1261 ("Removing the contents is failed: %d (%s)", ret, get_error_message(ret)));
1262 user_data->isSuccess = err;
1266 void ContentManager::playlistMove(const std::shared_ptr<ReplyCallbackData>& user_data) {
1268 media_playlist_h playlist = NULL;
1272 media_playlist_destroy(playlist);
1276 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1277 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1278 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1279 PlatformResult err =
1280 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1281 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1282 user_data->isSuccess = err;
1286 double member_id = user_data->args.get("memberId").get<double>();
1287 double delta = user_data->args.get("delta").get<double>();
1288 ret = media_playlist_get_play_order(playlist, static_cast<int>(member_id), &old_order);
1289 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1290 PlatformResult err = LogAndCreateResult(
1291 ErrorCode::UNKNOWN_ERR, "The content can't find form playlist.",
1292 ("The content can't find form playlist: %d (%s)", ret, get_error_message(ret)));
1293 user_data->isSuccess = err;
1296 int new_order = static_cast<int>(old_order) + static_cast<int>(delta);
1297 ret = media_playlist_set_play_order(playlist, static_cast<int>(member_id), new_order);
1298 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1299 PlatformResult err = LogAndCreateResult(
1300 ErrorCode::UNKNOWN_ERR, "The content can't update play_order.",
1301 ("The content can't update play_order: %d (%s)", ret, get_error_message(ret)));
1302 user_data->isSuccess = err;
1305 ret = media_playlist_update_to_db(playlist);
1306 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1307 PlatformResult err = LogAndCreateResult(
1308 ErrorCode::UNKNOWN_ERR, "Updateing play_order is failed.",
1309 ("Updateing play_order is failed: %d (%s)", ret, get_error_message(ret)));
1310 user_data->isSuccess = err;
1314 int ContentManager::getLyrics(const picojson::value& args, picojson::object& result) {
1317 int ret = METADATA_EXTRACTOR_ERROR_NONE;
1318 const std::string& contentURI = args.get("contentURI").to_str();
1319 if (contentURI.empty()) {
1320 LoggerE("contentURI empty - skipping media extractor");
1324 metadata_extractor_h extractor;
1325 ret = metadata_extractor_create(&extractor);
1326 if (METADATA_EXTRACTOR_ERROR_NONE != ret) {
1327 LoggerE("metadata_extractor_create failed, error: %d", ret);
1329 std::unique_ptr<std::remove_pointer<metadata_extractor_h>::type, int (*)(metadata_extractor_h)>
1330 extractor_ptr(extractor, &metadata_extractor_destroy); // automatically release the memory
1332 ret = metadata_extractor_set_path(extractor, contentURI.c_str());
1333 if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
1334 LoggerE("metadata_extractor_set_path failed, error: %d", ret);
1337 picojson::array timestamps;
1338 picojson::array texts = picojson::array();
1339 char* strSyncTextNum = NULL;
1341 ret = metadata_extractor_get_metadata(extractor, METADATA_SYNCLYRICS_NUM, &strSyncTextNum);
1342 if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
1343 LoggerE("Media extractor error %d", ret);
1347 int nSyncTextNum = 0;
1348 if (strSyncTextNum) {
1349 nSyncTextNum = atoi(strSyncTextNum);
1350 free(strSyncTextNum);
1351 strSyncTextNum = NULL;
1353 if (nSyncTextNum > 0) {
1354 result["type"] = picojson::value(std::string("SYNCHRONIZED"));
1355 for (int i = 0; i < nSyncTextNum; i++) {
1356 unsigned long time_info = 0;
1357 char* lyrics = NULL;
1358 ret = metadata_extractor_get_synclyrics(extractor, i, &time_info, &lyrics);
1359 if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
1360 timestamps.push_back(picojson::value(static_cast<double>(time_info)));
1361 texts.push_back(picojson::value(std::string(lyrics)));
1365 result["texts"] = picojson::value(texts);
1366 result["timestamps"] = picojson::value(timestamps);
1367 ret = METADATA_EXTRACTOR_ERROR_NONE;
1369 char* unSyncText = nullptr;
1370 ret = metadata_extractor_get_metadata(extractor, METADATA_UNSYNCLYRICS, &unSyncText);
1371 if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
1372 result["type"] = picojson::value(std::string("UNSYNCHRONIZED"));
1373 if (nullptr == unSyncText) {
1374 LoggerE("Unsynchronized lyrics text is NULL");
1376 texts.push_back(picojson::value(unSyncText ? unSyncText : ""));
1377 result["texts"] = picojson::value(texts);
1385 media_playlist_h getPlaylistHandle(int id) {
1387 media_playlist_h playlist_handle = nullptr;
1388 int ret_code = media_playlist_get_playlist_from_db(id, &playlist_handle);
1389 if (MEDIA_CONTENT_ERROR_NONE != ret_code || playlist_handle == nullptr) {
1390 LoggerE("could not get playlist handle for id: %d", id);
1394 return playlist_handle;
1397 void destroyMediaPlaylistHandle(media_playlist_h& playlist_handle) {
1399 if (playlist_handle) {
1400 int ret_code = media_playlist_destroy(playlist_handle);
1401 playlist_handle = nullptr;
1403 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1404 LoggerE("media_playlist_destroy failed");
1409 int ContentManager::getPlaylistName(int id, std::string* result) {
1411 media_playlist_h playlist_handle = getPlaylistHandle(id);
1412 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1414 char* tmp_playlist_name = nullptr;
1415 const int ret_code = media_playlist_get_name(playlist_handle, &tmp_playlist_name);
1417 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1418 LoggerE("media_playlist_get_name failed");
1419 return TIZEN_ERROR_UNKNOWN;
1422 std::string playlist_name;
1423 if (tmp_playlist_name) {
1424 playlist_name = tmp_playlist_name;
1425 free(tmp_playlist_name);
1426 tmp_playlist_name = nullptr;
1429 *result = playlist_name;
1430 return MEDIA_CONTENT_ERROR_NONE;
1433 int updatePlaylistInDB(media_playlist_h playlist_handle) {
1435 int ret_code = media_playlist_update_to_db(playlist_handle);
1436 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1437 LoggerE("media_playlist_update_to_db failed");
1440 return MEDIA_CONTENT_ERROR_NONE;
1443 int ContentManager::setPlaylistName(int id, const std::string& name) {
1446 LoggerE("Cannot set empty playlist name!");
1447 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1450 media_playlist_h playlist_handle = getPlaylistHandle(id);
1451 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1453 const int ret_code = media_playlist_set_name(playlist_handle, name.c_str());
1454 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1455 LoggerE("media_playlist_set_name failed");
1456 // Setting name that is used by other playlist does not return bad error code here.
1457 // MEDIA_CONTENT_ERROR_INVALID_OPERATION is being returned in updatePlaylistInDB
1458 return TIZEN_ERROR_UNKNOWN;
1461 int ret = updatePlaylistInDB(playlist_handle);
1462 if (MEDIA_CONTENT_ERROR_NONE != ret) {
1463 LoggerE("Error while updating playlist: %d", ret);
1464 if (MEDIA_CONTENT_ERROR_DB_FAILED == ret) {
1465 // We could fetch list of playlists and check if other playlist is using this
1466 // name, but that seems to be to much work in synchronous method
1467 LoggerE("Playlist name: %s is probably already used", name.c_str());
1468 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1472 return MEDIA_CONTENT_ERROR_NONE;
1475 int ContentManager::getThumbnailUri(int id, std::string* result) {
1477 media_playlist_h playlist_handle = getPlaylistHandle(id);
1478 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1480 char* tmp_playlist_thb_path = nullptr;
1481 const int ret_code = media_playlist_get_thumbnail_path(playlist_handle, &tmp_playlist_thb_path);
1483 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1484 LoggerE("media_playlist_get_name failed");
1485 return TIZEN_ERROR_UNKNOWN;
1488 std::string playlist_thb_path;
1489 if (tmp_playlist_thb_path) {
1490 playlist_thb_path = tmp_playlist_thb_path;
1491 free(tmp_playlist_thb_path);
1492 tmp_playlist_thb_path = nullptr;
1495 if (playlist_thb_path != " ") {
1496 playlist_thb_path = uri_prefix + playlist_thb_path;
1499 *result = playlist_thb_path;
1500 return MEDIA_CONTENT_ERROR_NONE;
1503 int ContentManager::setThumbnailUri(int id, const std::string& thb_uri) {
1506 // Allow setting empty URI, unfortunately Core API does not allow to set empty
1507 // path so we need to set one empty space. This is probably issue of Core API.
1508 if (!thb_uri.empty() && " " != thb_uri) {
1509 if (thb_uri.find(uri_absolute_prefix) != 0) {
1510 LoggerE("thumbnail URI is not valid: [%s]", thb_uri.c_str());
1511 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1515 media_playlist_h playlist_handle = getPlaylistHandle(id);
1516 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1518 std::string real_path = common::FilesystemProvider::Create().GetRealPath(thb_uri);
1519 const int ret_code = media_playlist_set_thumbnail_path(playlist_handle, real_path.c_str());
1520 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1521 LoggerE("media_playlist_set_thumbnail_path failed");
1522 return TIZEN_ERROR_UNKNOWN;
1525 int ret = updatePlaylistInDB(playlist_handle);
1529 int ContentManager::getNumberOfTracks(int id, int* result) {
1533 const int ret_code = media_playlist_get_media_count_from_db(id, nullptr, &count);
1535 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1536 LoggerE("media_playlist_get_media_count_from_db failed");
1537 return TIZEN_ERROR_UNKNOWN;
1541 return MEDIA_CONTENT_ERROR_NONE;
1544 common::PlatformResult ContentManager::createThumbnail(const std::string& id,
1545 picojson::object* obj) {
1548 media_info_h media_h = nullptr;
1549 int ret = media_info_get_media_from_db(id.c_str(), &media_h);
1550 if (MEDIA_CONTENT_ERROR_NONE != ret || nullptr == media_h) {
1551 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Getting media failed.",
1552 ("Getting media failed: %d (%s)", ret, get_error_message(ret)));
1555 media_info_destroy(media_h);
1558 ret = media_info_generate_thumbnail(media_h);
1559 if (MEDIA_CONTENT_ERROR_NONE != ret) {
1560 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Creating thumbnail failed.",
1561 ("Creating thumbnail failed: %d (%s)", ret, get_error_message(ret)));
1564 char* path = nullptr;
1565 ret = media_info_get_thumbnail_path(media_h, &path);
1566 if (MEDIA_CONTENT_ERROR_NONE != ret) {
1567 return LogAndCreateResult(
1568 ErrorCode::ABORT_ERR, "Creating thumbnail succeeded, but failed to get thumbnail path.",
1569 ("Getting thumbnail path failed: %d (%s)", ret, get_error_message(ret)));
1571 obj->emplace("result", picojson::value(path));
1572 std::unique_ptr<char[], decltype(&free)>(path, free);
1573 return PlatformResult(ErrorCode::NO_ERROR);
1576 PlatformResult ContentManager::convertError(int err) {
1577 char* error_msg = get_error_message(err);
1579 case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
1580 return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, error_msg);
1581 case MEDIA_CONTENT_ERROR_OUT_OF_MEMORY:
1582 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1583 case MEDIA_CONTENT_ERROR_INVALID_OPERATION:
1584 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1585 case MEDIA_CONTENT_FILE_NO_SPACE_ON_DEVICE:
1586 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1587 case MEDIA_CONTENT_ERROR_PERMISSION_DENIED:
1588 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1589 case MEDIA_CONTENT_ERROR_DB_FAILED:
1590 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1591 case MEDIA_CONTENT_ERROR_DB_BUSY:
1592 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1593 case MEDIA_CONTENT_ERROR_NETWORK:
1594 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1595 case MEDIA_CONTENT_ERROR_UNSUPPORTED_CONTENT:
1596 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1598 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
1602 } // namespace content
1603 } // namespace extension