[MediaController] Add guards to map of playlists' handles
[platform/core/api/webapi-plugins.git] / src / mediacontroller / mediacontroller_instance.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "mediacontroller/mediacontroller_instance.h"
18
19 #include "common/current_application.h"
20 #include "common/logger.h"
21 #include "common/picojson.h"
22 #include "common/platform_result.h"
23 #include "common/scope_exit.h"
24 #include "common/task-queue.h"
25 #include "common/tools.h"
26
27 #include "mediacontroller/mediacontroller_utils.h"
28
29 #define MediaControllerUnknownErrorMsg "Unknown error occurred."
30 #define MediaControllerServerUnknownErrorMsg "Failed: server_"
31 #define MediaControllerClientUnknownErrorMsg "Failed: client_"
32
33 namespace extension {
34 namespace mediacontroller {
35
36 using namespace privileges;
37 using namespace attributes;
38
39 using common::ErrorCode;
40 using common::PlatformResult;
41 using common::TaskQueue;
42
43 MediaControllerInstance::MediaControllerInstance() {
44   ScopeLogger();
45   using namespace std::placeholders;
46
47 #define REGISTER_METHOD(M) \
48   RegisterSyncHandler(#M, std::bind(&MediaControllerInstance::M, this, _1, _2))
49
50   // server
51   REGISTER_METHOD(MediaControllerManagerCreateServer);
52   REGISTER_METHOD(MediaControllerServerUpdatePlaybackState);
53   REGISTER_METHOD(MediaControllerServerUpdatePlaybackPosition);
54   REGISTER_METHOD(MediaControllerServerUpdatePlaybackAgeRating);
55   REGISTER_METHOD(MediaControllerServerUpdateRepeatMode);
56   REGISTER_METHOD(MediaControllerServerUpdateRepeatState);
57   REGISTER_METHOD(MediaControllerServerUpdateShuffleMode);
58   REGISTER_METHOD(MediaControllerServerUpdateMetadata);
59   REGISTER_METHOD(MediaControllerServerUpdatePlaybackContentType);
60   REGISTER_METHOD(MediaControllerServerUpdatePlaybackContentType);
61   REGISTER_METHOD(MediaControllerServerAddChangeRequestPlaybackInfoListener);
62   REGISTER_METHOD(MediaControllerServerRemoveChangeRequestPlaybackInfoListener);
63   REGISTER_METHOD(MediaControllerServerAddSearchRequestListener);
64   REGISTER_METHOD(MediaControllerServerRemoveSearchRequestListener);
65   REGISTER_METHOD(MediaControllerServerAddCommandListener);
66   REGISTER_METHOD(MediaControllerServerReplyCommand);
67   REGISTER_METHOD(MediaControllerServerRemoveCommandListener);
68   REGISTER_METHOD(MediaControllerServerCreatePlaylist);
69   REGISTER_METHOD(MediaControllerServerSavePlaylist);
70   REGISTER_METHOD(MediaControllerServerDeletePlaylist);
71   REGISTER_METHOD(MediaControllerServerUpdatePlaybackItem);
72
73   REGISTER_METHOD(MediaControllerServerGetAllPlaylists);
74   REGISTER_METHOD(MediaControllerServerUpdateIconURI);
75   REGISTER_METHOD(MediaControllerServerSavePlaybackAbilities);
76   REGISTER_METHOD(MediaControllerServerSetDisplayModeAbility);
77   REGISTER_METHOD(MediaControllerServerSetDisplayRotationAbility);
78   REGISTER_METHOD(MediaControllerServerSetSimpleAbility);
79   REGISTER_METHOD(MediaControllerServerGetAllClientsInfo);
80
81   // client info
82   REGISTER_METHOD(MediaControllerClientInfoSendEvent);
83
84   // client
85   REGISTER_METHOD(MediaControllerManagerGetClient);
86   REGISTER_METHOD(MediaControllerClientFindServers);
87   REGISTER_METHOD(MediaControllerClientGetLatestServerInfo);
88   REGISTER_METHOD(MediaControllerClientGetPlaybackInfo);
89   REGISTER_METHOD(MediaControllerClientGetPlaybackAbility);
90   REGISTER_METHOD(MediaControllerClientGetDisplayModeAbility);
91   REGISTER_METHOD(MediaControllerClientGetDisplayRotationAbility);
92   REGISTER_METHOD(MediaControllerClientGetSimpleAbility);
93   REGISTER_METHOD(MediaControllerClientFindSubscribedServers);
94   REGISTER_METHOD(MediaControllerClientSendEventReply);
95   REGISTER_METHOD(MediaControllerClientSetCustomEventListener);
96   REGISTER_METHOD(MediaControllerClientUnsetCustomEventListener);
97
98   // server_info
99   REGISTER_METHOD(MediaControllerServerInfoSendPlaybackState);
100   REGISTER_METHOD(MediaControllerServerInfoSendPlaybackPosition);
101   REGISTER_METHOD(MediaControllerServerInfoSendRepeatMode);
102   REGISTER_METHOD(MediaControllerServerInfoSendRepeatState);
103   REGISTER_METHOD(MediaControllerServerInfoSendShuffleMode);
104   REGISTER_METHOD(MediaControllerServerInfoSendSearchRequest);
105   REGISTER_METHOD(MediaControllerServerInfoSendCommand);
106   REGISTER_METHOD(MediaControllerServerInfoAddServerStatusChangeListener);
107   REGISTER_METHOD(MediaControllerServerInfoRemoveServerStatusChangeListener);
108   REGISTER_METHOD(MediaControllerServerInfoAddPlaybackInfoChangeListener);
109   REGISTER_METHOD(MediaControllerServerInfoRemovePlaybackInfoChangeListener);
110   REGISTER_METHOD(MediaControllerServerInfoSendPlaybackItem);
111   REGISTER_METHOD(MediaControllerServerInfoAddPlaylistUpdatedListener);
112   REGISTER_METHOD(MediaControllerServerInfoRemovePlaylistUpdatedListener);
113   REGISTER_METHOD(MediaControllerServerInfoGetAllPlaylists);
114   REGISTER_METHOD(MediaControllerServerInfoGetIconURI);
115   REGISTER_METHOD(MediaControllerClientAddAbilityChangeListener);
116   REGISTER_METHOD(MediaControllerClientRemoveAbilityChangeListener);
117   REGISTER_METHOD(MediaControllerServerInfoPlaybackInfoSendPlaybackAction);
118   REGISTER_METHOD(MediaControllerServerInfoPlaybackInfoSendPlaybackPosition);
119   REGISTER_METHOD(MediaControllerServerInfoPlaybackInfoSendShuffleMode);
120   REGISTER_METHOD(MediaControllerServerInfoPlaybackInfoSendRepeatState);
121
122   // abilities_info
123   REGISTER_METHOD(MediaControllerAbilitiesInfoSubscribe);
124   REGISTER_METHOD(MediaControllerAbilitiesInfoUnsubscribe);
125
126   // playlist
127   REGISTER_METHOD(MediaControllerPlaylistAddItem);
128   REGISTER_METHOD(MediaControllerPlaylistGetItems);
129
130   // subtitles
131   REGISTER_METHOD(MediaControllerSubtitlesUpdateEnabled);
132   REGISTER_METHOD(MediaControllerSubtitlesAddChangeRequestListener);
133   REGISTER_METHOD(MediaControllerSubtitlesRemoveChangeRequestListener);
134
135   REGISTER_METHOD(MediaControllerSubtitlesInfoGetEnabled);
136   REGISTER_METHOD(MediaControllerSubtitlesInfoSendRequest);
137   REGISTER_METHOD(MediaControllerSubtitlesInfoAddModeChangeListener);
138   REGISTER_METHOD(MediaControllerSubtitlesInfoRemoveModeChangeListener);
139
140   // mode360
141   REGISTER_METHOD(MediaControllerMode360UpdateEnabled);
142   REGISTER_METHOD(MediaControllerMode360AddChangeRequestListener);
143   REGISTER_METHOD(MediaControllerMode360RemoveChangeRequestListener);
144
145   REGISTER_METHOD(MediaControllerMode360InfoGetEnabled);
146   REGISTER_METHOD(MediaControllerMode360InfoSendRequest);
147   REGISTER_METHOD(MediaControllerMode360InfoAddModeChangeListener);
148   REGISTER_METHOD(MediaControllerMode360InfoRemoveModeChangeListener);
149
150   // displayMode
151   REGISTER_METHOD(MediaControllerDisplayModeUpdateType);
152   REGISTER_METHOD(MediaControllerDisplayModeAddChangeRequestListener);
153   REGISTER_METHOD(MediaControllerDisplayModeRemoveChangeRequestListener);
154
155   REGISTER_METHOD(MediaControllerDisplayModeInfoGetType);
156   REGISTER_METHOD(MediaControllerDisplayModeInfoSendType);
157   REGISTER_METHOD(MediaControllerDisplayModeInfoAddModeChangeListener);
158   REGISTER_METHOD(MediaControllerDisplayModeInfoRemoveModeChangeListener);
159
160   // displayRotation
161   REGISTER_METHOD(MediaControllerDisplayRotationUpdate);
162   REGISTER_METHOD(MediaControllerDisplayRotationAddChangeRequestListener);
163   REGISTER_METHOD(MediaControllerDisplayRotationRemoveChangeRequestListener);
164
165   REGISTER_METHOD(MediaControllerDisplayRotationInfoGet);
166   REGISTER_METHOD(MediaControllerDisplayRotationInfoSend);
167   REGISTER_METHOD(MediaControllerDisplayRotationInfoAddChangeListener);
168   REGISTER_METHOD(MediaControllerDisplayRotationInfoRemoveChangeListener);
169
170   // playlists
171   REGISTER_METHOD(MediaControllerPlaylistsGetPlaylist);
172
173   // playlists_info
174   REGISTER_METHOD(MediaControllerPlaylistsInfoSendPlaybackItem);
175   REGISTER_METHOD(MediaControllerPlaylistsInfoGetPlaylist);
176
177 #undef REGISTER_METHOD
178 }
179
180 MediaControllerInstance::~MediaControllerInstance() {
181   ScopeLogger();
182   std::lock_guard<std::mutex> lock(playlist_map_mutex_);
183   for (auto const& s : server_playlist_map_) {
184     for (auto const& v : s.second) {
185       if (MEDIA_CONTROLLER_ERROR_NONE != mc_playlist_destroy(v.second)) {
186         LoggerE("Unable to destroy playlist %s", v.first.c_str());
187       }
188     }
189   }
190 }
191
192 #define CHECK_EXIST(args, name, out)                                            \
193   if (!args.contains(name)) {                                                   \
194     std::string msg = std::string(name) + " is required argument";              \
195     LogAndReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, msg), &out); \
196     return;                                                                     \
197   }
198
199 #define CHECK_TYPE(args, name, type, out)                                       \
200   if (!args.get(name).is<type>()) {                                             \
201     std::string msg = std::string(name) + " is not a " + #type;                 \
202     LogAndReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, msg), &out); \
203     return;                                                                     \
204   }
205
206 #define CHECK_ARGS(args, name, type, out) \
207   CHECK_EXIST(args, name, out)            \
208   CHECK_TYPE(args, name, type, out)
209
210 void MediaControllerInstance::MediaControllerManagerCreateServer(const picojson::value& args,
211                                                                  picojson::object& out) {
212   ScopeLogger();
213
214   CHECK_PRIVILEGE_ACCESS(kPrivilegeMediaControllerServer, &out);
215
216   if (server_) {
217     ReportSuccess(out);
218     return;
219   }
220
221   server_ = std::make_shared<MediaControllerServer>();
222   const PlatformResult& result = server_->Init();
223   if (!result) {
224     server_.reset();
225     LogAndReportError(result, &out, ("Failed to create server."));
226   }
227
228   ReportSuccess(out);
229 }
230
231 void MediaControllerInstance::MediaControllerServerUpdatePlaybackState(const picojson::value& args,
232                                                                        picojson::object& out) {
233   ScopeLogger();
234   CHECK_EXIST(args, kState, out)
235
236   if (!server_) {
237     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
238                       (MediaControllerServerUnknownErrorMsg));
239     return;
240   }
241
242   const std::string& state = args.get(kState).get<std::string>();
243   const PlatformResult& result = server_->SetPlaybackState(state);
244   if (!result) {
245     LogAndReportError(result, &out, ("Failed server_->SetPlaybackState()"));
246     return;
247   }
248
249   ReportSuccess(out);
250 }
251
252 void MediaControllerInstance::MediaControllerServerUpdateIconURI(const picojson::value& args,
253                                                                  picojson::object& out) {
254   ScopeLogger();
255   CHECK_EXIST(args, kIconURI, out);
256
257   if (!server_) {
258     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
259                       (MediaControllerServerUnknownErrorMsg));
260     return;
261   }
262
263   const char* icon_uri = nullptr;
264   if (args.get(kIconURI).is<std::string>()) {
265     icon_uri = args.get(kIconURI).get<std::string>().c_str();
266   } else if (!args.get(kIconURI).is<picojson::null>()) {
267     LogAndReportError(
268         PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Icon URI must be a string or null."), &out,
269         ("Icon URI is not a string or null."));
270     return;
271   }
272
273   PlatformResult result = server_->UpdateIconURI(icon_uri);
274   if (!result) {
275     LogAndReportError(result, &out, ("Failed server_->UpdateIconURI()"));
276     return;
277   }
278
279   ReportSuccess(out);
280 }
281
282 void MediaControllerInstance::MediaControllerServerUpdatePlaybackPosition(
283     const picojson::value& args, picojson::object& out) {
284   ScopeLogger();
285   if (!server_) {
286     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
287                       (MediaControllerServerUnknownErrorMsg));
288     return;
289   }
290
291   CHECK_EXIST(args, kPosition, out)
292
293   double position = args.get(kPosition).get<double>();
294   const PlatformResult& result = server_->SetPlaybackPosition(position);
295   if (!result) {
296     LogAndReportError(result, &out, ("Failed: server_->SetPlaybackPosition()"));
297     return;
298   }
299
300   ReportSuccess(out);
301 }
302
303 void MediaControllerInstance::MediaControllerServerUpdatePlaybackAgeRating(
304     const picojson::value& args, picojson::object& out) {
305   ScopeLogger();
306   if (!server_) {
307     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Server handle not initialized."),
308                       &out, (MediaControllerServerUnknownErrorMsg));
309     return;
310   }
311
312   CHECK_EXIST(args, kRating, out)
313
314   const std::string& rating = args.get(kRating).get<std::string>();
315   const PlatformResult& result = server_->SetContentAgeRating(rating);
316   if (!result) {
317     LogAndReportError(result, &out, ("Failed: server_->SetContentAgeRating()"));
318     return;
319   }
320
321   ReportSuccess(out);
322 }
323
324 void MediaControllerInstance::MediaControllerServerUpdateShuffleMode(const picojson::value& args,
325                                                                      picojson::object& out) {
326   ScopeLogger();
327   if (!server_) {
328     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
329                       (MediaControllerServerUnknownErrorMsg));
330     return;
331   }
332
333   CHECK_EXIST(args, kMode, out)
334
335   bool mode = args.get(kMode).get<bool>();
336
337   const PlatformResult& result = server_->SetShuffleMode(mode);
338   if (!result) {
339     LogAndReportError(result, &out, ("Failed: server_->SetShuffleMode()"));
340     return;
341   }
342
343   ReportSuccess(out);
344 }
345
346 void MediaControllerInstance::MediaControllerServerUpdatePlaybackContentType(
347     const picojson::value& args, picojson::object& out) {
348   ScopeLogger();
349   if (!server_) {
350     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
351                       (MediaControllerServerUnknownErrorMsg));
352     return;
353   }
354
355   CHECK_ARGS(args, kContentType, std::string, out);
356   std::string content_type = args.get(kContentType).get<std::string>();
357
358   PlatformResult result = server_->SetContentType(content_type);
359   if (!result) {
360     LogAndReportError(result, &out, ("Failed: server_>SetContentType()"));
361     return;
362   }
363
364   ReportSuccess(out);
365 }
366
367 void MediaControllerInstance::MediaControllerServerUpdateRepeatMode(const picojson::value& args,
368                                                                     picojson::object& out) {
369   ScopeLogger();
370   common::tools::PrintDeprecationWarningFor("updateRepeatMode()", "updateRepeatState()");
371
372   if (!server_) {
373     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
374                       (MediaControllerServerUnknownErrorMsg));
375     return;
376   }
377
378   CHECK_EXIST(args, kMode, out)
379
380   bool mode = args.get(kMode).get<bool>();
381
382   const PlatformResult& result = server_->SetRepeatMode(mode);
383   if (!result) {
384     LogAndReportError(result, &out, ("Failed: server_->SetRepeatMode()"));
385     return;
386   }
387
388   ReportSuccess(out);
389 }
390
391 void MediaControllerInstance::MediaControllerServerUpdateRepeatState(const picojson::value& args,
392                                                                      picojson::object& out) {
393   ScopeLogger();
394   CHECK_EXIST(args, kState, out)
395
396   const std::string& state = args.get(kState).get<std::string>();
397
398   const PlatformResult& result = server_->SetRepeatState(state);
399   if (!result) {
400     LogAndReportError(result, &out, ("Failed: server_->SetRepeatState()"));
401     return;
402   }
403
404   ReportSuccess(out);
405 }
406
407 void MediaControllerInstance::MediaControllerServerUpdateMetadata(const picojson::value& args,
408                                                                   picojson::object& out) {
409   ScopeLogger();
410   if (!server_) {
411     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
412                       (MediaControllerServerUnknownErrorMsg));
413     return;
414   }
415
416   CHECK_EXIST(args, kMetadata, out)
417
418   const picojson::object& metadata = args.get(kMetadata).get<picojson::object>();
419
420   const PlatformResult& result = server_->SetMetadata(metadata);
421   if (!result) {
422     LogAndReportError(result, &out, ("Failed: server_->SetMetadata()"));
423     return;
424   }
425
426   ReportSuccess(out);
427 }
428
429 void MediaControllerInstance::MediaControllerServerAddChangeRequestPlaybackInfoListener(
430     const picojson::value& args, picojson::object& out) {
431   ScopeLogger();
432   if (!server_) {
433     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
434                       (MediaControllerServerUnknownErrorMsg));
435     return;
436   }
437
438   CHECK_EXIST(args, kListenerId, out)
439
440   JsonCallback callback = [this, args](picojson::value* data) -> void {
441     if (!data) {
442       LoggerE("No data passed to json callback");
443       return;
444     }
445
446     picojson::object& request_o = data->get<picojson::object>();
447     request_o[kListenerId] = args.get(kListenerId);
448
449     Instance::PostMessage(this, data->serialize().c_str());
450   };
451
452   auto result = server_->SetChangeRequestPlaybackInfoListener(callback);
453   if (!result) {
454     LogAndReportError(result, &out);
455   }
456
457   ReportSuccess(out);
458 }
459
460 void MediaControllerInstance::MediaControllerServerRemoveChangeRequestPlaybackInfoListener(
461     const picojson::value& args, picojson::object& out) {
462   ScopeLogger();
463   if (!server_) {
464     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
465                       (MediaControllerServerUnknownErrorMsg));
466     return;
467   }
468
469   auto result = server_->UnsetChangeRequestPlaybackInfoListener();
470   if (!result) {
471     LogAndReportError(result, &out);
472   }
473 }
474
475 void MediaControllerInstance::MediaControllerServerAddSearchRequestListener(
476     const picojson::value& args, picojson::object& out) {
477   ScopeLogger();
478
479   if (!server_) {
480     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Server not initialized."), &out,
481                       (MediaControllerServerUnknownErrorMsg));
482     return;
483   }
484
485   JsonCallback on_request = [this, args](picojson::value* request) -> void {
486     picojson::object& request_o = request->get<picojson::object>();
487     request_o[kListenerId] = args.get(kListenerId);
488     Instance::PostMessage(this, request->serialize().c_str());
489   };
490
491   auto result = server_->SetSearchRequestListener(on_request);
492   if (!result) {
493     LogAndReportError(result, &out);
494     return;
495   }
496
497   ReportSuccess(out);
498 }
499
500 void MediaControllerInstance::MediaControllerServerRemoveSearchRequestListener(
501     const picojson::value& args, picojson::object& out) {
502   ScopeLogger();
503
504   if (!server_) {
505     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Server not initialized."), &out,
506                       (MediaControllerServerUnknownErrorMsg));
507     return;
508   }
509
510   auto result = server_->UnsetSearchRequestListener();
511   if (!result) {
512     LogAndReportError(result, &out);
513     return;
514   }
515 }
516
517 void MediaControllerInstance::MediaControllerServerAddCommandListener(const picojson::value& args,
518                                                                       picojson::object& out) {
519   ScopeLogger();
520   if (!server_) {
521     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
522                       (MediaControllerServerUnknownErrorMsg));
523     return;
524   }
525
526   JsonCallback on_command = [this, args](picojson::value* request) -> void {
527     picojson::object& request_o = request->get<picojson::object>();
528     request_o[kListenerId] = args.get(kListenerId);
529
530     Instance::PostMessage(this, request->serialize().c_str());
531   };
532
533   auto result = server_->SetCommandListener(on_command);
534   if (!result) {
535     LogAndReportError(result, &out);
536   }
537
538   ReportSuccess(out);
539 }
540
541 void MediaControllerInstance::MediaControllerServerReplyCommand(const picojson::value& args,
542                                                                 picojson::object& out) {
543   ScopeLogger();
544   if (!server_) {
545     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
546                       (MediaControllerServerUnknownErrorMsg));
547     return;
548   }
549
550   CHECK_EXIST(args, kClientName, out);
551   CHECK_EXIST(args, kRequestId, out);
552   CHECK_EXIST(args, kReply, out);
553
554   if (args.get(kRequestId).is<picojson::null>()) {
555     LoggerD("The request was sent without reply listener, skipping");
556     ReportSuccess(out);
557     return;
558   }
559
560   auto client_name = args.get(kClientName).get<std::string>();
561   auto request_id = args.get(kRequestId).get<std::string>();
562
563   auto reply = args.get(kReply);
564   CHECK_EXIST(reply, kCode, out);
565   CHECK_EXIST(reply, kData, out);
566
567   LoggerD("reply json: %s", reply.serialize().c_str());
568   int code = static_cast<int>(reply.get(kCode).get<double>());
569   auto data = reply.get(kData);
570
571   auto result = server_->CommandReply(client_name, request_id, code, data);
572   if (!result) {
573     LogAndReportError(result, &out);
574     return;
575   }
576
577   ReportSuccess(out);
578 }
579
580 void MediaControllerInstance::MediaControllerServerRemoveCommandListener(
581     const picojson::value& args, picojson::object& out) {
582   ScopeLogger();
583   if (!server_) {
584     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
585                       (MediaControllerServerUnknownErrorMsg));
586     return;
587   }
588
589   auto result = server_->UnsetCommandListener();
590   if (!result) {
591     LogAndReportError(result, &out);
592   }
593
594   ReportSuccess(out);
595 }
596
597 void MediaControllerInstance::MediaControllerServerCreatePlaylist(const picojson::value& args,
598                                                                   picojson::object& out) {
599   ScopeLogger();
600   if (!server_) {
601     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
602                       (MediaControllerServerUnknownErrorMsg));
603     return;
604   }
605
606   CHECK_ARGS(args, kPlaylistName, std::string, out)
607
608   picojson::value playlist_info = picojson::value();
609   std::string serverName = common::CurrentApplication::GetInstance().GetApplicationId();
610   auto playlistName = args.get(kPlaylistName).get<std::string>();
611   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
612   std::lock_guard<std::mutex> lock(playlist_map_mutex_);
613
614   if (server_playlist_map_.find(serverName) != server_playlist_map_.end() &&
615       server_playlist_map_[serverName].find(playlistName) !=
616           server_playlist_map_[serverName].end()) {
617     result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
618                                 "Playlist with given name already exists");
619     LogAndReportError(result, &out);
620     return;
621   }
622   mc_playlist_h playlist_handle = nullptr;
623   result = server_->CreatePlaylist(serverName, playlistName, &playlist_info, playlist_handle);
624   if (!result) {
625     LogAndReportError(result, &out, ("Failed: server_->CreatePlaylist"));
626     return;
627   }
628
629   server_playlist_map_[serverName][playlistName] = playlist_handle;
630
631   ReportSuccess(playlist_info, out);
632 }
633
634 void MediaControllerInstance::MediaControllerServerSavePlaylist(const picojson::value& args,
635                                                                 picojson::object& out) {
636   ScopeLogger();
637   if (!server_) {
638     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
639                       (MediaControllerServerUnknownErrorMsg));
640     return;
641   }
642
643   CHECK_EXIST(args, kCallbackId, out)
644   CHECK_ARGS(args, kPlaylistName, std::string, out)
645   CHECK_ARGS(args, kServerName, std::string, out)
646
647   auto save = [this, args]() -> void {
648     picojson::value response = picojson::value(picojson::object());
649     picojson::object& response_obj = response.get<picojson::object>();
650     response_obj[kCallbackId] = args.get(kCallbackId);
651
652     auto name = args.get(kPlaylistName).get<std::string>();
653     auto serverName = args.get(kServerName).get<std::string>();
654
655     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
656
657     {
658       std::lock_guard<std::mutex> lock(playlist_map_mutex_);
659       if (server_playlist_map_.find(serverName) == server_playlist_map_.end() ||
660           server_playlist_map_[serverName].find(name) == server_playlist_map_[serverName].end()) {
661         result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
662                                     "Playlist with given name doesn't exist");
663         LogAndReportError(result, &response_obj,
664                           ("Failed: MediaControllerInstance::MediaControllerServerSavePlaylist"));
665         Instance::PostMessage(this, response.serialize().c_str());
666         return;
667       }
668
669       result = server_->SavePlaylist(server_playlist_map_[serverName][name]);
670     }
671     if (result) {
672       ReportSuccess(response_obj);
673     } else {
674       LogAndReportError(result, &response_obj, ("Failed: server_->SavePlaylist"));
675     }
676
677     Instance::PostMessage(this, response.serialize().c_str());
678   };
679
680   TaskQueue::GetInstance().Async(save);
681
682   ReportSuccess(out);
683 }
684
685 void MediaControllerInstance::MediaControllerServerDeletePlaylist(const picojson::value& args,
686                                                                   picojson::object& out) {
687   ScopeLogger();
688   if (!server_) {
689     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
690                       (MediaControllerServerUnknownErrorMsg));
691     return;
692   }
693
694   CHECK_EXIST(args, kCallbackId, out)
695   CHECK_ARGS(args, kPlaylistName, std::string, out)
696
697   auto del = [this, args]() -> void {
698     picojson::value response = picojson::value(picojson::object());
699     picojson::object& response_obj = response.get<picojson::object>();
700     response_obj[kCallbackId] = args.get(kCallbackId);
701
702     auto name = args.get(kPlaylistName).get<std::string>();
703     std::string serverName = common::CurrentApplication::GetInstance().GetApplicationId();
704
705     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
706
707     {
708       std::lock_guard<std::mutex> lock(playlist_map_mutex_);
709
710       if (server_playlist_map_.find(serverName) == server_playlist_map_.end() ||
711           server_playlist_map_[serverName].find(name) == server_playlist_map_[serverName].end()) {
712         result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
713                                     "Playlist with given name doesn't exist");
714         LogAndReportError(result, &response_obj,
715                           ("Failed: MediaControllerInstance::MediaControllerServerDeletePlaylist"));
716         Instance::PostMessage(this, response.serialize().c_str());
717         return;
718       }
719       result = server_->DeletePlaylist(server_playlist_map_[serverName][name]);
720
721       if (result) {
722         ReportSuccess(response_obj);
723       } else {
724         LogAndReportError(result, &response_obj, ("Failed: server_->DeletePlaylist"));
725       }
726
727       if (MEDIA_CONTROLLER_ERROR_NONE !=
728           mc_playlist_destroy(server_playlist_map_[serverName][name])) {
729         LoggerE("Unable to destroy playlist %s", name.c_str());
730       }
731
732       server_playlist_map_[serverName].erase(name);
733     }
734
735     Instance::PostMessage(this, response.serialize().c_str());
736   };
737
738   TaskQueue::GetInstance().Async(del);
739
740   ReportSuccess(out);
741 }
742
743 void MediaControllerInstance::MediaControllerServerUpdatePlaybackItem(const picojson::value& args,
744                                                                       picojson::object& out) {
745   ScopeLogger();
746   if (!server_) {
747     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
748                       (MediaControllerServerUnknownErrorMsg));
749     return;
750   }
751
752   CHECK_ARGS(args, kPlaylistName, std::string, out)
753   CHECK_ARGS(args, kIndex, std::string, out)
754
755   auto result = server_->UpdatePlaybackItem(args.get(kPlaylistName).get<std::string>(),
756                                             args.get(kIndex).get<std::string>());
757   if (!result) {
758     LogAndReportError(result, &out);
759     return;
760   }
761
762   ReportSuccess(out);
763 }
764
765 void MediaControllerInstance::MediaControllerServerGetAllPlaylists(const picojson::value& args,
766                                                                    picojson::object& out) {
767   ScopeLogger();
768   if (!server_) {
769     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
770                       (MediaControllerServerUnknownErrorMsg));
771     return;
772   }
773
774   auto get = [this, args]() -> void {
775     picojson::value response = picojson::value(picojson::object());
776     picojson::object& response_obj = response.get<picojson::object>();
777
778     response_obj[kCallbackId] = args.get(kCallbackId);
779
780     std::string app_id = common::CurrentApplication::GetInstance().GetApplicationId();
781
782     if (app_id.empty()) {
783       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while get playlists"),
784                         &response_obj, ("CurrentApplication::GetInstance().GetApplicationId()"));
785       Instance::PostMessage(this, response.serialize().c_str());
786       return;
787     }
788
789     std::map<std::string, mc_playlist_h> new_playlists_map;
790     auto result = utils::GetAllPlaylistsHandles(app_id, &new_playlists_map);
791     if (!result) {
792       LogAndReportError(result, &response_obj, ("Failed: utils::GetAllPlaylists"));
793       Instance::PostMessage(this, response.serialize().c_str());
794       return;
795     }
796     // update the list of stored handles
797     {
798       std::lock_guard<std::mutex> lock(playlist_map_mutex_);
799
800       utils::UpdatePlaylistHandleMap(app_id, new_playlists_map, server_playlist_map_);
801       picojson::value playlists = utils::CreatePlaylistsJSON(app_id, new_playlists_map);
802
803       response_obj[kResult] = picojson::value{playlists};
804     }
805     ReportSuccess(response_obj);
806     Instance::PostMessage(this, response.serialize().c_str());
807   };
808
809   TaskQueue::GetInstance().Async(get);
810
811   ReportSuccess(out);
812 }
813
814 void MediaControllerInstance::MediaControllerServerSavePlaybackAbilities(
815     const picojson::value& args, picojson::object& out) {
816   ScopeLogger();
817
818   if (!server_) {
819     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
820                       (MediaControllerServerUnknownErrorMsg));
821     return;
822   }
823
824   for (auto e : types::MediaControllerPlaybackActionEnum) {
825     CHECK_ARGS(args, e.first, std::string, out);
826   }
827
828   const PlatformResult& result = server_->SavePlaybackAbilities(args);
829   if (!result) {
830     LogAndReportError(result, &out, ("Failed server_->SavePlaybackAbilities()"));
831     return;
832   }
833
834   ReportSuccess(out);
835 }
836
837 void MediaControllerInstance::MediaControllerServerSetDisplayModeAbility(
838     const picojson::value& args, picojson::object& out) {
839   ScopeLogger();
840
841   if (!server_) {
842     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
843                       (MediaControllerServerUnknownErrorMsg));
844     return;
845   }
846
847   CHECK_ARGS(args, kMode, std::string, out)
848   CHECK_ARGS(args, kSupport, std::string, out)
849
850   std::string support = args.get(kSupport).get<std::string>();
851   std::string mode = args.get(kMode).get<std::string>();
852
853   const PlatformResult& result = server_->SetDisplayModeAbility(mode, support);
854   if (!result) {
855     LogAndReportError(result, &out, ("Failed server_->SetDisplayModeAbility()"));
856     return;
857   }
858
859   ReportSuccess(out);
860 }
861
862 void MediaControllerInstance::MediaControllerServerSetDisplayRotationAbility(
863     const picojson::value& args, picojson::object& out) {
864   ScopeLogger();
865
866   if (!server_) {
867     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
868                       (MediaControllerServerUnknownErrorMsg));
869     return;
870   }
871
872   CHECK_ARGS(args, kDisplayRotationAbility, std::string, out)
873   CHECK_ARGS(args, kSupport, std::string, out)
874
875   std::string display_rotation_ability = args.get(kDisplayRotationAbility).get<std::string>();
876   std::string support = args.get(kSupport).get<std::string>();
877   const PlatformResult& result =
878       server_->SetDisplayRotationAbility(display_rotation_ability, support);
879   if (!result) {
880     LogAndReportError(result, &out, ("Failed server_->SetDisplayRotationAbility()"));
881     return;
882   }
883
884   ReportSuccess(out);
885 }
886
887 void MediaControllerInstance::MediaControllerServerSetSimpleAbility(const picojson::value& args,
888                                                                     picojson::object& out) {
889   ScopeLogger();
890
891   if (!server_) {
892     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
893                       (MediaControllerServerUnknownErrorMsg));
894     return;
895   }
896
897   CHECK_ARGS(args, kAbilityType, std::string, out)
898   CHECK_ARGS(args, kSupport, std::string, out)
899
900   std::string ability_type = args.get(kAbilityType).get<std::string>();
901   std::string support = args.get(kSupport).get<std::string>();
902   const PlatformResult& result = server_->SetSimpleAbility(ability_type, support);
903   if (!result) {
904     LogAndReportError(result, &out, ("Failed server_->SetSimpleAbility()"));
905     return;
906   }
907
908   ReportSuccess(out);
909 }
910
911 void MediaControllerInstance::MediaControllerServerGetAllClientsInfo(const picojson::value& args,
912                                                                      picojson::object& out) {
913   ScopeLogger();
914   if (!server_) {
915     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out,
916                       ("Failed: server_"));
917     return;
918   }
919
920   picojson::array clientsInfo;
921   auto result = server_->GetAllClientsInfo(&clientsInfo);
922   if (!result) {
923     LogAndReportError(result, &out);
924     return;
925   }
926
927   ReportSuccess(picojson::value(clientsInfo), out);
928 }
929
930 void MediaControllerInstance::MediaControllerClientInfoSendEvent(const picojson::value& args,
931                                                                  picojson::object& out) {
932   ScopeLogger();
933   if (!server_) {
934     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out,
935                       ("Failed: server_"));
936     return;
937   }
938
939   CHECK_ARGS(args, kEventName, std::string, out);
940   CHECK_EXIST(args, kEventData, out);
941   CHECK_ARGS(args, kClientName, std::string, out);
942   CHECK_ARGS(args, kReplyListener, std::string, out);
943
944   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
945     picojson::object& reply_obj = reply->get<picojson::object>();
946     reply_obj[kListenerId] = args.get(kReplyListener);
947     Instance::PostMessage(this, reply->serialize().c_str());
948   };
949
950   char* request_id = nullptr;
951   SCOPE_EXIT {
952     free(request_id);
953   };
954
955   PlatformResult result =
956       server_->SendEvent(args.get(kEventName).get<std::string>().c_str(), args.get(kEventData),
957                          args.get(kClientName).get<std::string>().c_str(), reply_cb, &request_id);
958
959   if (result) {
960     out[kRequestId] = picojson::value(std::string(request_id));
961     ReportSuccess(out);
962   } else {
963     LogAndReportError(result, &out, ("Failed to send event."));
964   }
965 }
966
967 void MediaControllerInstance::MediaControllerManagerGetClient(const picojson::value& args,
968                                                               picojson::object& out) {
969   ScopeLogger();
970
971   CHECK_PRIVILEGE_ACCESS(kPrivilegeMediaControllerClient, &out);
972
973   if (client_) {
974     ReportSuccess(out);
975     return;
976   }
977
978   client_ = std::make_shared<MediaControllerClient>();
979   const PlatformResult& result = client_->Init();
980   if (!result) {
981     client_.reset();
982     LogAndReportError(result, &out, ("Failed: client_->Init()"));
983   }
984
985   ReportSuccess(out);
986 }
987
988 void MediaControllerInstance::MediaControllerClientSendEventReply(const picojson::value& args,
989                                                                   picojson::object& out) {
990   ScopeLogger();
991   if (!client_) {
992     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out,
993                       ("Failed: client_"));
994     return;
995   }
996
997   CHECK_ARGS(args, kServerName, std::string, out);
998   CHECK_EXIST(args, kResult, out);
999   CHECK_ARGS(args, kRequestId, std::string, out);
1000   CHECK_ARGS(args, kResultCode, double, out);
1001
1002   auto result =
1003       client_->SendEventReply(args.get(kServerName).get<std::string>().c_str(), args.get(kResult),
1004                               static_cast<int>(args.get(kResultCode).get<double>()),
1005                               args.get(kRequestId).get<std::string>().c_str());
1006
1007   if (!result) {
1008     LogAndReportError(result, &out);
1009     return;
1010   }
1011
1012   ReportSuccess(out);
1013 }
1014
1015 void MediaControllerInstance::MediaControllerClientSetCustomEventListener(
1016     const picojson::value& args, picojson::object& out) {
1017   ScopeLogger();
1018   if (!client_) {
1019     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out,
1020                       ("Failed: client_"));
1021     return;
1022   }
1023
1024   CHECK_ARGS(args, kListenerId, std::string, out);
1025
1026   JsonCallback callback = [this, args](picojson::value* data) -> void {
1027     if (nullptr == data) {
1028       LoggerE("No data passed to json callback");
1029       return;
1030     }
1031
1032     picojson::object& request_o = data->get<picojson::object>();
1033     request_o[kListenerId] = args.get(kListenerId);
1034
1035     Instance::PostMessage(this, data->serialize().c_str());
1036   };
1037
1038   auto result = client_->SetCustomEventListener(callback);
1039   if (!result) {
1040     LogAndReportError(result, &out);
1041     return;
1042   }
1043
1044   ReportSuccess(out);
1045 }
1046
1047 void MediaControllerInstance::MediaControllerClientUnsetCustomEventListener(
1048     const picojson::value& args, picojson::object& out) {
1049   ScopeLogger();
1050   if (!client_) {
1051     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out,
1052                       ("Failed: client_"));
1053     return;
1054   }
1055
1056   auto result = client_->UnsetCustomEventListener();
1057   if (!result) {
1058     LogAndReportError(result, &out);
1059     return;
1060   }
1061
1062   ReportSuccess(out);
1063 }
1064
1065 void MediaControllerInstance::MediaControllerClientFindServers(const picojson::value& args,
1066                                                                picojson::object& out) {
1067   ScopeLogger();
1068   if (!client_) {
1069     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1070                       (MediaControllerClientUnknownErrorMsg));
1071     return;
1072   }
1073
1074   CHECK_EXIST(args, kCallbackId, out)
1075
1076   auto search = [this, args]() -> void {
1077     picojson::value response = picojson::value(picojson::object());
1078     picojson::object& response_obj = response.get<picojson::object>();
1079
1080     picojson::value servers = picojson::value(picojson::array());
1081     PlatformResult result = client_->FindServers(&servers.get<picojson::array>());
1082
1083     response_obj[kCallbackId] = args.get(kCallbackId);
1084     if (result) {
1085       ReportSuccess(servers, response_obj);
1086     } else {
1087       LogAndReportError(result, &response_obj, ("Failed to find servers"));
1088     }
1089
1090     Instance::PostMessage(this, response.serialize().c_str());
1091   };
1092
1093   TaskQueue::GetInstance().Async(search);
1094
1095   ReportSuccess(out);
1096 }
1097
1098 void MediaControllerInstance::MediaControllerClientGetLatestServerInfo(const picojson::value& args,
1099                                                                        picojson::object& out) {
1100   ScopeLogger();
1101   if (!client_) {
1102     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1103                       (MediaControllerClientUnknownErrorMsg));
1104     return;
1105   }
1106
1107   picojson::value server_info = picojson::value();
1108   PlatformResult result = client_->GetLatestServerInfo(&server_info);
1109   if (!result) {
1110     LogAndReportError(result, &out, ("Failed: client_->GetLatestServerInfo"));
1111     return;
1112   }
1113
1114   ReportSuccess(server_info, out);
1115 }
1116
1117 void MediaControllerInstance::MediaControllerClientGetPlaybackInfo(const picojson::value& args,
1118                                                                    picojson::object& out) {
1119   ScopeLogger();
1120   if (!client_) {
1121     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1122                       (MediaControllerClientUnknownErrorMsg));
1123     return;
1124   }
1125
1126   CHECK_EXIST(args, kName, out)
1127
1128   picojson::value playback_info = picojson::value(picojson::object());
1129   PlatformResult result = client_->GetPlaybackInfo(args.get(kName).get<std::string>(),
1130                                                    &playback_info.get<picojson::object>());
1131
1132   if (!result) {
1133     LogAndReportError(result, &out, ("Failed: client_->GetPlaybackInfo"));
1134     return;
1135   }
1136
1137   ReportSuccess(playback_info, out);
1138 }
1139
1140 void MediaControllerInstance::MediaControllerClientGetPlaybackAbility(const picojson::value& args,
1141                                                                       picojson::object& out) {
1142   ScopeLogger();
1143
1144   if (!client_) {
1145     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1146                       (MediaControllerClientUnknownErrorMsg));
1147     return;
1148   }
1149
1150   CHECK_ARGS(args, kServerName, std::string, out)
1151   CHECK_ARGS(args, kAction, std::string, out)
1152
1153   std::string server_name = args.get(kServerName).get<std::string>();
1154   std::string action = args.get(kAction).get<std::string>();
1155   picojson::value ability = picojson::value(picojson::object());
1156   PlatformResult result = client_->GetPlaybackAbility(server_name, action, &ability);
1157   if (!result) {
1158     LogAndReportError(result, &out, ("Failed: client_->GetPlaybackAbility"));
1159     return;
1160   }
1161
1162   ReportSuccess(ability, out);
1163 }
1164
1165 void MediaControllerInstance::MediaControllerClientGetDisplayModeAbility(
1166     const picojson::value& args, picojson::object& out) {
1167   ScopeLogger();
1168
1169   if (!client_) {
1170     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1171                       (MediaControllerClientUnknownErrorMsg));
1172     return;
1173   }
1174
1175   CHECK_ARGS(args, kServerName, std::string, out)
1176   CHECK_ARGS(args, kMode, std::string, out)
1177
1178   std::string server_name = args.get(kServerName).get<std::string>();
1179   std::string mode = args.get(kMode).get<std::string>();
1180   std::string ability;
1181   PlatformResult result = client_->GetDisplayModeAbility(server_name, mode, &ability);
1182   if (!result) {
1183     LogAndReportError(result, &out, ("Failed: client_->GetDisplayModeAbility"));
1184     return;
1185   }
1186
1187   ReportSuccess(picojson::value(ability), out);
1188 }
1189
1190 void MediaControllerInstance::MediaControllerClientGetDisplayRotationAbility(
1191     const picojson::value& args, picojson::object& out) {
1192   ScopeLogger();
1193
1194   if (!client_) {
1195     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1196                       (MediaControllerClientUnknownErrorMsg));
1197     return;
1198   }
1199
1200   CHECK_ARGS(args, kServerName, std::string, out)
1201   CHECK_ARGS(args, kDisplayRotationAbility, std::string, out)
1202
1203   std::string server_name = args.get(kServerName).get<std::string>();
1204   std::string display_rotation_ability = args.get(kDisplayRotationAbility).get<std::string>();
1205   std::string ability;
1206
1207   PlatformResult result =
1208       client_->GetDisplayRotationAbility(server_name, display_rotation_ability, &ability);
1209   if (!result) {
1210     LogAndReportError(result, &out, ("Failed: client_->GetDisplayRotationAbility"));
1211     return;
1212   }
1213
1214   ReportSuccess(picojson::value(ability), out);
1215 }
1216
1217 void MediaControllerInstance::MediaControllerClientGetSimpleAbility(const picojson::value& args,
1218                                                                     picojson::object& out) {
1219   ScopeLogger();
1220
1221   if (!client_) {
1222     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1223                       (MediaControllerClientUnknownErrorMsg));
1224     return;
1225   }
1226
1227   CHECK_ARGS(args, kAbilityType, std::string, out)
1228   CHECK_ARGS(args, kServerName, std::string, out)
1229
1230   picojson::value ability_val = picojson::value();
1231   std::string ability_type = args.get(kAbilityType).get<std::string>();
1232   std::string server_name = args.get(kServerName).get<std::string>();
1233   PlatformResult result = client_->GetSimpleAbility(server_name, ability_type, &ability_val);
1234   if (!result) {
1235     LogAndReportError(result, &out, ("Failed: client_->GetSimpleAbility"));
1236     return;
1237   }
1238
1239   ReportSuccess(ability_val, out);
1240 }
1241
1242 void MediaControllerInstance::MediaControllerClientFindSubscribedServers(
1243     const picojson::value& args, picojson::object& out) {
1244   ScopeLogger();
1245
1246   if (!client_) {
1247     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1248                       (MediaControllerClientUnknownErrorMsg));
1249     return;
1250   }
1251
1252   CHECK_EXIST(args, kCallbackId, out)
1253
1254   picojson::value callback_id = args.get(kCallbackId);
1255
1256   auto search = [this, callback_id]() -> void {
1257     picojson::value response = picojson::value(picojson::object());
1258     picojson::object& response_obj = response.get<picojson::object>();
1259
1260     picojson::value servers = picojson::value(picojson::array());
1261     PlatformResult result = client_->FindSubscribedServers(&servers.get<picojson::array>());
1262
1263     response_obj[kCallbackId] = callback_id;
1264     if (result) {
1265       ReportSuccess(servers, response_obj);
1266     } else {
1267       LogAndReportError(result, &response_obj, ("Failed to find subscribed servers"));
1268     }
1269
1270     Instance::PostMessage(this, response.serialize().c_str());
1271   };
1272
1273   TaskQueue::GetInstance().Async(search);
1274
1275   ReportSuccess(out);
1276 }
1277
1278 void MediaControllerInstance::MediaControllerServerInfoSendPlaybackState(
1279     const picojson::value& args, picojson::object& out) {
1280   ScopeLogger();
1281   if (!client_) {
1282     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1283                       (MediaControllerClientUnknownErrorMsg));
1284     return;
1285   }
1286
1287   CHECK_EXIST(args, kCallbackId, out)
1288   CHECK_EXIST(args, kName, out)
1289   CHECK_EXIST(args, kState, out)
1290
1291   auto send = [this, args]() -> void {
1292     picojson::value response = picojson::value(picojson::object());
1293     picojson::object& response_obj = response.get<picojson::object>();
1294     response_obj[kCallbackId] = args.get(kCallbackId);
1295
1296     PlatformResult result = client_->SendPlaybackState(args.get(kName).get<std::string>(),
1297                                                        args.get(kState).get<std::string>());
1298
1299     if (result) {
1300       ReportSuccess(response_obj);
1301     } else {
1302       LogAndReportError(result, &response_obj, ("Failed: client_->SendPlaybackState"));
1303     }
1304
1305     Instance::PostMessage(this, response.serialize().c_str());
1306   };
1307
1308   TaskQueue::GetInstance().Async(send);
1309
1310   ReportSuccess(out);
1311 }
1312
1313 void MediaControllerInstance::MediaControllerServerInfoSendPlaybackPosition(
1314     const picojson::value& args, picojson::object& out) {
1315   ScopeLogger();
1316   if (!client_) {
1317     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1318                       (MediaControllerClientUnknownErrorMsg));
1319     return;
1320   }
1321
1322   CHECK_ARGS(args, kCallbackId, double, out)
1323   CHECK_ARGS(args, kServerName, std::string, out)
1324   CHECK_ARGS(args, kPosition, double, out)
1325
1326   auto send = [this, args]() -> void {
1327     picojson::value response = picojson::value(picojson::object());
1328     picojson::object& response_obj = response.get<picojson::object>();
1329     response_obj[kCallbackId] = args.get(kCallbackId);
1330     const std::string& server_name = args.get(kServerName).get<std::string>();
1331     const unsigned long long position =
1332         static_cast<unsigned long long>(args.get(kPosition).get<double>());
1333
1334     PlatformResult result = client_->SendPlaybackPosition(server_name, position);
1335
1336     if (result) {
1337       ReportSuccess(response_obj);
1338     } else {
1339       LogAndReportError(result, &response_obj, ("Failed: client_->SendPlaybackPosition"));
1340     }
1341
1342     Instance::PostMessage(this, response.serialize().c_str());
1343   };
1344
1345   TaskQueue::GetInstance().Async(send);
1346
1347   ReportSuccess(out);
1348 }
1349
1350 void MediaControllerInstance::MediaControllerServerInfoSendShuffleMode(const picojson::value& args,
1351                                                                        picojson::object& out) {
1352   ScopeLogger();
1353
1354   if (!client_) {
1355     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1356                       (MediaControllerClientUnknownErrorMsg));
1357     return;
1358   }
1359
1360   CHECK_ARGS(args, kCallbackId, double, out)
1361   CHECK_ARGS(args, kServerName, std::string, out)
1362   CHECK_ARGS(args, kMode, bool, out)
1363
1364   auto send = [this, args]() -> void {
1365     picojson::value response = picojson::value(picojson::object());
1366     picojson::object& response_obj = response.get<picojson::object>();
1367     response_obj[kCallbackId] = args.get(kCallbackId);
1368
1369     const std::string& server_name = args.get(kServerName).get<std::string>();
1370     const bool mode = args.get(kMode).get<bool>();
1371
1372     PlatformResult result = client_->SendShuffleMode(server_name, mode);
1373
1374     if (result) {
1375       ReportSuccess(response_obj);
1376     } else {
1377       LogAndReportError(result, &response_obj, ("Failed to send shuffle mode."));
1378     }
1379
1380     Instance::PostMessage(this, response.serialize().c_str());
1381   };
1382
1383   TaskQueue::GetInstance().Async(send);
1384
1385   ReportSuccess(out);
1386 }
1387
1388 void MediaControllerInstance::MediaControllerServerInfoSendRepeatMode(const picojson::value& args,
1389                                                                       picojson::object& out) {
1390   ScopeLogger();
1391   common::tools::PrintDeprecationWarningFor("sendRepeatMode()", "sendRepeatState()");
1392   if (!client_) {
1393     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1394                       (MediaControllerClientUnknownErrorMsg));
1395     return;
1396   }
1397
1398   CHECK_EXIST(args, kCallbackId, out)
1399   CHECK_EXIST(args, kName, out)
1400   CHECK_EXIST(args, kMode, out)
1401
1402   auto send = [this, args]() -> void {
1403     picojson::value response = picojson::value(picojson::object());
1404     picojson::object& response_obj = response.get<picojson::object>();
1405     response_obj[kCallbackId] = args.get(kCallbackId);
1406
1407     PlatformResult result =
1408         client_->SendRepeatMode(args.get(kName).get<std::string>(), args.get(kMode).get<bool>());
1409
1410     if (result) {
1411       ReportSuccess(response_obj);
1412     } else {
1413       LogAndReportError(result, &response_obj, ("Failed to send repeat mode."));
1414     }
1415
1416     Instance::PostMessage(this, response.serialize().c_str());
1417   };
1418
1419   TaskQueue::GetInstance().Async(send);
1420
1421   ReportSuccess(out);
1422 }
1423
1424 void MediaControllerInstance::MediaControllerServerInfoSendRepeatState(const picojson::value& args,
1425                                                                        picojson::object& out) {
1426   ScopeLogger();
1427
1428   auto send = [this, args]() {
1429     picojson::value response = picojson::value(picojson::object());
1430     picojson::object& response_obj = response.get<picojson::object>();
1431     response_obj[kCallbackId] = args.get(kCallbackId);
1432
1433     const std::string& server_name = args.get(kServerName).get<std::string>();
1434     const std::string& state = args.get(kState).get<std::string>();
1435
1436     PlatformResult result = client_->SendRepeatState(server_name, state);
1437
1438     if (result) {
1439       ReportSuccess(response_obj);
1440     } else {
1441       LogAndReportError(result, &response_obj, ("Failed to send repeat state."));
1442     }
1443
1444     Instance::PostMessage(this, response.serialize().c_str());
1445   };
1446
1447   TaskQueue::GetInstance().Async(send);
1448
1449   ReportSuccess(out);
1450 }
1451
1452 void MediaControllerInstance::MediaControllerServerInfoSendSearchRequest(
1453     const picojson::value& args, picojson::object& out) {
1454   ScopeLogger();
1455
1456   if (!client_) {
1457     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Client not initialized."), &out,
1458                       (MediaControllerClientUnknownErrorMsg));
1459     return;
1460   }
1461
1462   CHECK_EXIST(args, kListenerId, out);
1463   CHECK_EXIST(args, kName, out);
1464   CHECK_EXIST(args, kRequest, out);
1465
1466   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
1467     picojson::object& reply_obj = reply->get<picojson::object>();
1468     reply_obj[kListenerId] = args.get(kListenerId);
1469     Instance::PostMessage(this, reply->serialize().c_str());
1470   };
1471
1472   char* request_id = nullptr;
1473   SCOPE_EXIT {
1474     free(request_id);
1475   };
1476
1477   PlatformResult result = client_->SendSearchRequest(args.get(kName).get<std::string>(),
1478                                                      args.get(kRequest), reply_cb, &request_id);
1479
1480   if (result) {
1481     ReportSuccess(out);
1482     out[kRequestId] = picojson::value(std::string(request_id));
1483   } else {
1484     LogAndReportError(result, &out, ("Failed to send command."));
1485   }
1486 }
1487
1488 void MediaControllerInstance::MediaControllerServerInfoSendCommand(const picojson::value& args,
1489                                                                    picojson::object& out) {
1490   ScopeLogger();
1491   if (!client_) {
1492     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1493                       (MediaControllerClientUnknownErrorMsg));
1494     return;
1495   }
1496
1497   CHECK_EXIST(args, kListenerId, out)
1498   CHECK_EXIST(args, kName, out)
1499   CHECK_EXIST(args, kCommand, out)
1500   CHECK_EXIST(args, kData, out)
1501
1502   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
1503     picojson::object& reply_obj = reply->get<picojson::object>();
1504     reply_obj[kListenerId] = args.get(kListenerId);
1505     Instance::PostMessage(this, reply->serialize().c_str());
1506   };
1507
1508   char* request_id = nullptr;
1509   SCOPE_EXIT {
1510     free(request_id);
1511   };
1512
1513   PlatformResult result = client_->SendCommand(args.get(kName).get<std::string>(),
1514                                                args.get(kCommand).get<std::string>(),
1515                                                args.get(kData), reply_cb, &request_id);
1516
1517   if (result) {
1518     ReportSuccess(out);
1519     out[kRequestId] = picojson::value(std::string(request_id));
1520   } else {
1521     LogAndReportError(result, &out, ("Failed to send command."));
1522   }
1523 }
1524
1525 void MediaControllerInstance::MediaControllerServerInfoAddServerStatusChangeListener(
1526     const picojson::value& args, picojson::object& out) {
1527   ScopeLogger();
1528   if (!client_) {
1529     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1530                       (MediaControllerClientUnknownErrorMsg));
1531     return;
1532   }
1533
1534   CHECK_EXIST(args, kListenerId, out)
1535
1536   JsonCallback callback = [this, args](picojson::value* data) -> void {
1537     if (nullptr == data) {
1538       LoggerE("No data passed to json callback");
1539       return;
1540     }
1541
1542     picojson::object& request_o = data->get<picojson::object>();
1543     request_o[kListenerId] = args.get(kListenerId);
1544
1545     Instance::PostMessage(this, data->serialize().c_str());
1546   };
1547
1548   auto result = client_->SetServerStatusChangeListener(callback);
1549   if (!result) {
1550     LogAndReportError(result, &out);
1551   }
1552
1553   ReportSuccess(out);
1554 }
1555
1556 void MediaControllerInstance::MediaControllerServerInfoRemoveServerStatusChangeListener(
1557     const picojson::value& args, picojson::object& out) {
1558   ScopeLogger();
1559   if (!client_) {
1560     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1561                       (MediaControllerClientUnknownErrorMsg));
1562     return;
1563   }
1564
1565   auto result = client_->UnsetServerStatusChangeListener();
1566   if (!result) {
1567     LogAndReportError(result, &out);
1568   }
1569 }
1570
1571 void MediaControllerInstance::MediaControllerServerInfoAddPlaybackInfoChangeListener(
1572     const picojson::value& args, picojson::object& out) {
1573   ScopeLogger();
1574   if (!client_) {
1575     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1576                       (MediaControllerClientUnknownErrorMsg));
1577     return;
1578   }
1579
1580   CHECK_EXIST(args, kListenerId, out)
1581
1582   JsonCallback callback = [this, args](picojson::value* data) -> void {
1583     if (!data) {
1584       LoggerE("No data passed to json callback");
1585       return;
1586     }
1587
1588     picojson::object& request_o = data->get<picojson::object>();
1589     request_o[kListenerId] = args.get(kListenerId);
1590
1591     Instance::PostMessage(this, data->serialize().c_str());
1592   };
1593
1594   auto result = client_->SetPlaybackInfoListener(callback);
1595   if (!result) {
1596     LogAndReportError(result, &out);
1597     return;
1598   }
1599
1600   ReportSuccess(out);
1601 }
1602
1603 void MediaControllerInstance::MediaControllerServerInfoRemovePlaybackInfoChangeListener(
1604     const picojson::value& args, picojson::object& out) {
1605   if (!client_) {
1606     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1607                       (MediaControllerClientUnknownErrorMsg));
1608     return;
1609   }
1610
1611   auto result = client_->UnsetPlaybackInfoListener();
1612   if (!result) {
1613     LogAndReportError(result, &out);
1614   }
1615 }
1616
1617 void MediaControllerInstance::MediaControllerServerInfoSendPlaybackItem(const picojson::value& args,
1618                                                                         picojson::object& out) {
1619   ScopeLogger();
1620
1621   if (!client_) {
1622     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Client not initialized."), &out,
1623                       (MediaControllerClientUnknownErrorMsg));
1624     return;
1625   }
1626
1627   CHECK_ARGS(args, kServerName, std::string, out)
1628   CHECK_ARGS(args, kPlaylistName, std::string, out)
1629   CHECK_ARGS(args, kIndex, std::string, out)
1630   CHECK_ARGS(args, kState, std::string, out)
1631   CHECK_ARGS(args, kPosition, double, out)
1632
1633   const std::string& server_name = args.get(kServerName).get<std::string>();
1634   const std::string& playlist_name = args.get(kPlaylistName).get<std::string>();
1635   const std::string& index = args.get(kIndex).get<std::string>();
1636   const std::string& state = args.get(kState).get<std::string>();
1637   const int position = static_cast<unsigned long long>(args.get(kPosition).get<double>());
1638
1639   auto result = client_->SendPlaybackItem(server_name, playlist_name, index, state, position);
1640   if (!result) {
1641     LogAndReportError(result, &out);
1642     return;
1643   }
1644
1645   ReportSuccess(out);
1646 }
1647
1648 void MediaControllerInstance::MediaControllerServerInfoAddPlaylistUpdatedListener(
1649     const picojson::value& args, picojson::object& out) {
1650   ScopeLogger();
1651   if (!client_) {
1652     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1653                       (MediaControllerClientUnknownErrorMsg));
1654     return;
1655   }
1656
1657   CHECK_EXIST(args, kListenerId, out)
1658
1659   JsonCallback callback = [this, args](picojson::value* data) -> void {
1660     if (!data) {
1661       LoggerE("No data passed to json callback");
1662       return;
1663     }
1664
1665     picojson::object& request_o = data->get<picojson::object>();
1666     request_o[kListenerId] = args.get(kListenerId);
1667
1668     Instance::PostMessage(this, data->serialize().c_str());
1669   };
1670
1671   auto result = client_->SetPlaylistUpdateListener(callback);
1672   if (!result) {
1673     LogAndReportError(result, &out);
1674     return;
1675   }
1676
1677   ReportSuccess(out);
1678 }
1679
1680 void MediaControllerInstance::MediaControllerServerInfoRemovePlaylistUpdatedListener(
1681     const picojson::value& args, picojson::object& out) {
1682   if (!client_) {
1683     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1684                       (MediaControllerClientUnknownErrorMsg));
1685     return;
1686   }
1687
1688   auto result = client_->UnsetPlaylistUpdateListener();
1689   if (!result) {
1690     LogAndReportError(result, &out);
1691     return;
1692   }
1693
1694   ReportSuccess(out);
1695 }
1696
1697 void MediaControllerInstance::MediaControllerServerInfoGetAllPlaylists(const picojson::value& args,
1698                                                                        picojson::object& out) {
1699   ScopeLogger();
1700
1701   CHECK_ARGS(args, kServerName, std::string, out)
1702
1703   auto get = [this, args]() -> void {
1704     picojson::value response = picojson::value(picojson::object());
1705     picojson::object& response_obj = response.get<picojson::object>();
1706
1707     response_obj[kCallbackId] = args.get(kCallbackId);
1708
1709     std::map<std::string, mc_playlist_h> new_playlists_map;
1710     std::string serverName = args.get(kServerName).get<std::string>();
1711     auto result = utils::GetAllPlaylistsHandles(serverName, &new_playlists_map);
1712     if (!result) {
1713       LogAndReportError(result, &response_obj, ("Failed: utils::GetAllPlaylists"));
1714       Instance::PostMessage(this, response.serialize().c_str());
1715       return;
1716     }
1717     // update the list of stored handles
1718     {
1719       std::lock_guard<std::mutex> lock(playlist_map_mutex_);
1720       utils::UpdatePlaylistHandleMap(serverName, new_playlists_map, server_playlist_map_);
1721       picojson::value playlists = utils::CreatePlaylistsJSON(serverName, new_playlists_map);
1722
1723       response_obj[kResult] = picojson::value{playlists};
1724     }
1725     ReportSuccess(response_obj);
1726     Instance::PostMessage(this, response.serialize().c_str());
1727   };
1728
1729   TaskQueue::GetInstance().Async(get);
1730
1731   ReportSuccess(out);
1732 }
1733
1734 void MediaControllerInstance::MediaControllerPlaylistsInfoGetPlaylist(const picojson::value& args,
1735                                                                       picojson::object& out) {
1736   ScopeLogger();
1737
1738   CHECK_ARGS(args, kServerName, std::string, out);
1739   CHECK_ARGS(args, kPlaylistName, std::string, out);
1740
1741   const std::string& server_name = args.get(kServerName).get<std::string>();
1742   const std::string& playlist_name = args.get(kPlaylistName).get<std::string>();
1743   picojson::value playlist_info = picojson::value(picojson::object());
1744   picojson::object& playlist_obj = playlist_info.get<picojson::object>();
1745
1746   PlatformResult result = utils::GetPlaylist(server_name, playlist_name, &playlist_obj);
1747   if (!result) {
1748     LogAndReportError(result, &out, ("Failed: utils::GetPlaylist"));
1749     return;
1750   }
1751
1752   ReportSuccess(playlist_info, out);
1753 }
1754
1755 void MediaControllerInstance::MediaControllerServerInfoGetIconURI(const picojson::value& args,
1756                                                                   picojson::object& out) {
1757   ScopeLogger();
1758   CHECK_ARGS(args, kName, std::string, out);
1759
1760   if (!client_) {
1761     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1762                       (MediaControllerClientUnknownErrorMsg));
1763     return;
1764   }
1765
1766   std::string server_name = args.get(kName).get<std::string>();
1767
1768   common::optional<std::string> icon_uri;
1769   PlatformResult status = client_->GetServerIconURI(server_name, &icon_uri);
1770   if (!status) {
1771     LogAndReportError(status, &out, ("Failed: client_->GetServerIconURI()"));
1772     return;
1773   }
1774
1775   picojson::object result;
1776   if (icon_uri) {
1777     result[kIconURI] = picojson::value(*icon_uri);
1778   } else {
1779     result[kIconURI] = picojson::value();
1780   }
1781
1782   ReportSuccess(picojson::value(result), out);
1783 }
1784
1785 void MediaControllerInstance::MediaControllerServerInfoPlaybackInfoSendPlaybackAction(
1786     const picojson::value& args, picojson::object& out) {
1787   ScopeLogger();
1788   if (!client_) {
1789     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1790                       (MediaControllerClientUnknownErrorMsg));
1791     return;
1792   }
1793
1794   CHECK_ARGS(args, kServerName, std::string, out)
1795   CHECK_ARGS(args, kAttribute, std::string, out)
1796   CHECK_ARGS(args, kListenerId, std::string, out)
1797
1798   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
1799     if (reply) {
1800       picojson::object& reply_obj = reply->get<picojson::object>();
1801       reply_obj[kListenerId] = args.get(kListenerId);
1802       Instance::PostMessage(this, reply->serialize().c_str());
1803     } else {
1804       LoggerW("No reply passed to json callback, ignoring");
1805     }
1806   };
1807
1808   char* request_id = nullptr;
1809   SCOPE_EXIT {
1810     free(request_id);
1811   };
1812
1813   const std::string& server_name = args.get(kServerName).get<std::string>();
1814   const std::string& action = args.get(kAttribute).get<std::string>();
1815
1816   PlatformResult result = client_->SendPlaybackAction(server_name, action, reply_cb, &request_id);
1817
1818   if (result) {
1819     ReportSuccess(out);
1820     out[kRequestId] = picojson::value(std::string(request_id));
1821   } else {
1822     LogAndReportError(result, &out, ("Failed to send playback action."));
1823   }
1824 }
1825
1826 void MediaControllerInstance::MediaControllerServerInfoPlaybackInfoSendPlaybackPosition(
1827     const picojson::value& args, picojson::object& out) {
1828   ScopeLogger();
1829   if (!client_) {
1830     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1831                       (MediaControllerClientUnknownErrorMsg));
1832     return;
1833   }
1834
1835   CHECK_ARGS(args, kServerName, std::string, out)
1836   CHECK_ARGS(args, kAttribute, double, out)
1837   CHECK_ARGS(args, kListenerId, std::string, out)
1838
1839   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
1840     if (reply) {
1841       picojson::object& reply_obj = reply->get<picojson::object>();
1842       reply_obj[kListenerId] = args.get(kListenerId);
1843       Instance::PostMessage(this, reply->serialize().c_str());
1844     } else {
1845       LoggerW("No reply passed to json callback, ignoring");
1846     }
1847   };
1848
1849   char* request_id = nullptr;
1850   SCOPE_EXIT {
1851     free(request_id);
1852   };
1853
1854   const std::string& server_name = args.get(kServerName).get<std::string>();
1855   const unsigned long long position =
1856       static_cast<unsigned long long>(args.get(kAttribute).get<double>());
1857
1858   PlatformResult result =
1859       client_->SendPlaybackPosition(server_name, position, reply_cb, &request_id);
1860
1861   if (result) {
1862     ReportSuccess(out);
1863     out[kRequestId] = picojson::value(std::string(request_id));
1864   } else {
1865     LogAndReportError(result, &out, ("Failed to send playback position."));
1866   }
1867 }
1868
1869 void MediaControllerInstance::MediaControllerServerInfoPlaybackInfoSendShuffleMode(
1870     const picojson::value& args, picojson::object& out) {
1871   ScopeLogger();
1872   if (!client_) {
1873     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1874                       (MediaControllerClientUnknownErrorMsg));
1875     return;
1876   }
1877
1878   CHECK_ARGS(args, kServerName, std::string, out)
1879   CHECK_ARGS(args, kAttribute, bool, out)
1880   CHECK_ARGS(args, kListenerId, std::string, out)
1881
1882   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
1883     if (reply) {
1884       picojson::object& reply_obj = reply->get<picojson::object>();
1885       reply_obj[kListenerId] = args.get(kListenerId);
1886       Instance::PostMessage(this, reply->serialize().c_str());
1887     } else {
1888       LoggerW("No reply passed to json callback, ignoring");
1889     }
1890   };
1891
1892   char* request_id = nullptr;
1893   SCOPE_EXIT {
1894     free(request_id);
1895   };
1896
1897   const std::string& server_name = args.get(kServerName).get<std::string>();
1898   const bool mode = args.get(kAttribute).get<bool>();
1899
1900   PlatformResult result = client_->SendShuffleMode(server_name, mode, reply_cb, &request_id);
1901
1902   if (result) {
1903     ReportSuccess(out);
1904     out[kRequestId] = picojson::value(std::string(request_id));
1905   } else {
1906     LogAndReportError(result, &out, ("Failed to send playback position."));
1907   }
1908 }
1909
1910 void MediaControllerInstance::MediaControllerServerInfoPlaybackInfoSendRepeatState(
1911     const picojson::value& args, picojson::object& out) {
1912   ScopeLogger();
1913   if (!client_) {
1914     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1915                       (MediaControllerClientUnknownErrorMsg));
1916     return;
1917   }
1918
1919   CHECK_ARGS(args, kServerName, std::string, out)
1920   CHECK_ARGS(args, kAttribute, std::string, out)
1921   CHECK_ARGS(args, kListenerId, std::string, out)
1922
1923   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
1924     if (reply) {
1925       picojson::object& reply_obj = reply->get<picojson::object>();
1926       reply_obj[kListenerId] = args.get(kListenerId);
1927       Instance::PostMessage(this, reply->serialize().c_str());
1928     } else {
1929       LoggerW("No reply passed to json callback, ignoring");
1930     }
1931   };
1932
1933   char* request_id = nullptr;
1934   SCOPE_EXIT {
1935     free(request_id);
1936   };
1937
1938   const std::string& server_name = args.get(kServerName).get<std::string>();
1939   const std::string& state = args.get(kAttribute).get<std::string>();
1940
1941   PlatformResult result = client_->SendRepeatState(server_name, state, reply_cb, &request_id);
1942
1943   if (result) {
1944     ReportSuccess(out);
1945     out[kRequestId] = picojson::value(std::string(request_id));
1946   } else {
1947     LogAndReportError(result, &out, ("Failed to send playback position."));
1948   }
1949 }
1950
1951 void MediaControllerInstance::MediaControllerClientAddAbilityChangeListener(
1952     const picojson::value& args, picojson::object& out) {
1953   ScopeLogger();
1954
1955   if (!client_) {
1956     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1957                       (MediaControllerClientUnknownErrorMsg));
1958     return;
1959   }
1960
1961   CHECK_EXIST(args, kListenerId, out)
1962
1963   picojson::value listener_id = args.get(kListenerId);
1964
1965   JsonCallback callback = [this, listener_id](picojson::value* data) -> void {
1966     if (!data) {
1967       LoggerE("No data passed to json callback");
1968       return;
1969     }
1970
1971     picojson::object& request_o = data->get<picojson::object>();
1972     request_o[kListenerId] = listener_id;
1973
1974     Instance::PostMessage(this, data->serialize().c_str());
1975   };
1976
1977   auto result = client_->SetAbilityChangeListener(callback);
1978   if (!result) {
1979     LogAndReportError(result, &out);
1980     return;
1981   }
1982
1983   ReportSuccess(out);
1984 }
1985
1986 void MediaControllerInstance::MediaControllerClientRemoveAbilityChangeListener(
1987     const picojson::value& args, picojson::object& out) {
1988   ScopeLogger();
1989
1990   if (!client_) {
1991     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
1992                       (MediaControllerClientUnknownErrorMsg));
1993     return;
1994   }
1995
1996   auto result = client_->UnsetAbilityChangeListener();
1997   if (!result) {
1998     LogAndReportError(result, &out);
1999     return;
2000   }
2001
2002   ReportSuccess(out);
2003 }
2004
2005 void MediaControllerInstance::MediaControllerAbilitiesInfoSubscribe(const picojson::value& args,
2006                                                                     picojson::object& out) {
2007   ScopeLogger();
2008
2009   if (!client_) {
2010     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2011                       (MediaControllerClientUnknownErrorMsg));
2012     return;
2013   }
2014
2015   CHECK_ARGS(args, kServerName, std::string, out)
2016
2017   const std::string& server_name = args.get(kServerName).get<std::string>();
2018   auto result = client_->SubscribeServer(server_name);
2019   if (!result) {
2020     LogAndReportError(result, &out);
2021     return;
2022   }
2023
2024   ReportSuccess(out);
2025 }
2026
2027 void MediaControllerInstance::MediaControllerAbilitiesInfoUnsubscribe(const picojson::value& args,
2028                                                                       picojson::object& out) {
2029   ScopeLogger();
2030
2031   if (!client_) {
2032     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2033                       (MediaControllerClientUnknownErrorMsg));
2034     return;
2035   }
2036
2037   CHECK_ARGS(args, kServerName, std::string, out)
2038
2039   const std::string& server_name = args.get(kServerName).get<std::string>();
2040   auto result = client_->UnsubscribeServer(server_name);
2041   if (!result) {
2042     LogAndReportError(result, &out);
2043     return;
2044   }
2045
2046   ReportSuccess(out);
2047 }
2048
2049 void MediaControllerInstance::MediaControllerPlaylistAddItem(const picojson::value& args,
2050                                                              picojson::object& out) {
2051   ScopeLogger();
2052
2053   // MediaControllerPlaylistAddItem is implemented in MediaControllerServer because
2054   // mc_server_add_item_to_playlist need mc_server_h as parameter
2055   if (!server_) {
2056     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Server not initialized."), &out,
2057                       (MediaControllerServerUnknownErrorMsg));
2058     return;
2059   }
2060
2061   CHECK_ARGS(args, kIndex, std::string, out)
2062   CHECK_ARGS(args, kMetadata, picojson::object, out)
2063   CHECK_ARGS(args, kName, std::string, out)
2064
2065   const picojson::object& metadata = args.get(kMetadata).get<picojson::object>();
2066
2067   auto name = args.get(kName).get<std::string>();
2068
2069   std::string serverName = "";
2070   if (args.contains(kServerName)) {
2071     serverName = args.get(kServerName).get<std::string>();
2072   } else {
2073     serverName = common::CurrentApplication::GetInstance().GetApplicationId();
2074   }
2075
2076   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
2077   std::lock_guard<std::mutex> lock(playlist_map_mutex_);
2078
2079   if (server_playlist_map_.find(serverName) == server_playlist_map_.end() ||
2080       server_playlist_map_[serverName].find(name) == server_playlist_map_[serverName].end()) {
2081     result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Playlist with given name doesn't exist");
2082     LogAndReportError(result, &out);
2083     return;
2084   }
2085
2086   result = server_->MediaControllerPlaylistAddItem(server_playlist_map_[serverName][name],
2087                                                    args.get(kIndex).get<std::string>(), metadata);
2088   if (!result) {
2089     LogAndReportError(result, &out);
2090     return;
2091   }
2092
2093   ReportSuccess(out);
2094 }
2095
2096 void MediaControllerInstance::MediaControllerPlaylistGetItems(const picojson::value& args,
2097                                                               picojson::object& out) {
2098   ScopeLogger();
2099
2100   CHECK_EXIST(args, kCallbackId, out)
2101   CHECK_ARGS(args, kName, std::string, out)
2102   CHECK_ARGS(args, kServerName, std::string, out)
2103
2104   auto get = [this, args]() -> void {
2105     picojson::value response = picojson::value(picojson::object());
2106     picojson::object& response_obj = response.get<picojson::object>();
2107
2108     response_obj[kCallbackId] = args.get(kCallbackId);
2109
2110     picojson::value items{picojson::array{}};
2111
2112     auto name = args.get(kName).get<std::string>();
2113     auto serverName = args.get(kServerName).get<std::string>();
2114
2115     PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
2116     {
2117       std::lock_guard<std::mutex> lock(playlist_map_mutex_);
2118
2119       if (server_playlist_map_.find(serverName) == server_playlist_map_.end() ||
2120           server_playlist_map_[serverName].find(name) == server_playlist_map_[serverName].end()) {
2121         result =
2122             LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Playlist with given name doesn't exist");
2123         LogAndReportError(result, &response_obj,
2124                           ("Failed: MediaControllerInstance::MediaControllerPlaylistGetItems"));
2125         Instance::PostMessage(this, response.serialize().c_str());
2126         return;
2127       }
2128
2129       result = utils::MediaControllerPlaylistGetItems(server_playlist_map_[serverName][name],
2130                                                       &items.get<picojson::array>());
2131     }
2132     if (!result) {
2133       LogAndReportError(result, &response_obj, ("Failed: utils::MediaControllerPlaylistGetItems"));
2134       Instance::PostMessage(this, response.serialize().c_str());
2135       return;
2136     }
2137
2138     response_obj[kResult] = picojson::value{items};
2139     ReportSuccess(response_obj);
2140     Instance::PostMessage(this, response.serialize().c_str());
2141   };
2142
2143   TaskQueue::GetInstance().Async(get);
2144
2145   ReportSuccess(out);
2146 }
2147
2148 void MediaControllerInstance::MediaControllerPlaylistsGetPlaylist(const picojson::value& args,
2149                                                                   picojson::object& out) {
2150   ScopeLogger();
2151   if (!server_) {
2152     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2153                       (MediaControllerServerUnknownErrorMsg));
2154     return;
2155   }
2156   CHECK_ARGS(args, kPlaylistName, std::string, out);
2157
2158   const std::string& playlist_name = args.get(kPlaylistName).get<std::string>();
2159   const std::string& app_id = common::CurrentApplication::GetInstance().GetApplicationId();
2160   picojson::value playlist_info = picojson::value(picojson::object());
2161   picojson::object& playlist_obj = playlist_info.get<picojson::object>();
2162
2163   std::lock_guard<std::mutex> lock(playlist_map_mutex_);
2164   mc_playlist_h handle = nullptr;
2165   if (server_playlist_map_.find(app_id) != server_playlist_map_.end() &&
2166       server_playlist_map_[app_id].find(playlist_name) != server_playlist_map_[app_id].end()) {
2167     LoggerD("Using saved handle");
2168     handle = server_playlist_map_[app_id][playlist_name];
2169   }
2170
2171   auto result = utils::GetPlaylist(app_id, playlist_name, &playlist_obj, &handle);
2172   if (!result) {
2173     LogAndReportError(result, &out, ("Failed: utils::GetPlaylist"));
2174     return;
2175   }
2176
2177   // update the list of stored handles
2178   server_playlist_map_[app_id][playlist_name] = handle;
2179
2180   ReportSuccess(playlist_info, out);
2181 }
2182
2183 // subtitles
2184 void MediaControllerInstance::MediaControllerSubtitlesUpdateEnabled(const picojson::value& args,
2185                                                                     picojson::object& out) {
2186   ScopeLogger();
2187
2188   if (!server_) {
2189     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2190                       (MediaControllerServerUnknownErrorMsg));
2191     return;
2192   }
2193
2194   CHECK_ARGS(args, kEnabled, bool, out);
2195
2196   const bool enabled = args.get(kEnabled).get<bool>();
2197   PlatformResult result = server_->UpdateSubtitlesEnabled(enabled);
2198   if (!result) {
2199     LogAndReportError(result, &out, ("Failed server_->UpdateSubtitlesEnabled()"));
2200     return;
2201   }
2202   ReportSuccess(out);
2203 }
2204
2205 void MediaControllerInstance::MediaControllerSubtitlesAddChangeRequestListener(
2206     const picojson::value& args, picojson::object& out) {
2207   ScopeLogger();
2208   if (!server_) {
2209     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2210                       (MediaControllerServerUnknownErrorMsg));
2211     return;
2212   }
2213
2214   CHECK_ARGS(args, kListenerId, std::string, out)
2215
2216   JsonCallback callback = [this, args](picojson::value* data) -> void {
2217     if (!data) {
2218       LoggerE("No data passed to json callback");
2219       return;
2220     }
2221     picojson::object& request_o = data->get<picojson::object>();
2222     request_o[kListenerId] = args.get(kListenerId);
2223
2224     Instance::PostMessage(this, data->serialize().c_str());
2225   };
2226
2227   auto result = server_->SetSubtitlesChangeRequestListener(callback);
2228   if (!result) {
2229     LogAndReportError(result, &out);
2230     return;
2231   }
2232
2233   ReportSuccess(out);
2234 }
2235
2236 void MediaControllerInstance::MediaControllerSubtitlesRemoveChangeRequestListener(
2237     const picojson::value& args, picojson::object& out) {
2238   ScopeLogger();
2239   if (!server_) {
2240     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2241                       (MediaControllerServerUnknownErrorMsg));
2242     return;
2243   }
2244
2245   auto result = server_->UnsetSubtitlesChangeRequestListener();
2246   if (!result) {
2247     LogAndReportError(result, &out);
2248     return;
2249   }
2250   ReportSuccess(out);
2251 }
2252
2253 void MediaControllerInstance::MediaControllerSubtitlesInfoGetEnabled(const picojson::value& args,
2254                                                                      picojson::object& out) {
2255   ScopeLogger();
2256   if (!client_) {
2257     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2258                       (MediaControllerClientUnknownErrorMsg));
2259     return;
2260   }
2261
2262   CHECK_ARGS(args, kName, std::string, out)
2263
2264   bool enabled = false;
2265   PlatformResult result =
2266       client_->GetSubtitlesEnabled(args.get(kName).get<std::string>(), &enabled);
2267
2268   if (!result) {
2269     LogAndReportError(result, &out, ("Failed: client_->GetSubtitlesEnabled"));
2270     return;
2271   }
2272
2273   ReportSuccess(picojson::value(enabled), out);
2274 }
2275
2276 void MediaControllerInstance::MediaControllerSubtitlesInfoSendRequest(const picojson::value& args,
2277                                                                       picojson::object& out) {
2278   ScopeLogger();
2279   if (!client_) {
2280     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2281                       (MediaControllerClientUnknownErrorMsg));
2282     return;
2283   }
2284
2285   CHECK_ARGS(args, kListenerId, std::string, out)
2286   CHECK_ARGS(args, kName, std::string, out)
2287   CHECK_ARGS(args, kEnabled, bool, out)
2288
2289   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
2290     if (reply) {
2291       picojson::object& reply_obj = reply->get<picojson::object>();
2292       reply_obj[kListenerId] = args.get(kListenerId);
2293       Instance::PostMessage(this, reply->serialize().c_str());
2294     } else {
2295       LoggerW("No reply passed to json callback, ignoring");
2296     }
2297   };
2298
2299   char* request_id = nullptr;
2300   SCOPE_EXIT {
2301     free(request_id);
2302   };
2303
2304   PlatformResult result = client_->SendSubtitlesEnabled(
2305       args.get(kName).get<std::string>(), args.get(kEnabled).get<bool>(), reply_cb, &request_id);
2306
2307   if (result) {
2308     ReportSuccess(out);
2309     out[kRequestId] = picojson::value(std::string(request_id));
2310   } else {
2311     LogAndReportError(result, &out, ("Failed to send command."));
2312   }
2313 }
2314
2315 void MediaControllerInstance::MediaControllerSubtitlesInfoAddModeChangeListener(
2316     const picojson::value& args, picojson::object& out) {
2317   ScopeLogger();
2318   if (!client_) {
2319     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2320                       (MediaControllerClientUnknownErrorMsg));
2321     return;
2322   }
2323
2324   CHECK_ARGS(args, kListenerId, std::string, out)
2325
2326   JsonCallback callback = [this, args](picojson::value* data) -> void {
2327     if (nullptr == data) {
2328       LoggerE("No data passed to json callback");
2329       return;
2330     }
2331
2332     picojson::object& request_o = data->get<picojson::object>();
2333     request_o[kListenerId] = args.get(kListenerId);
2334
2335     Instance::PostMessage(this, data->serialize().c_str());
2336   };
2337
2338   auto result = client_->SetSubtitlesInfoChangeListener(callback);
2339   if (!result) {
2340     LogAndReportError(result, &out);
2341     return;
2342   }
2343
2344   ReportSuccess(out);
2345 }
2346
2347 void MediaControllerInstance::MediaControllerSubtitlesInfoRemoveModeChangeListener(
2348     const picojson::value& args, picojson::object& out) {
2349   ScopeLogger();
2350   if (!client_) {
2351     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2352                       (MediaControllerClientUnknownErrorMsg));
2353     return;
2354   }
2355
2356   auto result = client_->UnsetSubtitlesInfoChangeListener();
2357   if (!result) {
2358     LogAndReportError(result, &out);
2359     return;
2360   }
2361
2362   ReportSuccess(out);
2363 }
2364
2365 // mode360
2366 void MediaControllerInstance::MediaControllerMode360UpdateEnabled(const picojson::value& args,
2367                                                                   picojson::object& out) {
2368   ScopeLogger();
2369
2370   if (!server_) {
2371     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2372                       (MediaControllerServerUnknownErrorMsg));
2373     return;
2374   }
2375
2376   CHECK_ARGS(args, kEnabled, bool, out)
2377
2378   const bool enabled = args.get(kEnabled).get<bool>();
2379   PlatformResult result = server_->UpdateMode360Enabled(enabled);
2380   if (!result) {
2381     LogAndReportError(result, &out, ("Failed server_->UpdateMode360Enabled()"));
2382     return;
2383   }
2384   ReportSuccess(out);
2385 }
2386
2387 void MediaControllerInstance::MediaControllerMode360AddChangeRequestListener(
2388     const picojson::value& args, picojson::object& out) {
2389   ScopeLogger();
2390   if (!server_) {
2391     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2392                       (MediaControllerServerUnknownErrorMsg));
2393     return;
2394   }
2395
2396   CHECK_ARGS(args, kListenerId, std::string, out)
2397
2398   JsonCallback callback = [this, args](picojson::value* data) -> void {
2399     if (!data) {
2400       LoggerE("No data passed to json callback");
2401       return;
2402     }
2403     picojson::object& request_o = data->get<picojson::object>();
2404     request_o[kListenerId] = args.get(kListenerId);
2405
2406     Instance::PostMessage(this, data->serialize().c_str());
2407   };
2408
2409   auto result = server_->SetMode360ChangeRequestListener(callback);
2410   if (!result) {
2411     LogAndReportError(result, &out);
2412     return;
2413   }
2414
2415   ReportSuccess(out);
2416 }
2417
2418 void MediaControllerInstance::MediaControllerMode360RemoveChangeRequestListener(
2419     const picojson::value& args, picojson::object& out) {
2420   ScopeLogger();
2421   if (!server_) {
2422     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2423                       (MediaControllerServerUnknownErrorMsg));
2424     return;
2425   }
2426
2427   auto result = server_->UnsetMode360ChangeRequestListener();
2428   if (!result) {
2429     LogAndReportError(result, &out);
2430     return;
2431   }
2432   ReportSuccess(out);
2433 }
2434
2435 void MediaControllerInstance::MediaControllerMode360InfoGetEnabled(const picojson::value& args,
2436                                                                    picojson::object& out) {
2437   ScopeLogger();
2438   if (!client_) {
2439     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2440                       (MediaControllerClientUnknownErrorMsg));
2441     return;
2442   }
2443
2444   CHECK_ARGS(args, kName, std::string, out)
2445
2446   bool enabled = false;
2447   PlatformResult result = client_->GetMode360Enabled(args.get(kName).get<std::string>(), &enabled);
2448
2449   if (!result) {
2450     LogAndReportError(result, &out, ("Failed: client_->GetMode360Enabled"));
2451     return;
2452   }
2453
2454   ReportSuccess(picojson::value(enabled), out);
2455 }
2456
2457 void MediaControllerInstance::MediaControllerMode360InfoSendRequest(const picojson::value& args,
2458                                                                     picojson::object& out) {
2459   ScopeLogger();
2460   if (!client_) {
2461     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2462                       (MediaControllerClientUnknownErrorMsg));
2463     return;
2464   }
2465
2466   CHECK_ARGS(args, kListenerId, std::string, out)
2467   CHECK_ARGS(args, kName, std::string, out)
2468   CHECK_ARGS(args, kEnabled, bool, out)
2469
2470   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
2471     if (reply) {
2472       picojson::object& reply_obj = reply->get<picojson::object>();
2473       reply_obj[kListenerId] = args.get(kListenerId);
2474       Instance::PostMessage(this, reply->serialize().c_str());
2475     } else {
2476       LoggerW("No reply passed to json callback, ignoring");
2477     }
2478   };
2479
2480   char* request_id = nullptr;
2481   SCOPE_EXIT {
2482     free(request_id);
2483   };
2484
2485   PlatformResult result = client_->SendMode360Enabled(
2486       args.get(kName).get<std::string>(), args.get(kEnabled).get<bool>(), reply_cb, &request_id);
2487
2488   if (result) {
2489     ReportSuccess(out);
2490     out[kRequestId] = picojson::value(std::string(request_id));
2491   } else {
2492     LogAndReportError(result, &out, ("Failed to send command."));
2493   }
2494 }
2495
2496 void MediaControllerInstance::MediaControllerMode360InfoAddModeChangeListener(
2497     const picojson::value& args, picojson::object& out) {
2498   ScopeLogger();
2499   if (!client_) {
2500     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2501                       (MediaControllerClientUnknownErrorMsg));
2502     return;
2503   }
2504
2505   CHECK_ARGS(args, kListenerId, std::string, out)
2506
2507   JsonCallback callback = [this, args](picojson::value* data) -> void {
2508     if (nullptr == data) {
2509       LoggerE("No data passed to json callback");
2510       return;
2511     }
2512
2513     picojson::object& request_o = data->get<picojson::object>();
2514     request_o[kListenerId] = args.get(kListenerId);
2515
2516     Instance::PostMessage(this, data->serialize().c_str());
2517   };
2518
2519   auto result = client_->SetMode360InfoChangeListener(callback);
2520   if (!result) {
2521     LogAndReportError(result, &out);
2522     return;
2523   }
2524
2525   ReportSuccess(out);
2526 }
2527
2528 void MediaControllerInstance::MediaControllerMode360InfoRemoveModeChangeListener(
2529     const picojson::value& args, picojson::object& out) {
2530   ScopeLogger();
2531   if (!client_) {
2532     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2533                       (MediaControllerClientUnknownErrorMsg));
2534     return;
2535   }
2536
2537   auto result = client_->UnsetMode360InfoChangeListener();
2538   if (!result) {
2539     LogAndReportError(result, &out);
2540     return;
2541   }
2542
2543   ReportSuccess(out);
2544 }
2545
2546 // displayMode
2547 void MediaControllerInstance::MediaControllerDisplayModeUpdateType(const picojson::value& args,
2548                                                                    picojson::object& out) {
2549   ScopeLogger();
2550
2551   if (!server_) {
2552     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2553                       (MediaControllerServerUnknownErrorMsg));
2554     return;
2555   }
2556
2557   CHECK_ARGS(args, kType, std::string, out);
2558
2559   const std::string type = args.get(kType).get<std::string>();
2560   PlatformResult result = server_->UpdateDisplayModeType(type);
2561   if (!result) {
2562     LogAndReportError(result, &out, ("Failed server_->UpdateDisplayModeType()"));
2563     return;
2564   }
2565   ReportSuccess(out);
2566 }
2567
2568 void MediaControllerInstance::MediaControllerDisplayModeAddChangeRequestListener(
2569     const picojson::value& args, picojson::object& out) {
2570   ScopeLogger();
2571   if (!server_) {
2572     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2573                       (MediaControllerServerUnknownErrorMsg));
2574     return;
2575   }
2576
2577   CHECK_ARGS(args, kListenerId, std::string, out)
2578
2579   JsonCallback callback = [this, args](picojson::value* data) -> void {
2580     if (!data) {
2581       LoggerE("No data passed to json callback");
2582       return;
2583     }
2584     picojson::object& request_o = data->get<picojson::object>();
2585     request_o[kListenerId] = args.get(kListenerId);
2586
2587     Instance::PostMessage(this, data->serialize().c_str());
2588   };
2589
2590   auto result = server_->SetDisplayModeChangeRequestListener(callback);
2591   if (!result) {
2592     LogAndReportError(result, &out);
2593     return;
2594   }
2595
2596   ReportSuccess(out);
2597 }
2598
2599 void MediaControllerInstance::MediaControllerDisplayModeRemoveChangeRequestListener(
2600     const picojson::value& args, picojson::object& out) {
2601   ScopeLogger();
2602   if (!server_) {
2603     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2604                       (MediaControllerServerUnknownErrorMsg));
2605     return;
2606   }
2607
2608   auto result = server_->UnsetDisplayModeChangeRequestListener();
2609   if (!result) {
2610     LogAndReportError(result, &out);
2611     return;
2612   }
2613   ReportSuccess(out);
2614 }
2615
2616 void MediaControllerInstance::MediaControllerDisplayModeInfoGetType(const picojson::value& args,
2617                                                                     picojson::object& out) {
2618   ScopeLogger();
2619   if (!client_) {
2620     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2621                       (MediaControllerClientUnknownErrorMsg));
2622     return;
2623   }
2624
2625   CHECK_ARGS(args, kName, std::string, out)
2626
2627   std::string type;
2628   PlatformResult result = client_->GetDisplayModeType(args.get(kName).get<std::string>(), &type);
2629
2630   if (!result) {
2631     LogAndReportError(result, &out, ("Failed: client_->GetDisplayModeType"));
2632     return;
2633   }
2634
2635   ReportSuccess(picojson::value(type), out);
2636 }
2637
2638 void MediaControllerInstance::MediaControllerDisplayModeInfoSendType(const picojson::value& args,
2639                                                                      picojson::object& out) {
2640   ScopeLogger();
2641   if (!client_) {
2642     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2643                       (MediaControllerClientUnknownErrorMsg));
2644     return;
2645   }
2646
2647   CHECK_ARGS(args, kListenerId, std::string, out)
2648   CHECK_ARGS(args, kName, std::string, out)
2649   CHECK_ARGS(args, kType, std::string, out)
2650
2651   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
2652     picojson::object& reply_obj = reply->get<picojson::object>();
2653     reply_obj[kListenerId] = args.get(kListenerId);
2654     Instance::PostMessage(this, reply->serialize().c_str());
2655   };
2656
2657   char* request_id = nullptr;
2658   SCOPE_EXIT {
2659     free(request_id);
2660   };
2661
2662   PlatformResult result =
2663       client_->SendDisplayModeType(args.get(kName).get<std::string>(),
2664                                    args.get(kType).get<std::string>(), reply_cb, &request_id);
2665
2666   if (result) {
2667     ReportSuccess(out);
2668     out[kRequestId] = picojson::value(std::string(request_id));
2669   } else {
2670     LogAndReportError(result, &out, ("Failed to send command."));
2671   }
2672 }
2673
2674 void MediaControllerInstance::MediaControllerDisplayModeInfoAddModeChangeListener(
2675     const picojson::value& args, picojson::object& out) {
2676   ScopeLogger();
2677   if (!client_) {
2678     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2679                       (MediaControllerClientUnknownErrorMsg));
2680     return;
2681   }
2682
2683   CHECK_ARGS(args, kListenerId, std::string, out)
2684
2685   JsonCallback callback = [this, args](picojson::value* data) -> void {
2686     if (nullptr == data) {
2687       LoggerE("No data passed to json callback");
2688       return;
2689     }
2690
2691     picojson::object& request_o = data->get<picojson::object>();
2692     request_o[kListenerId] = args.get(kListenerId);
2693
2694     Instance::PostMessage(this, data->serialize().c_str());
2695   };
2696
2697   auto result = client_->SetDisplayModeInfoChangeListener(callback);
2698   if (!result) {
2699     LogAndReportError(result, &out);
2700     return;
2701   }
2702
2703   ReportSuccess(out);
2704 }
2705
2706 void MediaControllerInstance::MediaControllerDisplayModeInfoRemoveModeChangeListener(
2707     const picojson::value& args, picojson::object& out) {
2708   ScopeLogger();
2709   if (!client_) {
2710     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2711                       (MediaControllerClientUnknownErrorMsg));
2712     return;
2713   }
2714
2715   auto result = client_->UnsetDisplayModeInfoChangeListener();
2716   if (!result) {
2717     LogAndReportError(result, &out);
2718     return;
2719   }
2720
2721   ReportSuccess(out);
2722 }
2723
2724 // displayRotation
2725 void MediaControllerInstance::MediaControllerDisplayRotationUpdate(const picojson::value& args,
2726                                                                    picojson::object& out) {
2727   ScopeLogger();
2728
2729   if (!server_) {
2730     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2731                       (MediaControllerServerUnknownErrorMsg));
2732     return;
2733   }
2734
2735   CHECK_ARGS(args, kDisplayRotation, std::string, out)
2736
2737   const std::string display_rotation = args.get(kDisplayRotation).get<std::string>();
2738   PlatformResult result = server_->UpdateDisplayRotation(display_rotation);
2739   if (!result) {
2740     LogAndReportError(result, &out, ("Failed server_->UpdateDisplayRotation()"));
2741     return;
2742   }
2743   ReportSuccess(out);
2744 }
2745
2746 void MediaControllerInstance::MediaControllerDisplayRotationAddChangeRequestListener(
2747     const picojson::value& args, picojson::object& out) {
2748   ScopeLogger();
2749   if (!server_) {
2750     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2751                       (MediaControllerServerUnknownErrorMsg));
2752     return;
2753   }
2754
2755   CHECK_ARGS(args, kListenerId, std::string, out)
2756
2757   JsonCallback callback = [this, args](picojson::value* data) -> void {
2758     if (!data) {
2759       LoggerE("No data passed to json callback");
2760       return;
2761     }
2762     picojson::object& request_o = data->get<picojson::object>();
2763     request_o[kListenerId] = args.get(kListenerId);
2764
2765     Instance::PostMessage(this, data->serialize().c_str());
2766   };
2767
2768   auto result = server_->SetDisplayRotationChangeRequestListener(callback);
2769   if (!result) {
2770     LogAndReportError(result, &out);
2771     return;
2772   }
2773
2774   ReportSuccess(out);
2775 }
2776
2777 void MediaControllerInstance::MediaControllerDisplayRotationRemoveChangeRequestListener(
2778     const picojson::value& args, picojson::object& out) {
2779   ScopeLogger();
2780   if (!server_) {
2781     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2782                       (MediaControllerServerUnknownErrorMsg));
2783     return;
2784   }
2785
2786   auto result = server_->UnsetDisplayRotationChangeRequestListener();
2787   if (!result) {
2788     LogAndReportError(result, &out);
2789     return;
2790   }
2791   ReportSuccess(out);
2792 }
2793
2794 void MediaControllerInstance::MediaControllerDisplayRotationInfoGet(const picojson::value& args,
2795                                                                     picojson::object& out) {
2796   ScopeLogger();
2797   if (!client_) {
2798     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2799                       (MediaControllerClientUnknownErrorMsg));
2800     return;
2801   }
2802
2803   CHECK_ARGS(args, kName, std::string, out)
2804
2805   std::string rotation;
2806   PlatformResult result =
2807       client_->GetDisplayRotation(args.get(kName).get<std::string>(), &rotation);
2808
2809   if (!result) {
2810     LogAndReportError(result, &out, ("Failed: client_->GetDisplayRotation"));
2811     return;
2812   }
2813
2814   ReportSuccess(picojson::value(rotation), out);
2815 }
2816
2817 void MediaControllerInstance::MediaControllerDisplayRotationInfoSend(const picojson::value& args,
2818                                                                      picojson::object& out) {
2819   ScopeLogger();
2820   if (!client_) {
2821     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2822                       (MediaControllerClientUnknownErrorMsg));
2823     return;
2824   }
2825
2826   CHECK_ARGS(args, kListenerId, std::string, out)
2827   CHECK_ARGS(args, kName, std::string, out)
2828   CHECK_ARGS(args, kDisplayRotation, std::string, out)
2829
2830   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
2831     if (reply) {
2832       picojson::object& reply_obj = reply->get<picojson::object>();
2833       reply_obj[kListenerId] = args.get(kListenerId);
2834       Instance::PostMessage(this, reply->serialize().c_str());
2835     } else {
2836       LoggerW("No reply passed to json callback, ignoring");
2837     }
2838   };
2839
2840   char* request_id = nullptr;
2841   SCOPE_EXIT {
2842     free(request_id);
2843   };
2844
2845   PlatformResult result = client_->SendDisplayRotation(
2846       args.get(kName).get<std::string>(), args.get(kDisplayRotation).get<std::string>(), reply_cb,
2847       &request_id);
2848
2849   if (result) {
2850     ReportSuccess(out);
2851     out[kRequestId] = picojson::value(std::string(request_id));
2852   } else {
2853     LogAndReportError(result, &out, ("Failed to send display rotation command."));
2854   }
2855 }
2856
2857 void MediaControllerInstance::MediaControllerDisplayRotationInfoAddChangeListener(
2858     const picojson::value& args, picojson::object& out) {
2859   ScopeLogger();
2860   if (!client_) {
2861     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2862                       (MediaControllerClientUnknownErrorMsg));
2863     return;
2864   }
2865
2866   CHECK_ARGS(args, kListenerId, std::string, out)
2867
2868   JsonCallback callback = [this, args](picojson::value* data) -> void {
2869     if (nullptr == data) {
2870       LoggerE("No data passed to json callback");
2871       return;
2872     }
2873
2874     picojson::object& request_o = data->get<picojson::object>();
2875     request_o[kListenerId] = args.get(kListenerId);
2876
2877     Instance::PostMessage(this, data->serialize().c_str());
2878   };
2879
2880   auto result = client_->SetDisplayRotationInfoChangeListener(callback);
2881   if (!result) {
2882     LogAndReportError(result, &out);
2883     return;
2884   }
2885
2886   ReportSuccess(out);
2887 }
2888
2889 void MediaControllerInstance::MediaControllerDisplayRotationInfoRemoveChangeListener(
2890     const picojson::value& args, picojson::object& out) {
2891   ScopeLogger();
2892   if (!client_) {
2893     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2894                       (MediaControllerClientUnknownErrorMsg));
2895     return;
2896   }
2897
2898   auto result = client_->UnsetDisplayRotationInfoChangeListener();
2899   if (!result) {
2900     LogAndReportError(result, &out);
2901     return;
2902   }
2903
2904   ReportSuccess(out);
2905 }
2906
2907 void MediaControllerInstance::MediaControllerPlaylistsInfoSendPlaybackItem(
2908     const picojson::value& args, picojson::object& out) {
2909   ScopeLogger();
2910   if (!client_) {
2911     LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, MediaControllerUnknownErrorMsg), &out,
2912                       (MediaControllerClientUnknownErrorMsg));
2913     return;
2914   }
2915
2916   CHECK_ARGS(args, kServerName, std::string, out)
2917   CHECK_ARGS(args, kPlaylistName, std::string, out)
2918   CHECK_ARGS(args, kIndex, std::string, out)
2919   CHECK_ARGS(args, kAction, std::string, out)
2920   CHECK_ARGS(args, kPosition, double, out)
2921
2922   JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
2923     if (reply) {
2924       picojson::object& reply_obj = reply->get<picojson::object>();
2925       reply_obj[kListenerId] = args.get(kListenerId);
2926       Instance::PostMessage(this, reply->serialize().c_str());
2927     } else {
2928       LoggerW("No reply passed to json callback, ignoring");
2929     }
2930   };
2931
2932   char* request_id = nullptr;
2933   SCOPE_EXIT {
2934     free(request_id);
2935   };
2936
2937   const std::string& server_name = args.get(kServerName).get<std::string>();
2938   const std::string& playlist_name = args.get(kPlaylistName).get<std::string>();
2939   const std::string& index = args.get(kIndex).get<std::string>();
2940   const std::string& action = args.get(kAction).get<std::string>();
2941   const int position = static_cast<unsigned long long>(args.get(kPosition).get<double>());
2942
2943   PlatformResult result = client_->SendPlaybackItem(server_name, playlist_name, index, action,
2944                                                     position, reply_cb, &request_id);
2945
2946   if (result) {
2947     out[kRequestId] = picojson::value(std::string(request_id));
2948     ReportSuccess(out);
2949   } else {
2950     LogAndReportError(result, &out, ("Failed to send playback position."));
2951   }
2952 }
2953
2954 #undef CHECK_EXIST
2955
2956 }  // namespace mediacontroller
2957 }  // namespace extension