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 <metadata_extractor.h>
28 #include "common/converter.h"
29 #include "common/filesystem/filesystem_provider.h"
30 #include "common/logger.h"
31 #include "common/scope_exit.h"
32 #include "common/tools.h"
34 #include "content/content_filter.h"
37 using namespace common;
39 using common::tools::ReportSuccess;
40 using common::tools::ReportError;
46 static const std::string uri_prefix = "file://";
47 static const std::string uri_absolute_prefix = "file:///";
50 const std::map<std::string, media_content_orientation_e> orientationMap = {
51 {"NORMAL", MEDIA_CONTENT_ORIENTATION_NORMAL},
52 {"FLIP_HORIZONTAL", MEDIA_CONTENT_ORIENTATION_HFLIP},
53 {"ROTATE_180", MEDIA_CONTENT_ORIENTATION_ROT_180},
54 {"FLIP_VERTICAL", MEDIA_CONTENT_ORIENTATION_VFLIP},
55 {"TRANSPOSE", MEDIA_CONTENT_ORIENTATION_TRANSPOSE},
56 {"ROTATE_90", MEDIA_CONTENT_ORIENTATION_ROT_90},
57 {"TRANSVERSE", MEDIA_CONTENT_ORIENTATION_TRANSVERSE},
58 {"ROTATE_270", MEDIA_CONTENT_ORIENTATION_ROT_270},
61 std::string get_date(char* tmpStr) {
64 struct tm* result = (struct tm*)calloc(1, sizeof(struct tm));
65 if (nullptr != result) {
66 if (strptime(tmpStr, "%Y:%m:%d %H:%M:%S", result) == NULL) {
70 time_t t = mktime(result); // + get_utc_offset() * 3600;
71 std::stringstream str_date;
74 return str_date.str();
81 void ContentToJson(media_info_h info, picojson::object& o) {
89 long long unsigned int tmpLong;
90 media_content_type_e type;
92 ret = media_info_get_media_type(info, &type);
94 if (ret != MEDIA_CONTENT_ERROR_NONE) {
95 LoggerE("Get media type failed: %d", ret);
96 type = MEDIA_CONTENT_TYPE_OTHERS;
99 if (type == MEDIA_CONTENT_TYPE_IMAGE) {
100 o["type"] = picojson::value(std::string("IMAGE"));
102 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_image(info, &img)) {
103 std::unique_ptr<std::remove_pointer<image_meta_h>::type, int (*)(image_meta_h)> img_ptr(
104 img, &image_meta_destroy); // automatically release the memory
105 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_date_taken(img, &tmpStr)) {
107 o["releaseDate"] = picojson::value(get_date(tmpStr));
112 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_width(img, &tmpInt)) {
113 o["width"] = picojson::value(static_cast<double>(tmpInt));
115 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_height(img, &tmpInt)) {
116 o["height"] = picojson::value(static_cast<double>(tmpInt));
118 picojson::object geo;
119 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_latitude(info, &tmpDouble)) {
120 geo["latitude"] = picojson::value(tmpDouble);
122 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_longitude(info, &tmpDouble)) {
123 geo["longitude"] = picojson::value(tmpDouble);
125 o["geolocation"] = picojson::value(geo);
127 media_content_orientation_e orientation;
128 if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_orientation(img, &orientation)) {
129 switch (orientation) {
130 case MEDIA_CONTENT_ORIENTATION_NOT_AVAILABLE:
131 case MEDIA_CONTENT_ORIENTATION_NORMAL:
134 case MEDIA_CONTENT_ORIENTATION_HFLIP:
135 ori = "FLIP_HORIZONTAL";
137 case MEDIA_CONTENT_ORIENTATION_ROT_180:
140 case MEDIA_CONTENT_ORIENTATION_VFLIP:
141 ori = "FLIP_VERTICAL";
143 case MEDIA_CONTENT_ORIENTATION_TRANSPOSE:
146 case MEDIA_CONTENT_ORIENTATION_ROT_90:
149 case MEDIA_CONTENT_ORIENTATION_TRANSVERSE:
152 case MEDIA_CONTENT_ORIENTATION_ROT_270:
156 o["orientation"] = picojson::value(ori);
159 } else if (type == MEDIA_CONTENT_TYPE_VIDEO) {
160 o["type"] = picojson::value(std::string("VIDEO"));
162 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_video(info, &video)) {
163 std::unique_ptr<std::remove_pointer<video_meta_h>::type, int (*)(video_meta_h)> video_ptr(
164 video, &video_meta_destroy); // automatically release the memory
165 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_width(video, &tmpInt)) {
166 o["width"] = picojson::value(static_cast<double>(tmpInt));
169 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_height(video, &tmpInt)) {
170 o["height"] = picojson::value(static_cast<double>(tmpInt));
172 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_artist(video, &tmpStr)) {
173 picojson::array artists;
175 artists.push_back(picojson::value(std::string(tmpStr)));
179 o["artists"] = picojson::value(artists);
181 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_album(video, &tmpStr)) {
183 o["album"] = picojson::value(tmpStr);
188 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_duration(video, &tmpInt)) {
189 o["duration"] = picojson::value(static_cast<double>(tmpInt));
191 if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_recorded_date(video, &tmpStr)) {
193 o["releaseDate"] = picojson::value(get_date(tmpStr));
199 picojson::object geo;
200 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_latitude(info, &tmpDouble)) {
201 geo["latitude"] = picojson::value(tmpDouble);
203 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_longitude(info, &tmpDouble)) {
204 geo["longitude"] = picojson::value(tmpDouble);
206 o["geolocation"] = picojson::value(geo);
207 } else if (type == MEDIA_CONTENT_TYPE_SOUND || type == MEDIA_CONTENT_TYPE_MUSIC) {
208 o["type"] = picojson::value(std::string("AUDIO"));
210 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_audio(info, &audio)) {
211 std::unique_ptr<std::remove_pointer<audio_meta_h>::type, int (*)(audio_meta_h)> audio_ptr(
212 audio, &audio_meta_destroy); // automatically release the memory
213 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_recorded_date(audio, &tmpStr)) {
215 o["releaseDate"] = picojson::value(get_date(tmpStr));
220 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_album(audio, &tmpStr)) {
222 o["album"] = picojson::value(std::string(tmpStr));
227 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_artist(audio, &tmpStr)) {
229 picojson::array artists;
230 artists.push_back(picojson::value(std::string(tmpStr)));
231 o["artists"] = picojson::value(artists);
236 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_genre(audio, &tmpStr)) {
238 picojson::array genres;
239 genres.push_back(picojson::value(std::string(tmpStr)));
240 o["genres"] = picojson::value(genres);
245 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_composer(audio, &tmpStr)) {
247 picojson::array composers;
248 composers.push_back(picojson::value(std::string(tmpStr)));
249 o["composers"] = picojson::value(composers);
254 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_copyright(audio, &tmpStr)) {
256 o["copyright"] = picojson::value(std::string(tmpStr));
261 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_bit_rate(audio, &tmpInt)) {
262 o["bitrate"] = picojson::value(static_cast<double>(tmpInt));
264 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_track_num(audio, &tmpStr)) {
266 o["trackNumber"] = picojson::value(static_cast<double>(std::atoi(tmpStr)));
270 o["trackNumber"] = picojson::value();
273 if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_duration(audio, &tmpInt)) {
274 o["duration"] = picojson::value(static_cast<double>(tmpInt));
278 o["type"] = picojson::value(std::string("OTHER"));
281 ret = media_info_get_media_id(info, &tmpStr);
282 if (ret == MEDIA_CONTENT_ERROR_NONE) {
284 o["id"] = picojson::value(std::string(tmpStr));
289 ret = media_info_get_display_name(info, &tmpStr);
290 if (ret == MEDIA_CONTENT_ERROR_NONE) {
292 o["name"] = picojson::value(std::string(tmpStr));
298 ret = media_info_get_mime_type(info, &tmpStr);
299 if (ret == MEDIA_CONTENT_ERROR_NONE) {
301 o["mimeType"] = picojson::value(std::string(tmpStr));
306 ret = media_info_get_title(info, &tmpStr);
307 if (ret == MEDIA_CONTENT_ERROR_NONE) {
309 o["title"] = picojson::value(std::string(tmpStr));
314 ret = media_info_get_file_path(info, &tmpStr);
315 if (ret == MEDIA_CONTENT_ERROR_NONE) {
317 o["contentURI"] = picojson::value(std::string(tmpStr));
322 ret = media_info_get_thumbnail_path(info, &tmpStr);
323 if (ret == MEDIA_CONTENT_ERROR_NONE) {
325 picojson::array thumbnails;
326 thumbnails.push_back(picojson::value(std::string(tmpStr)));
327 o["thumbnailURIs"] = picojson::value(thumbnails);
332 ret = media_info_get_description(info, &tmpStr);
333 if (ret == MEDIA_CONTENT_ERROR_NONE) {
335 o["description"] = picojson::value(std::string(tmpStr));
340 ret = media_info_get_rating(info, &tmpInt);
341 if (ret == MEDIA_CONTENT_ERROR_NONE) {
342 o["rating"] = picojson::value(static_cast<double>(tmpInt));
344 ret = media_info_get_size(info, &tmpLong);
345 if (ret == MEDIA_CONTENT_ERROR_NONE) {
346 o["size"] = picojson::value(static_cast<double>(tmpLong));
348 ret = media_info_get_favorite(info, &tmpBool);
349 if (ret == MEDIA_CONTENT_ERROR_NONE) {
350 o["isFavorite"] = picojson::value(tmpBool);
352 ret = media_info_get_modified_time(info, &tmpDate);
353 if (ret == MEDIA_CONTENT_ERROR_NONE) {
354 o["modifiedDate"] = picojson::value(static_cast<double>(tmpDate));
358 void ContentDirToJson(media_folder_h folder, picojson::object& o) {
362 media_content_storage_e storage_type;
366 ret = media_folder_get_folder_id(folder, &tmpStr);
367 if (ret == MEDIA_CONTENT_ERROR_NONE) {
369 o["id"] = picojson::value(std::string(tmpStr));
376 ret = media_folder_get_path(folder, &tmpStr);
377 if (ret == MEDIA_CONTENT_ERROR_NONE) {
379 o["directoryURI"] = picojson::value(std::string(tmpStr));
386 ret = media_folder_get_name(folder, &tmpStr);
387 if (ret == MEDIA_CONTENT_ERROR_NONE) {
389 o["title"] = picojson::value(std::string(tmpStr));
396 ret = media_folder_get_storage_type(folder, &storage_type);
397 if (ret == MEDIA_CONTENT_ERROR_NONE) {
398 if (storage_type == MEDIA_CONTENT_STORAGE_INTERNAL) {
399 o["storageType"] = picojson::value(std::string("INTERNAL"));
400 } else if (storage_type == MEDIA_CONTENT_STORAGE_EXTERNAL) {
401 o["storageType"] = picojson::value(std::string("EXTERNAL"));
402 } else if (storage_type == MEDIA_CONTENT_STORAGE_CLOUD) {
403 o["storageType"] = picojson::value(std::string("CLOUD"));
408 ret = media_folder_get_modified_time(folder, &tmpDate);
409 if (ret == MEDIA_CONTENT_ERROR_NONE) {
410 o["modifiedDate"] = picojson::value(static_cast<double>(tmpDate));
414 static int setContent(media_info_h media, const picojson::value& content) {
418 std::string name = content.get("name").to_str();
419 std::string description = content.get("description").to_str();
420 int rating = std::stoi(content.get("rating").to_str());
421 bool is_fav = content.get("isFavorite").get<bool>();
424 LoggerE("MEDIA_CONTENT_ERROR_DB_FAILED");
425 return MEDIA_CONTENT_ERROR_DB_FAILED;
428 media_content_type_e type;
429 ret = media_info_get_media_type(media, &type);
430 if (ret != MEDIA_CONTENT_ERROR_NONE) {
431 LoggerE("Failed: media_info_get_media_type()");
435 ret = media_info_set_display_name(media, name.c_str());
436 if (ret != MEDIA_CONTENT_ERROR_NONE) {
437 LoggerE("Updating name failed.");
440 ret = media_info_set_description(media, description.c_str());
441 if (ret != MEDIA_CONTENT_ERROR_NONE) {
442 LoggerE("Updating description failed.");
445 ret = media_info_set_rating(media, rating);
446 if (ret != MEDIA_CONTENT_ERROR_NONE) {
447 LoggerE("Updating rating failed.");
450 ret = media_info_set_favorite(media, is_fav);
451 if (ret != MEDIA_CONTENT_ERROR_NONE) {
452 LoggerE("Updating isFavorite failed.");
455 if (ret != MEDIA_CONTENT_ERROR_NONE) {
456 LoggerE("Updating favorite failed.");
459 if (type == MEDIA_CONTENT_TYPE_IMAGE) {
460 std::string orientation = content.get("orientation").to_str();
461 auto orientationToSet = orientationMap.find(orientation);
463 if (orientationToSet != orientationMap.end()) {
465 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_image(media, &img) &&
466 MEDIA_CONTENT_ERROR_NONE == image_meta_set_orientation(img, orientationToSet->second) &&
467 MEDIA_CONTENT_ERROR_NONE == image_meta_update_to_db(img)) {
468 LoggerD("orientation update was successful");
470 LoggerE("orientation update failed");
472 image_meta_destroy(img);
476 if (type == MEDIA_CONTENT_TYPE_IMAGE || type == MEDIA_CONTENT_TYPE_VIDEO) {
477 picojson::value geo = content.get("geolocation");
478 if (geo.evaluate_as_boolean()) {
479 LoggerD("geolocation is not null");
480 double latitude = atof(geo.get("latitude").to_str().c_str());
481 double longitude = atof(geo.get("longitude").to_str().c_str());
482 ret = media_info_set_latitude(media, latitude);
483 if (ret != MEDIA_CONTENT_ERROR_NONE) {
484 LoggerE("Updating geolocation is failed.");
486 ret = media_info_set_longitude(media, longitude);
487 if (ret != MEDIA_CONTENT_ERROR_NONE) {
488 LoggerD("Updating geolocation is failed.");
491 LoggerD("geolocation is null");
495 return MEDIA_CONTENT_ERROR_NONE;
498 static void FolderToJson(media_folder_h folder, picojson::object* out) {
505 media_content_storage_e storageType;
509 ret = media_folder_get_folder_id(folder, &id);
510 if (ret != MEDIA_CONTENT_ERROR_NONE) {
511 LogAndReportError(ContentManager::convertError(ret), out,
512 ("Failed: media_folder_get_folder_id"));
516 ret = media_folder_get_name(folder, &name);
517 if (ret != MEDIA_CONTENT_ERROR_NONE) {
518 LogAndReportError(ContentManager::convertError(ret), out, ("Failed: media_folder_get_name"));
523 ret = media_folder_get_path(folder, &path);
524 if (ret != MEDIA_CONTENT_ERROR_NONE) {
525 LogAndReportError(ContentManager::convertError(ret), out, ("Failed: media_folder_get_path"));
531 ret = media_folder_get_modified_time(folder, &date);
532 if (ret != MEDIA_CONTENT_ERROR_NONE) {
533 LogAndReportError(ContentManager::convertError(ret), out, ("Failed: media_folder_get_path"));
540 ret = media_folder_get_storage_type(folder, &storageType);
541 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));
567 static bool media_foreach_directory_cb(media_folder_h folder, void* user_data) {
569 picojson::array* array = static_cast<picojson::array*>(user_data);
570 picojson::object json;
571 FolderToJson(folder, &json);
572 array->push_back(picojson::value(json));
576 static bool media_foreach_content_cb(media_info_h media, void* user_data) {
578 picojson::value::array* contents = static_cast<picojson::value::array*>(user_data);
579 picojson::value::object o;
580 ContentToJson(media, o);
581 contents->push_back(picojson::value(o));
585 static bool playlist_foreach_cb(media_playlist_h playlist, void* user_data) {
587 picojson::value::array* playlists = static_cast<picojson::value::array*>(user_data);
588 picojson::value::object o;
589 if (playlist != NULL) {
591 char* thumb_path = NULL;
593 filter_h filter = NULL;
594 if (media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
595 std::stringstream str_id;
597 o["id"] = picojson::value(std::to_string(id));
599 LoggerD("Invalid ID for playlist.");
601 if (media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
602 if (thumb_path != NULL) {
603 std::string thumbnail_uri(thumb_path);
604 if (thumbnail_uri != " ") {
605 thumbnail_uri = uri_prefix + thumbnail_uri;
607 o["thumbnailURI"] = picojson::value(thumbnail_uri);
610 o["thumbnailURI"] = picojson::value(); // picojson::value(std::string(""));
613 LoggerD("Invalid thumbnail path for playlist.");
615 if (media_playlist_get_name(playlist, &name) == MEDIA_CONTENT_ERROR_NONE) {
616 o["name"] = picojson::value(std::string(name));
619 LoggerD("Invalid name for playlist.");
622 media_filter_create(&filter);
623 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
624 filter, &media_filter_destroy); // automatically release the memory
625 if (media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
626 o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
628 LoggerE("Invalid count for playlist.");
630 playlists->push_back(picojson::value(o));
635 static bool playlist_content_member_cb(int playlist_member_id, media_info_h media,
638 picojson::value::array* contents = static_cast<picojson::value::array*>(user_data);
639 picojson::value::object o;
641 o["playlist_member_id"] = picojson::value(static_cast<double>(playlist_member_id));
642 ContentToJson(media, o);
643 contents->push_back(picojson::value(o));
647 void CreateThumbnailCallback(media_content_error_e err, const char* path, void* user_data) {
650 std::unique_ptr<CreateThumbnailCallbackData> callback_data_ptr(
651 (CreateThumbnailCallbackData*)user_data);
652 if (0 == callback_data_ptr->callback_id) {
653 LoggerD("Callback id is 0");
657 if (!(ContentManager::getInstance()->getContentInstance())) {
658 // There is not instance already
659 LoggerD("There is not instance now");
663 picojson::object out;
665 out["callbackId"] = picojson::value(callback_data_ptr->callback_id);
667 if (MEDIA_CONTENT_ERROR_NONE == err) {
668 out["result"] = picojson::value(std::string(path));
671 PlatformResult result = ContentManager::getInstance()->convertError(err);
672 LogAndReportError(result, &out, ("Failed to create a thumbnail"));
675 common::Instance::PostMessage(ContentManager::getInstance()->getContentInstance(),
676 picojson::value(out).serialize().c_str());
679 ContentManager::ContentManager() {
680 ScopeLogger("ContentManager called");
681 if (media_content_connect() == MEDIA_CONTENT_ERROR_NONE) {
682 m_dbConnected = true;
684 m_dbConnected = false;
686 m_contentInstance = nullptr;
689 ContentManager::~ContentManager() {
692 if (media_content_disconnect() == MEDIA_CONTENT_ERROR_NONE) {
693 m_dbConnected = false;
698 ContentManager* ContentManager::getInstance() {
700 static ContentManager instance;
704 ContentInstance* ContentManager::getContentInstance() {
706 return m_contentInstance;
709 void ContentManager::setContentInstance(ContentInstance* const content_instance) {
711 m_contentInstance = content_instance;
714 bool ContentManager::isConnected() {
716 return m_dbConnected;
719 void ContentManager::getDirectories(const std::shared_ptr<ReplyCallbackData>& user_data) {
722 filter_h filter = NULL;
723 ret = media_filter_create(&filter);
724 if (ret != MEDIA_CONTENT_ERROR_NONE) {
725 LoggerE("Failed: media_filter_create failed");
730 media_filter_destroy(filter);
733 std::string condition = "(FOLDER_STORAGE_TYPE = 0 OR FOLDER_STORAGE_TYPE = 1)";
734 media_filter_set_condition(filter, condition.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
736 picojson::array pico_dirs;
737 ret = media_folder_foreach_folder_from_db(filter, media_foreach_directory_cb, &pico_dirs);
738 if (ret != MEDIA_CONTENT_ERROR_NONE) {
739 PlatformResult err = LogAndCreateResult(
740 ErrorCode::UNKNOWN_ERR, "Getting the directories failed.",
741 ("Failed: Getting the directories failed %d (%s)", ret, get_error_message(ret)));
742 user_data->isSuccess = err;
746 user_data->result = picojson::value(pico_dirs);
749 void ContentManager::find(const std::shared_ptr<ReplyCallbackData>& user_data) {
756 picojson::value::array arrayContent;
757 filter_h filter = nullptr;
758 media_filter_create(&filter);
761 media_filter_destroy(filter);
765 if (!IsNull(user_data->args.get("filter"))) {
766 ContentFilter filterMechanism;
768 picojson::object argsObject = JsonCast<picojson::object>(user_data->args);
769 if (filterMechanism.BuildQuery(FromJson<picojson::object>(argsObject, "filter"), &query)) {
770 LoggerD("Filter query: %s", query.c_str());
771 ret = media_filter_set_condition(filter, query.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
772 if (MEDIA_CONTENT_ERROR_NONE != ret) {
773 LoggerE("Platform filter setting failed, error %d", ret);
778 if (user_data->args.contains("sortMode")) {
779 picojson::value vSortMode = user_data->args.get("sortMode");
781 if (vSortMode.is<picojson::object>()) {
782 std::string sortModeName, sortModeOrder;
784 ContentFilter::MapField(vSortMode.get("attributeName").to_str(), &sortModeName);
786 sortModeOrder = vSortMode.get("order").to_str();
787 if (!sortModeOrder.empty()) {
788 media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
790 if (sortModeOrder == "ASC") {
791 order = MEDIA_CONTENT_ORDER_ASC;
792 } else if (sortModeOrder == "DESC") {
793 order = MEDIA_CONTENT_ORDER_DESC;
796 ret = media_filter_set_order(filter, order, sortModeName.c_str(),
797 MEDIA_CONTENT_COLLATE_DEFAULT);
798 if (MEDIA_CONTENT_ERROR_NONE != ret) {
799 LoggerE("Platform SortMode setting failed, error: %d", ret);
805 if (!IsNull(user_data->args.get("count"))) {
806 count = static_cast<int>(user_data->args.get("count").get<double>());
810 if (!IsNull(user_data->args.get("offset"))) {
811 offset = static_cast<int>(user_data->args.get("offset").get<double>());
815 ret = media_filter_set_offset(filter, offset, count);
816 if (MEDIA_CONTENT_ERROR_NONE != ret) {
817 LoggerE("A platform error occurs in media_filter_set_offset: %d", ret);
819 if (!IsNull(user_data->args.get("directoryId"))) {
820 dirId = user_data->args.get("directoryId").get<std::string>();
821 ret = media_folder_foreach_media_from_db(dirId.c_str(), filter, media_foreach_content_cb,
822 static_cast<void*>(&arrayContent));
824 ret = media_info_foreach_media_from_db(filter, media_foreach_content_cb,
825 static_cast<void*>(&arrayContent));
828 if (ret == MEDIA_CONTENT_ERROR_NONE) {
829 user_data->result = picojson::value(arrayContent);
831 PlatformResult err = LogAndCreateResult(
832 ErrorCode::UNKNOWN_ERR, "The iteration failed in platform",
833 ("The iteration failed in platform: %d (%s)", ret, get_error_message(ret)));
834 user_data->isSuccess = err;
838 int ContentManager::scanFile(std::string& uri) {
840 return media_content_scan_file(uri.c_str());
843 PlatformResult ContentManager::scanDirectory(media_scan_completed_cb callback,
844 ReplyCallbackData* cbData) {
846 const std::string& contentDirURI = cbData->args.get("contentDirURI").get<std::string>();
847 std::string real_path = common::FilesystemProvider::Create().GetRealPath(contentDirURI);
848 const bool recursive = cbData->args.get("recursive").get<bool>();
850 int ret = media_content_scan_folder(real_path.c_str(), recursive, callback, (void*)cbData);
852 if (ret != MEDIA_CONTENT_ERROR_NONE) {
853 if (MEDIA_CONTENT_ERROR_INVALID_PARAMETER == ret) {
854 return LogAndCreateResult(
855 ErrorCode::INVALID_VALUES_ERR, "Scanning content directory failed",
856 ("Scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
859 return LogAndCreateResult(
860 ErrorCode::UNKNOWN_ERR, "Scanning content directory failed",
861 ("Scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
864 return PlatformResult(ErrorCode::NO_ERROR);
867 PlatformResult ContentManager::cancelScanDirectory(const std::string& content_dir_uri) {
870 int ret = media_content_cancel_scan_folder(content_dir_uri.c_str());
871 if (ret != MEDIA_CONTENT_ERROR_NONE) {
872 return LogAndCreateResult(
873 ErrorCode::UNKNOWN_ERR, "Cancel scan content directory failed",
874 ("Cancel scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
876 return PlatformResult(ErrorCode::NO_ERROR);
879 PlatformResult ContentManager::addChangeListener(media_content_noti_h* noti_handle,
880 media_content_db_update_cb callback,
884 int ret = media_content_add_db_updated_cb(callback, user_data, noti_handle);
886 if (MEDIA_CONTENT_ERROR_NONE != ret) {
887 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to add the listener.",
888 ("Failed to add the listener: %d (%s)", ret, get_error_message(ret)));
891 return PlatformResult(ErrorCode::NO_ERROR);
894 PlatformResult ContentManager::removeChangeListener(media_content_noti_h noti_handle) {
897 int ret = media_content_remove_db_updated_cb(noti_handle);
900 case MEDIA_CONTENT_ERROR_NONE:
901 return PlatformResult(ErrorCode::NO_ERROR);
902 case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
903 // Trying to remove non-existent listener, ignoring
904 LoggerI("Failed to remove the listener: %d (%s)", ret, get_error_message(ret));
905 return PlatformResult(ErrorCode::NO_ERROR);
907 return LogAndCreateResult(
908 ErrorCode::ABORT_ERR, "Failed to remove the listener.",
909 ("Failed to remove the listener: %d (%s)", ret, get_error_message(ret)));
913 PlatformResult ContentManager::setChangeListener(media_content_db_update_cb callback,
917 int ret = media_content_set_db_updated_cb(callback, user_data);
918 if (ret != MEDIA_CONTENT_ERROR_NONE) {
919 return LogAndCreateResult(
920 ErrorCode::UNKNOWN_ERR, "registering the listener is failed.",
921 ("Failed: registering the listener is failed %d (%s)", ret, get_error_message(ret)));
923 return PlatformResult(ErrorCode::NO_ERROR);
926 PlatformResult ContentManager::unSetChangeListener() {
929 int ret = media_content_unset_db_updated_cb();
930 if (ret != MEDIA_CONTENT_ERROR_NONE) {
931 return LogAndCreateResult(
932 ErrorCode::UNKNOWN_ERR, "unregistering the listener is failed.",
933 ("Failed: unregistering the listener is failed: %d (%s)", ret, get_error_message(ret)));
935 return PlatformResult(ErrorCode::NO_ERROR);
938 void ContentManager::createPlaylist(std::string name,
939 const std::shared_ptr<ReplyCallbackData>& user_data) {
941 media_playlist_h playlist = NULL;
943 int ret = media_playlist_insert_to_db(name.c_str(), &playlist);
944 std::unique_ptr<std::remove_pointer<media_playlist_h>::type, int (*)(media_playlist_h)>
945 playlist_ptr(playlist, &media_playlist_destroy); // automatically release the memory
946 if (ret != MEDIA_CONTENT_ERROR_NONE) {
947 // MEDIA_CONTENT_ERROR_DB_FAILED means that playlist probably already exists
948 PlatformResult err = LogAndCreateResult(
949 MEDIA_CONTENT_ERROR_DB_FAILED == ret ? ErrorCode::INVALID_VALUES_ERR
950 : ErrorCode::UNKNOWN_ERR,
951 "Creation of playlist has failed.",
952 ("Failed: creation of playlist is failed: %d (%s)", ret, get_error_message(ret)));
953 user_data->isSuccess = err;
956 picojson::value::object o;
958 if (playlist != NULL) {
960 char* thumb_path = NULL;
961 char* name_playlist = NULL;
962 filter_h filter = NULL;
963 if (media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
964 o["id"] = picojson::value(std::to_string(id));
967 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "loading of playlist is failed.");
968 user_data->isSuccess = err;
971 if (media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
972 if (thumb_path != NULL) {
973 o["thumbnailURI"] = picojson::value(std::string(thumb_path));
976 o["thumbnailURI"] = picojson::value();
979 LoggerE("Invalid thumbnail path for playlist.");
981 if (media_playlist_get_name(playlist, &name_playlist) == MEDIA_CONTENT_ERROR_NONE) {
982 o["name"] = picojson::value(std::string(name_playlist));
985 LoggerE("Invalid name for playlist.");
987 media_filter_create(&filter);
988 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
989 filter, &media_filter_destroy); // automatically release the memory
991 if (media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
992 o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
994 LoggerE("Invalid count for playlist.");
998 user_data->result = picojson::value(o);
1001 void ContentManager::getPlaylists(const std::shared_ptr<ReplyCallbackData>& user_data) {
1004 filter_h filter = nullptr;
1005 media_filter_create(&filter);
1006 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
1007 filter, &media_filter_destroy); // automatically release the memory
1008 picojson::value::array playlists;
1010 ret = media_playlist_foreach_playlist_from_db(filter, playlist_foreach_cb,
1011 static_cast<void*>(&playlists));
1013 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1014 PlatformResult err = LogAndCreateResult(
1015 ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1016 ("Failed: Getting playlist is failed %d (%s)", ret, get_error_message(ret)));
1017 user_data->isSuccess = err;
1020 user_data->result = picojson::value(playlists);
1023 void ContentManager::removePlaylist(std::string playlistId,
1024 const std::shared_ptr<ReplyCallbackData>& user_data) {
1026 int id = std::atoi(playlistId.c_str());
1028 PlatformResult err = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "PlaylistId is wrong.");
1029 user_data->isSuccess = err;
1033 int ret = media_playlist_delete_from_db(id);
1034 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1035 PlatformResult err =
1036 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Removal of playlist is failed.");
1037 user_data->isSuccess = err;
1041 int ContentManager::update(picojson::value args) {
1045 picojson::value content = args.get("content");
1046 std::string id = content.get("id").to_str();
1048 media_info_h media = NULL;
1049 ret = media_info_get_media_from_db(id.c_str(), &media);
1050 if (ret == MEDIA_CONTENT_ERROR_NONE) {
1051 setContent(media, content);
1052 ret = media_info_update_to_db(media);
1053 media_info_destroy(media);
1059 int ContentManager::updateBatch(picojson::value args) {
1062 std::vector<picojson::value> contents = args.get("contents").get<picojson::array>();
1064 for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
1065 picojson::value content = *it;
1066 std::string id = content.get("id").to_str();
1067 media_info_h media = NULL;
1068 ret = media_info_get_media_from_db(id.c_str(), &media);
1069 if (media != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1070 ret = setContent(media, content);
1071 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1072 LoggerE("setContent failed");
1076 ret = media_info_update_to_db(media);
1077 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1078 LoggerE("update to db failed");
1080 media_info_destroy(media);
1088 int ContentManager::playlistAdd(std::string playlist_id, std::string content_id) {
1091 media_playlist_h playlist = NULL;
1092 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1094 if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1095 ret = media_playlist_add_media(playlist, content_id.c_str());
1096 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1097 LoggerE("The content(id:%s) can't add to playlist", content_id.c_str());
1100 ret = media_playlist_update_to_db(playlist);
1101 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1102 LoggerE("The content(id:%s) can't add to playlist", content_id.c_str());
1105 LoggerE("Playlist(id:%s) is not exist", playlist_id.c_str());
1108 media_playlist_destroy(playlist);
1112 int ContentManager::playlistRemove(std::string playlist_id, int member_id) {
1115 media_playlist_h playlist = NULL;
1116 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1117 if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1118 ret = media_playlist_remove_media(playlist, member_id);
1119 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1120 LoggerE("The content can't remove to playlist");
1123 ret = media_playlist_update_to_db(playlist);
1124 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1125 LoggerE("The content can't remove to playlist");
1128 LoggerE("Playlist(id:%s) is not exist", playlist_id.c_str());
1130 media_playlist_destroy(playlist);
1135 void ContentManager::playlistAddbatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
1137 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1139 media_playlist_h playlist = NULL;
1140 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1142 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1143 PlatformResult err =
1144 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1145 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1146 user_data->isSuccess = err;
1150 std::vector<picojson::value> contents = user_data->args.get("contents").get<picojson::array>();
1151 for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
1152 picojson::value content = *it;
1153 std::string id = content.get("id").to_str();
1154 ret = media_playlist_add_media(playlist, id.c_str());
1155 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1156 LoggerE("Adding Content(id:%s) is failed.", id.c_str());
1160 ret = media_playlist_update_to_db(playlist);
1161 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1162 PlatformResult err =
1163 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Adding playlist is failed.",
1164 ("Adding playlist is failed: %d (%s)", ret, get_error_message(ret)));
1165 user_data->isSuccess = err;
1167 media_playlist_destroy(playlist);
1170 void ContentManager::playlistGet(const std::shared_ptr<ReplyCallbackData>& user_data) {
1172 media_playlist_h playlist = NULL;
1173 media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
1174 const std::string playOrder("play_order");
1178 media_playlist_destroy(playlist);
1182 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1183 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1184 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1185 PlatformResult err =
1186 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1187 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1188 user_data->isSuccess = err;
1192 filter_h filter = NULL;
1193 ret = media_filter_create(&filter);
1194 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1195 PlatformResult err =
1196 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.",
1197 ("Creating a filter is failed: %d (%s)", ret, get_error_message(ret)));
1198 user_data->isSuccess = err;
1202 int count = user_data->args.get("count").get<double>();
1203 int offset = user_data->args.get("offset").get<double>();
1204 ret = media_filter_set_offset(filter, offset, count);
1205 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1206 LoggerD("Setting a offset/count is failed.");
1208 ret = media_filter_set_order(filter, order, playOrder.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
1209 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1210 LoggerD("Setting a offset/count is failed.");
1213 picojson::value::array arrayContent;
1214 ret = media_playlist_foreach_media_from_db(std::stoi(playlist_id), filter,
1215 playlist_content_member_cb,
1216 static_cast<void*>(&arrayContent));
1218 media_filter_destroy(filter);
1219 if (ret == MEDIA_CONTENT_ERROR_NONE) {
1220 user_data->result = picojson::value(arrayContent);
1222 PlatformResult err =
1223 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.",
1224 ("Creating a filter is failed: %d (%s)", ret, get_error_message(ret)));
1225 user_data->isSuccess = err;
1229 void ContentManager::playlistRemovebatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
1231 media_playlist_h playlist = NULL;
1235 media_playlist_destroy(playlist);
1239 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1240 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1241 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1242 PlatformResult err =
1243 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1244 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1245 user_data->isSuccess = err;
1249 std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
1250 std::size_t members_size = members.size();
1251 for (std::size_t i = 0; i < members_size; ++i) {
1252 int member_id = static_cast<int>(members.at(i).get<double>());
1253 ret = media_playlist_remove_media(playlist, member_id);
1255 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1256 LoggerD("Removing a content is failed.");
1260 ret = media_playlist_update_to_db(playlist);
1261 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1262 PlatformResult err = LogAndCreateResult(
1263 ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.",
1264 ("Removing the contents is failed: %d (%s)", ret, get_error_message(ret)));
1265 user_data->isSuccess = err;
1269 void ContentManager::playlistSetOrder(const std::shared_ptr<ReplyCallbackData>& user_data) {
1271 media_playlist_h playlist = NULL;
1275 media_playlist_destroy(playlist);
1279 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1280 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1281 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1282 PlatformResult err =
1283 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1284 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1285 user_data->isSuccess = err;
1290 std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
1292 ret = media_playlist_get_media_count_from_db(std::stoi(playlist_id), NULL, &cnt);
1293 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1294 LoggerE("Failed: media_playlist_get_media_count_from_db");
1295 PlatformResult err = convertError(ret);
1296 user_data->isSuccess = err;
1299 std::size_t members_size = members.size();
1300 if (cnt < 0 || static_cast<size_t>(cnt) != members_size) {
1301 PlatformResult err = LogAndCreateResult(
1302 ErrorCode::INVALID_VALUES_ERR,
1303 "The items array does not contain all items from the playlist.",
1304 ("Failed: The items array does not contain all items from the playlist: %d (%s)", ret,
1305 get_error_message(ret)));
1306 user_data->isSuccess = err;
1310 for (std::size_t i = 0; i < members_size; ++i) {
1311 int member_id = static_cast<int>(members.at(i).get<double>());
1312 ret = media_playlist_set_play_order(playlist, member_id, i);
1313 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1314 LoggerD("Removing a content is failed.");
1318 ret = media_playlist_update_to_db(playlist);
1319 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1320 PlatformResult err = LogAndCreateResult(
1321 ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.",
1322 ("Removing the contents is failed: %d (%s)", ret, get_error_message(ret)));
1323 user_data->isSuccess = err;
1327 void ContentManager::playlistMove(const std::shared_ptr<ReplyCallbackData>& user_data) {
1329 media_playlist_h playlist = NULL;
1333 media_playlist_destroy(playlist);
1337 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1338 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1339 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1340 PlatformResult err =
1341 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1342 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1343 user_data->isSuccess = err;
1347 double member_id = user_data->args.get("memberId").get<double>();
1348 double delta = user_data->args.get("delta").get<double>();
1349 ret = media_playlist_get_play_order(playlist, static_cast<int>(member_id), &old_order);
1350 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1351 PlatformResult err = LogAndCreateResult(
1352 ErrorCode::UNKNOWN_ERR, "The content can't find form playlist.",
1353 ("The content can't find form playlist: %d (%s)", ret, get_error_message(ret)));
1354 user_data->isSuccess = err;
1357 int new_order = static_cast<int>(old_order) + static_cast<int>(delta);
1358 ret = media_playlist_set_play_order(playlist, static_cast<int>(member_id), new_order);
1359 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1360 PlatformResult err = LogAndCreateResult(
1361 ErrorCode::UNKNOWN_ERR, "The content can't update play_order.",
1362 ("The content can't update play_order: %d (%s)", ret, get_error_message(ret)));
1363 user_data->isSuccess = err;
1366 ret = media_playlist_update_to_db(playlist);
1367 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1368 PlatformResult err = LogAndCreateResult(
1369 ErrorCode::UNKNOWN_ERR, "Updateing play_order is failed.",
1370 ("Updateing play_order is failed: %d (%s)", ret, get_error_message(ret)));
1371 user_data->isSuccess = err;
1375 int ContentManager::getLyrics(const picojson::value& args, picojson::object& result) {
1378 int ret = METADATA_EXTRACTOR_ERROR_NONE;
1379 const std::string& contentURI = args.get("contentURI").to_str();
1380 if (contentURI.empty()) {
1381 LoggerE("contentURI empty - skipping media extractor");
1385 metadata_extractor_h extractor;
1386 ret = metadata_extractor_create(&extractor);
1387 if (METADATA_EXTRACTOR_ERROR_NONE != ret) {
1388 LoggerE("metadata_extractor_create failed, error: %d", ret);
1390 std::unique_ptr<std::remove_pointer<metadata_extractor_h>::type, int (*)(metadata_extractor_h)>
1391 extractor_ptr(extractor, &metadata_extractor_destroy); // automatically release the memory
1393 ret = metadata_extractor_set_path(extractor, contentURI.c_str());
1394 if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
1395 LoggerE("metadata_extractor_set_path failed, error: %d", ret);
1398 picojson::array timestamps;
1399 picojson::array texts = picojson::array();
1400 char* strSyncTextNum = NULL;
1402 ret = metadata_extractor_get_metadata(extractor, METADATA_SYNCLYRICS_NUM, &strSyncTextNum);
1403 if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
1404 LoggerE("Media extractor error %d", ret);
1408 int nSyncTextNum = 0;
1409 if (strSyncTextNum) {
1410 nSyncTextNum = atoi(strSyncTextNum);
1411 free(strSyncTextNum);
1412 strSyncTextNum = NULL;
1414 if (nSyncTextNum > 0) {
1415 result["type"] = picojson::value(std::string("SYNCHRONIZED"));
1416 for (int i = 0; i < nSyncTextNum; i++) {
1417 unsigned long time_info = 0;
1418 char* lyrics = NULL;
1419 ret = metadata_extractor_get_synclyrics(extractor, i, &time_info, &lyrics);
1420 if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
1421 timestamps.push_back(picojson::value(static_cast<double>(time_info)));
1422 texts.push_back(picojson::value(std::string(lyrics)));
1426 result["texts"] = picojson::value(texts);
1427 result["timestamps"] = picojson::value(timestamps);
1428 ret = METADATA_EXTRACTOR_ERROR_NONE;
1430 char* unSyncText = nullptr;
1431 ret = metadata_extractor_get_metadata(extractor, METADATA_UNSYNCLYRICS, &unSyncText);
1432 if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
1433 result["type"] = picojson::value(std::string("UNSYNCHRONIZED"));
1434 if (nullptr == unSyncText) {
1435 LoggerE("Unsynchronized lyrics text is NULL");
1437 texts.push_back(picojson::value(unSyncText ? unSyncText : ""));
1438 result["texts"] = picojson::value(texts);
1446 media_playlist_h getPlaylistHandle(int id) {
1448 media_playlist_h playlist_handle = nullptr;
1449 int ret_code = media_playlist_get_playlist_from_db(id, &playlist_handle);
1450 if (MEDIA_CONTENT_ERROR_NONE != ret_code || playlist_handle == nullptr) {
1451 LoggerE("could not get playlist handle for id: %d", id);
1455 return playlist_handle;
1458 void destroyMediaPlaylistHandle(media_playlist_h& playlist_handle) {
1460 if (playlist_handle) {
1461 int ret_code = media_playlist_destroy(playlist_handle);
1462 playlist_handle = nullptr;
1464 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1465 LoggerE("media_playlist_destroy failed");
1470 int ContentManager::getPlaylistName(int id, std::string* result) {
1472 media_playlist_h playlist_handle = getPlaylistHandle(id);
1473 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1475 char* tmp_playlist_name = nullptr;
1476 const int ret_code = media_playlist_get_name(playlist_handle, &tmp_playlist_name);
1478 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1479 LoggerE("media_playlist_get_name failed");
1480 return TIZEN_ERROR_UNKNOWN;
1483 std::string playlist_name;
1484 if (tmp_playlist_name) {
1485 playlist_name = tmp_playlist_name;
1486 free(tmp_playlist_name);
1487 tmp_playlist_name = nullptr;
1490 *result = playlist_name;
1491 return MEDIA_CONTENT_ERROR_NONE;
1494 int updatePlaylistInDB(media_playlist_h playlist_handle) {
1496 int ret_code = media_playlist_update_to_db(playlist_handle);
1497 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1498 LoggerE("media_playlist_update_to_db failed");
1501 return MEDIA_CONTENT_ERROR_NONE;
1504 int ContentManager::setPlaylistName(int id, const std::string& name) {
1507 LoggerE("Cannot set empty playlist name!");
1508 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1511 media_playlist_h playlist_handle = getPlaylistHandle(id);
1512 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1514 const int ret_code = media_playlist_set_name(playlist_handle, name.c_str());
1515 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1516 LoggerE("media_playlist_set_name failed");
1517 // Setting name that is used by other playlist does not return bad error code here.
1518 // MEDIA_CONTENT_ERROR_INVALID_OPERATION is being returned in updatePlaylistInDB
1519 return TIZEN_ERROR_UNKNOWN;
1522 int ret = updatePlaylistInDB(playlist_handle);
1523 if (MEDIA_CONTENT_ERROR_NONE != ret) {
1524 LoggerE("Error while updating playlist: %d", ret);
1525 if (MEDIA_CONTENT_ERROR_DB_FAILED == ret) {
1526 // We could fetch list of playlists and check if other playlist is using this
1527 // name, but that seems to be to much work in synchronous method
1528 LoggerE("Playlist name: %s is probably already used", name.c_str());
1529 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1533 return MEDIA_CONTENT_ERROR_NONE;
1536 int ContentManager::getThumbnailUri(int id, std::string* result) {
1538 media_playlist_h playlist_handle = getPlaylistHandle(id);
1539 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1541 char* tmp_playlist_thb_path = nullptr;
1542 const int ret_code = media_playlist_get_thumbnail_path(playlist_handle, &tmp_playlist_thb_path);
1544 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1545 LoggerE("media_playlist_get_name failed");
1546 return TIZEN_ERROR_UNKNOWN;
1549 std::string playlist_thb_path;
1550 if (tmp_playlist_thb_path) {
1551 playlist_thb_path = tmp_playlist_thb_path;
1552 free(tmp_playlist_thb_path);
1553 tmp_playlist_thb_path = nullptr;
1556 if (playlist_thb_path != " ") {
1557 playlist_thb_path = uri_prefix + playlist_thb_path;
1560 *result = playlist_thb_path;
1561 return MEDIA_CONTENT_ERROR_NONE;
1564 int ContentManager::setThumbnailUri(int id, const std::string& thb_uri) {
1567 // Allow setting empty URI, unfortunately Core API does not allow to set empty
1568 // path so we need to set one empty space. This is probably issue of Core API.
1569 if (!thb_uri.empty() && " " != thb_uri) {
1570 if (thb_uri.find(uri_absolute_prefix) != 0) {
1571 LoggerE("thumbnail URI is not valid: [%s]", thb_uri.c_str());
1572 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1576 media_playlist_h playlist_handle = getPlaylistHandle(id);
1577 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1579 std::string real_path = common::FilesystemProvider::Create().GetRealPath(thb_uri);
1580 const int ret_code = media_playlist_set_thumbnail_path(playlist_handle, real_path.c_str());
1581 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1582 LoggerE("media_playlist_set_thumbnail_path failed");
1583 return TIZEN_ERROR_UNKNOWN;
1586 int ret = updatePlaylistInDB(playlist_handle);
1590 int ContentManager::getNumberOfTracks(int id, int* result) {
1594 const int ret_code = media_playlist_get_media_count_from_db(id, nullptr, &count);
1596 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1597 LoggerE("media_playlist_get_media_count_from_db failed");
1598 return TIZEN_ERROR_UNKNOWN;
1602 return MEDIA_CONTENT_ERROR_NONE;
1605 common::PlatformResult ContentManager::createThumbnail(const picojson::value& args) {
1608 std::unique_ptr<CreateThumbnailCallbackData> callback_data_ptr{new CreateThumbnailCallbackData};
1609 callback_data_ptr->callback_id = args.get("callbackId").get<double>();
1610 std::string id = args.get("id").get<std::string>();
1612 int ret = media_info_get_media_from_db(id.c_str(), &callback_data_ptr->media);
1613 if (MEDIA_CONTENT_ERROR_NONE != ret && nullptr == callback_data_ptr->media) {
1614 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Getting media is failed.",
1615 ("Getting media is failed: %d (%s)", ret, get_error_message(ret)));
1618 ret = media_info_create_thumbnail(callback_data_ptr->media, CreateThumbnailCallback,
1619 static_cast<void*>(callback_data_ptr.get()));
1621 if (MEDIA_CONTENT_ERROR_NONE != ret) {
1622 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Creating thumbnail failed.",
1623 ("Creating thumbnail failed: %d (%s)", ret, get_error_message(ret)));
1625 callback_data_ptr.release();
1626 return PlatformResult(ErrorCode::NO_ERROR);
1629 PlatformResult ContentManager::convertError(int err) {
1630 char* error_msg = get_error_message(err);
1632 case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
1633 return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, error_msg);
1634 case MEDIA_CONTENT_ERROR_OUT_OF_MEMORY:
1635 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1636 case MEDIA_CONTENT_ERROR_INVALID_OPERATION:
1637 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1638 case MEDIA_CONTENT_FILE_NO_SPACE_ON_DEVICE:
1639 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1640 case MEDIA_CONTENT_ERROR_PERMISSION_DENIED:
1641 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1642 case MEDIA_CONTENT_ERROR_DB_FAILED:
1643 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1644 case MEDIA_CONTENT_ERROR_DB_BUSY:
1645 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1646 case MEDIA_CONTENT_ERROR_NETWORK:
1647 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1648 case MEDIA_CONTENT_ERROR_UNSUPPORTED_CONTENT:
1649 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1651 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
1655 } // namespace content
1656 } // namespace extension