00001
00002 #include "DisplayRes.h"
00003 #include "config.h"
00004 #include "mythlogging.h"
00005 #include "mythdb.h"
00006
00007 #ifdef USING_XRANDR
00008 #include "DisplayResX.h"
00009 #endif
00010 #if CONFIG_DARWIN
00011 #include "DisplayResOSX.h"
00012 #endif
00013
00014
00015 DisplayRes * DisplayRes::m_instance = NULL;
00016 bool DisplayRes::m_locked = false;
00017
00018 DisplayRes * DisplayRes::GetDisplayRes(bool lock)
00019 {
00020 if (lock && m_locked)
00021 return NULL;
00022
00023 if (!m_instance)
00024 {
00025 #ifdef USING_XRANDR
00026 m_instance = new DisplayResX();
00027 #elif CONFIG_DARWIN
00028 m_instance = new DisplayResOSX();
00029 #endif
00030 }
00031
00032 if (m_instance && lock)
00033 m_locked = true;
00034
00035 return m_instance;
00036 }
00037
00038 void DisplayRes::Unlock(void)
00039 {
00040 m_locked = false;
00041 }
00042
00043 void DisplayRes::SwitchToDesktop()
00044 {
00045 if (m_instance)
00046 m_instance->SwitchToGUI(DESKTOP);
00047 }
00048
00049 bool DisplayRes::Initialize(void)
00050 {
00051 int tW = 0, tH = 0, tW_mm = 0, tH_mm = 0;
00052 double tAspect = 0.0;
00053 double tRate = 0.0;
00054
00055 m_last.Init();
00056 m_curMode = GUI;
00057 m_pixelAspectRatio = 1.0;
00058
00059
00060 GetDisplayInfo(tW, tH, tW_mm, tH_mm, tRate, m_pixelAspectRatio);
00061 m_mode[DESKTOP].Init();
00062 m_mode[DESKTOP] = DisplayResScreen(tW, tH, tW_mm, tH_mm, -1.0, tRate);
00063 LOG(VB_GENERAL, LOG_NOTICE, QString("Desktop video mode: %1x%2 %3 Hz")
00064 .arg(tW).arg(tH).arg(tRate, 0, 'f', 3));
00065
00066
00067 m_mode[GUI].Init();
00068 tW = tH = 0;
00069 GetMythDB()->GetResolutionSetting("GuiVidMode", tW, tH, tAspect, tRate);
00070 GetMythDB()->GetResolutionSetting("DisplaySize", tW_mm, tH_mm);
00071 m_mode[GUI] = DisplayResScreen(tW, tH, tW_mm, tH_mm, -1.0, tRate);
00072
00073
00074
00075 tW = tH = 0;
00076 GetMythDB()->GetResolutionSetting("TVVidMode", tW, tH, tAspect, tRate);
00077 m_mode[VIDEO] = DisplayResScreen(tW, tH, tW_mm, tH_mm, tAspect, tRate);
00078
00079
00080
00081 m_inSizeToOutputMode.clear();
00082
00083 for (int i = 0; true; ++i)
00084 {
00085 int iw = 0, ih = 0, ow = 0, oh = 0;
00086 double iaspect = 0.0, oaspect = 0.0;
00087 double irate = 0.0, orate = 0.0;
00088
00089 GetMythDB()->GetResolutionSetting("VidMode", iw, ih, iaspect, irate, i);
00090 GetMythDB()->GetResolutionSetting("TVVidMode", ow, oh, oaspect, orate, i);
00091
00092 if (!(iw || ih || irate))
00093 break;
00094
00095 if (!(ih && ow && oh))
00096 break;
00097
00098 uint64_t key = DisplayResScreen::CalcKey(iw, ih, irate);
00099
00100 DisplayResScreen scr(ow, oh, tW_mm, tH_mm, oaspect, orate);
00101
00102 m_inSizeToOutputMode[key] = scr;
00103 }
00104
00105
00106 const DisplayResVector& screens = GetVideoModes();
00107
00108 for (uint i = 0; i < screens.size(); ++i)
00109 {
00110 m_maxWidth = std::max(m_maxWidth, screens[i].Width());
00111 m_maxHeight = std::max(m_maxHeight, screens[i].Height());
00112 }
00113
00114 LOG(VB_PLAYBACK, LOG_INFO, QString("max_width: %1 max_height: %2")
00115
00116 .arg(m_maxWidth).arg(m_maxHeight));
00117
00118 return true;
00119 }
00120
00121 bool DisplayRes::SwitchToVideo(int iwidth, int iheight, double frate)
00122 {
00123 tmode next_mode = VIDEO;
00124 DisplayResScreen next = m_mode[next_mode];
00125 double target_rate = 0.0;
00126
00127
00128 uint64_t key = DisplayResScreen::FindBestScreen(m_inSizeToOutputMode,
00129 iwidth, iheight, frate);
00130
00131 if (key != 0)
00132 {
00133 m_mode[next_mode = CUSTOM_VIDEO] = next = m_inSizeToOutputMode[key];
00134 LOG(VB_PLAYBACK, LOG_INFO, QString("Found custom screen override %1x%2")
00135 .arg(next.Width()).arg(next.Height()));
00136 }
00137
00138
00139 if ((int) next.RefreshRate() == 0)
00140 {
00141 LOG(VB_PLAYBACK, LOG_INFO,
00142 QString("Trying to match best refresh rate %1Hz")
00143 .arg(frate, 0, 'f', 3));
00144 next.AddRefreshRate(frate);
00145 }
00146
00147
00148 DisplayResScreen::FindBestMatch(GetVideoModes(), next, target_rate);
00149
00150 bool chg = !(next == m_last) ||
00151 !(DisplayResScreen::compare_rates(m_last.RefreshRate(),
00152 target_rate));
00153
00154 LOG(VB_PLAYBACK, LOG_INFO, QString("Trying %1x%2 %3 Hz")
00155 .arg(next.Width()).arg(next.Height())
00156 .arg(target_rate, 0, 'f', 3));
00157
00158 if (chg && !SwitchToVideoMode(next.Width(), next.Height(), target_rate))
00159 {
00160 LOG(VB_GENERAL, LOG_ERR, QString("SwitchToVideo: Video size %1 x %2: "
00161 "xrandr failed for %3 x %4")
00162 .arg(iwidth).arg(iheight)
00163 .arg(next.Width()).arg(next.Height()));
00164 return false;
00165 }
00166
00167 m_curMode = next_mode;
00168
00169 m_last = next;
00170
00171 LOG(VB_PLAYBACK, LOG_INFO,
00172 QString("SwitchToVideo: Video size %1 x %2: \n"
00173 " %7 displaying resolution %3 x %4, %5mm x %6mm")
00174 .arg(iwidth).arg(iheight).arg(GetWidth()).arg(GetHeight())
00175 .arg(GetPhysicalWidth()).arg(GetPhysicalHeight())
00176 .arg((chg) ? "Switched to" : "Already"));
00177
00178 return chg;
00179 }
00180
00181 bool DisplayRes::SwitchToGUI(tmode next_mode)
00182 {
00183 DisplayResScreen next = m_mode[next_mode];
00184
00185
00186 double target_rate = next.RefreshRate();
00187 DisplayResScreen::FindBestMatch(GetVideoModes(), next, target_rate);
00188
00189 bool chg = (!(next == m_last) ||
00190 (((int) next.RefreshRate()) != 0
00191 && !(DisplayResScreen::compare_rates(m_last.RefreshRate(),
00192 target_rate))));
00193
00194 LOG(VB_GENERAL, LOG_INFO, QString("Trying %1x%2 %3 Hz")
00195 .arg(next.Width()).arg(next.Height()).arg(target_rate, 0, 'f', 3));
00196
00197 if (chg && !SwitchToVideoMode(next.Width(), next.Height(), target_rate))
00198 {
00199 LOG(VB_GENERAL, LOG_ERR,
00200 QString("SwitchToGUI: xrandr failed for %1x%2 %3 Hz")
00201 .arg(next.Width()).arg(next.Height())
00202 .arg(next.RefreshRate(), 0, 'f', 3));
00203 return false;
00204 }
00205
00206 m_curMode = next_mode;
00207
00208 m_last = next;
00209
00210 LOG(VB_GENERAL, LOG_INFO, QString("SwitchToGUI: Switched to %1x%2 %3 Hz")
00211 .arg(GetWidth()).arg(GetHeight()).arg(GetRefreshRate(), 0, 'f', 3));
00212
00213 return chg;
00214 }
00215
00216 bool DisplayRes::SwitchToCustomGUI(int width, int height, short rate)
00217 {
00218 m_mode[CUSTOM_GUI] = DisplayResScreen(width, height, m_mode[GUI].Width_mm(),
00219 m_mode[GUI].Height_mm(), -1.0,
00220 (double)rate);
00221 return SwitchToGUI(CUSTOM_GUI);
00222 }
00223
00224 const std::vector<double> DisplayRes::GetRefreshRates(int width,
00225 int height) const
00226 {
00227 double tr;
00228 std::vector<double> empty;
00229
00230 const DisplayResScreen drs(width, height, 0, 0, -1.0, 0.0);
00231 const DisplayResVector& drv = GetVideoModes();
00232 int t = DisplayResScreen::FindBestMatch(drv, drs, tr);
00233
00234 if (t < 0)
00235 return empty;
00236
00237 return drv[t].RefreshRates();
00238 }
00239
00248 const DisplayResVector GetVideoModes(void)
00249 {
00250 DisplayRes *display_res = DisplayRes::GetDisplayRes();
00251
00252 if (display_res)
00253 return display_res->GetVideoModes();
00254
00255 DisplayResVector empty;
00256
00257 return empty;
00258 }