[content] Fixed coding style
[platform/core/api/webapi-plugins.git] / src / content / content_instance.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_instance.h"
18
19 #include <glib.h>
20 #include <media_content.h>
21 #include <functional>
22 #include <memory>
23 #include <string>
24
25 #include "common/logger.h"
26 #include "common/picojson.h"
27 #include "common/platform_result.h"
28 #include "common/task-queue.h"
29 #include "common/tools.h"
30
31 #include "common/filesystem/filesystem_provider.h"
32 #include "content/content_manager.h"
33
34 using namespace common;
35
36 namespace extension {
37 namespace content {
38
39 namespace {
40 // The privileges that required in Content API
41 const std::string kPrivilegeContentRead = "http://tizen.org/privilege/content.read";
42 const std::string kPrivilegeContentWrite = "http://tizen.org/privilege/content.write";
43
44 }  // namespace
45
46 using common::tools::ReportSuccess;
47 using common::tools::ReportError;
48 using common::PlatformResult;
49
50 ContentInstance::ContentInstance()
51     : noti_handle_(nullptr),
52       listener_handle_(nullptr),
53       listener_data_(nullptr),
54       callback_data_(nullptr) {
55   ScopeLogger();
56   using std::placeholders::_1;
57   using std::placeholders::_2;
58
59 #define REGISTER_SYNC(c, x) RegisterSyncHandler(c, std::bind(&ContentInstance::x, this, _1, _2));
60
61   REGISTER_SYNC("ContentManager_find", ContentManagerFind);
62   REGISTER_SYNC("ContentManager_update", ContentManagerUpdate);
63   REGISTER_SYNC("ContentManager_scanFile", ContentManagerScanfile);
64   REGISTER_SYNC("ContentManager_scanDirectory", ContentManagerScanDirectory);
65   REGISTER_SYNC("ContentManager_cancelScanDirectory", ContentManagerCancelScanDirectory);
66   REGISTER_SYNC("ContentManager_addChangeListener", ContentManagerAddChangeListener);
67   REGISTER_SYNC("ContentManager_removeChangeListener", ContentManagerRemoveChangeListener);
68   REGISTER_SYNC("ContentManager_unsetChangeListener", ContentManagerUnsetchangelistener);
69   REGISTER_SYNC("ContentManager_setChangeListener", ContentManagerSetchangelistener);
70   REGISTER_SYNC("ContentManager_getDirectories", ContentManagerGetdirectories);
71   REGISTER_SYNC("ContentManager_updateBatch", ContentManagerUpdatebatch);
72   REGISTER_SYNC("ContentManager_removePlaylist", ContentManagerRemoveplaylist);
73   REGISTER_SYNC("ContentManager_createPlaylist", ContentManagerCreateplaylist);
74   REGISTER_SYNC("ContentManager_getPlaylists", ContentManagerGetplaylists);
75   REGISTER_SYNC("ContentPlaylist_add", ContentManagerPlaylistAdd);
76   REGISTER_SYNC("ContentPlaylist_addBatch", ContentManagerPlaylistAddbatch);
77   REGISTER_SYNC("ContentPlaylist_get", ContentManagerPlaylistGet);
78   REGISTER_SYNC("ContentPlaylist_remove", ContentManagerPlaylistRemove);
79   REGISTER_SYNC("ContentPlaylist_removeBatch", ContentManagerPlaylistRemovebatch);
80   REGISTER_SYNC("ContentPlaylist_setOrder", ContentManagerPlaylistSetorder);
81   REGISTER_SYNC("ContentPlaylist_move", ContentManagerPlaylistMove);
82   REGISTER_SYNC("ContentManager_getLyrics", ContentManagerAudioGetLyrics);
83
84   REGISTER_SYNC("ContentPlaylist_getName", PlaylistGetName);
85   REGISTER_SYNC("ContentPlaylist_setName", PlaylistSetName);
86   REGISTER_SYNC("ContentPlaylist_getThumbnailUri", PlaylistGetThumbnailUri);
87   REGISTER_SYNC("ContentPlaylist_setThumbnailUri", PlaylistSetThumbnailUri);
88   REGISTER_SYNC("ContentPlaylist_getNumberOfTracks", PlaylistGetNumberOfTracks);
89   REGISTER_SYNC("ContentManager_createThumbnail", ContentManagerCreateThumbnail);
90 #undef REGISTER_SYNC
91
92   ContentManager::getInstance()->setContentInstance(this);
93 }
94
95 ContentInstance::~ContentInstance() {
96   ScopeLogger();
97
98   if (noti_handle_) {
99     media_content_remove_db_updated_cb(noti_handle_);
100     noti_handle_ = nullptr;
101   }
102
103   if (listener_handle_) {
104     media_content_remove_db_updated_cb(listener_handle_);
105     listener_handle_ = nullptr;
106   }
107
108   if (listener_data_) {
109     delete listener_data_;
110     listener_data_ = nullptr;
111   }
112
113   if (callback_data_) {
114     delete callback_data_;
115     callback_data_ = nullptr;
116   }
117
118   ContentManager::getInstance()->setContentInstance(nullptr);
119 }
120
121 static gboolean CompletedCallback(const std::shared_ptr<ReplyCallbackData>& user_data) {
122   ScopeLogger();
123
124   picojson::object out;
125   out["callbackId"] = picojson::value(user_data->callbackId);
126
127   if (user_data->isSuccess) {
128     ReportSuccess(user_data->result, out);
129   } else {
130     LogAndReportError(user_data->isSuccess, &out, ("Failed: user_data->isSuccess"));
131   }
132
133   common::Instance::PostMessage(user_data->instance, picojson::value(out).serialize().c_str());
134
135   return false;
136 }
137
138 static void* WorkThread(const std::shared_ptr<ReplyCallbackData>& user_data) {
139   ScopeLogger();
140
141   int ret = MEDIA_CONTENT_ERROR_NONE;
142   ContentCallbacks cbType = user_data->cbType;
143   switch (cbType) {
144     case ContentManagerUpdatebatchCallback: {
145       ret = ContentManager::getInstance()->updateBatch(user_data->args);
146       if (ret != MEDIA_CONTENT_ERROR_NONE) {
147         LoggerD("UpdateBatch Failed");
148         user_data->isSuccess = ContentManager::getInstance()->convertError(ret);
149       }
150       break;
151     }
152     case ContentManagerGetdirectoriesCallback: {
153       ContentManager::getInstance()->getDirectories(user_data);
154       break;
155     }
156     case ContentManagerFindCallback: {
157       ContentManager::getInstance()->find(user_data);
158       break;
159     }
160     case ContentManagerScanfileCallback: {
161       std::string contentURI = user_data->args.get("contentURI").get<std::string>();
162       std::string real_path = common::FilesystemProvider::Create().GetRealPath(contentURI);
163       ret = ContentManager::getInstance()->scanFile(real_path);
164       if (ret != MEDIA_CONTENT_ERROR_NONE) {
165         PlatformResult err =
166             LogAndCreateResult(common::ErrorCode::UNKNOWN_ERR, "Scan file failed.",
167                                ("Scan file failed, error: %d (%s)", ret, get_error_message(ret)));
168         user_data->isSuccess = err;
169       }
170       break;
171     }
172     case ContentManagerGetplaylistsCallback: {
173       ContentManager::getInstance()->getPlaylists(user_data);
174       break;
175     }
176     case ContentManagerCreateplaylistCallback: {
177       if (user_data->args.contains("sourcePlaylist")) {
178         picojson::object playlist = user_data->args.get("sourcePlaylist").get<picojson::object>();
179         user_data->result = picojson::value(playlist);
180       } else {
181         std::string name = user_data->args.get("name").get<std::string>();
182         ContentManager::getInstance()->createPlaylist(name, user_data);
183       }
184       break;
185     }
186     case ContentManagerRemoveplaylistCallback: {
187       std::string id = user_data->args.get("id").get<std::string>();
188       ContentManager::getInstance()->removePlaylist(id, user_data);
189       // do something...
190       break;
191     }
192     case ContentManagerPlaylistAddbatchCallback: {
193       ContentManager::getInstance()->playlistAddbatch(user_data);
194       break;
195     }
196     case ContentManagerPlaylistGetCallback: {
197       ContentManager::getInstance()->playlistGet(user_data);
198       break;
199     }
200     case ContentManagerPlaylistRemovebatchCallback: {
201       ContentManager::getInstance()->playlistRemovebatch(user_data);
202       break;
203     }
204     case ContentManagerPlaylistSetOrderCallback: {
205       ContentManager::getInstance()->playlistSetOrder(user_data);
206       break;
207       // ContentManagerPlaylistSetOrderCallback
208     }
209     case ContentManagerPlaylistMoveCallback: {
210       ContentManager::getInstance()->playlistMove(user_data);
211       break;
212     }
213     case ContentManagerErrorCallback: {
214       common::PlatformResult err =
215           LogAndCreateResult(common::ErrorCode::UNKNOWN_ERR, "DB Connection is failed.");
216       user_data->isSuccess = err;
217       break;
218     }
219     default: {
220       LoggerE("Invalid Callback Type");
221       return NULL;
222     }
223   }
224   return NULL;
225 }
226
227 static void ScanDirectoryCallback(media_content_error_e error, void* user_data) {
228   ScopeLogger();
229
230   ReplyCallbackData* cbData = (ReplyCallbackData*)user_data;
231
232   picojson::object out;
233   out["callbackId"] = picojson::value(cbData->callbackId);
234
235   if (error == MEDIA_CONTENT_ERROR_NONE) {
236     ReportSuccess(out);
237   } else {
238     LoggerE("Scanning directory failed error: %d (%s)", error, get_error_message(error));
239     ReportError(out);
240   }
241
242   common::Instance::PostMessage(cbData->instance, picojson::value(out).serialize().c_str());
243 }
244
245 static void changedContentCallback(media_content_error_e error, int pid,
246                                    media_content_db_update_item_type_e update_item,
247                                    media_content_db_update_type_e update_type,
248                                    media_content_type_e media_type, char* uuid, char* path,
249                                    char* mime_type, void* user_data) {
250   ScopeLogger("Directory change callback");
251
252   if (error != MEDIA_CONTENT_ERROR_NONE) {
253     LoggerE("Media content changed v2 callback error: %d", (int)error);
254     return;
255   }
256
257   if (update_item == MEDIA_ITEM_DIRECTORY) {
258     if (!uuid) {
259       LoggerE("Provided uuid is NULL, ignoring");
260       return;
261     }
262
263     ReplyCallbackData* cbData = static_cast<ReplyCallbackData*>(user_data);
264
265     int ret;
266     picojson::value result = picojson::value(picojson::object());
267     picojson::object& obj = result.get<picojson::object>();
268
269     if (update_type == MEDIA_CONTENT_INSERT || update_type == MEDIA_CONTENT_UPDATE) {
270       media_folder_h folder = NULL;
271       ret = media_folder_get_folder_from_db(uuid, &folder);
272       if (ret == MEDIA_CONTENT_ERROR_NONE && folder != NULL) {
273         picojson::object o;
274
275         ContentDirToJson(folder, o);
276         ReportSuccess(picojson::value(o), obj);
277
278         if (update_type == MEDIA_CONTENT_INSERT) {
279           obj["state"] = picojson::value("oncontentdiradded");
280         } else {
281           obj["state"] = picojson::value("oncontentdirupdated");
282         }
283
284         media_folder_destroy(folder);
285       }
286     } else {
287       ReportSuccess(picojson::value(std::string(uuid)), obj);
288       obj["state"] = picojson::value("oncontentdirremoved");
289     }
290
291     obj["listenerId"] = cbData->args.get("listenerId");
292     common::Instance::PostMessage(cbData->instance, result.serialize().c_str());
293   } else {
294     LoggerD("Media item is not directory, skipping.");
295     return;
296   }
297 }
298
299 static PlatformResult prepareDirectoryChangeResponse(media_content_db_update_type_e update_type,
300                                                      char* uuid, picojson::object& obj) {
301   ScopeLogger("Media item is a directory");
302
303   if (MEDIA_CONTENT_DELETE == update_type) {
304     ReportSuccess(picojson::value(std::string(uuid)), obj);
305     obj["state"] = picojson::value("oncontentdirremoved");
306     return PlatformResult(ErrorCode::NO_ERROR);
307   }
308
309   media_folder_h folder = nullptr;
310   int ret = media_folder_get_folder_from_db(uuid, &folder);
311
312   if (MEDIA_CONTENT_ERROR_NONE != ret || nullptr == folder) {
313     LoggerE("Failed to get media item (media_folder_get_folder_from_db): %d", ret);
314     return PlatformResult(ErrorCode::ABORT_ERR);
315   }
316
317   picojson::object o;
318   ContentDirToJson(folder, o);
319
320   ret = media_folder_destroy(folder);
321
322   if (MEDIA_CONTENT_ERROR_NONE != ret) {
323     LoggerE("Failed to destroy media folder (media_folder_destroy): %d", ret);
324     return PlatformResult(ErrorCode::ABORT_ERR);
325   }
326
327   ReportSuccess(picojson::value(o), obj);
328
329   if (MEDIA_CONTENT_INSERT == update_type) {
330     obj["state"] = picojson::value("oncontentdiradded");
331   } else if (MEDIA_CONTENT_UPDATE == update_type) {
332     obj["state"] = picojson::value("oncontentdirupdated");
333   }
334
335   return PlatformResult(ErrorCode::NO_ERROR);
336 }
337
338 static PlatformResult prepareFileChangeResponse(media_content_db_update_type_e update_type,
339                                                 char* uuid, picojson::object& obj) {
340   ScopeLogger("Media item is a file");
341
342   if (MEDIA_CONTENT_DELETE == update_type) {
343     ReportSuccess(picojson::value(std::string(uuid)), obj);
344     obj["state"] = picojson::value("oncontentremoved");
345     return PlatformResult(ErrorCode::NO_ERROR);
346   }
347
348   media_info_h media = nullptr;
349   int ret = media_info_get_media_from_db(uuid, &media);
350
351   if (MEDIA_CONTENT_ERROR_NONE != ret || nullptr == media) {
352     LoggerE("Failed to get media item (media_info_get_media_from_db): %d", ret);
353     return PlatformResult(ErrorCode::ABORT_ERR);
354   }
355
356   picojson::object o;
357   ContentToJson(media, o);
358
359   ret = media_info_destroy(media);
360
361   if (MEDIA_CONTENT_ERROR_NONE != ret) {
362     LoggerE("Failed to destroy media info (media_info_destroy): %d", ret);
363     return PlatformResult(ErrorCode::ABORT_ERR);
364   }
365
366   ReportSuccess(picojson::value(o), obj);
367
368   if (MEDIA_CONTENT_INSERT == update_type) {
369     obj["state"] = picojson::value("oncontentadded");
370   } else if (MEDIA_CONTENT_UPDATE == update_type) {
371     obj["state"] = picojson::value("oncontentupdated");
372   }
373
374   return PlatformResult(ErrorCode::NO_ERROR);
375 }
376
377 static void contentChangeCallback(media_content_error_e error, int pid,
378                                   media_content_db_update_item_type_e update_item,
379                                   media_content_db_update_type_e update_type,
380                                   media_content_type_e media_type, char* uuid, char* path,
381                                   char* mime_type, void* user_data) {
382   ScopeLogger("directory and file change callback");
383
384   if (MEDIA_CONTENT_ERROR_NONE != error) {
385     LoggerE("Failed to perform contentChangeCallback: %d", error);
386     return;
387   }
388
389   if (!uuid) {
390     LoggerE("Provided uuid is NULL, ignoring");
391     return;
392   }
393
394   if (nullptr == user_data) {
395     LoggerE("Provided user data is NULL, ignoring");
396     return;
397   }
398
399   if (MEDIA_ITEM_DIRECTORY != update_item && MEDIA_ITEM_FILE != update_item) {
400     LoggerD("Media item is not a directory nor a file, skipping");
401     return;
402   }
403
404   ReplyCallbackData* cbData = static_cast<ReplyCallbackData*>(user_data);
405
406   picojson::value result = picojson::value(picojson::object());
407   picojson::object& obj = result.get<picojson::object>();
408
409   PlatformResult ret(ErrorCode::NO_ERROR);
410   if (MEDIA_ITEM_DIRECTORY == update_item) {
411     ret = prepareDirectoryChangeResponse(update_type, uuid, obj);
412   } else if (MEDIA_ITEM_FILE == update_item) {
413     ret = prepareFileChangeResponse(update_type, uuid, obj);
414   }
415
416   if (ret.IsSuccess()) {
417     obj["listenerId"] = picojson::value("ContentManagerChangeCallback");
418     Instance::PostMessage(cbData->instance, result.serialize().c_str());
419   } else {
420     LoggerD("Failed to prepare content change callback, ignoring");
421   }
422 }
423
424 #define CHECK_EXIST(args, name, out)                                               \
425   if (!args.contains(name)) {                                                      \
426     LogAndReportError(common::PlatformResult(common::ErrorCode::TYPE_MISMATCH_ERR, \
427                                              (name " is required argument")),      \
428                       &out);                                                       \
429     return;                                                                        \
430   }
431
432 void ContentInstance::ContentManagerUpdate(const picojson::value& args, picojson::object& out) {
433   ScopeLogger();
434   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
435
436   if (ContentManager::getInstance()->isConnected()) {
437     int ret = ContentManager::getInstance()->update(args);
438     if (ret != 0) {
439       LogAndReportError(ContentManager::getInstance()->convertError(ret), &out);
440     }
441   } else {
442     LogAndReportError(
443         common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "DB connection is failed."), &out);
444   }
445 }
446
447 void ContentInstance::ContentManagerUpdatebatch(const picojson::value& args,
448                                                 picojson::object& out) {
449   ScopeLogger();
450   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
451   double callbackId = args.get("callbackId").get<double>();
452
453   auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
454   cbData->callbackId = callbackId;
455   cbData->instance = this;
456   cbData->args = args;
457
458   if (ContentManager::getInstance()->isConnected()) {
459     cbData->cbType = ContentManagerUpdatebatchCallback;
460   } else {
461     cbData->cbType = ContentManagerErrorCallback;
462   }
463   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
464 }
465 void ContentInstance::ContentManagerGetdirectories(const picojson::value& args,
466                                                    picojson::object& out) {
467   ScopeLogger();
468   CHECK_EXIST(args, "callbackId", out)
469
470   double callbackId = args.get("callbackId").get<double>();
471   // implement it
472
473   auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
474   cbData->callbackId = callbackId;
475   cbData->instance = this;
476
477   if (ContentManager::getInstance()->isConnected()) {
478     cbData->cbType = ContentManagerGetdirectoriesCallback;
479   } else {
480     cbData->cbType = ContentManagerErrorCallback;
481   }
482   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
483 }
484 void ContentInstance::ContentManagerFind(const picojson::value& args, picojson::object& out) {
485   ScopeLogger();
486   // CHECK_PRIVILEGE_ACCESS(kPrivilegeContentRead, &out);
487   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
488
489   CHECK_EXIST(args, "callbackId", out)
490
491   double callbackId = args.get("callbackId").get<double>();
492
493   auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
494   cbData->callbackId = callbackId;
495   cbData->instance = this;
496   cbData->args = args;
497   if (ContentManager::getInstance()->isConnected()) {
498     cbData->cbType = ContentManagerFindCallback;
499   } else {
500     cbData->cbType = ContentManagerErrorCallback;
501   }
502
503   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
504 }
505
506 void ContentInstance::ContentManagerScanfile(const picojson::value& args, picojson::object& out) {
507   ScopeLogger();
508   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
509
510   CHECK_EXIST(args, "callbackId", out)
511   CHECK_EXIST(args, "contentURI", out)
512
513   double callbackId = args.get("callbackId").get<double>();
514   auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
515   cbData->callbackId = callbackId;
516   cbData->instance = this;
517   cbData->args = args;
518   if (ContentManager::getInstance()->isConnected()) {
519     cbData->cbType = ContentManagerScanfileCallback;
520   } else {
521     cbData->cbType = ContentManagerErrorCallback;
522   }
523   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
524 }
525
526 void ContentInstance::ContentManagerScanDirectory(const picojson::value& args,
527                                                   picojson::object& out) {
528   ScopeLogger();
529   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
530
531   CHECK_EXIST(args, "callbackId", out)
532   CHECK_EXIST(args, "contentDirURI", out)
533   CHECK_EXIST(args, "recursive", out)
534
535   ReplyCallbackData* cbData = new ReplyCallbackData;
536   cbData->callbackId = args.get("callbackId").get<double>();
537   cbData->instance = this;
538   cbData->args = args;
539
540   common::PlatformResult result =
541       ContentManager::getInstance()->scanDirectory(ScanDirectoryCallback, cbData);
542   if (result.IsError()) {
543     LogAndReportError(result, &out);
544   }
545 }
546
547 void ContentInstance::ContentManagerCancelScanDirectory(const picojson::value& args,
548                                                         picojson::object& out) {
549   ScopeLogger();
550   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
551
552   CHECK_EXIST(args, "contentDirURI", out)
553   const std::string& content_dir_uri = args.get("contentDirURI").get<std::string>();
554
555   if (ContentManager::getInstance()->cancelScanDirectory(content_dir_uri).IsError()) {
556     LogAndReportError(
557         common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "Cancel scan directory failed"),
558         &out);
559   }
560 }
561
562 void ContentInstance::ContentManagerAddChangeListener(const picojson::value& args,
563                                                       picojson::object& out) {
564   ScopeLogger();
565
566   callback_data_ = new ReplyCallbackData();
567   callback_data_->instance = this;
568   callback_data_->args = args;
569
570   if (ContentManager::getInstance()->isConnected()) {
571     callback_data_->cbType = ContentManagerAddChangeListenerCallback;
572   } else {
573     callback_data_->cbType = ContentManagerErrorCallback;
574   }
575
576   PlatformResult result = ContentManager::getInstance()->addChangeListener(
577       &listener_handle_, contentChangeCallback, static_cast<void*>(callback_data_));
578
579   if (result.IsError()) {
580     delete callback_data_;
581     callback_data_ = nullptr;
582     LogAndReportError(result, &out);
583   }
584 }
585
586 void ContentInstance::ContentManagerRemoveChangeListener(const picojson::value& args,
587                                                          picojson::object& out) {
588   ScopeLogger();
589
590   PlatformResult result = ContentManager::getInstance()->removeChangeListener(listener_handle_);
591
592   if (result.IsSuccess()) {
593     listener_handle_ = nullptr;
594     delete callback_data_;
595     callback_data_ = nullptr;
596   } else {
597     LogAndReportError(result, &out);
598   }
599 }
600
601 void ContentInstance::ContentManagerSetchangelistener(const picojson::value& args,
602                                                       picojson::object& out) {
603   ScopeLogger();
604   LoggerW(
605       "DEPRECATION WARNING: setChangeListener() is deprecated and will be removed from next "
606       "release. "
607       "Use addChangeListener() instead.");
608   // CHECK_PRIVILEGE_ACCESS(kPrivilegeContentRead, &out);
609   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
610
611   CHECK_EXIST(args, "listenerId", out)
612
613   if (!listener_data_) {
614     listener_data_ = new ReplyCallbackData();
615   }
616
617   listener_data_->instance = this;
618   listener_data_->args = args;
619   if (ContentManager::getInstance()->isConnected()) {
620     listener_data_->cbType = ContentManagerSetchangelistenerCallback;
621   } else {
622     listener_data_->cbType = ContentManagerErrorCallback;
623   }
624
625   if (nullptr == noti_handle_) {  // To remain consistency with the previous implementation
626     if (ContentManager::getInstance()
627             ->addChangeListener(&noti_handle_, changedContentCallback,
628                                 static_cast<void*>(listener_data_))
629             .IsError()) {
630       LogAndReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
631                                                "The callback did not register properly"),
632                         &out);
633     }
634   }
635 }
636
637 void ContentInstance::ContentManagerUnsetchangelistener(const picojson::value& args,
638                                                         picojson::object& out) {
639   ScopeLogger();
640   LoggerW(
641       "DEPRECATION WARNING: unsetChangeListener() is deprecated and will be removed from next "
642       "release. "
643       "Use removeChangeListener() instead.");
644   // CHECK_PRIVILEGE_ACCESS(kPrivilegeContentRead, &out);
645   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
646
647   if (ContentManager::getInstance()->removeChangeListener(noti_handle_).IsError()) {
648     LoggerD("unsuccesfull deregistering of callback");
649   } else {
650     noti_handle_ = nullptr;  // To remain consistency with the previous implementation
651   }
652 }
653
654 void ContentInstance::ContentManagerGetplaylists(const picojson::value& args,
655                                                  picojson::object& out) {
656   ScopeLogger();
657   // CHECK_PRIVILEGE_ACCESS(kPrivilegeContentRead, &out);
658   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
659
660   CHECK_EXIST(args, "callbackId", out)
661
662   double callbackId = args.get("callbackId").get<double>();
663
664   // implement it
665   std::shared_ptr<ReplyCallbackData> cbData(new ReplyCallbackData);
666
667   cbData->callbackId = callbackId;
668   cbData->instance = this;
669   cbData->args = args;
670   if (ContentManager::getInstance()->isConnected()) {
671     cbData->cbType = ContentManagerGetplaylistsCallback;
672   } else {
673     cbData->cbType = ContentManagerErrorCallback;
674   }
675
676   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
677 }
678 void ContentInstance::ContentManagerCreateplaylist(const picojson::value& args,
679                                                    picojson::object& out) {
680   ScopeLogger();
681   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
682
683   CHECK_EXIST(args, "callbackId", out)
684   CHECK_EXIST(args, "name", out)
685
686   double callbackId = args.get("callbackId").get<double>();
687
688   auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
689   cbData->callbackId = callbackId;
690   cbData->instance = this;
691   cbData->args = args;
692
693   if (ContentManager::getInstance()->isConnected()) {
694     cbData->cbType = ContentManagerCreateplaylistCallback;
695   } else {
696     cbData->cbType = ContentManagerErrorCallback;
697   }
698
699   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
700 }
701 void ContentInstance::ContentManagerRemoveplaylist(const picojson::value& args,
702                                                    picojson::object& out) {
703   ScopeLogger();
704   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
705
706   double callbackId = args.get("callbackId").get<double>();
707
708   auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
709   cbData->callbackId = callbackId;
710   cbData->instance = this;
711   cbData->args = args;
712
713   if (ContentManager::getInstance()->isConnected()) {
714     cbData->cbType = ContentManagerRemoveplaylistCallback;
715   } else {
716     cbData->cbType = ContentManagerErrorCallback;
717   }
718
719   // implement it
720   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
721 }
722
723 void ContentInstance::ContentManagerCreateThumbnail(const picojson::value& args,
724                                                     picojson::object& out) {
725   ScopeLogger();
726   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
727   common::PlatformResult result = common::PlatformResult(common::ErrorCode::NO_ERROR);
728
729   if (ContentManager::getInstance()->isConnected()) {
730     result = ContentManager::getInstance()->createThumbnail(args);
731   } else {
732     result = LogAndCreateResult(common::ErrorCode::UNKNOWN_ERR, "DB Connection is failed.");
733   }
734   if (!result) {
735     LogAndReportError(result, &out, ("Failed to create a thumbnail"));
736     common::Instance::PostMessage(this, picojson::value(out).serialize().c_str());
737   }
738 }
739
740 void ContentInstance::ContentManagerPlaylistAdd(const picojson::value& args,
741                                                 picojson::object& out) {
742   ScopeLogger();
743   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
744
745   if (ContentManager::getInstance()->isConnected()) {
746     std::string playlist_id = args.get("playlistId").get<std::string>();
747     std::string content_id = args.get("contentId").get<std::string>();
748     int ret = ContentManager::getInstance()->playlistAdd(playlist_id, content_id);
749     if (ret != MEDIA_CONTENT_ERROR_NONE) {
750       LogAndReportError(ContentManager::getInstance()->convertError(ret), &out);
751     }
752   } else {
753     LogAndReportError(
754         common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "DB connection is failed."), &out);
755   }
756 }
757
758 void ContentInstance::ContentManagerPlaylistAddbatch(const picojson::value& args,
759                                                      picojson::object& out) {
760   ScopeLogger();
761   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
762
763   double callbackId = args.get("callbackId").get<double>();
764
765   auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
766   cbData->callbackId = callbackId;
767   cbData->instance = this;
768   cbData->args = args;
769
770   if (ContentManager::getInstance()->isConnected()) {
771     cbData->cbType = ContentManagerPlaylistAddbatchCallback;
772   } else {
773     cbData->cbType = ContentManagerErrorCallback;
774   }
775   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
776 }
777
778 void ContentInstance::ContentManagerPlaylistGet(const picojson::value& args,
779                                                 picojson::object& out) {
780   ScopeLogger();
781   // CHECK_PRIVILEGE_ACCESS(kPrivilegeContentRead, &out);
782   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
783
784   double callbackId = args.get("callbackId").get<double>();
785
786   auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
787   cbData->callbackId = callbackId;
788   cbData->instance = this;
789   cbData->args = args;
790
791   if (ContentManager::getInstance()->isConnected()) {
792     cbData->cbType = ContentManagerPlaylistGetCallback;
793   } else {
794     cbData->cbType = ContentManagerErrorCallback;
795   }
796   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
797 }
798
799 void ContentInstance::ContentManagerPlaylistRemove(const picojson::value& args,
800                                                    picojson::object& out) {
801   ScopeLogger();
802   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
803
804   if (ContentManager::getInstance()->isConnected()) {
805     std::string playlist_id = args.get("playlistId").get<std::string>();
806     int member_id = args.get("memberId").get<double>();
807     int ret = ContentManager::getInstance()->playlistRemove(playlist_id, member_id);
808     if (ret != MEDIA_CONTENT_ERROR_NONE) {
809       LogAndReportError(ContentManager::getInstance()->convertError(ret), &out);
810     }
811   } else {
812     LogAndReportError(
813         common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "DB connection is failed."), &out);
814   }
815 }
816
817 void ContentInstance::ContentManagerPlaylistRemovebatch(const picojson::value& args,
818                                                         picojson::object& out) {
819   ScopeLogger();
820   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
821
822   double callbackId = args.get("callbackId").get<double>();
823
824   auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
825   cbData->callbackId = callbackId;
826   cbData->instance = this;
827   cbData->args = args;
828
829   if (ContentManager::getInstance()->isConnected()) {
830     cbData->cbType = ContentManagerPlaylistRemovebatchCallback;
831   } else {
832     cbData->cbType = ContentManagerErrorCallback;
833   }
834   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
835 }
836
837 void ContentInstance::ContentManagerPlaylistSetorder(const picojson::value& args,
838                                                      picojson::object& out) {
839   ScopeLogger();
840   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
841
842   double callbackId = args.get("callbackId").get<double>();
843
844   auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
845   cbData->callbackId = callbackId;
846   cbData->instance = this;
847   cbData->args = args;
848
849   if (ContentManager::getInstance()->isConnected()) {
850     cbData->cbType = ContentManagerPlaylistSetOrderCallback;
851   } else {
852     cbData->cbType = ContentManagerErrorCallback;
853   }
854   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
855 }
856
857 void ContentInstance::ContentManagerPlaylistMove(const picojson::value& args,
858                                                  picojson::object& out) {
859   ScopeLogger();
860   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
861
862   double callbackId = args.get("callbackId").get<double>();
863
864   auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
865   cbData->callbackId = callbackId;
866   cbData->instance = this;
867   cbData->args = args;
868
869   if (ContentManager::getInstance()->isConnected()) {
870     cbData->cbType = ContentManagerPlaylistMoveCallback;
871   } else {
872     cbData->cbType = ContentManagerErrorCallback;
873   }
874   common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
875 }
876
877 void ContentInstance::ContentManagerAudioGetLyrics(const picojson::value& args,
878                                                    picojson::object& out) {
879   ScopeLogger();
880
881   picojson::object lyrics;
882   if (ContentManager::getInstance()->isConnected()) {
883     int ret = ContentManager::getInstance()->getLyrics(args, lyrics);
884     if (ret != MEDIA_CONTENT_ERROR_NONE) {
885       LogAndReportError(ContentManager::getInstance()->convertError(ret), &out);
886     } else {
887       ReportSuccess(picojson::value(lyrics), out);
888     }
889   } else {
890     LogAndReportError(
891         common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "DB connection is failed."), &out);
892   }
893 }
894
895 void ContentInstance::PlaylistGetName(const picojson::value& args, picojson::object& out) {
896   ScopeLogger();
897   int ret;
898   CHECK_EXIST(args, "id", out)
899   int id = static_cast<int>(args.get("id").get<double>());
900   std::string name;
901   ret = ContentManager::getInstance()->getPlaylistName(id, &name);
902   if (ret != MEDIA_CONTENT_ERROR_NONE) {
903     LogAndReportError(ContentManager::getInstance()->convertError(ret), &out);
904   } else {
905     ReportSuccess(picojson::value(name), out);
906   }
907 }
908
909 void ContentInstance::PlaylistSetName(const picojson::value& args, picojson::object& out) {
910   ScopeLogger();
911   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
912
913   int ret;
914   CHECK_EXIST(args, "id", out)
915   CHECK_EXIST(args, "name", out)
916   int id = static_cast<int>(args.get("id").get<double>());
917   std::string name = args.get("name").get<std::string>();
918   ret = ContentManager::getInstance()->setPlaylistName(id, name);
919   if (ret != MEDIA_CONTENT_ERROR_NONE) {
920     LogAndReportError(ContentManager::getInstance()->convertError(ret), &out);
921   } else {
922     ReportSuccess(out);
923   }
924 }
925
926 void ContentInstance::PlaylistGetThumbnailUri(const picojson::value& args, picojson::object& out) {
927   ScopeLogger();
928   int ret;
929   CHECK_EXIST(args, "id", out)
930   int id = static_cast<int>(args.get("id").get<double>());
931   std::string uri;
932   ret = ContentManager::getInstance()->getThumbnailUri(id, &uri);
933   if (ret != MEDIA_CONTENT_ERROR_NONE) {
934     LogAndReportError(ContentManager::getInstance()->convertError(ret), &out);
935   } else {
936     ReportSuccess(picojson::value(uri), out);
937   }
938 }
939
940 void ContentInstance::PlaylistSetThumbnailUri(const picojson::value& args, picojson::object& out) {
941   ScopeLogger();
942   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
943
944   int ret;
945   CHECK_EXIST(args, "id", out)
946   CHECK_EXIST(args, "uri", out)
947   int id = static_cast<int>(args.get("id").get<double>());
948   std::string uri = args.get("uri").get<std::string>();
949   ret = ContentManager::getInstance()->setThumbnailUri(id, uri);
950   if (ret != MEDIA_CONTENT_ERROR_NONE) {
951     LogAndReportError(ContentManager::getInstance()->convertError(ret), &out);
952   } else {
953     ReportSuccess(out);
954   }
955 }
956
957 void ContentInstance::PlaylistGetNumberOfTracks(const picojson::value& args,
958                                                 picojson::object& out) {
959   ScopeLogger();
960   CHECK_EXIST(args, "id", out)
961   int id = static_cast<int>(args.get("id").get<double>());
962   int count = 0;
963   int ret = ContentManager::getInstance()->getNumberOfTracks(id, &count);
964   if (ret != MEDIA_CONTENT_ERROR_NONE) {
965     LogAndReportError(ContentManager::getInstance()->convertError(ret), &out);
966   } else {
967     ReportSuccess(picojson::value(static_cast<double>(count)), out);
968   }
969 }
970
971 #undef CHECK_EXIST
972
973 }  // namespace content
974 }  // namespace extension