Merge "Revert "[SystemInfo] Replace deprecated native wifi API with wifi-manager...
[platform/core/api/webapi-plugins.git] / src / content / content_manager.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16  
17 #include "content/content_manager.h"
18
19 #include <algorithm>
20 #include <cstring>
21 #include <map>
22 #include <metadata_extractor.h>
23 #include <sstream>
24 #include <string>
25 #include <unistd.h>
26 #include <stdlib.h>
27
28 #include "common/converter.h"
29 #include "common/logger.h"
30 #include "common/scope_exit.h"
31 #include "common/tools.h"
32 #include "common/filesystem/filesystem_provider.h"
33
34 #include "content/content_filter.h"
35
36 using namespace std;
37 using namespace common;
38
39 using common::tools::ReportSuccess;
40 using common::tools::ReportError;
41
42 namespace extension {
43 namespace content {
44
45 namespace {
46 static const std::string uri_prefix = "file://";
47 static const std::string uri_absolute_prefix = "file:///";
48 }
49
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},
59 };
60
61 std::string get_date(char* tmpStr) {
62   LoggerD("Enter");
63   if (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) {
67         free(result);
68         return std::string();
69       } else {
70         time_t t = mktime(result);// + get_utc_offset() * 3600;
71         std::stringstream str_date;
72         str_date << t;
73         free(result);
74         return str_date.str();
75       }
76     }
77   }
78   return std::string();
79 }
80
81 void ContentToJson(media_info_h info, picojson::object& o) {
82   LoggerD("Enter");
83   int ret;
84   int tmpInt = 0;
85   bool tmpBool = false;
86   char* tmpStr = NULL;
87   time_t tmpDate;
88   double tmpDouble;
89   long long unsigned int tmpLong;
90   media_content_type_e type;
91
92   ret = media_info_get_media_type(info, &type);
93
94   if (ret != MEDIA_CONTENT_ERROR_NONE) {
95     LOGGER(ERROR) << "Get media type failed: " << ret;
96     type = MEDIA_CONTENT_TYPE_OTHERS;
97   }
98
99   if (type == MEDIA_CONTENT_TYPE_IMAGE) {
100     o["type"] = picojson::value(std::string("IMAGE"));
101     image_meta_h img;
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)>
104           img_ptr(img, &image_meta_destroy); // automatically release the memory
105       if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_date_taken(img, &tmpStr)) {
106         if (tmpStr) {
107           o["releaseDate"] = picojson::value(get_date(tmpStr));
108           free(tmpStr);
109           tmpStr = NULL;
110         }
111       }
112       if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_width(img, &tmpInt)) {
113         o["width"] = picojson::value(static_cast<double>(tmpInt));
114       }
115       if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_height(img, &tmpInt)) {
116         o["height"] = picojson::value(static_cast<double>(tmpInt));
117       }
118       picojson::object geo;
119       if (MEDIA_CONTENT_ERROR_NONE == media_info_get_latitude(info, &tmpDouble)) {
120         geo["latitude"] = picojson::value(tmpDouble);
121       }
122       if (MEDIA_CONTENT_ERROR_NONE == media_info_get_longitude(info, &tmpDouble)) {
123         geo["longitude"] = picojson::value(tmpDouble);
124       }
125       o["geolocation"] = picojson::value(geo);
126       std::string ori;
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:
132             ori = "NORMAL";
133             break;
134           case MEDIA_CONTENT_ORIENTATION_HFLIP:
135             ori = "FLIP_HORIZONTAL";
136             break;
137           case MEDIA_CONTENT_ORIENTATION_ROT_180:
138             ori = "ROTATE_180";
139             break;
140           case MEDIA_CONTENT_ORIENTATION_VFLIP:
141             ori = "FLIP_VERTICAL";
142             break;
143           case MEDIA_CONTENT_ORIENTATION_TRANSPOSE:
144             ori = "TRANSPOSE";
145             break;
146           case MEDIA_CONTENT_ORIENTATION_ROT_90:
147             ori = "ROTATE_90";
148             break;
149           case MEDIA_CONTENT_ORIENTATION_TRANSVERSE:
150             ori = "TRANSVERSE";
151             break;
152           case MEDIA_CONTENT_ORIENTATION_ROT_270:
153             ori = "ROTATE_270";
154             break;
155         }
156         o["orientation"] = picojson::value(ori);
157       }
158     }
159   } else if (type == MEDIA_CONTENT_TYPE_VIDEO) {
160     o["type"] = picojson::value(std::string("VIDEO"));
161     video_meta_h 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)>
164           video_ptr(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));
167       }
168
169       if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_height(video, &tmpInt)) {
170         o["height"] = picojson::value(static_cast<double>(tmpInt));
171       }
172       if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_artist(video, &tmpStr)) {
173         picojson::array artists;
174         if (tmpStr) {
175           artists.push_back(picojson::value(std::string(tmpStr)));
176           free(tmpStr);
177           tmpStr = NULL;
178         }
179         o["artists"] = picojson::value(artists);
180       }
181       if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_album(video, &tmpStr)) {
182         if (tmpStr) {
183           o["album"] = picojson::value(tmpStr);
184           free(tmpStr);
185           tmpStr = NULL;
186         }
187       }
188       if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_duration(video, &tmpInt)) {
189         o["duration"] = picojson::value(static_cast<double>(tmpInt));
190       }
191       if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_recorded_date(video, &tmpStr)) {
192         if (tmpStr) {
193           o["releaseDate"] = picojson::value(get_date(tmpStr));
194           free(tmpStr);
195           tmpStr = NULL;
196         }
197       }
198     }
199     picojson::object geo;
200     if (MEDIA_CONTENT_ERROR_NONE == media_info_get_latitude(info, &tmpDouble)) {
201       geo["latitude"] = picojson::value(tmpDouble);
202     }
203     if (MEDIA_CONTENT_ERROR_NONE == media_info_get_longitude(info, &tmpDouble)) {
204       geo["longitude"] = picojson::value(tmpDouble);
205     }
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"));
209     audio_meta_h 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)>
212           audio_ptr(audio, &audio_meta_destroy); // automatically release the memory
213       if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_recorded_date(audio, &tmpStr)) {
214         if(tmpStr) {
215           o["releaseDate"] = picojson::value(get_date(tmpStr));
216           free(tmpStr);
217           tmpStr = NULL;
218         }
219       }
220       if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_album(audio, &tmpStr)) {
221         if (tmpStr) {
222           o["album"] = picojson::value(std::string(tmpStr));
223           free(tmpStr);
224           tmpStr = NULL;
225         }
226       }
227       if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_artist(audio, &tmpStr)) {
228         if (tmpStr) {
229           picojson::array artists;
230           artists.push_back(picojson::value(std::string(tmpStr)));
231           o["artists"] = picojson::value(artists);
232           free(tmpStr);
233           tmpStr = NULL;
234         }
235       }
236       if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_genre(audio, &tmpStr)) {
237         if (tmpStr) {
238           picojson::array genres;
239           genres.push_back(picojson::value(std::string(tmpStr)));
240           o["genres"] = picojson::value(genres);
241           free(tmpStr);
242           tmpStr = NULL;
243         }
244       }
245       if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_composer(audio, &tmpStr)) {
246         if (tmpStr) {
247           picojson::array composers;
248           composers.push_back(picojson::value(std::string(tmpStr)));
249           o["composers"] = picojson::value(composers);
250           free(tmpStr);
251           tmpStr = NULL;
252         }
253       }
254       if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_copyright(audio, &tmpStr)) {
255         if (tmpStr) {
256           o["copyright"] = picojson::value(std::string(tmpStr));
257           free(tmpStr);
258           tmpStr = NULL;
259         }
260       }
261       if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_bit_rate(audio, &tmpInt)) {
262         o["bitrate"] = picojson::value(static_cast<double>(tmpInt));
263       }
264       if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_track_num(audio, &tmpStr)) {
265         if (tmpStr) {
266           o["trackNumber"] = picojson::value(static_cast<double>(std::atoi(tmpStr)));
267           free(tmpStr);
268           tmpStr = NULL;
269         }
270         else {
271           o["trackNumber"] = picojson::value();
272         }
273       }
274       if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_duration(audio, &tmpInt)) {
275         o["duration"] = picojson::value(static_cast<double>(tmpInt));
276       }
277     }
278   } else {
279     o["type"] = picojson::value(std::string("OTHER"));
280   }
281
282   ret = media_info_get_media_id(info, &tmpStr);
283   if(ret == MEDIA_CONTENT_ERROR_NONE) {
284     if(tmpStr) {
285       o["id"] = picojson::value(std::string(tmpStr));
286       free(tmpStr);
287       tmpStr = NULL;
288     }
289   }
290   ret = media_info_get_display_name(info, &tmpStr);
291   if(ret == MEDIA_CONTENT_ERROR_NONE) {
292     if(tmpStr) {
293       o["name"] = picojson::value(std::string(tmpStr));
294       free(tmpStr);
295       tmpStr = NULL;
296     }
297   }
298
299   ret = media_info_get_mime_type(info, &tmpStr);
300   if(ret == MEDIA_CONTENT_ERROR_NONE) {
301     if(tmpStr) {
302       o["mimeType"] = picojson::value(std::string(tmpStr));
303       free(tmpStr);
304       tmpStr = NULL;
305     }
306   }
307   ret = media_info_get_title(info, &tmpStr);
308   if(ret == MEDIA_CONTENT_ERROR_NONE) {
309     if(tmpStr) {
310       o["title"] = picojson::value(std::string(tmpStr));
311       free(tmpStr);
312       tmpStr = NULL;
313     }
314   }
315   ret = media_info_get_file_path(info, &tmpStr);
316   if(ret == MEDIA_CONTENT_ERROR_NONE) {
317     if(tmpStr) {
318       o["contentURI"] = picojson::value(std::string(tmpStr));
319       free(tmpStr);
320       tmpStr = NULL;
321     }
322   }
323   ret = media_info_get_thumbnail_path(info, &tmpStr);
324   if(ret == MEDIA_CONTENT_ERROR_NONE) {
325     if(tmpStr) {
326       picojson::array thumbnails;
327       thumbnails.push_back(picojson::value(std::string(tmpStr)));
328       o["thumbnailURIs"] = picojson::value(thumbnails);
329       free(tmpStr);
330       tmpStr = NULL;
331     }
332   }
333   ret = media_info_get_description(info, &tmpStr);
334   if(ret == MEDIA_CONTENT_ERROR_NONE) {
335     if(tmpStr) {
336       o["description"] = picojson::value(std::string(tmpStr));
337       free(tmpStr);
338       tmpStr = NULL;
339     }
340   }
341   ret = media_info_get_rating(info, &tmpInt);
342   if(ret == MEDIA_CONTENT_ERROR_NONE) {
343     o["rating"] = picojson::value(static_cast<double>(tmpInt));
344   }
345   ret = media_info_get_size(info, &tmpLong);
346   if(ret == MEDIA_CONTENT_ERROR_NONE) {
347     o["size"] = picojson::value(static_cast<double>(tmpLong));
348   }
349   ret = media_info_get_favorite(info, &tmpBool);
350   if(ret == MEDIA_CONTENT_ERROR_NONE) {
351     o["isFavorite"] = picojson::value(tmpBool);
352   }
353   ret = media_info_get_modified_time(info, &tmpDate);
354   if(ret == MEDIA_CONTENT_ERROR_NONE) {
355     o["modifiedDate"] = picojson::value(static_cast<double>(tmpDate));
356   }
357 }
358
359 void ContentDirToJson(media_folder_h folder, picojson::object& o) {
360   LoggerD("Enter");
361   int ret;
362   char* tmpStr = NULL;
363   media_content_storage_e storage_type;
364   time_t tmpDate;
365
366   // id
367   ret = media_folder_get_folder_id(folder, &tmpStr);
368   if(ret == MEDIA_CONTENT_ERROR_NONE) {
369     if(tmpStr) {
370       o["id"] = picojson::value(std::string(tmpStr));
371       free(tmpStr);
372       tmpStr = NULL;
373     }
374   }
375
376   // directoryURI
377   ret = media_folder_get_path(folder, &tmpStr);
378   if(ret == MEDIA_CONTENT_ERROR_NONE) {
379     if(tmpStr) {
380       o["directoryURI"] = picojson::value(std::string(tmpStr));
381       free(tmpStr);
382       tmpStr = NULL;
383     }
384   }
385
386   // title
387   ret = media_folder_get_name(folder, &tmpStr);
388   if(ret == MEDIA_CONTENT_ERROR_NONE) {
389     if(tmpStr) {
390       o["title"] = picojson::value(std::string(tmpStr));
391       free(tmpStr);
392       tmpStr = NULL;
393     }
394   }
395
396   // storageType
397   ret = media_folder_get_storage_type(folder, &storage_type);
398   if(ret == MEDIA_CONTENT_ERROR_NONE) {
399     if (storage_type == MEDIA_CONTENT_STORAGE_INTERNAL) {
400       o["storageType"] = picojson::value(std::string("INTERNAL"));
401     } else if (storage_type == MEDIA_CONTENT_STORAGE_EXTERNAL) {
402       o["storageType"] = picojson::value(std::string("EXTERNAL"));
403     } else if (storage_type == MEDIA_CONTENT_STORAGE_CLOUD) {
404       o["storageType"] = picojson::value(std::string("CLOUD"));
405     }
406   }
407
408   // modifiedData
409   ret = media_folder_get_modified_time(folder, &tmpDate);
410   if(ret == MEDIA_CONTENT_ERROR_NONE) {
411     o["modifiedDate"] = picojson::value(static_cast<double>(tmpDate));
412   }
413 }
414
415 static int setContent(media_info_h media, const picojson::value& content) {
416   LoggerD("Enter");
417
418   int ret;
419   std::string name = content.get("name").to_str();
420   std::string description = content.get("description").to_str();
421   int rating = std::stoi(content.get("rating").to_str());
422   bool is_fav = content.get("isFavorite").get<bool>();
423
424   if (NULL == media) {
425     LoggerE("MEDIA_CONTENT_ERROR_DB_FAILED");
426     return MEDIA_CONTENT_ERROR_DB_FAILED;
427   }
428
429   media_content_type_e type;
430   ret = media_info_get_media_type(media, &type);
431   if (ret != MEDIA_CONTENT_ERROR_NONE) {
432     LoggerE("Failed: media_info_get_media_type()");
433     return ret;
434   }
435
436   ret = media_info_set_display_name(media, name.c_str());
437   if (ret != MEDIA_CONTENT_ERROR_NONE) {
438     LoggerE("Updating name failed.");
439   }
440
441   ret = media_info_set_description(media, description.c_str());
442   if (ret != MEDIA_CONTENT_ERROR_NONE) {
443     LoggerE("Updating description failed.");
444   }
445
446   ret = media_info_set_rating(media, rating);
447   if (ret != MEDIA_CONTENT_ERROR_NONE) {
448     LoggerE("Updating rating failed.");
449   }
450
451   ret = media_info_set_favorite(media, is_fav);
452   if (ret != MEDIA_CONTENT_ERROR_NONE) {
453     LoggerE("Updating isFavorite failed.");
454   }
455
456   if (ret != MEDIA_CONTENT_ERROR_NONE) {
457     LoggerE("Updating favorite failed.");
458   }
459
460   if (type == MEDIA_CONTENT_TYPE_IMAGE) {
461     std::string orientation = content.get("orientation").to_str();
462     auto orientationToSet = orientationMap.find(orientation);
463
464     if (orientationToSet != orientationMap.end()) {
465       image_meta_h img;
466       if (MEDIA_CONTENT_ERROR_NONE == media_info_get_image(media, &img) &&
467           MEDIA_CONTENT_ERROR_NONE == image_meta_set_orientation(img, orientationToSet->second) &&
468           MEDIA_CONTENT_ERROR_NONE == image_meta_update_to_db(img)) {
469         LoggerD("orientation update was successful");
470       } else {
471         LoggerE("orientation update failed");
472       }
473       image_meta_destroy(img);
474     }
475   }
476
477   if (type == MEDIA_CONTENT_TYPE_IMAGE || type == MEDIA_CONTENT_TYPE_VIDEO) {
478     picojson::value geo = content.get("geolocation");
479     if (geo.evaluate_as_boolean()) {
480       LoggerD("geolocation is not null");
481       double latitude = atof(geo.get("latitude").to_str().c_str());
482       double longitude = atof(geo.get("longitude").to_str().c_str());
483       ret = media_info_set_latitude(media, latitude);
484       if (ret != MEDIA_CONTENT_ERROR_NONE) {
485         LoggerE("Updating geolocation is failed.");
486       }
487       ret = media_info_set_longitude(media, longitude);
488       if (ret != MEDIA_CONTENT_ERROR_NONE) {
489         LoggerD("Updating geolocation is failed.");
490       }
491     } else {
492       LoggerD("geolocation is null");
493     }
494   }
495
496   return MEDIA_CONTENT_ERROR_NONE;
497 }
498
499 static void FolderToJson(media_folder_h folder, picojson::object* out) {
500   LoggerD("Enter");
501
502   char* name = NULL;
503   char* id = NULL;
504   char* path = NULL;
505   time_t date;
506   media_content_storage_e storageType;
507
508   int ret;
509
510   ret = media_folder_get_folder_id(folder, &id);
511   if(ret!=MEDIA_CONTENT_ERROR_NONE)
512   {
513     LogAndReportError(ContentManager::convertError(ret), out,
514                 ("Failed: media_folder_get_folder_id"));
515     return;
516   }
517
518   ret = media_folder_get_name(folder, &name);
519   if(ret!=MEDIA_CONTENT_ERROR_NONE)
520   {
521     LogAndReportError(ContentManager::convertError(ret), out,
522                       ("Failed: media_folder_get_name"));
523     free(id);
524     return;
525   }
526
527   ret = media_folder_get_path(folder, &path);
528   if(ret!=MEDIA_CONTENT_ERROR_NONE)
529   {
530     LogAndReportError(ContentManager::convertError(ret), out,
531                       ("Failed: media_folder_get_path"));
532     free(id);
533     free(name);
534     return;
535   }
536
537   ret = media_folder_get_modified_time(folder, &date);
538   if(ret!=MEDIA_CONTENT_ERROR_NONE)
539   {
540     LogAndReportError(ContentManager::convertError(ret), out,
541                       ("Failed: media_folder_get_path"));
542     free(id);
543     free(name);
544     free(path);
545     return;
546   }
547
548   ret = media_folder_get_storage_type(folder, &storageType);
549   if(ret!=MEDIA_CONTENT_ERROR_NONE)
550   {
551     free(id);
552     free(name);
553     free(path);
554     LogAndReportError(ContentManager::convertError(ret), out,
555                       ("Failed: media_folder_get_storage_type"));
556     return;
557   }
558
559
560   (*out)["id"] = picojson::value(std::string(id));
561   (*out)["directoryURI"] = picojson::value(std::string(path));
562   (*out)["title"] = picojson::value(std::string(name));
563
564   if (storageType == MEDIA_CONTENT_STORAGE_INTERNAL) {
565     (*out)["storageType"] = picojson::value(std::string("INTERNAL"));
566   } else if (storageType == MEDIA_CONTENT_STORAGE_EXTERNAL) {
567     (*out)["storageType"] = picojson::value(std::string("EXTERNAL"));
568   }
569
570   (*out)["modifiedDate"] = picojson::value(static_cast<double>(date));
571
572   free(name);
573   free(id);
574   free(path);
575 }
576
577 static bool media_foreach_directory_cb(media_folder_h folder, void *user_data) {
578   LoggerD("Enter");
579   picojson::array *array = static_cast<picojson::array*>(user_data);
580   picojson::object json;
581   FolderToJson(folder, &json);
582   array->push_back(picojson::value(json));
583   return true;
584 }
585
586 static bool media_foreach_content_cb(media_info_h media, void *user_data) {
587   LoggerD("Enter");
588   picojson::value::array *contents = static_cast<picojson::value::array*>(user_data);
589   picojson::value::object o;
590   ContentToJson(media, o);
591   contents->push_back(picojson::value(o));
592   return true;
593 }
594
595 static bool playlist_foreach_cb(media_playlist_h playlist, void *user_data) {
596
597   LoggerD("Enter");
598   picojson::value::array *playlists = static_cast<picojson::value::array*>(user_data);
599   picojson::value::object o;
600   if (playlist != NULL) {
601     int id,cnt;
602     char* thumb_path = NULL;
603     char* name = NULL;
604     filter_h filter = NULL;
605     if( media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
606       std::stringstream str_id;
607       str_id << id;
608       o["id"] = picojson::value(std::to_string(id));
609     }
610     else {
611       LoggerD("Invalid ID for playlist.");
612     }
613     if( media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
614       if (thumb_path != NULL) {
615         std::string thumbnail_uri (thumb_path);
616         if (thumbnail_uri != " ") {
617           thumbnail_uri = uri_prefix + thumbnail_uri;
618         }
619         o["thumbnailURI"] = picojson::value(thumbnail_uri);
620         free(thumb_path);
621       }
622       else {
623        o["thumbnailURI"] = picojson::value();//picojson::value(std::string(""));
624       }
625     }
626     else {
627       LoggerD("Invalid thumbnail path for playlist.");
628     }
629     if( media_playlist_get_name(playlist, &name) == MEDIA_CONTENT_ERROR_NONE) {
630       o["name"] = picojson::value(std::string(name));
631       free(name);
632     }
633     else {
634       LoggerD("Invalid name for playlist.");
635     }
636
637     media_filter_create(&filter);
638     std::unique_ptr<std::remove_pointer<filter_h>::type, int(*)(filter_h)>
639         filter_ptr(filter, &media_filter_destroy); // automatically release the memory
640     if( media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
641       o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
642     }
643     else {
644       LoggerE("Invalid count for playlist.");
645     }
646     playlists->push_back(picojson::value(o));
647
648   }
649   return true;
650 }
651
652 static bool playlist_content_member_cb(int playlist_member_id, media_info_h media, void *user_data) {
653
654   LoggerD("Enter");
655   picojson::value::array *contents = static_cast<picojson::value::array*>(user_data);
656   picojson::value::object o;
657
658   o["playlist_member_id"] = picojson::value(static_cast<double>(playlist_member_id));
659   ContentToJson(media, o);
660   contents->push_back(picojson::value(o));
661   return true;
662 }
663
664 void CreateThumbnailCallback(media_content_error_e err, const char* path, void* user_data) {
665   LoggerD("Enter");
666
667   unsigned int* callbackId = (unsigned int*) user_data;
668
669   if (!(ContentManager::getInstance()->getContentInstance())) {
670     // There is not instance already
671     LoggerD("There is not instance now");
672     delete callbackId;
673     return;
674   }
675
676   picojson::object out;
677
678   out["callbackId"] = picojson::value(static_cast<double>(*callbackId));
679
680   if (MEDIA_CONTENT_ERROR_NONE == err) {
681     out["result"] = picojson::value(std::string(path));
682     ReportSuccess(out);
683   } else {
684     PlatformResult result = ContentManager::getInstance()->convertError(err);
685     LogAndReportError(result, &out, ("Failed to create a thumbnail"));
686   }
687
688   delete callbackId;
689   common::Instance::PostMessage(ContentManager::getInstance()->getContentInstance(),
690                                 picojson::value(out).serialize().c_str());
691 }
692
693
694 ContentManager::ContentManager() {
695   LoggerD("ContentManager called");
696   if(media_content_connect() == MEDIA_CONTENT_ERROR_NONE) {
697       m_dbConnected = true;
698   }
699   else
700       m_dbConnected = false;
701   m_contentInstance = nullptr;
702 }
703
704 ContentManager::~ContentManager() {
705   LoggerD("Enter");
706   if(m_dbConnected) {
707     if(media_content_disconnect() == MEDIA_CONTENT_ERROR_NONE) {
708       m_dbConnected = false;
709     }
710   }
711 }
712
713 ContentManager* ContentManager::getInstance() {
714   LoggerD("Enter");
715   static ContentManager instance;
716   return &instance;
717 }
718
719 ContentInstance* ContentManager::getContentInstance() {
720   LoggerD("Enter");
721   return m_contentInstance;
722 }
723
724 void ContentManager::setContentInstance(ContentInstance* const content_instance) {
725   LoggerD("Enter");
726   m_contentInstance = content_instance;
727 }
728
729 bool ContentManager::isConnected() {
730   LoggerD("Enter");
731   return m_dbConnected;
732 }
733
734 void ContentManager::getDirectories(const std::shared_ptr<ReplyCallbackData>& user_data) {
735
736   LoggerD("Enter");
737   int ret;
738   filter_h filter = NULL;
739   ret = media_filter_create(&filter);
740   if (ret != MEDIA_CONTENT_ERROR_NONE) {
741     LoggerE("Failed: media_filter_create failed");
742     return;
743   }
744
745   SCOPE_EXIT {
746     media_filter_destroy(filter);
747   };
748
749   std::string condition = "(FOLDER_STORAGE_TYPE = 0 OR FOLDER_STORAGE_TYPE = 1)";
750   media_filter_set_condition(filter, condition.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
751
752   picojson::array pico_dirs;
753   ret = media_folder_foreach_folder_from_db(filter, media_foreach_directory_cb, &pico_dirs);
754   if (ret != MEDIA_CONTENT_ERROR_NONE) {
755     PlatformResult err = LogAndCreateResult(
756                             ErrorCode::UNKNOWN_ERR, "Getting the directories failed.",
757                             ("Failed: Getting the directories failed %d (%s)",
758                               ret, get_error_message(ret)));
759     user_data->isSuccess = err;
760     return;
761   }
762
763   user_data->result = picojson::value(pico_dirs);
764 }
765
766 void ContentManager::find(const std::shared_ptr<ReplyCallbackData>& user_data) {
767   LoggerD("Enter");
768
769   int ret;
770   int count, offset;
771   std::string dirId;
772
773   picojson::value::array arrayContent;
774   filter_h filter = nullptr;
775   media_filter_create(&filter);
776   SCOPE_EXIT {
777     if (filter) {
778       media_filter_destroy(filter);
779     }
780   };
781
782   if (!IsNull(user_data->args.get("filter"))) {
783     ContentFilter filterMechanism;
784     std::string query;
785     picojson::object argsObject = JsonCast<picojson::object>(user_data->args);
786     if (filterMechanism.BuildQuery(
787         FromJson<picojson::object>(argsObject, "filter"), &query)) {
788       LOGGER(DEBUG) << "Filter query: " << query;
789       ret = media_filter_set_condition(filter, query.c_str(),
790           MEDIA_CONTENT_COLLATE_DEFAULT);
791       if (MEDIA_CONTENT_ERROR_NONE != ret) {
792         LoggerE("Platform filter setting failed, error %d", ret);
793       }
794     }
795   }
796
797   if (user_data->args.contains("sortMode")) {
798     picojson::value vSortMode = user_data->args.get("sortMode");
799
800     if (vSortMode.is<picojson::object>()) {
801       std::string sortModeName, sortModeOrder;
802
803       ContentFilter::MapField(vSortMode.get("attributeName").to_str(), &sortModeName);
804
805       sortModeOrder = vSortMode.get("order").to_str();
806       if (!sortModeOrder.empty()) {
807         media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
808
809         if (sortModeOrder == "ASC") {
810           order = MEDIA_CONTENT_ORDER_ASC;
811         } else if (sortModeOrder == "DESC") {
812           order = MEDIA_CONTENT_ORDER_DESC;
813         }
814
815         ret = media_filter_set_order(filter, order, sortModeName.c_str(),
816             MEDIA_CONTENT_COLLATE_DEFAULT);
817         if (MEDIA_CONTENT_ERROR_NONE != ret) {
818           LoggerE("Platform SortMode setting failed, error: %d", ret);
819         }
820       }
821     }
822   }
823
824   if (!IsNull(user_data->args.get("count"))) {
825     count = static_cast<int>(user_data->args.get("count").get<double>());
826   } else {
827     count = -1;
828   }
829   if (!IsNull(user_data->args.get("offset"))) {
830     offset = static_cast<int>(user_data->args.get("offset").get<double>());
831   } else {
832     offset = -1;
833   }
834   ret = media_filter_set_offset(filter, offset, count);
835   if (MEDIA_CONTENT_ERROR_NONE != ret) {
836     LoggerE("A platform error occurs in media_filter_set_offset: %d", ret);
837   }
838   if (!IsNull(user_data->args.get("directoryId"))) {
839     dirId = user_data->args.get("directoryId").get<std::string>();
840     ret = media_folder_foreach_media_from_db(dirId.c_str(), filter, media_foreach_content_cb, static_cast<void*>(&arrayContent));
841   } else {
842     ret = media_info_foreach_media_from_db(filter, media_foreach_content_cb, static_cast<void*>(&arrayContent));
843   }
844
845   if (ret == MEDIA_CONTENT_ERROR_NONE) {
846     user_data->result = picojson::value(arrayContent);
847   } else {
848     PlatformResult err = LogAndCreateResult(
849                             ErrorCode::UNKNOWN_ERR, "The iteration failed in platform",
850                             ("The iteration failed in platform: %d (%s)",
851                                 ret, get_error_message(ret)));
852     user_data->isSuccess = err;
853   }
854 }
855
856 int ContentManager::scanFile(std::string& uri) {
857   LoggerD("Enter");
858   return media_content_scan_file(uri.c_str());
859 }
860
861 PlatformResult ContentManager::scanDirectory(media_scan_completed_cb callback, ReplyCallbackData* cbData) {
862   LoggerD("Enter");
863   const std::string& contentDirURI = cbData->args.get("contentDirURI").get<std::string>();
864   std::string real_path = common::FilesystemProvider::Create().GetRealPath(contentDirURI);
865   const bool recursive = cbData->args.get("recursive").get<bool>();
866
867   int ret = media_content_scan_folder(real_path.c_str(), recursive, callback, (void*) cbData);
868
869   if (ret != MEDIA_CONTENT_ERROR_NONE) {
870     if (MEDIA_CONTENT_ERROR_INVALID_PARAMETER == ret) {
871       return LogAndCreateResult(
872                 ErrorCode::INVALID_VALUES_ERR, "Scanning content directory failed",
873                 ("Scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
874
875     } else {
876       return LogAndCreateResult(
877                 ErrorCode::UNKNOWN_ERR, "Scanning content directory failed",
878                 ("Scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
879     }
880   }
881   return PlatformResult(ErrorCode::NO_ERROR);
882 }
883
884 PlatformResult ContentManager::cancelScanDirectory(const std::string& content_dir_uri) {
885   LoggerD("Enter");
886
887   int ret = media_content_cancel_scan_folder(content_dir_uri.c_str());
888   if (ret != MEDIA_CONTENT_ERROR_NONE) {
889     return LogAndCreateResult(
890               ErrorCode::UNKNOWN_ERR, "Cancel scan content directory failed",
891               ("Cancel scan folder failed in platform: %d (%s)", ret, get_error_message(ret)));
892   }
893   return PlatformResult(ErrorCode::NO_ERROR);
894 }
895
896 PlatformResult ContentManager::addChangeListener(media_content_noti_h* noti_handle,
897                                                  media_content_db_update_cb callback,
898                                                  void *user_data) {
899   LoggerD("Enter");
900
901   int ret = media_content_add_db_updated_cb(callback, user_data, noti_handle);
902
903   if (MEDIA_CONTENT_ERROR_NONE != ret) {
904     return LogAndCreateResult(
905         ErrorCode::ABORT_ERR,
906         "Failed to add the listener.",
907         ("Failed to add the listener: %d (%s)", ret, get_error_message(ret)));
908   }
909
910   return PlatformResult(ErrorCode::NO_ERROR);
911 }
912
913 PlatformResult ContentManager::removeChangeListener(media_content_noti_h noti_handle) {
914   LoggerD("Enter");
915
916   int ret = media_content_remove_db_updated_cb(noti_handle);
917
918   switch (ret) {
919     case MEDIA_CONTENT_ERROR_NONE:
920       return PlatformResult(ErrorCode::NO_ERROR);
921     case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
922       // Trying to remove non-existent listener, ignoring
923       LoggerI("Failed to remove the listener: %d (%s)", ret, get_error_message(ret));
924       return PlatformResult(ErrorCode::NO_ERROR);
925     default:
926       return LogAndCreateResult(
927           ErrorCode::ABORT_ERR,
928           "Failed to remove the listener.",
929           ("Failed to remove the listener: %d (%s)", ret, get_error_message(ret)));
930   }
931 }
932
933 PlatformResult ContentManager::setChangeListener(media_content_db_update_cb callback,
934                                                  void *user_data) {
935   LoggerD("Enter");
936
937   int ret = media_content_set_db_updated_cb(callback, user_data);
938   if(ret != MEDIA_CONTENT_ERROR_NONE) {
939     return LogAndCreateResult(
940               ErrorCode::UNKNOWN_ERR, "registering the listener is failed.",
941               ("Failed: registering the listener is failed %d (%s)", ret, get_error_message(ret)));
942   }
943   return PlatformResult(ErrorCode::NO_ERROR);
944 }
945
946 PlatformResult ContentManager::unSetChangeListener() {
947   LoggerD("Enter");
948
949   int ret = media_content_unset_db_updated_cb();
950   if(ret != MEDIA_CONTENT_ERROR_NONE) {
951     return LogAndCreateResult(
952               ErrorCode::UNKNOWN_ERR, "unregistering the listener is failed.",
953               ("Failed: unregistering the listener is failed: %d (%s)", ret, get_error_message(ret)));
954   }
955   return PlatformResult(ErrorCode::NO_ERROR);
956 }
957
958 void ContentManager::createPlaylist(std::string name,
959   const std::shared_ptr<ReplyCallbackData>& user_data) {
960   LoggerD("Enter");
961   media_playlist_h playlist = NULL;
962
963   int ret = media_playlist_insert_to_db(name.c_str(),&playlist);
964   std::unique_ptr<std::remove_pointer<media_playlist_h>::type, int(*)(media_playlist_h)>
965       playlist_ptr(playlist, &media_playlist_destroy); // automatically release the memory
966   if(ret != MEDIA_CONTENT_ERROR_NONE) {
967     // MEDIA_CONTENT_ERROR_DB_FAILED means that playlist probably already exists
968     PlatformResult err = LogAndCreateResult(MEDIA_CONTENT_ERROR_DB_FAILED == ret ?
969                                                 ErrorCode::INVALID_VALUES_ERR :
970                                                 ErrorCode::UNKNOWN_ERR, "Creation of playlist has failed.",
971                                             ("Failed: creation of playlist is failed: %d (%s)",
972                                                 ret, get_error_message(ret)));
973     user_data->isSuccess = err;
974     return;
975   }
976   picojson::value::object o;
977
978   if( playlist != NULL) {
979     int id,cnt;
980     char* thumb_path = NULL;
981     char* name = NULL;
982     filter_h filter = NULL;
983     if( media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
984       o["id"] = picojson::value(std::to_string(id));
985     }
986     else {
987       PlatformResult err = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "loading of playlist is failed.");
988       user_data->isSuccess = err;
989       return;
990     }
991     if( media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
992       if (thumb_path != NULL) {
993         o["thumbnailURI"] = picojson::value(std::string(thumb_path));
994         free(thumb_path);
995       }
996       else {
997         o["thumbnailURI"] = picojson::value();
998       }
999     }
1000     else {
1001       LoggerE("Invalid thumbnail path for playlist.");
1002     }
1003     if( media_playlist_get_name(playlist, &name) == MEDIA_CONTENT_ERROR_NONE) {
1004       o["name"] = picojson::value(std::string(name));
1005       free(name);
1006     }
1007     else {
1008       LoggerE("Invalid name for playlist.");
1009     }
1010     media_filter_create(&filter);
1011     std::unique_ptr<std::remove_pointer<filter_h>::type, int(*)(filter_h)>
1012         filter_ptr(filter, &media_filter_destroy); // automatically release the memory
1013
1014     if( media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
1015       o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
1016     }
1017     else {
1018       LoggerE("Invalid count for playlist.");
1019     }
1020   }
1021
1022   user_data->result = picojson::value(o);
1023 }
1024
1025 void ContentManager::getPlaylists(const std::shared_ptr<ReplyCallbackData>& user_data) {
1026
1027   LoggerD("Enter");
1028   int ret;
1029   filter_h filter = nullptr;
1030   media_filter_create(&filter);
1031   std::unique_ptr<std::remove_pointer<filter_h>::type, int(*)(filter_h)>
1032       filter_ptr(filter, &media_filter_destroy); // automatically release the memory
1033   picojson::value::array playlists;
1034
1035   ret = media_playlist_foreach_playlist_from_db(filter, playlist_foreach_cb, static_cast<void*>(&playlists));
1036
1037   if(ret != MEDIA_CONTENT_ERROR_NONE) {
1038     PlatformResult err = LogAndCreateResult(
1039                             ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1040                             ("Failed: Getting playlist is failed %d (%s)", ret, get_error_message(ret)));
1041     user_data->isSuccess = err;
1042   }
1043
1044   user_data->result = picojson::value(playlists);
1045 }
1046
1047 void ContentManager::removePlaylist(std::string playlistId,
1048   const std::shared_ptr<ReplyCallbackData>& user_data) {
1049
1050   LoggerD("Enter");
1051   int id = std::atoi(playlistId.c_str());
1052   if(id == 0) {
1053     PlatformResult err = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "PlaylistId is wrong.");
1054     user_data->isSuccess = err;
1055     return;
1056   }
1057
1058   int ret = media_playlist_delete_from_db(id);
1059   if(ret != MEDIA_CONTENT_ERROR_NONE) {
1060     PlatformResult err = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Removal of playlist is failed.");
1061     user_data->isSuccess = err;
1062   }
1063 }
1064
1065 int ContentManager::update(picojson::value args) {
1066   LoggerD("Enter");
1067
1068   int ret;
1069   picojson::value content = args.get("content");
1070   std::string id = content.get("id").to_str();
1071
1072   media_info_h media = NULL;
1073   ret = media_info_get_media_from_db(id.c_str(), &media);
1074   if (ret == MEDIA_CONTENT_ERROR_NONE) {
1075     setContent(media, content);
1076     ret = media_info_update_to_db(media);
1077     media_info_destroy(media);
1078   }
1079
1080   return ret;
1081 }
1082
1083 int ContentManager::updateBatch(picojson::value args) {
1084   LoggerD("Enter");
1085   int ret = 0;
1086   std::vector<picojson::value> contents = args.get("contents").get<picojson::array>();
1087
1088   for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
1089     picojson::value content = *it;
1090     std::string id = content.get("id").to_str();
1091     media_info_h media = NULL;
1092     ret = media_info_get_media_from_db(id.c_str(), &media);
1093     if (media != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1094       ret = setContent(media, content);
1095       if(ret != MEDIA_CONTENT_ERROR_NONE){
1096         LoggerE("setContent failed");
1097         return ret;
1098       }
1099                         
1100       ret = media_info_update_to_db(media);
1101       if(ret != MEDIA_CONTENT_ERROR_NONE){
1102         LoggerE("update to db failed");
1103       }
1104       media_info_destroy(media);
1105     } else {
1106       return ret;
1107     }
1108   }
1109   return ret;
1110 }
1111
1112 int ContentManager::playlistAdd(std::string playlist_id, std::string content_id) {
1113   LoggerD("Enter");
1114
1115   media_playlist_h playlist = NULL;
1116   int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1117
1118   if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1119     ret = media_playlist_add_media(playlist, content_id.c_str());
1120     if (ret != MEDIA_CONTENT_ERROR_NONE) {
1121       LoggerE("The content(id:%s) can't add to playlist",content_id.c_str());
1122     }
1123
1124     ret = media_playlist_update_to_db(playlist);
1125     if (ret != MEDIA_CONTENT_ERROR_NONE) {
1126       LoggerE("The content(id:%s) can't add to playlist",content_id.c_str());
1127     }
1128   }
1129   else {
1130     LoggerE("Playlist(id:%s) is not exist",playlist_id.c_str());
1131   }
1132
1133   media_playlist_destroy(playlist);
1134   return ret;
1135 }
1136
1137 int ContentManager::playlistRemove(std::string playlist_id, int member_id) {
1138   LoggerD("Enter");
1139
1140   media_playlist_h playlist = NULL;
1141   int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1142   if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
1143     ret = media_playlist_remove_media(playlist, member_id);
1144     if (ret != MEDIA_CONTENT_ERROR_NONE) {
1145       LoggerE("The content can't remove to playlist");
1146     }
1147
1148     ret = media_playlist_update_to_db(playlist);
1149     if (ret != MEDIA_CONTENT_ERROR_NONE) {
1150       LoggerE("The content can't remove to playlist");
1151     }
1152   }
1153   else {
1154     LoggerE("Playlist(id:%s) is not exist",playlist_id.c_str());
1155   }
1156   media_playlist_destroy(playlist);
1157
1158   return ret;
1159 }
1160
1161
1162 void ContentManager::playlistAddbatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
1163
1164   LoggerD("Enter");
1165   std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1166
1167   media_playlist_h playlist = NULL;
1168   int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1169
1170   if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1171     PlatformResult err = LogAndCreateResult(
1172                             ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1173                             ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1174     user_data->isSuccess = err;
1175     return;
1176   }
1177
1178   std::vector<picojson::value> contents = user_data->args.get("contents").get<picojson::array>();
1179   for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
1180     picojson::value content = *it;
1181     std::string id = content.get("id").to_str();
1182     ret = media_playlist_add_media(playlist, id.c_str());
1183     if (ret != MEDIA_CONTENT_ERROR_NONE) {
1184       LoggerE("Adding Content(id:%s) is failed.", id.c_str());
1185     }
1186   }
1187
1188   ret = media_playlist_update_to_db(playlist);
1189   if(ret != MEDIA_CONTENT_ERROR_NONE ) {
1190     PlatformResult err = LogAndCreateResult(
1191                             ErrorCode::UNKNOWN_ERR, "Adding playlist is failed.",
1192                             ("Adding playlist is failed: %d (%s)", ret, get_error_message(ret)));
1193     user_data->isSuccess = err;
1194   }
1195   media_playlist_destroy(playlist);
1196 }
1197
1198 void ContentManager::playlistGet(const std::shared_ptr<ReplyCallbackData>& user_data) {
1199
1200   LoggerD("Enter");
1201   media_playlist_h playlist = NULL;
1202   media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
1203   const std::string playOrder("play_order");
1204
1205   SCOPE_EXIT {
1206     if (playlist) {
1207       media_playlist_destroy(playlist);
1208     }
1209   };
1210
1211   std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1212   int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1213   if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1214     PlatformResult err = LogAndCreateResult(
1215                             ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1216                             ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1217     user_data->isSuccess = err;
1218     return;
1219   }
1220
1221   filter_h filter = NULL;
1222   ret = media_filter_create(&filter);
1223   if (ret != MEDIA_CONTENT_ERROR_NONE) {
1224     PlatformResult err = LogAndCreateResult(
1225                             ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.",
1226                             ("Creating a filter is failed: %d (%s)", ret, get_error_message(ret)));
1227     user_data->isSuccess = err;
1228     return;
1229   }
1230
1231   int count = user_data->args.get("count").get<double>();
1232   int offset = user_data->args.get("offset").get<double>();
1233   ret = media_filter_set_offset(filter, offset, count);
1234   if (ret != MEDIA_CONTENT_ERROR_NONE) {
1235     LoggerD("Setting a offset/count is failed.");
1236   }
1237   ret = media_filter_set_order(filter, order, playOrder.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
1238   if (ret != MEDIA_CONTENT_ERROR_NONE) {
1239     LoggerD("Setting a offset/count is failed.");
1240   }
1241
1242   picojson::value::array arrayContent;
1243   ret = media_playlist_foreach_media_from_db(std::stoi(playlist_id),
1244     filter, playlist_content_member_cb, static_cast<void*>(&arrayContent));
1245
1246   media_filter_destroy(filter);
1247   if (ret == MEDIA_CONTENT_ERROR_NONE) {
1248     user_data->result = picojson::value(arrayContent);
1249   }
1250   else {
1251     PlatformResult err = LogAndCreateResult(
1252                             ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.",
1253                             ("Creating a filter is failed: %d (%s)", ret, get_error_message(ret)));
1254     user_data->isSuccess = err;
1255   }
1256 }
1257
1258 void ContentManager::playlistRemovebatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
1259
1260   LoggerD("Enter");
1261   media_playlist_h playlist = NULL;
1262
1263   SCOPE_EXIT {
1264     if (playlist) {
1265       media_playlist_destroy(playlist);
1266     }
1267   };
1268
1269   std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1270   int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1271   if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1272     PlatformResult err = LogAndCreateResult(
1273                             ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1274                             ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1275     user_data->isSuccess = err;
1276     return;
1277   }
1278
1279   std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
1280   std::size_t members_size = members.size();
1281   for (std::size_t i = 0; i < members_size; ++i) {
1282     int member_id = static_cast<int>(members.at(i).get<double>());
1283     ret = media_playlist_remove_media(playlist, member_id);
1284
1285     if (ret != MEDIA_CONTENT_ERROR_NONE) {
1286       LoggerD("Removing a content is failed.");
1287     }
1288   }
1289
1290   ret = media_playlist_update_to_db(playlist);
1291   if (ret != MEDIA_CONTENT_ERROR_NONE) {
1292     PlatformResult err = LogAndCreateResult(
1293                             ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.",
1294                             ("Removing the contents is failed: %d (%s)", ret, get_error_message(ret)));
1295     user_data->isSuccess = err;
1296   }
1297 }
1298
1299 void ContentManager::playlistSetOrder(const std::shared_ptr<ReplyCallbackData>& user_data) {
1300
1301   LoggerD("Enter");
1302   media_playlist_h playlist = NULL;
1303
1304   SCOPE_EXIT {
1305     if (playlist) {
1306       media_playlist_destroy(playlist);
1307     }
1308   };
1309
1310   std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1311   int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1312   if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1313     PlatformResult err = LogAndCreateResult(
1314                             ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1315                             ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1316     user_data->isSuccess = err;
1317     return;
1318   }
1319
1320   int cnt;
1321   std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
1322
1323   ret = media_playlist_get_media_count_from_db(std::stoi(playlist_id), NULL, &cnt);
1324   if(ret != MEDIA_CONTENT_ERROR_NONE)
1325   {
1326     LoggerE("Failed: media_playlist_get_media_count_from_db");
1327     PlatformResult err = convertError(ret);
1328     user_data->isSuccess = err;
1329     return;
1330   }
1331   std::size_t members_size = members.size();
1332   if (cnt < 0 || static_cast<size_t>(cnt) != members_size ) {
1333     PlatformResult err = LogAndCreateResult(
1334                             ErrorCode::INVALID_VALUES_ERR,
1335                             "The items array does not contain all items from the playlist.",
1336                             ("Failed: The items array does not contain all items from the playlist: %d (%s)",
1337                                 ret, get_error_message(ret)));
1338     user_data->isSuccess = err;
1339     return;
1340   }
1341
1342   for (std::size_t i = 0; i < members_size; ++i) {
1343     int member_id = static_cast<int>(members.at(i).get<double>());
1344     ret = media_playlist_set_play_order(playlist, member_id, i);
1345     if (ret != MEDIA_CONTENT_ERROR_NONE) {
1346       LoggerD("Removing a content is failed.");
1347     }
1348   }
1349
1350   ret = media_playlist_update_to_db(playlist);
1351   if (ret != MEDIA_CONTENT_ERROR_NONE) {
1352     PlatformResult err = LogAndCreateResult(
1353                             ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.",
1354                             ("Removing the contents is failed: %d (%s)", ret, get_error_message(ret)));
1355     user_data->isSuccess = err;
1356   }
1357 }
1358
1359 void ContentManager::playlistMove(const std::shared_ptr<ReplyCallbackData>& user_data) {
1360   LoggerD("Enter");
1361   media_playlist_h playlist = NULL;
1362
1363   SCOPE_EXIT {
1364     if (playlist) {
1365       media_playlist_destroy(playlist);
1366     }
1367   };
1368
1369   std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
1370   int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
1371   if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
1372     PlatformResult err = LogAndCreateResult(
1373                             ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.",
1374                             ("Getting playlist is failed: %d (%s)", ret, get_error_message(ret)));
1375     user_data->isSuccess = err;
1376     return;
1377   }
1378   int old_order;
1379   double member_id = user_data->args.get("memberId").get<double>();
1380   double delta = user_data->args.get("delta").get<double>();
1381   ret = media_playlist_get_play_order(playlist, static_cast<int>(member_id), &old_order);
1382   if (ret != MEDIA_CONTENT_ERROR_NONE) {
1383     PlatformResult err = LogAndCreateResult(
1384                             ErrorCode::UNKNOWN_ERR, "The content can't find form playlist.",
1385                             ("The content can't find form playlist: %d (%s)", ret, get_error_message(ret)));
1386     user_data->isSuccess = err;
1387     return;
1388   }
1389   int new_order = static_cast<int>(old_order) + static_cast<int>(delta);
1390   ret = media_playlist_set_play_order(playlist, static_cast<int>(member_id), new_order);
1391   if (ret != MEDIA_CONTENT_ERROR_NONE) {
1392     PlatformResult err = LogAndCreateResult(
1393                             ErrorCode::UNKNOWN_ERR, "The content can't update play_order.",
1394                             ("The content can't update play_order: %d (%s)", ret, get_error_message(ret)));
1395     user_data->isSuccess = err;
1396     return;
1397   }
1398   ret = media_playlist_update_to_db(playlist);
1399   if (ret != MEDIA_CONTENT_ERROR_NONE) {
1400     PlatformResult err = LogAndCreateResult(
1401                             ErrorCode::UNKNOWN_ERR, "Updateing play_order is failed.",
1402                             ("Updateing play_order is failed: %d (%s)", ret, get_error_message(ret)));
1403     user_data->isSuccess = err;
1404   }
1405 }
1406
1407 int ContentManager::getLyrics(const picojson::value& args, picojson::object& result) {
1408   LoggerD("Enter");
1409
1410   int ret = METADATA_EXTRACTOR_ERROR_NONE;
1411   const std::string& contentURI = args.get("contentURI").to_str();
1412   if (contentURI.empty()) {
1413     LOGGER(ERROR) << "contentURI empty - skipping media extractor";
1414     return -1;
1415   }
1416
1417   metadata_extractor_h extractor;
1418   metadata_extractor_create(&extractor);
1419   std::unique_ptr<std::remove_pointer<metadata_extractor_h>::type, int(*)(metadata_extractor_h)>
1420       extractor_ptr(extractor, &metadata_extractor_destroy); // automatically release the memory
1421
1422   ret = metadata_extractor_set_path(extractor, contentURI.c_str());
1423   if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
1424     LOGGER(ERROR) << "metadata_extractor_set_path failed, error: " << ret;
1425     return ret;
1426   }
1427   picojson::array timestamps;
1428   picojson::array texts = picojson::array();
1429   char* strSyncTextNum = NULL;
1430
1431   ret = metadata_extractor_get_metadata(extractor,
1432       METADATA_SYNCLYRICS_NUM, &strSyncTextNum);
1433   if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
1434     LOGGER(ERROR) << "Media extractor error " << ret;
1435     return ret;
1436   }
1437
1438   int nSyncTextNum = 0;
1439   if (strSyncTextNum) {
1440     nSyncTextNum = atoi(strSyncTextNum);
1441     free(strSyncTextNum);
1442     strSyncTextNum = NULL;
1443   }
1444   if (nSyncTextNum > 0) {
1445     result["type"] = picojson::value(std::string("SYNCHRONIZED"));
1446     for (int i = 0; i < nSyncTextNum; i++) {
1447       unsigned long time_info = 0;
1448       char* lyrics = NULL;
1449       ret = metadata_extractor_get_synclyrics(extractor, i, &time_info, &lyrics);
1450       if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
1451         timestamps.push_back(picojson::value(static_cast<double>(time_info)));
1452         texts.push_back(picojson::value(std::string(lyrics)));
1453         free(lyrics);
1454       }
1455     }
1456     result["texts"] = picojson::value(texts);
1457     result["timestamps"] = picojson::value(timestamps);
1458     ret = METADATA_EXTRACTOR_ERROR_NONE;
1459   } else {
1460     char* unSyncText = nullptr;
1461     ret = metadata_extractor_get_metadata(extractor, METADATA_UNSYNCLYRICS,
1462                                           &unSyncText);
1463     if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
1464       result["type"] = picojson::value(std::string("UNSYNCHRONIZED"));
1465       if (nullptr == unSyncText) {
1466         LOGGER(ERROR) << "Unsynchronized lyrics text is NULL";
1467       }
1468       texts.push_back(picojson::value(unSyncText ? unSyncText : ""));
1469       result["texts"] = picojson::value(texts);
1470       free(unSyncText);
1471     }
1472   }
1473
1474   return ret;
1475 }
1476
1477 media_playlist_h getPlaylistHandle(int id)
1478 {
1479   LoggerD("Entered");
1480   media_playlist_h playlist_handle = nullptr;
1481   int ret_code = media_playlist_get_playlist_from_db(id, &playlist_handle);
1482   if(MEDIA_CONTENT_ERROR_NONE != ret_code ||
1483       playlist_handle == nullptr) {
1484     LoggerE("could not get playlist handle for id: %d", id);
1485     return nullptr;
1486   }
1487
1488   return playlist_handle;
1489 }
1490
1491 void destroyMediaPlaylistHandle(media_playlist_h& playlist_handle)
1492 {
1493   LoggerD("Entered");
1494   if(playlist_handle) {
1495     int ret_code = media_playlist_destroy(playlist_handle);
1496     playlist_handle = nullptr;
1497
1498     if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
1499       LoggerE("media_playlist_destroy failed");
1500     }
1501   }
1502 }
1503
1504 int ContentManager::getPlaylistName(int id, std::string* result) {
1505   LoggerD("Entered");
1506   media_playlist_h playlist_handle = getPlaylistHandle(id);
1507   PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1508
1509   char* tmp_playlist_name = nullptr;
1510   const int ret_code = media_playlist_get_name(playlist_handle, &tmp_playlist_name);
1511
1512   if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
1513     LoggerE("media_playlist_get_name failed");
1514     return TIZEN_ERROR_UNKNOWN;
1515   }
1516
1517   std::string playlist_name;
1518   if(tmp_playlist_name) {
1519     playlist_name = tmp_playlist_name;
1520     free(tmp_playlist_name);
1521     tmp_playlist_name = nullptr;
1522   }
1523
1524   *result = playlist_name;
1525   return MEDIA_CONTENT_ERROR_NONE;
1526 }
1527
1528 int updatePlaylistInDB(media_playlist_h playlist_handle)
1529 {
1530   LoggerD("Entered");
1531   int ret_code = media_playlist_update_to_db(playlist_handle);
1532   if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
1533     LoggerE("media_playlist_update_to_db failed");
1534     return ret_code;
1535   }
1536   return MEDIA_CONTENT_ERROR_NONE;
1537 }
1538
1539 int ContentManager::setPlaylistName(int id, const std::string& name)
1540 {
1541   LoggerD("Entered");
1542   if(name.empty()) {
1543     LoggerE("Cannot set empty playlist name!");
1544     return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1545   }
1546
1547   media_playlist_h playlist_handle = getPlaylistHandle(id);
1548   PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1549
1550   const int ret_code = media_playlist_set_name(playlist_handle, name.c_str());
1551   if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
1552     LoggerE("media_playlist_set_name failed");
1553     //Setting name that is used by other playlist does not return bad error code here.
1554     //MEDIA_CONTENT_ERROR_INVALID_OPERATION is being returned in updatePlaylistInDB
1555     return TIZEN_ERROR_UNKNOWN;
1556   }
1557
1558   int ret = updatePlaylistInDB(playlist_handle);
1559   if (MEDIA_CONTENT_ERROR_NONE != ret) {
1560     LoggerE("Error while updating playlist: %d", ret);
1561     if (MEDIA_CONTENT_ERROR_DB_FAILED == ret) {
1562       //We could fetch list of playlists and check if other playlist is using this
1563       //name, but that seems to be to much work in synchronous method
1564       LoggerE("Playlist name: %s is probably already used", name.c_str());
1565       return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1566     }
1567     return ret;
1568   }
1569   return MEDIA_CONTENT_ERROR_NONE;
1570 }
1571
1572 int ContentManager::getThumbnailUri(int id, std::string* result)
1573 {
1574   LoggerD("Entered");
1575   media_playlist_h playlist_handle = getPlaylistHandle(id);
1576   PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1577
1578   char* tmp_playlist_thb_path = nullptr;
1579   const int ret_code = media_playlist_get_thumbnail_path(playlist_handle, &tmp_playlist_thb_path);
1580
1581   if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
1582     LoggerE("media_playlist_get_name failed");
1583     return TIZEN_ERROR_UNKNOWN;
1584   }
1585
1586   std::string playlist_thb_path;
1587   if(tmp_playlist_thb_path) {
1588     playlist_thb_path = tmp_playlist_thb_path;
1589     free(tmp_playlist_thb_path);
1590     tmp_playlist_thb_path = nullptr;
1591   }
1592
1593   if (playlist_thb_path != " ") {
1594     playlist_thb_path = uri_prefix + playlist_thb_path;
1595   }
1596
1597   *result = playlist_thb_path;
1598   return MEDIA_CONTENT_ERROR_NONE;
1599 }
1600
1601 int ContentManager::setThumbnailUri(int id, const std::string& thb_uri)
1602 {
1603   LoggerD("Entered");
1604
1605   //Allow setting empty URI, unfortunately Core API does not allow to set empty
1606   //path so we need to set one empty space. This is probably issue of Core API.
1607   if(!thb_uri.empty() && " " != thb_uri) {
1608     if(thb_uri.find(uri_absolute_prefix) != 0) {
1609       LoggerE("thumbnail URI is not valid: [%s]", thb_uri.c_str());
1610       return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
1611     }
1612   }
1613
1614   media_playlist_h playlist_handle = getPlaylistHandle(id);
1615   PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
1616
1617   std::string real_path = common::FilesystemProvider::Create().GetRealPath(thb_uri);
1618   const int ret_code = media_playlist_set_thumbnail_path(playlist_handle,
1619                                                          real_path.c_str());
1620   if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
1621     LoggerE("media_playlist_set_thumbnail_path failed");
1622     return TIZEN_ERROR_UNKNOWN;
1623   }
1624
1625   int ret = updatePlaylistInDB(playlist_handle);
1626   return ret;
1627 }
1628
1629 int ContentManager::getNumberOfTracks(int id, int* result) {
1630   LoggerD("Entered");
1631
1632   int count = 0;
1633   const int ret_code = media_playlist_get_media_count_from_db(id, nullptr,
1634                                                               &count);
1635
1636   if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
1637     LoggerE("media_playlist_get_media_count_from_db failed");
1638     return TIZEN_ERROR_UNKNOWN;
1639   }
1640
1641   *result = count;
1642   return MEDIA_CONTENT_ERROR_NONE;
1643 }
1644
1645 common::PlatformResult ContentManager::createThumbnail(const picojson::value& args) {
1646   LoggerD("Enter");
1647
1648   unsigned int* callbackId = new unsigned int(static_cast<unsigned int>(args.get("callbackId").get<double>()));
1649   std::string id = args.get("id").get<std::string>();
1650
1651   media_info_h media = NULL;
1652   int ret = media_info_get_media_from_db(id.c_str(), &media);
1653   if(MEDIA_CONTENT_ERROR_NONE != ret && nullptr == media) {
1654     delete callbackId;
1655     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Getting media is failed.",
1656                               ("Getting media is failed: %d (%s)", ret, get_error_message(ret)));
1657   }
1658
1659   ret = media_info_create_thumbnail(media, CreateThumbnailCallback, /* (void*) callbackId */ nullptr);
1660   media_info_destroy(media);
1661   if(MEDIA_CONTENT_ERROR_NONE != ret) {
1662     delete callbackId;
1663     return LogAndCreateResult(ErrorCode::ABORT_ERR, "Creating thumbnail failed.",
1664                               ("Creating thumbnail failed: %d (%s)", ret, get_error_message(ret)));
1665   }
1666
1667   delete callbackId;
1668
1669   return PlatformResult(ErrorCode::NO_ERROR);
1670 }
1671
1672 PlatformResult ContentManager::convertError(int err) {
1673   char* error_msg = get_error_message(err);
1674   switch (err) {
1675     case MEDIA_CONTENT_ERROR_INVALID_PARAMETER :
1676       return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, error_msg);
1677     case MEDIA_CONTENT_ERROR_OUT_OF_MEMORY :
1678       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1679     case MEDIA_CONTENT_ERROR_INVALID_OPERATION :
1680       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1681     case MEDIA_CONTENT_FILE_NO_SPACE_ON_DEVICE :
1682       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1683     case MEDIA_CONTENT_ERROR_PERMISSION_DENIED :
1684       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1685     case MEDIA_CONTENT_ERROR_DB_FAILED :
1686       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1687     case MEDIA_CONTENT_ERROR_DB_BUSY :
1688       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1689     case MEDIA_CONTENT_ERROR_NETWORK :
1690       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1691     case MEDIA_CONTENT_ERROR_UNSUPPORTED_CONTENT :
1692       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, error_msg);
1693     default:
1694       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
1695   }
1696 }
1697
1698 } // namespace content
1699 } // namespace extension