2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "mediacontroller/mediacontroller_server.h"
20 #include <bundle_internal.h>
22 #include "common/logger.h"
23 #include "common/scope_exit.h"
25 #include "mediacontroller/mediacontroller_types.h"
28 namespace mediacontroller {
30 using common::PlatformResult;
31 using common::ErrorCode;
33 MediaControllerServer::MediaControllerServer()
35 playback_state_(MC_PLAYBACK_STATE_STOPPED),
37 shuffle_mode_(MC_SHUFFLE_MODE_OFF),
38 repeat_mode_(MC_REPEAT_MODE_OFF),
39 is_shuffle_mode_set_(false),
40 is_repeat_mode_set_(false) {
44 MediaControllerServer::~MediaControllerServer() {
47 if (nullptr != change_request_playback_info_listener_ &&
48 !UnsetChangeRequestPlaybackInfoListener()) {
49 LoggerE("Failed to unset change request playback info listener");
52 if (nullptr != command_listener_ && !UnsetCommandListener()) {
53 LoggerE("Failed to unset command listener");
56 if (nullptr != handle_ && MEDIA_CONTROLLER_ERROR_NONE != mc_server_destroy(handle_)) {
57 LoggerE("Unable to destroy media controller server");
62 PlatformResult MediaControllerServer::Init() {
65 int ret = mc_server_create(&handle_);
66 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
67 return LogAndCreateResult(
68 ErrorCode::UNKNOWN_ERR, "Unable to create media controller server",
69 ("mc_server_create() error: %d, message: %s", ret, get_error_message(ret)));
72 return PlatformResult(ErrorCode::NO_ERROR);
75 PlatformResult MediaControllerServer::SetPlaybackState(const std::string& state) {
78 mc_playback_states_e state_e;
79 PlatformResult result = types::MediaControllerPlaybackStateEnum.getValue(state, &state_e);
84 if (state_e == playback_state_) {
85 LoggerD("No change in playback state requested, skipping");
86 return PlatformResult(ErrorCode::NO_ERROR);
89 int ret = mc_server_set_playback_state(handle_, state_e);
90 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
91 return LogAndCreateResult(
92 ErrorCode::UNKNOWN_ERR, "Error setting playback state",
93 ("mc_server_set_playback_state() error: %d, message: %s", ret, get_error_message(ret)));
96 playback_state_ = state_e;
98 ret = mc_server_update_playback_info(handle_);
99 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
100 return LogAndCreateResult(
101 ErrorCode::UNKNOWN_ERR, "Error updating playback info",
102 ("mc_server_update_playback_info() error: %d, message: %s", ret, get_error_message(ret)));
105 return PlatformResult(ErrorCode::NO_ERROR);
108 PlatformResult MediaControllerServer::SetPlaybackPosition(double position) {
111 if (static_cast<unsigned long long>(position) == position_) {
112 LoggerD("No change in playback position requested, skipping");
113 return PlatformResult(ErrorCode::NO_ERROR);
116 int ret = mc_server_set_playback_position(handle_, static_cast<unsigned long long>(position));
117 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
118 return LogAndCreateResult(
119 ErrorCode::UNKNOWN_ERR, "Error setting playback position",
120 ("mc_server_set_playback_position() error: %d, message: %s", ret, get_error_message(ret)));
123 position_ = static_cast<unsigned long long>(position);
125 ret = mc_server_update_playback_info(handle_);
126 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
127 return LogAndCreateResult(
128 ErrorCode::UNKNOWN_ERR, "Error updating playback info",
129 ("mc_server_update_playback_info() error: %d, message: %s", ret, get_error_message(ret)));
132 return PlatformResult(ErrorCode::NO_ERROR);
135 PlatformResult MediaControllerServer::SetShuffleMode(bool mode) {
138 mc_shuffle_mode_e shuffle_mode = mode ? MC_SHUFFLE_MODE_ON : MC_SHUFFLE_MODE_OFF;
139 if ((shuffle_mode == shuffle_mode_) && (is_shuffle_mode_set_)) {
140 LoggerD("No change in shuffle mode requested, skipping");
141 return PlatformResult(ErrorCode::NO_ERROR);
144 int ret = mc_server_update_shuffle_mode(handle_, shuffle_mode);
145 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
146 return LogAndCreateResult(
147 ErrorCode::UNKNOWN_ERR, "Error updating shuffle mode",
148 ("mc_server_update_shuffle_mode() error: %d, message: %s", ret, get_error_message(ret)));
151 shuffle_mode_ = shuffle_mode;
152 is_shuffle_mode_set_ = true;
154 return PlatformResult(ErrorCode::NO_ERROR);
157 PlatformResult MediaControllerServer::SetRepeatMode(bool mode) {
160 mc_repeat_mode_e repeat_mode = mode ? MC_REPEAT_MODE_ON : MC_REPEAT_MODE_OFF;
161 if ((repeat_mode == repeat_mode_) && (is_repeat_mode_set_)) {
162 LoggerD("No change in repeat mode requested, skipping");
163 return PlatformResult(ErrorCode::NO_ERROR);
166 int ret = mc_server_update_repeat_mode(handle_, repeat_mode);
167 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
168 return LogAndCreateResult(
169 ErrorCode::UNKNOWN_ERR, "Error updating repeat mode",
170 ("mc_server_update_repeat_mode() error: %d, message: %s", ret, get_error_message(ret)));
173 repeat_mode_ = repeat_mode;
174 is_repeat_mode_set_ = true;
176 return PlatformResult(ErrorCode::NO_ERROR);
179 PlatformResult MediaControllerServer::SetMetadata(const picojson::object& metadata) {
182 for (picojson::object::const_iterator i = metadata.begin(); i != metadata.end(); ++i) {
184 PlatformResult result = types::MediaControllerMetadataAttributeEnum.getValue(i->first, &attr_e);
189 int ret = mc_server_set_metadata(handle_, attr_e, i->second.to_str().c_str());
190 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
191 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Error setting metadata",
192 ("mc_server_set_metadata(%s) error: %d, message: %s",
193 i->first.c_str(), ret, get_error_message(ret)));
197 int ret = mc_server_update_metadata(handle_);
198 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
199 return LogAndCreateResult(
200 ErrorCode::UNKNOWN_ERR, "Error updating metadata",
201 ("mc_server_update_metadata() error: %d, message: %s", ret, get_error_message(ret)));
204 return PlatformResult(ErrorCode::NO_ERROR);
207 void MediaControllerServer::OnCommandReceived(const char* client_name, const char* request_id,
208 const char* command, bundle* bundle,
212 MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
215 char* data_str = nullptr;
219 picojson::value data;
221 ret = bundle_get_str(bundle, "data", &data_str);
222 if (BUNDLE_ERROR_NONE != ret || nullptr == data_str) {
223 LoggerE("bundle_get_str(data) failed, error: %d", ret);
226 picojson::parse(data, data_str, data_str + strlen(data_str), &err);
228 LoggerE("Failed to parse bundle data: %s", err.c_str());
233 picojson::value request = picojson::value(picojson::object());
234 picojson::object& request_o = request.get<picojson::object>();
236 request_o["clientName"] = picojson::value(std::string(client_name));
237 request_o["command"] = picojson::value(std::string(command));
238 request_o["requestId"] = picojson::value(std::string(request_id));
239 request_o["data"] = data;
241 server->command_listener_(&request);
244 PlatformResult MediaControllerServer::CommandReply(const std::string& client_name,
245 const std::string& request_id,
246 const picojson::value& data) {
251 bundle* bundle = bundle_create();
256 ret = bundle_add(bundle, "data", data.serialize().c_str());
257 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
258 return LogAndCreateResult(
259 ErrorCode::UNKNOWN_ERR, "Unable to add data to bundle",
260 ("bundle_add(data) error: %d, message: %s", ret, get_error_message(ret)));
263 ret = mc_server_send_cmd_reply(handle_, client_name.c_str(), request_id.c_str(), 0, bundle);
264 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
265 return LogAndCreateResult(
266 ErrorCode::UNKNOWN_ERR, "Error sending command reply",
267 ("mc_server_send_cmd_reply() error: %d, message: %s", ret, get_error_message(ret)));
270 return PlatformResult(ErrorCode::NO_ERROR);
273 PlatformResult MediaControllerServer::SetCommandListener(const JsonCallback& callback) {
276 int ret = mc_server_set_custom_cmd_received_cb(handle_, OnCommandReceived, this);
277 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
278 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to set command callback",
279 ("mc_server_set_custom_cmd_received_cb() error: %d, message: %s", ret,
280 get_error_message(ret)));
282 command_listener_ = callback;
284 return PlatformResult(ErrorCode::NO_ERROR);
287 PlatformResult MediaControllerServer::UnsetCommandListener() {
290 int ret = mc_server_unset_custom_cmd_received_cb(handle_);
291 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
292 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to unset command callback",
293 ("mc_server_unset_custom_cmd_received_cb() error: %d, message: %s",
294 ret, get_error_message(ret)));
296 command_listener_ = nullptr;
298 return PlatformResult(ErrorCode::NO_ERROR);
301 PlatformResult MediaControllerServer::SetChangeRequestPlaybackInfoListener(
302 const JsonCallback& callback) {
304 int failed_setter = 0;
306 // Lambda function used to clean all set listeners (in case of failure of
307 // SetPlaybackInfoListener method).
308 // The purpose of this lambda is to unset as many setters as we can in case of failure.
310 int (*unsetters[])(mc_server_h) = {
311 mc_server_unset_playback_action_cmd_received_cb,
312 mc_server_unset_playback_position_cmd_received_cb,
313 mc_server_unset_shuffle_mode_cmd_received_cb,
314 /*mc_server_unset_repeat_mode_cmd_received_cb the last unsetter will never be used*/};
316 // This loop is no-op in case of success.
317 for (int i = 0; i < failed_setter; ++i) {
318 auto ret = unsetters[i](handle_);
319 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
320 LoggerE("Fail (%d) returned by the [%d] unsetter", ret, i);
325 // In Native API, since Tizen 5.0 an action instead of a state is sent to change the state of a
326 // server. In Web API the names were not refactored.
327 int ret = mc_server_set_playback_action_cmd_received_cb(handle_, OnPlaybackActionCommand, this);
328 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
329 return LogAndCreateResult(
330 ErrorCode::UNKNOWN_ERR, "Unable to set playback state command listener",
331 ("mc_server_set_playback_action_cmd_received_cb() error: %d, message: %s", ret,
332 get_error_message(ret)));
335 ret = mc_server_set_playback_position_cmd_received_cb(handle_, OnPlaybackPositionCommand, this);
336 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
338 return LogAndCreateResult(
339 ErrorCode::UNKNOWN_ERR, "Unable to set playback position command listener",
340 ("mc_server_set_playback_position_cmd_received_cb() error: %d, message: %s", ret,
341 get_error_message(ret)));
344 ret = mc_server_set_shuffle_mode_cmd_received_cb(handle_, OnShuffleModeCommand, this);
345 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
347 return LogAndCreateResult(
348 ErrorCode::UNKNOWN_ERR, "Unable to set shuffle mode command listener",
349 ("mc_server_set_shuffle_mode_cmd_received_cb() error: %d, message: %s", ret,
350 get_error_message(ret)));
353 ret = mc_server_set_repeat_mode_cmd_received_cb(handle_, OnRepeatModeCommand, this);
354 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
356 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to set repeat mode command listener",
357 ("mc_server_set_repeat_mode_cmd_received_cb() error: %d, message: %s",
358 ret, get_error_message(ret)));
361 change_request_playback_info_listener_ = callback;
363 return PlatformResult(ErrorCode::NO_ERROR);
366 PlatformResult MediaControllerServer::UnsetChangeRequestPlaybackInfoListener() {
369 int ret = mc_server_unset_playback_action_cmd_received_cb(handle_);
370 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
371 return LogAndCreateResult(
372 ErrorCode::UNKNOWN_ERR, "Unable to unset playback state command listener",
373 ("mc_server_unset_playback_action_cmd_received_cb() error: %d, message: %s", ret,
374 get_error_message(ret)));
377 ret = mc_server_unset_playback_position_cmd_received_cb(handle_);
378 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
379 return LogAndCreateResult(
380 ErrorCode::UNKNOWN_ERR, "Unable to unset playback position command listener",
381 ("mc_server_unset_playback_position_cmd_received_cb() error: %d, message: %s", ret,
382 get_error_message(ret)));
385 ret = mc_server_unset_shuffle_mode_cmd_received_cb(handle_);
386 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
387 return LogAndCreateResult(
388 ErrorCode::UNKNOWN_ERR, "Unable to unset shuffle mode command listener",
389 ("mc_server_unset_shuffle_mode_cmd_received_cb() error: %d, message: %s", ret,
390 get_error_message(ret)));
393 ret = mc_server_unset_repeat_mode_cmd_received_cb(handle_);
394 if (MEDIA_CONTROLLER_ERROR_NONE != ret) {
395 return LogAndCreateResult(
396 ErrorCode::UNKNOWN_ERR, "Unable to unset repeat mode command listener",
397 ("mc_server_unset_repeat_mode_cmd_received_cb() error: %d, message: %s", ret,
398 get_error_message(ret)));
401 change_request_playback_info_listener_ = nullptr;
403 return PlatformResult(ErrorCode::NO_ERROR);
406 void MediaControllerServer::OnPlaybackActionCommand(const char* client_name, const char* request_id,
407 mc_playback_action_e action, void* user_data) {
410 MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
412 // Here, we need to convert mc_playback_action_e enum to mc_playback_states_e enum.
413 std::string action_str;
414 PlatformResult result = types::MediaControllerPlaybackActionEnum.getName(action, &action_str);
416 LoggerW("MediaControllerPlaybackActionEnum.getName() failed, error: %s",
417 result.message().c_str());
421 mc_playback_states_e state_e;
422 result = types::MediaControllerPlaybackStateEnum.getValue(action_str, &state_e);
424 LoggerE("MediaControllerPlaybackStateEnum.getValue() failed, error: %s",
425 result.message().c_str());
429 if (server->playback_state_ == state_e) {
430 LoggerD("The media playback state did not change, skipping");
434 picojson::value data = picojson::value(picojson::object());
435 picojson::object& data_o = data.get<picojson::object>();
437 data_o["action"] = picojson::value(std::string("onplaybackstaterequest"));
438 data_o["state"] = picojson::value(action_str);
440 server->change_request_playback_info_listener_(&data);
443 void MediaControllerServer::OnPlaybackPositionCommand(const char* client_name,
444 const char* request_id,
445 unsigned long long position,
449 MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
451 if (server->position_ == position) {
452 LoggerD("The position did not change, skipping");
456 picojson::value data = picojson::value(picojson::object());
457 picojson::object& data_o = data.get<picojson::object>();
459 data_o["action"] = picojson::value(std::string("onplaybackpositionrequest"));
460 data_o["position"] = picojson::value(static_cast<double>(position));
462 server->change_request_playback_info_listener_(&data);
465 void MediaControllerServer::OnShuffleModeCommand(const char* client_name, const char* request_id,
466 mc_shuffle_mode_e mode, void* user_data) {
469 MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
471 if (server->shuffle_mode_ == mode) {
472 LoggerD("The shuffle mode did not change, skipping");
476 picojson::value data = picojson::value(picojson::object());
477 picojson::object& data_o = data.get<picojson::object>();
479 data_o["action"] = picojson::value(std::string("onshufflemoderequest"));
480 data_o["mode"] = picojson::value(mode == MC_SHUFFLE_MODE_ON);
482 server->change_request_playback_info_listener_(&data);
485 void MediaControllerServer::OnRepeatModeCommand(const char* client_name, const char* request_id,
486 mc_repeat_mode_e mode, void* user_data) {
489 MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
491 if (server->repeat_mode_ == mode) {
492 LoggerD("The repeat mode did not change, skipping");
496 picojson::value data = picojson::value(picojson::object());
497 picojson::object& data_o = data.get<picojson::object>();
499 data_o["action"] = picojson::value(std::string("onrepeatmoderequest"));
500 data_o["mode"] = picojson::value(mode == MC_REPEAT_MODE_ON);
502 server->change_request_playback_info_listener_(&data);
505 } // namespace mediacontroller
506 } // namespace extension