From: Piotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/삼성전자 Date: Thu, 5 Sep 2019 05:21:53 +0000 (+0200) Subject: [Mediacontroller] added mode 360 feature X-Git-Tag: submit/tizen/20190919.123326~7^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0bd67b3f46ebf1824c71a533ea38b1322d08f78c;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Mediacontroller] added mode 360 feature [ACR] http://suprem.sec.samsung.net/jira/browse/TWDAPI-229 [Verification] Code compiles without errors. Basic test in chrome console works properly. /// 1. adding command listener var mcServer = tizen.mediacontroller.createServer(); mcServer.updatePlaybackState("PLAY"); var changeListener = function(enabled, clientName) { console.log("Spherical mode change requested to: " + enabled + " by " + clientName); return new tizen.mediacontroller.RequestReply(new tizen.Bundle({"message": "Not allowed"}), 13); }; watcherId = mcServer.mode360.addChangeRequestListener(changeListener); /// 2. checking NotSupportedError when sending without enabled ability var mcClient = tizen.mediacontroller.getClient(); var mcServerInfo = mcClient.getLatestServerInfo() var enabled = true; mcServerInfo.mode360.sendRequest(enabled, function(data, code) { console.log( "Server replied with return data: " + JSON.stringify(data) + " and code: " + code); }, function(e) { console.log("Error executing command: " + e.message); }); /// 3. register listener for mode changes (client side) watcherId = mcServerInfo.mode360.addModeChangeListener(function(status) { console.log(mcServerInfo.name + " server spherical mode changed to " + status); }); /// 4. change the value of mode 360 (should trigger listener from point 3) mcServer.mode360.enabled = true /// 5. enable ability of server mcServer.abilities.mode360 = "YES" /// sendRequest again (should trigger listener from point 1) mcServerInfo.mode360.sendRequest(enabled, function(data, code) { console.log( "Server replied with return data: " + JSON.stringify(data) + " and code: " + code); }, function(e) { console.log("Error executing command: " + e.message); }); /// 6. register ability change listener and trigger the update var listener = { onsimpleabilitychanged: function(server, type, ability) { console.log(type + " ability changed, server name: " + server.name + ", ability: " + ability); } }; mcClient.addAbilityChangeListener(listener); /// call updates to trigger listener mcServer.abilities.mode360 = "NO" mcServer.abilities.mode360 = "NO" /// Listener should be triggered once Change-Id: I8170d56f6d5b18f053047d48d55e68d3ebbe7719 --- diff --git a/src/mediacontroller/mediacontroller_api.js b/src/mediacontroller/mediacontroller_api.js index 1766ee92..1d3f2fae 100755 --- a/src/mediacontroller/mediacontroller_api.js +++ b/src/mediacontroller/mediacontroller_api.js @@ -223,7 +223,10 @@ var ServerInfoPlaybackInfoListener = new ListenerManager( native_.callIfPossible(listener[msg.action], msg.state); } if (msg.action === 'onmetadatachanged') { - native_.callIfPossible(listener[msg.action], new MediaControllerMetadata(msg.metadata)); + native_.callIfPossible( + listener[msg.action], + new MediaControllerMetadata(msg.metadata) + ); } } ); @@ -233,7 +236,11 @@ var ServerInfoPlaylistUpdatedListener = new ListenerManager( '_ServerInfoPlaylistUpdatedListener', function(msg, listener) { if (msg.action === 'onplaylistupdated') { - native_.callIfPossible(listener[msg.action], msg.serverName, new MediaControllerPlaylist(msg)); + native_.callIfPossible( + listener[msg.action], + msg.serverName, + new MediaControllerPlaylist(msg) + ); } if (msg.action === 'onplaylistdeleted') { native_.callIfPossible(listener[msg.action], msg.serverName, msg.name); @@ -350,7 +357,8 @@ var MediaControllerSimpleAbility = { REPEAT: 'REPEAT', PLAYLIST: 'PLAYLIST', CLIENT_CUSTOM: 'CLIENT_CUSTOM', - SEARCH: 'SEARCH' + SEARCH: 'SEARCH', + MODE_360: 'MODE_360' }; function MediaControllerManager() {} @@ -618,7 +626,8 @@ var MediaControllerAbilities = function() { _repeat = MediaControllerAbilitySupport.UNDECIDED, _playlist = MediaControllerAbilitySupport.UNDECIDED, _clientCustom = MediaControllerAbilitySupport.UNDECIDED, - _search = MediaControllerAbilitySupport.UNDECIDED; + _search = MediaControllerAbilitySupport.UNDECIDED, + _mode360 = MediaControllerAbilitySupport.NO; Object.defineProperties(this, { playback: { @@ -630,8 +639,10 @@ var MediaControllerAbilities = function() { return _playbackPosition; }, set: function(val) { - setSimpleAbility(MediaControllerSimpleAbility.PLAYBACK_POSITION, val); - _playbackPosition = val; + if (val !== _playbackPosition) { + setSimpleAbility(MediaControllerSimpleAbility.PLAYBACK_POSITION, val); + _playbackPosition = val; + } }, enumerable: true }, @@ -640,8 +651,10 @@ var MediaControllerAbilities = function() { return _shuffle; }, set: function(val) { - setSimpleAbility(MediaControllerSimpleAbility.SHUFFLE, val); - _shuffle = val; + if (val !== _shuffle) { + setSimpleAbility(MediaControllerSimpleAbility.SHUFFLE, val); + _shuffle = val; + } }, enumerable: true }, @@ -650,8 +663,10 @@ var MediaControllerAbilities = function() { return _repeat; }, set: function(val) { - setSimpleAbility(MediaControllerSimpleAbility.REPEAT, val); - _repeat = val; + if (val !== _repeat) { + setSimpleAbility(MediaControllerSimpleAbility.REPEAT, val); + _repeat = val; + } }, enumerable: true }, @@ -660,8 +675,10 @@ var MediaControllerAbilities = function() { return _playlist; }, set: function(val) { - setSimpleAbility(MediaControllerSimpleAbility.PLAYLIST, val); - _playlist = val; + if (val !== _playlist) { + setSimpleAbility(MediaControllerSimpleAbility.PLAYLIST, val); + _playlist = val; + } }, enumerable: true }, @@ -670,8 +687,10 @@ var MediaControllerAbilities = function() { return _clientCustom; }, set: function(val) { - setSimpleAbility(MediaControllerSimpleAbility.CLIENT_CUSTOM, val); - _clientCustom = val; + if (val !== _clientCustom) { + setSimpleAbility(MediaControllerSimpleAbility.CLIENT_CUSTOM, val); + _clientCustom = val; + } }, enumerable: true }, @@ -680,8 +699,22 @@ var MediaControllerAbilities = function() { return _search; }, set: function(val) { - setSimpleAbility(MediaControllerSimpleAbility.SEARCH, val); - _search = val; + if (val !== _search) { + setSimpleAbility(MediaControllerSimpleAbility.SEARCH, val); + _search = val; + } + }, + enumerable: true + }, + mode360: { + get: function() { + return _mode360; + }, + set: function(val) { + if (val !== _mode360) { + setSimpleAbility(MediaControllerSimpleAbility.MODE_360, val); + _mode360 = val; + } }, enumerable: true } @@ -860,6 +893,16 @@ var MediaControllerAbilitiesInfo = function(serverName) { }, set: function() {}, enumerable: true + }, + mode360: { + get: function() { + return getSimpleAbility( + serverName, + MediaControllerSimpleAbility.MODE_360 + ); + }, + set: function() {}, + enumerable: true } }); @@ -954,9 +997,198 @@ var MediaControllerPlaybackAbilitiesInfo = function(serverName) { // TODO subtitles var MediaControllerSubtitles = function() {}; var MediaControllerSubtitlesInfo = function() {}; -// TODO mode360 -var MediaControllerMode360 = function() {}; -var MediaControllerMode360Info = function() {}; +// mode360 +var MediaControllerMode360 = function() { + // the default value is false + var _enabled = false; + Object.defineProperties(this, { + enabled: { + get: function() { + return _enabled; + }, + set: function(v) { + var data = { + enabled: converter_.toBoolean(v) + }; + if (data.enabled !== _enabled) { + var result = native_.callSync( + 'MediaControllerMode360_updateEnabled', + data + ); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + _enabled = data.enabled; + } + }, + enumerable: true + } + }); +}; + +var MediaControllerMode360Listener = new ListenerManager( + native_, + '_MediaControllerMode360Listener', + function(msg, listener) { + var reply = listener(msg.clientName, msg.enabled); + + if (!(reply instanceof RequestReply)) { + reply = new RequestReply( + xwalk.utils.type.isNullOrUndefined(reply) ? null : reply, + 0 + ); + } + + var nativeData = { + clientName: msg.clientName, + requestId: msg.requestId, + reply: reply + }; + var result = native_.callSync('MediaControllerServer_replyCommand', nativeData); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + } +); + +MediaControllerMode360.prototype.addChangeRequestListener = function() { + var args = validator_.validateArgs(arguments, [ + { + name: 'listener', + type: types_.FUNCTION, + optional: false, + nullable: false + } + ]); + + if (type_.isEmptyObject(MediaControllerMode360Listener.listeners)) { + var result = native_.callSync('MediaControllerMode360_addChangeRequestListener', { + listenerId: MediaControllerMode360Listener.listenerName + }); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + } + return MediaControllerMode360Listener.addListener(args.listener); +}; + +MediaControllerMode360.prototype.removeChangeRequestListener = function(watchId) { + var args = validator_.validateArgs(arguments, [ + { name: 'watchId', type: types_.LONG } + ]); + + MediaControllerMode360Listener.removeListener(args.watchId); + + if (type_.isEmptyObject(MediaControllerMode360Listener.listeners)) { + var result = native_.callSync( + 'MediaControllerMode360_removeChangeRequestListener' + ); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + } +}; + +var Mode360ChangeListener = new ListenerManager( + native_, + '_Mode360ChangeListener', + function(msg, listener) { + listener(msg.enabled); + } +); + +var MediaControllerMode360Info = function(name) { + var _serverName = name; + Object.defineProperties(this, { + enabled: { + get: function() { + var result = native_.callSync('MediaControllerMode360Info_getEnabled', { + name: _serverName + }); + if (native_.isFailure(result)) { + throw new native_.getErrorObject(result); + } + return native_.getResultObject(result); + }, + set: function(v) {}, + enumerable: true + } + }); + + this.sendRequest = function() { + var args = validator_.validateArgs(arguments, [ + { + name: 'enabled', + type: types_.BOOLEAN + }, + { + name: 'replyCallback', + type: types_.FUNCTION + } + ]); + var callback = function(result) { + native_.callIfPossible( + args.replyCallback, + native_.getResultObject(result).data, + native_.getResultObject(result).code + ); + }; + + var nativeData = { + enabled: args.enabled, + name: _serverName, + listenerId: ReplyCommandListener.listenerName + }; + + var result = native_.callSync( + 'MediaControllerMode360Info_sendRequest', + nativeData + ); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + + var replyListenerId = ReplyCommandListener.addListener(callback); + ReplyCommandListener.requestIdToListenerId[replyListenerId] = result.requestId; + }; + + this.addModeChangeListener = function(listener) { + var args = validator_.validateArgs(arguments, [ + { name: 'listener', type: types_.FUNCTION } + ]); + + if (type_.isEmptyObject(Mode360ChangeListener.listeners)) { + var result = native_.callSync( + 'MediaControllerMode360Info_addModeChangeListener', + { + listenerId: Mode360ChangeListener.listenerName + } + ); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + } + return Mode360ChangeListener.addServerInfoListener(args.listener, _serverName); + }; + + this.removeModeChangeListener = function(watchId) { + var args = validator_.validateArgs(arguments, [ + { name: 'watchId', type: types_.LONG } + ]); + + Mode360ChangeListener.removeServerInfoListener(args.watchId); + + if (type_.isEmptyObject(Mode360ChangeListener.listeners)) { + var result = native_.callSync( + 'MediaControllerMode360Info_removeModeChangeListener' + ); + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } + } + }; +}; + // TODO displayMode var MediaControllerDisplayMode = function() {}; var MediaControllerDisplayModeInfo = function() {}; @@ -1756,11 +1988,10 @@ MediaControllerClient.prototype.addAbilityChangeListener = function(callback) { } ]); - var nativeData = { - listenerId: ClientAbilityChangeListener.listenerName - }; - if (type_.isEmptyObject(ClientAbilityChangeListener.listeners)) { + var nativeData = { + listenerId: ClientAbilityChangeListener.listenerName + }; var result = native_.callSync( 'MediaControllerClient_addAbilityChangeListener', nativeData @@ -1881,7 +2112,7 @@ function MediaControllerServerInfo(data) { writable: false }, mode360: { - value: new MediaControllerMode360Info(), + value: new MediaControllerMode360Info(data.name), enumerable: true, writable: false }, diff --git a/src/mediacontroller/mediacontroller_client.cc b/src/mediacontroller/mediacontroller_client.cc index 3fb8fe5c..4fa5788e 100644 --- a/src/mediacontroller/mediacontroller_client.cc +++ b/src/mediacontroller/mediacontroller_client.cc @@ -63,6 +63,10 @@ MediaControllerClient::~MediaControllerClient() { LoggerE("Failed to unset ability listener"); } + if (nullptr != mode360_update_listener_ && !UnsetMode360InfoChangeListener()) { + LoggerE("Failed to unset mode 360 listener"); + } + if (nullptr != handle_ && MEDIA_CONTROLLER_ERROR_NONE != mc_client_destroy(handle_)) { LoggerE("Unable to destroy media controller client"); } @@ -1157,7 +1161,75 @@ PlatformResult MediaControllerClient::UnsetPlaylistUpdateListener() { } // TODO subtitles -// TODO mode360 +// mode360 +PlatformResult MediaControllerClient::GetMode360Enabled(const std::string& name, bool* enabled) { + ScopeLogger(); + + int ret = mc_client_get_server_360_mode_enabled(handle_, name.c_str(), enabled); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error getting mode 360 enabled", + ("mc_client_get_server_360_mode_enabled() error: %d, message: %s", + ret, get_error_message(ret))); + } + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult MediaControllerClient::SendMode360Enabled(const std::string& server_name, + bool enabled, const JsonCallback& reply_cb, + char** request_id) { + ScopeLogger(); + int ret = mc_client_send_360_mode_cmd(handle_, server_name.c_str(), enabled, request_id); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult( + utils::ConvertMediaControllerError(ret), "Error sending 360 mode command", + ("mc_client_send_360_mode_cmd() error: %d, message: %s", ret, get_error_message(ret))); + } + + command_reply_callback_ = reply_cb; + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult MediaControllerClient::SetMode360InfoChangeListener(const JsonCallback& callback) { + ScopeLogger(); + + int ret = mc_client_set_360_mode_updated_cb(handle_, OnMode360Update, this); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to set mode 360 listener", + ("mc_client_set_360_mode_updated_cb() error: %d, message: %s", ret, + get_error_message(ret))); + } + + mode360_update_listener_ = callback; + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult MediaControllerClient::UnsetMode360InfoChangeListener() { + ScopeLogger(); + int ret = mc_client_unset_360_mode_updated_cb(handle_); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to unset mode 360 listener", + ("mc_client_unset_360_mode_updated_cb() error: %d, message: %s", ret, + get_error_message(ret))); + } + mode360_update_listener_ = nullptr; + return PlatformResult(ErrorCode::NO_ERROR); +} + +void MediaControllerClient::OnMode360Update(const char* server_name, bool enabled, + void* user_data) { + ScopeLogger(); + MediaControllerClient* client = static_cast(user_data); + + picojson::value data = picojson::value(picojson::object()); + picojson::object& data_o = data.get(); + + data_o["enabled"] = picojson::value(enabled); + data_o["name"] = picojson::value(server_name); + + client->mode360_update_listener_(&data); +} // TODO displayMode // TODO displayRotation diff --git a/src/mediacontroller/mediacontroller_client.h b/src/mediacontroller/mediacontroller_client.h index 50c7744a..9b361776 100644 --- a/src/mediacontroller/mediacontroller_client.h +++ b/src/mediacontroller/mediacontroller_client.h @@ -74,7 +74,12 @@ class MediaControllerClient { common::PlatformResult UnsubscribeServer(const std::string& server_name); common::PlatformResult FindSubscribedServers(picojson::array* servers); // TODO subtitles - // TODO mode360 + // mode360 + common::PlatformResult GetMode360Enabled(const std::string& name, bool* enabled); + common::PlatformResult SendMode360Enabled(const std::string& server_name, bool enabled, + const JsonCallback& reply_cb, char** request_id); + common::PlatformResult SetMode360InfoChangeListener(const JsonCallback& callback); + common::PlatformResult UnsetMode360InfoChangeListener(); // TODO displayMode // TODO displayRotation @@ -86,6 +91,8 @@ class MediaControllerClient { JsonCallback command_reply_callback_; JsonCallback playlist_update_listener_; JsonCallback ability_listener_; + // mode 360 + JsonCallback mode360_update_listener_; std::list subscribed_servers; @@ -106,7 +113,8 @@ class MediaControllerClient { static void OnSimpleAbilityUpdate(const char* server_name, mc_ability_e type, mc_ability_support_e mode, void* user_data); // TODO subtitles - // TODO mode360 + // mode360 + static void OnMode360Update(const char* server_name, bool enabled, void* user_data); // TODO displayMode // TODO displayRotation }; diff --git a/src/mediacontroller/mediacontroller_instance.cc b/src/mediacontroller/mediacontroller_instance.cc index 7dd0705e..f9b35c73 100644 --- a/src/mediacontroller/mediacontroller_instance.cc +++ b/src/mediacontroller/mediacontroller_instance.cc @@ -35,10 +35,10 @@ const std::string kPrivilegeMediaControllerClient = "http://tizen.org/privilege/mediacontroller.client"; const std::string kPrivilegeMediaControllerServer = "http://tizen.org/privilege/mediacontroller.server"; - // TODO subtitles const - // TODO mode360 const - // TODO displayMode const - // TODO displayRotation const +// TODO subtitles const +// TODO mode360 const +// TODO displayMode const +// TODO displayRotation const const char* kAbilityType = "abilityType"; const char* kServerName = "serverName"; @@ -153,9 +153,21 @@ MediaControllerInstance::MediaControllerInstance() { REGISTER_ASYNC("MediaControllerPlaylist_getItems", MediaControllerPlaylistGetItems); // TODO subtitles - // TODO mode360 - // TODO displayMode - // TODO displayRotation + // mode360 + REGISTER_SYNC("MediaControllerMode360_updateEnabled", MediaControllerMode360UpdateEnabled); + REGISTER_SYNC("MediaControllerMode360_addChangeRequestListener", + MediaControllerMode360AddChangeRequestListener); + REGISTER_SYNC("MediaControllerMode360_removeChangeRequestListener", + MediaControllerMode360RemoveChangeRequestListener); + + REGISTER_SYNC("MediaControllerMode360Info_getEnabled", MediaControllerMode360InfoGetEnabled); + REGISTER_ASYNC("MediaControllerMode360Info_sendRequest", MediaControllerMode360InfoSendRequest); + REGISTER_SYNC("MediaControllerMode360Info_addModeChangeListener", + MediaControllerMode360InfoAddModeChangeListener); + REGISTER_SYNC("MediaControllerMode360Info_removeModeChangeListener", + MediaControllerMode360InfoRemoveModeChangeListener); +// TODO displayMode +// TODO displayRotation #undef REGISTER_SYNC #undef REGISTER_ASYNC @@ -1586,7 +1598,187 @@ void MediaControllerInstance::MediaControllerPlaylistGetItems(const picojson::va } // TODO subtitles -// TODO mode360 +// mode360 +void MediaControllerInstance::MediaControllerMode360UpdateEnabled(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + + if (!server_) { + LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out, + ("Failed: server_")); + return; + } + + CHECK_ARGS(args, "enabled", bool, out) + + const bool enabled = args.get("enabled").get(); + PlatformResult result = server_->UpdateMode360Enabled(enabled); + if (!result) { + LogAndReportError(result, &out, ("Failed server_->UpdateMode360Enabled()")); + return; + } + ReportSuccess(out); +} + +void MediaControllerInstance::MediaControllerMode360AddChangeRequestListener( + const picojson::value& args, picojson::object& out) { + ScopeLogger(); + if (!server_) { + LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out, + ("Failed: server_")); + return; + } + + CHECK_ARGS(args, "listenerId", std::string, out) + + JsonCallback callback = [this, args](picojson::value* data) -> void { + if (!data) { + LoggerE("No data passed to json callback"); + return; + } + picojson::object& request_o = data->get(); + request_o["listenerId"] = args.get("listenerId"); + + Instance::PostMessage(this, data->serialize().c_str()); + }; + + auto result = server_->SetMode360ChangeRequestListener(callback); + if (!result) { + LogAndReportError(result, &out); + return; + } + + ReportSuccess(out); +} + +void MediaControllerInstance::MediaControllerMode360RemoveChangeRequestListener( + const picojson::value& args, picojson::object& out) { + ScopeLogger(); + if (!server_) { + LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out, + ("Failed: server_")); + return; + } + + auto result = server_->UnsetMode360ChangeRequestListener(); + if (!result) { + LogAndReportError(result, &out); + return; + } + ReportSuccess(out); +} + +void MediaControllerInstance::MediaControllerMode360InfoGetEnabled(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + if (!client_) { + LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out, + ("Failed: client_")); + return; + } + + CHECK_ARGS(args, "name", std::string, out) + + bool enabled = false; + PlatformResult result = client_->GetMode360Enabled(args.get("name").get(), &enabled); + + if (!result) { + LogAndReportError(result, &out, ("Failed: client_->GetMode360Enabled")); + return; + } + + ReportSuccess(picojson::value(enabled), out); +} + +void MediaControllerInstance::MediaControllerMode360InfoSendRequest(const picojson::value& args, + picojson::object& out) { + ScopeLogger(); + if (!client_) { + LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out, + ("Failed: client_")); + return; + } + + CHECK_ARGS(args, "listenerId", std::string, out) + CHECK_ARGS(args, "name", std::string, out) + CHECK_ARGS(args, "enabled", bool, out) + + JsonCallback reply_cb = [this, args](picojson::value* reply) -> void { + if (reply) { + picojson::object& reply_obj = reply->get(); + reply_obj["listenerId"] = args.get("listenerId"); + Instance::PostMessage(this, reply->serialize().c_str()); + } else { + LoggerW("No reply passed to json callback, ignoring"); + } + }; + + char* request_id = nullptr; + SCOPE_EXIT { + free(request_id); + }; + + PlatformResult result = client_->SendMode360Enabled( + args.get("name").get(), args.get("enabled").get(), 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::MediaControllerMode360InfoAddModeChangeListener( + const picojson::value& args, picojson::object& out) { + ScopeLogger(); + if (!client_) { + LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occured."), &out, + ("Failed: client_")); + return; + } + + CHECK_ARGS(args, "listenerId", std::string, out) + + JsonCallback callback = [this, args](picojson::value* data) -> void { + if (nullptr == data) { + LoggerE("No data passed to json callback"); + return; + } + + picojson::object& request_o = data->get(); + request_o["listenerId"] = args.get("listenerId"); + + Instance::PostMessage(this, data->serialize().c_str()); + }; + + auto result = client_->SetMode360InfoChangeListener(callback); + if (!result) { + LogAndReportError(result, &out); + return; + } + + ReportSuccess(out); +} + +void MediaControllerInstance::MediaControllerMode360InfoRemoveModeChangeListener( + const picojson::value& args, picojson::object& out) { + ScopeLogger(); + if (!client_) { + LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occured."), &out, + ("Failed: client_")); + return; + } + + auto result = client_->UnsetMode360InfoChangeListener(); + if (!result) { + LogAndReportError(result, &out); + return; + } + + ReportSuccess(out); +} + // TODO displayMode // TODO displayRotation diff --git a/src/mediacontroller/mediacontroller_instance.h b/src/mediacontroller/mediacontroller_instance.h index c9254310..199fd2c1 100644 --- a/src/mediacontroller/mediacontroller_instance.h +++ b/src/mediacontroller/mediacontroller_instance.h @@ -120,7 +120,19 @@ class MediaControllerInstance : public common::ParsedInstance { void MediaControllerPlaylistGetItems(const picojson::value& args, picojson::object& out); // TODO subtitles - // TODO mode360 + // mode360 + void MediaControllerMode360UpdateEnabled(const picojson::value& args, picojson::object& out); + void MediaControllerMode360AddChangeRequestListener(const picojson::value& args, + picojson::object& out); + void MediaControllerMode360RemoveChangeRequestListener(const picojson::value& args, + picojson::object& out); + void MediaControllerMode360InfoGetEnabled(const picojson::value& args, picojson::object& out); + void MediaControllerMode360InfoSendRequest(const picojson::value& args, picojson::object& out); + void MediaControllerMode360InfoAddModeChangeListener(const picojson::value& args, + picojson::object& out); + void MediaControllerMode360InfoRemoveModeChangeListener(const picojson::value& args, + picojson::object& out); + // TODO displayMode // TODO displayRotation diff --git a/src/mediacontroller/mediacontroller_server.cc b/src/mediacontroller/mediacontroller_server.cc index 9f1a86b3..2a4cc72a 100644 --- a/src/mediacontroller/mediacontroller_server.cc +++ b/src/mediacontroller/mediacontroller_server.cc @@ -40,14 +40,7 @@ MediaControllerServer::MediaControllerServer() shuffle_mode_(MC_SHUFFLE_MODE_OFF), repeat_mode_(MC_REPEAT_MODE_OFF), is_shuffle_mode_set_(false), - is_repeat_mode_set_(false), - playback_abilities_{MC_ABILITY_SUPPORTED_UNDECIDED, MC_ABILITY_SUPPORTED_UNDECIDED, - MC_ABILITY_SUPPORTED_UNDECIDED, MC_ABILITY_SUPPORTED_UNDECIDED, - MC_ABILITY_SUPPORTED_UNDECIDED, MC_ABILITY_SUPPORTED_UNDECIDED, - MC_ABILITY_SUPPORTED_UNDECIDED, MC_ABILITY_SUPPORTED_UNDECIDED}, - simple_abilities_{MC_ABILITY_SUPPORTED_UNDECIDED, MC_ABILITY_SUPPORTED_UNDECIDED, - MC_ABILITY_SUPPORTED_UNDECIDED, MC_ABILITY_SUPPORTED_UNDECIDED, - MC_ABILITY_SUPPORTED_UNDECIDED, MC_ABILITY_SUPPORTED_UNDECIDED} { + is_repeat_mode_set_(false) { ScopeLogger(); } @@ -67,6 +60,10 @@ MediaControllerServer::~MediaControllerServer() { LoggerE("Failed to unset search request listener"); } + if (nullptr != mode360_change_request_listener_ && !UnsetMode360ChangeRequestListener()) { + LoggerE("Failed to unset mode 360 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()); @@ -667,9 +664,14 @@ PlatformResult MediaControllerServer::MediaControllerPlaylistGetItems(const std: } PlatformResult MediaControllerServer::SetPlaybackAbility(const std::string& action, - const std::string& support_str) { + const std::string& support_str, + bool* is_changed) { ScopeLogger(); PlatformResult result = PlatformResult(ErrorCode::NO_ERROR); + // UNDECIDED should not be used while setting playback ability, thus we skip these cases + if (support_str == "UNDECIDED") { + return result; + } mc_playback_action_e action_e; // Currently MediaControllerPlaybackActionEnum does not have member "TOGGLE_PLAY_PAUSE". @@ -693,9 +695,11 @@ PlatformResult MediaControllerServer::SetPlaybackAbility(const std::string& acti result.message().c_str())); } - if (support == playback_abilities_.get(action)) { - LoggerD("No change in playback ability support, skipping"); - return PlatformResult(ErrorCode::NO_ERROR); + if (abilities_.end() != abilities_.find(action)) { + if (support == abilities_[action]) { + LoggerD("No change in ability support, skipping"); + return PlatformResult(ErrorCode::NO_ERROR); + } } int ret = mc_server_set_playback_ability(handle_, action_e, support); @@ -705,35 +709,37 @@ PlatformResult MediaControllerServer::SetPlaybackAbility(const std::string& acti ("mc_server_set_playback_ability() error: %d, message: %s", ret, get_error_message(ret))); } - playback_abilities_.set(action, support); + abilities_[action] = support; + *is_changed = true; return PlatformResult(ErrorCode::NO_ERROR); } PlatformResult MediaControllerServer::SavePlaybackAbilities(const picojson::value& abilities) { ScopeLogger(); - + bool is_changed = false; // Currently MediaControllerPlaybackActionEnum does not have member "TOGGLE_PLAY_PAUSE". // It should be fixed in the future. - PlatformResult result = SetPlaybackAbility("TOGGLE_PLAY_PAUSE", - abilities.get("TOGGLE_PLAY_PAUSE").get()); + PlatformResult result = SetPlaybackAbility( + "TOGGLE_PLAY_PAUSE", abilities.get("TOGGLE_PLAY_PAUSE").get(), &is_changed); if (!result) { return result; } - for (auto action : types::MediaControllerPlaybackActionEnum) { const std::string& action_str = action.first.c_str(); const std::string& support_str = abilities.get(action_str).get(); - result = SetPlaybackAbility(action_str, support_str); + result = SetPlaybackAbility(action_str, support_str, &is_changed); if (!result) { return result; } } - int ret = mc_server_update_playback_ability(handle_); - if (MEDIA_CONTROLLER_ERROR_NONE != ret) { - return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error updating playback ability", - ("mc_server_update_playback_ability() error: %d, message: %s", ret, - get_error_message(ret))); + if (is_changed) { + int ret = mc_server_update_playback_ability(handle_); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error updating playback ability", + ("mc_server_update_playback_ability() error: %d, message: %s", ret, + get_error_message(ret))); + } } return PlatformResult(ErrorCode::NO_ERROR); } @@ -751,11 +757,11 @@ PlatformResult MediaControllerServer::SetSimpleAbility(const std::string& abilit result.message().c_str())); } - mc_ability_support_e current_ability = simple_abilities_.get(ability_type); - - if (support_e == current_ability) { - LoggerD("No change in ability support, skipping"); - return PlatformResult(ErrorCode::NO_ERROR); + if (abilities_.end() != abilities_.find(ability_type)) { + if (support_e == abilities_[ability_type]) { + LoggerD("No change in ability support, skipping"); + return PlatformResult(ErrorCode::NO_ERROR); + } } mc_ability_e ability_e; @@ -773,7 +779,7 @@ PlatformResult MediaControllerServer::SetSimpleAbility(const std::string& abilit ("mc_server_set_ability_support() error: %d, message: %s", ret, get_error_message(ret))); } - simple_abilities_.set(ability_type, support_e); + abilities_[ability_type] = support_e; return PlatformResult(ErrorCode::NO_ERROR); } @@ -1048,7 +1054,64 @@ void MediaControllerServer::OnPlaybackItemCommand(const char* client_name, const } // TODO subtitles -// TODO mode360 +// mode360 +common::PlatformResult MediaControllerServer::UpdateMode360Enabled(bool enabled) { + ScopeLogger(); + int ret = mc_server_update_360_mode_enabled(handle_, enabled); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error setting server mode 360", + ("mc_server_update_360_mode_enabled() error: %d, message: %s", ret, + get_error_message(ret))); + } + return PlatformResult(ErrorCode::NO_ERROR); +} + +void MediaControllerServer::OnMode360ChangeCommand(const char* client_name, const char* request_id, + bool enabled, void* user_data) { + ScopeLogger(); + + MediaControllerServer* server = static_cast(user_data); + + picojson::value data = picojson::value(picojson::object()); + picojson::object& data_o = data.get(); + + data_o["enabled"] = picojson::value(enabled); + data_o["clientName"] = picojson::value(client_name); + data_o["requestId"] = picojson::value(std::string(request_id)); + + server->mode360_change_request_listener_(&data); +} + +PlatformResult MediaControllerServer::SetMode360ChangeRequestListener( + const JsonCallback& callback) { + ScopeLogger(); + + int ret = mc_server_set_360_mode_cmd_received_cb(handle_, OnMode360ChangeCommand, this); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to set mode 360 command listener", + ("mc_server_set_360_mode_cmd_received_cb() error: %d, message: %s", + ret, get_error_message(ret))); + } + + mode360_change_request_listener_ = callback; + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult MediaControllerServer::UnsetMode360ChangeRequestListener() { + ScopeLogger(); + + int ret = mc_server_unset_360_mode_cmd_received_cb(handle_); + if (MEDIA_CONTROLLER_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to unset mode 360 command listener", + ("mc_server_unset_360_mode_cmd_received_cb() error: %d, message: %s", + ret, get_error_message(ret))); + } + mode360_change_request_listener_ = nullptr; + + return PlatformResult(ErrorCode::NO_ERROR); +} + // TODO displayMode // TODO displayRotation diff --git a/src/mediacontroller/mediacontroller_server.h b/src/mediacontroller/mediacontroller_server.h index 3889682a..7c79faa3 100644 --- a/src/mediacontroller/mediacontroller_server.h +++ b/src/mediacontroller/mediacontroller_server.h @@ -26,143 +26,6 @@ namespace extension { namespace mediacontroller { -namespace { -const char* kPlay = "PLAY"; -const char* kPause = "PAUSE"; -const char* kStop = "STOP"; -const char* kNext = "NEXT"; -const char* kPrev = "PREV"; -const char* kForward = "FORWARD"; -const char* kRewind = "REWIND"; -const char* kTogglePlayPause = "TOGGLE_PLAY_PAUSE"; - -const char* kPlaybackPosition = "PLAYBACK_POSITION"; -const char* kShuffle = "SHUFFLE"; -const char* kRepeat = "REPEAT"; -const char* kPlaylist = "PLAYLIST"; -const char* kClientCustom = "CLIENT_CUSTOM"; -const char* kSearch = "SEARCH"; - -} // namespace - -struct playback_abilities { - mc_ability_support_e play_; - mc_ability_support_e pause_; - mc_ability_support_e stop_; - mc_ability_support_e next_; - mc_ability_support_e prev_; - mc_ability_support_e forward_; - mc_ability_support_e rewind_; - mc_ability_support_e toggle_play_pause_; - - mc_ability_support_e get(const std::string& ability) { - if (kPlay == ability) { - return play_; - } - if (kPause == ability) { - return pause_; - } - if (kStop == ability) { - return stop_; - } - if (kNext == ability) { - return next_; - } - if (kPrev == ability) { - return prev_; - } - if (kForward == ability) { - return forward_; - } - if (kRewind == ability) { - return rewind_; - } - if (kTogglePlayPause == ability) { - return toggle_play_pause_; - } - return MC_ABILITY_SUPPORTED_UNDECIDED; - } - - void set(const std::string& action, mc_ability_support_e val) { - if (kPlay == action) { - play_ = val; - } - if (kPause == action) { - pause_ = val; - } - if (kStop == action) { - stop_ = val; - } - if (kNext == action) { - next_ = val; - } - if (kPrev == action) { - prev_ = val; - } - if (kForward == action) { - forward_ = val; - } - if (kRewind == action) { - rewind_ = val; - } - if (kTogglePlayPause == action) { - toggle_play_pause_ = val; - } - } -}; - -struct simple_abilities { - mc_ability_support_e playback_position_; - mc_ability_support_e shuffle_; - mc_ability_support_e repeat_; - mc_ability_support_e playlist_; - mc_ability_support_e custom_command_; - mc_ability_support_e search_; - - mc_ability_support_e get(const std::string& ability) { - if (kPlaybackPosition == ability) { - return playback_position_; - } - if (kShuffle == ability) { - return shuffle_; - } - if (kRepeat == ability) { - return repeat_; - } - if (kPlaylist == ability) { - return playlist_; - } - if (kClientCustom == ability) { - return custom_command_; - } - if (kSearch == ability) { - return search_; - } - return MC_ABILITY_SUPPORTED_UNDECIDED; - } - - void set(const std::string& ability, mc_ability_support_e val) { - if (kPlaybackPosition == ability) { - playback_position_ = val; - } - if (kShuffle == ability) { - shuffle_ = val; - } - if (kRepeat == ability) { - repeat_ = val; - } - if (kPlaylist == ability) { - playlist_ = val; - } - if (kClientCustom == ability) { - custom_command_ = val; - } - if (kSearch == ability) { - search_ = val; - } - } -}; - class MediaControllerServer { public: MediaControllerServer(); @@ -202,12 +65,15 @@ class MediaControllerServer { picojson::array* items); common::PlatformResult UpdateIconURI(const char* icon_uri); common::PlatformResult SetPlaybackAbility(const std::string& action, - const std::string& support_str); + const std::string& support_str, bool* is_changed); common::PlatformResult SavePlaybackAbilities(const picojson::value& abilities); common::PlatformResult SetSimpleAbility(const std::string& ability_type, const std::string& support_str); // TODO subtitles - // TODO mode360 + // mode360 + common::PlatformResult UpdateMode360Enabled(bool enabled); + common::PlatformResult SetMode360ChangeRequestListener(const JsonCallback& callback); + common::PlatformResult UnsetMode360ChangeRequestListener(); // TODO displayMode // TODO displayRotation private: @@ -222,8 +88,7 @@ class MediaControllerServer { mc_repeat_mode_e repeat_mode_; bool is_shuffle_mode_set_; bool is_repeat_mode_set_; - playback_abilities playback_abilities_; - simple_abilities simple_abilities_; + std::map abilities_; JsonCallback command_listener_; std::map playlist_handle_map_; @@ -247,7 +112,10 @@ class MediaControllerServer { static void OnCommandReceived(const char* client_name, const char* request_id, const char* command, bundle* data, void* user_data); // TODO subtitles - // TODO mode360 + // mode360 + JsonCallback mode360_change_request_listener_; + static void OnMode360ChangeCommand(const char* client_name, const char* request_id, bool enabled, + void* user_data); // TODO displayMode // TODO displayRotation }; diff --git a/src/mediacontroller/mediacontroller_utils.cc b/src/mediacontroller/mediacontroller_utils.cc index 8bf61a7e..4aa1d0ca 100644 --- a/src/mediacontroller/mediacontroller_utils.cc +++ b/src/mediacontroller/mediacontroller_utils.cc @@ -110,7 +110,8 @@ const common::PlatformEnum MediaControllerSimpleAbilityEnum{ {"REPEAT", MC_ABILITY_REPEAT}, {"PLAYLIST", MC_ABILITY_PLAYLIST}, {"CLIENT_CUSTOM", MC_ABILITY_CLIENT_CUSTOM}, - {"SEARCH", MC_ABILITY_SEARCH}}; + {"SEARCH", MC_ABILITY_SEARCH}, + {"MODE_360", MC_ABILITY_360_MODE}}; PlatformResult ConvertPlaybackState(mc_playback_h playback_h, std::string* state) { ScopeLogger(); @@ -293,5 +294,20 @@ PlatformResult utils::GetAllPlaylists(const std::string& app_id, picojson::array return PlatformResult(ErrorCode::NO_ERROR); } +ErrorCode utils::ConvertMediaControllerError(int e) { + ScopeLogger(); + ErrorCode error; + + switch (e) { + case MEDIA_CONTROLLER_ERROR_ABILITY_LIMITED_BY_SERVER_APP: + error = ErrorCode::NOT_SUPPORTED_ERR; + break; + default: + error = ErrorCode::UNKNOWN_ERR; + break; + } + return error; +} + } // namespace mediacontroller } // namespace extension diff --git a/src/mediacontroller/mediacontroller_utils.h b/src/mediacontroller/mediacontroller_utils.h index 6d98e884..cc570d57 100644 --- a/src/mediacontroller/mediacontroller_utils.h +++ b/src/mediacontroller/mediacontroller_utils.h @@ -56,6 +56,7 @@ extern const common::PlatformEnum MediaControllerSimpleAbilityEnum namespace utils { common::PlatformResult GetAllPlaylists(const std::string& app_id, picojson::array* playlists); +common::ErrorCode ConvertMediaControllerError(int e); } } // namespace mediacontroller