[Mediacontroller] added mode 360 feature 30/213330/19
authorPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/삼성전자 <p.kosko@samsung.com>
Thu, 5 Sep 2019 05:21:53 +0000 (07:21 +0200)
committerPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/삼성전자 <p.kosko@samsung.com>
Thu, 19 Sep 2019 09:13:51 +0000 (11:13 +0200)
[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

src/mediacontroller/mediacontroller_api.js
src/mediacontroller/mediacontroller_client.cc
src/mediacontroller/mediacontroller_client.h
src/mediacontroller/mediacontroller_instance.cc
src/mediacontroller/mediacontroller_instance.h
src/mediacontroller/mediacontroller_server.cc
src/mediacontroller/mediacontroller_server.h
src/mediacontroller/mediacontroller_utils.cc
src/mediacontroller/mediacontroller_utils.h

index 1766ee9..1d3f2fa 100755 (executable)
@@ -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
         },
index 3fb8fe5..4fa5788 100644 (file)
@@ -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<MediaControllerClient*>(user_data);
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["enabled"] = picojson::value(enabled);
+  data_o["name"] = picojson::value(server_name);
+
+  client->mode360_update_listener_(&data);
+}
 // TODO displayMode
 // TODO displayRotation
 
index 50c7744..9b36177 100644 (file)
@@ -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<std::string> 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
 };
index 7dd0705..f9b35c7 100644 (file)
@@ -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<bool>();
+  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<picojson::object>();
+    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<std::string>(), &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<picojson::object>();
+      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<std::string>(), args.get("enabled").get<bool>(), 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<picojson::object>();
+    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
 
index c925431..199fd2c 100644 (file)
@@ -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
 
index 9f1a86b..2a4cc72 100644 (file)
@@ -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<std::string>());
+  PlatformResult result = SetPlaybackAbility(
+      "TOGGLE_PLAY_PAUSE", abilities.get("TOGGLE_PLAY_PAUSE").get<std::string>(), &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<std::string>();
-    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<MediaControllerServer*>(user_data);
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  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
 
index 3889682..7c79faa 100644 (file)
 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<std::string, mc_ability_support_e> abilities_;
 
   JsonCallback command_listener_;
   std::map<std::string, mc_playlist_h> 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
 };
index 8bf61a7..4aa1d0c 100644 (file)
@@ -110,7 +110,8 @@ const common::PlatformEnum<mc_ability_e> 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
index 6d98e88..cc570d5 100644 (file)
@@ -56,6 +56,7 @@ extern const common::PlatformEnum<mc_ability_e> MediaControllerSimpleAbilityEnum
 
 namespace utils {
 common::PlatformResult GetAllPlaylists(const std::string& app_id, picojson::array* playlists);
+common::ErrorCode ConvertMediaControllerError(int e);
 }
 
 }  // namespace mediacontroller