Merge pull request #4314 from MartijnKaijser/beta1
[vuplus_xbmc] / xbmc / video / windows / GUIWindowFullScreen.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://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 "threads/SystemClock.h"
22 #include "system.h"
23 #include "GUIWindowFullScreen.h"
24 #include "Application.h"
25 #include "ApplicationMessenger.h"
26 #include "Util.h"
27 #ifdef HAS_VIDEO_PLAYBACK
28 #include "cores/VideoRenderers/RenderManager.h"
29 #endif
30 #include "GUIInfoManager.h"
31 #include "guilib/GUIProgressControl.h"
32 #include "guilib/GUIAudioManager.h"
33 #include "guilib/GUILabelControl.h"
34 #include "video/dialogs/GUIDialogVideoOSD.h"
35 #include "guilib/GUIFontManager.h"
36 #include "guilib/GUITextLayout.h"
37 #include "guilib/GUIWindowManager.h"
38 #include "guilib/Key.h"
39 #include "video/dialogs/GUIDialogFullScreenInfo.h"
40 #include "dialogs/GUIDialogNumeric.h"
41 #include "settings/DisplaySettings.h"
42 #include "settings/MediaSettings.h"
43 #include "settings/Settings.h"
44 #include "guilib/GUISelectButtonControl.h"
45 #include "FileItem.h"
46 #include "video/VideoReferenceClock.h"
47 #include "settings/AdvancedSettings.h"
48 #include "utils/CPUInfo.h"
49 #include "guilib/LocalizeStrings.h"
50 #include "threads/SingleLock.h"
51 #include "utils/log.h"
52 #include "utils/TimeUtils.h"
53 #include "utils/URIUtils.h"
54 #include "utils/StringUtils.h"
55 #include "XBDateTime.h"
56 #include "input/ButtonTranslator.h"
57 #include "pvr/PVRManager.h"
58 #include "pvr/channels/PVRChannelGroupsContainer.h"
59 #include "windowing/WindowingFactory.h"
60 #include "cores/IPlayer.h"
61 #include "filesystem/File.h"
62
63 #include <stdio.h>
64 #include <algorithm>
65 #if defined(TARGET_DARWIN)
66 #include "linux/LinuxResourceCounter.h"
67 #endif
68
69 using namespace PVR;
70
71 #define BLUE_BAR                          0
72 #define LABEL_ROW1                       10
73 #define LABEL_ROW2                       11
74 #define LABEL_ROW3                       12
75 #define CONTROL_GROUP_CHOOSER            503
76
77 //Displays current position, visible after seek or when forced
78 //Alt, use conditional visibility Player.DisplayAfterSeek
79 #define LABEL_CURRENT_TIME               22
80
81 //Displays when video is rebuffering
82 //Alt, use conditional visibility Player.IsCaching
83 #define LABEL_BUFFERING                  24
84
85 //Progressbar used for buffering status and after seeking
86 #define CONTROL_PROGRESS                 23
87
88 #if defined(TARGET_DARWIN)
89 static CLinuxResourceCounter m_resourceCounter;
90 #endif
91
92 CGUIWindowFullScreen::CGUIWindowFullScreen(void)
93     : CGUIWindow(WINDOW_FULLSCREEN_VIDEO, "VideoFullScreen.xml")
94 {
95   m_timeCodeStamp[0] = 0;
96   m_timeCodePosition = 0;
97   m_timeCodeShow = false;
98   m_timeCodeTimeout = 0;
99   m_bShowViewModeInfo = false;
100   m_dwShowViewModeTimeout = 0;
101   m_bShowCurrentTime = false;
102   m_bGroupSelectShow = false;
103   m_loadType = KEEP_IN_MEMORY;
104   // audio
105   //  - language
106   //  - volume
107   //  - stream
108
109   // video
110   //  - Create Bookmark (294)
111   //  - Cycle bookmarks (295)
112   //  - Clear bookmarks (296)
113   //  - jump to specific time
114   //  - slider
115   //  - av delay
116
117   // subtitles
118   //  - delay
119   //  - language
120
121 }
122
123 CGUIWindowFullScreen::~CGUIWindowFullScreen(void)
124 {}
125
126 bool CGUIWindowFullScreen::OnAction(const CAction &action)
127 {
128   if (m_timeCodePosition > 0 && action.GetButtonCode())
129   { // check whether we have a mapping in our virtual videotimeseek "window" and have a select action
130     CKey key(action.GetButtonCode());
131     CAction timeSeek = CButtonTranslator::GetInstance().GetAction(WINDOW_VIDEO_TIME_SEEK, key, false);
132     if (timeSeek.GetID() == ACTION_SELECT_ITEM)
133     {
134       SeekToTimeCodeStamp(SEEK_ABSOLUTE);
135       return true;
136     }
137   }
138
139   switch (action.GetID())
140   {
141   case ACTION_SHOW_OSD:
142     ToggleOSD();
143     return true;
144
145   case ACTION_SHOW_GUI:
146     {
147       // switch back to the menu
148       OutputDebugString("Switching to GUI\n");
149       g_windowManager.PreviousWindow();
150       OutputDebugString("Now in GUI\n");
151       return true;
152     }
153     break;
154
155   case ACTION_PLAYER_PLAY:
156   case ACTION_PAUSE:
157     if (m_timeCodePosition > 0)
158     {
159       SeekToTimeCodeStamp(SEEK_ABSOLUTE);
160       return true;
161     }
162     break;
163
164   case ACTION_STEP_BACK:
165     if (m_timeCodePosition > 0)
166       SeekToTimeCodeStamp(SEEK_RELATIVE, SEEK_BACKWARD);
167     else
168       g_application.m_pPlayer->Seek(false, false);
169     return true;
170
171   case ACTION_STEP_FORWARD:
172     if (m_timeCodePosition > 0)
173       SeekToTimeCodeStamp(SEEK_RELATIVE, SEEK_FORWARD);
174     else
175       g_application.m_pPlayer->Seek(true, false);
176     return true;
177
178   case ACTION_BIG_STEP_BACK:
179   case ACTION_CHAPTER_OR_BIG_STEP_BACK:
180     if (m_timeCodePosition > 0)
181       SeekToTimeCodeStamp(SEEK_RELATIVE, SEEK_BACKWARD);
182     else
183       g_application.m_pPlayer->Seek(false, true, action.GetID() == ACTION_CHAPTER_OR_BIG_STEP_BACK);
184     return true;
185
186   case ACTION_BIG_STEP_FORWARD:
187   case ACTION_CHAPTER_OR_BIG_STEP_FORWARD:
188     if (m_timeCodePosition > 0)
189       SeekToTimeCodeStamp(SEEK_RELATIVE, SEEK_FORWARD);
190     else
191       g_application.m_pPlayer->Seek(true, true, action.GetID() == ACTION_CHAPTER_OR_BIG_STEP_FORWARD);
192     return true;
193
194   case ACTION_NEXT_SCENE:
195     if (g_application.m_pPlayer->SeekScene(true))
196       g_infoManager.SetDisplayAfterSeek();
197     return true;
198     break;
199
200   case ACTION_PREV_SCENE:
201     if (g_application.m_pPlayer->SeekScene(false))
202       g_infoManager.SetDisplayAfterSeek();
203     return true;
204     break;
205
206   case ACTION_SHOW_OSD_TIME:
207     m_bShowCurrentTime = !m_bShowCurrentTime;
208     if(!m_bShowCurrentTime)
209       g_infoManager.SetDisplayAfterSeek(0); //Force display off
210     g_infoManager.SetShowTime(m_bShowCurrentTime);
211     return true;
212     break;
213
214   case ACTION_SHOW_INFO:
215     {
216       CGUIDialogFullScreenInfo* pDialog = (CGUIDialogFullScreenInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_FULLSCREEN_INFO);
217       if (pDialog)
218       {
219         CFileItem item(g_application.CurrentFileItem());
220         pDialog->DoModal();
221         return true;
222       }
223       break;
224     }
225
226   case REMOTE_0:
227   case REMOTE_1:
228   case REMOTE_2:
229   case REMOTE_3:
230   case REMOTE_4:
231   case REMOTE_5:
232   case REMOTE_6:
233   case REMOTE_7:
234   case REMOTE_8:
235   case REMOTE_9:
236     {
237       if (g_application.CurrentFileItem().IsLiveTV())
238       {
239         CPVRChannelPtr playingChannel;
240         if(!g_PVRManager.GetCurrentChannel(playingChannel))
241           return false;
242
243         if (action.GetID() == REMOTE_0)
244         {
245           CPVRChannelGroupPtr group = g_PVRChannelGroups->GetPreviousPlayedGroup();
246           if (group)
247           {
248             g_PVRManager.SetPlayingGroup(group);
249             CFileItemPtr fileItem = group->GetLastPlayedChannel(playingChannel->ChannelID());
250             if (fileItem && fileItem->HasPVRChannelInfoTag())
251             {
252               CLog::Log(LOGDEBUG, "%s - switch to channel number %d", __FUNCTION__, fileItem->GetPVRChannelInfoTag()->ChannelNumber());
253               g_application.OnAction(CAction(ACTION_CHANNEL_SWITCH, (float) fileItem->GetPVRChannelInfoTag()->ChannelNumber()));
254             }
255           }
256         }
257         else
258         {
259           int autoCloseTime = CSettings::Get().GetBool("pvrplayback.confirmchannelswitch") ? 0 : g_advancedSettings.m_iPVRNumericChannelSwitchTimeout;
260           CStdString strChannel = StringUtils::Format("%i", action.GetID() - REMOTE_0);
261           if (CGUIDialogNumeric::ShowAndGetNumber(strChannel, g_localizeStrings.Get(19000), autoCloseTime) || autoCloseTime)
262           {
263             int iChannelNumber = atoi(strChannel.c_str());
264             if (iChannelNumber > 0 && iChannelNumber != playingChannel->ChannelNumber())
265             {
266               CPVRChannelGroupPtr selectedGroup = g_PVRManager.GetPlayingGroup(playingChannel->IsRadio());
267               CFileItemPtr channel = selectedGroup->GetByChannelNumber(iChannelNumber);
268               if (!channel || !channel->HasPVRChannelInfoTag())
269                 return false;
270
271               g_application.OnAction(CAction(ACTION_CHANNEL_SWITCH, (float)iChannelNumber));
272             }
273           }
274         }
275       }
276       else
277       {
278         ChangetheTimeCode(action.GetID());
279       }
280       return true;
281     }
282     break;
283
284   case ACTION_ASPECT_RATIO:
285     { // toggle the aspect ratio mode (only if the info is onscreen)
286       if (m_bShowViewModeInfo)
287       {
288 #ifdef HAS_VIDEO_PLAYBACK
289         g_renderManager.SetViewMode(++CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode);
290 #endif
291       }
292       m_bShowViewModeInfo = true;
293       m_dwShowViewModeTimeout = XbmcThreads::SystemClockMillis();
294     }
295     return true;
296     break;
297   case ACTION_SMALL_STEP_BACK:
298     if (m_timeCodePosition > 0)
299       SeekToTimeCodeStamp(SEEK_RELATIVE, SEEK_BACKWARD);
300     else
301     {
302       int orgpos = (int)g_application.GetTime();
303       int jumpsize = g_advancedSettings.m_videoSmallStepBackSeconds; // secs
304       int setpos = (orgpos > jumpsize) ? orgpos - jumpsize : 0;
305       g_application.SeekTime((double)setpos);
306     }
307     return true;
308     break;
309   case ACTION_SHOW_PLAYLIST:
310     {
311       CFileItem item(g_application.CurrentFileItem());
312       if (item.HasPVRChannelInfoTag())
313         g_windowManager.ActivateWindow(WINDOW_DIALOG_PVR_OSD_CHANNELS);
314       else if (item.HasVideoInfoTag())
315         g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
316       else if (item.HasMusicInfoTag())
317         g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST);
318     }
319     return true;
320     break;
321   case ACTION_PREVIOUS_CHANNELGROUP:
322     {
323       if (g_application.CurrentFileItem().HasPVRChannelInfoTag())
324         ChangetheTVGroup(false);
325       return true;
326     }
327   case ACTION_NEXT_CHANNELGROUP:
328     {
329       if (g_application.CurrentFileItem().HasPVRChannelInfoTag())
330         ChangetheTVGroup(true);
331       return true;
332     }
333   default:
334       break;
335   }
336
337   return CGUIWindow::OnAction(action);
338 }
339
340 void CGUIWindowFullScreen::OnWindowLoaded()
341 {
342   CGUIWindow::OnWindowLoaded();
343   // override the clear colour - we must never clear fullscreen
344   m_clearBackground = 0;
345
346   CGUIProgressControl* pProgress = (CGUIProgressControl*)GetControl(CONTROL_PROGRESS);
347   if(pProgress)
348   {
349     if( pProgress->GetInfo() == 0 || !pProgress->HasVisibleCondition())
350     {
351       pProgress->SetInfo(PLAYER_PROGRESS);
352       pProgress->SetVisibleCondition("player.displayafterseek");
353       pProgress->SetVisible(true);
354     }
355   }
356
357   CGUILabelControl* pLabel = (CGUILabelControl*)GetControl(LABEL_BUFFERING);
358   if(pLabel && !pLabel->HasVisibleCondition())
359   {
360     pLabel->SetVisibleCondition("player.caching");
361     pLabel->SetVisible(true);
362   }
363
364   pLabel = (CGUILabelControl*)GetControl(LABEL_CURRENT_TIME);
365   if(pLabel && !pLabel->HasVisibleCondition())
366   {
367     pLabel->SetVisibleCondition("player.displayafterseek");
368     pLabel->SetVisible(true);
369     pLabel->SetLabel("$INFO(VIDEOPLAYER.TIME) / $INFO(VIDEOPLAYER.DURATION)");
370   }
371
372   m_showCodec.Parse("player.showcodec", GetID());
373
374   FillInTVGroups();
375 }
376
377 bool CGUIWindowFullScreen::OnMessage(CGUIMessage& message)
378 {
379   switch (message.GetMessage())
380   {
381   case GUI_MSG_WINDOW_INIT:
382     {
383       // check whether we've come back here from a window during which time we've actually
384       // stopped playing videos
385       if (message.GetParam1() == WINDOW_INVALID && !g_application.m_pPlayer->IsPlayingVideo())
386       { // why are we here if nothing is playing???
387         g_windowManager.PreviousWindow();
388         return true;
389       }
390       g_infoManager.SetShowInfo(false);
391       g_infoManager.SetShowCodec(false);
392       m_bShowCurrentTime = false;
393       m_bGroupSelectShow = false;
394       g_infoManager.SetDisplayAfterSeek(0); // Make sure display after seek is off.
395
396       // switch resolution
397       g_graphicsContext.SetFullScreenVideo(true);
398
399 #ifdef HAS_VIDEO_PLAYBACK
400       // make sure renderer is uptospeed
401       g_renderManager.Update();
402 #endif
403       // now call the base class to load our windows
404       CGUIWindow::OnMessage(message);
405
406       m_bShowViewModeInfo = false;
407
408       return true;
409     }
410   case GUI_MSG_WINDOW_DEINIT:
411     {
412       CGUIDialog *pDialog = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_OSD_TELETEXT);
413       if (pDialog) pDialog->Close(true);
414       pDialog = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_SLIDER);
415       if (pDialog) pDialog->Close(true);
416       pDialog = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OSD);
417       if (pDialog) pDialog->Close(true);
418       pDialog = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_FULLSCREEN_INFO);
419       if (pDialog) pDialog->Close(true);
420       pDialog = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_PVR_OSD_CHANNELS);
421       if (pDialog) pDialog->Close(true);
422       pDialog = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_PVR_OSD_GUIDE);
423       if (pDialog) pDialog->Close(true);
424       pDialog = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_PVR_OSD_DIRECTOR);
425       if (pDialog) pDialog->Close(true);
426       pDialog = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_PVR_OSD_CUTTER);
427       if (pDialog) pDialog->Close(true);
428       pDialog = (CGUIDialog *)g_windowManager.GetWindow(WINDOW_DIALOG_SUBTITLES);
429       if (pDialog) pDialog->Close(true);
430
431       CGUIWindow::OnMessage(message);
432
433       CSettings::Get().Save();
434
435       CSingleLock lock (g_graphicsContext);
436       g_graphicsContext.SetFullScreenVideo(false);
437       lock.Leave();
438
439 #ifdef HAS_VIDEO_PLAYBACK
440       // make sure renderer is uptospeed
441       g_renderManager.Update();
442 #endif
443       return true;
444     }
445   case GUI_MSG_CLICKED:
446     {
447       unsigned int iControl = message.GetSenderId();
448       if (iControl == CONTROL_GROUP_CHOOSER && g_PVRManager.IsStarted())
449       {
450         // Get the currently selected label of the Select button
451         CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), iControl);
452         OnMessage(msg);
453         CStdString strLabel = msg.GetLabel();
454
455         CPVRChannelPtr playingChannel;
456         if (g_PVRManager.GetCurrentChannel(playingChannel))
457         {
458           CPVRChannelGroupPtr selectedGroup = g_PVRChannelGroups->Get(playingChannel->IsRadio())->GetByName(strLabel);
459           if (selectedGroup)
460           {
461             g_PVRManager.SetPlayingGroup(selectedGroup);
462             CLog::Log(LOGDEBUG, "%s - switched to group '%s'", __FUNCTION__, selectedGroup->GroupName().c_str());
463
464             if (!selectedGroup->IsGroupMember(*playingChannel))
465             {
466               CLog::Log(LOGDEBUG, "%s - channel '%s' is not a member of '%s', switching to channel 1 of the new group",
467                   __FUNCTION__, playingChannel->ChannelName().c_str(), selectedGroup->GroupName().c_str());
468               CFileItemPtr switchChannel = selectedGroup->GetByChannelNumber(1);
469
470               if (switchChannel && switchChannel->HasPVRChannelInfoTag())
471                 g_application.OnAction(CAction(ACTION_CHANNEL_SWITCH, (float) switchChannel->GetPVRChannelInfoTag()->ChannelNumber()));
472               else
473               {
474                 CLog::Log(LOGERROR, "%s - cannot find channel '1' in group %s", __FUNCTION__, selectedGroup->GroupName().c_str());
475                 CApplicationMessenger::Get().MediaStop(false);
476               }
477             }
478           }
479           else
480           {
481             CLog::Log(LOGERROR, "%s - could not switch to group '%s'", __FUNCTION__, selectedGroup->GroupName().c_str());
482             CApplicationMessenger::Get().MediaStop(false);
483           }
484         }
485         else
486         {
487           CLog::Log(LOGERROR, "%s - cannot find the current channel", __FUNCTION__);
488           CApplicationMessenger::Get().MediaStop(false);
489         }
490
491         // hide the control and reset focus
492         m_bGroupSelectShow = false;
493         SET_CONTROL_HIDDEN(CONTROL_GROUP_CHOOSER);
494 //      SET_CONTROL_FOCUS(0, 0);
495
496         return true;
497       }
498       break;
499     }
500   case GUI_MSG_SETFOCUS:
501   case GUI_MSG_LOSTFOCUS:
502     if (message.GetSenderId() != WINDOW_FULLSCREEN_VIDEO) return true;
503     break;
504   }
505
506   return CGUIWindow::OnMessage(message);
507 }
508
509 EVENT_RESULT CGUIWindowFullScreen::OnMouseEvent(const CPoint &point, const CMouseEvent &event)
510 {
511   if (event.m_id == ACTION_MOUSE_RIGHT_CLICK)
512   { // no control found to absorb this click - go back to GUI
513     OnAction(CAction(ACTION_SHOW_GUI));
514     return EVENT_RESULT_HANDLED;
515   }
516   if (event.m_id == ACTION_MOUSE_WHEEL_UP)
517   {
518     return g_application.OnAction(CAction(ACTION_ANALOG_SEEK_FORWARD, 0.5f)) ? EVENT_RESULT_HANDLED : EVENT_RESULT_UNHANDLED;
519   }
520   if (event.m_id == ACTION_MOUSE_WHEEL_DOWN)
521   {
522     return g_application.OnAction(CAction(ACTION_ANALOG_SEEK_BACK, 0.5f)) ? EVENT_RESULT_HANDLED : EVENT_RESULT_UNHANDLED;
523   }
524   if (event.m_id >= ACTION_GESTURE_NOTIFY && event.m_id <= ACTION_GESTURE_END) // gestures
525     return EVENT_RESULT_UNHANDLED;
526   if (event.m_id != ACTION_MOUSE_MOVE || event.m_offsetX || event.m_offsetY)
527   { // some other mouse action has occurred - bring up the OSD
528     // if it is not already running
529     CGUIDialogVideoOSD *pOSD = (CGUIDialogVideoOSD *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OSD);
530     if (pOSD && !pOSD->IsDialogRunning())
531     {
532       pOSD->SetAutoClose(3000);
533       pOSD->DoModal();
534     }
535     return EVENT_RESULT_HANDLED;
536   }
537   return EVENT_RESULT_UNHANDLED;
538 }
539
540 void CGUIWindowFullScreen::FrameMove()
541 {
542   if (g_application.m_pPlayer->GetPlaySpeed() != 1)
543     g_infoManager.SetDisplayAfterSeek();
544   if (m_bShowCurrentTime)
545     g_infoManager.SetDisplayAfterSeek();
546
547   if (!g_application.m_pPlayer->HasPlayer()) return;
548
549   if( g_application.m_pPlayer->IsCaching() )
550   {
551     g_infoManager.SetDisplayAfterSeek(0); //Make sure these stuff aren't visible now
552   }
553
554   //------------------------
555   m_showCodec.Update();
556   if (m_showCodec)
557   {
558     // show audio codec info
559     CStdString strAudio, strVideo, strGeneral;
560     g_application.m_pPlayer->GetAudioInfo(strAudio);
561     {
562       CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), LABEL_ROW1);
563       msg.SetLabel(strAudio);
564       OnMessage(msg);
565     }
566     // show video codec info
567     g_application.m_pPlayer->GetVideoInfo(strVideo);
568     {
569       CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), LABEL_ROW2);
570       msg.SetLabel(strVideo);
571       OnMessage(msg);
572     }
573     // show general info
574     g_application.m_pPlayer->GetGeneralInfo(strGeneral);
575     {
576       CStdString strGeneralFPS;
577 #if defined(TARGET_DARWIN)
578       // We show CPU usage for the entire process, as it's arguably more useful.
579       double dCPU = m_resourceCounter.GetCPUUsage();
580       CStdString strCores;
581       strCores = StringUtils::Format("cpu:%.0f%%", dCPU);
582 #else
583       CStdString strCores = g_cpuInfo.GetCoresUsageString();
584 #endif
585       int    missedvblanks;
586       int    refreshrate;
587       double clockspeed;
588       CStdString strClock;
589
590       if (g_VideoReferenceClock.GetClockInfo(missedvblanks, clockspeed, refreshrate))
591         strClock = StringUtils::Format("S( refresh:%i missed:%i speed:%+.3f%% %s )"
592                                        , refreshrate
593                                        , missedvblanks
594                                        , clockspeed - 100.0
595                                        , g_renderManager.GetVSyncState().c_str());
596
597       strGeneralFPS = StringUtils::Format("%s\nW( fps:%02.2f %s ) %s"
598                                           , strGeneral.c_str()
599                                           , g_infoManager.GetFPS()
600                                           , strCores.c_str(), strClock.c_str() );
601
602       CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), LABEL_ROW3);
603       msg.SetLabel(strGeneralFPS);
604       OnMessage(msg);
605     }
606   }
607   //----------------------
608   // ViewMode Information
609   //----------------------
610   if (m_bShowViewModeInfo && XbmcThreads::SystemClockMillis() - m_dwShowViewModeTimeout > 2500)
611   {
612     m_bShowViewModeInfo = false;
613   }
614   if (m_bShowViewModeInfo)
615   {
616     RESOLUTION_INFO res = g_graphicsContext.GetResInfo();
617
618     {
619       // get the "View Mode" string
620       CStdString strTitle = g_localizeStrings.Get(629);
621       CStdString strMode = g_localizeStrings.Get(630 + CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode);
622       CStdString strInfo = StringUtils::Format("%s : %s", strTitle.c_str(), strMode.c_str());
623       CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), LABEL_ROW1);
624       msg.SetLabel(strInfo);
625       OnMessage(msg);
626     }
627     // show sizing information
628     SPlayerVideoStreamInfo info;
629     g_application.m_pPlayer->GetVideoStreamInfo(info);
630     {
631       // Splitres scaling factor
632       float xscale = (float)res.iScreenWidth  / (float)res.iWidth;
633       float yscale = (float)res.iScreenHeight / (float)res.iHeight;
634
635       CStdString strSizing = StringUtils::Format(g_localizeStrings.Get(245),
636                                                  (int)info.SrcRect.Width(),
637                                                  (int)info.SrcRect.Height(),
638                                                  (int)(info.DestRect.Width() * xscale),
639                                                  (int)(info.DestRect.Height() * yscale),
640                                                  CDisplaySettings::Get().GetZoomAmount(),
641                                                  info.videoAspectRatio*CDisplaySettings::Get().GetPixelRatio(),
642                                                  CDisplaySettings::Get().GetPixelRatio(),
643                                                  CDisplaySettings::Get().GetVerticalShift());
644       CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), LABEL_ROW2);
645       msg.SetLabel(strSizing);
646       OnMessage(msg);
647     }
648     // show resolution information
649     {
650       CStdString strStatus;
651       if (g_Windowing.IsFullScreen())
652         strStatus = StringUtils::Format("%s %ix%i@%.2fHz - %s",
653                                         g_localizeStrings.Get(13287).c_str(),
654                                         res.iScreenWidth,
655                                         res.iScreenHeight,
656                                         res.fRefreshRate,
657                                         g_localizeStrings.Get(244).c_str());
658       else
659         strStatus = StringUtils::Format("%s %ix%i - %s",
660                                         g_localizeStrings.Get(13287).c_str(),
661                                         res.iScreenWidth,
662                                         res.iScreenHeight,
663                                         g_localizeStrings.Get(242).c_str());
664
665       CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), LABEL_ROW3);
666       msg.SetLabel(strStatus);
667       OnMessage(msg);
668     }
669   }
670
671   if (m_timeCodeShow && m_timeCodePosition != 0)
672   {
673     if ( (XbmcThreads::SystemClockMillis() - m_timeCodeTimeout) >= 2500)
674     {
675       m_timeCodeShow = false;
676       m_timeCodePosition = 0;
677     }
678     CStdString strDispTime = "00:00:00";
679
680     CGUIMessage msg(GUI_MSG_LABEL_SET, GetID(), LABEL_ROW1);
681
682     for (int pos = 7, i = m_timeCodePosition; pos >= 0 && i > 0; pos--)
683     {
684       if (strDispTime[pos] != ':')
685       {
686         i -= 1;
687         strDispTime[pos] = (char)m_timeCodeStamp[i] + '0';
688       }
689     }
690
691     strDispTime += "/" + g_infoManager.GetDuration(TIME_FORMAT_HH_MM_SS) + " [" + g_infoManager.GetCurrentPlayTime(TIME_FORMAT_HH_MM_SS) + "]"; // duration [ time ]
692     msg.SetLabel(strDispTime);
693     OnMessage(msg);
694   }
695
696   if (m_showCodec || m_bShowViewModeInfo)
697   {
698     SET_CONTROL_VISIBLE(LABEL_ROW1);
699     SET_CONTROL_VISIBLE(LABEL_ROW2);
700     SET_CONTROL_VISIBLE(LABEL_ROW3);
701     SET_CONTROL_VISIBLE(BLUE_BAR);
702     SET_CONTROL_HIDDEN(CONTROL_GROUP_CHOOSER);
703   }
704   else if (m_timeCodeShow)
705   {
706     SET_CONTROL_VISIBLE(LABEL_ROW1);
707     SET_CONTROL_HIDDEN(LABEL_ROW2);
708     SET_CONTROL_HIDDEN(LABEL_ROW3);
709     SET_CONTROL_VISIBLE(BLUE_BAR);
710     SET_CONTROL_HIDDEN(CONTROL_GROUP_CHOOSER);
711   }
712   else if (m_bGroupSelectShow)
713   {
714     SET_CONTROL_HIDDEN(LABEL_ROW1);
715     SET_CONTROL_HIDDEN(LABEL_ROW2);
716     SET_CONTROL_HIDDEN(LABEL_ROW3);
717     SET_CONTROL_HIDDEN(BLUE_BAR);
718     SET_CONTROL_VISIBLE(CONTROL_GROUP_CHOOSER);
719   }
720   else
721   {
722     SET_CONTROL_HIDDEN(LABEL_ROW1);
723     SET_CONTROL_HIDDEN(LABEL_ROW2);
724     SET_CONTROL_HIDDEN(LABEL_ROW3);
725     SET_CONTROL_HIDDEN(BLUE_BAR);
726     SET_CONTROL_HIDDEN(CONTROL_GROUP_CHOOSER);
727   }
728 }
729
730 void CGUIWindowFullScreen::Process(unsigned int currentTime, CDirtyRegionList &dirtyregion)
731 {
732   // TODO: This isn't quite optimal - ideally we'd only be dirtying up the actual video render rect
733   //       which is probably the job of the renderer as it can more easily track resizing etc.
734   MarkDirtyRegion();
735   CGUIWindow::Process(currentTime, dirtyregion);
736   m_renderRegion.SetRect(0, 0, (float)g_graphicsContext.GetWidth(), (float)g_graphicsContext.GetHeight());
737 }
738
739 void CGUIWindowFullScreen::Render()
740 {
741   CGUIWindow::Render();
742 }
743
744 void CGUIWindowFullScreen::ChangetheTimeCode(int remote)
745 {
746   if (remote >= REMOTE_0 && remote <= REMOTE_9)
747   {
748     m_timeCodeShow = true;
749     m_timeCodeTimeout = XbmcThreads::SystemClockMillis();
750
751     if (m_timeCodePosition < 6)
752       m_timeCodeStamp[m_timeCodePosition++] = remote - REMOTE_0;
753     else
754     {
755       // rotate around
756       for (int i = 0; i < 5; i++)
757         m_timeCodeStamp[i] = m_timeCodeStamp[i+1];
758       m_timeCodeStamp[5] = remote - REMOTE_0;
759     }
760   }
761 }
762
763 void CGUIWindowFullScreen::SeekToTimeCodeStamp(SEEK_TYPE type, SEEK_DIRECTION direction)
764 {
765   double total = GetTimeCodeStamp();
766   if (type == SEEK_RELATIVE)
767     total = g_application.GetTime() + (((direction == SEEK_FORWARD) ? 1 : -1) * total);
768
769   if (total < g_application.GetTotalTime())
770     g_application.SeekTime(total);
771
772   m_timeCodePosition = 0;
773   m_timeCodeShow = false;
774 }
775
776 double CGUIWindowFullScreen::GetTimeCodeStamp()
777 {
778   // Convert the timestamp into an integer
779   int tot = 0;
780   for (int i = 0; i < m_timeCodePosition; i++)
781     tot = tot * 10 + m_timeCodeStamp[i];
782
783   // Interpret result as HHMMSS
784   int s = tot % 100; tot /= 100;
785   int m = tot % 100; tot /= 100;
786   int h = tot % 100;
787   return h * 3600 + m * 60 + s;
788 }
789
790 void CGUIWindowFullScreen::SeekChapter(int iChapter)
791 {
792   g_application.m_pPlayer->SeekChapter(iChapter);
793
794   // Make sure gui items are visible.
795   g_infoManager.SetDisplayAfterSeek();
796 }
797
798 void CGUIWindowFullScreen::FillInTVGroups()
799 {
800   if (!g_PVRManager.IsStarted())
801     return;
802
803   CGUIMessage msgReset(GUI_MSG_LABEL_RESET, GetID(), CONTROL_GROUP_CHOOSER);
804   g_windowManager.SendMessage(msgReset);
805
806   const CPVRChannelGroups *groups = g_PVRChannelGroups->Get(g_PVRManager.IsPlayingRadio());
807   if (groups)
808     groups->FillGroupsGUI(GetID(), CONTROL_GROUP_CHOOSER);
809 }
810
811 void CGUIWindowFullScreen::ChangetheTVGroup(bool next)
812 {
813   if (!g_PVRManager.IsStarted())
814     return;
815
816   CGUISelectButtonControl* pButton = (CGUISelectButtonControl*)GetControl(CONTROL_GROUP_CHOOSER);
817   if (!pButton)
818     return;
819
820   if (!m_bGroupSelectShow)
821   {
822     SET_CONTROL_VISIBLE(CONTROL_GROUP_CHOOSER);
823     SET_CONTROL_FOCUS(CONTROL_GROUP_CHOOSER, 0);
824
825     // fire off an event that we've pressed this button...
826     OnAction(CAction(ACTION_SELECT_ITEM));
827
828     m_bGroupSelectShow = true;
829   }
830   else
831   {
832     if (next)
833       pButton->OnRight();
834     else
835       pButton->OnLeft();
836   }
837 }
838
839 void CGUIWindowFullScreen::ToggleOSD()
840 {
841   CGUIDialogVideoOSD *pOSD = (CGUIDialogVideoOSD *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_OSD);
842   if (pOSD)
843   {
844     if (pOSD->IsDialogRunning())
845       pOSD->Close();
846     else
847       pOSD->DoModal();
848   }
849 }