Index: 0.21-fixes/mythtv/libs/libmyth/DisplayRes.cpp
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmyth/DisplayRes.cpp	2009-06-30 22:32:42.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmyth/DisplayRes.cpp	2009-06-30 22:32:57.000000000 +1000
@@ -9,6 +9,8 @@
 #include "DisplayResOSX.h"
 #endif
 
+#include <cmath>
+
 DisplayRes * DisplayRes::instance = NULL;
 
 DisplayRes * DisplayRes::GetDisplayRes(void)
@@ -37,16 +39,16 @@
     // Initialize GUI mode
     mode[GUI].Init();
     tW = tH = 0;
-    gContext->GetResolutionSetting("GuiVidMode", tW, tH);
+    gContext->GetResolutionSetting("GuiVidMode", tW, tH, tAspect, tRate);
     GetDisplaySize(tW_mm, tH_mm);
     gContext->GetResolutionSetting("DisplaySize", tW_mm, tH_mm);
-    mode[GUI] = DisplayResScreen(tW, tH, tW_mm, tH_mm, -1.0, 0);
+    mode[GUI] = DisplayResScreen(tW, tH, tW_mm, tH_mm, -1.0, (float)tRate);
 
 
     // Initialize default VIDEO mode
     tW = tH = 0;
     gContext->GetResolutionSetting("TVVidMode", tW, tH, tAspect, tRate);
-    mode[VIDEO] = DisplayResScreen(tW, tH, tW_mm, tH_mm, tAspect, tRate);
+    mode[VIDEO] = DisplayResScreen(tW, tH, tW_mm, tH_mm, tAspect, (float)tRate);
 
 
     // Initialize video override mode
@@ -64,7 +66,7 @@
             break;
 
         uint key = DisplayResScreen::CalcKey(iw, ih, irate);
-        DisplayResScreen scr(ow, oh, tW_mm, tH_mm, oaspect, orate);
+        DisplayResScreen scr(ow, oh, tW_mm, tH_mm, oaspect, (float)orate);
         in_size_to_output_mode[key] = scr;            
     }
 
@@ -82,21 +84,28 @@
     return true;
 }
 
-bool DisplayRes::SwitchToVideo(int iwidth, int iheight, short irate)
+bool DisplayRes::SwitchToVideo(int iwidth, int iheight, float frate)
 {
     tmode next_mode = VIDEO; // default VIDEO mode
     DisplayResScreen next = mode[next_mode];
 
+    // If requested refresh rate is 0, attempt to match video fps
+    if (next.RefreshRate() == 0)
+    {
+        VERBOSE(VB_PLAYBACK, QString("*** Trying to match best resolution %1Hz") .arg(frate));
+        next.AddRefreshRate(frate);
+    }
+
     // try to find video override mode
-    uint key = DisplayResScreen::CalcKey(iwidth, iheight, irate);
+    uint key = DisplayResScreen::CalcKey(iwidth, iheight, (short) roundf(frate));
     DisplayResMapCIt it = in_size_to_output_mode.find(key);
     if (it != in_size_to_output_mode.end())
         mode[next_mode = CUSTOM_VIDEO] = next = it->second;
 
     // need to change video mode?
-    short target_rate = 0;
+    float target_rate = 0.0;
     DisplayResScreen::FindBestMatch(GetVideoModes(), next, target_rate);
-    bool chg = !(next == last) || !(last.RefreshRate() == target_rate);
+    bool chg = !(next == last) || !(DisplayResScreen::compare_rates(last.RefreshRate(),target_rate));
 
     VERBOSE(VB_PLAYBACK, QString("Trying %1x%2 %3 Hz")
             .arg(next.Width()).arg(next.Height()).arg(target_rate));
@@ -128,9 +137,11 @@
     DisplayResScreen next = mode[next_mode];
 
     // need to change video mode?
-    short target_rate = 0;
+    float target_rate = 0.0;
     DisplayResScreen::FindBestMatch(GetVideoModes(), next, target_rate);
-    bool chg = !(next == last) || !(last.RefreshRate() == target_rate);
+    // If GuiVidModeRefreshRate is 0, assume any refresh rate is good enough.
+    bool chg = (!(next == last) || (next.RefreshRate() !=0
+                && !(DisplayResScreen::compare_rates(last.RefreshRate(), target_rate)))); 
 
     VERBOSE(VB_PLAYBACK, QString("Trying %1x%2 %3 Hz")
             .arg(next.Width()).arg(next.Height()).arg(target_rate));
@@ -154,15 +165,23 @@
 bool DisplayRes::SwitchToCustomGUI(int width, int height, short rate)
 {
     mode[CUSTOM_GUI] = DisplayResScreen(width, height, mode[GUI].Width_mm(),
-                                        mode[GUI].Height_mm(), -1.0, rate);
+                                        mode[GUI].Height_mm(), -1.0, (float)rate);
     return SwitchToGUI(CUSTOM_GUI);
 }
 
 const vector<short> DisplayRes::GetRefreshRates(int width, int height) const {
-    short tr;
-    vector<short> empty;
+    vector<short> srates;
+    vector<float> rates = GetRefreshRatesFloat(width, height);
+
+    for (int i=0; i<rates.size(); i++)
+        srates.push_back((short) rates[i]);
+    return srates;
+}
+const vector<float> DisplayRes::GetRefreshRatesFloat(int width, int height) const {
+    float tr;
+    vector<float> empty;
 
-    const DisplayResScreen drs(width, height, 0, 0, -1.0, 0);
+    const DisplayResScreen drs(width, height, 0, 0, -1.0, 0.0);
     const DisplayResVector& drv = GetVideoModes();
     int t = DisplayResScreen::FindBestMatch(drv, drs, tr);
     if (t < 0)
Index: 0.21-fixes/mythtv/libs/libmyth/DisplayRes.h
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmyth/DisplayRes.h	2009-06-30 22:32:42.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmyth/DisplayRes.h	2009-06-30 22:32:57.000000000 +1000
@@ -46,7 +46,7 @@
      *  \brief Switches to the resolution and refresh rate defined in the
      *         database for the specified video resolution and frame rate.
      */
-    bool SwitchToVideo(int iwidth, int iheight, short irate = 0);
+    bool SwitchToVideo(int iwidth, int iheight, float frate = 0.0);
     /** \brief Switches to the GUI resolution specified.
      *
      *   If which_gui is GUI then this switches to the resolution
@@ -110,7 +110,8 @@
     /// \brief Returns all video modes supported by the display.
     virtual const vector<DisplayResScreen>& GetVideoModes() const = 0;
     /// \brief Returns refresh rates available at a specific screen resolution.
-    const vector<short> GetRefreshRates(int width, int height) const;
+    const vector<float> GetRefreshRatesFloat(int width, int height) const;
+    const vector<short> GetRefreshRates(int width, int height) const; 
     /** @} */
 
   protected:
@@ -120,7 +121,7 @@
     
     // These methods are implemented by the subclasses
     virtual bool GetDisplaySize(int &width_mm, int &height_mm) const = 0;
-    virtual bool SwitchToVideoMode(int width, int height, short framerate) = 0;
+    virtual bool SwitchToVideoMode(int width, int height, float framerate) = 0;
 
   private:
     DisplayRes(const DisplayRes & rhs); // disable copy constructor;
Index: 0.21-fixes/mythtv/libs/libmyth/DisplayResScreen.cpp
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmyth/DisplayResScreen.cpp	2009-06-30 22:32:42.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmyth/DisplayResScreen.cpp	2009-06-30 22:32:57.000000000 +1000
@@ -1,9 +1,11 @@
 #include "DisplayResScreen.h"
 #include "mythcontext.h"
 
+#include <cmath>
+
 DisplayResScreen::DisplayResScreen(int w, int h, int mw, int mh,
-                                   double aspectRatio, short refreshRate)
-    : width(w), height(h), width_mm(mw), height_mm(mh)
+                                   double aspectRatio, float refreshRate)
+    : width(w), height(h), width_mm(mw), height_mm(mh), custom(false)
 {
     SetAspectRatio(aspectRatio);
     if (refreshRate > 0)
@@ -11,15 +13,22 @@
 }
 
 DisplayResScreen::DisplayResScreen(int w, int h, int mw, int mh,
-                                   const vector<short>& rr)
-    : width(w), height(h), width_mm(mw), height_mm(mh), refreshRates(rr)
+                                   const vector<float>& rr)
+    : width(w), height(h), width_mm(mw), height_mm(mh), refreshRates(rr), custom(false)
 {
     SetAspectRatio(-1.0);
 }
 
 DisplayResScreen::DisplayResScreen(int w, int h, int mw, int mh,
-                                   const short* rr, uint rr_length)
-    : width(w), height(h), width_mm(mw), height_mm(mh)
+                                   const vector<float>& rr, const map<float, short>& rr2)
+: width(w), height(h), width_mm(mw), height_mm(mh), refreshRates(rr), realRates(rr2), custom(true)
+{
+    SetAspectRatio(-1.0);
+}
+
+DisplayResScreen::DisplayResScreen(int w, int h, int mw, int mh,
+                                   const float* rr, uint rr_length)
+    : width(w), height(h), width_mm(mw), height_mm(mh), custom(false)
 {
     SetAspectRatio(-1.0);
     for (uint i = 0; i < rr_length; ++i)
@@ -28,8 +37,20 @@
     sort(refreshRates.begin(), refreshRates.end());
 }
 
+DisplayResScreen::DisplayResScreen(int w, int h, int mw, int mh,
+                                   const short* rr, uint rr_length)
+    : width(w), height(h), width_mm(mw), height_mm(mh), custom(false)
+{
+    SetAspectRatio(-1.0);
+    for (uint i = 0; i < rr_length; ++i)
+    {
+        refreshRates.push_back((float)rr[i]);
+    }
+    sort(refreshRates.begin(), refreshRates.end());
+}
+
 DisplayResScreen::DisplayResScreen(const QString &str)
-    : width(0), height(0), width_mm(0), height_mm(0), aspect(-1.0)
+    : width(0), height(0), width_mm(0), height_mm(0), aspect(-1.0), custom(false)
 {
     refreshRates.clear();
     QStringList slist = QStringList::split(":", str);
@@ -43,7 +64,7 @@
         height_mm = slist[3].toInt();
         aspect = slist[4].toDouble();
         for (uint i = 5; i<slist.size(); ++i)
-            refreshRates.push_back(slist[i].toShort());
+            refreshRates.push_back(slist[i].toFloat());
     }
 }
 
@@ -80,22 +101,66 @@
     return dsr;
 }
 
+//compares if the float f1 is equal with f2 and returns 1 if true and 0 if false
+bool DisplayResScreen::compare_rates(float f1, float f2)
+{
+    float precision = 0.01;
+    if (((f1 - precision) < f2) && 
+        ((f1 + precision) > f2))
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
 int DisplayResScreen::FindBestMatch(const vector<DisplayResScreen>& dsr,
                                     const DisplayResScreen& d,
                                     short& target_rate)
 {
+    float target;
+    int i = FindBestMatch(dsr, d, target);
+    target_rate = target;
+    return i;
+}
+
+int DisplayResScreen::FindBestMatch(const vector<DisplayResScreen>& dsr,
+                                    const DisplayResScreen& d,
+                                    float& target_rate)
+{
+  // Amend vector with custom list
     for (uint i=0; i<dsr.size(); ++i)
     {
         if (dsr[i].Width()==d.Width() && dsr[i].Height()==d.Height())
         {
-            const vector<short>& rates = dsr[i].RefreshRates();
-            if (rates.size())
+            const vector<float>& rates = dsr[i].RefreshRates();
+            if (rates.size() && d.RefreshRate() != 0)
             {
-                vector<short>::const_iterator it =
-                    find(rates.begin(), rates.end(), d.RefreshRate());
-                target_rate = (it == rates.end()) ? *(--rates.end()) : *it;
-                return i;
+                for (uint j=0; j < rates.size(); ++j)
+                {
+                    // Multiple of target_rate will do
+                    if (compare_rates(d.RefreshRate(),rates[j]) || (fmod(rates[j],d.RefreshRate()) <= 0.01))
+                    {
+                      target_rate = rates[j];
+                      return i;
+                    }
+                }
+                // Can't find exact frame rate, so try rounding to the nearest integer, so 23.97Hz will work with 24Hz etc
+                for (uint j=0; j < rates.size(); ++j)
+                {
+                    float rounded = (float) ((int) (rates[j] + 0.5));
+                    // Multiple of target_rate will do
+                    if (compare_rates(d.RefreshRate(),rounded) || (fmod(rounded,d.RefreshRate()) <= 0.01))
+                    {
+                      target_rate = rounded;
+                              return i;
+                    }
+                }
+                target_rate = rates[rates.size() - 1];
             }
+            return i;
         }
     }
     return -1;
Index: 0.21-fixes/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp	2009-06-30 22:32:35.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp	2009-06-30 22:32:57.000000000 +1000
@@ -635,7 +635,8 @@
             GetDecoder()->GetVideoCodecID(),
             GetDecoder()->GetVideoCodecPrivate(),
             video_disp_dim, video_aspect,
-            widget->winId(), display_rect, 0 /*embedid*/);
+            widget->winId(), display_rect, (video_frame_rate * play_speed), 
+            0 /*embedid*/);
 
         if (!videoOutput)
         {
Index: 0.21-fixes/mythtv/libs/libmythtv/videoout_xv.cpp
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmythtv/videoout_xv.cpp	2009-06-30 22:32:35.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmythtv/videoout_xv.cpp	2009-06-30 22:32:57.000000000 +1000
@@ -405,7 +405,7 @@
     if ((width == 1920 || width == 1440) && height == 1088)
         height = 1080; // ATSC 1920x1080
 
-    if (display_res && display_res->SwitchToVideo(width, height))
+    if (display_res && display_res->SwitchToVideo(width, height, video_prate))
     {
         // Switching to custom display resolution succeeded
         // Make a note of the new size
Index: 0.21-fixes/mythtv/libs/libmythtv/videooutbase.cpp
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmythtv/videooutbase.cpp	2009-06-30 22:32:35.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmythtv/videooutbase.cpp	2009-06-30 22:32:57.000000000 +1000
@@ -68,7 +68,7 @@
         void          *codec_priv,
         const QSize   &video_dim, float        video_aspect,
         WId            win_id,    const QRect &display_rect,
-        WId            embed_id)
+        float          video_prate,     WId     embed_id)
 {
     (void) codec_priv;
 
@@ -167,6 +167,7 @@
 
         if (vo)
         {
+            vo->video_prate = video_prate;
             if (vo->Init(
                     video_dim.width(), video_dim.height(), video_aspect,
                     win_id, display_rect.x(), display_rect.y(),
@@ -406,6 +407,7 @@
 
 void VideoOutput::SetVideoFrameRate(float playback_fps)
 {
+    video_prate = playback_fps;
     db_vdisp_profile->SetOutput(playback_fps);
 }
 
Index: 0.21-fixes/mythtv/libs/libmythtv/videooutbase.h
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmythtv/videooutbase.h	2009-06-30 22:32:35.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmythtv/videooutbase.h	2009-06-30 22:32:57.000000000 +1000
@@ -36,7 +36,7 @@
         void          *codec_priv,
         const QSize   &video_dim, float        video_aspect,
         WId            win_id,    const QRect &display_rect,
-        WId            embed_id);
+        float video_prate,        WId          embed_id);
 
     VideoOutput();
     virtual ~VideoOutput();
@@ -276,6 +276,7 @@
     QSize   video_dim;        ///< Pixel dimensions of video buffer
     QSize   video_disp_dim;   ///< Pixel dimensions of video display area
     float   video_aspect;     ///< Physical aspect ratio of video
+    float   video_prate;      ///< Playback frame rate of video
 
     /// Normally this is the same as videoAspect, but may not be
     /// if the user has toggled the aspect override mode.
Index: 0.21-fixes/mythtv/programs/mythfrontend/globalsettings.cpp
===================================================================
--- 0.21-fixes.orig/mythtv/programs/mythfrontend/globalsettings.cpp	2009-06-30 22:32:42.000000000 +1000
+++ 0.21-fixes/mythtv/programs/mythfrontend/globalsettings.cpp	2009-06-30 22:32:57.000000000 +1000
@@ -2414,6 +2414,15 @@
     return gc;
 }
 
+static HostLineEdit *CustomScreenConfig()
+{
+    HostLineEdit *gedit = new HostLineEdit("CustomScreenRate");
+    gedit->setLabel(QObject::tr("Custom screen rate definition file"));
+    gedit->setHelpText(QObject::tr("Custom screen resolution configuration "
+                                        "for matching xrandr value."));
+    return gedit;
+}
+ 
 static HostSpinBox *VidModeWidth(int idx)
 {
     HostSpinBox *gs = new HostSpinBox(QString("VidModeWidth%1").arg(idx),
@@ -2582,9 +2591,15 @@
                     rate, SLOT(ChangeResolution(const QString&)));
         }
 
+        ConfigurationGroup* customscreensettings =
+            new HorizontalConfigurationGroup(false, false);
+
+        customscreensettings->addChild(CustomScreenConfig());
+
         ConfigurationGroup* settings = new VerticalConfigurationGroup(false);
         settings->addChild(defaultsettings);
         settings->addChild(overrides);
+        settings->addChild(customscreensettings);
 
         addTarget("1", settings);
         addTarget("0", new VerticalConfigurationGroup(true));
Index: 0.21-fixes/mythtv/libs/libmyth/DisplayResOSX.cpp
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmyth/DisplayResOSX.cpp	2009-06-30 22:32:42.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmyth/DisplayResOSX.cpp	2009-06-30 22:32:57.000000000 +1000
@@ -66,7 +66,7 @@
     return d;
 }
 
-bool DisplayResOSX::SwitchToVideoMode(int width, int height, short refreshrate)
+bool DisplayResOSX::SwitchToVideoMode(int width, int height, float refreshrate)
 {
     CGDirectDisplayID d = mythtv_display();
     CFDictionaryRef dispMode = NULL;
@@ -75,7 +75,7 @@
     // find mode that matches the desired size
     if (refreshrate)
         dispMode = CGDisplayBestModeForParametersAndRefreshRate(
-            d, 32, width, height, (CGRefreshRate)(refreshrate), &match);
+            d, 32, width, height, (CGRefreshRate)((short)refreshrate), &match);
 
     if (!match)
         dispMode = 
@@ -122,7 +122,7 @@
 
 	if (screen_map.find(key)==screen_map.end())
             screen_map[key] = DisplayResScreen(width, height,
-                                               0, 0, -1.0, refresh);
+                                               0, 0, -1.0, (float) refresh);
         else
             screen_map[key].AddRefreshRate(refresh);
     }
Index: 0.21-fixes/mythtv/libs/libmyth/DisplayResOSX.h
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmyth/DisplayResOSX.h	2009-06-30 22:32:42.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmyth/DisplayResOSX.h	2009-06-30 22:32:57.000000000 +1000
@@ -12,7 +12,7 @@
 
   protected:
     bool GetDisplaySize(int &width_mm, int &height_mm) const;
-    bool SwitchToVideoMode(int width, int height, short framerate);
+    bool SwitchToVideoMode(int width, int height, float framerate);
     
   private:
     mutable vector<DisplayResScreen> m_video_modes;
Index: 0.21-fixes/mythtv/libs/libmyth/DisplayResScreen.h
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmyth/DisplayResScreen.h	2009-06-30 22:32:42.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmyth/DisplayResScreen.h	2009-06-30 22:32:57.000000000 +1000
@@ -14,11 +14,15 @@
   public:
     // Constructors, initializers
     DisplayResScreen()
-        : width(0), height(0), width_mm(0), height_mm(0), aspect(-1.0) {;}
+        : width(0), height(0), width_mm(0), height_mm(0), aspect(-1.0), custom(false) {;}
     DisplayResScreen(int w, int h, int mw, int mh,
-                     double aspectRatio/* = -1.0*/, short refreshRate/* = 0*/);
+                     double aspectRatio/* = -1.0*/, float refreshRate/* = 0*/);
     DisplayResScreen(int w, int h, int mw, int mh,
-                     const vector<short>& refreshRates);
+                     const vector<float>& refreshRates);
+    DisplayResScreen(int w, int h, int mw, int mh,
+                     const vector<float>& refreshRates, const map<float, short>& realrates);
+    DisplayResScreen(int w, int h, int mw, int mh,
+                     const float* refreshRates, uint rr_length);
     DisplayResScreen(int w, int h, int mw, int mh,
                      const short* refreshRates, uint rr_length);
     DisplayResScreen(const QString &str);
@@ -29,17 +33,29 @@
     int Height() const { return height; }
     int Width_mm() const { return width_mm; }
     int Height_mm() const { return height_mm; }
+    bool Custom() const { return custom; }
+
     inline double AspectRatio() const;
-    inline short RefreshRate() const;
-    const vector<short>& RefreshRates() const { return refreshRates; }
+    inline float RefreshRate() const;
+    const vector<float>& RefreshRates() const { return refreshRates; }
 
     // Sets, adds
     void SetAspectRatio(double a);
-    void AddRefreshRate(short rr) {
+    void AddRefreshRate(float rr) {
         refreshRates.push_back(rr);
         sort(refreshRates.begin(), refreshRates.end());
     }
-
+    void ClearRefreshRates(void) {
+    	refreshRates.clear();
+    }	
+    void SetCustom(bool b) {
+    	custom = b;
+    }
+	
+    // Map for matching real rates and xrandr rate;
+    map<float, short> realRates;
+    map<short, float> xrandrRates;
+	
     // Converters & comparitors
     QString toString() const;
     inline bool operator < (const DisplayResScreen& b) const;
@@ -50,16 +66,22 @@
     static vector<DisplayResScreen> Convert(const QStringList& slist);
     static int FindBestMatch(const vector<DisplayResScreen>& dsr,
                              const DisplayResScreen& d,
+                             float& target_rate);
+    static int FindBestMatch(const vector<DisplayResScreen>& dsr,
+                             const DisplayResScreen& d,
                              short& target_rate);
     static inline int CalcKey(int w, int h, int rate);
+    static bool compare_rates(float f1, float f2);
 
   private:
     int width, height; // size in pixels
     int width_mm, height_mm; // physical size in millimeters
     double aspect; // aspect ratio, calculated or set
-    vector<short> refreshRates;
+    vector<float> refreshRates;
+    bool custom;	// Set if resolution was defined manually
 };
 
+
 typedef vector<DisplayResScreen>          DisplayResVector;
 typedef DisplayResVector::iterator        DisplayResVectorIt;
 typedef DisplayResVector::const_iterator  DisplayResVectorCIt;
@@ -85,11 +107,11 @@
     return aspect;
 }
 
-inline short DisplayResScreen::RefreshRate() const
+inline float DisplayResScreen::RefreshRate() const
 {
     if (refreshRates.size() >= 1)
         return refreshRates[0];
-    else return 0;
+    else return 0.0;
 }
 
 inline bool DisplayResScreen::operator < (const DisplayResScreen& b) const
Index: 0.21-fixes/mythtv/libs/libmyth/DisplayResX.cpp
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmyth/DisplayResX.cpp	2009-06-30 22:32:42.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmyth/DisplayResX.cpp	2009-06-30 22:32:57.000000000 +1000
@@ -4,6 +4,11 @@
 #include <cstring>
 #include <cstdlib>
 
+#include "mythcontext.h"
+#include <qregexp.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+
 #include "util-x11.h"
 
 #include <X11/extensions/Xrandr.h> // this has to be after util-x11.h (Qt bug)
@@ -32,9 +37,11 @@
     return false;
 }
 
-bool DisplayResX::SwitchToVideoMode(int width, int height, short desired_rate)
+bool DisplayResX::SwitchToVideoMode(int width, int height, float desired_rate)
 {
-    short rate;
+    float rate;
+    short finalrate;
+
     DisplayResScreen desired_screen(width, height, 0, 0, -1.0, desired_rate);
     int idx = DisplayResScreen::FindBestMatch(m_video_modes_unsorted,
                                               desired_screen, rate);
@@ -49,9 +56,23 @@
         Rotation rot;
         XRRConfigCurrentConfiguration(cfg, &rot);
         
+        // Search real xrandr rate for desired_rate
+        finalrate = (short) rate;
+        for (uint i=0; i < m_video_modes.size(); i++) {
+            if ((m_video_modes[i].Width() == width) && (m_video_modes[i].Height() == height))
+            {
+                if (m_video_modes[i].Custom())
+                {
+                    finalrate = m_video_modes[i].realRates[rate];
+                    VERBOSE(VB_PLAYBACK, QString("CustomRate Found, set %1Hz as %2") .arg(rate) .arg(finalrate));
+                }
+                break;
+            }
+        }
+    	       
         Window root = DefaultRootWindow(display);
         Status status = XRRSetScreenConfigAndRate(display, cfg, root, idx,
-                                                  rot, rate, CurrentTime);
+                                                  rot, finalrate, CurrentTime);
         
         XRRFreeScreenConfigInfo(cfg);
         XCloseDisplay(display);
@@ -87,6 +108,90 @@
                              rates, num_rates);
         m_video_modes.push_back(scr);
     }
+
+    QString customscreen = gContext->GetSetting("CustomScreenRate");
+    if (gContext->GetNumSetting("UseVideoModes", 0) && customscreen.length());
+    {
+        map<uint, DisplayResScreen> customscr;
+        
+        QFileInfo fi(customscreen);
+        QFile file(customscreen);
+	
+        if (!fi.exists() || !fi.isFile())
+        {
+            VERBOSE(VB_PLAYBACK, QString("CustomScreenRate: \"%1\" failed: does not exist or isn't a file")
+                    .arg(customscreen));
+        }
+        else if ( file.open(IO_ReadOnly) )
+        {
+            QRegExp regexp = QRegExp("^\\s*(\\d+),(\\d+),(\\d+\\.?\\d*),(\\d+)\\s*$");
+            QTextStream stream( &file );
+            QString line;
+            int pos;
+            while ( !stream.atEnd() )
+            {
+                pos = regexp.search(stream.readLine());
+                if (pos > -1)
+                {
+                    int w = regexp.cap(1).toInt();
+                    int h = regexp.cap(2).toInt();
+                    float hz = regexp.cap(3).toFloat();
+                    int xrandrhz = regexp.cap(4).toShort();
+                    uint key = DisplayResScreen::CalcKey(w, h, 0);
+                    // Check if that resolution has already been defined, and if not create a new screen
+                    if (customscr.find(key) == customscr.end())
+                    {
+                        customscr[key] = DisplayResScreen(w, h, 0, 0, 0, hz);
+                    }
+                    else
+                    {
+                        customscr[key].AddRefreshRate(hz);
+                    }
+                    customscr[key].realRates[hz] = xrandrhz;
+                    customscr[key].xrandrRates[xrandrhz] = hz;
+                }
+            }
+            file.close();
+
+            // Update existing DisplayResScreen vector, and update it with new frequencies
+            for (uint i=0; i < m_video_modes.size(); i++)
+            {
+                DisplayResScreen scr = m_video_modes[i];
+                int w = scr.Width();
+                int h = scr.Height();
+                int mw = scr.Width_mm();
+                int mh = scr.Height_mm();
+                uint key = DisplayResScreen::CalcKey(w, h, 0);
+                if (customscr.find(key) != customscr.end())
+                {
+                    // Found custom information for that resolution
+                    // Replace xrandr refresh rate, with real one
+                    vector<float> newrates;
+                    map<float, short> realRates;
+                    const vector<float>& rates = scr.RefreshRates();
+                    bool found = false;
+                    for (vector<float>::const_iterator it = rates.begin() ; it !=  rates.end();  it++)
+                    {
+                        if (customscr[key].xrandrRates.find(*it) != customscr[key].xrandrRates.end())
+                        {
+                            // Defined in custom rate, use it
+                            newrates.push_back(customscr[key].xrandrRates[*it]);
+                            realRates[customscr[key].xrandrRates[*it]] = *it;
+                            found = true;
+                            VERBOSE(VB_PLAYBACK, QString("CustomRate Found, set %1 as %2Hz") .arg(*it) .arg(customscr[key].xrandrRates[*it]));
+                        }
+                    }
+                    if (found)
+                    {
+                        m_video_modes.erase(m_video_modes.begin() + i);
+                        sort(newrates.begin(), newrates.end());
+                        m_video_modes.insert(m_video_modes.begin() + i, DisplayResScreen(w, h, mw, mh, newrates, realRates));
+                    }
+                }
+            }
+        }
+    }
+
     m_video_modes_unsorted = m_video_modes;
     sort(m_video_modes.begin(), m_video_modes.end());
 
Index: 0.21-fixes/mythtv/libs/libmyth/DisplayResX.h
===================================================================
--- 0.21-fixes.orig/mythtv/libs/libmyth/DisplayResX.h	2009-06-30 22:32:42.000000000 +1000
+++ 0.21-fixes/mythtv/libs/libmyth/DisplayResX.h	2009-06-30 22:32:57.000000000 +1000
@@ -12,7 +12,7 @@
 
   protected:
     bool GetDisplaySize(int &width_mm, int &height_mm) const;
-    bool SwitchToVideoMode(int width, int height, short framerate);
+    bool SwitchToVideoMode(int width, int height, float framerate);
 
   private:
     mutable vector<DisplayResScreen> m_video_modes;

