Don't reset transform stack on window process/render
[xbmc:paulepanters-xbmc.git] / xbmc / settings / GUIWindowSettingsScreenCalibration.cpp
1 /*
2  *      Copyright (C) 2005-2008 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 "system.h"
23 #include "GUIWindowSettingsScreenCalibration.h"
24 #include "guilib/GUIMoverControl.h"
25 #include "guilib/GUIResizeControl.h"
26 #ifdef HAS_VIDEO_PLAYBACK
27 #include "cores/VideoRenderers/RenderManager.h"
28 #endif
29 #include "Application.h"
30 #include "Settings.h"
31 #include "GUISettings.h"
32 #include "guilib/GUIWindowManager.h"
33 #include "dialogs/GUIDialogYesNo.h"
34 #include "guilib/LocalizeStrings.h"
35 #include "utils/log.h"
36
37 using namespace std;
38
39 #define CONTROL_LABEL_ROW1  2
40 #define CONTROL_LABEL_ROW2  3
41 #define CONTROL_TOP_LEFT  8
42 #define CONTROL_BOTTOM_RIGHT 9
43 #define CONTROL_SUBTITLES  10
44 #define CONTROL_PIXEL_RATIO  11
45 #define CONTROL_VIDEO   20
46 #define CONTROL_NONE   0
47
48 CGUIWindowSettingsScreenCalibration::CGUIWindowSettingsScreenCalibration(void)
49     : CGUIWindow(WINDOW_SCREEN_CALIBRATION, "SettingsScreenCalibration.xml")
50 {
51   m_needsScaling = false;         // we handle all the scaling
52 }
53
54 CGUIWindowSettingsScreenCalibration::~CGUIWindowSettingsScreenCalibration(void)
55 {}
56
57
58 bool CGUIWindowSettingsScreenCalibration::OnAction(const CAction &action)
59 {
60   switch (action.GetID())
61   {
62   case ACTION_CALIBRATE_SWAP_ARROWS:
63     {
64       NextControl();
65       return true;
66     }
67     break;
68
69   case ACTION_CALIBRATE_RESET:
70     {
71       CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
72       pDialog->SetHeading(20325);
73       CStdString strText;
74       strText.Format(g_localizeStrings.Get(20326).c_str(), g_settings.m_ResInfo[m_Res[m_iCurRes]].strMode.c_str());
75       pDialog->SetLine(0, strText);
76       pDialog->SetLine(1, 20327);
77       pDialog->SetChoice(0, 222);
78       pDialog->SetChoice(1, 186);
79       pDialog->DoModal();
80       if (pDialog->IsConfirmed())
81       {
82         g_graphicsContext.ResetScreenParameters(m_Res[m_iCurRes]);
83         ResetControls();
84       }
85       return true;
86     }
87     break;
88
89   case ACTION_CHANGE_RESOLUTION:
90     // choose the next resolution in our list
91     {
92       m_iCurRes = (m_iCurRes+1) % m_Res.size();
93       g_graphicsContext.SetVideoResolution(m_Res[m_iCurRes]);
94       ResetControls();
95       return true;
96     }
97     break;
98   }
99   return CGUIWindow::OnAction(action); // base class to handle basic movement etc.
100 }
101
102 void CGUIWindowSettingsScreenCalibration::AllocResources(bool forceLoad)
103 {
104   CGUIWindow::AllocResources(forceLoad);
105 }
106
107 void CGUIWindowSettingsScreenCalibration::FreeResources(bool forceUnload)
108 {
109   CGUIWindow::FreeResources(forceUnload);
110 }
111
112
113 bool CGUIWindowSettingsScreenCalibration::OnMessage(CGUIMessage& message)
114 {
115   switch ( message.GetMessage() )
116   {
117   case GUI_MSG_WINDOW_DEINIT:
118     {
119       g_settings.Save();
120       g_graphicsContext.SetCalibrating(false);
121       g_windowManager.ShowOverlay(OVERLAY_STATE_SHOWN);
122       // reset our screen resolution to what it was initially
123       g_graphicsContext.SetVideoResolution(g_guiSettings.m_LookAndFeelResolution);
124       // Inform the player so we can update the resolution
125 #ifdef HAS_VIDEO_PLAYBACK
126       g_renderManager.Update(false);
127 #endif
128       g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_WINDOW_RESIZE);
129     }
130     break;
131
132   case GUI_MSG_WINDOW_INIT:
133     {
134       CGUIWindow::OnMessage(message);
135       g_windowManager.ShowOverlay(OVERLAY_STATE_HIDDEN);
136       g_graphicsContext.SetCalibrating(true);
137
138       // Get the allowable resolutions that we can calibrate...
139       m_Res.clear();
140       if (g_application.IsPlayingVideo())
141       { // don't allow resolution switching if we are playing a video
142
143 #ifdef HAS_VIDEO_PLAYBACK
144         RESOLUTION res = g_renderManager.GetResolution();
145         g_graphicsContext.SetVideoResolution(res);
146         // Inform the renderer so we can update the resolution
147         g_renderManager.Update(false);
148 #endif
149
150         m_iCurRes = 0;
151         m_Res.push_back(g_graphicsContext.GetVideoResolution());
152         SET_CONTROL_VISIBLE(CONTROL_VIDEO);
153       }
154       else
155       {
156         SET_CONTROL_HIDDEN(CONTROL_VIDEO);
157         m_iCurRes = (unsigned int)-1;
158         g_graphicsContext.GetAllowedResolutions(m_Res);
159         // find our starting resolution
160         RESOLUTION curRes = g_graphicsContext.GetVideoResolution();
161         for (UINT i = 0; i < m_Res.size(); i++)
162         {
163           // If it's a CUSTOM (monitor) resolution, then g_graphicsContext.GetAllowedResolutions()
164           // returns just one entry with CUSTOM in it. Update that entry to point to the current
165           // CUSTOM resolution.
166           if (curRes>=RES_CUSTOM)
167           {
168             if (m_Res[i]==RES_CUSTOM)
169             {
170               m_iCurRes = i;
171               m_Res[i] = curRes;
172               break;
173             }
174           }
175           else if (m_Res[i] == g_graphicsContext.GetVideoResolution())
176           {
177             m_iCurRes = i;
178             break;
179           }
180         }
181       }
182       if (m_iCurRes==(unsigned int)-1)
183       {
184         CLog::Log(LOGERROR, "CALIBRATION: Reported current resolution: %d", (int)g_graphicsContext.GetVideoResolution());
185         CLog::Log(LOGERROR, "CALIBRATION: Could not determine current resolution, falling back to default");
186         m_iCurRes = 0;
187       }
188
189       // Setup the first control
190       m_iControl = CONTROL_TOP_LEFT;
191       ResetControls();
192       return true;
193     }
194     break;
195   case GUI_MSG_CLICKED:
196     {
197       // clicked - change the control...
198       NextControl();
199     }
200     break;
201   }
202   return CGUIWindow::OnMessage(message);
203 }
204
205 void CGUIWindowSettingsScreenCalibration::NextControl()
206 { // set the old control invisible and not focused, and choose the next control
207   CGUIControl *pControl = (CGUIControl *)GetControl(m_iControl);
208   if (pControl)
209   {
210     pControl->SetVisible(false);
211     pControl->SetFocus(false);
212   }
213   // switch to the next control
214   m_iControl++;
215   if (m_iControl > CONTROL_PIXEL_RATIO)
216     m_iControl = CONTROL_TOP_LEFT;
217   // enable the new control
218   EnableControl(m_iControl);
219 }
220
221 void CGUIWindowSettingsScreenCalibration::EnableControl(int iControl)
222 {
223   SET_CONTROL_VISIBLE(CONTROL_TOP_LEFT);
224   SET_CONTROL_VISIBLE(CONTROL_BOTTOM_RIGHT);
225   SET_CONTROL_VISIBLE(CONTROL_SUBTITLES);
226   SET_CONTROL_VISIBLE(CONTROL_PIXEL_RATIO);
227   SET_CONTROL_FOCUS(iControl, 0);
228 }
229
230 void CGUIWindowSettingsScreenCalibration::ResetControls()
231 {
232   // disable the video control, so that our other controls take mouse clicks etc.
233   CONTROL_DISABLE(CONTROL_VIDEO);
234   // disable the UI calibration for our controls
235   // and set their limits
236   // also, set them to invisible if they don't have focus
237   CGUIMoverControl *pControl = (CGUIMoverControl*)GetControl(CONTROL_TOP_LEFT);
238   if (pControl)
239   {
240     pControl->SetLimits( -g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth / 4,
241                          -g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight / 4,
242                          g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth / 4,
243                          g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight / 4);
244     pControl->SetPosition((float)g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.left,
245                           (float)g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.top);
246     pControl->SetLocation(g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.left,
247                           g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.top, false);
248   }
249   pControl = (CGUIMoverControl*)GetControl(CONTROL_BOTTOM_RIGHT);
250   if (pControl)
251   {
252     pControl->SetLimits(g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth*3 / 4,
253                         g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight*3 / 4,
254                         g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth*5 / 4,
255                         g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight*5 / 4);
256     pControl->SetPosition((float)g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.right - (int)pControl->GetWidth(),
257                           (float)g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.bottom - (int)pControl->GetHeight());
258     pControl->SetLocation(g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.right,
259                           g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.bottom, false);
260   }
261   // Subtitles and OSD controls can only move up and down
262   pControl = (CGUIMoverControl*)GetControl(CONTROL_SUBTITLES);
263   if (pControl)
264   {
265     pControl->SetLimits(0, g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight*3 / 4,
266                         0, g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight*5 / 4);
267     pControl->SetPosition((g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth - pControl->GetWidth()) * 0.5f,
268                           g_settings.m_ResInfo[m_Res[m_iCurRes]].iSubtitles - pControl->GetHeight());
269     pControl->SetLocation(0, g_settings.m_ResInfo[m_Res[m_iCurRes]].iSubtitles, false);
270   }
271   // lastly the pixel ratio control...
272   CGUIResizeControl *pResize = (CGUIResizeControl*)GetControl(CONTROL_PIXEL_RATIO);
273   if (pResize)
274   {
275     pResize->SetLimits(g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth*0.25f, g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight*0.5f,
276                        g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth*0.75f, g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight*0.5f);
277     pResize->SetHeight(g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight * 0.5f);
278     pResize->SetWidth(pResize->GetHeight() / g_settings.m_ResInfo[m_Res[m_iCurRes]].fPixelRatio);
279     pResize->SetPosition((g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth - pResize->GetWidth()) / 2,
280                          (g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight - pResize->GetHeight()) / 2);
281   }
282   // Enable the default control
283   EnableControl(m_iControl);
284 }
285
286 void CGUIWindowSettingsScreenCalibration::UpdateFromControl(int iControl)
287 {
288   CStdString strStatus;
289   if (iControl == CONTROL_PIXEL_RATIO)
290   {
291     CGUIResizeControl *pControl = (CGUIResizeControl*)GetControl(CONTROL_PIXEL_RATIO);
292     if (pControl)
293     {
294       float fWidth = (float)pControl->GetWidth();
295       float fHeight = (float)pControl->GetHeight();
296       g_settings.m_ResInfo[m_Res[m_iCurRes]].fPixelRatio = fHeight / fWidth;
297       // recenter our control...
298       pControl->SetPosition((g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth - pControl->GetWidth()) / 2,
299                             (g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight - pControl->GetHeight()) / 2);
300       strStatus.Format("%s (%5.3f)", g_localizeStrings.Get(275).c_str(), g_settings.m_ResInfo[m_Res[m_iCurRes]].fPixelRatio);
301       SET_CONTROL_LABEL(CONTROL_LABEL_ROW2, 278);
302     }
303   }
304   else
305   {
306     CGUIMoverControl *pControl = (CGUIMoverControl*)GetControl(iControl);
307     if (pControl)
308     {
309       switch (iControl)
310       {
311       case CONTROL_TOP_LEFT:
312         {
313           g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.left = pControl->GetXLocation();
314           g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.top = pControl->GetYLocation();
315           strStatus.Format("%s (%i,%i)", g_localizeStrings.Get(272).c_str(), pControl->GetXLocation(), pControl->GetYLocation());
316           SET_CONTROL_LABEL(CONTROL_LABEL_ROW2, 276);
317         }
318         break;
319
320       case CONTROL_BOTTOM_RIGHT:
321         {
322           g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.right = pControl->GetXLocation();
323           g_settings.m_ResInfo[m_Res[m_iCurRes]].Overscan.bottom = pControl->GetYLocation();
324           int iXOff1 = g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth - pControl->GetXLocation();
325           int iYOff1 = g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight - pControl->GetYLocation();
326           strStatus.Format("%s (%i,%i)", g_localizeStrings.Get(273).c_str(), iXOff1, iYOff1);
327           SET_CONTROL_LABEL(CONTROL_LABEL_ROW2, 276);
328         }
329         break;
330
331       case CONTROL_SUBTITLES:
332         {
333           g_settings.m_ResInfo[m_Res[m_iCurRes]].iSubtitles = pControl->GetYLocation();
334           strStatus.Format("%s (%i)", g_localizeStrings.Get(274).c_str(), pControl->GetYLocation());
335           SET_CONTROL_LABEL(CONTROL_LABEL_ROW2, 277);
336         }
337         break;
338       }
339     }
340   }
341   // set the label control correctly
342   CStdString strText;
343   if (g_settings.m_ResInfo[m_Res[m_iCurRes]].bFullScreen)
344     strText.Format("%ix%i@%.2f - %s | %s", g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth,
345       g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight, g_settings.m_ResInfo[m_Res[m_iCurRes]].fRefreshRate,
346       g_localizeStrings.Get(244).c_str(), strStatus.c_str());
347   else
348     strText.Format("%ix%i - %s | %s", g_settings.m_ResInfo[m_Res[m_iCurRes]].iWidth,
349       g_settings.m_ResInfo[m_Res[m_iCurRes]].iHeight,
350       g_localizeStrings.Get(242).c_str(), strStatus.c_str());
351
352   SET_CONTROL_LABEL(CONTROL_LABEL_ROW1, strText);
353 }
354
355 void CGUIWindowSettingsScreenCalibration::FrameMove()
356 {
357   //  g_Windowing.Get3DDevice()->Clear(0, NULL, D3DCLEAR_TARGET, 0, 0, 0);
358   m_iControl = GetFocusedControlID();
359   if (m_iControl >= 0)
360   {
361     UpdateFromControl(m_iControl);
362   }
363   else
364   {
365     SET_CONTROL_LABEL(CONTROL_LABEL_ROW1, "");
366     SET_CONTROL_LABEL(CONTROL_LABEL_ROW2, "");
367   }
368   CGUIWindow::FrameMove();
369 }
370
371 void CGUIWindowSettingsScreenCalibration::DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyregions)
372 {
373   MarkDirtyRegion();
374
375   for (int i = CONTROL_TOP_LEFT; i <= CONTROL_PIXEL_RATIO; i++)
376     SET_CONTROL_HIDDEN(i);
377
378   m_needsScaling = true;
379   CGUIWindow::DoProcess(currentTime, dirtyregions);
380   m_needsScaling = false;
381
382   g_graphicsContext.SetRenderingResolution(m_Res[m_iCurRes], false);
383   g_graphicsContext.AddGUITransform();
384
385   // process the movers etc.
386   for (int i = CONTROL_TOP_LEFT; i <= CONTROL_PIXEL_RATIO; i++)
387   {
388     SET_CONTROL_VISIBLE(i);
389     CGUIControl *control = (CGUIControl *)GetControl(i);
390     if (control)
391       control->DoProcess(currentTime, dirtyregions);
392   }
393   g_graphicsContext.RemoveTransform();
394 }
395
396 void CGUIWindowSettingsScreenCalibration::Render()
397 {
398   // we set that we need scaling here to render so that anything else on screen scales correctly
399   m_needsScaling = true;
400   CGUIWindow::Render();
401   m_needsScaling = false;
402 }