00001 #include "config.h"
00002 #include "DisplayRes.h"
00003 #include "mythcontext.h"
00004
00005 #ifdef USING_XRANDR
00006 #include "DisplayResX.h"
00007 #endif
00008 #ifdef CONFIG_DARWIN
00009 #include "DisplayResOSX.h"
00010 #endif
00011
00012 DisplayRes * DisplayRes::instance = NULL;
00013
00014 DisplayRes * DisplayRes::GetDisplayRes(void)
00015 {
00016 if (!instance)
00017 {
00018 #ifdef USING_XRANDR
00019 instance = new DisplayResX();
00020 #elif defined(CONFIG_DARWIN)
00021 instance = new DisplayResOSX();
00022 #endif
00023 }
00024 return instance;
00025 }
00026
00027 bool DisplayRes::Initialize(void)
00028 {
00029 int tW = 0, tH = 0, tW_mm = 0, tH_mm = 0;
00030 double tAspect = 0.0;
00031 short tRate = 0;
00032
00033 last.Init();
00034 cur_mode = GUI;
00035
00036
00037
00038 mode[GUI].Init();
00039 tW = tH = 0;
00040 gContext->GetResolutionSetting("GuiVidMode", tW, tH);
00041 GetDisplaySize(tW_mm, tH_mm);
00042 gContext->GetResolutionSetting("DisplaySize", tW_mm, tH_mm);
00043 mode[GUI] = DisplayResScreen(tW, tH, tW_mm, tH_mm, -1.0, 0);
00044
00045
00046
00047 tW = tH = 0;
00048 gContext->GetResolutionSetting("TVVidMode", tW, tH, tAspect, tRate);
00049 mode[VIDEO] = DisplayResScreen(tW, tH, tW_mm, tH_mm, tAspect, tRate);
00050
00051
00052
00053 in_size_to_output_mode.clear();
00054 for (int i = 0; true; ++i)
00055 {
00056 int iw = 0, ih = 0, ow = 0, oh = 0;
00057 double iaspect = 0.0, oaspect = 0.0;
00058 short irate = 0, orate = 0;
00059
00060 gContext->GetResolutionSetting("VidMode", iw, ih, iaspect, irate, i);
00061 gContext->GetResolutionSetting("TVVidMode", ow, oh, oaspect, orate, i);
00062
00063 if (!(iw && ih && ow && oh))
00064 break;
00065
00066 uint key = DisplayResScreen::CalcKey(iw, ih, irate);
00067 DisplayResScreen scr(ow, oh, tW_mm, tH_mm, oaspect, orate);
00068 in_size_to_output_mode[key] = scr;
00069 }
00070
00071
00072
00073 const DisplayResVector& screens = GetVideoModes();
00074 for (uint i=0; i<screens.size(); ++i)
00075 {
00076 max_width = max(max_width, screens[i].Width());
00077 max_height = max(max_height, screens[i].Height());
00078 }
00079 VERBOSE(VB_PLAYBACK, QString("max_width: %1 max_height: %2")
00080 .arg(max_width).arg(max_height));
00081
00082 return true;
00083 }
00084
00085 bool DisplayRes::SwitchToVideo(int iwidth, int iheight, short irate)
00086 {
00087 tmode next_mode = VIDEO;
00088 DisplayResScreen next = mode[next_mode];
00089
00090
00091 uint key = DisplayResScreen::CalcKey(iwidth, iheight, irate);
00092 DisplayResMapCIt it = in_size_to_output_mode.find(key);
00093 if (it != in_size_to_output_mode.end())
00094 mode[next_mode = CUSTOM_VIDEO] = next = it->second;
00095
00096
00097 short target_rate = 0;
00098 DisplayResScreen::FindBestMatch(GetVideoModes(), next, target_rate);
00099 bool chg = !(next == last) || !(last.RefreshRate() == target_rate);
00100
00101 VERBOSE(VB_PLAYBACK, QString("Trying %1x%2 %3 Hz")
00102 .arg(next.Width()).arg(next.Height()).arg(target_rate));
00103
00104 if (chg && !SwitchToVideoMode(next.Width(), next.Height(), target_rate))
00105 {
00106 VERBOSE(VB_IMPORTANT,
00107 QString("SwitchToVideo: Video size %1 x %2: "
00108 "xrandr failed for %3 x %4")
00109 .arg(iwidth).arg(iheight).arg(next.Width()).arg(next.Height()));
00110 return false;
00111 }
00112
00113 cur_mode = next_mode;
00114 last = next;
00115
00116 VERBOSE(VB_PLAYBACK,
00117 QString("SwitchToVideo: Video size %1 x %2: \n"
00118 " %7 displaying resolution %3 x %4, %5mm x %6mm")
00119 .arg(iwidth).arg(iheight).arg(GetWidth()).arg(GetHeight())
00120 .arg(GetPhysicalWidth()).arg(GetPhysicalHeight())
00121 .arg((chg) ? "Switched to" : "Already"));
00122
00123 return chg;
00124 }
00125
00126 bool DisplayRes::SwitchToGUI(tmode next_mode)
00127 {
00128 DisplayResScreen next = mode[next_mode];
00129
00130
00131 short target_rate = 0;
00132 DisplayResScreen::FindBestMatch(GetVideoModes(), next, target_rate);
00133 bool chg = !(next == last) || !(last.RefreshRate() == target_rate);
00134
00135 VERBOSE(VB_PLAYBACK, QString("Trying %1x%2 %3 Hz")
00136 .arg(next.Width()).arg(next.Height()).arg(target_rate));
00137
00138 if (chg && !SwitchToVideoMode(next.Width(), next.Height(), target_rate))
00139 {
00140 VERBOSE(VB_IMPORTANT, QString("SwitchToGUI: xrandr failed for %1 x %2")
00141 .arg(next.Width()).arg(next.Height()));
00142 return false;
00143 }
00144
00145 cur_mode = next_mode;
00146 last = next;
00147
00148 VERBOSE(VB_PLAYBACK, QString("SwitchToGUI: Switched to %1 x %2")
00149 .arg(GetWidth()).arg(GetHeight()));
00150
00151 return chg;
00152 }
00153
00154 bool DisplayRes::SwitchToCustomGUI(int width, int height, short rate)
00155 {
00156 mode[CUSTOM_GUI] = DisplayResScreen(width, height, mode[GUI].Width_mm(),
00157 mode[GUI].Height_mm(), -1.0, rate);
00158 return SwitchToGUI(CUSTOM_GUI);
00159 }
00160
00161 const vector<short> DisplayRes::GetRefreshRates(int width, int height) const {
00162 short tr;
00163 vector<short> empty;
00164
00165 const DisplayResScreen drs(width, height, 0, 0, -1.0, 0);
00166 const DisplayResVector& drv = GetVideoModes();
00167 int t = DisplayResScreen::FindBestMatch(drv, drs, tr);
00168 if (t < 0)
00169 return empty;
00170 return drv[t].RefreshRates();
00171 }
00172
00181 const vector<DisplayResScreen> GetVideoModes(void)
00182 {
00183 DisplayRes *display_res = DisplayRes::GetDisplayRes();
00184 if (display_res)
00185 return display_res->GetVideoModes();
00186
00187 vector<DisplayResScreen> empty;
00188 return empty;
00189 }