[MediaController] Client native implementation of:
authorRafal Galka <r.galka@samsung.com>
Tue, 14 Apr 2015 07:57:48 +0000 (09:57 +0200)
committerRafal Galka <r.galka@samsung.com>
Mon, 27 Apr 2015 14:16:32 +0000 (23:16 +0900)
- findServers
- getLatestServerInfo

[Verification] Code compiles.

Change-Id: Ib9aae61b9e5cc5106483b0e8994438fb9f0fbbc5

src/mediacontroller/mediacontroller.gyp
src/mediacontroller/mediacontroller_client.cc [new file with mode: 0644]
src/mediacontroller/mediacontroller_client.h [new file with mode: 0644]
src/mediacontroller/mediacontroller_instance.cc
src/mediacontroller/mediacontroller_instance.h
src/mediacontroller/mediacontroller_types.cc [new file with mode: 0644]
src/mediacontroller/mediacontroller_types.h [new file with mode: 0644]

index 8f6bb1256acc176e0c5e49943da158ade1c14269..679d212072ae28077bc4e6cc27996b9d39756418 100755 (executable)
       ],
       'sources': [
         'mediacontroller_api.js',
+        'mediacontroller_client.cc',
+        'mediacontroller_client.h',
         'mediacontroller_extension.cc',
         'mediacontroller_extension.h',
         'mediacontroller_instance.cc',
         'mediacontroller_instance.h',
+        'mediacontroller_types.cc',
+        'mediacontroller_types.h',
       ],
       'conditions': [
         ['tizen == 1', {
diff --git a/src/mediacontroller/mediacontroller_client.cc b/src/mediacontroller/mediacontroller_client.cc
new file mode 100644 (file)
index 0000000..4d7dfb7
--- /dev/null
@@ -0,0 +1,141 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mediacontroller/mediacontroller_client.h"
+
+#include "common/logger.h"
+#include "common/scope_exit.h"
+
+#include "mediacontroller/mediacontroller_types.h"
+
+namespace extension {
+namespace mediacontroller {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+MediaControllerClient::MediaControllerClient() : handle_(nullptr) {
+}
+
+MediaControllerClient::~MediaControllerClient() {
+  LOGGER(DEBUG) << "entered";
+
+  if (handle_) {
+    int ret = mc_client_destroy(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to destroy media controller client";
+    }
+  }
+}
+
+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 result;
+}
+
+PlatformResult MediaControllerClient::FindServers(picojson::array* servers) {
+  LOGGER(DEBUG) << "entered";
+
+  int ret;
+
+  ret = mc_client_foreach_server(handle_, FindServersCallback, servers);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "Unable to fetch active servers, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unable to create media controller client");
+  }
+
+  // check latest server state - if exist
+  picojson::value latest_server = picojson::value();
+  PlatformResult result = GetLatestServerInfo(&latest_server);
+  if (!result) {
+    LOGGER(ERROR) << "GetLatestServerInfo failed, error: " << result.message();
+    return result;
+  }
+
+  if (latest_server.is<picojson::null>()) {
+    LOGGER(DEBUG) << "No latest server available";
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  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) {
+      server["state"] = latest_server.get("state");
+      break;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+bool MediaControllerClient::FindServersCallback(const char* server_name,
+                                                void* user_data) {
+  LOGGER(DEBUG) << "entered";
+
+  picojson::array* servers = static_cast<picojson::array*>(user_data);
+
+  picojson::value server = picojson::value(picojson::object());
+  picojson::object& server_o = server.get<picojson::object>();
+  server_o["name"] = picojson::value(std::string(server_name));
+  // active by default in CAPI
+  server_o["state"] = picojson::value(std::string("ACTIVE"));
+
+  servers->push_back(server);
+
+  return true;
+}
+
+PlatformResult MediaControllerClient::GetLatestServerInfo(
+    picojson::value* server_info) {
+
+  int ret;
+
+  char* name;
+  mc_server_state_e state;
+  ret = mc_client_get_latest_server_info(handle_, &name, &state);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_get_latest_server_info failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error getting latest server info");
+  }
+
+  if (NULL == name) {
+    LOGGER(DEBUG) << "No active server available";
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  SCOPE_EXIT {
+    free(name);
+  };
+
+  std::string state_str;
+  PlatformResult result = Types::PlatformEnumToString(
+      Types::kMediaControllerServerState, static_cast<int>(state), &state_str);
+  if (!result) {
+    LOGGER(ERROR) << "PlatformEnumToString failed, error: " << result.message();
+    return result;
+  }
+
+  *server_info = picojson::value(picojson::object());
+  picojson::object& obj = server_info->get<picojson::object>();
+  obj["name"] = picojson::value(std::string(name));
+  obj["state"] = picojson::value(state_str);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} // namespace mediacontroller
+} // namespace extension
diff --git a/src/mediacontroller/mediacontroller_client.h b/src/mediacontroller/mediacontroller_client.h
new file mode 100644 (file)
index 0000000..37c2b6d
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIACONTROLLER_MEDIACONTROLLER_CLIENT_H_
+#define MEDIACONTROLLER_MEDIACONTROLLER_CLIENT_H_
+
+#include <media_controller_client.h>
+#include <string>
+
+#include "common/platform_result.h"
+
+namespace extension {
+namespace mediacontroller {
+
+class MediaControllerClient {
+ public:
+  MediaControllerClient();
+  virtual ~MediaControllerClient();
+
+  common::PlatformResult Init();
+  common::PlatformResult FindServers(picojson::array* servers);
+  common::PlatformResult GetLatestServerInfo(picojson::value* server_info);
+
+ private:
+  mc_client_h handle_;
+
+  static bool FindServersCallback(const char* server_name, void* user_data);
+};
+
+} // namespace mediacontroller
+} // namespace extension
+
+#endif  // MEDIACONTROLLER_MEDIACONTROLLER_CLIENT_H_
index 0d87054caf4d7dd88c56e589e5fcef03f7332b35..5cc9724ec61322a4fc5e42abfb7254c393a21b7b 100644 (file)
@@ -9,6 +9,7 @@
 #include "common/logger.h"
 #include "common/picojson.h"
 #include "common/platform_result.h"
+#include "common/task-queue.h"
 
 namespace extension {
 namespace mediacontroller {
@@ -16,14 +17,15 @@ namespace mediacontroller {
 namespace {
 // The privileges required in MediaController API
 const std::string kPrivilegeMediaControllerClient =
-    "http://tizen.org/privilege/mediacontroller.client";
+    "http://tizen.org/privilege/mediacontroller.write";
 const std::string kPrivilegeMediaControllerServer =
-    "http://tizen.org/privilege/mediacontroller.server";
+    "http://tizen.org/privilege/mediacontroller.read";
 
 } // namespace
 
-using common::PlatformResult;
 using common::ErrorCode;
+using common::PlatformResult;
+using common::TaskQueue;
 
 MediaControllerInstance::MediaControllerInstance() {
   using namespace std::placeholders;
@@ -236,41 +238,78 @@ void MediaControllerInstance::MediaControllerManagerGetClient(
     const picojson::value& args,
     picojson::object& out) {
 
-  // implement it
+  if (client_) {
+    ReportSuccess(out);
+    return;
+  }
 
-  // if success
-  // ReportSuccess(out);
-  // if error
-  // ReportError(out);
+  // TODO(r.galka) check privileges
+
+  client_ = std::make_shared<MediaControllerClient>();
+  const PlatformResult& result = client_->Init();
+  if (!result) {
+    client_.reset();
+    ReportError(result, &out);
+  }
+
+  ReportSuccess(out);
 }
 
 void MediaControllerInstance::MediaControllerClientFindServers(
     const picojson::value& args,
     picojson::object& out) {
+
+  if (!client_) {
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
   CHECK_EXIST(args, "callbackId", out)
 
-  int callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  auto search = [this, args]() -> void {
+    LOGGER(DEBUG) << "entered";
 
-  // implement it
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
 
-  // call ReplyAsync in later (Asynchronously)
+    picojson::value servers = picojson::value(picojson::array());
+    PlatformResult result = client_->FindServers(
+        &servers.get<picojson::array>());
 
-  // if success
-  // ReportSuccess(out);
-  // if error
-  // ReportError(out);
+    response_obj["callbackId"] = args.get("callbackId");
+    if (result) {
+      ReportSuccess(servers, response_obj);
+    } else {
+      ReportError(result, &response_obj);
+    }
+
+    PostMessage(response.serialize().c_str());
+  };
+
+  TaskQueue::GetInstance().Async(search);
+
+  ReportSuccess(out);
 }
 
 void MediaControllerInstance::MediaControllerClientGetLatestServerInfo(
     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);
+  picojson::value server_info = picojson::value();
+  PlatformResult result = client_->GetLatestServerInfo(&server_info);
+  if (!result) {
+    ReportError(result, &out);
+    return;
+  }
+
+  ReportSuccess(server_info, out);
 }
 
 void MediaControllerInstance::MediaControllerServerInfoSendPlaybackState(
index 2c62ed12fefd4e089f362ba093c8ee7d4c8ff5fc..0b57c6855a071a086034444ed6282b96ed94c7cf 100644 (file)
@@ -5,8 +5,12 @@
 #ifndef MEDIACONTROLLER_MEDIACONTROLLER_INSTANCE_H_
 #define MEDIACONTROLLER_MEDIACONTROLLER_INSTANCE_H_
 
+#include <memory>
+
 #include "common/extension.h"
 
+#include "mediacontroller/mediacontroller_client.h"
+
 namespace extension {
 namespace mediacontroller {
 
@@ -41,6 +45,8 @@ class MediaControllerInstance : public common::ParsedInstance {
   void MediaControllerServerInfoRemoveServerStatusChangeListener(const picojson::value& args, picojson::object& out);
   void MediaControllerServerInfoAddPlaybackInfoChangeListener(const picojson::value& args, picojson::object& out);
   void MediaControllerServerInfoRemovePlaybackInfoChangeListener(const picojson::value& args, picojson::object& out);
+
+  std::shared_ptr<MediaControllerClient> client_;
 };
 
 } // namespace mediacontroller
diff --git a/src/mediacontroller/mediacontroller_types.cc b/src/mediacontroller/mediacontroller_types.cc
new file mode 100644 (file)
index 0000000..179cd82
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mediacontroller/mediacontroller_types.h"
+
+#include "common/platform_result.h"
+
+namespace extension {
+namespace mediacontroller {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+const std::string Types::kMediaControllerServerState
+    = "MediaControllerServerState";
+const std::string Types::kMediaControllerPlaybackState
+    = "MediaControllerPlaybackState";
+const std::string Types::kMediaControllerMetadataAttribute
+    = "MediaControllerMetadataAttribute";
+
+const PlatformEnumMap Types::platform_enum_map_ = {
+    {kMediaControllerServerState, {
+        {"ACTIVE", MC_SERVER_STATE_ACTIVATE},
+        {"INACTIVE", MC_SERVER_STATE_DEACTIVATE}}},
+    {kMediaControllerPlaybackState, {
+        {"PLAY", MEDIA_PLAYBACK_STATE_PLAYING},
+        {"PAUSE", MEDIA_PLAYBACK_STATE_PAUSED},
+        {"STOP", MEDIA_PLAYBACK_STATE_STOPPED},
+        {"NEXT", MEDIA_PLAYBACK_STATE_NEXT_FILE},
+        {"PREV", MEDIA_PLAYBACK_STATE_PREV_FILE},
+        {"FORWARD", MEDIA_PLAYBACK_STATE_FAST_FORWARD},
+        {"REWIND", MEDIA_PLAYBACK_STATE_REWIND}}},
+    {kMediaControllerMetadataAttribute, {
+        {"title", MEDIA_TITLE},
+        {"artist", MEDIA_ARTIST},
+        {"album", MEDIA_ALBUM},
+        {"author", MEDIA_AUTHOR},
+        {"genre", MEDIA_GENRE},
+        {"duration", MEDIA_DURATION},
+        {"date", MEDIA_DATE},
+        {"copyright", MEDIA_COPYRIGHT},
+        {"description", MEDIA_DESCRIPTION},
+        {"trackNum", MEDIA_TRACK_NUM},
+        {"picture", MEDIA_PICTURE}
+    }}
+};
+
+PlatformEnumReverseMap Types::platform_enum_reverse_map_ = {};
+
+PlatformResult Types::StringToPlatformEnum(const std::string& field,
+                                           const std::string& value,
+                                           int* platform_enum) {
+  auto iter = platform_enum_map_.find(field);
+  if (iter == platform_enum_map_.end()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+        std::string("Undefined platform enum type ") + field);
+  }
+
+  auto def = platform_enum_map_.at(field);
+  auto def_iter = def.find(value);
+  if (def_iter != def.end()) {
+    *platform_enum = def_iter->second;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  std::string message =
+      "Platform enum value " + value + " not found for " + field;
+  return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
+}
+
+PlatformResult Types::PlatformEnumToString(const std::string& field,
+                                           int value,
+                                           std::string* platform_str) {
+  // TODO(r.galka) can be replaced by Boost.Bimap
+  if (platform_enum_reverse_map_.empty()) {
+    for (auto& def : platform_enum_map_) {
+      platform_enum_reverse_map_[def.first] = {};
+
+      for (auto& key : def.second) {
+        platform_enum_reverse_map_[def.first][key.second] = key.first;
+      }
+    }
+  }
+
+  auto it = platform_enum_reverse_map_.find(field);
+  if (it == platform_enum_reverse_map_.end()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+        std::string("Undefined platform enum type ") + field);
+  }
+
+  auto def = platform_enum_reverse_map_.at(field);
+  auto def_it = def.find(value);
+  if (def_it != def.end()) {
+    *platform_str = def_it->second;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  std::string message = "Platform enum value " + std::to_string(value) +
+      " not found for " + field;
+  return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
+}
+
+} // namespace mediacontroller
+} // namespace extension
diff --git a/src/mediacontroller/mediacontroller_types.h b/src/mediacontroller/mediacontroller_types.h
new file mode 100644 (file)
index 0000000..84f77c0
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIACONTROLLER_MEDIACONTROLLER_TYPES_H_
+#define MEDIACONTROLLER_MEDIACONTROLLER_TYPES_H_
+
+#include <map>
+#include <media_controller_type.h>
+#include <string>
+
+#include "common/platform_result.h"
+
+namespace extension {
+namespace mediacontroller {
+
+typedef std::map<std::string, std::map<std::string, int>> PlatformEnumMap;
+typedef std::map<std::string, std::map<int, std::string>> PlatformEnumReverseMap;
+
+class Types {
+ public:
+  static const std::string kMediaControllerServerState;
+  static const std::string kMediaControllerPlaybackState;
+  static const std::string kMediaControllerMetadataAttribute;
+
+  static common::PlatformResult StringToPlatformEnum(const std::string& type,
+                                                     const std::string& value,
+                                                     int* platform_enum);
+
+  static common::PlatformResult PlatformEnumToString(const std::string& field,
+                                                     int value,
+                                                     std::string* platform_str);
+
+ private:
+  static const PlatformEnumMap platform_enum_map_;
+  // TODO(r.galka) can be replaced by Boost.Bimap
+  static PlatformEnumReverseMap platform_enum_reverse_map_;
+};
+
+} // namespace mediacontroller
+} // namespace extension
+
+#endif  // MEDIACONTROLLER_MEDIACONTROLLER_TYPES_H_