From ed12c55352b44e47dff702f0c3a4beba0192e138 Mon Sep 17 00:00:00 2001 From: Michal Michalski Date: Wed, 3 Apr 2019 12:49:20 +0200 Subject: [PATCH] [mediacontroller][common][webapi-plugins.spec][tizen] Implementation for search API. http://suprem.sec.samsung.net/jira/browse/TWDAPI-208 Implementation for search API. [Verification] Manual API testing. tct-mediacontroller-tizen-tests 100% pass tct-messageport-tizen-tests 100% pass Signed-off-by: Michal Michalski Change-Id: I47cb4b3234e212db77ed20c4f899f4b5bed2d662 --- src/mediacontroller/mediacontroller_api.js | 201 +++++++++++++++++++++++- src/mediacontroller/mediacontroller_client.cc | 83 ++++++++++ src/mediacontroller/mediacontroller_client.h | 5 + src/mediacontroller/mediacontroller_instance.cc | 115 +++++++++++++- src/mediacontroller/mediacontroller_instance.h | 7 +- src/mediacontroller/mediacontroller_server.cc | 97 +++++++++++- src/mediacontroller/mediacontroller_server.h | 8 +- src/mediacontroller/mediacontroller_utils.cc | 13 +- src/mediacontroller/mediacontroller_utils.h | 1 + src/tizen/tizen_api.js | 3 +- 10 files changed, 521 insertions(+), 12 deletions(-) diff --git a/src/mediacontroller/mediacontroller_api.js b/src/mediacontroller/mediacontroller_api.js index 5c9ceb1..0eec9e5 100755 --- a/src/mediacontroller/mediacontroller_api.js +++ b/src/mediacontroller/mediacontroller_api.js @@ -60,6 +60,8 @@ ListenerManager.prototype.addListener = function(callback) { return id; }; + + ListenerManager.prototype.addServerInfoListener = function(callback, name) { var id = this.nextId; if (!this.nativeSet) { @@ -298,6 +300,15 @@ var MediaControllerContentAgeRating = { NINETEEN: '19' }; +var MediaControllerSearchCategory = { + NO_CATEGORY: "NO_CATEGORY", + TITLE: "TITLE", + ARTIST: "ARTIST", + ALBUM: "ALBUM", + GENRE: "GENRE", + TPO: "TPO" +}; + var MediaControllerContentType = { IMAGE: 'IMAGE', MUSIC: 'MUSIC', @@ -1016,7 +1027,6 @@ MediaControllerServer.prototype.getAllPlaylists = function( native_.callIfPossible(args.successCallback, playlists); }; - var result = native_.call('MediaControllerServer_getAllPlaylists', {}, callback); if (native_.isFailure(result)) { @@ -1024,6 +1034,74 @@ MediaControllerServer.prototype.getAllPlaylists = function( } }; +function RequestReply(data, code) { + xwalk.utils.validator.isConstructorCall(this, RequestReply); + this.code = xwalk.utils.converter.toLong(code); + if (xwalk.utils.type.isUndefined(data)) { + this.data = null; + } + else if (!(data instanceof tizen.Bundle)) { + this.data = new tizen.Bundle(data); + } + else { + this.data = data; + } +} + +MediaControllerServer.prototype.setSearchRequestListener = function(listener) { + var args = validator_.validateArgs(arguments, [ + {name: 'listener', type: types_.FUNCTION} + ]); + + if (!native_.isListenerSet("SearchRequestListener")) { + var result = native_.callSync('MediaControllerServer_addSearchRequestListener', { + listenerId: "SearchRequestListener" + }); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + } + + var callback = function (msg) { + var request = []; + msg.request.forEach(function (filter) { + request.push(new SearchFilter( + filter.contentType, + filter.category, + filter.keyword, + filter.extraData + )); + }); + + var reply = args.listener(msg.clientName, request); + if (type_.isUndefined(reply)) { + reply = null; + } + + var nativeData = { + clientName: msg.clientName, + requestId: msg.requestId, + reply: reply, + replyType: "RequestReply" + }; + + var result = native_.callSync('MediaControllerServer_replyCommand', nativeData); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + } + + native_.addListener("SearchRequestListener", callback); +} + +MediaControllerServer.prototype.unsetSearchRequestListener = function() { + var result = native_.callSync('MediaControllerServer_removeSearchRequestListener'); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + native_.removeListener("SearchRequestListener"); +} + function MediaControllerClient() {} MediaControllerClient.prototype.findServers = function(successCallback, errorCallback) { @@ -1065,6 +1143,92 @@ MediaControllerClient.prototype.getLatestServerInfo = function() { return serverInfo; }; +function SearchFilter(contentType, category, keyword, extraData) { + validator_.isConstructorCall(this, SearchFilter); + var args = validator_.validateArgs(arguments, [ + {name: 'contentType', type: types_.ENUM, values: Object.values(MediaControllerContentType)}, + {name: 'category', type: types_.ENUM, values: Object.values(MediaControllerSearchCategory), optional: true}, + {name: 'keyword', type: types_.STRING, nullable: true, optional: true}, + ]); + + if (!args.hasOwnProperty("category")) {args.category = "NO_CATEGORY";} + if (!args.hasOwnProperty("keyword")) {args.keyword = null;} + + extraData = xwalk.utils.type.isUndefined(extraData) ? null : extraData; + args.extraData = xwalk.utils.type.isNull(extraData) ? null : new tizen.Bundle(extraData); + + var extraData_ = args.extraData; + var contentType_ = args.contentType; + var category_ = args.category; + var keyword_ = args.keyword; + + // keyword can be null only when category is NO_CATEGORY + if (xwalk.utils.type.isNull(keyword_) && category_ != MediaControllerSearchCategory.NO_CATEGORY) { + throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR); + } + + Object.defineProperties(this, { + contentType: { + enumerable: true, + get: function () { return contentType_; }, + set: function (newContentType) { + var args = validator_.validateArgs(arguments, [{ + name: 'newContentType', + type: types_.ENUM, + values: Object.values(MediaControllerContentType) + }]); + contentType_ = args.newContentType; + } + }, + category: { + enumerable: true, + get: function () { return category_; }, + set: function (newCategory) { + var args = validator_.validateArgs(arguments, [{ + name: 'newCategory', + type: types_.ENUM, + values: Object.values(MediaControllerSearchCategory) + }]); + + // Keyword can be null only if category is NO_CATEGORY. + if (xwalk.utils.type.isNull(keyword_) && args.newCategory != MediaControllerSearchCategory.NO_CATEGORY) { + throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR); + } + + category_ = args.newCategory; + } + }, + keyword: { + enumerable: true, + get: function () { return keyword_; }, + set: function (newKeyword) { + var args = validator_.validateArgs(arguments, [{ + name: 'newKeyword', + type: types_.STRING, + nullable: true + }]); + + // Keyword can only be null if category is NO_CATEGORY. + if (xwalk.utils.type.isNull(args.newKeyword) && this.category != MediaControllerSearchCategory.NO_CATEGORY) { + throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR); + } + + keyword_ = args.newKeyword; + } + }, + extraData: { + enumerable: true, + get: function () { return extraData_ }, + set: function (newData) { + if (xwalk.utils.type.isUndefined(newData)) { + newData = null; + } + extraData_ = xwalk.utils.type.isNull(newData) ? null : new tizen.Bundle(newData); + } + } + }); +} + function MediaControllerServerInfo(data) { Object.defineProperties(this, { name: { @@ -1322,6 +1486,38 @@ MediaControllerServerInfo.prototype.sendCommand = function( ReplyCommandListener.requestIdToListenerId[replyListenerId] = result.requestId; }; +MediaControllerServerInfo.prototype.sendSearchRequest = function(request, successCallback, errorCallback) { + var args = validator_.validateArgs(arguments, [ + {name: 'request', type: types_.ARRAY, values: SearchFilter}, + {name: 'successCallback', type: types_.FUNCTION}, + {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true} + ]); + + if (args.request.length < 1 || args.request.length > 20) { + throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR); + } + + var callback = function(result) { + if (native_.isFailure(result)) { + native_.callIfPossible(args.errorCallback, native_.getErrorObject(result)); + return; + } + var reply = native_.getResultObject(result); + native_.callIfPossible(args.successCallback, new RequestReply(reply.data, reply.code)); + }; + + var nativeData = { + request: args.request, + name: this.name, + listenerId: ReplyCommandListener.listenerName + }; + + var replyListenerId = ReplyCommandListener.addListener(callback); + var result = native_.callSync('MediaControllerServerInfo_sendSearchRequest', nativeData, callback); + + ReplyCommandListener.requestIdToListenerId[replyListenerId] = result.requestId; +} + MediaControllerServerInfo.prototype.addServerStatusChangeListener = function(listener) { var args = validator_.validateArgs(arguments, [ { name: 'listener', type: types_.FUNCTION } @@ -1627,3 +1823,6 @@ MediaControllerPlaylist.prototype.getItems = function(successCallback, errorCall }; exports = new MediaControllerManager(); +exports.SearchFilter = SearchFilter; +exports.RequestReply = RequestReply; + diff --git a/src/mediacontroller/mediacontroller_client.cc b/src/mediacontroller/mediacontroller_client.cc index 749ff21..7d6c20c 100644 --- a/src/mediacontroller/mediacontroller_client.cc +++ b/src/mediacontroller/mediacontroller_client.cc @@ -32,6 +32,7 @@ using common::PlatformResult; using common::ErrorCode; using common::tools::ReportError; using common::tools::ReportSuccess; +using common::JsonToBundle; MediaControllerClient::MediaControllerClient() : handle_(nullptr) { ScopeLogger(); @@ -540,6 +541,87 @@ void MediaControllerClient::OnMetadataUpdate(const char* server_name, mc_metadat client->playback_info_listener_(&data); } +PlatformResult MediaControllerClient::SendSearchRequest(const std::string& server_name, + const picojson::value& request, + const JsonCallback& callback, + char** request_id) +{ + ScopeLogger(); + mc_search_h search_request; + SCOPE_EXIT { + mc_search_destroy(search_request); + }; + + int ret = mc_search_create(&search_request); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult( + ErrorCode::UNKNOWN_ERR, "Unable to create search request.", + ("mc_search_create error: %d, message: %s", ret, get_error_message(ret))); + } + + if (!request.is()) { + return LogAndCreateResult( + ErrorCode::INVALID_VALUES_ERR, + "MediaControllerClient::SendSearchRequest request param is not an array."); + } + + for (const auto& filter_obj: request.get()) { + const picojson::object& filter = filter_obj.get(); + + // contentType + std::string content_type_str = filter.at("contentType").get(); + mc_content_type_e content_type_e; + PlatformResult result = types::MediaControllerContentTypeEnum.getValue(content_type_str, &content_type_e); + if (!result) { + LoggerE("MediaControllerContentTypeEnum.getValue(%s) failed.", content_type_str.c_str()); + return result; + } + + // category + std::string search_category_str = filter.at("category").get(); + mc_search_category_e search_category_e; + result = types::MediaControllerSearchCategoryEnum.getValue(search_category_str, &search_category_e); + if (!result) { + LoggerE("MediaControllerSearchCategoryEnum.getValue(%s) failed.", search_category_str.c_str()); + return result; + } + + // extra data + bundle* bundle_data = nullptr; + SCOPE_EXIT { bundle_free(bundle_data); }; + result = JsonToBundle(filter.at("extraData"), &bundle_data); + if (!result) { + return LogAndCreateResult( + ErrorCode::INVALID_VALUES_ERR, "Unable to add data to bundle", + ("JsonToBundle() error message: %s", result.message().c_str())); + } + + ret = mc_search_set_condition( + search_request, + content_type_e, + search_category_e, + filter.at("keyword").get().c_str(), + bundle_data); + + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult( + ErrorCode::UNKNOWN_ERR, "Unable to set search condition.", + ("mc_search_set_condition error: %d, message: %s", ret, get_error_message(ret))); + } + } + + ret = mc_client_send_search_cmd(handle_, server_name.c_str(), search_request, request_id); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult( + ErrorCode::UNKNOWN_ERR, "Unable to send search request.", + ("mc_client_send_search_cmd error: %d, message: %s", ret, get_error_message(ret))); + } + + command_reply_callback_ = callback; + + return PlatformResult(ErrorCode::NO_ERROR); +} + PlatformResult MediaControllerClient::SendCommand(const std::string& server_name, const std::string& command, const picojson::value& data, @@ -593,6 +675,7 @@ void MediaControllerClient::OnCommandReply(const char* server_name, const char* reply_o["data"] = data; reply_o["name"] = picojson::value(server_name); + reply_o["code"] = picojson::value(static_cast(result_code)); if (nullptr == request_id) { LoggerE("Request id is null."); diff --git a/src/mediacontroller/mediacontroller_client.h b/src/mediacontroller/mediacontroller_client.h index a07f533..f41fa79 100644 --- a/src/mediacontroller/mediacontroller_client.h +++ b/src/mediacontroller/mediacontroller_client.h @@ -47,6 +47,11 @@ class MediaControllerClient { common::PlatformResult SendRepeatMode(const std::string& server_name, bool mode); common::PlatformResult SendRepeatState(const std::string& server_name, const std::string& state); + common::PlatformResult SendSearchRequest(const std::string& server_name, + const picojson::value& request, + const JsonCallback& callback, + char** request_id); + common::PlatformResult SendCommand(const std::string& server_name, const std::string& command, const picojson::value& data, const JsonCallback& reply_cb, char** request_id); diff --git a/src/mediacontroller/mediacontroller_instance.cc b/src/mediacontroller/mediacontroller_instance.cc index 2629d35..e39eab0 100644 --- a/src/mediacontroller/mediacontroller_instance.cc +++ b/src/mediacontroller/mediacontroller_instance.cc @@ -69,6 +69,10 @@ MediaControllerInstance::MediaControllerInstance() { MediaControllerServerAddChangeRequestPlaybackInfoListener); REGISTER_SYNC("MediaControllerServer_removeChangeRequestPlaybackInfoListener", MediaControllerServerRemoveChangeRequestPlaybackInfoListener); + REGISTER_SYNC("MediaControllerServer_addSearchRequestListener", + MediaControllerServerAddSearchRequestListener); + REGISTER_SYNC("MediaControllerServer_removeSearchRequestListener", + MediaControllerServerRemoveSearchRequestListener); REGISTER_SYNC("MediaControllerServer_addCommandListener", MediaControllerServerAddCommandListener); REGISTER_SYNC("MediaControllerServer_replyCommand", MediaControllerServerReplyCommand); @@ -98,6 +102,8 @@ MediaControllerInstance::MediaControllerInstance() { MediaControllerServerInfoSendRepeatState); REGISTER_ASYNC("MediaControllerServerInfo_sendShuffleMode", MediaControllerServerInfoSendShuffleMode); + REGISTER_ASYNC("MediaControllerServerInfo_sendSearchRequest", + MediaControllerServerInfoSendSearchRequest); REGISTER_ASYNC("MediaControllerServerInfo_sendCommand", MediaControllerServerInfoSendCommand); REGISTER_SYNC("MediaControllerServerInfo_addServerStatusChangeListener", MediaControllerServerInfoAddServerStatusChangeListener); @@ -412,6 +418,50 @@ void MediaControllerInstance::MediaControllerServerRemoveChangeRequestPlaybackIn } } +void MediaControllerInstance::MediaControllerServerAddSearchRequestListener( + const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + + if (!server_) { + LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Server not initialized."), &out, + ("Failed: server_")); + return; + } + + JsonCallback on_request = [this, args](picojson::value* request) -> void { + picojson::object& request_o = request->get(); + request_o["listenerId"] = args.get("listenerId"); + Instance::PostMessage(this, request->serialize().c_str()); + }; + + auto result = server_->SetSearchRequestListener(on_request); + if (!result) { + LogAndReportError(result, &out); + return; + } + + ReportSuccess(out); +} + +void MediaControllerInstance::MediaControllerServerRemoveSearchRequestListener( + const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + + if (!server_) { + LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Server not initialized."), + &out, ("Failed: server_")); + return; + } + + auto result = server_->UnsetSearchRequestListener(); + if (!result) { + LogAndReportError(result, &out); + return; + } +} + void MediaControllerInstance::MediaControllerServerAddCommandListener(const picojson::value& args, picojson::object& out) { ScopeLogger(); @@ -445,13 +495,27 @@ void MediaControllerInstance::MediaControllerServerReplyCommand(const picojson:: return; } - CHECK_EXIST(args, "clientName", out) - CHECK_EXIST(args, "requestId", out) - CHECK_EXIST(args, "data", out) + CHECK_EXIST(args, "clientName", out); + CHECK_EXIST(args, "requestId", out); + CHECK_EXIST(args, "reply", out); + CHECK_EXIST(args, "replyType", out); + + int code = 0; + picojson::value data; + + if (args.get("replyType").get() == "RequestReply") { + CHECK_EXIST(args.get("reply"), "code", out); + CHECK_EXIST(args.get("reply"), "data", out); + code = static_cast(args.get("reply").get("code").get()); + data = args.get("reply").get().at("data"); + } + else { + data = args.get("reply"); + } - picojson::value json = args.get("data"); auto result = server_->CommandReply(args.get("clientName").get(), - args.get("requestId").get(), json); + args.get("requestId").get(), + code, data); if (!result) { LogAndReportError(result, &out); @@ -890,6 +954,47 @@ void MediaControllerInstance::MediaControllerServerInfoSendRepeatState(const pic ReportSuccess(out); } +void MediaControllerInstance::MediaControllerServerInfoSendSearchRequest( + const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + + if (!client_) { + LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Client not initialized."), &out, + ("Failed: client_")); + return; + } + + CHECK_EXIST(args, "listenerId", out); + CHECK_EXIST(args, "name", out); + CHECK_EXIST(args, "request", out); + + JsonCallback reply_cb = [this, args](picojson::value* reply) -> void { + picojson::object& reply_obj = reply->get(); + reply_obj["listenerId"] = args.get("listenerId"); + Instance::PostMessage(this, reply->serialize().c_str()); + }; + + char* request_id = nullptr; + SCOPE_EXIT { + free(request_id); + }; + + PlatformResult result = client_->SendSearchRequest( + args.get("name").get(), + args.get("request"), + reply_cb, + &request_id); + + if (result) { + ReportSuccess(out); + out["requestId"] = picojson::value(std::string(request_id)); + } + else { + LogAndReportError(result, &out, ("Failed to send command.")); + } +} + void MediaControllerInstance::MediaControllerServerInfoSendCommand(const picojson::value& args, picojson::object& out) { ScopeLogger(); diff --git a/src/mediacontroller/mediacontroller_instance.h b/src/mediacontroller/mediacontroller_instance.h index 20a7e1d..829a332 100644 --- a/src/mediacontroller/mediacontroller_instance.h +++ b/src/mediacontroller/mediacontroller_instance.h @@ -49,8 +49,12 @@ class MediaControllerInstance : public common::ParsedInstance { picojson::object& out); void MediaControllerServerRemoveChangeRequestPlaybackInfoListener(const picojson::value& args, picojson::object& out); - void MediaControllerServerAddCommandListener(const picojson::value& args, picojson::object& out); + + void MediaControllerServerAddSearchRequestListener(const picojson::value& args, picojson::object& out); + void MediaControllerServerRemoveSearchRequestListener(const picojson::value& args, picojson::object& out); + void MediaControllerServerReplyCommand(const picojson::value& args, picojson::object& out); + void MediaControllerServerAddCommandListener(const picojson::value& args, picojson::object& out); void MediaControllerServerRemoveCommandListener(const picojson::value& args, picojson::object& out); void MediaControllerServerCreatePlaylist(const picojson::value& args, picojson::object& out); @@ -72,6 +76,7 @@ class MediaControllerInstance : public common::ParsedInstance { void MediaControllerServerInfoSendRepeatMode(const picojson::value& args, picojson::object& out); void MediaControllerServerInfoSendRepeatState(const picojson::value& args, picojson::object& out); void MediaControllerServerInfoSendShuffleMode(const picojson::value& args, picojson::object& out); + void MediaControllerServerInfoSendSearchRequest(const picojson::value& args, picojson::object& out); void MediaControllerServerInfoSendCommand(const picojson::value& args, picojson::object& out); void MediaControllerServerInfoAddServerStatusChangeListener(const picojson::value& args, picojson::object& out); diff --git a/src/mediacontroller/mediacontroller_server.cc b/src/mediacontroller/mediacontroller_server.cc index 0a2858e..266f8d7 100644 --- a/src/mediacontroller/mediacontroller_server.cc +++ b/src/mediacontroller/mediacontroller_server.cc @@ -29,6 +29,7 @@ namespace mediacontroller { using common::PlatformResult; using common::ErrorCode; +using common::BundleJsonIterator; MediaControllerServer::MediaControllerServer() : handle_(nullptr), @@ -55,6 +56,10 @@ MediaControllerServer::~MediaControllerServer() { LoggerE("Failed to unset command listener"); } + if (nullptr != search_request_listener_ && !UnsetSearchRequestListener()) { + LoggerE("Failed to unset search request listener"); + } + 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()); @@ -297,6 +302,69 @@ PlatformResult MediaControllerServer::SetMetadata(const picojson::object& metada return PlatformResult(ErrorCode::NO_ERROR); } +void MediaControllerServer::OnSearchRequestReceived(const char* client_name, const char* request_id, + mc_search_h request, void* user_data) { + ScopeLogger(); + MediaControllerServer* server = static_cast(user_data); + if (nullptr == server->search_request_listener_) { + LoggerW("search_request_listener_ is not set"); + return; + } + + auto request_json = picojson::value(picojson::object()); + auto& request_o = request_json.get(); + + request_o["clientName"] = picojson::value(std::string(client_name)); + request_o["requestId"] = picojson::value(std::string(request_id)); + + auto condition_cb = [](mc_content_type_e content_type, mc_search_category_e category, + const char* keyword, bundle* data, void* user_data) -> bool { + LoggerD("condition callback for: %s", keyword); + auto filters = static_cast(user_data); + + auto value = picojson::value(picojson::object()); + auto& object = value.get(); + + std::string temp; + PlatformResult result = types::MediaControllerContentTypeEnum.getName(content_type, &temp); + if (!result) { + LoggerE("MediaControllerContentTypeEnum.getName() failed with error message: %s", result.message().c_str()); + return false; + } + object["contentType"] = picojson::value(temp); + + result = types::MediaControllerSearchCategoryEnum.getName(category, &temp); + if (!result) { + LoggerE("MediaControllerSearchCategoryEnum.getName() failed with error message: %s", result.message().c_str()); + return false; + } + object["category"] = picojson::value(temp); + + object["keyword"] = picojson::value(std::string(keyword)); + + picojson::value data_json; + result = common::BundleToJson(data, &data_json); + if (!result) { + LoggerE("BundleToJson failed with error message: %s", result.message().c_str()); + return false; + } + object["extraData"] = data_json; + + filters->push_back(value); + return true; + }; + + picojson::array filters; + int ret = mc_search_foreach_condition(request, condition_cb, &filters); + if (ret != MEDIA_CONTROLLER_ERROR_NONE) { + LoggerE("mc_search_foreach_condition failed with error: %d", ret); + return; + } + + request_o["request"] = picojson::value(filters); + server->search_request_listener_(&request_json); +} + void MediaControllerServer::OnCommandReceived(const char* client_name, const char* request_id, const char* command, bundle* bundle, void* user_data) { @@ -323,6 +391,7 @@ void MediaControllerServer::OnCommandReceived(const char* client_name, const cha PlatformResult MediaControllerServer::CommandReply(const std::string& client_name, const std::string& request_id, + int code, const picojson::value& data) { ScopeLogger(); @@ -340,7 +409,7 @@ PlatformResult MediaControllerServer::CommandReply(const std::string& client_nam } } - ret = mc_server_send_cmd_reply(handle_, client_name.c_str(), request_id.c_str(), 0, bundle); + ret = mc_server_send_cmd_reply(handle_, client_name.c_str(), request_id.c_str(), code, bundle); if (MEDIA_CONTROLLER_ERROR_NONE != ret) { return LogAndCreateResult( ErrorCode::UNKNOWN_ERR, "Error sending command reply", @@ -350,6 +419,32 @@ PlatformResult MediaControllerServer::CommandReply(const std::string& client_nam return PlatformResult(ErrorCode::NO_ERROR); } +PlatformResult MediaControllerServer::SetSearchRequestListener(const JsonCallback& callback) { + ScopeLogger(); + + int ret = mc_server_set_search_cmd_received_cb(handle_, OnSearchRequestReceived, this); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to set search request callback.", + ("mc_server_set_search_cmd_received_cb() error: %d, message: %s", + ret, get_error_message(ret))); + } + + search_request_listener_ = callback; + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult MediaControllerServer::UnsetSearchRequestListener() { + ScopeLogger(); + int ret = mc_server_unset_search_cmd_received_cb(handle_); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to unset search request callback.", + ("mc_server_unset_search_cmd_received_cb() error: %d, message: %s", + ret, get_error_message(ret))); + } + search_request_listener_ = nullptr; + return PlatformResult(ErrorCode::NO_ERROR); +} + PlatformResult MediaControllerServer::SetCommandListener(const JsonCallback& callback) { ScopeLogger(); diff --git a/src/mediacontroller/mediacontroller_server.h b/src/mediacontroller/mediacontroller_server.h index 6ad8be7..fc5a3bb 100644 --- a/src/mediacontroller/mediacontroller_server.h +++ b/src/mediacontroller/mediacontroller_server.h @@ -44,8 +44,11 @@ class MediaControllerServer { common::PlatformResult SetChangeRequestPlaybackInfoListener(const JsonCallback& callback); common::PlatformResult UnsetChangeRequestPlaybackInfoListener(); + common::PlatformResult SetSearchRequestListener(const JsonCallback& callback); + common::PlatformResult UnsetSearchRequestListener(); + common::PlatformResult CommandReply(const std::string& client_name, const std::string& request_id, - const picojson::value& data); + int code, const picojson::value& data); common::PlatformResult SetCommandListener(const JsonCallback& callback); common::PlatformResult UnsetCommandListener(); @@ -77,6 +80,7 @@ class MediaControllerServer { JsonCallback command_listener_; std::map playlist_handle_map_; + JsonCallback search_request_listener_; static void OnPlaybackActionCommand(const char* client_name, const char* request_id, mc_playback_action_e action, void* user_data); @@ -91,6 +95,8 @@ class MediaControllerServer { mc_playback_action_e action, unsigned long long position, void* user_data); + static void OnSearchRequestReceived(const char* client_name, const char* request_id, + mc_search_h request, void* user_data); static void OnCommandReceived(const char* client_name, const char* request_id, const char* command, bundle* data, void* user_data); }; diff --git a/src/mediacontroller/mediacontroller_utils.cc b/src/mediacontroller/mediacontroller_utils.cc index 0814bc8..ebe070c 100644 --- a/src/mediacontroller/mediacontroller_utils.cc +++ b/src/mediacontroller/mediacontroller_utils.cc @@ -85,7 +85,18 @@ const common::PlatformEnum MediaControllerContentTypeEnum{ {"MUSIC", MC_CONTENT_TYPE_MUSIC}, {"VIDEO", MC_CONTENT_TYPE_VIDEO}, {"OTHER", MC_CONTENT_TYPE_OTHER}, - {"UNDECIDED", MC_CONTENT_TYPE_UNDECIDED}}; + {"UNDECIDED", MC_CONTENT_TYPE_UNDECIDED} +}; + +const common::PlatformEnum MediaControllerSearchCategoryEnum { + {"NONE", MC_SEARCH_NO_CATEGORY}, + {"TITLE", MC_SEARCH_TITLE}, + {"ARTIST", MC_SEARCH_ARTIST}, + {"ALBUM", MC_SEARCH_ALBUM}, + {"GENRE", MC_SEARCH_GENRE}, + {"TPO", MC_SEARCH_TPO} +}; + PlatformResult ConvertPlaybackState(mc_playback_h playback_h, std::string* state) { ScopeLogger(); diff --git a/src/mediacontroller/mediacontroller_utils.h b/src/mediacontroller/mediacontroller_utils.h index 80947a5..18fe21b 100644 --- a/src/mediacontroller/mediacontroller_utils.h +++ b/src/mediacontroller/mediacontroller_utils.h @@ -45,6 +45,7 @@ extern const common::PlatformEnum MediaControllerMetadataAttributeEnu extern const common::PlatformEnum MediaControllerRepeatModeEnum; extern const common::PlatformEnum MediaControllerContentAgeRatingEnum; extern const common::PlatformEnum MediaControllerContentTypeEnum; +extern const common::PlatformEnum MediaControllerSearchCategoryEnum; } // namespace types diff --git a/src/tizen/tizen_api.js b/src/tizen/tizen_api.js index 691514e..7b96118 100644 --- a/src/tizen/tizen_api.js +++ b/src/tizen/tizen_api.js @@ -514,11 +514,10 @@ function Bundle(arg) { // copy constructor if (arg instanceof tizen.Bundle) { - // perform deep copy of the other bundle. json = JSON.parse(arg.toString()); } // json to bundle conversion - else if (xwalk.utils.type.isObject(json)) { + else if (xwalk.utils.type.isObject(arg)) { json = arg; } -- 2.7.4