}
);
+var ClientAbilityChangeListener = new ListenerManager(
+ native_,
+ '_ClientAbilityChangeListener',
+ function(msg, listener) {
+ if (msg.action === 'onplaybackabilitychanged') {
+ native_.callIfPossible(
+ listener[msg.action],
+ new MediaControllerServerInfo(msg),
+ new MediaControllerPlaybackAbilitiesInfo(msg.name)
+ );
+ }
+ if (msg.action === 'onsimpleabilitychanged') {
+ native_.callIfPossible(
+ listener[msg.action],
+ new MediaControllerServerInfo(msg),
+ msg.type,
+ msg.ability
+ );
+ }
+ }
+);
+
var EditManager = function() {
this.isAllowed = false;
};
UNDECIDED: 'UNDECIDED'
};
+var MediaControllerAbilitySupport = {
+ YES: 'YES',
+ NO: 'NO',
+ UNDECIDED: 'UNDECIDED'
+};
+
+var MediaControllerSimpleAbility = {
+ PLAYBACK_POSITION: 'PLAYBACK_POSITION',
+ SHUFFLE: 'SHUFFLE',
+ REPEAT: 'REPEAT',
+ PLAYLIST: 'PLAYLIST',
+ CLIENT_CUSTOM: 'CLIENT_CUSTOM',
+ SEARCH: 'SEARCH'
+};
+
function MediaControllerManager() {}
MediaControllerManager.prototype.getClient = function() {
}
};
+var MediaControllerAbilities = function() {
+ var _playbackPosition = MediaControllerAbilitySupport.UNDECIDED,
+ _shuffle = MediaControllerAbilitySupport.UNDECIDED,
+ _repeat = MediaControllerAbilitySupport.UNDECIDED,
+ _playlist = MediaControllerAbilitySupport.UNDECIDED,
+ _clientCustom = MediaControllerAbilitySupport.UNDECIDED,
+ _search = MediaControllerAbilitySupport.UNDECIDED;
+
+ Object.defineProperties(this, {
+ playback: {
+ value: new MediaControllerPlaybackAbilities(),
+ enumerable: true
+ },
+ playbackPosition: {
+ get: function() {
+ return _playbackPosition;
+ },
+ set: function(val) {
+ setSimpleAbility(MediaControllerSimpleAbility.PLAYBACK_POSITION, val);
+ _playbackPosition = val;
+ },
+ enumerable: true
+ },
+ shuffle: {
+ get: function() {
+ return _shuffle;
+ },
+ set: function(val) {
+ setSimpleAbility(MediaControllerSimpleAbility.SHUFFLE, val);
+ _shuffle = val;
+ },
+ enumerable: true
+ },
+ repeat: {
+ get: function() {
+ return _repeat;
+ },
+ set: function(val) {
+ setSimpleAbility(MediaControllerSimpleAbility.REPEAT, val);
+ _repeat = val;
+ },
+ enumerable: true
+ },
+ playlist: {
+ get: function() {
+ return _playlist;
+ },
+ set: function(val) {
+ setSimpleAbility(MediaControllerSimpleAbility.PLAYLIST, val);
+ _playlist = val;
+ },
+ enumerable: true
+ },
+ clientCustom: {
+ get: function() {
+ return _clientCustom;
+ },
+ set: function(val) {
+ setSimpleAbility(MediaControllerSimpleAbility.CLIENT_CUSTOM, val);
+ _clientCustom = val;
+ },
+ enumerable: true
+ },
+ search: {
+ get: function() {
+ return _search;
+ },
+ set: function(val) {
+ setSimpleAbility(MediaControllerSimpleAbility.SEARCH, val);
+ _search = val;
+ },
+ enumerable: true
+ }
+ });
+};
+
+var MediaControllerPlaybackAbilities = function() {
+ var _play = MediaControllerAbilitySupport.UNDECIDED,
+ _pause = MediaControllerAbilitySupport.UNDECIDED,
+ _stop = MediaControllerAbilitySupport.UNDECIDED,
+ _next = MediaControllerAbilitySupport.UNDECIDED,
+ _prev = MediaControllerAbilitySupport.UNDECIDED,
+ _forward = MediaControllerAbilitySupport.UNDECIDED,
+ _rewind = MediaControllerAbilitySupport.UNDECIDED,
+ _togglePlayPause = MediaControllerAbilitySupport.UNDECIDED;
+
+ Object.defineProperties(this, {
+ play: {
+ get: function() {
+ return _play;
+ },
+ set: function(val) {
+ checkSupportValue(val);
+ _play = val;
+ },
+ enumerable: true
+ },
+ pause: {
+ get: function() {
+ return _pause;
+ },
+ set: function(val) {
+ checkSupportValue(val);
+ _pause = val;
+ },
+ enumerable: true
+ },
+ stop: {
+ get: function() {
+ return _stop;
+ },
+ set: function(val) {
+ checkSupportValue(val);
+ _stop = val;
+ },
+ enumerable: true
+ },
+ next: {
+ get: function() {
+ return _next;
+ },
+ set: function(val) {
+ checkSupportValue(val);
+ _next = val;
+ },
+ enumerable: true
+ },
+ prev: {
+ get: function() {
+ return _prev;
+ },
+ set: function(val) {
+ checkSupportValue(val);
+ _prev = val;
+ },
+ enumerable: true
+ },
+ forward: {
+ get: function() {
+ return _forward;
+ },
+ set: function(val) {
+ checkSupportValue(val);
+ _forward = val;
+ },
+ enumerable: true
+ },
+ rewind: {
+ get: function() {
+ return _rewind;
+ },
+ set: function(val) {
+ checkSupportValue(val);
+ _rewind = val;
+ },
+ enumerable: true
+ },
+ togglePlayPause: {
+ get: function() {
+ return _togglePlayPause;
+ },
+ set: function(val) {
+ checkSupportValue(val);
+ _togglePlayPause = val;
+ },
+ enumerable: true
+ }
+ });
+
+ this.saveAbilities = function() {
+ var data = {
+ PLAY: _play,
+ PAUSE: _pause,
+ STOP: _stop,
+ NEXT: _next,
+ PREV: _prev,
+ FORWARD: _forward,
+ REWIND: _rewind,
+ TOGGLE_PLAY_PAUSE: _togglePlayPause
+ };
+
+ var result = native_.callSync(
+ 'MediaControllerServer_savePlaybackAbilities',
+ data
+ );
+ if (native_.isFailure(result)) {
+ throw new native_.getErrorObject(result);
+ }
+ };
+};
+
+var MediaControllerAbilitiesInfo = function(serverName) {
+ Object.defineProperties(this, {
+ playback: {
+ value: new MediaControllerPlaybackAbilitiesInfo(serverName),
+ enumerable: true,
+ writable: false
+ },
+ playbackPosition: {
+ get: function() {
+ return getSimpleAbility(
+ serverName,
+ MediaControllerSimpleAbility.PLAYBACK_POSITION
+ );
+ },
+ set: function() {},
+ enumerable: true
+ },
+ shuffle: {
+ get: function() {
+ return getSimpleAbility(serverName, MediaControllerSimpleAbility.SHUFFLE);
+ },
+ set: function() {},
+ enumerable: true
+ },
+ repeat: {
+ get: function() {
+ return getSimpleAbility(serverName, MediaControllerSimpleAbility.REPEAT);
+ },
+ set: function() {},
+ enumerable: true
+ },
+ playlist: {
+ get: function() {
+ return getSimpleAbility(
+ serverName,
+ MediaControllerSimpleAbility.PLAYLIST
+ );
+ },
+ set: function() {},
+ enumerable: true
+ },
+ clientCustom: {
+ get: function() {
+ return getSimpleAbility(
+ serverName,
+ MediaControllerSimpleAbility.CLIENT_CUSTOM
+ );
+ },
+ set: function() {},
+ enumerable: true
+ },
+ search: {
+ get: function() {
+ return getSimpleAbility(serverName, MediaControllerSimpleAbility.SEARCH);
+ },
+ set: function() {},
+ enumerable: true
+ }
+ });
+
+ this.subscribe = function() {
+ var data = {
+ serverName: serverName
+ };
+ var result = native_.callSync('MediaControllerAbilitiesInfo_subscribe', data);
+ if (native_.isFailure(result)) {
+ throw new native_.getErrorObject(result);
+ }
+ };
+
+ this.unsubscribe = function() {
+ var data = {
+ serverName: serverName
+ };
+ var result = native_.callSync('MediaControllerAbilitiesInfo_unsubscribe', data);
+ if (native_.isFailure(result)) {
+ throw new native_.getErrorObject(result);
+ }
+ };
+};
+
+var MediaControllerPlaybackAbilitiesInfo = function(serverName) {
+ Object.defineProperties(this, {
+ play: {
+ get: function() {
+ return getPlaybackAbility(serverName, MediaControllerPlaybackState.PLAY);
+ },
+ set: function() {},
+ enumerable: true
+ },
+ pause: {
+ get: function() {
+ return getPlaybackAbility(serverName, MediaControllerPlaybackState.PAUSE);
+ },
+ set: function() {},
+ enumerable: true
+ },
+ stop: {
+ get: function() {
+ return getPlaybackAbility(serverName, MediaControllerPlaybackState.STOP);
+ },
+ set: function() {},
+ enumerable: true
+ },
+ next: {
+ get: function() {
+ return getPlaybackAbility(serverName, MediaControllerPlaybackState.NEXT);
+ },
+ set: function() {},
+ enumerable: true
+ },
+ prev: {
+ get: function() {
+ return getPlaybackAbility(serverName, MediaControllerPlaybackState.PREV);
+ },
+ set: function() {},
+ enumerable: true
+ },
+ forward: {
+ get: function() {
+ return getPlaybackAbility(
+ serverName,
+ MediaControllerPlaybackState.FORWARD
+ );
+ },
+ set: function() {},
+ enumerable: true
+ },
+ rewind: {
+ get: function() {
+ return getPlaybackAbility(
+ serverName,
+ MediaControllerPlaybackState.REWIND
+ );
+ },
+ set: function() {},
+ enumerable: true
+ },
+ togglePlayPause: {
+ get: function() {
+ return getPlaybackAbility(serverName, 'TOGGLE_PLAY_PAUSE');
+ },
+ set: function() {},
+ enumerable: true
+ }
+ });
+};
+
function MediaControllerServer(data) {
var _iconURI = null;
_iconURI = edit_.isAllowed ? (v ? v : null) : _iconURI;
},
enumerable: true
+ },
+ abilities: {
+ value: new MediaControllerAbilities(),
+ enumerable: true
}
});
}
native_.removeListener('SearchRequestListener');
};
+var getPlaybackAbility = function(serverName, action) {
+ var data = {
+ serverName: serverName,
+ action: action
+ };
+
+ var result = native_.callSync('MediaControllerClient_getPlaybackAbility', data);
+ if (native_.isFailure(result)) {
+ throw new native_.getErrorObject(result);
+ }
+ var ability = native_.getResultObject(result);
+ return ability.value;
+};
+
+var getSimpleAbility = function(name, type) {
+ var data = {
+ serverName: name,
+ abilityType: type
+ };
+ var result = native_.callSync('MediaControllerClient_getSimpleAbility', data);
+ if (native_.isFailure(result)) {
+ throw new native_.getErrorObject(result);
+ }
+ var ability = native_.getResultObject(result);
+ return ability.value;
+};
+
+var setSimpleAbility = function(abilityType, support) {
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'abilityType',
+ type: types_.ENUM,
+ values: Object.keys(MediaControllerSimpleAbility)
+ },
+ {
+ name: 'support',
+ type: types_.ENUM,
+ values: Object.keys(MediaControllerAbilitySupport)
+ }
+ ]);
+
+ if (MediaControllerAbilitySupport.UNDECIDED === args.support) {
+ throw new WebAPIException(
+ WebAPIException.INVALID_VALUES_ERR,
+ 'Cannot set ability value to ' + args.support
+ );
+ }
+
+ var data = {
+ abilityType: args.abilityType,
+ support: args.support
+ };
+
+ var result = native_.callSync('MediaControllerServer_setSimpleAbility', data);
+
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObject(result);
+ }
+};
+
+var checkSupportValue = function(support) {
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'support',
+ type: types_.ENUM,
+ values: Object.keys(MediaControllerAbilitySupport)
+ }
+ ]);
+
+ if (MediaControllerAbilitySupport.UNDECIDED === args.support) {
+ throw new WebAPIException(
+ WebAPIException.INVALID_VALUES_ERR,
+ 'Cannot set ability value to ' + args.support
+ );
+ }
+};
+
function MediaControllerClient() {}
MediaControllerClient.prototype.findServers = function(successCallback, errorCallback) {
});
}
+MediaControllerClient.prototype.addAbilityChangeListener = function(callback) {
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'callback',
+ type: types_.LISTENER,
+ values: ['onplaybackabilitychanged', 'onsimpleabilitychanged']
+ }
+ ]);
+
+ var nativeData = {
+ listenerId: ClientAbilityChangeListener.listenerName
+ };
+
+ if (type_.isEmptyObject(ClientAbilityChangeListener.listeners)) {
+ var result = native_.callSync(
+ 'MediaControllerClient_addAbilityChangeListener',
+ nativeData
+ );
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObject(result);
+ }
+ }
+
+ return ClientAbilityChangeListener.addListener(args.callback);
+};
+
+MediaControllerClient.prototype.removeAbilityChangeListener = function(callbackId) {
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'callbackId',
+ type: types_.LONG
+ }
+ ]);
+
+ ClientAbilityChangeListener.removeListener(args.callbackId);
+
+ if (type_.isEmptyObject(ClientAbilityChangeListener.listeners)) {
+ var result = native_.callSync(
+ 'MediaControllerClient_removeAbilityChangeListener'
+ );
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObject(result);
+ }
+ }
+};
+
+MediaControllerClient.prototype.findSubscribedServers = function(
+ successCallback,
+ errorCallback
+) {
+ var args = validator_.validateArgs(arguments, [
+ {
+ name: 'successCallback',
+ type: types_.FUNCTION
+ },
+ {
+ name: 'errorCallback',
+ type: types_.FUNCTION,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ var callback = function(result) {
+ if (native_.isFailure(result)) {
+ native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+ return;
+ }
+ var info = [];
+ var data = native_.getResultObject(result);
+ for (var i = 0; i < data.length; i++) {
+ info.push(new MediaControllerServerInfo(data[i]));
+ }
+ native_.callIfPossible(args.successCallback, info);
+ };
+
+ native_.call('MediaControllerClient_findSubscribedServers', {}, callback);
+};
+
function MediaControllerServerInfo(data) {
Object.defineProperties(this, {
name: {
}.bind(this),
set: function() {},
enumerable: true
+ },
+ abilities: {
+ value: new MediaControllerAbilitiesInfo(data.name),
+ enumerable: true,
+ writable: false
}
});
}
var result = native_.callSync(
'MediaControllerServerInfo_removePlaylistUpdatedListener'
);
-
if (native_.isFailure(result)) {
throw native_.getErrorObject(result);
}
using common::tools::ReportSuccess;
using common::JsonToBundle;
-MediaControllerClient::MediaControllerClient() : handle_(nullptr) {
+MediaControllerClient::MediaControllerClient() : handle_(nullptr), subscribed_servers{} {
ScopeLogger();
}
LoggerE("Failed to unset playlist update listener");
}
+ if (nullptr != ability_listener_ && !UnsetAbilityChangeListener()) {
+ LoggerE("Failed to unset ability listener");
+ }
+
if (nullptr != handle_ && MEDIA_CONTROLLER_ERROR_NONE != mc_client_destroy(handle_)) {
LoggerE("Unable to destroy media controller client");
}
return PlatformResult(ErrorCode::NO_ERROR);
}
+PlatformResult MediaControllerClient::GetPlaybackAbility(const std::string& server_name,
+ const std::string& action,
+ picojson::value* abilities) {
+ ScopeLogger();
+ mc_playback_ability_h ability_h = nullptr;
+
+ SCOPE_EXIT {
+ mc_playback_ability_destroy(ability_h);
+ };
+
+ int ret = mc_client_get_server_playback_ability(handle_, server_name.c_str(), &ability_h);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error getting playback ability",
+ ("mc_client_get_server_playback_ability() error: %d, message: %s",
+ ret, get_error_message(ret)));
+ }
+
+ std::string ability_str;
+ PlatformResult result = types::ConvertPlaybackAbility(ability_h, action, &ability_str);
+ if (!result) {
+ return LogAndCreateResult(
+ ErrorCode::UNKNOWN_ERR, "Error getting playback ability",
+ ("types::ConvertPlaybackAbility() error: %d, message: %s", ret, get_error_message(ret)));
+ }
+
+ picojson::object& abilities_obj = abilities->get<picojson::object>();
+ abilities_obj["value"] = picojson::value(ability_str);
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerClient::GetSimpleAbility(const std::string& server_name,
+ const std::string& ability_type,
+ picojson::value* ability_val) {
+ ScopeLogger();
+ mc_ability_support_e support_e = MC_ABILITY_SUPPORTED_YES;
+ mc_ability_e ability_e = MC_ABILITY_SHUFFLE;
+ PlatformResult result =
+ types::MediaControllerSimpleAbilityEnum.getValue(ability_type, &ability_e);
+ if (!result) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error getting value of ability",
+ ("MediaControllerSimpleAbilityEnum.getValue() failed, error: %s",
+ result.message().c_str()));
+ }
+
+ int ret =
+ mc_client_get_server_ability_support(handle_, server_name.c_str(), ability_e, &support_e);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ return LogAndCreateResult(
+ ErrorCode::UNKNOWN_ERR, "Error getting ability",
+ ("mc_client_get_ability_support() error: %d, message: %s", ret, get_error_message(ret)));
+ }
+
+ std::string ability_str;
+ result = types::MediaControllerAbilitySupportEnum.getName(support_e, &ability_str);
+ if (!result) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error getting name of ability",
+ ("MediaControllerAbilitySupportEnum.getName() failed, error: %s",
+ result.message().c_str()));
+ }
+
+ *ability_val = picojson::value(picojson::object());
+ picojson::object& obj = ability_val->get<picojson::object>();
+ obj["value"] = picojson::value(ability_str);
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
PlatformResult MediaControllerClient::GetPlaybackInfo(const std::string& server_name,
picojson::object* playback_info) {
ScopeLogger();
return PlatformResult(ErrorCode::NO_ERROR);
}
+PlatformResult MediaControllerClient::SetAbilityChangeListener(const JsonCallback& callback) {
+ ScopeLogger();
+ int failed_setters = 0;
+ SCOPE_EXIT {
+ int (*unsetters[])(mc_client_h) = {mc_client_unset_playback_ability_updated_cb,
+ mc_client_unset_ability_support_updated_cb};
+
+ for (int i = 0; i < failed_setters; ++i) {
+ auto ret = unsetters[i](handle_);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ LoggerE("Fail (%d) returned by the [%d] unsetter", ret, i);
+ }
+ }
+ };
+
+ int ret = mc_client_set_playback_ability_updated_cb(handle_, OnPlaybackAbilityUpdate, this);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
+ "Unable to register playback ability listener",
+ ("mc_client_set_playback_ability_updated_cb() error: %d, message: %s",
+ ret, get_error_message(ret)));
+ }
+
+ ret = mc_client_set_ability_support_updated_cb(handle_, OnSimpleAbilityUpdate, this);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ failed_setters = 1;
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to register simple ability listener",
+ ("mc_client_set_ability_support_updated_cb() error: %d, message: %s",
+ ret, get_error_message(ret)));
+ }
+
+ ability_listener_ = callback;
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void UnsubscribeAllTypes(mc_client_h handle_, const std::string& server_name) {
+ int ret;
+ for (auto type : types::MediaControllerSubscriptionTypeEnum) {
+ ret = mc_client_unsubscribe(handle_, type.second, server_name.c_str());
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ LoggerE("mc_client_unsubscribe() failed with type %s, error: %d, message: %s",
+ type.first.c_str(), ret, get_error_message(ret));
+ }
+ }
+}
+
+PlatformResult MediaControllerClient::UnsetAbilityChangeListener() {
+ ScopeLogger();
+
+ // we have to unsubscribe all servers before unsetting callback to avoid
+ // calling callback twice if the callback will be set again
+ for (auto srv : subscribed_servers) {
+ UnsubscribeAllTypes(handle_, srv);
+ }
+ subscribed_servers.clear();
+
+ int ret = mc_client_unset_playback_ability_updated_cb(handle_);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ LoggerW("mc_client_unset_playback_ability_updated_cb() failed with error %d, message: %s", ret,
+ get_error_message(ret));
+ }
+
+ ret = mc_client_unset_ability_support_updated_cb(handle_);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ LoggerW("mc_client_unset_ability_support_updated_cb() failed with error %d, message: %s", ret,
+ get_error_message(ret));
+ }
+
+ ability_listener_ = nullptr;
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerClient::SubscribeServer(const std::string& server_name) {
+ ScopeLogger();
+ int ret = 0;
+ int to_unsubscribe = 0;
+ if (nullptr == ability_listener_) {
+ return PlatformResult(ErrorCode::INVALID_STATE_ERR,
+ "Unable to subscribe server, AbilityChangeListener is not set");
+ }
+
+ SCOPE_EXIT {
+ if (to_unsubscribe > 0) {
+ for (auto type : types::MediaControllerSubscriptionTypeEnum) {
+ if (to_unsubscribe > 0) {
+ ret = mc_client_unsubscribe(handle_, type.second, server_name.c_str());
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ LoggerW("mc_client_unsubscribe() failed on type: %s, with error: %d, message: %s",
+ type.first.c_str(), ret, get_error_message(ret));
+ }
+ }
+ --to_unsubscribe;
+ }
+ }
+ };
+
+ for (auto type : types::MediaControllerSubscriptionTypeEnum) {
+ ret = mc_client_subscribe(handle_, type.second, server_name.c_str());
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ return LogAndCreateResult(
+ ErrorCode::UNKNOWN_ERR, "Unable to subscribe server",
+ ("mc_client_subscribe() error: %d, message: %s", ret, get_error_message(ret)));
+ }
+ ++to_unsubscribe;
+ }
+
+ to_unsubscribe = 0;
+ subscribed_servers.push_back(server_name);
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerClient::UnsubscribeServer(const std::string& server_name) {
+ ScopeLogger();
+
+ UnsubscribeAllTypes(handle_, server_name);
+ subscribed_servers.remove(server_name);
+
+ /**
+ * After unsubscribing last media controller server, unsetting and setting callback
+ * is needed to receive again callbacks from all media controller servers.
+ */
+ if (subscribed_servers.size() <= 0 && nullptr != ability_listener_) {
+ JsonCallback callback = ability_listener_;
+ UnsetAbilityChangeListener();
+ auto result = SetAbilityChangeListener(callback);
+ if (!result) {
+ return result;
+ }
+ }
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerClient::FindSubscribedServers(picojson::array* servers) {
+ ScopeLogger();
+
+ /**
+ * If subscription is successful, then servers are subscribed to every subscription type,
+ * so we can check only the one type of subscription to receive all subscribed servers.
+ */
+ int ret = mc_client_foreach_server_subscribed(handle_, MC_SUBSCRIPTION_TYPE_ABILITY_SUPPORT,
+ FindServersCallback, servers);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ return LogAndCreateResult(
+ ErrorCode::UNKNOWN_ERR, "Unable to fetch active servers.",
+ ("mc_client_foreach_server() error: %d, message: %s", ret, get_error_message(ret)));
+ }
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
void MediaControllerClient::OnPlaybackUpdate(const char* server_name, mc_playback_h playback,
void* user_data) {
ScopeLogger();
client->playback_info_listener_(&data);
}
+void MediaControllerClient::OnPlaybackAbilityUpdate(const char* server_name,
+ mc_playback_ability_h ability,
+ 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["action"] = picojson::value(std::string("onplaybackabilitychanged"));
+ data_o["name"] = picojson::value(std::string(server_name));
+ // only active servers can trigger listener, thus state is always "ACTIVE"
+ data_o["state"] = picojson::value(std::string("ACTIVE"));
+
+ client->ability_listener_(&data);
+}
+
void MediaControllerClient::OnShuffleModeUpdate(const char* server_name, mc_shuffle_mode_e mode,
void* user_data) {
ScopeLogger();
client->playback_info_listener_(&data);
}
+void MediaControllerClient::OnSimpleAbilityUpdate(const char* server_name, mc_ability_e type,
+ mc_ability_support_e ability, void* user_data) {
+ ScopeLogger();
+ MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+ std::string type_str;
+ PlatformResult result = types::MediaControllerSimpleAbilityEnum.getName(type, &type_str);
+ if (!result) {
+ LoggerE("MediaControllerSimpleAbilityEnum.getName() failed, error: %s",
+ result.message().c_str());
+ return;
+ }
+
+ std::string ability_str;
+ result = types::MediaControllerAbilitySupportEnum.getName(ability, &ability_str);
+ if (!result) {
+ LoggerE("MediaControllerAbilitySupportEnum.getName() failed, error: %s",
+ result.message().c_str());
+ return;
+ }
+
+ picojson::value data = picojson::value(picojson::object());
+ picojson::object& data_o = data.get<picojson::object>();
+
+ data_o["action"] = picojson::value(std::string("onsimpleabilitychanged"));
+ data_o["name"] = picojson::value(std::string(server_name));
+ // only active servers can trigger listener, thus state is always "ACTIVE"
+ data_o["state"] = picojson::value(std::string("ACTIVE"));
+ data_o["type"] = picojson::value(type_str);
+ data_o["ability"] = picojson::value(ability_str);
+
+ client->ability_listener_(&data);
+}
+
void MediaControllerClient::OnRepeatModeUpdate(const char* server_name, mc_repeat_mode_e mode,
void* user_data) {
ScopeLogger();
#define MEDIACONTROLLER_MEDIACONTROLLER_CLIENT_H_
#include <media_controller_client.h>
+#include <list>
#include <string>
#include "common/optional.h"
common::PlatformResult GetPlaybackInfo(const std::string& server_name,
picojson::object* playback_info);
common::PlatformResult GetMetadata(const std::string& server_name, picojson::object* metadata);
-
common::PlatformResult SendPlaybackState(const std::string& server_name,
const std::string& state);
common::PlatformResult SendPlaybackPosition(const std::string& server_name, double position);
common::PlatformResult SendShuffleMode(const std::string& server_name, bool mode);
common::PlatformResult SendRepeatMode(const std::string& server_name, bool mode);
common::PlatformResult SendRepeatState(const std::string& server_name, const std::string& state);
-
common::PlatformResult SendSearchRequest(const std::string& server_name,
const picojson::value& request,
const JsonCallback& callback, char** request_id);
-
common::PlatformResult SendCommand(const std::string& server_name, const std::string& command,
const picojson::value& data, const JsonCallback& reply_cb,
char** request_id);
-
common::PlatformResult SetServerStatusChangeListener(const JsonCallback& callback);
common::PlatformResult UnsetServerStatusChangeListener();
-
common::PlatformResult SetPlaybackInfoListener(const JsonCallback& callback);
common::PlatformResult UnsetPlaybackInfoListener();
common::PlatformResult SendPlaybackItem(const std::string& name, const std::string& playlist_name,
common::PlatformResult UnsetPlaylistUpdateListener();
common::PlatformResult GetServerIconURI(const std::string& name,
common::optional<std::string>* icon_uri);
+ common::PlatformResult GetPlaybackAbility(const std::string& server_name,
+ const std::string& action, picojson::value* abilities);
+ common::PlatformResult SetAbilityChangeListener(const JsonCallback& callback);
+ common::PlatformResult UnsetAbilityChangeListener();
+ common::PlatformResult GetSimpleAbility(const std::string& server_name,
+ const std::string& ability_type,
+ picojson::value* ability_val);
+ common::PlatformResult SubscribeServer(const std::string& server_name);
+ common::PlatformResult UnsubscribeServer(const std::string& server_name);
+ common::PlatformResult FindSubscribedServers(picojson::array* servers);
private:
mc_client_h handle_;
JsonCallback server_status_listener_;
JsonCallback command_reply_callback_;
JsonCallback playlist_update_listener_;
+ JsonCallback ability_listener_;
+
+ std::list<std::string> subscribed_servers;
static bool FindServersCallback(const char* server_name, void* user_data);
static void OnMetadataUpdate(const char* server_name, mc_metadata_h metadata_h, void* user_data);
static void OnPlaylistUpdate(const char* server_name, mc_playlist_update_mode_e mode,
const char* playlist_name, mc_playlist_h playlist, void* user_data);
+ static void OnPlaybackAbilityUpdate(const char* server_name, mc_playback_ability_h ability,
+ void* user_data);
+ static void OnSimpleAbilityUpdate(const char* server_name, mc_ability_e type,
+ mc_ability_support_e mode, void* user_data);
};
} // namespace mediacontroller
const std::string kPrivilegeMediaControllerServer =
"http://tizen.org/privilege/mediacontroller.server";
+const char* kAbilityType = "abilityType";
+const char* kServerName = "serverName";
} // namespace
using common::ErrorCode;
MediaControllerServerUpdatePlaybackItem);
REGISTER_ASYNC("MediaControllerServer_getAllPlaylists", MediaControllerServerGetAllPlaylists);
REGISTER_SYNC("MediaControllerServer_updateIconURI", MediaControllerServerUpdateIconURI);
+ REGISTER_SYNC("MediaControllerServer_savePlaybackAbilities",
+ MediaControllerServerSavePlaybackAbilities);
+ REGISTER_SYNC("MediaControllerServer_setSimpleAbility", MediaControllerServerSetSimpleAbility);
// client
REGISTER_SYNC("MediaControllerManager_getClient", MediaControllerManagerGetClient);
REGISTER_SYNC("MediaControllerClient_getLatestServerInfo",
MediaControllerClientGetLatestServerInfo);
REGISTER_SYNC("MediaControllerClient_getPlaybackInfo", MediaControllerClientGetPlaybackInfo);
+ REGISTER_SYNC("MediaControllerClient_getPlaybackAbility",
+ MediaControllerClientGetPlaybackAbility);
+ REGISTER_SYNC("MediaControllerClient_getSimpleAbility", MediaControllerClientGetSimpleAbility);
+ REGISTER_ASYNC("MediaControllerClient_findSubscribedServers",
+ MediaControllerClientFindSubscribedServers);
+
+ // server_info
REGISTER_SYNC("MediaControllerServerInfo_sendPlaybackState",
MediaControllerServerInfoSendPlaybackState);
REGISTER_ASYNC("MediaControllerServerInfo_sendPlaybackPosition",
REGISTER_ASYNC("MediaControllerServerInfo_getAllPlaylists",
MediaControllerServerInfoGetAllPlaylists);
REGISTER_SYNC("MediaControllerServerInfo_getIconURI", MediaControllerServerInfoGetIconURI);
+ REGISTER_SYNC("MediaControllerClient_addAbilityChangeListener",
+ MediaControllerClientAddAbilityChangeListener);
+ REGISTER_SYNC("MediaControllerClient_removeAbilityChangeListener",
+ MediaControllerClientRemoveAbilityChangeListener);
+
+ // abilities_info
+ REGISTER_SYNC("MediaControllerAbilitiesInfo_subscribe", MediaControllerAbilitiesInfoSubscribe);
+ REGISTER_SYNC("MediaControllerAbilitiesInfo_unsubscribe",
+ MediaControllerAbilitiesInfoUnsubscribe);
// playlist
REGISTER_SYNC("MediaControllerPlaylist_addItem", MediaControllerPlaylistAddItem);
ScopeLogger();
}
-#define CHECK_EXIST(args, name, out) \
- if (!args.contains(name)) { \
- LogAndReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, name " is required argument"), \
- &out); \
- return; \
+#define CHECK_EXIST(args, name, out) \
+ if (!args.contains(name)) { \
+ std::string msg = std::string(name) + " is required argument"; \
+ LogAndReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, msg), &out); \
+ return; \
}
-#define CHECK_TYPE(args, name, type, out) \
- if (!args.get(name).is<type>()) { \
- LogAndReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, name " is not a " #type), \
- &out); \
- return; \
+#define CHECK_TYPE(args, name, type, out) \
+ if (!args.get(name).is<type>()) { \
+ std::string msg = std::string(name) + " is not a " + #type; \
+ LogAndReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, msg), &out); \
+ return; \
}
#define CHECK_ARGS(args, name, type, out) \
ReportSuccess(out);
}
+void MediaControllerInstance::MediaControllerServerSavePlaybackAbilities(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+
+ if (!server_) {
+ LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occured."), &out,
+ ("Failed: server_"));
+ return;
+ }
+
+ CHECK_ARGS(args, "PLAY", std::string, out)
+ CHECK_ARGS(args, "PAUSE", std::string, out)
+ CHECK_ARGS(args, "STOP", std::string, out)
+ CHECK_ARGS(args, "NEXT", std::string, out)
+ CHECK_ARGS(args, "PREV", std::string, out)
+ CHECK_ARGS(args, "FORWARD", std::string, out)
+ CHECK_ARGS(args, "REWIND", std::string, out)
+ CHECK_ARGS(args, "TOGGLE_PLAY_PAUSE", std::string, out)
+
+ const PlatformResult& result = server_->SavePlaybackAbilities(args);
+ if (!result) {
+ LogAndReportError(result, &out, ("Failed server_->SavePlaybackAbilities()"));
+ return;
+ }
+
+ ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerSetSimpleAbility(const picojson::value& args,
+ picojson::object& out) {
+ ScopeLogger();
+
+ if (!server_) {
+ LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occured."), &out,
+ ("Failed: server_"));
+ return;
+ }
+
+ CHECK_ARGS(args, kAbilityType, std::string, out)
+ CHECK_ARGS(args, "support", std::string, out)
+
+ std::string ability_type = args.get(kAbilityType).get<std::string>();
+ std::string support = args.get("support").get<std::string>();
+ const PlatformResult& result = server_->SetSimpleAbility(ability_type, support);
+ if (!result) {
+ LogAndReportError(result, &out, ("Failed server_->SetSimpleAbility()"));
+ return;
+ }
+
+ ReportSuccess(out);
+}
+
void MediaControllerInstance::MediaControllerManagerGetClient(const picojson::value& args,
picojson::object& out) {
ScopeLogger();
ReportSuccess(playback_info, out);
}
+void MediaControllerInstance::MediaControllerClientGetPlaybackAbility(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, kServerName, std::string, out)
+ CHECK_ARGS(args, "action", std::string, out)
+
+ std::string server_name = args.get(kServerName).get<std::string>();
+ std::string action = args.get("action").get<std::string>();
+ picojson::value ability = picojson::value(picojson::object());
+ PlatformResult result = client_->GetPlaybackAbility(server_name, action, &ability);
+ if (!result) {
+ LogAndReportError(result, &out, ("Failed: client_->GetPlaybackAbility"));
+ return;
+ }
+
+ ReportSuccess(ability, out);
+}
+
+void MediaControllerInstance::MediaControllerClientGetSimpleAbility(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, kAbilityType, std::string, out)
+ CHECK_ARGS(args, kServerName, std::string, out)
+
+ picojson::value ability_val = picojson::value();
+ std::string ability_type = args.get(kAbilityType).get<std::string>();
+ std::string server_name = args.get(kServerName).get<std::string>();
+ PlatformResult result = client_->GetSimpleAbility(server_name, ability_type, &ability_val);
+ if (!result) {
+ LogAndReportError(result, &out, ("Failed: client_->GetSimpleAbility"));
+ return;
+ }
+
+ ReportSuccess(ability_val, out);
+}
+
+void MediaControllerInstance::MediaControllerClientFindSubscribedServers(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+
+ if (!client_) {
+ LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occured."), &out,
+ ("Failed: client_"));
+ return;
+ }
+
+ CHECK_EXIST(args, "callbackId", out)
+
+ picojson::value callback_id = args.get("callbackId");
+
+ auto search = [this, callback_id]() -> void {
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& response_obj = response.get<picojson::object>();
+
+ picojson::value servers = picojson::value(picojson::array());
+ PlatformResult result = client_->FindSubscribedServers(&servers.get<picojson::array>());
+
+ response_obj["callbackId"] = callback_id;
+ if (result) {
+ ReportSuccess(servers, response_obj);
+ } else {
+ LogAndReportError(result, &response_obj, ("Failed to find subscribed servers"));
+ }
+
+ Instance::PostMessage(this, response.serialize().c_str());
+ };
+
+ TaskQueue::GetInstance().Async(search);
+
+ ReportSuccess(out);
+}
+
void MediaControllerInstance::MediaControllerServerInfoSendPlaybackState(
const picojson::value& args, picojson::object& out) {
ScopeLogger();
ReportSuccess(picojson::value(result), out);
}
+void MediaControllerInstance::MediaControllerClientAddAbilityChangeListener(
+ const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+
+ if (!client_) {
+ LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occured."), &out,
+ ("Failed: client_"));
+ return;
+ }
+
+ CHECK_EXIST(args, "listenerId", out)
+
+ picojson::value listener_id = args.get("listenerId");
+
+ JsonCallback callback = [this, listener_id](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"] = listener_id;
+
+ Instance::PostMessage(this, data->serialize().c_str());
+ };
+
+ auto result = client_->SetAbilityChangeListener(callback);
+ if (!result) {
+ LogAndReportError(result, &out);
+ return;
+ }
+
+ ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerClientRemoveAbilityChangeListener(
+ 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_->UnsetAbilityChangeListener();
+ if (!result) {
+ LogAndReportError(result, &out);
+ return;
+ }
+
+ ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerAbilitiesInfoSubscribe(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, kServerName, std::string, out)
+
+ const std::string& server_name = args.get(kServerName).get<std::string>();
+ auto result = client_->SubscribeServer(server_name);
+ if (!result) {
+ LogAndReportError(result, &out);
+ return;
+ }
+
+ ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerAbilitiesInfoUnsubscribe(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, kServerName, std::string, out)
+
+ const std::string& server_name = args.get(kServerName).get<std::string>();
+ auto result = client_->UnsubscribeServer(server_name);
+ if (!result) {
+ LogAndReportError(result, &out);
+ return;
+ }
+
+ ReportSuccess(out);
+}
+
void MediaControllerInstance::MediaControllerPlaylistAddItem(const picojson::value& args,
picojson::object& out) {
ScopeLogger();
void MediaControllerServerUpdatePlaybackItem(const picojson::value& args, picojson::object& out);
void MediaControllerServerGetAllPlaylists(const picojson::value& args, picojson::object& out);
void MediaControllerServerUpdateIconURI(const picojson::value& args, picojson::object& out);
+ void MediaControllerServerSavePlaybackAbilities(const picojson::value& args,
+ picojson::object& out);
+ void MediaControllerServerSetSimpleAbility(const picojson::value& args, picojson::object& out);
// client
void MediaControllerManagerGetClient(const picojson::value& args, picojson::object& out);
void MediaControllerClientFindServers(const picojson::value& args, picojson::object& out);
void MediaControllerClientGetLatestServerInfo(const picojson::value& args, picojson::object& out);
void MediaControllerClientGetPlaybackInfo(const picojson::value& args, picojson::object& out);
+ void MediaControllerClientGetPlaybackAbility(const picojson::value& args, picojson::object& out);
+ void MediaControllerClientGetSimpleAbility(const picojson::value& args, picojson::object& out);
+ void MediaControllerClientAddAbilityChangeListener(const picojson::value& args,
+ picojson::object& out);
+ void MediaControllerClientRemoveAbilityChangeListener(const picojson::value& args,
+ picojson::object& out);
+ void MediaControllerClientFindSubscribedServers(const picojson::value& args,
+ picojson::object& out);
+
+ // serverInfo
void MediaControllerServerInfoSendPlaybackState(const picojson::value& args,
picojson::object& out);
void MediaControllerServerInfoSendPlaybackPosition(const picojson::value& args,
void MediaControllerServerInfoGetAllPlaylists(const picojson::value& args, picojson::object& out);
void MediaControllerServerInfoGetIconURI(const picojson::value& args, picojson::object& out);
+ // abilities_info
+ void MediaControllerAbilitiesInfoSubscribe(const picojson::value& args, picojson::object& out);
+ void MediaControllerAbilitiesInfoUnsubscribe(const picojson::value& args, picojson::object& out);
+
// playlist
void MediaControllerPlaylistAddItem(const picojson::value& args, picojson::object& out);
void MediaControllerPlaylistGetItems(const picojson::value& args, picojson::object& out);
shuffle_mode_(MC_SHUFFLE_MODE_OFF),
repeat_mode_(MC_REPEAT_MODE_OFF),
is_shuffle_mode_set_(false),
- is_repeat_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} {
ScopeLogger();
}
return PlatformResult(ErrorCode::NO_ERROR);
}
+PlatformResult MediaControllerServer::SetPlaybackAbility(const std::string& action,
+ const std::string& support_str) {
+ ScopeLogger();
+ PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+ mc_playback_action_e action_e;
+ // Currently MediaControllerPlaybackActionEnum does not have member "TOGGLE_PLAY_PAUSE".
+ // It should be fixed in the future.
+ if ("TOGGLE_PLAY_PAUSE" == action) {
+ action_e = MC_PLAYBACK_ACTION_TOGGLE_PLAY_PAUSE;
+ } else {
+ result = types::MediaControllerPlaybackActionEnum.getValue(action, &action_e);
+ if (!result) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error getting value of playback action",
+ ("MediaControllerPlaybackActionEnum.getValue() failed, error: %s",
+ result.message().c_str()));
+ }
+ }
+
+ mc_ability_support_e support;
+ result = types::MediaControllerAbilitySupportEnum.getValue(support_str, &support);
+ if (!result) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error getting value of ability",
+ ("MediaControllerAbilitySupportEnum.getValue() failed, error: %s",
+ result.message().c_str()));
+ }
+
+ if (support == playback_abilities_.get(action)) {
+ LoggerD("No change in playback ability support, skipping");
+ return PlatformResult(ErrorCode::NO_ERROR);
+ }
+
+ int ret = mc_server_set_playback_ability(handle_, action_e, support);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ return LogAndCreateResult(
+ ErrorCode::UNKNOWN_ERR, "Error setting playback ability",
+ ("mc_server_set_playback_ability() error: %d, message: %s", ret, get_error_message(ret)));
+ }
+
+ playback_abilities_.set(action, support);
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerServer::SavePlaybackAbilities(const picojson::value& abilities) {
+ ScopeLogger();
+
+ // 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>());
+ 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);
+ 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)));
+ }
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerServer::SetSimpleAbility(const std::string& ability_type,
+ const std::string& support_str) {
+ ScopeLogger();
+
+ mc_ability_support_e support_e;
+ PlatformResult result =
+ types::MediaControllerAbilitySupportEnum.getValue(support_str, &support_e);
+ if (!result) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error getting value of ability",
+ ("MediaControllerAbilitySupportEnum.getValue() failed, error: %s",
+ 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);
+ }
+
+ mc_ability_e ability_e;
+ result = types::MediaControllerSimpleAbilityEnum.getValue(ability_type, &ability_e);
+ if (!result) {
+ return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error getting value of ability",
+ ("MediaControllerSimpleAbilityEnum.getValue() failed, error: %s",
+ result.message().c_str()));
+ }
+
+ int ret = mc_server_set_ability_support(handle_, ability_e, support_e);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ return LogAndCreateResult(
+ ErrorCode::UNKNOWN_ERR, "Error setting ability",
+ ("mc_server_set_ability_support() error: %d, message: %s", ret, get_error_message(ret)));
+ }
+
+ simple_abilities_.set(ability_type, support_e);
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
PlatformResult MediaControllerServer::SetChangeRequestPlaybackInfoListener(
const JsonCallback& callback) {
ScopeLogger();
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();
common::PlatformResult MediaControllerPlaylistGetItems(const std::string& name,
picojson::array* items);
common::PlatformResult UpdateIconURI(const char* icon_uri);
+ common::PlatformResult SetPlaybackAbility(const std::string& action,
+ const std::string& support_str);
+ common::PlatformResult SavePlaybackAbilities(const picojson::value& abilities);
+ common::PlatformResult SetSimpleAbility(const std::string& ability_type,
+ const std::string& support_str);
private:
mc_server_h handle_;
mc_repeat_mode_e repeat_mode_;
bool is_shuffle_mode_set_;
bool is_repeat_mode_set_;
+ playback_abilities playback_abilities_;
+ simple_abilities simple_abilities_;
JsonCallback command_listener_;
std::map<std::string, mc_playlist_h> playlist_handle_map_;
{"GENRE", MC_SEARCH_GENRE},
{"TPO", MC_SEARCH_TPO}};
+const common::PlatformEnum<mc_ability_support_e> MediaControllerAbilitySupportEnum{
+ {"YES", MC_ABILITY_SUPPORTED_YES},
+ {"NO", MC_ABILITY_SUPPORTED_NO},
+ {"UNDECIDED", MC_ABILITY_SUPPORTED_UNDECIDED}};
+
+const common::PlatformEnum<mc_subscription_type_e> MediaControllerSubscriptionTypeEnum{
+ {"PLAYBACK_ABILITY", MC_SUBSCRIPTION_TYPE_PLAYBACK_ABILITY},
+ {"SIMPLE_ABILITIES", MC_SUBSCRIPTION_TYPE_ABILITY_SUPPORT}};
+
+const common::PlatformEnum<mc_ability_e> MediaControllerSimpleAbilityEnum{
+ {"PLAYBACK_POSITION", MC_ABILITY_PLAYBACK_POSITION},
+ {"SHUFFLE", MC_ABILITY_SHUFFLE},
+ {"REPEAT", MC_ABILITY_REPEAT},
+ {"PLAYLIST", MC_ABILITY_PLAYLIST},
+ {"CLIENT_CUSTOM", MC_ABILITY_CLIENT_CUSTOM},
+ {"SEARCH", MC_ABILITY_SEARCH}};
+
PlatformResult ConvertPlaybackState(mc_playback_h playback_h, std::string* state) {
ScopeLogger();
return PlatformResult(ErrorCode::NO_ERROR);
}
+PlatformResult ConvertPlaybackAbility(mc_playback_ability_h ability_h, const std::string& action,
+ std::string* ability_str) {
+ ScopeLogger();
+
+ mc_ability_support_e ability_e;
+ mc_playback_action_e action_e;
+ PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+ if ("TOGGLE_PLAY_PAUSE" == action) {
+ action_e = MC_PLAYBACK_ACTION_TOGGLE_PLAY_PAUSE;
+ } else {
+ result = MediaControllerPlaybackActionEnum.getValue(action, &action_e);
+ if (!result) {
+ LoggerE("MediaControllerPlaybackActionEnum.getValue() failed, error: %s",
+ result.message().c_str());
+ return result;
+ }
+ }
+
+ int ret = mc_playback_action_is_supported(ability_h, action_e, &ability_e);
+ if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
+ return LogAndCreateResult(
+ ErrorCode::UNKNOWN_ERR, "Error checking playback action ability support",
+ ("mc_playback_action_is_supported() error: %d, message: %s", ret, get_error_message(ret)));
+ }
+ result = MediaControllerAbilitySupportEnum.getName(ability_e, ability_str);
+ if (!result) {
+ LoggerE("MediaControllerAbilitySupportEnum.getName() failed, error: %s",
+ result.message().c_str());
+ return result;
+ }
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
} // types
PlatformResult utils::GetAllPlaylists(const std::string& app_id, picojson::array* playlists) {
common::PlatformResult ConvertPlaybackPosition(mc_playback_h playback_h, double* position);
common::PlatformResult ConvertMetadata(mc_metadata_h metadata_h, picojson::object* metadata);
common::PlatformResult ConvertContentType(mc_playback_h playback_h, std::string* contentType);
+common::PlatformResult ConvertPlaybackAbility(mc_playback_ability_h ability_h,
+ const std::string& action, std::string* ability_str);
extern const common::PlatformEnum<mc_server_state_e> MediaControllerServerStateEnum;
extern const common::PlatformEnum<mc_playback_states_e> MediaControllerPlaybackStateEnum;
extern const common::PlatformEnum<mc_content_age_rating_e> MediaControllerContentAgeRatingEnum;
extern const common::PlatformEnum<mc_content_type_e> MediaControllerContentTypeEnum;
extern const common::PlatformEnum<mc_search_category_e> MediaControllerSearchCategoryEnum;
+extern const common::PlatformEnum<mc_ability_support_e> MediaControllerAbilitySupportEnum;
+extern const common::PlatformEnum<mc_subscription_type_e> MediaControllerSubscriptionTypeEnum;
+extern const common::PlatformEnum<mc_ability_e> MediaControllerSimpleAbilityEnum;
} // namespace types