[Mediacontroller] Added refreshing the list of handles 94/245294/1 accepted/tizen/5.5/unified/20201103.003327 submit/tizen_5.5/20201026.095948
authorPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Thu, 3 Sep 2020 08:35:44 +0000 (10:35 +0200)
committerPiotr Kosko <p.kosko@samsung.com>
Tue, 6 Oct 2020 11:47:32 +0000 (13:47 +0200)
[Bug] If native application (e.g. service) adds the playlist,
web api is able to gather it, but cannot perform any actions on it,
because web API stores only handles to playlists created by itself.

[Solution] Added functionality of refreshing handles always when gathering
a playlists handles using native API

[Verification] Code compiles without errors.

Change-Id: I9bb757f50c3bc4167b0a97c923d49a1ccbbe0195

src/mediacontroller/mediacontroller_api.js
src/mediacontroller/mediacontroller_instance.cc
src/mediacontroller/mediacontroller_instance.h
src/mediacontroller/mediacontroller_server.cc
src/mediacontroller/mediacontroller_server.h
src/mediacontroller/mediacontroller_utils.cc
src/mediacontroller/mediacontroller_utils.h

index 50b767fcdad2afb0a7bce9e99d9a8d12785cfc7e..1420462ae1ac6791189ed31e24c9866d9253d84e 100755 (executable)
@@ -2486,11 +2486,11 @@ MediaControllerServer.prototype.removeCommandListener = function(watchId) {
 
 MediaControllerServer.prototype.createPlaylist = function(name) {
     var args = validator_.validateArgs(arguments, [
-        { name: 'name', type: types_.STRING }
+        { name: 'playlistName', type: types_.STRING }
     ]);
 
     var data = {
-        name: args.name
+        playlistName: args.playlistName
     };
 
     var result = native_.callSync('MediaControllerServerCreatePlaylist', data);
@@ -2523,7 +2523,8 @@ MediaControllerServer.prototype.savePlaylist = function(
     ]);
 
     var data = {
-        name: args.playlist.name
+        playlistName: args.playlist.name,
+        serverName: args.playlist._serverName
     };
 
     var callback = function(result) {
@@ -2547,7 +2548,7 @@ MediaControllerServer.prototype.deletePlaylist = function(
     errorCallback
 ) {
     var args = validator_.validateArgs(arguments, [
-        { name: 'name', type: types_.STRING },
+        { name: 'playlistName', type: types_.STRING },
         {
             name: 'successCallback',
             type: types_.FUNCTION,
@@ -2558,7 +2559,7 @@ MediaControllerServer.prototype.deletePlaylist = function(
     ]);
 
     var data = {
-        name: args.name
+        playlistName: args.playlistName
     };
 
     var callback = function(result) {
@@ -3628,7 +3629,7 @@ MediaControllerServerInfo.prototype.getAllPlaylists = function(
 
     var result = native_.call(
         'MediaControllerServerInfoGetAllPlaylists',
-        { name: this.name },
+        { serverName: this.name },
         callback
     );
 
@@ -3758,6 +3759,11 @@ function MediaControllerPlaylist(data) {
                 _name = edit_.isAllowed && v ? v : _name;
             },
             enumerable: true
+        },
+        _serverName: {
+            value: data.serverName,
+            writable: false,
+            enumerable: false
         }
     });
     edit_.allow();
@@ -3802,7 +3808,8 @@ MediaControllerPlaylist.prototype.getItems = function(successCallback, errorCall
     ]);
 
     var data = {
-        name: this.name
+        name: this.name,
+        serverName: this._serverName
     };
 
     var callback = function(result) {
index ed9cacd7a976e47dcc876645c902d383537328c4..76ae04c6dce5f5e0e0db204ed8c2796a2a174fa4 100644 (file)
@@ -168,6 +168,13 @@ MediaControllerInstance::MediaControllerInstance() {
 
 MediaControllerInstance::~MediaControllerInstance() {
   ScopeLogger();
+  for (auto const& s : server_playlist_map_) {
+    for (auto const& v : s.second) {
+      if (MEDIA_CONTROLLER_ERROR_NONE != mc_playlist_destroy(v.second)) {
+        LoggerE("Unable to destroy playlist %s", v.first.c_str());
+      }
+    }
+  }
 }
 
 #define CHECK_EXIST(args, name, out)                                            \
@@ -578,16 +585,29 @@ void MediaControllerInstance::MediaControllerServerCreatePlaylist(const picojson
     return;
   }
 
-  CHECK_ARGS(args, kName, std::string, out)
+  CHECK_ARGS(args, kPlaylistName, std::string, out)
 
   picojson::value playlist_info = picojson::value();
-
-  auto result = server_->CreatePlaylist(args.get(kName).get<std::string>(), &playlist_info);
+  std::string serverName = common::CurrentApplication::GetInstance().GetApplicationId();
+  auto playlistName = args.get(kPlaylistName).get<std::string>();
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+  if (server_playlist_map_.find(serverName) != server_playlist_map_.end() &&
+      server_playlist_map_[serverName].find(playlistName) !=
+          server_playlist_map_[serverName].end()) {
+    result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
+                                "Playlist with given name already exists");
+    LogAndReportError(result, &out);
+    return;
+  }
+  mc_playlist_h playlist_handle = nullptr;
+  result = server_->CreatePlaylist(serverName, playlistName, &playlist_info, playlist_handle);
   if (!result) {
-    LogAndReportError(result, &out, ("Failed: server_->CreatePlaylist["));
+    LogAndReportError(result, &out, ("Failed: server_->CreatePlaylist"));
     return;
   }
 
+  server_playlist_map_[serverName][playlistName] = playlist_handle;
+
   ReportSuccess(playlist_info, out);
 }
 
@@ -601,14 +621,30 @@ void MediaControllerInstance::MediaControllerServerSavePlaylist(const picojson::
   }
 
   CHECK_EXIST(args, kCallbackId, out)
-  CHECK_ARGS(args, kName, std::string, out)
+  CHECK_ARGS(args, kPlaylistName, std::string, out)
+  CHECK_ARGS(args, kServerName, std::string, out)
 
   auto save = [this, args]() -> void {
     picojson::value response = picojson::value(picojson::object());
     picojson::object& response_obj = response.get<picojson::object>();
     response_obj[kCallbackId] = args.get(kCallbackId);
 
-    auto result = server_->SavePlaylist(args.get(kName).get<std::string>());
+    auto name = args.get(kPlaylistName).get<std::string>();
+    auto serverName = args.get(kServerName).get<std::string>();
+
+    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+    if (server_playlist_map_.find(serverName) == server_playlist_map_.end() ||
+        server_playlist_map_[serverName].find(name) == server_playlist_map_[serverName].end()) {
+      result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
+                                  "Playlist with given name doesn't exist");
+      LogAndReportError(result, &response_obj,
+                        ("Failed: MediaControllerInstance::MediaControllerServerSavePlaylist"));
+      Instance::PostMessage(this, response.serialize().c_str());
+      return;
+    }
+
+    result = server_->SavePlaylist(server_playlist_map_[serverName][name]);
 
     if (result) {
       ReportSuccess(response_obj);
@@ -634,14 +670,28 @@ void MediaControllerInstance::MediaControllerServerDeletePlaylist(const picojson
   }
 
   CHECK_EXIST(args, kCallbackId, out)
-  CHECK_ARGS(args, kName, std::string, out)
+  CHECK_ARGS(args, kPlaylistName, std::string, out)
 
   auto del = [this, args]() -> void {
     picojson::value response = picojson::value(picojson::object());
     picojson::object& response_obj = response.get<picojson::object>();
     response_obj[kCallbackId] = args.get(kCallbackId);
 
-    auto result = server_->DeletePlaylist(args.get(kName).get<std::string>());
+    auto name = args.get(kPlaylistName).get<std::string>();
+    std::string serverName = common::CurrentApplication::GetInstance().GetApplicationId();
+
+    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+    if (server_playlist_map_.find(serverName) == server_playlist_map_.end() ||
+        server_playlist_map_[serverName].find(name) == server_playlist_map_[serverName].end()) {
+      result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
+                                  "Playlist with given name doesn't exist");
+      LogAndReportError(result, &response_obj,
+                        ("Failed: MediaControllerInstance::MediaControllerServerDeletePlaylist"));
+      Instance::PostMessage(this, response.serialize().c_str());
+      return;
+    }
+    result = server_->DeletePlaylist(server_playlist_map_[serverName][name]);
 
     if (result) {
       ReportSuccess(response_obj);
@@ -649,6 +699,12 @@ void MediaControllerInstance::MediaControllerServerDeletePlaylist(const picojson
       LogAndReportError(result, &response_obj, ("Failed: server_->DeletePlaylist"));
     }
 
+    if (MEDIA_CONTROLLER_ERROR_NONE != mc_playlist_destroy(server_playlist_map_[serverName][name])) {
+      LoggerE("Unable to destroy playlist %s", name.c_str());
+    }
+
+    server_playlist_map_[serverName].erase(name);
+
     Instance::PostMessage(this, response.serialize().c_str());
   };
 
@@ -682,6 +738,11 @@ void MediaControllerInstance::MediaControllerServerUpdatePlaybackItem(const pico
 void MediaControllerInstance::MediaControllerServerGetAllPlaylists(const picojson::value& args,
                                                                    picojson::object& out) {
   ScopeLogger();
+  if (!server_) {
+    LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
+                      (MediaControllerServerUnknownErrorMsg));
+    return;
+  }
 
   auto get = [this, args]() -> void {
     picojson::value response = picojson::value(picojson::object());
@@ -698,14 +759,16 @@ void MediaControllerInstance::MediaControllerServerGetAllPlaylists(const picojso
       return;
     }
 
-    picojson::value playlists{picojson::array{}};
-    auto result = utils::GetAllPlaylists(app_id, &playlists.get<picojson::array>());
-
+    std::map<std::string, mc_playlist_h> new_playlists_map;
+    auto result = utils::GetAllPlaylistsHandles(app_id, &new_playlists_map);
     if (!result) {
       LogAndReportError(result, &response_obj, ("Failed: utils::GetAllPlaylists"));
       Instance::PostMessage(this, response.serialize().c_str());
       return;
     }
+    // update the list of stored handles
+    utils::UpdatePlaylistHandleMap(app_id, new_playlists_map, server_playlist_map_);
+    picojson::value playlists = utils::CreatePlaylistsJSON(app_id, new_playlists_map);
 
     response_obj[kResult] = picojson::value{playlists};
     ReportSuccess(response_obj);
@@ -1596,7 +1659,7 @@ void MediaControllerInstance::MediaControllerServerInfoGetAllPlaylists(const pic
                                                                        picojson::object& out) {
   ScopeLogger();
 
-  CHECK_ARGS(args, kName, std::string, out)
+  CHECK_ARGS(args, kServerName, std::string, out)
 
   auto get = [this, args]() -> void {
     picojson::value response = picojson::value(picojson::object());
@@ -1604,16 +1667,17 @@ void MediaControllerInstance::MediaControllerServerInfoGetAllPlaylists(const pic
 
     response_obj[kCallbackId] = args.get(kCallbackId);
 
-    picojson::value playlists{picojson::array{}};
-
-    auto result = utils::GetAllPlaylists(args.get(kName).get<std::string>(),
-                                         &playlists.get<picojson::array>());
-
+    std::map<std::string, mc_playlist_h> new_playlists_map;
+    std::string serverName = args.get(kServerName).get<std::string>();
+    auto result = utils::GetAllPlaylistsHandles(serverName, &new_playlists_map);
     if (!result) {
       LogAndReportError(result, &response_obj, ("Failed: utils::GetAllPlaylists"));
       Instance::PostMessage(this, response.serialize().c_str());
       return;
     }
+    // update the list of stored handles
+    utils::UpdatePlaylistHandleMap(serverName, new_playlists_map, server_playlist_map_);
+    picojson::value playlists = utils::CreatePlaylistsJSON(serverName, new_playlists_map);
 
     response_obj[kResult] = picojson::value{playlists};
     ReportSuccess(response_obj);
@@ -1771,8 +1835,26 @@ void MediaControllerInstance::MediaControllerPlaylistAddItem(const picojson::val
 
   const picojson::object& metadata = args.get(kMetadata).get<picojson::object>();
 
-  auto result = server_->MediaControllerPlaylistAddItem(
-      args.get(kName).get<std::string>(), args.get(kIndex).get<std::string>(), metadata);
+  auto name = args.get(kName).get<std::string>();
+
+  std::string serverName = "";
+  if (args.contains(kServerName)) {
+    serverName = args.get(kServerName).get<std::string>();
+  } else {
+    serverName = common::CurrentApplication::GetInstance().GetApplicationId();
+  }
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+  if (server_playlist_map_.find(serverName) == server_playlist_map_.end() ||
+      server_playlist_map_[serverName].find(name) == server_playlist_map_[serverName].end()) {
+    result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Playlist with given name doesn't exist");
+    LogAndReportError(result, &out);
+    return;
+  }
+
+  result = server_->MediaControllerPlaylistAddItem(server_playlist_map_[serverName][name],
+                                                   args.get(kIndex).get<std::string>(), metadata);
   if (!result) {
     LogAndReportError(result, &out);
     return;
@@ -1785,15 +1867,9 @@ void MediaControllerInstance::MediaControllerPlaylistGetItems(const picojson::va
                                                               picojson::object& out) {
   ScopeLogger();
 
-  // MediaControllerPlaylistGetItems is implemented in MediaControllerServer because
-  // mc_playlist_foreach_item need mc_playlist_h as parameter which is already stored in server
-  if (!server_) {
-    LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
-                      (MediaControllerServerUnknownErrorMsg));
-    return;
-  }
   CHECK_EXIST(args, kCallbackId, out)
   CHECK_ARGS(args, kName, std::string, out)
+  CHECK_ARGS(args, kServerName, std::string, out)
 
   auto get = [this, args]() -> void {
     picojson::value response = picojson::value(picojson::object());
@@ -1803,12 +1879,24 @@ void MediaControllerInstance::MediaControllerPlaylistGetItems(const picojson::va
 
     picojson::value items{picojson::array{}};
 
-    auto result = server_->MediaControllerPlaylistGetItems(args.get(kName).get<std::string>(),
-                                                           &items.get<picojson::array>());
+    auto name = args.get(kName).get<std::string>();
+    auto serverName = args.get(kServerName).get<std::string>();
 
-    if (!result) {
+    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+    if (server_playlist_map_.find(serverName) == server_playlist_map_.end() ||
+        server_playlist_map_[serverName].find(name) == server_playlist_map_[serverName].end()) {
+      result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Playlist with given name doesn't exist");
       LogAndReportError(result, &response_obj,
-                        ("Failed: server_->MediaControllerPlaylistGetItems"));
+                        ("Failed: MediaControllerInstance::MediaControllerPlaylistGetItems"));
+      Instance::PostMessage(this, response.serialize().c_str());
+      return;
+    }
+
+    result = utils::MediaControllerPlaylistGetItems(server_playlist_map_[serverName][name],
+                                                    &items.get<picojson::array>());
+    if (!result) {
+      LogAndReportError(result, &response_obj, ("Failed: utils::MediaControllerPlaylistGetItems"));
       Instance::PostMessage(this, response.serialize().c_str());
       return;
     }
index b73765a96cc03e918754642c5087ed94892cf9c8..4a4c957bee84a4189f2953491a00dd5018ea2237 100644 (file)
@@ -190,6 +190,7 @@ class MediaControllerInstance : public common::ParsedInstance {
 
   std::shared_ptr<MediaControllerClient> client_;
   std::shared_ptr<MediaControllerServer> server_;
+  std::map<std::string, PlaylistHandleMap> server_playlist_map_;
 };
 
 }  // namespace mediacontroller
index 71d61f3f8945d3b9c60ab4d9ef830b37b6bcab86..88b74bc193361b5a5f999f137708fbb608830da2 100644 (file)
@@ -93,14 +93,9 @@ MediaControllerServer::~MediaControllerServer() {
     LoggerE("Failed to unset event reply received callback");
   }
 
-  for (auto const& v : playlist_handle_map_) {
-    if (MEDIA_CONTROLLER_ERROR_NONE != mc_playlist_destroy(v.second)) {
-      LoggerE("Unable to destroy playlist %s", v.first.c_str());
-    }
-  }
-
   {
     std::lock_guard<std::mutex> lock(handle_mutex_);
+
     if (nullptr != handle_ && MEDIA_CONTROLLER_ERROR_NONE != mc_server_destroy(handle_)) {
       LoggerE("Unable to destroy media controller server");
     }
@@ -527,15 +522,12 @@ PlatformResult MediaControllerServer::UnsetCommandListener() {
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult MediaControllerServer::CreatePlaylist(const std::string& name,
-                                                     picojson::value* playlist_info) {
+PlatformResult MediaControllerServer::CreatePlaylist(const std::string& serverName,
+                                                     const std::string& name,
+                                                     picojson::value* playlist_info,
+                                                     mc_playlist_h& playlist_handle) {
   ScopeLogger();
 
-  if (playlist_handle_map_.find(name) != playlist_handle_map_.end()) {
-    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
-                              "Playlist with given name already exists");
-  }
-
   mc_playlist_h playlist_handle_ = nullptr;
 
   int ret = mc_server_create_playlist(handle_, name.c_str(), &playlist_handle_);
@@ -546,7 +538,7 @@ PlatformResult MediaControllerServer::CreatePlaylist(const std::string& name,
         ("mc_server_create_playlist() error: %d, message: %s", ret, get_error_message(ret)));
   }
 
-  playlist_handle_map_[name] = playlist_handle_;
+  playlist_handle = playlist_handle_;
 
   if (playlist_info == nullptr) {
     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to createPlaylist",
@@ -556,20 +548,16 @@ PlatformResult MediaControllerServer::CreatePlaylist(const std::string& name,
   *playlist_info = picojson::value(picojson::object());
   picojson::object& obj = playlist_info->get<picojson::object>();
   obj[kName] = picojson::value(name);
+  obj[kServerName] = picojson::value(serverName);
 
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult MediaControllerServer::SavePlaylist(const std::string& name) {
+PlatformResult MediaControllerServer::SavePlaylist(const mc_playlist_h& playlist_handle) {
   ScopeLogger();
 
-  if (playlist_handle_map_.find(name) == playlist_handle_map_.end()) {
-    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
-                              "Playlist with given name doesn't exist");
-  }
-
   std::lock_guard<std::mutex> lock(handle_mutex_);
-  int ret = mc_server_update_playlist_done(handle_, playlist_handle_map_[name]);
+  int ret = mc_server_update_playlist_done(handle_, playlist_handle);
 
   if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
     return LogAndCreateResult(
@@ -580,16 +568,11 @@ PlatformResult MediaControllerServer::SavePlaylist(const std::string& name) {
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult MediaControllerServer::DeletePlaylist(const std::string& name) {
+PlatformResult MediaControllerServer::DeletePlaylist(const mc_playlist_h& playlist_handle) {
   ScopeLogger();
 
-  if (playlist_handle_map_.find(name) == playlist_handle_map_.end()) {
-    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
-                              "Playlist with given name doesn't exist");
-  }
-
   std::lock_guard<std::mutex> lock(handle_mutex_);
-  int ret = mc_server_delete_playlist(handle_, playlist_handle_map_[name]);
+  int ret = mc_server_delete_playlist(handle_, playlist_handle);
 
   if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
     return LogAndCreateResult(
@@ -597,8 +580,6 @@ PlatformResult MediaControllerServer::DeletePlaylist(const std::string& name) {
         ("mc_server_delete_playlist() error: %d, message: %s", ret, get_error_message(ret)));
   }
 
-  playlist_handle_map_.erase(name);
-
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
@@ -636,13 +617,10 @@ common::PlatformResult MediaControllerServer::UpdateIconURI(const char* icon_uri
 }
 
 PlatformResult MediaControllerServer::MediaControllerPlaylistAddItem(
-    const std::string& name, const std::string& index, const picojson::object& metadata) {
+    const mc_playlist_h& playlist_handle, const std::string& index,
+    const picojson::object& metadata) {
   ScopeLogger();
 
-  if (playlist_handle_map_.find(name) == playlist_handle_map_.end()) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Playlist with given name doesn't exist");
-  }
-
   picojson::object encoded;
   PlatformResult result = utils::EncodeMetadata(metadata, &encoded);
   if (!result) {
@@ -653,8 +631,8 @@ PlatformResult MediaControllerServer::MediaControllerPlaylistAddItem(
     std::string value = encoded[v.first].get<std::string>();
     LoggerD("Key: %s - Value: %s", v.first.c_str(), value.c_str());
 
-    int ret = mc_server_add_item_to_playlist(handle_, playlist_handle_map_[name], index.c_str(),
-                                             v.second, value.c_str());
+    int ret = mc_server_add_item_to_playlist(handle_, playlist_handle, index.c_str(), v.second,
+                                             value.c_str());
     if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
       return LogAndCreateResult(
           ErrorCode::UNKNOWN_ERR, "Error adding playlist item",
@@ -665,49 +643,6 @@ PlatformResult MediaControllerServer::MediaControllerPlaylistAddItem(
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult MediaControllerServer::MediaControllerPlaylistGetItems(const std::string& name,
-                                                                      picojson::array* items) {
-  ScopeLogger();
-
-  if (playlist_handle_map_.find(name) == playlist_handle_map_.end()) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Playlist with given name doesn't exist");
-  }
-
-  auto OnPlaylistItemCommand = [](const char* index, mc_metadata_h metadata,
-                                  void* user_data) -> bool {
-    ScopeLogger();
-
-    auto items = static_cast<picojson::array*>(user_data);
-
-    picojson::value metadata_v = picojson::value(picojson::object());
-    picojson::object& metadata_obj = metadata_v.get<picojson::object>();
-
-    auto result = types::ConvertMetadata(metadata, &metadata_obj);
-    if (!result) {
-      return false;
-    }
-
-    picojson::value value = picojson::value(picojson::object());
-    picojson::object& obj = value.get<picojson::object>();
-
-    obj.insert(std::make_pair(kIndex, picojson::value{index}));
-    obj.insert(std::make_pair(kMetadata, metadata_v));
-    items->push_back(value);
-
-    return true;
-  };
-
-  int ret = mc_playlist_foreach_item(playlist_handle_map_[name], OnPlaylistItemCommand, items);
-
-  if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
-    return LogAndCreateResult(
-        ErrorCode::UNKNOWN_ERR, "Error while get playlist item",
-        ("mc_playlist_foreach_item() error: %d, message: %s", ret, get_error_message(ret)));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
 PlatformResult MediaControllerServer::SetPlaybackAbility(const std::string& action,
                                                          const std::string& support_str,
                                                          bool* is_changed) {
index a9af3040143d6ef2de75c00e6f3cfe8f2e8416d3..83ee0863eb82e36f1f8c5782b300e2ff4510a5a0 100644 (file)
@@ -54,16 +54,17 @@ class MediaControllerServer {
   common::PlatformResult SetCommandListener(const JsonCallback& callback);
   common::PlatformResult UnsetCommandListener();
 
-  common::PlatformResult CreatePlaylist(const std::string& name, picojson::value* playlist_info);
-  common::PlatformResult SavePlaylist(const std::string& name);
-  common::PlatformResult DeletePlaylist(const std::string& name);
+  common::PlatformResult CreatePlaylist(const std::string& serverName, const std::string& name,
+                                        picojson::value* playlist_info,
+                                        mc_playlist_h& playlist_handle);
+  common::PlatformResult SavePlaylist(const mc_playlist_h& playlist_handle);
+  common::PlatformResult DeletePlaylist(const mc_playlist_h& playlist_handle);
   common::PlatformResult UpdatePlaybackItem(const std::string& name, const std::string& index);
 
-  common::PlatformResult MediaControllerPlaylistAddItem(const std::string& name,
+  common::PlatformResult MediaControllerPlaylistAddItem(const mc_playlist_h& playlist_handle,
                                                         const std::string& index,
                                                         const picojson::object& metadata);
-  common::PlatformResult MediaControllerPlaylistGetItems(const std::string& name,
-                                                         picojson::array* items);
+
   common::PlatformResult UpdateIconURI(const char* icon_uri);
   common::PlatformResult SetPlaybackAbility(const std::string& action,
                                             const std::string& support_str, bool* is_changed);
@@ -124,8 +125,6 @@ class MediaControllerServer {
   bool is_repeat_mode_set_;
   std::map<std::string, mc_ability_support_e> abilities_;
 
-  std::map<std::string, mc_playlist_h> playlist_handle_map_;
-
   static void OnPlaybackActionCommand(const char* client_name, const char* request_id,
                                       mc_playback_action_e action, void* user_data);
   static void OnPlaybackPositionCommand(const char* client_name, const char* request_id,
index 7c6404b28b1b4669c7dd5aa724bcb89e76d70437..ddd4ba88da0a23a2dd7d371dea84f8e010aa5804 100644 (file)
@@ -381,6 +381,121 @@ PlatformResult utils::GetAllPlaylists(const std::string& app_id, picojson::array
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
+PlatformResult utils::GetAllPlaylistsHandles(const std::string& app_id,
+                                             std::map<std::string, mc_playlist_h>* playlists) {
+  ScopeLogger();
+
+  auto OnPlaylists = [](mc_playlist_h playlist, void* user_data) -> bool {
+    char* name = nullptr;
+
+    SCOPE_EXIT {
+      free(name);
+    };
+
+    int ret = mc_playlist_get_name(playlist, &name);
+    if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+      return false;
+    }
+
+    auto playlists = static_cast<std::map<std::string, mc_playlist_h>*>(user_data);
+    mc_playlist_h playlist_cpy = nullptr;
+    ret = mc_playlist_clone(playlist, &playlist_cpy);
+    if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+      return false;
+    }
+    (*playlists)[name] = playlist_cpy;
+
+    return true;
+  };
+
+  int ret = mc_playlist_foreach_playlist(app_id.c_str(), OnPlaylists, playlists);
+
+  if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Error while get playlists",
+        ("mc_playlist_foreach_playlist() error: %d, message: %s", ret, get_error_message(ret)));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+picojson::value utils::CreatePlaylistsJSON(const std::string& app_id,
+                                           const std::map<std::string, mc_playlist_h>& playlists) {
+  ScopeLogger();
+  picojson::value playlists_json{picojson::array{}};
+  picojson::array& playlists_array = playlists_json.get<picojson::array>();
+  for (const auto& v : playlists) {
+    picojson::value value = picojson::value(picojson::object());
+    picojson::object& obj = value.get<picojson::object>();
+    obj.insert(std::make_pair(kName, picojson::value{v.first}));
+    obj.insert(std::make_pair(kServerName, picojson::value{app_id}));
+    playlists_array.push_back(value);
+  }
+  return playlists_json;
+}
+
+void utils::UpdatePlaylistHandleMap(const std::string& serverName,
+                                    const std::map<std::string, mc_playlist_h>& to_update,
+                                    std::map<std::string, PlaylistHandleMap>& server_playlist_map) {
+  ScopeLogger();
+
+  if (server_playlist_map.find(serverName) != server_playlist_map.end()) {
+    // drop all old saved elements
+    for (auto const& v : server_playlist_map[serverName]) {
+      if (MEDIA_CONTROLLER_ERROR_NONE != mc_playlist_destroy(v.second)) {
+        LoggerW("Unable to destroy playlist %s handle", v.first.c_str());
+      }
+    }
+    server_playlist_map.erase(serverName);
+  }
+
+  // save new elements
+  for (auto const& u : to_update) {
+    server_playlist_map[serverName][u.first] = u.second;
+  }
+}
+
+PlatformResult utils::GetPlaylist(const std::string& app_id, const std::string& playlist_name,
+                                  picojson::object* playlist_obj, mc_playlist_h* handle) {
+  ScopeLogger();
+
+  if (nullptr == playlist_obj) {
+    LoggerE("playlist_obj is nullptr, skipping");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error while getting a playlist named " + playlist_name);
+  }
+
+  mc_playlist_h playlist_item = nullptr;
+  SCOPE_EXIT {
+    if (!handle) {
+      mc_playlist_destroy(playlist_item);
+    }
+  };
+
+  int ret = mc_playlist_get_playlist(app_id.c_str(), playlist_name.c_str(), &playlist_item);
+
+  if (MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER == ret) {
+    return LogAndCreateResult(
+        ErrorCode::NOT_FOUND_ERR,
+        "A playlist named " + playlist_name + " does not exist on the server " + app_id,
+        ("mc_playlist_get_playlist() error: %d, message: %s", ret, get_error_message(ret)));
+  }
+
+  if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Error while getting a playlist named " + playlist_name,
+        ("mc_playlist_get_playlist() error: %d, message: %s", ret, get_error_message(ret)));
+  }
+
+  (*playlist_obj)[kName] = picojson::value(playlist_name);
+  if (handle && handle != playlist_item) {
+    mc_playlist_destroy(*handle);
+    *handle = playlist_item;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 ErrorCode utils::ConvertMediaControllerError(int e) {
   ScopeLogger();
   ErrorCode error;
@@ -396,6 +511,45 @@ ErrorCode utils::ConvertMediaControllerError(int e) {
   return error;
 }
 
+PlatformResult utils::MediaControllerPlaylistGetItems(const mc_playlist_h playlist_handle,
+                                                      picojson::array* items) {
+  ScopeLogger();
+
+  auto OnPlaylistItemCommand = [](const char* index, mc_metadata_h metadata,
+                                  void* user_data) -> bool {
+    ScopeLogger();
+
+    auto items = static_cast<picojson::array*>(user_data);
+
+    picojson::value metadata_v = picojson::value(picojson::object());
+    picojson::object& metadata_obj = metadata_v.get<picojson::object>();
+
+    auto result = types::ConvertMetadata(metadata, &metadata_obj);
+    if (!result) {
+      return false;
+    }
+
+    picojson::value value = picojson::value(picojson::object());
+    picojson::object& obj = value.get<picojson::object>();
+
+    obj.insert(std::make_pair(kIndex, picojson::value{index}));
+    obj.insert(std::make_pair(kMetadata, metadata_v));
+    items->push_back(value);
+
+    return true;
+  };
+
+  int ret = mc_playlist_foreach_item(playlist_handle, OnPlaylistItemCommand, items);
+
+  if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Error while get playlist item",
+        ("mc_playlist_foreach_item() error: %d, message: %s", ret, get_error_message(ret)));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 bool utils::isMetadataAttributeEncodable(const std::string& name) {
   return name == kSeason || name == kEpisode || name == kResolution;
 }
index e1f54625c18961beb77e2d3ed08bb3c4100154aa..ba7ea5d27e38ad1b68e98fb36feff702ed0f38ae 100644 (file)
@@ -29,6 +29,7 @@ namespace extension {
 namespace mediacontroller {
 
 typedef std::function<void(picojson::value*)> JsonCallback;
+typedef std::map<std::string, mc_playlist_h> PlaylistHandleMap;
 
 namespace privileges {
 
@@ -121,7 +122,19 @@ extern const common::PlatformEnum<mc_display_rotation_e> MediaControllerDisplayR
 
 namespace utils {
 common::PlatformResult GetAllPlaylists(const std::string& app_id, picojson::array* playlists);
+common::PlatformResult GetAllPlaylistsHandles(const std::string& app_id,
+                                              std::map<std::string, mc_playlist_h>* playlists);
+picojson::value CreatePlaylistsJSON(const std::string& app_id,
+                                    const std::map<std::string, mc_playlist_h>& playlists);
+void UpdatePlaylistHandleMap(const std::string& app_id,
+                             const std::map<std::string, mc_playlist_h>& to_update,
+                             std::map<std::string, PlaylistHandleMap>& server_playlist_map);
+common::PlatformResult GetPlaylist(const std::string& app_id, const std::string& playlist_name,
+                                   picojson::object* playlist_obj, mc_playlist_h* handle = nullptr);
 common::ErrorCode ConvertMediaControllerError(int e);
+common::PlatformResult MediaControllerPlaylistGetItems(const mc_playlist_h playlist_handle,
+                                                       picojson::array* items);
+
 bool isMetadataAttributeEncodable(const std::string& name);
 common::PlatformResult EncodeMetadata(const picojson::object& to_encode, picojson::object* encoded);
 common::PlatformResult DecodeMetadata(const picojson::value& to_decode, picojson::object* decoded);