fb2b5e4492fc4b3a65da238f212d8d763b8f1574
[vuplus_xbmc] / xbmc / interfaces / json-rpc / PlayerOperations.cpp
1 /*
2  *      Copyright (C) 2005-2012 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "PlayerOperations.h"
22 #include "Application.h"
23 #include "Util.h"
24 #include "PlayListPlayer.h"
25 #include "playlists/PlayList.h"
26 #include "guilib/GUIWindowManager.h"
27 #include "GUIUserMessages.h"
28 #include "pictures/GUIWindowSlideShow.h"
29 #include "interfaces/Builtins.h"
30 #include "PartyModeManager.h"
31 #include "ApplicationMessenger.h"
32 #include "FileItem.h"
33 #include "VideoLibrary.h"
34 #include "video/VideoDatabase.h"
35 #include "AudioLibrary.h"
36 #include "GUIInfoManager.h"
37 #include "filesystem/File.h"
38 #include "PartyModeManager.h"
39 #include "epg/EpgInfoTag.h"
40 #include "music/MusicDatabase.h"
41 #include "pvr/PVRManager.h"
42 #include "pvr/channels/PVRChannel.h"
43 #include "pvr/channels/PVRChannelGroupsContainer.h"
44
45 using namespace JSONRPC;
46 using namespace PLAYLIST;
47 using namespace PVR;
48
49 JSONRPC_STATUS CPlayerOperations::GetActivePlayers(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
50 {
51   int activePlayers = GetActivePlayers();
52   result = CVariant(CVariant::VariantTypeArray);
53
54   if (activePlayers & Video)
55   {
56     CVariant video = CVariant(CVariant::VariantTypeObject);
57     video["playerid"] = GetPlaylist(Video);
58     video["type"] = "video";
59     result.append(video);
60   }
61   if (activePlayers & Audio)
62   {
63     CVariant audio = CVariant(CVariant::VariantTypeObject);
64     audio["playerid"] = GetPlaylist(Audio);
65     audio["type"] = "audio";
66     result.append(audio);
67   }
68   if (activePlayers & Picture)
69   {
70     CVariant picture = CVariant(CVariant::VariantTypeObject);
71     picture["playerid"] = GetPlaylist(Picture);
72     picture["type"] = "picture";
73     result.append(picture);
74   }
75
76   return OK;
77 }
78
79 JSONRPC_STATUS CPlayerOperations::GetProperties(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
80 {
81   PlayerType player = GetPlayer(parameterObject["playerid"]);
82
83   CVariant properties = CVariant(CVariant::VariantTypeObject);
84   for (unsigned int index = 0; index < parameterObject["properties"].size(); index++)
85   {
86     CStdString propertyName = parameterObject["properties"][index].asString();
87     CVariant property;
88     JSONRPC_STATUS ret;
89     if ((ret = GetPropertyValue(player, propertyName, property)) != OK)
90       return ret;
91
92     properties[propertyName] = property;
93   }
94
95   result = properties;
96
97   return OK;
98 }
99
100 JSONRPC_STATUS CPlayerOperations::GetItem(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
101 {
102   PlayerType player = GetPlayer(parameterObject["playerid"]);
103   CFileItemPtr fileItem;
104
105   switch (player)
106   {
107     case Video:
108     case Audio:
109     {
110       fileItem = CFileItemPtr(new CFileItem(g_application.CurrentFileItem()));
111       if (fileItem->GetLabel().empty())
112       {
113         if (IsPVRChannel())
114         {
115           CPVRChannelPtr currentChannel;
116           if (g_PVRManager.GetCurrentChannel(currentChannel) && currentChannel.get() != NULL)
117             fileItem = CFileItemPtr(new CFileItem(*currentChannel.get()));
118         }
119         else if (player == Video)
120         {
121           if (!CVideoLibrary::FillFileItem(g_application.CurrentFile(), fileItem, parameterObject))
122           {
123             const CVideoInfoTag *currentVideoTag = g_infoManager.GetCurrentMovieTag();
124             if (currentVideoTag != NULL)
125               fileItem = CFileItemPtr(new CFileItem(*currentVideoTag));
126             fileItem->SetPath(g_application.CurrentFileItem().GetPath());
127           }
128         }
129         else
130         {
131           if (!CAudioLibrary::FillFileItem(g_application.CurrentFile(), fileItem, parameterObject))
132           {
133             const MUSIC_INFO::CMusicInfoTag *currentMusicTag = g_infoManager.GetCurrentSongTag();
134             if (currentMusicTag != NULL)
135               fileItem = CFileItemPtr(new CFileItem(*currentMusicTag));
136             fileItem->SetPath(g_application.CurrentFileItem().GetPath());
137           }
138         }
139       }
140
141       if (IsPVRChannel())
142         break;
143
144       if (player == Video)
145       {
146         bool additionalInfo = false;
147         bool streamdetails = false;
148         for (CVariant::const_iterator_array itr = parameterObject["properties"].begin_array(); itr != parameterObject["properties"].end_array(); itr++)
149         {
150           CStdString fieldValue = itr->asString();
151           if (fieldValue == "cast" || fieldValue == "set" || fieldValue == "setid" || fieldValue == "showlink" || fieldValue == "resume" ||
152              (fieldValue == "streamdetails" && !fileItem->GetVideoInfoTag()->m_streamDetails.HasItems()))
153             additionalInfo = true;
154         }
155
156         CVideoDatabase videodatabase;
157         if ((additionalInfo) &&
158             videodatabase.Open())
159         {
160           if (additionalInfo)
161           {
162             switch (fileItem->GetVideoContentType())
163             {
164               case VIDEODB_CONTENT_MOVIES:
165                 videodatabase.GetMovieInfo("", *(fileItem->GetVideoInfoTag()), fileItem->GetVideoInfoTag()->m_iDbId);
166                 break;
167
168               case VIDEODB_CONTENT_MUSICVIDEOS:
169                 videodatabase.GetMusicVideoInfo("", *(fileItem->GetVideoInfoTag()), fileItem->GetVideoInfoTag()->m_iDbId);
170                 break;
171
172               case VIDEODB_CONTENT_EPISODES:
173                 videodatabase.GetEpisodeInfo("", *(fileItem->GetVideoInfoTag()), fileItem->GetVideoInfoTag()->m_iDbId);
174                 break;
175
176               case VIDEODB_CONTENT_TVSHOWS:
177               case VIDEODB_CONTENT_MOVIE_SETS:
178               default:
179                 break;
180             }
181           }
182
183           videodatabase.Close();
184         }
185       }
186       else if (player == Audio)
187       {
188         if (fileItem->IsMusicDb())
189         {
190           CMusicDatabase musicdb;
191           CFileItemList items;
192           items.Add(fileItem);
193           CAudioLibrary::GetAdditionalSongDetails(parameterObject, items, musicdb);
194         }
195       }
196       break;
197     }
198
199     case Picture:
200     {
201       CGUIWindowSlideShow *slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
202       if (!slideshow)
203         return FailedToExecute;
204
205       CFileItemList slides;
206       slideshow->GetSlideShowContents(slides);
207       fileItem = slides[slideshow->CurrentSlide() - 1];
208       break;
209     }
210
211     case None:
212     default:
213       return FailedToExecute;
214   }
215
216   HandleFileItem("id", !IsPVRChannel(), "item", fileItem, parameterObject, parameterObject["properties"], result, false);
217   return OK;
218 }
219
220 JSONRPC_STATUS CPlayerOperations::PlayPause(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
221 {
222   CGUIWindowSlideShow *slideshow = NULL;
223   switch (GetPlayer(parameterObject["playerid"]))
224   {
225     case Video:
226     case Audio:
227       if (g_application.m_pPlayer && !g_application.m_pPlayer->CanPause())
228         return FailedToExecute;
229       
230       if (parameterObject["play"].isString())
231         CBuiltins::Execute("playercontrol(play)");
232       else
233       {
234         if (parameterObject["play"].asBoolean() == g_application.IsPaused())
235           CApplicationMessenger::Get().MediaPause();
236       }
237       result["speed"] = g_application.IsPaused() ? 0 : g_application.GetPlaySpeed();
238       return OK;
239
240     case Picture:
241       slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
242       if (slideshow && slideshow->IsPlaying() &&
243          (parameterObject["play"].isString() ||
244          (parameterObject["play"].isBoolean() && parameterObject["play"].asBoolean() == slideshow->IsPaused())))
245         SendSlideshowAction(ACTION_PAUSE);
246
247       if (slideshow && slideshow->IsPlaying() && !slideshow->IsPaused())
248         result["speed"] = slideshow->GetDirection();
249       else
250         result["speed"] = 0;
251       return OK;
252
253     case None:
254     default:
255       return FailedToExecute;
256   }
257 }
258
259 JSONRPC_STATUS CPlayerOperations::Stop(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
260 {
261   switch (GetPlayer(parameterObject["playerid"]))
262   {
263     case Video:
264     case Audio:
265       CApplicationMessenger::Get().SendAction(CAction(ACTION_STOP));
266       return ACK;
267
268     case Picture:
269       SendSlideshowAction(ACTION_STOP);
270       return ACK;
271
272     case None:
273     default:
274       return FailedToExecute;
275   }
276 }
277
278 JSONRPC_STATUS CPlayerOperations::SetSpeed(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
279 {
280   int speed;
281   switch (GetPlayer(parameterObject["playerid"]))
282   {
283     case Video:
284     case Audio:
285       if (parameterObject["speed"].isInteger())
286       {
287         speed = (int)parameterObject["speed"].asInteger();
288         if (speed != 0)
289         {
290           // If the player is paused we first need to unpause
291           if (g_application.IsPaused())
292             g_application.m_pPlayer->Pause();
293           g_application.SetPlaySpeed(speed);
294         }
295         else
296           g_application.m_pPlayer->Pause();
297       }
298       else if (parameterObject["speed"].isString())
299       {
300         speed = g_application.GetPlaySpeed();
301         if (parameterObject["speed"].asString().compare("increment") == 0)
302           CBuiltins::Execute("playercontrol(forward)");
303         else
304           CBuiltins::Execute("playercontrol(rewind)");
305       }
306       else
307         return InvalidParams;
308
309       result["speed"] = g_application.IsPaused() ? 0 : g_application.GetPlaySpeed();
310       return OK;
311
312     case Picture:
313     case None:
314     default:
315       return FailedToExecute;
316   }
317 }
318
319 JSONRPC_STATUS CPlayerOperations::Seek(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
320 {
321   PlayerType player = GetPlayer(parameterObject["playerid"]);
322   switch (player)
323   {
324     case Video:
325     case Audio:
326       if (g_application.m_pPlayer && !g_application.m_pPlayer->CanSeek())
327         return FailedToExecute;
328       
329       if (parameterObject["value"].isObject())
330         g_application.SeekTime(ParseTimeInSeconds(parameterObject["value"]));
331       else if (IsType(parameterObject["value"], NumberValue))
332         g_application.SeekPercentage(parameterObject["value"].asFloat());
333       else if (parameterObject["value"].isString())
334       {
335         CStdString step = parameterObject["value"].asString();
336         if (step.Equals("smallforward"))
337           CBuiltins::Execute("playercontrol(smallskipforward)");
338         else if (step.Equals("smallbackward"))
339           CBuiltins::Execute("playercontrol(smallskipbackward)");
340         else if (step.Equals("bigforward"))
341           CBuiltins::Execute("playercontrol(bigskipforward)");
342         else if (step.Equals("bigbackward"))
343           CBuiltins::Execute("playercontrol(bigskipbackward)");
344         else
345           return InvalidParams;
346       }
347       else
348         return InvalidParams;
349
350       GetPropertyValue(player, "percentage", result["percentage"]);
351       GetPropertyValue(player, "time", result["time"]);
352       GetPropertyValue(player, "totaltime", result["totaltime"]);
353       return OK;
354
355     case Picture:
356     case None:
357     default:
358       return FailedToExecute;
359   }
360 }
361
362 JSONRPC_STATUS CPlayerOperations::Move(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
363 {
364   std::string direction = parameterObject["direction"].asString();
365   switch (GetPlayer(parameterObject["playerid"]))
366   {
367     case Picture:
368       if (direction == "left")
369         SendSlideshowAction(ACTION_MOVE_LEFT);
370       else if (direction == "right")
371         SendSlideshowAction(ACTION_MOVE_RIGHT);
372       else if (direction == "up")
373         SendSlideshowAction(ACTION_MOVE_UP);
374       else if (direction == "down")
375         SendSlideshowAction(ACTION_MOVE_DOWN);
376       else
377         return InvalidParams;
378
379       return ACK;
380
381     case Video:
382     case Audio:
383       if (direction == "left" || direction == "up")
384         CApplicationMessenger::Get().SendAction(CAction(ACTION_PREV_ITEM));
385       else if (direction == "right" || direction == "down")
386         CApplicationMessenger::Get().SendAction(CAction(ACTION_NEXT_ITEM));
387       else
388         return InvalidParams;
389
390       return ACK;
391
392     case None:
393     default:
394       return FailedToExecute;
395   }
396 }
397
398 JSONRPC_STATUS CPlayerOperations::Zoom(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
399 {
400   CVariant zoom = parameterObject["zoom"];
401   switch (GetPlayer(parameterObject["playerid"]))
402   {
403     case Picture:
404       if (zoom.isInteger())
405         SendSlideshowAction(ACTION_ZOOM_LEVEL_NORMAL + ((int)zoom.asInteger() - 1));
406       else if (zoom.isString())
407       {
408         std::string strZoom = zoom.asString();
409         if (strZoom == "in")
410           SendSlideshowAction(ACTION_ZOOM_IN);
411         else if (strZoom == "out")
412           SendSlideshowAction(ACTION_ZOOM_OUT);
413         else
414           return InvalidParams;
415       }
416       else
417         return InvalidParams;
418
419       return ACK;
420
421     case Video:
422     case Audio:
423     case None:
424     default:
425       return FailedToExecute;
426   }
427 }
428
429 JSONRPC_STATUS CPlayerOperations::Rotate(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
430 {
431   switch (GetPlayer(parameterObject["playerid"]))
432   {
433     case Picture:
434       if (parameterObject["value"].asString().compare("clockwise") == 0)
435         SendSlideshowAction(ACTION_ROTATE_PICTURE_CW);
436       else
437         SendSlideshowAction(ACTION_ROTATE_PICTURE_CCW);
438       return ACK;
439
440     case Video:
441     case Audio:
442     case None:
443     default:
444       return FailedToExecute;
445   }
446 }
447
448 JSONRPC_STATUS CPlayerOperations::Open(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
449 {
450   CVariant optionShuffled = parameterObject["options"]["shuffled"];
451   CVariant optionRepeat = parameterObject["options"]["repeat"];
452   CVariant optionResume = parameterObject["options"]["resume"];
453
454   if (parameterObject["item"].isObject() && parameterObject["item"].isMember("playlistid"))
455   {
456     int playlistid = (int)parameterObject["item"]["playlistid"].asInteger();
457
458     if (playlistid < PLAYLIST_PICTURE)
459     {
460       // Apply the "shuffled" option if available
461       if (optionShuffled.isBoolean())
462         g_playlistPlayer.SetShuffle(playlistid, optionShuffled.asBoolean(), false);
463       // Apply the "repeat" option if available
464       if (!optionRepeat.isNull())
465         g_playlistPlayer.SetRepeat(playlistid, (REPEAT_STATE)ParseRepeatState(optionRepeat), false);
466     }
467
468     switch (playlistid)
469     {
470       case PLAYLIST_MUSIC:
471       case PLAYLIST_VIDEO:
472         CApplicationMessenger::Get().MediaPlay(playlistid, (int)parameterObject["item"]["position"].asInteger());
473         OnPlaylistChanged();
474         break;
475
476       case PLAYLIST_PICTURE:
477         return StartSlideshow("", false, optionShuffled.isBoolean() && optionShuffled.asBoolean());
478         break;
479     }
480
481     return ACK;
482   }
483   else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("path"))
484   {
485     bool random = (optionShuffled.isBoolean() && optionShuffled.asBoolean()) ||
486                   (!optionShuffled.isBoolean() && parameterObject["item"]["random"].asBoolean());
487     return StartSlideshow(parameterObject["item"]["path"].asString(), parameterObject["item"]["recursive"].asBoolean(), random);
488   }
489   else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("partymode"))
490   {
491     if (g_partyModeManager.IsEnabled())
492       g_partyModeManager.Disable();
493     CApplicationMessenger::Get().ExecBuiltIn("playercontrol(partymode(" + parameterObject["item"]["partymode"].asString() + "))");
494     return ACK;
495   }
496   else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("channelid"))
497   {
498     if (!g_PVRManager.IsStarted())
499       return FailedToExecute;
500
501     CPVRChannelGroupsContainer *channelGroupContainer = g_PVRChannelGroups;
502     if (channelGroupContainer == NULL)
503       return FailedToExecute;
504
505     CPVRChannelPtr channel = channelGroupContainer->GetChannelById((int)parameterObject["item"]["channelid"].asInteger());
506     if (channel == NULL)
507       return InvalidParams;
508
509     CApplicationMessenger::Get().MediaPlay(CFileItem(*channel.get()));
510     return ACK;
511   }
512   else
513   {
514     CFileItemList list;
515     if (FillFileItemList(parameterObject["item"], list) && list.Size() > 0)
516     {
517       bool slideshow = true;
518       for (int index = 0; index < list.Size(); index++)
519       {
520         if (!list[index]->IsPicture())
521         {
522           slideshow = false;
523           break;
524         }
525       }
526
527       if (slideshow)
528       {
529         CGUIWindowSlideShow *slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
530         if (!slideshow)
531           return FailedToExecute;
532
533         SendSlideshowAction(ACTION_STOP);
534         slideshow->Reset();
535         for (int index = 0; index < list.Size(); index++)
536           slideshow->Add(list[index].get());
537
538         return StartSlideshow("", false, optionShuffled.isBoolean() && optionShuffled.asBoolean());
539       }
540       else
541       {
542         // Handle "shuffled" option
543         if (optionShuffled.isBoolean())
544           list.SetProperty("shuffled", optionShuffled);
545         // Handle "repeat" option
546         if (!optionRepeat.isNull())
547           list.SetProperty("repeat", ParseRepeatState(optionRepeat));
548         // Handle "resume" option
549         if (list.Size() == 1)
550         {
551           if (optionResume.isBoolean() && optionResume.asBoolean())
552             list[0]->m_lStartOffset = STARTOFFSET_RESUME;
553           else if (optionResume.isDouble())
554             list[0]->SetProperty("StartPercent", optionResume);
555           else if (optionResume.isObject())
556             list[0]->m_lStartOffset = (int)(ParseTimeInSeconds(optionResume) * 75.0);
557         }
558
559         CApplicationMessenger::Get().MediaPlay(list);
560       }
561
562       return ACK;
563     }
564     else
565       return InvalidParams;
566   }
567
568   return InvalidParams;
569 }
570
571 JSONRPC_STATUS CPlayerOperations::GoTo(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
572 {
573   CVariant to = parameterObject["to"];
574   switch (GetPlayer(parameterObject["playerid"]))
575   {
576     case Video:
577     case Audio:
578       if (to.isString())
579       {
580         std::string strTo = to.asString();
581         int actionID;
582         if (strTo == "previous")
583           actionID = ACTION_PREV_ITEM;
584         else if (strTo == "next")
585           actionID = ACTION_NEXT_ITEM;
586         else
587           return InvalidParams;
588
589         CApplicationMessenger::Get().SendAction(CAction(actionID));
590       }
591       else if (to.isInteger())
592       {
593         if (IsPVRChannel())
594           CApplicationMessenger::Get().SendAction(CAction(ACTION_CHANNEL_SWITCH, (float)to.asInteger()));
595         else
596           CApplicationMessenger::Get().PlayListPlayerPlay((int)to.asInteger());
597       }
598       else
599         return InvalidParams;
600       break;
601
602     case Picture:
603       if (to.isString())
604       {
605         std::string strTo = to.asString();
606         int actionID;
607         if (strTo == "previous")
608           actionID = ACTION_PREV_PICTURE;
609         else if (strTo == "next")
610           actionID = ACTION_NEXT_PICTURE;
611         else
612           return InvalidParams;
613
614         SendSlideshowAction(actionID);
615       }
616       else
617         return FailedToExecute;
618       break;
619
620     case None:
621     default:
622       return FailedToExecute;
623   }
624
625   OnPlaylistChanged();
626   return ACK;
627 }
628
629 JSONRPC_STATUS CPlayerOperations::SetShuffle(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
630 {
631   CGUIWindowSlideShow *slideshow = NULL;
632   CVariant shuffle = parameterObject["shuffle"];
633   switch (GetPlayer(parameterObject["playerid"]))
634   {
635     case Video:
636     case Audio:
637     {
638       if (IsPVRChannel())
639         return FailedToExecute;
640
641       int playlistid = GetPlaylist(GetPlayer(parameterObject["playerid"]));
642       if (g_playlistPlayer.IsShuffled(playlistid))
643       {
644         if ((shuffle.isBoolean() && !shuffle.asBoolean()) ||
645             (shuffle.isString() && shuffle.asString() == "toggle"))
646         {
647           CApplicationMessenger::Get().PlayListPlayerShuffle(playlistid, false);
648           OnPlaylistChanged();
649         }
650       }
651       else
652       {
653         if ((shuffle.isBoolean() && shuffle.asBoolean()) ||
654             (shuffle.isString() && shuffle.asString() == "toggle"))
655         {
656           CApplicationMessenger::Get().PlayListPlayerShuffle(playlistid, true);
657           OnPlaylistChanged();
658         }
659       }
660       break;
661     }
662
663     case Picture:
664       slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
665       if (slideshow == NULL)
666         return FailedToExecute;
667       if (slideshow->IsShuffled())
668       {
669         if ((shuffle.isBoolean() && !shuffle.asBoolean()) ||
670             (shuffle.isString() && shuffle.asString() == "toggle"))
671           return FailedToExecute;
672       }
673       else
674       {
675         if ((shuffle.isBoolean() && shuffle.asBoolean()) ||
676             (shuffle.isString() && shuffle.asString() == "toggle"))
677           slideshow->Shuffle();
678       }
679       break;
680
681     default:
682       return FailedToExecute;
683   }
684   return ACK;
685 }
686
687 JSONRPC_STATUS CPlayerOperations::SetRepeat(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
688 {
689   switch (GetPlayer(parameterObject["playerid"]))
690   {
691     case Video:
692     case Audio:
693     {
694       if (IsPVRChannel())
695         return FailedToExecute;
696
697       REPEAT_STATE repeat = REPEAT_NONE;
698       int playlistid = GetPlaylist(GetPlayer(parameterObject["playerid"]));
699       if (parameterObject["repeat"].asString() == "cycle")
700       {
701         REPEAT_STATE repeatPrev = g_playlistPlayer.GetRepeat(playlistid);
702         repeat = repeatPrev;
703         if (repeatPrev == REPEAT_NONE)
704           repeat = REPEAT_ALL;
705         else if (repeatPrev == REPEAT_ALL)
706           repeat = REPEAT_ONE;
707         else
708           repeat = REPEAT_NONE;
709       }
710       else
711         repeat = (REPEAT_STATE)ParseRepeatState(parameterObject["repeat"]);
712
713       CApplicationMessenger::Get().PlayListPlayerRepeat(playlistid, repeat);
714       OnPlaylistChanged();
715       break;
716     }
717
718     case Picture:
719     default:
720       return FailedToExecute;
721   }
722
723   return ACK;
724 }
725
726 JSONRPC_STATUS CPlayerOperations::SetPartymode(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
727 {
728   PlayerType player = GetPlayer(parameterObject["playerid"]);
729   switch (player)
730   {
731     case Video:
732     case Audio:
733     {
734       if (IsPVRChannel())
735         return FailedToExecute;
736
737       bool change = false;
738       PartyModeContext context = PARTYMODECONTEXT_UNKNOWN;
739       std::string strContext;
740       if (player == Video)
741       {
742         context = PARTYMODECONTEXT_VIDEO;
743         strContext = "video";
744       }
745       else if (player == Audio)
746       {
747         context = PARTYMODECONTEXT_MUSIC;
748         strContext = "music";
749       }
750
751       bool toggle = parameterObject["partymode"].isString();
752       if (g_partyModeManager.IsEnabled())
753       {
754         if (g_partyModeManager.GetType() != context)
755           return InvalidParams;
756
757         if (toggle || parameterObject["partymode"].asBoolean() == false)
758           change = true;
759       }
760       else
761       {
762         if (toggle || parameterObject["partymode"].asBoolean() == true)
763           change = true;
764       }
765
766       if (change)
767         CApplicationMessenger::Get().ExecBuiltIn("playercontrol(partymode(" + strContext + "))");
768       break;
769     }
770
771     case Picture:
772     default:
773       return FailedToExecute;
774   }
775
776   return ACK;
777 }
778
779 JSONRPC_STATUS CPlayerOperations::SetAudioStream(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
780 {
781   switch (GetPlayer(parameterObject["playerid"]))
782   {
783     case Video:
784       if (g_application.m_pPlayer)
785       {
786         int index = -1;
787         if (parameterObject["stream"].isString())
788         {
789           std::string action = parameterObject["stream"].asString();
790           if (action.compare("previous") == 0)
791           {
792             index = g_application.m_pPlayer->GetAudioStream() - 1;
793             if (index < 0)
794               index = g_application.m_pPlayer->GetAudioStreamCount() - 1;
795           }
796           else if (action.compare("next") == 0)
797           {
798             index = g_application.m_pPlayer->GetAudioStream() + 1;
799             if (index >= g_application.m_pPlayer->GetAudioStreamCount())
800               index = 0;
801           }
802           else
803             return InvalidParams;
804         }
805         else if (parameterObject["stream"].isInteger())
806           index = (int)parameterObject["stream"].asInteger();
807
808         if (index < 0 || g_application.m_pPlayer->GetAudioStreamCount() <= index)
809           return InvalidParams;
810
811         g_application.m_pPlayer->SetAudioStream(index);
812       }
813       else
814         return FailedToExecute;
815       break;
816       
817     case Audio:
818     case Picture:
819     default:
820       return FailedToExecute;
821   }
822
823   return ACK;
824 }
825
826 JSONRPC_STATUS CPlayerOperations::SetSubtitle(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
827 {
828   switch (GetPlayer(parameterObject["playerid"]))
829   {
830     case Video:
831       if (g_application.m_pPlayer)
832       {
833         int index = -1;
834         if (parameterObject["subtitle"].isString())
835         {
836           std::string action = parameterObject["subtitle"].asString();
837           if (action.compare("previous") == 0)
838           {
839             index = g_application.m_pPlayer->GetSubtitle() - 1;
840             if (index < 0)
841               index = g_application.m_pPlayer->GetSubtitleCount() - 1;
842           }
843           else if (action.compare("next") == 0)
844           {
845             index = g_application.m_pPlayer->GetSubtitle() + 1;
846             if (index >= g_application.m_pPlayer->GetSubtitleCount())
847               index = 0;
848           }
849           else if (action.compare("off") == 0)
850           {
851             g_application.m_pPlayer->SetSubtitleVisible(false);
852             return ACK;
853           }
854           else if (action.compare("on") == 0)
855           {
856             g_application.m_pPlayer->SetSubtitleVisible(true);
857             return ACK;
858           }
859           else
860             return InvalidParams;
861         }
862         else if (parameterObject["subtitle"].isInteger())
863           index = (int)parameterObject["subtitle"].asInteger();
864
865         if (index < 0 || g_application.m_pPlayer->GetSubtitleCount() <= index)
866           return InvalidParams;
867
868         g_application.m_pPlayer->SetSubtitle(index);
869
870         // Check if we need to enable subtitles to be displayed
871         if (parameterObject["enable"].asBoolean() && !g_application.m_pPlayer->GetSubtitleVisible())
872           g_application.m_pPlayer->SetSubtitleVisible(true);
873       }
874       else
875         return FailedToExecute;
876       break;
877       
878     case Audio:
879     case Picture:
880     default:
881       return FailedToExecute;
882   }
883
884   return ACK;
885 }
886
887 int CPlayerOperations::GetActivePlayers()
888 {
889   int activePlayers = 0;
890
891   if (g_application.IsPlayingVideo() || g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRecording())
892     activePlayers |= Video;
893   if (g_application.IsPlayingAudio() || g_PVRManager.IsPlayingRadio())
894     activePlayers |= Audio;
895   if (g_windowManager.IsWindowActive(WINDOW_SLIDESHOW))
896     activePlayers |= Picture;
897
898   return activePlayers;
899 }
900
901 PlayerType CPlayerOperations::GetPlayer(const CVariant &player)
902 {
903   int activePlayers = GetActivePlayers();
904   int playerID;
905
906   switch ((int)player.asInteger())
907   {
908     case PLAYLIST_VIDEO:
909       playerID = Video;
910       break;
911
912     case PLAYLIST_MUSIC:
913       playerID = Audio;
914       break;
915
916     case PLAYLIST_PICTURE:
917       playerID = Picture;
918       break;
919
920     default:
921       playerID = PlayerImplicit;
922       break;
923   }
924
925   int choosenPlayer = playerID & activePlayers;
926
927   // Implicit order
928   if (choosenPlayer & Video)
929     return Video;
930   else if (choosenPlayer & Audio)
931     return Audio;
932   else if (choosenPlayer & Picture)
933     return Picture;
934   else
935     return None;
936 }
937
938 int CPlayerOperations::GetPlaylist(PlayerType player)
939 {
940   switch (player)
941   {
942     case Video:
943       return PLAYLIST_VIDEO;
944
945     case Audio:
946       return PLAYLIST_MUSIC;
947
948     case Picture:
949       return PLAYLIST_PICTURE;
950
951     default:
952       return PLAYLIST_NONE;
953   }
954 }
955
956 JSONRPC_STATUS CPlayerOperations::StartSlideshow(const std::string path, bool recursive, bool random)
957 {
958   int flags = 0;
959   if (recursive)
960     flags |= 1;
961   if (random)
962     flags |= 2;
963   else
964     flags |= 4;
965
966   CGUIMessage msg(GUI_MSG_START_SLIDESHOW, 0, 0, flags);
967   msg.SetStringParam(path);
968   CApplicationMessenger::Get().SendGUIMessage(msg, WINDOW_SLIDESHOW, true);
969
970   return ACK;
971 }
972
973 void CPlayerOperations::SendSlideshowAction(int actionID)
974 {
975   CApplicationMessenger::Get().SendAction(CAction(actionID), WINDOW_SLIDESHOW);
976 }
977
978 void CPlayerOperations::OnPlaylistChanged()
979 {
980   CGUIMessage msg(GUI_MSG_PLAYLIST_CHANGED, 0, 0);
981   g_windowManager.SendThreadMessage(msg);
982 }
983
984 JSONRPC_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStdString &property, CVariant &result)
985 {
986   if (player == None)
987     return FailedToExecute;
988
989   int playlist = GetPlaylist(player);
990
991   if (property.Equals("type"))
992   {
993     switch (player)
994     {
995       case Video:
996         result = "video";
997         break;
998
999       case Audio:
1000         result = "audio";
1001         break;
1002
1003       case Picture:
1004         result = "picture";
1005         break;
1006
1007       default:
1008         return FailedToExecute;
1009     }
1010   }
1011   else if (property.Equals("partymode"))
1012   {
1013     switch (player)
1014     {
1015       case Video:
1016       case Audio:
1017         if (IsPVRChannel())
1018         {
1019           result = false;
1020           break;
1021         }
1022
1023         result = g_partyModeManager.IsEnabled();
1024         break;
1025
1026       case Picture:
1027         result = false;
1028         break;
1029
1030       default:
1031         return FailedToExecute;
1032     }
1033   }
1034   else if (property.Equals("speed"))
1035   {
1036     CGUIWindowSlideShow *slideshow = NULL;
1037     switch (player)
1038     {
1039       case Video:
1040       case Audio:
1041         result = g_application.IsPaused() ? 0 : g_application.GetPlaySpeed();
1042         break;
1043
1044       case Picture:
1045         slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
1046         if (slideshow && slideshow->IsPlaying() && !slideshow->IsPaused())
1047           result = slideshow->GetDirection();
1048         else
1049           result = 0;
1050         break;
1051
1052       default:
1053         return FailedToExecute;
1054     }
1055   }
1056   else if (property.Equals("time"))
1057   {
1058     switch (player)
1059     {
1060       case Video:
1061       case Audio:
1062       {
1063         int ms = 0;
1064         if (!IsPVRChannel())
1065           ms = (int)(g_application.GetTime() * 1000.0);
1066         else
1067         {
1068           EPG::CEpgInfoTag epg;
1069           if (GetCurrentEpg(epg))
1070             ms = epg.Progress() * 1000;
1071         }
1072
1073         MillisecondsToTimeObject(ms, result);
1074         break;
1075       }
1076
1077       case Picture:
1078         MillisecondsToTimeObject(0, result);
1079         break;
1080
1081       default:
1082         return FailedToExecute;
1083     }
1084   }
1085   else if (property.Equals("percentage"))
1086   {
1087     CGUIWindowSlideShow *slideshow = NULL;
1088     switch (player)
1089     {
1090       case Video:
1091       case Audio:
1092       {
1093         if (!IsPVRChannel())
1094           result = g_application.GetPercentage();
1095         else
1096         {
1097           EPG::CEpgInfoTag epg;
1098           if (GetCurrentEpg(epg))
1099             result = epg.ProgressPercentage();
1100           else
1101             result = 0;
1102         }
1103         break;
1104       }
1105
1106       case Picture:
1107         slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
1108         if (slideshow && slideshow->NumSlides() > 0)
1109           result = (double)slideshow->CurrentSlide() / slideshow->NumSlides();
1110         else
1111           result = 0.0;
1112         break;
1113
1114       default:
1115         return FailedToExecute;
1116     }
1117   }
1118   else if (property.Equals("totaltime"))
1119   {
1120     switch (player)
1121     {
1122       case Video:
1123       case Audio:
1124       {
1125         int ms = 0;
1126         if (!IsPVRChannel())
1127           ms = (int)(g_application.GetTotalTime() * 1000.0);
1128         else
1129         {
1130           EPG::CEpgInfoTag epg;
1131           if (GetCurrentEpg(epg))
1132             ms = epg.GetDuration() * 1000;
1133         }
1134         
1135         MillisecondsToTimeObject(ms, result);
1136         break;
1137       }
1138
1139       case Picture:
1140         MillisecondsToTimeObject(0, result);
1141         break;
1142
1143       default:
1144         return FailedToExecute;
1145     }
1146   }
1147   else if (property.Equals("playlistid"))
1148   {
1149     result = playlist;
1150   }
1151   else if (property.Equals("position"))
1152   {
1153     CGUIWindowSlideShow *slideshow = NULL;
1154     switch (player)
1155     {
1156       case Video:
1157       case Audio:
1158         if (!IsPVRChannel() && g_playlistPlayer.GetCurrentPlaylist() == playlist)
1159           result = g_playlistPlayer.GetCurrentSong();
1160         else
1161           result = -1;
1162         break;
1163
1164       case Picture:
1165         slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
1166         if (slideshow && slideshow->IsPlaying())
1167           result = slideshow->CurrentSlide() - 1;
1168         else
1169           result = -1;
1170         break;
1171
1172       default:
1173         result = -1;
1174         break;
1175     }
1176   }
1177   else if (property.Equals("repeat"))
1178   {
1179     switch (player)
1180     {
1181       case Video:
1182       case Audio:
1183         if (IsPVRChannel())
1184         {
1185           result = "off";
1186           break;
1187         }
1188
1189         switch (g_playlistPlayer.GetRepeat(playlist))
1190         {
1191         case REPEAT_ONE:
1192           result = "one";
1193           break;
1194         case REPEAT_ALL:
1195           result = "all";
1196           break;
1197         default:
1198           result = "off";
1199           break;
1200         }
1201         break;
1202
1203       case Picture:
1204       default:
1205         result = "off";
1206         break;
1207     }
1208   }
1209   else if (property.Equals("shuffled"))
1210   {
1211     CGUIWindowSlideShow *slideshow = NULL;
1212     switch (player)
1213     {
1214       case Video:
1215       case Audio:
1216         if (IsPVRChannel())
1217         {
1218           result = false;
1219           break;
1220         }
1221
1222         result = g_playlistPlayer.IsShuffled(playlist);
1223         break;
1224
1225       case Picture:
1226         slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
1227         if (slideshow && slideshow->IsPlaying())
1228           result = slideshow->IsShuffled();
1229         else
1230           result = -1;
1231         break;
1232
1233       default:
1234         result = -1;
1235         break;
1236     }
1237   }
1238   else if (property.Equals("canseek"))
1239   {
1240     switch (player)
1241     {
1242       case Video:
1243       case Audio:
1244         if (g_application.m_pPlayer)
1245           result = g_application.m_pPlayer->CanSeek();
1246         else
1247           result = false;
1248         break;
1249
1250       case Picture:
1251       default:
1252         result = false;
1253         break;
1254     }
1255   }
1256   else if (property.Equals("canchangespeed"))
1257   {
1258     switch (player)
1259     {
1260       case Video:
1261       case Audio:
1262         result = !IsPVRChannel();
1263         break;
1264
1265       case Picture:
1266       default:
1267         result = false;
1268         break;
1269     }
1270   }
1271   else if (property.Equals("canmove"))
1272   {
1273     switch (player)
1274     {
1275       case Picture:
1276         result = true;
1277         break;
1278
1279       case Video:
1280       case Audio:
1281       default:
1282         result = false;
1283         break;
1284     }
1285   }
1286   else if (property.Equals("canzoom"))
1287   {
1288     switch (player)
1289     {
1290       case Picture:
1291         result = true;
1292         break;
1293
1294       case Video:
1295       case Audio:
1296       default:
1297         result = false;
1298         break;
1299     }
1300   }
1301   else if (property.Equals("canrotate"))
1302   {
1303     switch (player)
1304     {
1305       case Picture:
1306         result = true;
1307         break;
1308
1309       case Video:
1310       case Audio:
1311       default:
1312         result = false;
1313         break;
1314     }
1315   }
1316   else if (property.Equals("canshuffle"))
1317   {
1318     switch (player)
1319     {
1320       case Video:
1321       case Audio:
1322       case Picture:
1323         result = !IsPVRChannel();
1324         break;
1325
1326       default:
1327         result = false;
1328         break;
1329     }
1330   }
1331   else if (property.Equals("canrepeat"))
1332   {
1333     switch (player)
1334     {
1335       case Video:
1336       case Audio:
1337         result = !IsPVRChannel();
1338         break;
1339
1340       case Picture:
1341       default:
1342         result = false;
1343         break;
1344     }
1345   }
1346   else if (property.Equals("currentaudiostream"))
1347   {
1348     switch (player)
1349     {
1350       case Video:
1351       case Audio:
1352         if (g_application.m_pPlayer)
1353         {
1354           result = CVariant(CVariant::VariantTypeObject);
1355           int index = g_application.m_pPlayer->GetAudioStream();
1356           if (index >= 0)
1357           {
1358             result["index"] = index;
1359             CStdString value;
1360             g_application.m_pPlayer->GetAudioStreamName(index, value);
1361             result["name"] = value;
1362             value.Empty();
1363             g_application.m_pPlayer->GetAudioStreamLanguage(index, value);
1364             result["language"] = value;
1365           }
1366           result["codec"] = g_application.m_pPlayer->GetAudioCodecName();
1367           result["bitrate"] = g_application.m_pPlayer->GetAudioBitrate();
1368           result["channels"] = g_application.m_pPlayer->GetChannels();
1369         }
1370         else
1371           result = CVariant(CVariant::VariantTypeNull);
1372         break;
1373         
1374       case Picture:
1375       default:
1376         result = CVariant(CVariant::VariantTypeNull);
1377         break;
1378     }
1379   }
1380   else if (property.Equals("audiostreams"))
1381   {
1382     result = CVariant(CVariant::VariantTypeArray);
1383     switch (player)
1384     {
1385       case Video:
1386         if (g_application.m_pPlayer)
1387         {
1388           for (int index = 0; index < g_application.m_pPlayer->GetAudioStreamCount(); index++)
1389           {
1390             CVariant audioStream(CVariant::VariantTypeObject);
1391             audioStream["index"] = index;
1392             CStdString value;
1393             g_application.m_pPlayer->GetAudioStreamName(index, value);
1394             audioStream["name"] = value;
1395             value.Empty();
1396             g_application.m_pPlayer->GetAudioStreamLanguage(index, value);
1397             audioStream["language"] = value;
1398
1399             result.append(audioStream);
1400           }
1401         }
1402         break;
1403         
1404       case Audio:
1405       case Picture:
1406       default:
1407         break;
1408     }
1409   }
1410   else if (property.Equals("subtitleenabled"))
1411   {
1412     switch (player)
1413     {
1414       case Video:
1415         if (g_application.m_pPlayer)
1416           result = g_application.m_pPlayer->GetSubtitleVisible();
1417         break;
1418         
1419       case Audio:
1420       case Picture:
1421       default:
1422         result = false;
1423         break;
1424     }
1425   }
1426   else if (property.Equals("currentsubtitle"))
1427   {
1428     switch (player)
1429     {
1430       case Video:
1431         if (g_application.m_pPlayer)
1432         {
1433           result = CVariant(CVariant::VariantTypeObject);
1434           int index = g_application.m_pPlayer->GetSubtitle();
1435           if (index >= 0)
1436           {
1437             result["index"] = index;
1438             CStdString value;
1439             g_application.m_pPlayer->GetSubtitleName(index, value);
1440             result["name"] = value;
1441             value.Empty();
1442             g_application.m_pPlayer->GetSubtitleLanguage(index, value);
1443             result["language"] = value;
1444           }
1445         }
1446         else
1447           result = CVariant(CVariant::VariantTypeNull);
1448         break;
1449         
1450       case Audio:
1451       case Picture:
1452       default:
1453         result = CVariant(CVariant::VariantTypeNull);
1454         break;
1455     }
1456   }
1457   else if (property.Equals("subtitles"))
1458   {
1459     result = CVariant(CVariant::VariantTypeArray);
1460     switch (player)
1461     {
1462       case Video:
1463         if (g_application.m_pPlayer)
1464         {
1465           for (int index = 0; index < g_application.m_pPlayer->GetSubtitleCount(); index++)
1466           {
1467             CVariant subtitle(CVariant::VariantTypeObject);
1468             subtitle["index"] = index;
1469             CStdString value;
1470             g_application.m_pPlayer->GetSubtitleName(index, value);
1471             subtitle["name"] = value;
1472             value.Empty();
1473             g_application.m_pPlayer->GetSubtitleLanguage(index, value);
1474             subtitle["language"] = value;
1475
1476             result.append(subtitle);
1477           }
1478         }
1479         break;
1480         
1481       case Audio:
1482       case Picture:
1483       default:
1484         break;
1485     }
1486   }
1487   else if (property.Equals("live"))
1488     result = IsPVRChannel();
1489   else
1490     return InvalidParams;
1491
1492   return OK;
1493 }
1494
1495 int CPlayerOperations::ParseRepeatState(const CVariant &repeat)
1496 {
1497   REPEAT_STATE state = REPEAT_NONE;
1498   std::string strState = repeat.asString();
1499
1500   if (strState.compare("one") == 0)
1501     state = REPEAT_ONE;
1502   else if (strState.compare("all") == 0)
1503     state = REPEAT_ALL;
1504
1505   return state;
1506 }
1507
1508 double CPlayerOperations::ParseTimeInSeconds(const CVariant &time)
1509 {
1510   double seconds = 0.0;
1511   if (time.isObject())
1512   {
1513     if (time.isMember("hours"))
1514       seconds += time["hours"].asInteger() * 60 * 60;
1515     if (time.isMember("minutes"))
1516       seconds += time["minutes"].asInteger() * 60;
1517     if (time.isMember("seconds"))
1518       seconds += time["seconds"].asInteger();
1519     if (time.isMember("milliseconds"))
1520       seconds += time["milliseconds"].asDouble() / 1000.0;
1521   }
1522
1523   return seconds;
1524 }
1525
1526 bool CPlayerOperations::IsPVRChannel()
1527 {
1528   return g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio();
1529 }
1530
1531 bool CPlayerOperations::GetCurrentEpg(EPG::CEpgInfoTag &epg)
1532 {
1533   if (!g_PVRManager.IsPlayingTV() && !g_PVRManager.IsPlayingRadio())
1534     return false;
1535
1536   CPVRChannelPtr currentChannel;
1537   if (!g_PVRManager.GetCurrentChannel(currentChannel))
1538     return false;
1539
1540   if (!currentChannel->GetEPGNow(epg))
1541     return false;
1542
1543   return true;
1544 }