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 // TODO: The function media_folder_get_storage_type is marked as deprecated since 5.0.
402 // As an alternative, it is recommended to use storage_get_type_dev function. However,
403 // this function does not work with internal storages. The media_folder_get_storage_type
404 // function should be kept or moved to internal header by Native API.
405 if (ret == MEDIA_CONTENT_ERROR_NONE) {
406 if (storage_type == MEDIA_CONTENT_STORAGE_INTERNAL) {
407 o["storageType"] = picojson::value(std::string("INTERNAL"));
409 LoggerD("storageType = %d, assuming EXTERNAL as storage type", storage_type);
410 o["storageType"] = picojson::value(std::string("EXTERNAL"));
415 struct stat stat_res;
416 if (stat(folder_path.c_str(), &stat_res) == 0) {
417 auto mod_time = stat_res.st_mtime;
418 o["modifiedDate"] = picojson::value(static_cast<double>(mod_time));
422 static int setContent(media_info_h media, const picojson::value& content) {
426 std::string name = content.get("name").to_str();
427 std::string description = content.get("description").to_str();
428 int rating = std::stoi(content.get("rating").to_str());
429 bool is_fav = content.get("isFavorite").get<bool>();
432 LoggerE("MEDIA_CONTENT_ERROR_DB_FAILED");
433 return MEDIA_CONTENT_ERROR_DB_FAILED;
436 media_content_type_e type;
437 ret = media_info_get_media_type(media, &type);
438 if (ret != MEDIA_CONTENT_ERROR_NONE) {
439 LoggerE("Failed: media_info_get_media_type()");
443 ret = media_info_set_display_name(media, name.c_str());
444 if (ret != MEDIA_CONTENT_ERROR_NONE) {
445 LoggerE("Updating name failed.");
448 ret = media_info_set_description(media, description.c_str());
449 if (ret != MEDIA_CONTENT_ERROR_NONE) {
450 LoggerE("Updating description failed.");
453 ret = media_info_set_rating(media, rating);
454 if (ret != MEDIA_CONTENT_ERROR_NONE) {
455 LoggerE("Updating rating failed.");
458 ret = media_info_set_favorite(media, is_fav);
459 if (ret != MEDIA_CONTENT_ERROR_NONE) {
460 LoggerE("Updating isFavorite failed.");
463 if (ret != MEDIA_CONTENT_ERROR_NONE) {
464 LoggerE("Updating favorite failed.");
467 if (type == MEDIA_CONTENT_TYPE_IMAGE) {
468 std::string orientation = content.get("orientation").to_str();
469 auto orientationToSet = orientationMap.find(orientation);
471 if (orientationToSet != orientationMap.end()) {
473 if (MEDIA_CONTENT_ERROR_NONE == media_info_get_image(media, &img) &&
474 MEDIA_CONTENT_ERROR_NONE == image_meta_set_orientation(img, orientationToSet->second) &&
475 MEDIA_CONTENT_ERROR_NONE == image_meta_update_to_db(img)) {
476 LoggerD("orientation update was successful");
478 LoggerE("orientation update failed");
480 image_meta_destroy(img);
484 if (type == MEDIA_CONTENT_TYPE_IMAGE || type == MEDIA_CONTENT_TYPE_VIDEO) {
485 picojson::value geo = content.get("geolocation");
486 if (geo.evaluate_as_boolean()) {
487 LoggerD("geolocation is not null");
488 double latitude = atof(geo.get("latitude").to_str().c_str());
489 double longitude = atof(geo.get("longitude").to_str().c_str());
490 ret = media_info_set_latitude(media, latitude);
491 if (ret != MEDIA_CONTENT_ERROR_NONE) {
492 LoggerE("Updating geolocation is failed.");
494 ret = media_info_set_longitude(media, longitude);
495 if (ret != MEDIA_CONTENT_ERROR_NONE) {
496 LoggerD("Updating geolocation is failed.");
499 LoggerD("geolocation is null");
503 return MEDIA_CONTENT_ERROR_NONE;
506 static void FolderToJson(media_folder_h folder, picojson::object* out) {
513 media_content_storage_e storageType;
517 ret = media_folder_get_folder_id(folder, &id);
518 if (ret != MEDIA_CONTENT_ERROR_NONE) {
519 LogAndReportError(ContentManager::convertError(ret), out,
520 ("Failed: media_folder_get_folder_id"));
523 std::unique_ptr<char, decltype(&free)> id_ptr(id, &free);
525 ret = media_folder_get_name(folder, &name);
526 if (ret != MEDIA_CONTENT_ERROR_NONE) {
527 LogAndReportError(ContentManager::convertError(ret), out, ("Failed: media_folder_get_name"));
530 std::unique_ptr<char, decltype(&free)> name_ptr(name, &free);
532 ret = media_folder_get_path(folder, &path);
533 if (ret != MEDIA_CONTENT_ERROR_NONE) {
534 LogAndReportError(ContentManager::convertError(ret), out, ("Failed: media_folder_get_path"));
537 std::unique_ptr<char, decltype(&free)> path_ptr(path, &free);
539 struct stat stat_res;
540 ret = stat(path, &stat_res);
542 LogAndReportError(ContentManager::convertError(errno), out, ("Failed: stat"));
545 date = stat_res.st_mtime;
547 ret = media_folder_get_storage_type(folder, &storageType);
548 // TODO: The function media_folder_get_storage_type is marked as deprecated since 5.0.
549 // As an alternative, it is recommended to use storage_get_type_dev function. However,
550 // this function does not work with internal storages. The media_folder_get_storage_type
551 // function should be kept or moved to internal header by Native API.
552 if (ret != MEDIA_CONTENT_ERROR_NONE) {
553 LogAndReportError(ContentManager::convertError(ret), out,
554 ("Failed: media_folder_get_storage_type"));
558 (*out)["id"] = picojson::value(std::string(id));
559 (*out)["directoryURI"] = picojson::value(std::string(path));
560 (*out)["title"] = picojson::value(std::string(name));
562 if (storageType == MEDIA_CONTENT_STORAGE_INTERNAL) {
563 (*out)["storageType"] = picojson::value(std::string("INTERNAL"));
564 } else if (storageType == MEDIA_CONTENT_STORAGE_EXTERNAL) {
565 (*out)["storageType"] = picojson::value(std::string("EXTERNAL"));
568 (*out)["modifiedDate"] = picojson::value(static_cast<double>(date));
571 static bool media_foreach_directory_cb(media_folder_h folder, void* user_data) {
573 picojson::array* array = static_cast<picojson::array*>(user_data);
574 picojson::object json;
575 FolderToJson(folder, &json);
576 array->push_back(picojson::value(json));
580 static bool media_foreach_content_cb(media_info_h media, void* user_data) {
582 picojson::value::array* contents = static_cast<picojson::value::array*>(user_data);
583 picojson::value::object o;
584 ContentToJson(media, o);
585 contents->push_back(picojson::value(o));
589 static bool playlist_foreach_cb(media_playlist_h playlist, void* user_data) {
591 picojson::value::array* playlists = static_cast<picojson::value::array*>(user_data);
592 picojson::value::object o;
593 if (playlist != NULL) {
595 char* thumb_path = NULL;
597 filter_h filter = NULL;
598 if (media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
599 std::stringstream str_id;
601 o["id"] = picojson::value(std::to_string(id));
603 LoggerD("Invalid ID for playlist.");
605 if (media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
606 if (thumb_path != NULL) {
607 std::string thumbnail_uri(thumb_path);
608 if (thumbnail_uri != " ") {
609 thumbnail_uri = uri_prefix + thumbnail_uri;
611 o["thumbnailURI"] = picojson::value(thumbnail_uri);
614 o["thumbnailURI"] = picojson::value(); // picojson::value(std::string(""));
617 LoggerD("Invalid thumbnail path for playlist.");
619 if (media_playlist_get_name(playlist, &name) == MEDIA_CONTENT_ERROR_NONE) {
620 o["name"] = picojson::value(std::string(name));
623 LoggerD("Invalid name for playlist.");
626 media_filter_create(&filter);
627 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
628 filter, &media_filter_destroy); // automatically release the memory
629 if (media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
630 o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
632 LoggerE("Invalid count for playlist.");
634 playlists->push_back(picojson::value(o));
639 static bool playlist_content_member_cb(int playlist_member_id, media_info_h media,
642 picojson::value::array* contents = static_cast<picojson::value::array*>(user_data);
643 picojson::value::object o;
645 o["playlist_member_id"] = picojson::value(static_cast<double>(playlist_member_id));
646 ContentToJson(media, o);
647 contents->push_back(picojson::value(o));
651 ContentManager::ContentManager() {
652 ScopeLogger("ContentManager called");
653 if (media_content_connect() == MEDIA_CONTENT_ERROR_NONE) {
654 m_dbConnected = true;
656 m_dbConnected = false;
658 m_contentInstance = nullptr;
661 ContentManager::~ContentManager() {
664 if (media_content_disconnect() == MEDIA_CONTENT_ERROR_NONE) {
665 m_dbConnected = false;
670 ContentManager* ContentManager::getInstance() {
672 static ContentManager instance;
676 ContentInstance* ContentManager::getContentInstance() {
678 return m_contentInstance;
681 void ContentManager::setContentInstance(ContentInstance* const content_instance) {
683 m_contentInstance = content_instance;
686 bool ContentManager::isConnected() {
688 return m_dbConnected;
691 void ContentManager::getDirectories(const std::shared_ptr<ReplyCallbackData>& user_data) {
694 filter_h filter = NULL;
695 ret = media_filter_create(&filter);
696 if (ret != MEDIA_CONTENT_ERROR_NONE) {
697 LoggerE("Failed: media_filter_create failed");
702 media_filter_destroy(filter);
705 std::string condition = "(FOLDER_STORAGE_TYPE = 0 OR FOLDER_STORAGE_TYPE = 1)";
706 media_filter_set_condition(filter, condition.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
708 picojson::array pico_dirs;
709 ret = media_folder_foreach_folder_from_db(filter, media_foreach_directory_cb, &pico_dirs);
710 if (ret != MEDIA_CONTENT_ERROR_NONE) {
711 PlatformResult err = LogAndCreateResult(
712 ErrorCode::UNKNOWN_ERR, "Getting the directories failed.",
713 ("Failed: Getting the directories failed %d (%s)", ret, get_error_message(ret)));
714 user_data->isSuccess = err;
718 user_data->result = picojson::value(pico_dirs);
721 void ContentManager::find(const std::shared_ptr<ReplyCallbackData>& user_data) {
728 picojson::value::array arrayContent;
729 filter_h filter = nullptr;
730 media_filter_create(&filter);
733 media_filter_destroy(filter);
737 if (!IsNull(user_data->args.get("filter"))) {
738 ContentFilter filterMechanism;
740 picojson::object argsObject = JsonCast<picojson::object>(user_data->args);
741 if (filterMechanism.BuildQuery(FromJson<picojson::object>(argsObject, "filter"), &query)) {
742 LoggerD("Filter query: %s", query.c_str());
743 ret = media_filter_set_condition(filter, query.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
744 if (MEDIA_CONTENT_ERROR_NONE != ret) {
745 LoggerE("Platform filter setting failed, error %d", ret);
750 if (user_data->args.contains("sortMode")) {
751 picojson::value vSortMode = user_data->args.get("sortMode");
753 if (vSortMode.is<picojson::object>()) {
754 std::string sortModeName, sortModeOrder;
756 ContentFilter::MapField(vSortMode.get("attributeName").to_str(), &sortModeName);
758 sortModeOrder = vSortMode.get("order").to_str();
759 if (!sortModeOrder.empty()) {
760 media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
762 if (sortModeOrder == "ASC") {
763 order = MEDIA_CONTENT_ORDER_ASC;
764 } else if (sortModeOrder == "DESC") {
765 order = MEDIA_CONTENT_ORDER_DESC;
768 ret = media_filter_set_order(filter, order, sortModeName.c_str(),
769 MEDIA_CONTENT_COLLATE_DEFAULT);
770 if (MEDIA_CONTENT_ERROR_NONE != ret) {
771 LoggerE("Platform SortMode setting failed, error: %d", ret);
777 if (!IsNull(user_data->args.get("count"))) {
778 count = static_cast<int>(user_data->args.get("count").get<double>());
782 if (!IsNull(user_data->args.get("offset"))) {
783 offset = static_cast<int>(user_data->args.get("offset").get<double>());
787 ret = media_filter_set_offset(filter, offset, count);
788 if (MEDIA_CONTENT_ERROR_NONE != ret) {
789 LoggerE("A platform error occurs in media_filter_set_offset: %d", ret);
791 if (!IsNull(user_data->args.get("directoryId"))) {
792 dirId = user_data->args.get("directoryId").get<std::string>();
793 ret = media_folder_foreach_media_from_db(dirId.c_str(), filter, media_foreach_content_cb,
794 static_cast<void*>(&arrayContent));
796 ret = media_info_foreach_media_from_db(filter, media_foreach_content_cb,
797 static_cast<void*>(&arrayContent));
800 if (ret == MEDIA_CONTENT_ERROR_NONE) {
801 user_data->result = picojson::value(arrayContent);
803 PlatformResult err = LogAndCreateResult(
804 ErrorCode::UNKNOWN_ERR, "The iteration failed in platform",
805 ("The iteration failed in platform: %d (%s)", ret, get_error_message(ret)));
806 user_data->isSuccess = err;
810 int ContentManager::scanFile(std::string& uri) {
812 return media_content_scan_file(uri.c_str());
815 PlatformResult ContentManager::scanDirectory(media_scan_completed_cb callback,
816 ReplyCallbackData* cbData) {
818 const std::string& contentDirURI = cbData->args.get("contentDirURI").get<std::string>();
819 std::string real_path = common::FilesystemProvider::Create().GetRealPath(contentDirURI);
820 const bool recursive = cbData->args.get("recursive").get<bool>();
822 int ret = media_content_scan_folder(real_path.c_str(), recursive, callback, (void*)cbData);
824 if (ret != MEDIA_CONTENT_ERROR_NONE) {
825 if (MEDIA_CONTENT_ERROR_INVALID_PARAMETER == ret) {
826 return LogAndCreateResult(
827 ErrorCode::INVALID_VALUES_ERR, "Scanning content directory failed",
828 ("Scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
831 return LogAndCreateResult(
832 ErrorCode::UNKNOWN_ERR, "Scanning content directory failed",
833 ("Scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
836 return PlatformResult(ErrorCode::NO_ERROR);
839 PlatformResult ContentManager::cancelScanDirectory(const std::string& content_dir_uri) {
842 int ret = media_content_cancel_scan_folder(content_dir_uri.c_str());
843 if (ret != MEDIA_CONTENT_ERROR_NONE) {
844 return LogAndCreateResult(
845 ErrorCode::UNKNOWN_ERR, "Cancel scan content directory failed",
846 ("Cancel scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
848 return PlatformResult(ErrorCode::NO_ERROR);
851 PlatformResult ContentManager::addChangeListener(media_content_noti_h* noti_handle,
852 media_content_db_update_cb callback,
856 int ret = media_content_add_db_updated_cb(callback, user_data, noti_handle);
858 if (MEDIA_CONTENT_ERROR_NONE != ret) {
859 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to add the listener.",
860 ("Failed to add the listener: %d (%s)", ret, get_error_message(ret)));
863 return PlatformResult(ErrorCode::NO_ERROR);
866 PlatformResult ContentManager::removeChangeListener(media_content_noti_h noti_handle) {
869 int ret = media_content_remove_db_updated_cb(noti_handle);
872 case MEDIA_CONTENT_ERROR_NONE:
873 return PlatformResult(ErrorCode::NO_ERROR);
874 case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
875 // Trying to remove non-existent listener, ignoring
876 LoggerI("Failed to remove the listener: %d (%s)", ret, get_error_message(ret));
877 return PlatformResult(ErrorCode::NO_ERROR);
879 return LogAndCreateResult(
880 ErrorCode::ABORT_ERR, "Failed to remove the listener.",
881 ("Failed to remove the listener: %d (%s)", ret, get_error_message(ret)));
885 void ContentManager::createPlaylist(std::string name,
886 const std::shared_ptr<ReplyCallbackData>& user_data) {
888 media_playlist_h playlist = NULL;
890 int ret = media_playlist_insert_to_db(name.c_str(), &playlist);
891 std::unique_ptr<std::remove_pointer<media_playlist_h>::type, int (*)(media_playlist_h)>
892 playlist_ptr(playlist, &media_playlist_destroy); // automatically release the memory
893 if (ret != MEDIA_CONTENT_ERROR_NONE) {
894 // MEDIA_CONTENT_ERROR_DB_FAILED means that playlist probably already exists
895 PlatformResult err = LogAndCreateResult(
896 MEDIA_CONTENT_ERROR_DB_FAILED == ret ? ErrorCode::INVALID_VALUES_ERR
897 : ErrorCode::UNKNOWN_ERR,
898 "Creation of playlist has failed.",
899 ("Failed: creation of playlist is failed: %d (%s)", ret, get_error_message(ret)));
900 user_data->isSuccess = err;
903 picojson::value::object o;
905 if (playlist != NULL) {
907 char* thumb_path = NULL;
908 char* name_playlist = NULL;
909 filter_h filter = NULL;
910 if (media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
911 o["id"] = picojson::value(std::to_string(id));
914 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "loading of playlist is failed.");
915 user_data->isSuccess = err;
918 if (media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
919 if (thumb_path != NULL) {
920 o["thumbnailURI"] = picojson::value(std::string(thumb_path));
923 o["thumbnailURI"] = picojson::value();
926 LoggerE("Invalid thumbnail path for playlist.");
928 if (media_playlist_get_name(playlist, &name_playlist) == MEDIA_CONTENT_ERROR_NONE) {
929 o["name"] = picojson::value(std::string(name_playlist));
932 LoggerE("Invalid name for playlist.");
934 media_filter_create(&filter);
935 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
936 filter, &media_filter_destroy); // automatically release the memory
938 if (media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
939 o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
941 LoggerE("Invalid count for playlist.");
945 user_data->result = picojson::value(o);
948 void ContentManager::getPlaylists(const std::shared_ptr<ReplyCallbackData>& user_data) {
951 filter_h filter = nullptr;
952 media_filter_create(&filter);
953 std::unique_ptr<std::remove_pointer<filter_h>::type, int (*)(filter_h)> filter_ptr(
954 filter, &media_filter_destroy); // automatically release the memory
955 picojson::value::array playlists;
957 ret = media_playlist_foreach_playlist_from_db(filter, playlist_foreach_cb,
958 static_cast<void*>(&playlists));
960 if (ret != MEDIA_CONTENT_ERROR_NONE) {
961 PlatformResult err = LogAndCreateResult(
962 ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
963 ("Failed: Getting playlist is failed %d (%s)", ret, get_error_message(ret)));
964 user_data->isSuccess = err;
967 user_data->result = picojson::value(playlists);
970 void ContentManager::removePlaylist(std::string playlistId,
971 const std::shared_ptr<ReplyCallbackData>& user_data) {
973 int id = std::atoi(playlistId.c_str());
975 PlatformResult err = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "PlaylistId is wrong.");
976 user_data->isSuccess = err;
980 int ret = media_playlist_delete_from_db(id);
981 if (ret != MEDIA_CONTENT_ERROR_NONE) {
983 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Removal of playlist is failed.");
984 user_data->isSuccess = err;
988 int ContentManager::update(const picojson::value& args) {
992 picojson::value content = args.get("content");
993 std::string id = content.get("id").to_str();
995 media_info_h media = NULL;
996 ret = media_info_get_media_from_db(id.c_str(), &media);
997 if (ret == MEDIA_CONTENT_ERROR_NONE) {
998 setContent(media, content);
999 ret = media_info_update_to_db(media);
1000 media_info_destroy(media);
1006 int ContentManager::updateBatch(const picojson::value& args) {
1009 std::vector<picojson::value> contents = args.get("contents").get<picojson::array>();
1011 for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
1012 picojson::value content = *it;
1013 std::string id = content.get("id").to_str();
1014 media_info_h media = NULL;
1015 ret = media_info_get_media_from_db(id.c_str(), &media);
1016 if (media != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1017 ret = setContent(media, content);
1018 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1019 LoggerE("setContent failed");
1023 ret = media_info_update_to_db(media);
1024 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1025 LoggerE("update to db failed");
1027 media_info_destroy(media);
1035 int ContentManager::playlistAdd(std::string playlist_id, std::string content_id) {
1038 media_playlist_h playlist = NULL;
1039 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1041 if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1042 ret = media_playlist_add_media(playlist, content_id.c_str());
1043 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1044 LoggerE("The content(id:%s) can't add to playlist", content_id.c_str());
1047 ret = media_playlist_update_to_db(playlist);
1048 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1049 LoggerE("The content(id:%s) can't add to playlist", content_id.c_str());
1052 LoggerE("Playlist(id:%s) is not exist", playlist_id.c_str());
1055 media_playlist_destroy(playlist);
1059 int ContentManager::playlistRemove(std::string playlist_id, int member_id) {
1062 media_playlist_h playlist = NULL;
1063 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1064 if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1065 ret = media_playlist_remove_media(playlist, member_id);
1066 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1067 LoggerE("The content can't remove to playlist");
1070 ret = media_playlist_update_to_db(playlist);
1071 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1072 LoggerE("The content can't remove to playlist");
1075 LoggerE("Playlist(id:%s) is not exist", playlist_id.c_str());
1077 media_playlist_destroy(playlist);
1082 void ContentManager::playlistAddbatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
1084 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1086 media_playlist_h playlist = NULL;
1087 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1089 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1090 PlatformResult err =
1091 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1092 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1093 user_data->isSuccess = err;
1097 std::vector<picojson::value> contents = user_data->args.get("contents").get<picojson::array>();
1098 for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
1099 picojson::value content = *it;
1100 std::string id = content.get("id").to_str();
1101 ret = media_playlist_add_media(playlist, id.c_str());
1102 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1103 LoggerE("Adding Content(id:%s) is failed.", id.c_str());
1107 ret = media_playlist_update_to_db(playlist);
1108 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1109 PlatformResult err =
1110 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Adding playlist is failed.",
1111 ("Adding playlist is failed: %d (%s)", ret, get_error_message(ret)));
1112 user_data->isSuccess = err;
1114 media_playlist_destroy(playlist);
1117 void ContentManager::playlistGet(const std::shared_ptr<ReplyCallbackData>& user_data) {
1119 media_playlist_h playlist = NULL;
1120 media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
1121 const std::string playOrder("play_order");
1125 media_playlist_destroy(playlist);
1129 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1130 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1131 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1132 PlatformResult err =
1133 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1134 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1135 user_data->isSuccess = err;
1139 filter_h filter = NULL;
1140 ret = media_filter_create(&filter);
1141 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1142 PlatformResult err =
1143 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.",
1144 ("Creating a filter is failed: %d (%s)", ret, get_error_message(ret)));
1145 user_data->isSuccess = err;
1149 int count = user_data->args.get("count").get<double>();
1150 int offset = user_data->args.get("offset").get<double>();
1151 ret = media_filter_set_offset(filter, offset, count);
1152 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1153 LoggerD("Setting a offset/count is failed.");
1155 ret = media_filter_set_order(filter, order, playOrder.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
1156 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1157 LoggerD("Setting a offset/count is failed.");
1160 picojson::value::array arrayContent;
1161 ret = media_playlist_foreach_media_from_db(std::stoi(playlist_id), filter,
1162 playlist_content_member_cb,
1163 static_cast<void*>(&arrayContent));
1165 media_filter_destroy(filter);
1166 if (ret == MEDIA_CONTENT_ERROR_NONE) {
1167 user_data->result = picojson::value(arrayContent);
1169 PlatformResult err =
1170 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.",
1171 ("Creating a filter is failed: %d (%s)", ret, get_error_message(ret)));
1172 user_data->isSuccess = err;
1176 void ContentManager::playlistRemovebatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
1178 media_playlist_h playlist = NULL;
1182 media_playlist_destroy(playlist);
1186 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1187 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1188 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1189 PlatformResult err =
1190 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1191 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1192 user_data->isSuccess = err;
1196 std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
1197 std::size_t members_size = members.size();
1198 for (std::size_t i = 0; i < members_size; ++i) {
1199 int member_id = static_cast<int>(members.at(i).get<double>());
1200 ret = media_playlist_remove_media(playlist, member_id);
1202 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1203 LoggerD("Removing a content is failed.");
1207 ret = media_playlist_update_to_db(playlist);
1208 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1209 PlatformResult err = LogAndCreateResult(
1210 ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.",
1211 ("Removing the contents is failed: %d (%s)", ret, get_error_message(ret)));
1212 user_data->isSuccess = err;
1216 void ContentManager::playlistSetOrder(const std::shared_ptr<ReplyCallbackData>& user_data) {
1218 media_playlist_h playlist = NULL;
1222 media_playlist_destroy(playlist);
1226 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1227 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1228 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1229 PlatformResult err =
1230 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1231 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1232 user_data->isSuccess = err;
1237 std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
1239 ret = media_playlist_get_media_count_from_db(std::stoi(playlist_id), NULL, &cnt);
1240 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1241 LoggerE("Failed: media_playlist_get_media_count_from_db");
1242 PlatformResult err = convertError(ret);
1243 user_data->isSuccess = err;
1246 std::size_t members_size = members.size();
1247 if (cnt < 0 || static_cast<size_t>(cnt) != members_size) {
1248 PlatformResult err = LogAndCreateResult(
1249 ErrorCode::INVALID_VALUES_ERR,
1250 "The items array does not contain all items from the playlist.",
1251 ("Failed: The items array does not contain all items from the playlist: %d (%s)", ret,
1252 get_error_message(ret)));
1253 user_data->isSuccess = err;
1257 for (std::size_t i = 0; i < members_size; ++i) {
1258 int member_id = static_cast<int>(members.at(i).get<double>());
1259 ret = media_playlist_set_play_order(playlist, member_id, i);
1260 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1261 LoggerD("Removing a content is failed.");
1265 ret = media_playlist_update_to_db(playlist);
1266 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1267 PlatformResult err = LogAndCreateResult(
1268 ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.",
1269 ("Removing the contents is failed: %d (%s)", ret, get_error_message(ret)));
1270 user_data->isSuccess = err;
1274 void ContentManager::playlistMove(const std::shared_ptr<ReplyCallbackData>& user_data) {
1276 media_playlist_h playlist = NULL;
1280 media_playlist_destroy(playlist);
1284 std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1285 int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1286 if (ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1287 PlatformResult err =
1288 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1289 ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1290 user_data->isSuccess = err;
1294 double member_id = user_data->args.get("memberId").get<double>();
1295 double delta = user_data->args.get("delta").get<double>();
1296 ret = media_playlist_get_play_order(playlist, static_cast<int>(member_id), &old_order);
1297 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1298 PlatformResult err = LogAndCreateResult(
1299 ErrorCode::UNKNOWN_ERR, "The content can't find form playlist.",
1300 ("The content can't find form playlist: %d (%s)", ret, get_error_message(ret)));
1301 user_data->isSuccess = err;
1304 int new_order = static_cast<int>(old_order) + static_cast<int>(delta);
1305 ret = media_playlist_set_play_order(playlist, static_cast<int>(member_id), new_order);
1306 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1307 PlatformResult err = LogAndCreateResult(
1308 ErrorCode::UNKNOWN_ERR, "The content can't update play_order.",
1309 ("The content can't update play_order: %d (%s)", ret, get_error_message(ret)));
1310 user_data->isSuccess = err;
1313 ret = media_playlist_update_to_db(playlist);
1314 if (ret != MEDIA_CONTENT_ERROR_NONE) {
1315 PlatformResult err = LogAndCreateResult(
1316 ErrorCode::UNKNOWN_ERR, "Updateing play_order is failed.",
1317 ("Updateing play_order is failed: %d (%s)", ret, get_error_message(ret)));
1318 user_data->isSuccess = err;
1322 int ContentManager::getLyrics(const picojson::value& args, picojson::object& result) {
1325 int ret = METADATA_EXTRACTOR_ERROR_NONE;
1326 const std::string& contentURI = args.get("contentURI").to_str();
1327 if (contentURI.empty()) {
1328 LoggerE("contentURI empty - skipping media extractor");
1332 metadata_extractor_h extractor;
1333 ret = metadata_extractor_create(&extractor);
1334 if (METADATA_EXTRACTOR_ERROR_NONE != ret) {
1335 LoggerE("metadata_extractor_create failed, error: %d", ret);
1337 std::unique_ptr<std::remove_pointer<metadata_extractor_h>::type, int (*)(metadata_extractor_h)>
1338 extractor_ptr(extractor, &metadata_extractor_destroy); // automatically release the memory
1340 ret = metadata_extractor_set_path(extractor, contentURI.c_str());
1341 if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
1342 LoggerE("metadata_extractor_set_path failed, error: %d", ret);
1345 picojson::array timestamps;
1346 picojson::array texts = picojson::array();
1347 char* strSyncTextNum = NULL;
1349 ret = metadata_extractor_get_metadata(extractor, METADATA_SYNCLYRICS_NUM, &strSyncTextNum);
1350 if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
1351 LoggerE("Media extractor error %d", ret);
1355 int nSyncTextNum = 0;
1356 if (strSyncTextNum) {
1357 nSyncTextNum = atoi(strSyncTextNum);
1358 free(strSyncTextNum);
1359 strSyncTextNum = NULL;
1361 if (nSyncTextNum > 0) {
1362 result["type"] = picojson::value(std::string("SYNCHRONIZED"));
1363 for (int i = 0; i < nSyncTextNum; i++) {
1364 unsigned long time_info = 0;
1365 char* lyrics = NULL;
1366 ret = metadata_extractor_get_synclyrics(extractor, i, &time_info, &lyrics);
1367 if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
1368 timestamps.push_back(picojson::value(static_cast<double>(time_info)));
1369 texts.push_back(picojson::value(std::string(lyrics)));
1373 result["texts"] = picojson::value(texts);
1374 result["timestamps"] = picojson::value(timestamps);
1375 ret = METADATA_EXTRACTOR_ERROR_NONE;
1377 char* unSyncText = nullptr;
1378 ret = metadata_extractor_get_metadata(extractor, METADATA_UNSYNCLYRICS, &unSyncText);
1379 if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
1380 result["type"] = picojson::value(std::string("UNSYNCHRONIZED"));
1381 if (nullptr == unSyncText) {
1382 LoggerE("Unsynchronized lyrics text is NULL");
1384 texts.push_back(picojson::value(unSyncText ? unSyncText : ""));
1385 result["texts"] = picojson::value(texts);
1393 media_playlist_h getPlaylistHandle(int id) {
1395 media_playlist_h playlist_handle = nullptr;
1396 int ret_code = media_playlist_get_playlist_from_db(id, &playlist_handle);
1397 if (MEDIA_CONTENT_ERROR_NONE != ret_code || playlist_handle == nullptr) {
1398 LoggerE("could not get playlist handle for id: %d", id);
1402 return playlist_handle;
1405 void destroyMediaPlaylistHandle(media_playlist_h& playlist_handle) {
1407 if (playlist_handle) {
1408 int ret_code = media_playlist_destroy(playlist_handle);
1409 playlist_handle = nullptr;
1411 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1412 LoggerE("media_playlist_destroy failed");
1417 int ContentManager::getPlaylistName(int id, std::string* result) {
1419 media_playlist_h playlist_handle = getPlaylistHandle(id);
1420 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1422 char* tmp_playlist_name = nullptr;
1423 const int ret_code = media_playlist_get_name(playlist_handle, &tmp_playlist_name);
1425 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1426 LoggerE("media_playlist_get_name failed");
1427 return TIZEN_ERROR_UNKNOWN;
1430 std::string playlist_name;
1431 if (tmp_playlist_name) {
1432 playlist_name = tmp_playlist_name;
1433 free(tmp_playlist_name);
1434 tmp_playlist_name = nullptr;
1437 *result = playlist_name;
1438 return MEDIA_CONTENT_ERROR_NONE;
1441 int updatePlaylistInDB(media_playlist_h playlist_handle) {
1443 int ret_code = media_playlist_update_to_db(playlist_handle);
1444 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1445 LoggerE("media_playlist_update_to_db failed");
1448 return MEDIA_CONTENT_ERROR_NONE;
1451 int ContentManager::setPlaylistName(int id, const std::string& name) {
1454 LoggerE("Cannot set empty playlist name!");
1455 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1458 media_playlist_h playlist_handle = getPlaylistHandle(id);
1459 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1461 const int ret_code = media_playlist_set_name(playlist_handle, name.c_str());
1462 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1463 LoggerE("media_playlist_set_name failed");
1464 // Setting name that is used by other playlist does not return bad error code here.
1465 // MEDIA_CONTENT_ERROR_INVALID_OPERATION is being returned in updatePlaylistInDB
1466 return TIZEN_ERROR_UNKNOWN;
1469 int ret = updatePlaylistInDB(playlist_handle);
1470 if (MEDIA_CONTENT_ERROR_NONE != ret) {
1471 LoggerE("Error while updating playlist: %d", ret);
1472 if (MEDIA_CONTENT_ERROR_DB_FAILED == ret) {
1473 // We could fetch list of playlists and check if other playlist is using this
1474 // name, but that seems to be to much work in synchronous method
1475 LoggerE("Playlist name: %s is probably already used", name.c_str());
1476 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1480 return MEDIA_CONTENT_ERROR_NONE;
1483 int ContentManager::getThumbnailUri(int id, std::string* result) {
1485 media_playlist_h playlist_handle = getPlaylistHandle(id);
1486 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1488 char* tmp_playlist_thb_path = nullptr;
1489 const int ret_code = media_playlist_get_thumbnail_path(playlist_handle, &tmp_playlist_thb_path);
1491 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1492 LoggerE("media_playlist_get_name failed");
1493 return TIZEN_ERROR_UNKNOWN;
1496 std::string playlist_thb_path;
1497 if (tmp_playlist_thb_path) {
1498 playlist_thb_path = tmp_playlist_thb_path;
1499 free(tmp_playlist_thb_path);
1500 tmp_playlist_thb_path = nullptr;
1503 if (playlist_thb_path != " ") {
1504 playlist_thb_path = uri_prefix + playlist_thb_path;
1507 *result = playlist_thb_path;
1508 return MEDIA_CONTENT_ERROR_NONE;
1511 int ContentManager::setThumbnailUri(int id, const std::string& thb_uri) {
1514 // Allow setting empty URI, unfortunately Core API does not allow to set empty
1515 // path so we need to set one empty space. This is probably issue of Core API.
1516 if (!thb_uri.empty() && " " != thb_uri) {
1517 if (thb_uri.find(uri_absolute_prefix) != 0) {
1518 LoggerE("thumbnail URI is not valid: [%s]", thb_uri.c_str());
1519 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1523 media_playlist_h playlist_handle = getPlaylistHandle(id);
1524 PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1526 std::string real_path = common::FilesystemProvider::Create().GetRealPath(thb_uri);
1527 const int ret_code = media_playlist_set_thumbnail_path(playlist_handle, real_path.c_str());
1528 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1529 LoggerE("media_playlist_set_thumbnail_path failed");
1530 return TIZEN_ERROR_UNKNOWN;
1533 int ret = updatePlaylistInDB(playlist_handle);
1537 int ContentManager::getNumberOfTracks(int id, int* result) {
1541 const int ret_code = media_playlist_get_media_count_from_db(id, nullptr, &count);
1543 if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1544 LoggerE("media_playlist_get_media_count_from_db failed");
1545 return TIZEN_ERROR_UNKNOWN;
1549 return MEDIA_CONTENT_ERROR_NONE;
1552 common::PlatformResult ContentManager::createThumbnail(const std::string& id,
1553 picojson::object* obj) {
1556 media_info_h media_h = nullptr;
1557 int ret = media_info_get_media_from_db(id.c_str(), &media_h);
1558 if (MEDIA_CONTENT_ERROR_NONE != ret || nullptr == media_h) {
1559 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Getting media failed.",
1560 ("Getting media failed: %d (%s)", ret, get_error_message(ret)));
1563 media_info_destroy(media_h);
1566 ret = media_info_generate_thumbnail(media_h);
1567 if (MEDIA_CONTENT_ERROR_NONE != ret) {
1568 return LogAndCreateResult(ErrorCode::ABORT_ERR, "Creating thumbnail failed.",
1569 ("Creating thumbnail failed: %d (%s)", ret, get_error_message(ret)));
1572 char* path = nullptr;
1573 ret = media_info_get_thumbnail_path(media_h, &path);
1574 if (MEDIA_CONTENT_ERROR_NONE != ret) {
1575 return LogAndCreateResult(
1576 ErrorCode::ABORT_ERR, "Creating thumbnail succeeded, but failed to get thumbnail path.",
1577 ("Getting thumbnail path failed: %d (%s)", ret, get_error_message(ret)));
1579 obj->emplace("result", picojson::value(path));
1580 std::unique_ptr<char[], decltype(&free)>(path, free);
1581 return PlatformResult(ErrorCode::NO_ERROR);
1584 PlatformResult ContentManager::convertError(int err) {
1585 char* error_msg = get_error_message(err);
1587 case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
1588 return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, error_msg);
1589 case MEDIA_CONTENT_ERROR_OUT_OF_MEMORY:
1590 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1591 case MEDIA_CONTENT_ERROR_INVALID_OPERATION:
1592 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1593 case MEDIA_CONTENT_FILE_NO_SPACE_ON_DEVICE:
1594 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1595 case MEDIA_CONTENT_ERROR_PERMISSION_DENIED:
1596 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1597 case MEDIA_CONTENT_ERROR_DB_FAILED:
1598 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1599 case MEDIA_CONTENT_ERROR_DB_BUSY:
1600 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1601 case MEDIA_CONTENT_ERROR_NETWORK:
1602 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1603 case MEDIA_CONTENT_ERROR_UNSUPPORTED_CONTENT:
1604 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1606 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
1610 } // namespace content
1611 } // namespace extension