only call IPlayerCallback::OnPlayBackSpeedChanged if the speed has actually changed
[vuplus_xbmc] / xbmc / interfaces / json-rpc / PlayerOperations.cpp
1 /*
2  *      Copyright (C) 2005-2010 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, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "PlayerOperations.h"
23 #include "Application.h"
24 #include "Util.h"
25 #include "PlayListPlayer.h"
26 #include "guilib/GUIWindowManager.h"
27 #include "GUIUserMessages.h"
28 #include "pictures/GUIWindowSlideShow.h"
29 #include "interfaces/Builtins.h"
30 #include "PlayListPlayer.h"
31 #include "PartyModeManager.h"
32 #include "ApplicationMessenger.h"
33 #include "FileItem.h"
34
35 using namespace JSONRPC;
36 using namespace PLAYLIST;
37
38 JSON_STATUS CPlayerOperations::GetActivePlayers(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
39 {
40   int activePlayers = GetActivePlayers();
41   result = CVariant(CVariant::VariantTypeArray);
42
43   if (activePlayers & Video)
44   {
45     CVariant video = CVariant(CVariant::VariantTypeObject);
46     video["playerid"] = GetPlaylist(Video);
47     video["type"] = "video";
48     result.append(video);
49   }
50   if (activePlayers & Audio)
51   {
52     CVariant audio = CVariant(CVariant::VariantTypeObject);
53     audio["playerid"] = GetPlaylist(Audio);
54     audio["type"] = "audio";
55     result.append(audio);
56   }
57   if (activePlayers & Picture)
58   {
59     CVariant picture = CVariant(CVariant::VariantTypeObject);
60     picture["playerid"] = GetPlaylist(Picture);
61     picture["type"] = "picture";
62     result.append(picture);
63   }
64
65   return OK;
66 }
67
68 JSON_STATUS CPlayerOperations::GetProperties(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
69 {
70   PlayerType player = GetPlayer(parameterObject["playerid"]);
71
72   CVariant properties = CVariant(CVariant::VariantTypeObject);
73   for (unsigned int index = 0; index < parameterObject["properties"].size(); index++)
74   {
75     CStdString propertyName = parameterObject["properties"][index].asString();
76     CVariant property;
77     JSON_STATUS ret;
78     if ((ret = GetPropertyValue(player, propertyName, property)) != OK)
79       return ret;
80
81     properties[propertyName] = property;
82   }
83
84   result = properties;
85
86   return OK;
87 }
88
89 JSON_STATUS CPlayerOperations::PlayPause(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
90 {
91   CGUIWindowSlideShow *slideshow = NULL;
92   switch (GetPlayer(parameterObject["playerid"]))
93   {
94     case Video:
95     case Audio:
96       CBuiltins::Execute("playercontrol(play)");
97       result["speed"] = g_application.IsPaused() ? 0 : g_application.GetPlaySpeed();
98       return OK;
99
100     case Picture:
101       SendSlideshowAction(ACTION_PAUSE);
102       slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
103       if (slideshow && slideshow->IsPlaying() && !slideshow->IsPaused())
104         result["speed"] = slideshow->GetDirection();
105       else
106         result["speed"] = 0;
107       return OK;
108
109     case None:
110     default:
111       return FailedToExecute;
112   }
113 }
114
115 JSON_STATUS CPlayerOperations::Stop(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
116 {
117   switch (GetPlayer(parameterObject["playerid"]))
118   {
119     case Video:
120     case Audio:
121       g_application.getApplicationMessenger().SendAction(CAction(ACTION_STOP));
122       return ACK;
123
124     case Picture:
125       SendSlideshowAction(ACTION_STOP);
126       return ACK;
127
128     case None:
129     default:
130       return FailedToExecute;
131   }
132 }
133
134 JSON_STATUS CPlayerOperations::SetSpeed(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
135 {
136   int speed;
137   switch (GetPlayer(parameterObject["playerid"]))
138   {
139     case Video:
140     case Audio:
141       if (parameterObject["speed"].isInteger())
142       {
143         speed = (int)parameterObject["speed"].asInteger();
144         if (speed != 0)
145         {
146           // If the player is paused we first need to unpause
147           if (g_application.IsPaused())
148             g_application.m_pPlayer->Pause();
149           g_application.SetPlaySpeed(speed);
150         }
151         else
152           g_application.m_pPlayer->Pause();
153       }
154       else if (parameterObject["speed"].isString())
155       {
156         speed = g_application.GetPlaySpeed();
157         if (parameterObject["speed"].asString().compare("increment") == 0)
158           CBuiltins::Execute("playercontrol(forward)");
159         else
160           CBuiltins::Execute("playercontrol(rewind)");
161       }
162       else
163         return InvalidParams;
164
165       result["speed"] = g_application.IsPaused() ? 0 : g_application.GetPlaySpeed();
166       return OK;
167
168     case Picture:
169     case None:
170     default:
171       return FailedToExecute;
172   }
173 }
174
175 JSON_STATUS CPlayerOperations::Seek(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
176 {
177   PlayerType player = GetPlayer(parameterObject["playerid"]);
178   switch (player)
179   {
180     case Video:
181     case Audio:
182       if (parameterObject["value"].isObject())
183         g_application.SeekTime(((parameterObject["value"]["hours"].asInteger() * 60) + parameterObject["value"]["minutes"].asInteger()) * 60 + 
184           parameterObject["value"]["seconds"].asInteger() + ((double)parameterObject["value"]["milliseconds"].asInteger() / 1000.0));
185       else if (IsType(parameterObject["value"], NumberValue))
186         g_application.SeekPercentage(parameterObject["value"].asFloat());
187       else if (parameterObject["value"].isString())
188       {
189         CStdString step = parameterObject["value"].asString();
190         if (step.Equals("smallforward"))
191           CBuiltins::Execute("playercontrol(smallskipforward)");
192         else if (step.Equals("smallbackward"))
193           CBuiltins::Execute("playercontrol(smallskipbackward)");
194         else if (step.Equals("bigforward"))
195           CBuiltins::Execute("playercontrol(bigskipforward)");
196         else if (step.Equals("bigbackward"))
197           CBuiltins::Execute("playercontrol(bigskipbackward)");
198         else
199           return InvalidParams;
200       }
201       else
202         return InvalidParams;
203
204       GetPropertyValue(player, "percentage", result["percentage"]);
205       GetPropertyValue(player, "time", result["time"]);
206       GetPropertyValue(player, "totaltime", result["totaltime"]);
207       return OK;
208
209     case Picture:
210     case None:
211     default:
212       return FailedToExecute;
213   }
214 }
215
216 JSON_STATUS CPlayerOperations::MoveLeft(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
217 {
218   switch (GetPlayer(parameterObject["playerid"]))
219   {
220     case Picture:
221       SendSlideshowAction(ACTION_MOVE_LEFT);
222       return ACK;
223
224     case Video:
225     case Audio:
226     case None:
227     default:
228       return FailedToExecute;
229   }
230 }
231
232 JSON_STATUS CPlayerOperations::MoveRight(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
233 {
234   switch (GetPlayer(parameterObject["playerid"]))
235   {
236     case Picture:
237       SendSlideshowAction(ACTION_MOVE_RIGHT);
238       return ACK;
239
240     case Video:
241     case Audio:
242     case None:
243     default:
244       return FailedToExecute;
245   }
246 }
247
248 JSON_STATUS CPlayerOperations::MoveDown(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
249 {
250   switch (GetPlayer(parameterObject["playerid"]))
251   {
252     case Picture:
253       SendSlideshowAction(ACTION_MOVE_DOWN);
254       return ACK;
255
256     case Video:
257     case Audio:
258     case None:
259     default:
260       return FailedToExecute;
261   }
262 }
263
264 JSON_STATUS CPlayerOperations::MoveUp(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
265 {
266   switch (GetPlayer(parameterObject["playerid"]))
267   {
268     case Picture:
269       SendSlideshowAction(ACTION_MOVE_UP);
270       return ACK;
271
272     case Video:
273     case Audio:
274     case None:
275     default:
276       return FailedToExecute;
277   }
278 }
279
280 JSON_STATUS CPlayerOperations::ZoomOut(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
281 {
282   switch (GetPlayer(parameterObject["playerid"]))
283   {
284     case Picture:
285       SendSlideshowAction(ACTION_ZOOM_OUT);
286       return ACK;
287
288     case Video:
289     case Audio:
290     case None:
291     default:
292       return FailedToExecute;
293   }
294 }
295
296 JSON_STATUS CPlayerOperations::ZoomIn(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
297 {
298   switch (GetPlayer(parameterObject["playerid"]))
299   {
300     case Picture:
301       SendSlideshowAction(ACTION_ZOOM_IN);
302       return ACK;
303
304     case Video:
305     case Audio:
306     case None:
307     default:
308       return FailedToExecute;
309   }
310 }
311
312 JSON_STATUS CPlayerOperations::Zoom(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
313 {
314   switch (GetPlayer(parameterObject["playerid"]))
315   {
316     case Picture:
317       SendSlideshowAction(ACTION_ZOOM_LEVEL_NORMAL + ((int)parameterObject["value"].asInteger() - 1));
318       return ACK;
319
320     case Video:
321     case Audio:
322     case None:
323     default:
324       return FailedToExecute;
325   }
326 }
327
328 JSON_STATUS CPlayerOperations::Rotate(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
329 {
330   switch (GetPlayer(parameterObject["playerid"]))
331   {
332     case Picture:
333       SendSlideshowAction(ACTION_ROTATE_PICTURE);
334       return ACK;
335
336     case Video:
337     case Audio:
338     case None:
339     default:
340       return FailedToExecute;
341   }
342 }
343
344 JSON_STATUS CPlayerOperations::Open(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
345 {
346   if (parameterObject["item"].isObject() && parameterObject["item"].isMember("playlistid"))
347   {
348     int playlistid = (int)parameterObject["item"]["playlistid"].asInteger();
349     switch (playlistid)
350     {
351       case PLAYLIST_MUSIC:
352       case PLAYLIST_VIDEO:
353         if (g_playlistPlayer.GetCurrentPlaylist() != playlistid)
354           g_playlistPlayer.SetCurrentPlaylist(playlistid);
355
356         g_application.getApplicationMessenger().PlayListPlayerPlay((int)parameterObject["item"]["position"].asInteger());
357
358         OnPlaylistChanged();
359         break;
360
361       case PLAYLIST_PICTURE:
362         return StartSlideshow();
363         break;
364     }
365
366     return ACK;
367   }
368   else if (parameterObject["item"].isObject() && parameterObject["item"].isMember("path"))
369   {
370     CStdString exec = "slideShow(";
371
372     exec += parameterObject["item"]["path"].asString();
373
374     if (parameterObject["item"]["random"].asBoolean())
375       exec += ", random";
376     else
377       exec += ", notrandom";
378
379     if (parameterObject["item"]["recursive"].asBoolean())
380       exec += ", recursive";
381
382     exec += ")";
383     ThreadMessage msg = { TMSG_EXECUTE_BUILT_IN, (DWORD)0, (DWORD)0, exec };
384     g_application.getApplicationMessenger().SendMessage(msg);
385
386     return ACK;
387   }
388   else
389   {
390     CFileItemList list;
391     if (FillFileItemList(parameterObject["item"], list) && list.Size() > 0)
392     {
393       bool slideshow = true;
394       for (int index = 0; index < list.Size(); index++)
395       {
396         if (!list[index]->HasPictureInfoTag())
397         {
398           slideshow = false;
399           break;
400         }
401       }
402
403       if (slideshow)
404       {
405         CGUIWindowSlideShow *slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
406         if (!slideshow)
407           return FailedToExecute;
408
409         SendSlideshowAction(ACTION_STOP);
410         slideshow->Reset();
411         for (int index = 0; index < list.Size(); index++)
412           slideshow->Add(list[index].get());
413
414         return StartSlideshow();
415       }
416       else
417         g_application.getApplicationMessenger().MediaPlay(list);
418
419       return ACK;
420     }
421     else
422       return InvalidParams;
423   }
424
425   return InvalidParams;
426 }
427
428 JSON_STATUS CPlayerOperations::GoPrevious(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
429 {
430   switch (GetPlayer(parameterObject["playerid"]))
431   {
432     case Video:
433     case Audio:
434       g_application.getApplicationMessenger().SendAction(CAction(ACTION_PREV_ITEM));
435       return ACK;
436
437     case Picture:
438       SendSlideshowAction(ACTION_PREV_PICTURE);
439       return ACK;
440
441     case None:
442     default:
443       return FailedToExecute;
444   }
445 }
446
447 JSON_STATUS CPlayerOperations::GoNext(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
448 {
449   switch (GetPlayer(parameterObject["playerid"]))
450   {
451     case Video:
452     case Audio:
453       g_application.getApplicationMessenger().SendAction(CAction(ACTION_NEXT_ITEM));
454       return ACK;
455
456     case Picture:
457       SendSlideshowAction(ACTION_NEXT_PICTURE);
458       return ACK;
459
460     case None:
461     default:
462       return FailedToExecute;
463   }
464 }
465
466 JSON_STATUS CPlayerOperations::GoTo(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
467 {
468   int position = (int)parameterObject["position"].asInteger();
469   switch (GetPlayer(parameterObject["playerid"]))
470   {
471     case Video:
472     case Audio:
473       g_application.getApplicationMessenger().PlayListPlayerPlay(position);
474       break;
475
476     case Picture:
477     case None:
478     default:
479       return FailedToExecute;
480   }
481
482   OnPlaylistChanged();
483   return ACK;
484 }
485
486 JSON_STATUS CPlayerOperations::Shuffle(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
487 {
488   CGUIWindowSlideShow *slideshow = NULL;
489   switch (GetPlayer(parameterObject["playerid"]))
490   {
491     case Video:
492     case Audio:
493       g_application.getApplicationMessenger().PlayListPlayerShuffle(GetPlaylist(GetPlayer(parameterObject["playerid"])), true);
494       OnPlaylistChanged();
495       break;
496
497     case Picture:
498       slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
499       if (slideshow && !slideshow->IsShuffled())
500         slideshow->Shuffle();
501       else if (!slideshow)
502         return FailedToExecute;
503       break;
504
505     default:
506       return FailedToExecute;
507   }
508   return ACK;
509 }
510
511 JSON_STATUS CPlayerOperations::UnShuffle(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
512 {
513   switch (GetPlayer(parameterObject["playerid"]))
514   {
515     case Video:
516     case Audio:
517       g_application.getApplicationMessenger().PlayListPlayerShuffle(GetPlaylist(GetPlayer(parameterObject["playerid"])), false);
518       OnPlaylistChanged();
519       break;
520
521     case Picture:
522     default:
523       return FailedToExecute;
524   }
525   return ACK;
526 }
527
528 JSON_STATUS CPlayerOperations::Repeat(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
529 {
530   REPEAT_STATE state = REPEAT_NONE;
531   std::string strState = parameterObject["state"].asString();
532   
533   switch (GetPlayer(parameterObject["playerid"]))
534   {
535     case Video:
536     case Audio:
537       if (strState.compare("one") == 0)
538         state = REPEAT_ONE;
539       else if (strState.compare("all") == 0)
540         state = REPEAT_ALL;
541
542       g_application.getApplicationMessenger().PlayListPlayerRepeat(GetPlaylist(GetPlayer(parameterObject["playerid"])), state);
543       OnPlaylistChanged();
544       break;
545
546     case Picture:
547     default:
548       return FailedToExecute;
549   }
550
551   return ACK;
552 }
553
554 JSON_STATUS CPlayerOperations::SetAudioStream(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
555 {
556   switch (GetPlayer(parameterObject["playerid"]))
557   {
558     case Video:
559       if (g_application.m_pPlayer)
560       {
561         int index = -1;
562         if (parameterObject["stream"].isString())
563         {
564           std::string action = parameterObject["stream"].asString();
565           if (action.compare("previous") == 0)
566           {
567             index = g_application.m_pPlayer->GetAudioStream() - 1;
568             if (index < 0)
569               index = g_application.m_pPlayer->GetAudioStreamCount() - 1;
570           }
571           else if (action.compare("next") == 0)
572           {
573             index = g_application.m_pPlayer->GetAudioStream() + 1;
574             if (index >= g_application.m_pPlayer->GetAudioStreamCount())
575               index = 0;
576           }
577           else
578             return InvalidParams;
579         }
580         else if (parameterObject["stream"].isInteger())
581           index = (int)parameterObject["stream"].asInteger();
582
583         if (index < 0 || g_application.m_pPlayer->GetAudioStreamCount() <= index)
584           return InvalidParams;
585
586         g_application.m_pPlayer->SetAudioStream(index);
587       }
588       else
589         return FailedToExecute;
590       break;
591       
592     case Audio:
593     case Picture:
594     default:
595       return FailedToExecute;
596   }
597
598   return ACK;
599 }
600
601 JSON_STATUS CPlayerOperations::SetSubtitle(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant &parameterObject, CVariant &result)
602 {
603   switch (GetPlayer(parameterObject["playerid"]))
604   {
605     case Video:
606       if (g_application.m_pPlayer)
607       {
608         int index = -1;
609         if (parameterObject["subtitle"].isString())
610         {
611           std::string action = parameterObject["subtitle"].asString();
612           if (action.compare("previous") == 0)
613           {
614             index = g_application.m_pPlayer->GetSubtitle() - 1;
615             if (index < 0)
616               index = g_application.m_pPlayer->GetSubtitleCount() - 1;
617           }
618           else if (action.compare("next") == 0)
619           {
620             index = g_application.m_pPlayer->GetSubtitle() + 1;
621             if (index >= g_application.m_pPlayer->GetSubtitleCount())
622               index = 0;
623           }
624           else if (action.compare("off") == 0)
625           {
626             g_application.m_pPlayer->SetSubtitleVisible(false);
627             return ACK;
628           }
629           else if (action.compare("on") == 0)
630           {
631             g_application.m_pPlayer->SetSubtitleVisible(true);
632             return ACK;
633           }
634           else
635             return InvalidParams;
636         }
637         else if (parameterObject["subtitle"].isInteger())
638           index = (int)parameterObject["subtitle"].asInteger();
639
640         if (index < 0 || g_application.m_pPlayer->GetSubtitleCount() <= index)
641           return InvalidParams;
642
643         g_application.m_pPlayer->SetSubtitle(index);
644       }
645       else
646         return FailedToExecute;
647       break;
648       
649     case Audio:
650     case Picture:
651     default:
652       return FailedToExecute;
653   }
654
655   return ACK;
656 }
657
658 int CPlayerOperations::GetActivePlayers()
659 {
660   int activePlayers = 0;
661
662   if (g_application.IsPlayingVideo())
663     activePlayers |= Video;
664   if (g_application.IsPlayingAudio())
665     activePlayers |= Audio;
666   if (g_windowManager.IsWindowActive(WINDOW_SLIDESHOW))
667     activePlayers |= Picture;
668
669   return activePlayers;
670 }
671
672 PlayerType CPlayerOperations::GetPlayer(const CVariant &player)
673 {
674   int activePlayers = GetActivePlayers();
675   int playerID;
676
677   switch ((int)player.asInteger())
678   {
679     case PLAYLIST_VIDEO:
680       playerID = Video;
681       break;
682
683     case PLAYLIST_MUSIC:
684       playerID = Audio;
685       break;
686
687     case PLAYLIST_PICTURE:
688       playerID = Picture;
689       break;
690
691     default:
692       playerID = PlayerImplicit;
693       break;
694   }
695
696   int choosenPlayer = playerID & activePlayers;
697
698   // Implicit order
699   if (choosenPlayer & Video)
700     return Video;
701   else if (choosenPlayer & Audio)
702     return Audio;
703   else if (choosenPlayer & Picture)
704     return Picture;
705   else
706     return None;
707 }
708
709 int CPlayerOperations::GetPlaylist(PlayerType player)
710 {
711   switch (player)
712   {
713     case Video:
714       return PLAYLIST_VIDEO;
715
716     case Audio:
717       return PLAYLIST_MUSIC;
718
719     case Picture:
720       return PLAYLIST_PICTURE;
721
722     default:
723       return PLAYLIST_NONE;
724   }
725 }
726
727 JSON_STATUS CPlayerOperations::StartSlideshow()
728 {
729   CGUIWindowSlideShow *slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
730   if (!slideshow && slideshow->NumSlides() <= 0)
731     return FailedToExecute;
732
733   if (g_application.IsPlayingVideo())
734     g_application.StopPlaying();
735
736   g_graphicsContext.Lock();
737
738   g_application.WakeUpScreenSaverAndDPMS();
739   slideshow->StartSlideShow();
740
741   if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW)
742     g_windowManager.ActivateWindow(WINDOW_SLIDESHOW);
743
744   g_graphicsContext.Unlock();
745
746   return ACK;
747 }
748
749 void CPlayerOperations::SendSlideshowAction(int actionID)
750 {
751   g_application.getApplicationMessenger().SendAction(CAction(actionID), WINDOW_SLIDESHOW);
752 }
753
754 void CPlayerOperations::OnPlaylistChanged()
755 {
756   CGUIMessage msg(GUI_MSG_PLAYLIST_CHANGED, 0, 0);
757   g_windowManager.SendThreadMessage(msg);
758 }
759
760 JSON_STATUS CPlayerOperations::GetPropertyValue(PlayerType player, const CStdString &property, CVariant &result)
761 {
762   if (player == None)
763     return FailedToExecute;
764
765   int playlist = GetPlaylist(player);
766
767   if (property.Equals("type"))
768   {
769     switch (player)
770     {
771       case Video:
772         result = "video";
773         break;
774
775       case Audio:
776         result = "audio";
777         break;
778
779       case Picture:
780         result = "picture";
781         break;
782
783       default:
784         return FailedToExecute;
785     }
786   }
787   else if (property.Equals("partymode"))
788   {
789     switch (player)
790     {
791       case Video:
792       case Audio:
793         result = g_partyModeManager.IsEnabled();
794         break;
795
796       case Picture:
797         result = false;
798         break;
799
800       default:
801         return FailedToExecute;
802     }
803   }
804   else if (property.Equals("speed"))
805   {
806     CGUIWindowSlideShow *slideshow = NULL;
807     switch (player)
808     {
809       case Video:
810       case Audio:
811         result = g_application.IsPaused() ? 0 : g_application.GetPlaySpeed();
812         break;
813
814       case Picture:
815         slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
816         if (slideshow && slideshow->IsPlaying() && !slideshow->IsPaused())
817           result = slideshow->GetDirection();
818         else
819           result = 0;
820         break;
821
822       default:
823         return FailedToExecute;
824     }
825   }
826   else if (property.Equals("time"))
827   {
828     switch (player)
829     {
830       case Video:
831       case Audio:
832         MillisecondsToTimeObject((int)(g_application.GetTime() * 1000.0), result);
833         break;
834
835       case Picture:
836         MillisecondsToTimeObject(0, result);
837         break;
838
839       default:
840         return FailedToExecute;
841     }
842   }
843   else if (property.Equals("percentage"))
844   {
845     CGUIWindowSlideShow *slideshow = NULL;
846     switch (player)
847     {
848       case Video:
849       case Audio:
850         result = g_application.GetPercentage();
851         break;
852
853       case Picture:
854         slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
855         if (slideshow && slideshow->NumSlides() > 0)
856           result = (double)slideshow->CurrentSlide() / slideshow->NumSlides();
857         else
858           result = 0.0;
859         break;
860
861       default:
862         return FailedToExecute;
863     }
864   }
865   else if (property.Equals("totaltime"))
866   {
867     switch (player)
868     {
869       case Video:
870       case Audio:
871         MillisecondsToTimeObject((int)(g_application.GetTotalTime() * 1000.0), result);
872         break;
873
874       case Picture:
875         MillisecondsToTimeObject(0, result);
876         break;
877
878       default:
879         return FailedToExecute;
880     }
881   }
882   else if (property.Equals("playlistid"))
883   {
884     result = playlist;
885   }
886   else if (property.Equals("position"))
887   {
888     CGUIWindowSlideShow *slideshow = NULL;
889     switch (player)
890     {
891       case Video:
892       case Audio:
893         if (g_playlistPlayer.GetCurrentPlaylist() == playlist)
894           result = g_playlistPlayer.GetCurrentSong();
895         else
896           result = -1;
897         break;
898
899       case Picture:
900         slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
901         if (slideshow && slideshow->IsPlaying())
902           result = slideshow->CurrentSlide() - 1;
903         else
904           result = -1;
905         break;
906
907       default:
908         result = -1;
909         break;
910     }
911   }
912   else if (property.Equals("repeat"))
913   {
914     switch (player)
915     {
916       case Video:
917       case Audio:
918         switch (g_playlistPlayer.GetRepeat(playlist))
919         {
920         case REPEAT_ONE:
921           result = "one";
922           break;
923         case REPEAT_ALL:
924           result = "all";
925           break;
926         default:
927           result = "off";
928           break;
929         }
930         break;
931
932       case Picture:
933       default:
934         result = "off";
935         break;
936     }
937   }
938   else if (property.Equals("shuffled"))
939   {
940     CGUIWindowSlideShow *slideshow = NULL;
941     switch (player)
942     {
943       case Video:
944       case Audio:
945         result = g_playlistPlayer.IsShuffled(playlist);
946         break;
947
948       case Picture:
949         slideshow = (CGUIWindowSlideShow*)g_windowManager.GetWindow(WINDOW_SLIDESHOW);
950         if (slideshow && slideshow->IsPlaying())
951           result = slideshow->IsShuffled();
952         else
953           result = -1;
954         break;
955
956       default:
957         result = -1;
958         break;
959     }
960   }
961   else if (property.Equals("canseek"))
962   {
963     switch (player)
964     {
965       case Video:
966       case Audio:
967         if (g_application.m_pPlayer)
968           result = g_application.m_pPlayer->CanSeek();
969         else
970           result = false;
971         break;
972
973       case Picture:
974       default:
975         result = false;
976         break;
977     }
978   }
979   else if (property.Equals("canchangespeed"))
980   {
981     switch (player)
982     {
983       case Video:
984       case Audio:
985         result = true;
986         break;
987
988       case Picture:
989       default:
990         result = false;
991         break;
992     }
993   }
994   else if (property.Equals("canmove"))
995   {
996     switch (player)
997     {
998       case Picture:
999         result = true;
1000         break;
1001
1002       case Video:
1003       case Audio:
1004       default:
1005         result = false;
1006         break;
1007     }
1008   }
1009   else if (property.Equals("canzoom"))
1010   {
1011     switch (player)
1012     {
1013       case Picture:
1014         result = true;
1015         break;
1016
1017       case Video:
1018       case Audio:
1019       default:
1020         result = false;
1021         break;
1022     }
1023   }
1024   else if (property.Equals("canrotate"))
1025   {
1026     switch (player)
1027     {
1028       case Picture:
1029         result = true;
1030         break;
1031
1032       case Video:
1033       case Audio:
1034       default:
1035         result = false;
1036         break;
1037     }
1038   }
1039   else if (property.Equals("canshuffle"))
1040   {
1041     switch (player)
1042     {
1043       case Video:
1044       case Audio:
1045       case Picture:
1046         result = true;
1047         break;
1048
1049       default:
1050         result = false;
1051         break;
1052     }
1053   }
1054   else if (property.Equals("canrepeat"))
1055   {
1056     switch (player)
1057     {
1058       case Video:
1059       case Audio:
1060         result = true;
1061         break;
1062
1063       case Picture:
1064       default:
1065         result = false;
1066         break;
1067     }
1068   }
1069   else if (property.Equals("currentaudiostream"))
1070   {
1071     switch (player)
1072     {
1073       case Video:
1074       case Audio:
1075         if (g_application.m_pPlayer)
1076         {
1077           result = CVariant(CVariant::VariantTypeObject);
1078           int index = g_application.m_pPlayer->GetAudioStream();
1079           if (index >= 0)
1080           {
1081             result["index"] = index;
1082             CStdString value;
1083             g_application.m_pPlayer->GetAudioStreamName(index, value);
1084             result["name"] = value;
1085             value.Empty();
1086             g_application.m_pPlayer->GetAudioStreamLanguage(index, value);
1087             result["language"] = value;
1088           }
1089           result["codec"] = g_application.m_pPlayer->GetAudioCodecName();
1090           result["bitrate"] = g_application.m_pPlayer->GetAudioBitrate();
1091           result["channels"] = g_application.m_pPlayer->GetChannels();
1092         }
1093         else
1094           result = CVariant(CVariant::VariantTypeNull);
1095         break;
1096         
1097       case Picture:
1098       default:
1099         result = CVariant(CVariant::VariantTypeNull);
1100         break;
1101     }
1102   }
1103   else if (property.Equals("audiostreams"))
1104   {
1105     result = CVariant(CVariant::VariantTypeArray);
1106     switch (player)
1107     {
1108       case Video:
1109         if (g_application.m_pPlayer)
1110         {
1111           for (int index = 0; index < g_application.m_pPlayer->GetAudioStreamCount(); index++)
1112           {
1113             CVariant audioStream(CVariant::VariantTypeObject);
1114             audioStream["index"] = index;
1115             CStdString value;
1116             g_application.m_pPlayer->GetAudioStreamName(index, value);
1117             audioStream["name"] = value;
1118             value.Empty();
1119             g_application.m_pPlayer->GetAudioStreamLanguage(index, value);
1120             audioStream["language"] = value;
1121
1122             result.append(audioStream);
1123           }
1124         }
1125         break;
1126         
1127       case Audio:
1128       case Picture:
1129       default:
1130         break;
1131     }
1132   }
1133   else if (property.Equals("subtitleenabled"))
1134   {
1135     switch (player)
1136     {
1137       case Video:
1138         if (g_application.m_pPlayer)
1139           result = g_application.m_pPlayer->GetSubtitleVisible();
1140         break;
1141         
1142       case Audio:
1143       case Picture:
1144       default:
1145         result = false;
1146         break;
1147     }
1148   }
1149   else if (property.Equals("currentsubtitle"))
1150   {
1151     switch (player)
1152     {
1153       case Video:
1154         if (g_application.m_pPlayer)
1155         {
1156           result = CVariant(CVariant::VariantTypeObject);
1157           int index = g_application.m_pPlayer->GetSubtitle();
1158           if (index >= 0)
1159           {
1160             result["index"] = index;
1161             CStdString value;
1162             g_application.m_pPlayer->GetSubtitleName(index, value);
1163             result["name"] = value;
1164             value.Empty();
1165             g_application.m_pPlayer->GetSubtitleLanguage(index, value);
1166             result["language"] = value;
1167           }
1168         }
1169         else
1170           result = CVariant(CVariant::VariantTypeNull);
1171         break;
1172         
1173       case Audio:
1174       case Picture:
1175       default:
1176         result = CVariant(CVariant::VariantTypeNull);
1177         break;
1178     }
1179   }
1180   else if (property.Equals("subtitles"))
1181   {
1182     result = CVariant(CVariant::VariantTypeArray);
1183     switch (player)
1184     {
1185       case Video:
1186         if (g_application.m_pPlayer)
1187         {
1188           for (int index = 0; index < g_application.m_pPlayer->GetSubtitleCount(); index++)
1189           {
1190             CVariant subtitle(CVariant::VariantTypeObject);
1191             subtitle["index"] = index;
1192             CStdString value;
1193             g_application.m_pPlayer->GetSubtitleName(index, value);
1194             subtitle["name"] = value;
1195             value.Empty();
1196             g_application.m_pPlayer->GetSubtitleLanguage(index, value);
1197             subtitle["language"] = value;
1198
1199             result.append(subtitle);
1200           }
1201         }
1202         break;
1203         
1204       case Audio:
1205       case Picture:
1206       default:
1207         break;
1208     }
1209   }
1210   else
1211     return InvalidParams;
1212
1213   return OK;
1214 }