From: Rafal Galka Date: Tue, 14 Apr 2015 07:57:48 +0000 (+0200) Subject: [MediaController] Client native implementation of: X-Git-Tag: submit/tizen_tv/20150603.064601~1^2~133 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=39898e312608805f7baae15f114a8665d6b46929;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [MediaController] Client native implementation of: - findServers - getLatestServerInfo [Verification] Code compiles. Change-Id: Ib9aae61b9e5cc5106483b0e8994438fb9f0fbbc5 --- diff --git a/src/mediacontroller/mediacontroller.gyp b/src/mediacontroller/mediacontroller.gyp index 8f6bb125..679d2120 100755 --- a/src/mediacontroller/mediacontroller.gyp +++ b/src/mediacontroller/mediacontroller.gyp @@ -11,10 +11,14 @@ ], '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 index 00000000..4d7dfb76 --- /dev/null +++ b/src/mediacontroller/mediacontroller_client.cc @@ -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()) { + LOGGER(DEBUG) << "No latest server available"; + return PlatformResult(ErrorCode::NO_ERROR); + } + + const std::string& latest_name = latest_server.get("name").get(); + + // update current server state in list + for (picojson::array::iterator it; it != servers->end(); ++it) { + picojson::object& server = it->get(); + if (it->get("name").get() == 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(user_data); + + picojson::value server = picojson::value(picojson::object()); + picojson::object& server_o = server.get(); + 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(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(); + 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 index 00000000..37c2b6d2 --- /dev/null +++ b/src/mediacontroller/mediacontroller_client.h @@ -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 +#include + +#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_ diff --git a/src/mediacontroller/mediacontroller_instance.cc b/src/mediacontroller/mediacontroller_instance.cc index 0d87054c..5cc9724e 100644 --- a/src/mediacontroller/mediacontroller_instance.cc +++ b/src/mediacontroller/mediacontroller_instance.cc @@ -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(); + 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(args.get("callbackId").get()); + auto search = [this, args]() -> void { + LOGGER(DEBUG) << "entered"; - // implement it + picojson::value response = picojson::value(picojson::object()); + picojson::object& response_obj = response.get(); - // call ReplyAsync in later (Asynchronously) + picojson::value servers = picojson::value(picojson::array()); + PlatformResult result = client_->FindServers( + &servers.get()); - // 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( diff --git a/src/mediacontroller/mediacontroller_instance.h b/src/mediacontroller/mediacontroller_instance.h index 2c62ed12..0b57c685 100644 --- a/src/mediacontroller/mediacontroller_instance.h +++ b/src/mediacontroller/mediacontroller_instance.h @@ -5,8 +5,12 @@ #ifndef MEDIACONTROLLER_MEDIACONTROLLER_INSTANCE_H_ #define MEDIACONTROLLER_MEDIACONTROLLER_INSTANCE_H_ +#include + #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 client_; }; } // namespace mediacontroller diff --git a/src/mediacontroller/mediacontroller_types.cc b/src/mediacontroller/mediacontroller_types.cc new file mode 100644 index 00000000..179cd829 --- /dev/null +++ b/src/mediacontroller/mediacontroller_types.cc @@ -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 index 00000000..84f77c0f --- /dev/null +++ b/src/mediacontroller/mediacontroller_types.h @@ -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 +#include +#include + +#include "common/platform_result.h" + +namespace extension { +namespace mediacontroller { + +typedef std::map> PlatformEnumMap; +typedef std::map> 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_