[mediacontroller] add api for new metadata features 14/214814/5
authorDawid Juszczak <d.juszczak@samsung.com>
Thu, 26 Sep 2019 14:23:22 +0000 (16:23 +0200)
committerDawid Juszczak <d.juszczak@samsung.com>
Mon, 30 Sep 2019 13:42:44 +0000 (15:42 +0200)
[ACR]
http://suprem.sec.samsung.net/jira/browse/TWDAPI-238

[Verification]
tested manually on chrome console
tct-mediacontroller-tizen-tests 100% PASS

Change-Id: I459724bfa88ab9a37a97be55eda0bd2e01e83add
Signed-off-by: Dawid Juszczak <d.juszczak@samsung.com>
src/mediacontroller/mediacontroller_api.js
src/mediacontroller/mediacontroller_server.cc
src/mediacontroller/mediacontroller_utils.cc
src/mediacontroller/mediacontroller_utils.h

index 71bfaf6..2e8576e 100755 (executable)
@@ -423,6 +423,12 @@ var MediaControllerMetadata = function(data) {
     var _description = '';
     var _trackNum = '';
     var _picture = '';
+    var _seasonNumber = 0;
+    var _seasonTitle = null;
+    var _episodeNumber = 0;
+    var _episodeTitle = null;
+    var _resolutionWidth = 0;
+    var _resolutionHeight = 0;
     Object.defineProperties(this, {
         title: {
             get: function() {
@@ -522,6 +528,62 @@ var MediaControllerMetadata = function(data) {
                 _picture = converter_.toString(v);
             },
             enumerable: true
+        },
+        seasonNumber: {
+            get: function() {
+                return _seasonNumber;
+            },
+            set: function(v) {
+                _seasonNumber = converter_.toLong(v);
+            },
+            enumerable: true
+        },
+        seasonTitle: {
+            get: function() {
+                return _seasonTitle;
+            },
+            set: function(v) {
+                _seasonTitle = converter_.toString(v, true);
+            },
+            enumerable: true,
+            nullable: true
+        },
+        episodeNumber: {
+            get: function() {
+                return _episodeNumber;
+            },
+            set: function(v) {
+                _episodeNumber = converter_.toLong(v);
+            },
+            enumerable: true
+        },
+        episodeTitle: {
+            get: function() {
+                return _episodeTitle;
+            },
+            set: function(v) {
+                _episodeTitle = converter_.toString(v, true);
+            },
+            enumerable: true,
+            nullable: true
+        },
+        resolutionWidth: {
+            get: function() {
+                return _resolutionWidth;
+            },
+            set: function(v) {
+                _resolutionWidth = v < 0 ? _resolutionWidth : converter_.toLong(v);
+            },
+            enumerable: true
+        },
+        resolutionHeight: {
+            get: function() {
+                return _resolutionHeight;
+            },
+            set: function(v) {
+                _resolutionHeight = v < 0 ? _resolutionHeight : converter_.toLong(v);
+            },
+            enumerable: true
         }
     });
 
@@ -3592,7 +3654,7 @@ MediaControllerPlaylist.prototype.addItem = function(index, metadata) {
 
     var data = {
         index: args.index,
-        metadata: args.metadata,
+        metadata: new MediaControllerMetadata(args.metadata),
         name: this.name
     };
 
index 1d86a52..2f7629e 100644 (file)
@@ -295,9 +295,15 @@ PlatformResult MediaControllerServer::SetRepeatState(const std::string& state) {
 PlatformResult MediaControllerServer::SetMetadata(const picojson::object& metadata) {
   ScopeLogger();
 
-  for (picojson::object::const_iterator i = metadata.begin(); i != metadata.end(); ++i) {
+  picojson::object encoded;
+  PlatformResult result = utils::EncodeMetadata(metadata, &encoded);
+  if (!result) {
+    return result;
+  }
+
+  for (picojson::object::const_iterator i = encoded.begin(); i != encoded.end(); ++i) {
     mc_meta_e attr_e;
-    PlatformResult result = types::MediaControllerMetadataAttributeEnum.getValue(i->first, &attr_e);
+    result = types::MediaControllerMetadataAttributeEnum.getValue(i->first, &attr_e);
     if (!result) {
       return result;
     }
@@ -613,17 +619,18 @@ PlatformResult MediaControllerServer::MediaControllerPlaylistAddItem(
     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Playlist with given name doesn't exist");
   }
 
-  for (const auto& v : metadata) {
-    LoggerD("Key: %s - Value: %s ", v.first.c_str(), v.second.to_str().c_str());
+  picojson::object encoded;
+  PlatformResult result = utils::EncodeMetadata(metadata, &encoded);
+  if (!result) {
+    return result;
+  }
 
-    mc_meta_e attr_e;
-    PlatformResult result = types::MediaControllerMetadataAttributeEnum.getValue(v.first, &attr_e);
-    if (!result) {
-      return result;
-    }
+  for (auto v : types::MediaControllerMetadataAttributeEnum) {
+    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(),
-                                             attr_e, v.second.to_str().c_str());
+                                             v.second, value.c_str());
     if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
       return LogAndCreateResult(
           ErrorCode::UNKNOWN_ERR, "Error adding playlist item",
index 28fd445..7c5507e 100644 (file)
@@ -61,7 +61,10 @@ const common::PlatformEnum<mc_meta_e> MediaControllerMetadataAttributeEnum{
     {"copyright", MC_META_MEDIA_COPYRIGHT},
     {"description", MC_META_MEDIA_DESCRIPTION},
     {"trackNum", MC_META_MEDIA_TRACK_NUM},
-    {"picture", MC_META_MEDIA_PICTURE}};
+    {"picture", MC_META_MEDIA_PICTURE},
+    {"season", MC_META_MEDIA_SEASON},
+    {"episode", MC_META_MEDIA_EPISODE},
+    {"resolution", MC_META_MEDIA_RESOLUTION}};
 
 const common::PlatformEnum<mc_repeat_mode_e> MediaControllerRepeatModeEnum{
     {"REPEAT_OFF", MC_REPEAT_MODE_OFF},
@@ -126,7 +129,7 @@ const common::PlatformEnum<mc_display_rotation_e> MediaControllerDisplayRotation
     {"ROTATION_180", MC_DISPLAY_ROTATION_180},
     {"ROTATION_270", MC_DISPLAY_ROTATION_270}};
 
-PlatformResult ConvertPlaybackState(mc_playback_h playback_h, std::stringstate) {
+PlatformResult ConvertPlaybackState(mc_playback_h playback_h, std::string *state) {
   ScopeLogger();
 
   int ret;
@@ -151,7 +154,7 @@ PlatformResult ConvertPlaybackState(mc_playback_h playback_h, std::string* state
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult ConvertContentAgeRating(mc_playback_h playback_h, std::stringrating) {
+PlatformResult ConvertContentAgeRating(mc_playback_h playback_h, std::string *rating) {
   ScopeLogger();
 
   mc_content_age_rating_e rating_e = MC_CONTENT_RATING_ALL;
@@ -172,7 +175,7 @@ PlatformResult ConvertContentAgeRating(mc_playback_h playback_h, std::string* ra
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult ConvertContentType(mc_playback_h playback_h, std::stringcontentType) {
+PlatformResult ConvertContentType(mc_playback_h playback_h, std::string *contentType) {
   ScopeLogger();
   mc_content_type_e content_type_e = MC_CONTENT_TYPE_UNDECIDED;
   int ret = mc_client_get_playback_content_type(playback_h, &content_type_e);
@@ -191,7 +194,7 @@ PlatformResult ConvertContentType(mc_playback_h playback_h, std::string* content
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult ConvertPlaybackPosition(mc_playback_h playback_h, doubleposition) {
+PlatformResult ConvertPlaybackPosition(mc_playback_h playback_h, double *position) {
   ScopeLogger();
 
   int ret;
@@ -209,14 +212,17 @@ PlatformResult ConvertPlaybackPosition(mc_playback_h playback_h, double* positio
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult ConvertMetadata(mc_metadata_h metadata_h, picojson::objectmetadata) {
+PlatformResult ConvertMetadata(mc_metadata_h metadata_h, picojson::object *metadata) {
   ScopeLogger();
 
-  charvalue = nullptr;
+  char *value = nullptr;
   SCOPE_EXIT {
     free(value);
   };
 
+  picojson::value to_decode = picojson::value(picojson::object());
+  picojson::object &obj = to_decode.get<picojson::object>();
+
   for (auto entry : MediaControllerMetadataAttributeEnum) {
     int ret = mc_metadata_get(metadata_h, entry.second, &value);
     if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
@@ -225,14 +231,19 @@ PlatformResult ConvertMetadata(mc_metadata_h metadata_h, picojson::object* metad
                                  ret, get_error_message(ret)));
     }
 
-    (*metadata)[entry.first] = picojson::value(std::string(value ? value : ""));
+    obj[entry.first] = picojson::value(value);
+  }
+
+  PlatformResult result = utils::DecodeMetadata(to_decode, metadata);
+  if (!result) {
+    return result;
   }
 
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult ConvertPlaybackAbility(mc_playback_ability_h ability_h, const std::stringaction,
-                                      std::stringability_str) {
+PlatformResult ConvertPlaybackAbility(mc_playback_ability_h ability_h, const std::string &action,
+                                      std::string *ability_str) {
   ScopeLogger();
 
   mc_ability_support_e ability_e;
@@ -268,11 +279,11 @@ PlatformResult ConvertPlaybackAbility(mc_playback_ability_h ability_h, const std
 
 }  // namespace types
 
-PlatformResult utils::GetAllPlaylists(const std::string& app_id, picojson::array* playlists) {
+PlatformResult utils::GetAllPlaylists(const std::string &app_id, picojson::array *playlists) {
   ScopeLogger();
 
-  auto OnPlaylists = [](mc_playlist_h playlist, voiduser_data) -> bool {
-    charname = nullptr;
+  auto OnPlaylists = [](mc_playlist_h playlist, void *user_data) -> bool {
+    char *name = nullptr;
 
     SCOPE_EXIT {
       free(name);
@@ -284,10 +295,10 @@ PlatformResult utils::GetAllPlaylists(const std::string& app_id, picojson::array
       return false;
     }
 
-    auto playlists = static_cast<picojson::array*>(user_data);
+    auto playlists = static_cast<picojson::array *>(user_data);
 
     picojson::value value = picojson::value(picojson::object());
-    picojson::objectobj = value.get<picojson::object>();
+    picojson::object &obj = value.get<picojson::object>();
 
     obj.insert(std::make_pair("name", picojson::value{name}));
     playlists->push_back(value);
@@ -321,5 +332,160 @@ ErrorCode utils::ConvertMediaControllerError(int e) {
   return error;
 }
 
+bool isEncodable(std::string name) {
+  if (name == "season" || name == "episode" || name == "resolution") {
+    return true;
+  }
+  return false;
+}
+
+PlatformResult utils::EncodeMetadata(const picojson::object &to_encode, picojson::object *encoded) {
+  ScopeLogger();
+
+  int ret = 0;
+  char *encoded_value = nullptr;
+  int number = 0;
+
+  SCOPE_EXIT {
+    free(encoded_value);
+  };
+
+  // season
+  try {
+    number = static_cast<int>(to_encode.at("seasonNumber").get<double>());
+    const char *season_title = to_encode.at("seasonTitle").is<picojson::null>()
+                                   ? nullptr
+                                   : to_encode.at("seasonTitle").get<std::string>().c_str();
+
+    ret = mc_metadata_encode_season(number, season_title, &encoded_value);
+    if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+      return LogAndCreateResult(
+          ErrorCode::UNKNOWN_ERR, "Error while encoding season",
+          ("mc_metadata_encode_season() error: %d, message: %s", ret, get_error_message(ret)));
+    }
+
+    (*encoded).insert(std::make_pair("season", picojson::value(encoded_value)));
+  } catch (...) {
+    LoggerE("Season formation missing! - This should never happened.");
+  }
+
+  // episode
+  try {
+    number = static_cast<int>(to_encode.at("episodeNumber").get<double>());
+    const char *episode_title = to_encode.at("episodeTitle").is<picojson::null>()
+                                    ? nullptr
+                                    : to_encode.at("episodeTitle").get<std::string>().c_str();
+
+    ret = mc_metadata_encode_episode(number, episode_title, &encoded_value);
+    if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+      return LogAndCreateResult(
+          ErrorCode::UNKNOWN_ERR, "Error while encoding episode",
+          ("mc_metadata_encode_episode() error: %d, message: %s", ret, get_error_message(ret)));
+    }
+
+    (*encoded).insert(std::make_pair("episode", picojson::value(encoded_value)));
+  } catch (...) {
+    LoggerE("Episode formation missing! - This should never happened.");
+  }
+
+  // resolution
+  try {
+    u_int width = static_cast<u_int>(to_encode.at("resolutionWidth").get<double>());
+    u_int height = static_cast<u_int>(to_encode.at("resolutionHeight").get<double>());
+
+    ret = mc_metadata_encode_resolution(width, height, &encoded_value);
+    if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+      return LogAndCreateResult(
+          ErrorCode::UNKNOWN_ERR, "Error while encoding resolution",
+          ("mc_metadata_encode_resolution() error: %d, message: %s", ret, get_error_message(ret)));
+    }
+
+    (*encoded).insert(std::make_pair("resolution", picojson::value(encoded_value)));
+  } catch (...) {
+    LoggerE("Resolution formation missing! - This should never happened.");
+  }
+
+  // other metadata attributes
+  for (auto entry : types::MediaControllerMetadataAttributeEnum) {
+    std::string name = entry.first;
+    if (name != "season" && name != "episode" && name != "resolution") {
+      try {
+        std::string value_str = to_encode.at(entry.first).get<std::string>();
+        (*encoded).insert(std::make_pair(entry.first, picojson::value(value_str)));
+      } catch (...) {
+        LoggerE("%s formation missing! - This should never happened.", name.c_str());
+      }
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult utils::DecodeMetadata(const picojson::value &to_decode, picojson::object *decoded) {
+  ScopeLogger();
+
+  int ret = 0;
+  int number = 0;
+  char *season_title = nullptr;
+  char *episode_title = nullptr;
+
+  SCOPE_EXIT {
+    free(season_title);
+    free(episode_title);
+  };
+
+  // decode season
+  std::string val = to_decode.get("season").get<std::string>();
+
+  ret = mc_metadata_decode_season(val.c_str(), &number, &season_title);
+  if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Error while decoding season",
+        ("mc_metadata_decode_season() error: %d, message: %s", ret, get_error_message(ret)));
+  }
+
+  (*decoded)["seasonNumber"] = picojson::value((double)number);
+  (*decoded)["episodeTitle"] = season_title ? picojson::value(std::string(season_title)) : picojson::value();
+
+  // decode episode
+  val = to_decode.get("episode").get<std::string>();
+
+  ret = mc_metadata_decode_episode(val.c_str(), &number, &episode_title);
+  if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Error while decoding episode",
+        ("mc_metadata_decode_episode() error: %d, message: %s", ret, get_error_message(ret)));
+  }
+
+  (*decoded)["episodeNumber"] = picojson::value((double)number);
+  (*decoded)["episodeTitle"] = episode_title ? picojson::value(std::string(episode_title)) : picojson::value();
+
+  // decode resolution
+  val = to_decode.get("resolution").get<std::string>();
+  u_int width = 0;
+  u_int height = 0;
+
+  ret = mc_metadata_decode_resolution(val.c_str(), &width, &height);
+  if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Error while decoding resolution",
+        ("mc_metadata_decode_resolution() error: %d, message: %s", ret, get_error_message(ret)));
+  }
+
+  (*decoded)["resolutionWidth"] = picojson::value((double)width);
+  (*decoded)["resolutionHeight"] = picojson::value((double)height);
+
+  // now rewrite not encoded attributes
+  for (auto entry : types::MediaControllerMetadataAttributeEnum) {
+    std::string name = entry.first;
+    // to omit decoded attributes
+    if (!isEncodable(name)) {
+      (*decoded)[name] = to_decode.get(name);
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 }  // namespace mediacontroller
 }  // namespace extension
index 9655659..3922c43 100644 (file)
@@ -59,6 +59,9 @@ extern const common::PlatformEnum<mc_display_rotation_e> MediaControllerDisplayR
 namespace utils {
 common::PlatformResult GetAllPlaylists(const std::string& app_id, picojson::array* playlists);
 common::ErrorCode ConvertMediaControllerError(int e);
+bool isEncodable(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);
 }  // namespace utils
 
 }  // namespace mediacontroller