this.native.addListener(this.listenerName, function(msg) {
for (var watchId in this.listeners) {
if (this.listeners.hasOwnProperty(watchId)) {
- this.handle(msg, this.listeners[watchId], watchId);
+ var stop = this.handle(msg, this.listeners[watchId], watchId);
+ if (stop) {
+ break;
+ }
}
}
}.bind(this));
};
var ServerCommandListener = new ListenerManager(native_, '_ServerCommandListener', function(msg, listener) {
- var d = native_.getResultObject(msg);
- var data = listener(d.clientName, d.command, d.data);
+ var data = listener(msg.clientName, msg.command, msg.data);
+
+ if (type_.isNullOrUndefined(data)) {
+ return;
+ }
var nativeData = {
- clientName: d.clientName,
+ clientName: msg.clientName,
+ replyId: msg.replyId,
data: data
};
});
var ReplyCommandListener = new ListenerManager(native_, '_ReplyCommandListener', function(msg, listener, watchId) {
- listener(msg.reply);
- this.removeListener(watchId);
+ if (msg.replyId === watchId) {
+ listener(msg.data);
+ this.removeListener(watchId);
+ return true;
+ }
+
+ return false;
});
var ServerPlaybackInfoListener = new ListenerManager(native_, '_ServerPlaybackInfoListener', function(msg, listener) {
#include "mediacontroller/mediacontroller_client.h"
+#include <bundle.h>
+#include <memory>
+
#include "common/logger.h"
#include "common/scope_exit.h"
int ret;
- char* name;
+ char* name = nullptr;
+ SCOPE_EXIT {
+ free(name);
+ };
mc_server_state_e state;
ret = mc_client_get_latest_server_info(handle_, &name, &state);
if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
"Error getting latest server info");
}
- if (NULL == name) {
+ if (!name) {
LOGGER(DEBUG) << "No active server available";
return PlatformResult(ErrorCode::NO_ERROR);
}
- SCOPE_EXIT {
- free(name);
- };
-
std::string state_str;
PlatformResult result = Types::PlatformEnumToString(
Types::kMediaControllerServerState, static_cast<int>(state), &state_str);
client->playback_info_listener_(&data);
}
+PlatformResult MediaControllerClient::SendCommand(
+ const std::string& server_name,
+ const std::string& command,
+ const picojson::value& data,
+ const std::string& reply_id,
+ const JsonCallback& reply_cb) {
+ LOGGER(DEBUG) << "entered";
+
+ int ret;
+
+ bundle* bundle = bundle_create();
+ SCOPE_EXIT {
+ bundle_free(bundle);
+ };
+
+ ret = bundle_add(bundle, "replyId", reply_id.c_str());
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "bundle_add(replyId) failed, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Unable to add replyId to bundle");
+ }
+
+ ret = bundle_add(bundle, "data", data.serialize().c_str());
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "bundle_add(data) failed, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Unable to add data to bundle");
+ }
+
+ ret = mc_client_send_custom_command(handle_,
+ server_name.c_str(),
+ command.c_str(),
+ bundle,
+ OnCommandReply,
+ this);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "mc_client_send_custom_command failed, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Error sending custom command");
+ }
+
+ command_reply_callback_ = reply_cb;
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void MediaControllerClient::OnCommandReply(const char* server_name,
+ int result_code,
+ bundle* bundle,
+ void* user_data) {
+ LOGGER(DEBUG) << "entered";
+
+ MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+ picojson::value reply = picojson::value(picojson::object());
+ picojson::object& reply_o = reply.get<picojson::object>();
+
+ int ret;
+ char* reply_id_str = nullptr;
+ char* data_str = nullptr;
+ SCOPE_EXIT {
+ free(reply_id_str);
+ free(data_str);
+ };
+
+ ret = bundle_get_str(bundle, "replyId", &reply_id_str);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "bundle_get_str(replyId) failed, error: " << ret;
+ return;
+ }
+
+ reply_o["replyId"] = picojson::value(std::string(reply_id_str));
+
+ ret = bundle_get_str(bundle, "data", &data_str);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "bundle_get_str(data) failed, error: " << ret;
+ return;
+ }
+
+ picojson::value data;
+ std::string err;
+ picojson::parse(data, data_str, data_str + strlen(data_str), &err);
+ if (!err.empty()) {
+ LOGGER(ERROR) << "Failed to parse bundle data: " << err;
+ return;
+ }
+ reply_o["data"] = data;
+
+ client->command_reply_callback_(&reply);
+}
+
PlatformResult MediaControllerClient::SendPlaybackState(
const std::string& server_name,
const std::string& state) {
common::PlatformResult SendPlaybackState(const std::string& server_name,
const std::string& state);
+ common::PlatformResult SendCommand(const std::string& server_name,
+ const std::string& command,
+ const picojson::value& data,
+ const std::string& reply_id,
+ const JsonCallback& reply_cb);
+
common::PlatformResult SetServerStatusChangeListener(JsonCallback callback);
common::PlatformResult SetPlaybackInfoListener(JsonCallback callback);
private:
mc_client_h handle_;
+
JsonCallback playback_info_listener_;
JsonCallback server_status_listener_;
+ JsonCallback command_reply_callback_;
static bool FindServersCallback(const char* server_name, void* user_data);
static void OnServerStatusUpdate(const char *server_name,
mc_server_state_e state,
void *user_data);
+ static void OnCommandReply(const char* server_name,
+ int result_code,
+ bundle* bundle,
+ void* user_data);
static void OnPlaybackUpdate(const char *server_name,
mc_playback_h playback,
void *user_data);
MediaControllerServerRemoveChangeRequestPlaybackInfoListener);
REGISTER_SYNC("MediaControllerServer_addCommandListener",
MediaControllerServerAddCommandListener);
+ REGISTER_SYNC("MediaControllerServer_replyCommand",
+ MediaControllerServerReplyCommand);
REGISTER_SYNC("MediaControllerServer_removeCommandListener",
MediaControllerServerRemoveCommandListener);
void MediaControllerInstance::MediaControllerServerAddCommandListener(
const picojson::value& args,
picojson::object& out) {
+ LOGGER(DEBUG) << "entered";
- // implement it
+ if (!server_) {
+ ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+ "Server not initialized."), &out);
+ return;
+ }
- // if success
- // ReportSuccess(out);
- // if error
- // ReportError(out);
+ JsonCallback on_command = [this, args](picojson::value* request) -> void {
+ LOGGER(DEBUG) << "entered";
+
+ picojson::object& request_o = request->get<picojson::object>();
+ request_o["listenerId"] = args.get("listenerId");
+
+ PostMessage(request->serialize().c_str());
+ };
+
+ server_->set_command_listener(on_command);
+
+ ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerReplyCommand(
+ const picojson::value& args,
+ picojson::object& out) {
+ LOGGER(DEBUG) << "entered";
+
+ if (!server_) {
+ ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+ "Server not initialized."), &out);
+ return;
+ }
+
+ CHECK_EXIST(args, "clientName", out)
+ CHECK_EXIST(args, "replyId", out)
+ CHECK_EXIST(args, "data", out)
+
+ server_->CommandReply(args.get("clientName").get<std::string>(),
+ args.get("replyId").to_str(),
+ args.get("data"));
+
+ ReportSuccess(out);
}
void MediaControllerInstance::MediaControllerServerRemoveCommandListener(
const picojson::value& args,
picojson::object& out) {
- CHECK_EXIST(args, "watchId", out)
+ LOGGER(DEBUG) << "entered";
- double watchId = args.get("watchId").get<double>();
+ if (!server_) {
+ ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+ "Server not initialized."), &out);
+ return;
+ }
- // implement it
+ server_->set_command_listener(nullptr);
- // if success
- // ReportSuccess(out);
- // if error
- // ReportError(out);
+ ReportSuccess(out);
}
void MediaControllerInstance::MediaControllerManagerGetClient(
void MediaControllerInstance::MediaControllerServerInfoSendCommand(
const picojson::value& args,
picojson::object& out) {
- CHECK_EXIST(args, "callbackId", out)
+
+ if (!client_) {
+ LOGGER(ERROR) << "Client not initialized.";
+ ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+ "Client not initialized."), &out);
+ return;
+ }
+
+ CHECK_EXIST(args, "listenerId", out)
+ CHECK_EXIST(args, "replyId", out)
+ CHECK_EXIST(args, "name", out)
CHECK_EXIST(args, "command", out)
CHECK_EXIST(args, "data", out)
- int callbackId = static_cast<int>(args.get("callbackId").get<double>());
- const std::string& command = args.get("command").get<std::string>();
- const picojson::object data = args.get("data").get<picojson::object>();
+ JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
+ LOGGER(DEBUG) << "entered";
- // implement it
+ picojson::object& reply_obj = reply->get<picojson::object>();
- // call ReplyAsync in later (Asynchronously)
+ reply_obj["listenerId"] = args.get("listenerId");
- // if success
- // ReportSuccess(out);
- // if error
- // ReportError(out);
+ PostMessage(reply->serialize().c_str());
+ };
+
+ PlatformResult result = client_->SendCommand(
+ args.get("name").get<std::string>(),
+ args.get("command").get<std::string>(),
+ args.get("data"),
+ args.get("replyId").to_str(),
+ reply_cb);
+
+ if (result) {
+ ReportSuccess(out);
+ } else {
+ ReportError(result, &out);
+ }
}
void MediaControllerInstance::MediaControllerServerInfoAddServerStatusChangeListener(
void MediaControllerServerAddChangeRequestPlaybackInfoListener(const picojson::value& args, picojson::object& out);
void MediaControllerServerRemoveChangeRequestPlaybackInfoListener(const picojson::value& args, picojson::object& out);
void MediaControllerServerAddCommandListener(const picojson::value& args, picojson::object& out);
+ void MediaControllerServerReplyCommand(const picojson::value& args, picojson::object& out);
void MediaControllerServerRemoveCommandListener(const picojson::value& args, picojson::object& out);
// client
#include "mediacontroller/mediacontroller_server.h"
+#include <bundle.h>
+
#include "common/logger.h"
+#include "common/scope_exit.h"
#include "mediacontroller/mediacontroller_types.h"
MediaControllerServer::~MediaControllerServer() {
if (handle_) {
- int ret = mc_server_destroy(handle_);
+ int ret;
+ ret = mc_server_unset_custom_command_received_cb(handle_);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "Unable to unset command callback, error: " << ret;
+ }
+
+ ret = mc_server_destroy(handle_);
if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
- LOGGER(ERROR) << "Unable to destroy media controller server";
+ LOGGER(ERROR) << "mc_server_destroy() failed, error: " << ret;
}
}
}
-common::PlatformResult MediaControllerServer::Init() {
- PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+PlatformResult MediaControllerServer::Init() {
int ret = mc_server_create(&handle_);
if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
LOGGER(ERROR) << "Unable to create media controller server, error: " << ret;
- result = PlatformResult(ErrorCode::UNKNOWN_ERR,
- "Unable to create media controller server");
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Unable to create media controller server");
+ }
+
+ ret = mc_server_set_custom_command_received_cb(handle_,
+ OnCommandReceived,
+ this);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "Unable to set command callback, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Unable to set command callback");
}
- return result;
+ return PlatformResult(ErrorCode::NO_ERROR);
}
-common::PlatformResult MediaControllerServer::SetPlaybackState(
+PlatformResult MediaControllerServer::SetPlaybackState(
const std::string& state) {
int state_int;
return PlatformResult(ErrorCode::NO_ERROR);
}
-common::PlatformResult MediaControllerServer::SetPlaybackPosition(
- double position) {
+PlatformResult MediaControllerServer::SetPlaybackPosition(double position) {
int ret = mc_server_set_playback_position(
handle_, static_cast<unsigned long long>(position));
return PlatformResult(ErrorCode::NO_ERROR);
}
-common::PlatformResult MediaControllerServer::SetShuffleMode(bool mode) {
+PlatformResult MediaControllerServer::SetShuffleMode(bool mode) {
int ret = mc_server_update_shuffle_mode(handle_,
mode ? SHUFFLE_MODE_ON
return PlatformResult(ErrorCode::NO_ERROR);
}
-common::PlatformResult MediaControllerServer::SetRepeatMode(bool mode) {
+PlatformResult MediaControllerServer::SetRepeatMode(bool mode) {
int ret = mc_server_update_repeat_mode(handle_,
mode ? REPEAT_MODE_ON
return PlatformResult(ErrorCode::NO_ERROR);
}
-common::PlatformResult MediaControllerServer::SetMetadata(
+PlatformResult MediaControllerServer::SetMetadata(
const picojson::object& metadata) {
int attribute_int, ret;
- PlatformResult result(ErrorCode::NO_ERROR);
for (picojson::object::const_iterator i = metadata.begin();
i != metadata.end();
++i) {
- result = Types::StringToPlatformEnum(
+ PlatformResult result = Types::StringToPlatformEnum(
Types::kMediaControllerMetadataAttribute, i->first, &attribute_int);
if (!result) {
return result;
return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error updating metadata");
}
- return result;
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void MediaControllerServer::OnCommandReceived(const char* client_name,
+ const char* command,
+ bundle* bundle,
+ void* user_data) {
+ LOGGER(DEBUG) << "entered";
+
+ MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
+
+ if (server->command_listener_) {
+ picojson::value request = picojson::value(picojson::object());
+ picojson::object& request_o = request.get<picojson::object>();
+
+ int ret;
+ char* reply_id_str = nullptr;
+ char* data_str = nullptr;
+ SCOPE_EXIT {
+ free(reply_id_str);
+ free(data_str);
+ };
+
+ ret = bundle_get_str(bundle, "replyId", &reply_id_str);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "bundle_get_str(replyId) failed, error: " << ret;
+ return;
+ }
+
+ ret = bundle_get_str(bundle, "data", &data_str);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "bundle_get_str(data) failed, error: " << ret;
+ return;
+ }
+
+ picojson::value data;
+ std::string err;
+ picojson::parse(data, data_str, data_str + strlen(data_str), &err);
+ if (!err.empty()) {
+ LOGGER(ERROR) << "Failed to parse bundle data: " << err;
+ return;
+ }
+
+ request_o["clientName"] = picojson::value(std::string(client_name));
+ request_o["command"] = picojson::value(std::string(command));
+ request_o["replyId"] = picojson::value(std::string(reply_id_str));
+ request_o["data"] = data;
+
+ server->command_listener_(&request);
+ }
+}
+
+PlatformResult MediaControllerServer::CommandReply(
+ const std::string& client_name,
+ const std::string& reply_id,
+ const picojson::value& data) {
+ LOGGER(DEBUG) << "entered";
+
+ int ret;
+
+ bundle* bundle = bundle_create();
+ SCOPE_EXIT {
+ bundle_free(bundle);
+ };
+
+ ret = bundle_add(bundle, "replyId", reply_id.c_str());
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "bundle_add(replyId) failed, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Unable to add replyId to bundle");
+ }
+
+ ret = bundle_add(bundle, "data", data.serialize().c_str());
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "bundle_add(data) failed, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Unable to add data to bundle");
+ }
+
+ ret = mc_server_send_command_reply(handle_, client_name.c_str(), 0, bundle, NULL);
+ if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+ LOGGER(ERROR) << "mc_server_send_command_reply failed, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error sending command reply");
+ }
+
+ return PlatformResult(ErrorCode::NO_ERROR);
}
PlatformResult MediaControllerServer::SetChangeRequestPlaybackInfoListener(
common::PlatformResult SetChangeRequestPlaybackInfoListener(
JsonCallback callback);
+ common::PlatformResult CommandReply(const std::string& client_name,
+ const std::string& reply_id,
+ const picojson::value& data);
+
+ void set_command_listener(const JsonCallback& func) {
+ command_listener_ = func;
+ }
+
private:
mc_server_h handle_;
+
JsonCallback change_request_playback_info_listener_;
+ JsonCallback command_listener_;
static void OnPlaybackStateCommand(const char* client_name,
mc_playback_states_e state_e,
void *user_data);
+ static void OnCommandReceived(const char* client_name,
+ const char* command,
+ bundle* data,
+ void* user_data);
};
} // namespace mediacontroller
return result;
}
- char* value;
+ char* value = nullptr;
SCOPE_EXIT {
- free(value);
+ free(value);
};
int ret;