[MediaController] Client playback info change listener
authorRafal Galka <r.galka@samsung.com>
Tue, 28 Apr 2015 10:22:32 +0000 (12:22 +0200)
committerRafal Galka <r.galka@samsung.com>
Tue, 28 Apr 2015 10:23:37 +0000 (19:23 +0900)
Change-Id: Ia81805e2bf709f15b996baf7b1bcda0c9eb02ff4
Signed-off-by: Rafal Galka <r.galka@samsung.com>
src/mediacontroller/mediacontroller_api.js
src/mediacontroller/mediacontroller_client.cc
src/mediacontroller/mediacontroller_client.h
src/mediacontroller/mediacontroller_instance.cc
src/mediacontroller/mediacontroller_server.cc
src/mediacontroller/mediacontroller_types.cc
src/mediacontroller/mediacontroller_types.h

index 8fa58d1..9d296db 100644 (file)
@@ -17,16 +17,16 @@ function ListenerManager(native, listenerName, handle) {
   this.nativeSet = false;
   this.native = native;
   this.listenerName = listenerName;
-  this.handle = handle || function(){};
+  this.handle = handle || function(msg, listener, watchId) {};
 }
 
 ListenerManager.prototype.addListener = function(callback, data) {
   var id = this.nextId;
   if (!this.nativeSet) {
     this.native.addListener(this.listenerName, function(msg) {
-      for (var key in this.listeners) {
-        if (this.listeners.hasOwnProperty(key)) {
-          this.handle(msg, this.listeners[key], key);
+      for (var watchId in this.listeners) {
+        if (this.listeners.hasOwnProperty(watchId)) {
+          this.handle(msg, this.listeners[watchId], watchId);
         }
       }
     }.bind(this));
@@ -92,7 +92,15 @@ var ServerInfoStatusListener = new ListenerManager(native_, '_ServerInfoStatusLi
 });
 
 var ServerInfoPlaybackInfoListener = new ListenerManager(native_, '_ServerInfoPlaybackInfoListener', function(msg, listener) {
-  listener(msg.status);
+  if (msg.action === 'onplaybackchanged') {
+    listener[msg.action](msg.state, msg.position);
+  }
+  if (msg.action === 'onshufflemodechanged' || msg.action === 'onrepeatmodechanged') {
+    listener[msg.action](msg.mode);
+  }
+  if (msg.action === 'onmetadatachanged') {
+    listener[msg.action](new MediaControllerMetadata(msg.metadata));
+  }
 });
 
 var EditManager = function() {
@@ -136,8 +144,7 @@ MediaControllerManager.prototype.getClient = function() {
     throw native_.getErrorObject(result);
   }
 
-  var client = new MediaControllerClient(native_.getResultObject(result));
-  return client;
+  return new MediaControllerClient(native_.getResultObject(result));
 };
 
 MediaControllerManager.prototype.createServer = function() {
@@ -146,8 +153,7 @@ MediaControllerManager.prototype.createServer = function() {
     throw native_.getErrorObject(result);
   }
 
-  var server = new MediaControllerServer(native_.getResultObject(result));
-  return server;
+  return new MediaControllerServer(native_.getResultObject(result));
 };
 
 
@@ -223,7 +229,7 @@ var MediaControllerMetadata = function(data) {
 
   if (data instanceof Object) {
     for (var prop in data) {
-      if (this.hasOwnProperty(prop)) {
+      if (data.hasOwnProperty(prop) && this.hasOwnProperty(prop)) {
         this[prop] = data[prop];
       }
     }
@@ -676,12 +682,22 @@ MediaControllerServerInfo.prototype.removeServerStatusChangeListener = function(
 };
 
 MediaControllerServerInfo.prototype.addPlaybackInfoChangeListener = function(listener) {
-  var args = validator_.validateArgs(arguments, [
-    {name: 'listener', type: types_.LISTENER, values: ['onplaybackstatechanged', 'onplaybackpositionchanged', 'onshufflemodechanged', 'onrepeatmodechanged', 'onmetadatachanged']}
-  ]);
+  var args = validator_.validateArgs(arguments, [{
+    name: 'listener',
+    type: types_.LISTENER,
+    values: [
+      'onplaybackchanged',
+      'onshufflemodechanged',
+      'onrepeatmodechanged',
+      'onmetadatachanged'
+    ]
+  }]);
 
   if (type_.isEmptyObject(ServerInfoPlaybackInfoListener.listeners)) {
-    var result = native_.callSync('MediaControllerServerInfo_addPlaybackInfoChangeListener');
+    var result = native_.callSync(
+        'MediaControllerServerInfo_addPlaybackInfoChangeListener', {
+          listenerId: ServerInfoPlaybackInfoListener.listenerName
+        });
     if (native_.isFailure(result)) {
       throw native_.getErrorObject(result);
     }
index 12915b0..282dc67 100644 (file)
@@ -19,8 +19,6 @@ MediaControllerClient::MediaControllerClient() : handle_(nullptr) {
 }
 
 MediaControllerClient::~MediaControllerClient() {
-  LOGGER(DEBUG) << "entered";
-
   if (handle_) {
     int ret = mc_client_destroy(handle_);
     if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
@@ -30,20 +28,17 @@ MediaControllerClient::~MediaControllerClient() {
 }
 
 PlatformResult MediaControllerClient::Init() {
-  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
-
   int ret = mc_client_create(&handle_);
   if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
     LOGGER(ERROR) << "Unable to create media controller client, error: " << ret;
-    result = PlatformResult(ErrorCode::UNKNOWN_ERR,
-                            "Unable to create media controller client");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unable to create media controller client");
   }
 
-  return result;
+  return PlatformResult(ErrorCode::NO_ERROR);
 }
 
 PlatformResult MediaControllerClient::FindServers(picojson::array* servers) {
-  LOGGER(DEBUG) << "entered";
 
   int ret;
 
@@ -70,9 +65,9 @@ PlatformResult MediaControllerClient::FindServers(picojson::array* servers) {
   const std::string& latest_name = latest_server.get("name").get<std::string>();
 
   // update current server state in list
-  for (picojson::array::iterator it; it != servers->end(); ++it) {
-    picojson::object& server = it->get<picojson::object>();
-    if (it->get("name").get<std::string>() == latest_name) {
+  for (auto& it : *servers) {
+    picojson::object& server = it.get<picojson::object>();
+    if (server["name"].get<std::string>() == latest_name) {
       server["state"] = latest_server.get("state");
       break;
     }
@@ -83,7 +78,6 @@ PlatformResult MediaControllerClient::FindServers(picojson::array* servers) {
 
 bool MediaControllerClient::FindServersCallback(const char* server_name,
                                                 void* user_data) {
-  LOGGER(DEBUG) << "entered";
 
   picojson::array* servers = static_cast<picojson::array*>(user_data);
 
@@ -158,33 +152,19 @@ PlatformResult MediaControllerClient::GetPlaybackInfo(
   };
 
   // playback state
-  mc_playback_states_e state;
-  ret = mc_client_get_playback_state(playback_h, &state);
-  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-    LOGGER(ERROR) << "mc_client_get_playback_state failed, error: " << ret;
-    return PlatformResult(ErrorCode::UNKNOWN_ERR,
-                          "Error getting playback state");
-  }
-  if (state == MEDIA_PLAYBACK_STATE_NONE) {
-    state = MEDIA_PLAYBACK_STATE_STOPPED;
-  }
-
-  std::string state_str;
-  PlatformResult result = Types::PlatformEnumToString(
-      Types::kMediaControllerPlaybackState,
-      static_cast<int>(state), &state_str);
+  std::string state;
+  PlatformResult result = Types::ConvertPlaybackState(playback_h, &state);
   if (!result) {
-    LOGGER(ERROR) << "PlatformEnumToString failed, error: " << result.message();
+    LOGGER(ERROR) << "ConvertPlaybackState failed, error: " << result.message();
     return result;
   }
 
   // playback position
-  unsigned long long position;
-  ret = mc_client_get_playback_position(playback_h, &position);
-  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-    LOGGER(ERROR) << "mc_client_get_playback_position failed, error: " << ret;
-    return PlatformResult(ErrorCode::UNKNOWN_ERR,
-                          "Error getting playback position");
+  double position;
+  result = Types::ConvertPlaybackPosition(playback_h, &position);
+  if (!result) {
+    LOGGER(ERROR) << "ConvertPlaybackPosition failed, error: " << result.message();
+    return result;
   }
 
   // shuffle mode
@@ -215,8 +195,8 @@ PlatformResult MediaControllerClient::GetPlaybackInfo(
   }
 
   // fill return object
-  (*playback_info)["state"] = picojson::value(state_str);
-  (*playback_info)["position"] = picojson::value(static_cast<double>(position));
+  (*playback_info)["state"] = picojson::value(state);
+  (*playback_info)["position"] = picojson::value(position);
   (*playback_info)["shuffleMode"] = picojson::value(shuffle == SHUFFLE_MODE_ON);
   (*playback_info)["repeatMode"] = picojson::value(repeat == REPEAT_MODE_ON);
   (*playback_info)["metadata"] = metadata;
@@ -227,7 +207,6 @@ PlatformResult MediaControllerClient::GetPlaybackInfo(
 PlatformResult MediaControllerClient::GetMetadata(
     const std::string& server_name,
     picojson::object* metadata) {
-  LOGGER(DEBUG) << "entered";
 
   int ret;
 
@@ -244,36 +223,193 @@ PlatformResult MediaControllerClient::GetMetadata(
     mc_client_destroy_metadata(metadata_h);
   };
 
-  std::map<std::string, int> metadata_fields;
-  PlatformResult result = Types::GetPlatformEnumMap(
-      Types::kMediaControllerMetadataAttribute, &metadata_fields);
+  PlatformResult result = Types::ConvertMetadata(metadata_h, metadata);
   if (!result) {
-    LOGGER(ERROR) << "GetPlatformEnumMap failed, error: " << result.message();
     return result;
   }
 
-  char* value = nullptr;
-  SCOPE_EXIT {
-    free(value);
-  };
-  for (auto& field : metadata_fields) {
-    ret = mc_client_get_metadata(metadata_h,
-                                 static_cast<mc_meta_e>(field.second),
-                                 &value);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerClient::SetPlaybackInfoListener(
+    JsonCallback callback) {
+
+  if (callback && playback_info_listener_) {
+    LOGGER(ERROR) << "Listener already registered";
+    return PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                          "Listener already registered");
+  }
+
+  playback_info_listener_ = callback;
+
+  int ret;
+  if (callback) { // set platform callbacks
+
+    ret = mc_client_set_playback_update_cb(handle_, OnPlaybackUpdate, this);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to register playback listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to register playback listener");
+    }
+
+    ret = mc_client_set_shuffle_mode_update_cb(handle_, OnShuffleModeUpdate, this);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to register shuffle mode listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to register shuffle mode listener");
+    }
+
+    ret = mc_client_set_repeat_mode_update_cb(handle_, OnRepeatModeUpdate, this);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to register repeat mode listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to register repeat mode listener");
+    }
+
+    ret = mc_client_set_metadata_update_cb(handle_, OnMetadataUpdate, this);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to register metadata listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to register metadata listener");
+    }
+
+  } else { // unset platform callbacks
+
+    ret = mc_client_unset_playback_update_cb(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to unregister playback listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to unregister playback listener");
+    }
+
+    ret = mc_client_unset_shuffle_mode_update_cb(handle_);
     if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
-      LOGGER(ERROR) << "mc_client_get_metadata failed for field '"
-          << field.first << "', error: " << ret;
+      LOGGER(ERROR) << "Unable to unregister shuffle mode listener, error: " << ret;
       return PlatformResult(ErrorCode::UNKNOWN_ERR,
-                            "Error getting metadata");
+                            "Unable to unregister shuffle mode listener");
     }
-    if (!value) {
-      value = strdup("");
+
+    ret = mc_client_unset_repeat_mode_update_cb(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to unregister repeat mode listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to unregister repeat mode listener");
     }
 
-    (*metadata)[field.first] = picojson::value(std::string(value));
+    ret = mc_client_unset_metadata_update_cb(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to unregister metadata listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to unregister metadata listener");
+    }
   }
 
   return PlatformResult(ErrorCode::NO_ERROR);
+};
+
+void MediaControllerClient::OnPlaybackUpdate(const char *server_name,
+                                             mc_playback_h playback,
+                                             void *user_data) {
+
+  MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+  if (!client->playback_info_listener_) {
+    LOGGER(DEBUG) << "No playback info listener registered, skipping";
+    return;
+  }
+
+  // playback state
+  std::string state;
+  PlatformResult result = Types::ConvertPlaybackState(playback, &state);
+  if (!result) {
+    LOGGER(ERROR) << "ConvertPlaybackState failed, error: " << result.message();
+    return;
+  }
+
+  // playback position
+  double position;
+  result = Types::ConvertPlaybackPosition(playback, &position);
+  if (!result) {
+    LOGGER(ERROR) << "ConvertPlaybackPosition failed, error: " << result.message();
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["action"] = picojson::value(std::string("onplaybackchanged"));
+  data_o["state"] = picojson::value(state);
+  data_o["position"] = picojson::value(position);
+
+  client->playback_info_listener_(&data);
+}
+
+void MediaControllerClient::OnShuffleModeUpdate(const char *server_name,
+                                             mc_shuffle_mode_e mode,
+                                             void *user_data) {
+
+  MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+  if (!client->playback_info_listener_) {
+    LOGGER(DEBUG) << "No playback info listener registered, skipping";
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["action"] = picojson::value(std::string("onshufflemodechanged"));
+  data_o["mode"] = picojson::value(mode == SHUFFLE_MODE_ON);
+
+  client->playback_info_listener_(&data);
+}
+
+void MediaControllerClient::OnRepeatModeUpdate(const char *server_name,
+                                                mc_repeat_mode_e mode,
+                                                void *user_data) {
+
+  MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+  if (!client->playback_info_listener_) {
+    LOGGER(DEBUG) << "No playback info listener registered, skipping";
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["action"] = picojson::value(std::string("onrepeatmodechanged"));
+  data_o["mode"] = picojson::value(mode == REPEAT_MODE_ON);
+
+  client->playback_info_listener_(&data);
+}
+
+void MediaControllerClient::OnMetadataUpdate(const char* server_name,
+                                             mc_metadata_h metadata_h,
+                                             void* user_data) {
+
+  MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+  if (!client->playback_info_listener_) {
+    LOGGER(DEBUG) << "No playback info listener registered, skipping";
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  picojson::value metadata = picojson::value(picojson::object());
+  PlatformResult result = Types::ConvertMetadata(
+      metadata_h, &metadata.get<picojson::object>());
+  if (!result) {
+    LOGGER(ERROR) << "ConvertMetadata failed, error: " << result.message();
+    return;
+  }
+
+  data_o["action"] = picojson::value(std::string("onmetadatachanged"));
+  data_o["metadata"] = metadata;
+
+  client->playback_info_listener_(&data);
 }
 
 } // namespace mediacontroller
index 939b0ea..f904344 100644 (file)
@@ -10,6 +10,8 @@
 
 #include "common/platform_result.h"
 
+#include "mediacontroller/mediacontroller_types.h"
+
 namespace extension {
 namespace mediacontroller {
 
@@ -26,10 +28,24 @@ class MediaControllerClient {
   common::PlatformResult GetMetadata(const std::string& server_name,
                                          picojson::object* metadata);
 
+  common::PlatformResult SetPlaybackInfoListener(JsonCallback callback);
  private:
   mc_client_h handle_;
+  JsonCallback playback_info_listener_;
 
   static bool FindServersCallback(const char* server_name, void* user_data);
+  static void OnPlaybackUpdate(const char *server_name,
+                               mc_playback_h playback,
+                               void *user_data);
+  static void OnShuffleModeUpdate(const char *server_name,
+                                  mc_shuffle_mode_e mode,
+                                  void *user_data);
+  static void OnRepeatModeUpdate(const char *server_name,
+                                  mc_repeat_mode_e mode,
+                                  void *user_data);
+  static void OnMetadataUpdate(const char* server_name,
+                               mc_metadata_h metadata_h,
+                               void* user_data);
 };
 
 } // namespace mediacontroller
index 7ec9e1f..1cb869c 100644 (file)
@@ -4,13 +4,13 @@
 
 #include "mediacontroller/mediacontroller_instance.h"
 
-#include <functional>
-
 #include "common/logger.h"
 #include "common/picojson.h"
 #include "common/platform_result.h"
 #include "common/task-queue.h"
 
+#include "mediacontroller/mediacontroller_types.h"
+
 namespace extension {
 namespace mediacontroller {
 
@@ -322,7 +322,6 @@ void MediaControllerInstance::MediaControllerClientFindServers(
   CHECK_EXIST(args, "callbackId", out)
 
   auto search = [this, args]() -> void {
-    LOGGER(DEBUG) << "entered";
 
     picojson::value response = picojson::value(picojson::object());
     picojson::object& response_obj = response.get<picojson::object>();
@@ -517,27 +516,43 @@ void MediaControllerInstance::MediaControllerServerInfoAddPlaybackInfoChangeList
     const picojson::value& args,
     picojson::object& out) {
 
-  // implement it
+  if (!client_) {
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
 
-  // if success
-  // ReportSuccess(out);
-  // if error
-  // ReportError(out);
+  CHECK_EXIST(args, "listenerId", out)
+
+  JsonCallback callback = [this, args](picojson::value* data) -> void {
+
+    if (!data) {
+      LOGGER(ERROR) << "No data passed to json callback";
+      return;
+    }
+
+    picojson::object& request_o = data->get<picojson::object>();
+    request_o["listenerId"] = args.get("listenerId");
+
+    PostMessage(data->serialize().c_str());
+  };
+
+  client_->SetPlaybackInfoListener(callback);
+
+  ReportSuccess(out);
 }
 
 void MediaControllerInstance::MediaControllerServerInfoRemovePlaybackInfoChangeListener(
     const picojson::value& args,
     picojson::object& out) {
-  CHECK_EXIST(args, "watchId", out)
 
-  double watchId = args.get("watchId").get<double>();
-
-  // implement it
+  if (!client_) {
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
 
-  // if success
-  // ReportSuccess(out);
-  // if error
-  // ReportError(out);
+  client_->SetPlaybackInfoListener(nullptr);
 }
 
 #undef CHECK_EXIST
index 434d8ab..5ecd7aa 100644 (file)
@@ -18,7 +18,6 @@ MediaControllerServer::MediaControllerServer() : handle_(nullptr) {
 }
 
 MediaControllerServer::~MediaControllerServer() {
-  LOGGER(DEBUG) << "entered";
 
   if (handle_) {
     int ret = mc_server_destroy(handle_);
index 6b5c444..62bf01b 100644 (file)
@@ -4,7 +4,11 @@
 
 #include "mediacontroller/mediacontroller_types.h"
 
+#include <media_controller_client.h>
+
+#include "common/logger.h"
 #include "common/platform_result.h"
+#include "common/scope_exit.h"
 
 namespace extension {
 namespace mediacontroller {
@@ -114,5 +118,83 @@ PlatformResult Types::PlatformEnumToString(const std::string& type,
   return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
 }
 
+PlatformResult Types::ConvertPlaybackState(mc_playback_h playback_h,
+                                           std::string* state) {
+  int ret;
+  mc_playback_states_e state_e;
+  ret = mc_client_get_playback_state(playback_h, &state_e);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_get_playback_state failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error getting playback state");
+  }
+  if (state_e == MEDIA_PLAYBACK_STATE_NONE) {
+    state_e = MEDIA_PLAYBACK_STATE_STOPPED;
+  }
+
+  PlatformResult result = Types::PlatformEnumToString(
+      Types::kMediaControllerPlaybackState,
+      static_cast<int>(state_e), state);
+  if (!result) {
+    LOGGER(ERROR) << "PlatformEnumToString failed, error: " << result.message();
+    return result;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Types::ConvertPlaybackPosition(mc_playback_h playback_h,
+                                              double* position) {
+  int ret;
+
+  unsigned long long pos;
+  ret = mc_client_get_playback_position(playback_h, &pos);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_get_playback_position failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error getting playback position");
+  }
+
+  *position = static_cast<double>(pos);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Types::ConvertMetadata(mc_metadata_h metadata_h,
+                                      picojson::object* metadata) {
+  std::map<std::string, int> metadata_fields;
+  PlatformResult result = GetPlatformEnumMap(
+      Types::kMediaControllerMetadataAttribute, &metadata_fields);
+  if (!result) {
+    LOGGER(ERROR) << "GetPlatformEnumMap failed, error: " << result.message();
+    return result;
+  }
+
+  char* value;
+  SCOPE_EXIT {
+      free(value);
+  };
+
+  int ret;
+  for (auto& field : metadata_fields) {
+    ret = mc_client_get_metadata(metadata_h,
+                                 static_cast<mc_meta_e>(field.second),
+                                 &value);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "mc_client_get_metadata failed for field '"
+          << field.first << "', error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Error getting metadata");
+    }
+    if (NULL == value) {
+      value = strdup("");
+    }
+
+    (*metadata)[field.first] = picojson::value(std::string(value));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 } // namespace mediacontroller
 } // namespace extension
index 1a8209c..72d1a74 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef MEDIACONTROLLER_MEDIACONTROLLER_TYPES_H_
 #define MEDIACONTROLLER_MEDIACONTROLLER_TYPES_H_
 
+#include <functional>
 #include <map>
 #include <media_controller_type.h>
 #include <string>
@@ -16,6 +17,7 @@ namespace mediacontroller {
 
 typedef std::map<std::string, std::map<std::string, int>> PlatformEnumMap;
 typedef std::map<std::string, std::map<int, std::string>> PlatformEnumReverseMap;
+typedef std::function<void(picojson::value*)> JsonCallback;
 
 class Types {
  public:
@@ -34,6 +36,13 @@ class Types {
                                                      int value,
                                                      std::string* platform_str);
 
+  static common::PlatformResult ConvertPlaybackState(mc_playback_h playback_h,
+                                                     std::string* state);
+  static common::PlatformResult ConvertPlaybackPosition(mc_playback_h playback_h,
+                                                        double* position);
+  static common::PlatformResult ConvertMetadata(mc_metadata_h metadata_h,
+                                                picojson::object* metadata);
+
  private:
   static const PlatformEnumMap platform_enum_map_;
   // TODO(r.galka) can be replaced by Boost.Bimap