diff -Naur --exclude=.svn mythtv.opengl/adjust_rate3.patch~ mythtv/adjust_rate3.patch~
--- mythtv.opengl/adjust_rate3.patch~	1970-01-01 10:00:00.000000000 +1000
+++ mythtv/adjust_rate3.patch~	2009-05-16 22:26:45.000000000 +1000
@@ -0,0 +1,935 @@
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayRes.cpp mythtv/libs/libmyth/DisplayRes.cpp
+--- mythtv.opengl/libs/libmyth/DisplayRes.cpp	2009-05-02 07:32:08.000000000 +1000
++++ mythtv/libs/libmyth/DisplayRes.cpp	2009-05-16 21:10:25.000000000 +1000
+@@ -37,16 +37,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 +64,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,11 +82,18 @@
+     return true;
+ }
+ 
+-bool DisplayRes::SwitchToVideo(int iwidth, int iheight, short irate)
++bool DisplayRes::SwitchToVideo(int iwidth, int iheight, short irate, 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);
+     DisplayResMapCIt it = in_size_to_output_mode.find(key);
+@@ -94,9 +101,9 @@
+         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 +135,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 +163,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)
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayRes.h mythtv/libs/libmyth/DisplayRes.h
+--- mythtv.opengl/libs/libmyth/DisplayRes.h	2009-05-02 07:32:09.000000000 +1000
++++ mythtv/libs/libmyth/DisplayRes.h	2009-05-15 16:57:30.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, short irate = 0, 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;
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResOSX.cpp mythtv/libs/libmyth/DisplayResOSX.cpp
+--- mythtv.opengl/libs/libmyth/DisplayResOSX.cpp	2009-05-02 07:32:08.000000000 +1000
++++ mythtv/libs/libmyth/DisplayResOSX.cpp	2009-05-15 16:57:30.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);
+     }
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResOSX.h mythtv/libs/libmyth/DisplayResOSX.h
+--- mythtv.opengl/libs/libmyth/DisplayResOSX.h	2009-05-02 07:32:08.000000000 +1000
++++ mythtv/libs/libmyth/DisplayResOSX.h	2009-05-15 16:57:30.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;
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResScreen.cpp mythtv/libs/libmyth/DisplayResScreen.cpp
+--- mythtv.opengl/libs/libmyth/DisplayResScreen.cpp	2009-05-02 07:32:08.000000000 +1000
++++ mythtv/libs/libmyth/DisplayResScreen.cpp	2009-05-15 16:57:30.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,15 @@
+ }
+ 
+ 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 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 +30,19 @@
+     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 +56,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 +93,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;
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResScreen.h mythtv/libs/libmyth/DisplayResScreen.h
+--- mythtv.opengl/libs/libmyth/DisplayResScreen.h	2009-05-02 07:32:08.000000000 +1000
++++ mythtv/libs/libmyth/DisplayResScreen.h	2009-05-16 18:29:21.000000000 +1000
+@@ -14,11 +14,13 @@
+   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 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 +31,28 @@
+     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;
++	
+     // Converters & comparitors
+     QString toString() const;
+     inline bool operator < (const DisplayResScreen& b) const;
+@@ -50,16 +63,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 +104,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
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResX.cpp mythtv/libs/libmyth/DisplayResX.cpp
+--- mythtv.opengl/libs/libmyth/DisplayResX.cpp	2009-05-02 07:32:08.000000000 +1000
++++ mythtv/libs/libmyth/DisplayResX.cpp	2009-05-16 18:44:28.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 (int 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,60 @@
+                              rates, num_rates);
+         m_video_modes.push_back(scr);
+     }
++
++    QString customscreen = gContext->GetSetting("CustomScreenRate");
++    if (gContext->GetNumSetting("UseVideoModes", 0) && !customscreen.size());
++    {
++        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();
++                    int found = -1;
++                    VERBOSE(VB_PLAYBACK, QString("Found definition for %1x%2 @ %3Hz (xrandr: %4)")
++                            .arg(w) .arg(h) .arg(hz) .arg(xrandrhz));
++                    // find if video mode already exist, and remove refresh rates for custom one
++                    for (int i=0; i < m_video_modes.size(); i++) {
++                        if ((m_video_modes[i].Width() == w) && (m_video_modes[i].Height() == h))
++                        {
++                            found = i;
++                            if (!m_video_modes[i].Custom())
++                            {
++                                m_video_modes[i].ClearRefreshRates();
++                                m_video_modes[i].SetCustom(true);
++                            }
++                            m_video_modes[i].AddRefreshRate(hz);
++                            m_video_modes[i].realRates[hz] = xrandrhz;
++                            break;
++                        }
++                    }
++                    if (found < 0)
++                    {
++                        DisplayResScreen scr(w, h, 0, 0, -1.0, hz);
++                        scr.SetCustom(true);
++                        m_video_modes.push_back(scr);
++                    }
++                }
++            }
++            file.close();
++        }
++    }
++
+     m_video_modes_unsorted = m_video_modes;
+     sort(m_video_modes.begin(), m_video_modes.end());
+ 
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResX.h mythtv/libs/libmyth/DisplayResX.h
+--- mythtv.opengl/libs/libmyth/DisplayResX.h	2009-05-02 07:32:08.000000000 +1000
++++ mythtv/libs/libmyth/DisplayResX.h	2009-05-15 16:57:30.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;
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/NuppelVideoPlayer.cpp mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
+--- mythtv.opengl/libs/libmythtv/NuppelVideoPlayer.cpp	2009-05-15 16:58:34.000000000 +1000
++++ mythtv/libs/libmythtv/NuppelVideoPlayer.cpp	2009-05-16 19:13:30.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)
+         {
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_d3d.cpp mythtv/libs/libmythtv/videoout_d3d.cpp
+--- mythtv.opengl/libs/libmythtv/videoout_d3d.cpp	2009-05-02 07:30:34.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_d3d.cpp	2009-05-16 19:16:43.000000000 +1000
+@@ -451,7 +451,7 @@
+ 
+ bool VideoOutputD3D::Init(int width, int height, float aspect,
+                           WId winid, int winx, int winy, int winw,
+-                          int winh, WId embedid)
++                          int winh, float video_prate, WId embedid)
+ {
+     VERBOSE(VB_PLAYBACK, LOC +
+             "Init w=" << width << " h=" << height);
+@@ -462,8 +462,8 @@
+                   kPrebufferFramesNormal, kPrebufferFramesSmall,
+                   kKeepPrebuffer);
+ 
+-    VideoOutput::Init(width, height, aspect, winid,
+-                      winx, winy, winw, winh, embedid);
++    VideoOutput::Init(width, height, aspect, winid, winx, 
++                      winy, winw, winh, video_prate, embedid);
+ 
+     m_hWnd = winid;
+ 
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_d3d.h mythtv/libs/libmythtv/videoout_d3d.h
+--- mythtv.opengl/libs/libmythtv/videoout_d3d.h	2009-05-02 07:30:34.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_d3d.h	2009-05-16 19:17:02.000000000 +1000
+@@ -20,7 +20,8 @@
+    ~VideoOutputD3D();
+ 
+     bool Init(int width, int height, float aspect, WId winid,
+-              int winx, int winy, int winw, int winh, WId embedid = 0);
++              int winx, int winy, int winw, int winh, 
++              float video_prate, WId embedid = 0);
+ 
+     bool InitD3D();
+     void UnInitD3D();
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_directfb.cpp mythtv/libs/libmythtv/videoout_directfb.cpp
+--- mythtv.opengl/libs/libmythtv/videoout_directfb.cpp	2009-05-02 07:30:34.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_directfb.cpp	2009-05-15 16:57:30.000000000 +1000
+@@ -353,7 +353,7 @@
+ 
+ bool VideoOutputDirectfb::Init(int width, int height, float aspect, WId winid,
+                                int winx, int winy, int winw, int winh,
+-                               WId embedid)
++                               float video_prate, WId embedid)
+ {
+     // Hack to avoid embedded video output...
+     if ((winw < 320) || (winh < 240))
+@@ -646,7 +646,7 @@
+                            display_visible_rect.y(),
+                            display_visible_rect.width(),
+                            display_visible_rect.height(),
+-                           embedid))
++                           video_prate, embedid))
+     {
+         return false;
+     }
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_directfb.h mythtv/libs/libmythtv/videoout_directfb.h
+--- mythtv.opengl/libs/libmythtv/videoout_directfb.h	2009-05-02 07:30:35.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_directfb.h	2009-05-16 20:21:24.000000000 +1000
+@@ -14,7 +14,8 @@
+     ~VideoOutputDirectfb();
+ 
+     bool Init(int width, int height, float aspect, WId winid,
+-              int winx, int winy, int winw, int winh, WId embedid = 0);
++              int winx, int winy, int winw, int winh, 
++              float video_prate, WId embedid = 0);
+ 
+     void ProcessFrame(VideoFrame *frame, OSD *osd,
+                       FilterChain *filterList,
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_dx.cpp mythtv/libs/libmythtv/videoout_dx.cpp
+--- mythtv.opengl/libs/libmythtv/videoout_dx.cpp	2009-05-02 07:30:36.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_dx.cpp	2009-05-16 20:56:37.000000000 +1000
+@@ -158,16 +158,16 @@
+ }
+ 
+ bool VideoOutputDX::Init(int width, int height, float aspect,
+-                           WId winid, int winx, int winy, int winw, 
+-                           int winh, WId embedid)
++                         WId winid, int winx, int winy, int winw, 
++                         int winh, float video_prate, WId embedid)
+ {
+     db_vdisp_profile->SetVideoRenderer("directx");
+ 
+     vbuffers.Init(kNumBuffers, true, kNeedFreeFrames, 
+                   kPrebufferFramesNormal, kPrebufferFramesSmall, 
+                   kKeepPrebuffer);
+-    VideoOutput::Init(width, height, aspect, winid,
+-                      winx, winy, winw, winh, embedid);
++    VideoOutput::Init(width, height, aspect, winid, winx, 
++                      winy, winw, winh, video_prate, embedid);
+ 
+     wnd = winid;
+ 
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_dx.h mythtv/libs/libmythtv/videoout_dx.h
+--- mythtv.opengl/libs/libmythtv/videoout_dx.h	2009-05-02 07:30:34.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_dx.h	2009-05-16 20:38:14.000000000 +1000
+@@ -21,7 +21,8 @@
+    ~VideoOutputDX();
+ 
+     bool Init(int width, int height, float aspect, WId winid,
+-              int winx, int winy, int winw, int winh, WId embedid = 0);
++              int winx, int winy, int winw, int winh, 
++              float video_prate, WId embedid = 0);
+     void PrepareFrame(VideoFrame *buffer, FrameScanType);
+     void Show(FrameScanType );
+ 
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_ivtv.cpp mythtv/libs/libmythtv/videoout_ivtv.cpp
+--- mythtv.opengl/libs/libmythtv/videoout_ivtv.cpp	2009-05-02 07:30:35.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_ivtv.cpp	2009-05-15 16:57:30.000000000 +1000
+@@ -405,7 +405,7 @@
+ 
+ bool VideoOutputIvtv::Init(int width, int height, float aspect, 
+                            WId winid, int winx, int winy, int winw, 
+-                           int winh, WId embedid)
++                           int winh, float video_prate, WId embedid)
+ {
+     VERBOSE(VB_PLAYBACK, LOC + "Init() -- begin");
+ 
+@@ -416,7 +416,7 @@
+     videoDevice = gContext->GetSetting("PVR350VideoDev");
+ 
+     VideoOutput::Init(width, height, aspect, winid, winx, winy, winw, winh, 
+-                      embedid);
++                      video_prate, embedid);
+ 
+     osdbufsize = video_dim.width() * video_dim.height() * 4;
+ 
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_ivtv.h mythtv/libs/libmythtv/videoout_ivtv.h
+--- mythtv.opengl/libs/libmythtv/videoout_ivtv.h	2009-05-02 07:30:34.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_ivtv.h	2009-05-16 20:24:09.000000000 +1000
+@@ -16,7 +16,8 @@
+    ~VideoOutputIvtv();
+ 
+     bool Init(int width, int height, float aspect, WId winid,
+-              int winx, int winy, int winw, int winh, WId embedid = 0);
++              int winx, int winy, int winw, int winh,
++              float video_prate, WId embedid = 0);
+     void PrepareFrame(VideoFrame *buffer, FrameScanType);
+     void Show(FrameScanType );
+ 
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_null.cpp mythtv/libs/libmythtv/videoout_null.cpp
+--- mythtv.opengl/libs/libmythtv/videoout_null.cpp	2009-05-02 07:30:35.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_null.cpp	2009-05-16 20:25:07.000000000 +1000
+@@ -115,15 +115,15 @@
+ 
+ bool VideoOutputNull::Init(int width, int height, float aspect,
+                            WId winid, int winx, int winy, int winw, 
+-                           int winh, WId embedid)
++                           int winh, float video_prate, WId embedid)
+ {
+     if ((width <= 0) || (height <= 0))
+         return false;
+ 
+     QMutexLocker locker(&global_lock);
+ 
+-    VideoOutput::Init(width, height, aspect, winid,
+-                      winx, winy, winw, winh, embedid);
++    VideoOutput::Init(width, height, aspect, winid, winx, 
++                      winy, winw, winh, video_prate, embedid);
+ 
+     vbuffers.Init(kNumBuffers, true, kNeedFreeFrames, 
+                   kPrebufferFramesNormal, kPrebufferFramesSmall, 
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_null.h mythtv/libs/libmythtv/videoout_null.h
+--- mythtv.opengl/libs/libmythtv/videoout_null.h	2009-05-02 07:30:36.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_null.h	2009-05-16 20:25:34.000000000 +1000
+@@ -12,7 +12,8 @@
+    ~VideoOutputNull();
+ 
+     bool Init(int width, int height, float aspect, WId winid,
+-              int winx, int winy, int winw, int winh, WId embedid = 0);
++              int winx, int winy, int winw, int winh,
++              float video_prate, WId embedid = 0);
+ 
+     bool SetupDeinterlace(bool, const QString &ovrf = "")
+         { (void)ovrf; return false; } // we don't deinterlace in null output..
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_quartz.cpp mythtv/libs/libmythtv/videoout_quartz.cpp
+--- mythtv.opengl/libs/libmythtv/videoout_quartz.cpp	2009-05-02 07:30:34.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_quartz.cpp	2009-05-16 20:27:22.000000000 +1000
+@@ -1192,8 +1192,8 @@
+ }
+ 
+ bool VideoOutputQuartz::Init(int width, int height, float aspect,
+-                             WId winid, int winx, int winy,
+-                             int winw, int winh, WId embedid)
++                             WId winid, int winx, int winy, int winw,
++                             int winh, float video_prate, WId embedid)
+ {
+     VERBOSE(VB_PLAYBACK, LOC +
+             QString("Init(WxH %1x%2, aspect=%3, winid=%4\n\t\t\t"
+@@ -1215,8 +1215,8 @@
+     vbuffers.Init(kNumBuffers, true, kNeedFreeFrames,
+                   kPrebufferFramesNormal, kPrebufferFramesSmall,
+                   kKeepPrebuffer);
+-    VideoOutput::Init(width, height, aspect, winid,
+-                      winx, winy, winw, winh, embedid);
++    VideoOutput::Init(width, height, aspect, winid, winx, 
++                      winy, winw, winh, video_prate, embedid);
+ 
+     data->srcWidth  = video_dim.width();
+     data->srcHeight = video_dim.height();
+@@ -1381,6 +1381,7 @@
+ 
+ void VideoOutputQuartz::SetVideoFrameRate(float playback_fps)
+ {
++    video_prate = playback_fps;
+     VERBOSE(VB_PLAYBACK, "SetVideoFrameRate("<<playback_fps<<")");
+ }
+ 
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_quartz.h mythtv/libs/libmythtv/videoout_quartz.h
+--- mythtv.opengl/libs/libmythtv/videoout_quartz.h	2009-05-02 07:30:36.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_quartz.h	2009-05-16 20:27:58.000000000 +1000
+@@ -13,7 +13,8 @@
+    ~VideoOutputQuartz();
+ 
+     bool Init(int width, int height, float aspect, WId winid,
+-              int winx, int winy, int winw, int winh, WId embedid = 0);
++              int winx, int winy, int winw, int winh, 
++              float video_prate, WId embedid = 0);
+     void SetVideoFrameRate(float playback_fps);
+     void PrepareFrame(VideoFrame *buffer, FrameScanType t);
+     void Show(FrameScanType);
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_xv.cpp mythtv/libs/libmythtv/videoout_xv.cpp
+--- mythtv.opengl/libs/libmythtv/videoout_xv.cpp	2009-05-15 16:58:35.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_xv.cpp	2009-05-16 20:48:13.000000000 +1000
+@@ -450,7 +450,9 @@
+     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, 
++                                                  (short) roundf(video_prate),
++                                                  video_prate))
+     {
+         // Switching to custom display resolution succeeded
+         // Make a note of the new size
+@@ -1698,14 +1700,14 @@
+ }
+ 
+ /**
+- * \fn VideoOutputXv::Init(int,int,float,WId,int,int,int,int,WId)
++ * \fn VideoOutputXv::Init(int,int,float,WId,int,int,int,int,float,WId)
+  * Initializes class for video output.
+  *
+  * \return success or failure.
+  */
+ bool VideoOutputXv::Init(
+-    int width, int height, float aspect,
+-    WId winid, int winx, int winy, int winw, int winh, WId embedid)
++    int width, int height, float aspect, WId winid, int winx, 
++    int winy, int winw, int winh, float video_prate, WId embedid)
+ {
+     needrepaint = true;
+ 
+@@ -1739,7 +1741,7 @@
+     // Basic setup
+     VideoOutput::Init(width, height, aspect,
+                       winid, winx, winy, winw, winh,
+-                      embedid);
++                      video_prate, embedid);
+ 
+     // Set resolution/measurements (check XRandR, Xinerama, config settings)
+     InitDisplayMeasurements(width, height);
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_xv.h mythtv/libs/libmythtv/videoout_xv.h
+--- mythtv.opengl/libs/libmythtv/videoout_xv.h	2009-05-15 16:58:35.000000000 +1000
++++ mythtv/libs/libmythtv/videoout_xv.h	2009-05-16 20:29:46.000000000 +1000
+@@ -62,7 +62,8 @@
+    ~VideoOutputXv();
+ 
+     bool Init(int width, int height, float aspect, WId winid,
+-              int winx, int winy, int winw, int winh, WId embedid = 0);
++              int winx, int winy, int winw, int winh, 
++              float video_prate, WId embedid = 0);
+ 
+     bool SetDeinterlacingEnabled(bool);
+     bool SetupDeinterlace(bool interlaced, const QString& ovrf="");
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videooutbase.cpp mythtv/libs/libmythtv/videooutbase.cpp
+--- mythtv.opengl/libs/libmythtv/videooutbase.cpp	2009-05-15 16:58:35.000000000 +1000
++++ mythtv/libs/libmythtv/videooutbase.cpp	2009-05-16 20:53:44.000000000 +1000
+@@ -71,7 +71,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;
+ 
+@@ -170,10 +170,12 @@
+ 
+         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(),
+-                    display_rect.width(), display_rect.height(), embed_id))
++                    display_rect.width(), display_rect.height(),
++                    video_prate, embed_id))
+             {
+                 return vo;
+             }
+@@ -367,7 +369,8 @@
+  * \return true if successful, false otherwise.
+  */
+ bool VideoOutput::Init(int width, int height, float aspect, WId winid,
+-                       int winx, int winy, int winw, int winh, WId embedid)
++                       int winx, int winy, int winw, int winh,
++                       float video_prate, WId embedid)
+ {
+     (void)winid;
+     (void)embedid;
+@@ -409,6 +412,7 @@
+ 
+ void VideoOutput::SetVideoFrameRate(float playback_fps)
+ {
++    video_prate = playback_fps;
+     db_vdisp_profile->SetOutput(playback_fps);
+ }
+ 
+diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videooutbase.h mythtv/libs/libmythtv/videooutbase.h
+--- mythtv.opengl/libs/libmythtv/videooutbase.h	2009-05-15 16:58:35.000000000 +1000
++++ mythtv/libs/libmythtv/videooutbase.h	2009-05-16 20:49:57.000000000 +1000
+@@ -36,14 +36,14 @@
+         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();
+ 
+     virtual bool Init(int width, int height, float aspect,
+                       WId winid, int winx, int winy, int winw, 
+-                      int winh, WId embedid = 0);
++                      int winh, float video_prate, WId embedid = 0);
+     virtual void InitOSD(OSD *osd);
+     virtual void SetVideoFrameRate(float);
+ 
+@@ -279,6 +279,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.
+diff -Naur --exclude=.svn mythtv.opengl/programs/mythfrontend/globalsettings.cpp mythtv/programs/mythfrontend/globalsettings.cpp
+--- mythtv.opengl/programs/mythfrontend/globalsettings.cpp	2009-05-02 07:32:18.000000000 +1000
++++ mythtv/programs/mythfrontend/globalsettings.cpp	2009-05-15 16:57:30.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,16 @@
+                     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));
diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayRes.cpp mythtv/libs/libmyth/DisplayRes.cpp
--- mythtv.opengl/libs/libmyth/DisplayRes.cpp	2009-05-02 07:32:08.000000000 +1000
+++ mythtv/libs/libmyth/DisplayRes.cpp	2009-05-16 21:10:25.000000000 +1000
@@ -37,16 +37,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 +64,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,11 +82,18 @@
     return true;
 }
 
-bool DisplayRes::SwitchToVideo(int iwidth, int iheight, short irate)
+bool DisplayRes::SwitchToVideo(int iwidth, int iheight, short irate, 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);
     DisplayResMapCIt it = in_size_to_output_mode.find(key);
@@ -94,9 +101,9 @@
         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 +135,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 +163,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)
diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayRes.h mythtv/libs/libmyth/DisplayRes.h
--- mythtv.opengl/libs/libmyth/DisplayRes.h	2009-05-02 07:32:09.000000000 +1000
+++ mythtv/libs/libmyth/DisplayRes.h	2009-05-16 22:27:15.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, short irate = 0, 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;
diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResOSX.cpp mythtv/libs/libmyth/DisplayResOSX.cpp
--- mythtv.opengl/libs/libmyth/DisplayResOSX.cpp	2009-05-02 07:32:08.000000000 +1000
+++ mythtv/libs/libmyth/DisplayResOSX.cpp	2009-05-15 16:57:30.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);
     }
diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResOSX.h mythtv/libs/libmyth/DisplayResOSX.h
--- mythtv.opengl/libs/libmyth/DisplayResOSX.h	2009-05-02 07:32:08.000000000 +1000
+++ mythtv/libs/libmyth/DisplayResOSX.h	2009-05-15 16:57:30.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;
diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResScreen.cpp mythtv/libs/libmyth/DisplayResScreen.cpp
--- mythtv.opengl/libs/libmyth/DisplayResScreen.cpp	2009-05-02 07:32:08.000000000 +1000
+++ mythtv/libs/libmyth/DisplayResScreen.cpp	2009-05-15 16:57:30.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,15 @@
 }
 
 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 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 +30,19 @@
     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 +56,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 +93,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;
diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResScreen.h mythtv/libs/libmyth/DisplayResScreen.h
--- mythtv.opengl/libs/libmyth/DisplayResScreen.h	2009-05-02 07:32:08.000000000 +1000
+++ mythtv/libs/libmyth/DisplayResScreen.h	2009-05-16 21:27:59.000000000 +1000
@@ -14,11 +14,13 @@
   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 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 +31,28 @@
     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;
+	
     // Converters & comparitors
     QString toString() const;
     inline bool operator < (const DisplayResScreen& b) const;
@@ -50,16 +63,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 +104,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
diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResX.cpp mythtv/libs/libmyth/DisplayResX.cpp
--- mythtv.opengl/libs/libmyth/DisplayResX.cpp	2009-05-02 07:32:08.000000000 +1000
+++ mythtv/libs/libmyth/DisplayResX.cpp	2009-05-16 23:07:42.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,60 @@
                              rates, num_rates);
         m_video_modes.push_back(scr);
     }
+
+    QString customscreen = gContext->GetSetting("CustomScreenRate");
+    if (gContext->GetNumSetting("UseVideoModes", 0) && !customscreen.length());
+    {
+        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();
+                    int found = -1;
+                    VERBOSE(VB_PLAYBACK, QString("Found definition for %1x%2 @ %3Hz (xrandr: %4)")
+                            .arg(w) .arg(h) .arg(hz) .arg(xrandrhz));
+                    // find if video mode already exist, and remove refresh rates for custom one
+                    for (uint i=0; i < m_video_modes.size(); i++) {
+                        if ((m_video_modes[i].Width() == w) && (m_video_modes[i].Height() == h))
+                        {
+                            found = i;
+                            if (!m_video_modes[i].Custom())
+                            {
+                                m_video_modes[i].ClearRefreshRates();
+                                m_video_modes[i].SetCustom(true);
+                            }
+                            m_video_modes[i].AddRefreshRate(hz);
+                            m_video_modes[i].realRates[hz] = xrandrhz;
+                            break;
+                        }
+                    }
+                    if (found < 0)
+                    {
+                        DisplayResScreen scr(w, h, 0, 0, -1.0, hz);
+                        scr.SetCustom(true);
+                        m_video_modes.push_back(scr);
+                    }
+                }
+            }
+            file.close();
+        }
+    }
+
     m_video_modes_unsorted = m_video_modes;
     sort(m_video_modes.begin(), m_video_modes.end());
 
diff -Naur --exclude=.svn mythtv.opengl/libs/libmyth/DisplayResX.h mythtv/libs/libmyth/DisplayResX.h
--- mythtv.opengl/libs/libmyth/DisplayResX.h	2009-05-02 07:32:08.000000000 +1000
+++ mythtv/libs/libmyth/DisplayResX.h	2009-05-15 16:57:30.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;
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/NuppelVideoPlayer.cpp mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
--- mythtv.opengl/libs/libmythtv/NuppelVideoPlayer.cpp	2009-05-15 16:58:34.000000000 +1000
+++ mythtv/libs/libmythtv/NuppelVideoPlayer.cpp	2009-05-16 19:13:30.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)
         {
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_d3d.cpp mythtv/libs/libmythtv/videoout_d3d.cpp
--- mythtv.opengl/libs/libmythtv/videoout_d3d.cpp	2009-05-02 07:30:34.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_d3d.cpp	2009-05-16 19:16:43.000000000 +1000
@@ -451,7 +451,7 @@
 
 bool VideoOutputD3D::Init(int width, int height, float aspect,
                           WId winid, int winx, int winy, int winw,
-                          int winh, WId embedid)
+                          int winh, float video_prate, WId embedid)
 {
     VERBOSE(VB_PLAYBACK, LOC +
             "Init w=" << width << " h=" << height);
@@ -462,8 +462,8 @@
                   kPrebufferFramesNormal, kPrebufferFramesSmall,
                   kKeepPrebuffer);
 
-    VideoOutput::Init(width, height, aspect, winid,
-                      winx, winy, winw, winh, embedid);
+    VideoOutput::Init(width, height, aspect, winid, winx, 
+                      winy, winw, winh, video_prate, embedid);
 
     m_hWnd = winid;
 
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_d3d.h mythtv/libs/libmythtv/videoout_d3d.h
--- mythtv.opengl/libs/libmythtv/videoout_d3d.h	2009-05-02 07:30:34.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_d3d.h	2009-05-16 19:17:02.000000000 +1000
@@ -20,7 +20,8 @@
    ~VideoOutputD3D();
 
     bool Init(int width, int height, float aspect, WId winid,
-              int winx, int winy, int winw, int winh, WId embedid = 0);
+              int winx, int winy, int winw, int winh, 
+              float video_prate, WId embedid = 0);
 
     bool InitD3D();
     void UnInitD3D();
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_directfb.cpp mythtv/libs/libmythtv/videoout_directfb.cpp
--- mythtv.opengl/libs/libmythtv/videoout_directfb.cpp	2009-05-02 07:30:34.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_directfb.cpp	2009-05-15 16:57:30.000000000 +1000
@@ -353,7 +353,7 @@
 
 bool VideoOutputDirectfb::Init(int width, int height, float aspect, WId winid,
                                int winx, int winy, int winw, int winh,
-                               WId embedid)
+                               float video_prate, WId embedid)
 {
     // Hack to avoid embedded video output...
     if ((winw < 320) || (winh < 240))
@@ -646,7 +646,7 @@
                            display_visible_rect.y(),
                            display_visible_rect.width(),
                            display_visible_rect.height(),
-                           embedid))
+                           video_prate, embedid))
     {
         return false;
     }
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_directfb.h mythtv/libs/libmythtv/videoout_directfb.h
--- mythtv.opengl/libs/libmythtv/videoout_directfb.h	2009-05-02 07:30:35.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_directfb.h	2009-05-16 20:21:24.000000000 +1000
@@ -14,7 +14,8 @@
     ~VideoOutputDirectfb();
 
     bool Init(int width, int height, float aspect, WId winid,
-              int winx, int winy, int winw, int winh, WId embedid = 0);
+              int winx, int winy, int winw, int winh, 
+              float video_prate, WId embedid = 0);
 
     void ProcessFrame(VideoFrame *frame, OSD *osd,
                       FilterChain *filterList,
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_dx.cpp mythtv/libs/libmythtv/videoout_dx.cpp
--- mythtv.opengl/libs/libmythtv/videoout_dx.cpp	2009-05-02 07:30:36.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_dx.cpp	2009-05-16 20:56:37.000000000 +1000
@@ -158,16 +158,16 @@
 }
 
 bool VideoOutputDX::Init(int width, int height, float aspect,
-                           WId winid, int winx, int winy, int winw, 
-                           int winh, WId embedid)
+                         WId winid, int winx, int winy, int winw, 
+                         int winh, float video_prate, WId embedid)
 {
     db_vdisp_profile->SetVideoRenderer("directx");
 
     vbuffers.Init(kNumBuffers, true, kNeedFreeFrames, 
                   kPrebufferFramesNormal, kPrebufferFramesSmall, 
                   kKeepPrebuffer);
-    VideoOutput::Init(width, height, aspect, winid,
-                      winx, winy, winw, winh, embedid);
+    VideoOutput::Init(width, height, aspect, winid, winx, 
+                      winy, winw, winh, video_prate, embedid);
 
     wnd = winid;
 
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_dx.h mythtv/libs/libmythtv/videoout_dx.h
--- mythtv.opengl/libs/libmythtv/videoout_dx.h	2009-05-02 07:30:34.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_dx.h	2009-05-16 20:38:14.000000000 +1000
@@ -21,7 +21,8 @@
    ~VideoOutputDX();
 
     bool Init(int width, int height, float aspect, WId winid,
-              int winx, int winy, int winw, int winh, WId embedid = 0);
+              int winx, int winy, int winw, int winh, 
+              float video_prate, WId embedid = 0);
     void PrepareFrame(VideoFrame *buffer, FrameScanType);
     void Show(FrameScanType );
 
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_ivtv.cpp mythtv/libs/libmythtv/videoout_ivtv.cpp
--- mythtv.opengl/libs/libmythtv/videoout_ivtv.cpp	2009-05-02 07:30:35.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_ivtv.cpp	2009-05-15 16:57:30.000000000 +1000
@@ -405,7 +405,7 @@
 
 bool VideoOutputIvtv::Init(int width, int height, float aspect, 
                            WId winid, int winx, int winy, int winw, 
-                           int winh, WId embedid)
+                           int winh, float video_prate, WId embedid)
 {
     VERBOSE(VB_PLAYBACK, LOC + "Init() -- begin");
 
@@ -416,7 +416,7 @@
     videoDevice = gContext->GetSetting("PVR350VideoDev");
 
     VideoOutput::Init(width, height, aspect, winid, winx, winy, winw, winh, 
-                      embedid);
+                      video_prate, embedid);
 
     osdbufsize = video_dim.width() * video_dim.height() * 4;
 
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_ivtv.h mythtv/libs/libmythtv/videoout_ivtv.h
--- mythtv.opengl/libs/libmythtv/videoout_ivtv.h	2009-05-02 07:30:34.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_ivtv.h	2009-05-16 20:24:09.000000000 +1000
@@ -16,7 +16,8 @@
    ~VideoOutputIvtv();
 
     bool Init(int width, int height, float aspect, WId winid,
-              int winx, int winy, int winw, int winh, WId embedid = 0);
+              int winx, int winy, int winw, int winh,
+              float video_prate, WId embedid = 0);
     void PrepareFrame(VideoFrame *buffer, FrameScanType);
     void Show(FrameScanType );
 
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_null.cpp mythtv/libs/libmythtv/videoout_null.cpp
--- mythtv.opengl/libs/libmythtv/videoout_null.cpp	2009-05-02 07:30:35.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_null.cpp	2009-05-16 20:25:07.000000000 +1000
@@ -115,15 +115,15 @@
 
 bool VideoOutputNull::Init(int width, int height, float aspect,
                            WId winid, int winx, int winy, int winw, 
-                           int winh, WId embedid)
+                           int winh, float video_prate, WId embedid)
 {
     if ((width <= 0) || (height <= 0))
         return false;
 
     QMutexLocker locker(&global_lock);
 
-    VideoOutput::Init(width, height, aspect, winid,
-                      winx, winy, winw, winh, embedid);
+    VideoOutput::Init(width, height, aspect, winid, winx, 
+                      winy, winw, winh, video_prate, embedid);
 
     vbuffers.Init(kNumBuffers, true, kNeedFreeFrames, 
                   kPrebufferFramesNormal, kPrebufferFramesSmall, 
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_null.h mythtv/libs/libmythtv/videoout_null.h
--- mythtv.opengl/libs/libmythtv/videoout_null.h	2009-05-02 07:30:36.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_null.h	2009-05-16 20:25:34.000000000 +1000
@@ -12,7 +12,8 @@
    ~VideoOutputNull();
 
     bool Init(int width, int height, float aspect, WId winid,
-              int winx, int winy, int winw, int winh, WId embedid = 0);
+              int winx, int winy, int winw, int winh,
+              float video_prate, WId embedid = 0);
 
     bool SetupDeinterlace(bool, const QString &ovrf = "")
         { (void)ovrf; return false; } // we don't deinterlace in null output..
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_quartz.cpp mythtv/libs/libmythtv/videoout_quartz.cpp
--- mythtv.opengl/libs/libmythtv/videoout_quartz.cpp	2009-05-02 07:30:34.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_quartz.cpp	2009-05-16 20:27:22.000000000 +1000
@@ -1192,8 +1192,8 @@
 }
 
 bool VideoOutputQuartz::Init(int width, int height, float aspect,
-                             WId winid, int winx, int winy,
-                             int winw, int winh, WId embedid)
+                             WId winid, int winx, int winy, int winw,
+                             int winh, float video_prate, WId embedid)
 {
     VERBOSE(VB_PLAYBACK, LOC +
             QString("Init(WxH %1x%2, aspect=%3, winid=%4\n\t\t\t"
@@ -1215,8 +1215,8 @@
     vbuffers.Init(kNumBuffers, true, kNeedFreeFrames,
                   kPrebufferFramesNormal, kPrebufferFramesSmall,
                   kKeepPrebuffer);
-    VideoOutput::Init(width, height, aspect, winid,
-                      winx, winy, winw, winh, embedid);
+    VideoOutput::Init(width, height, aspect, winid, winx, 
+                      winy, winw, winh, video_prate, embedid);
 
     data->srcWidth  = video_dim.width();
     data->srcHeight = video_dim.height();
@@ -1381,6 +1381,7 @@
 
 void VideoOutputQuartz::SetVideoFrameRate(float playback_fps)
 {
+    video_prate = playback_fps;
     VERBOSE(VB_PLAYBACK, "SetVideoFrameRate("<<playback_fps<<")");
 }
 
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_quartz.h mythtv/libs/libmythtv/videoout_quartz.h
--- mythtv.opengl/libs/libmythtv/videoout_quartz.h	2009-05-02 07:30:36.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_quartz.h	2009-05-16 20:27:58.000000000 +1000
@@ -13,7 +13,8 @@
    ~VideoOutputQuartz();
 
     bool Init(int width, int height, float aspect, WId winid,
-              int winx, int winy, int winw, int winh, WId embedid = 0);
+              int winx, int winy, int winw, int winh, 
+              float video_prate, WId embedid = 0);
     void SetVideoFrameRate(float playback_fps);
     void PrepareFrame(VideoFrame *buffer, FrameScanType t);
     void Show(FrameScanType);
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_xv.cpp mythtv/libs/libmythtv/videoout_xv.cpp
--- mythtv.opengl/libs/libmythtv/videoout_xv.cpp	2009-05-15 16:58:35.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_xv.cpp	2009-05-16 20:48:13.000000000 +1000
@@ -450,7 +450,9 @@
     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, 
+                                                  (short) roundf(video_prate),
+                                                  video_prate))
     {
         // Switching to custom display resolution succeeded
         // Make a note of the new size
@@ -1698,14 +1700,14 @@
 }
 
 /**
- * \fn VideoOutputXv::Init(int,int,float,WId,int,int,int,int,WId)
+ * \fn VideoOutputXv::Init(int,int,float,WId,int,int,int,int,float,WId)
  * Initializes class for video output.
  *
  * \return success or failure.
  */
 bool VideoOutputXv::Init(
-    int width, int height, float aspect,
-    WId winid, int winx, int winy, int winw, int winh, WId embedid)
+    int width, int height, float aspect, WId winid, int winx, 
+    int winy, int winw, int winh, float video_prate, WId embedid)
 {
     needrepaint = true;
 
@@ -1739,7 +1741,7 @@
     // Basic setup
     VideoOutput::Init(width, height, aspect,
                       winid, winx, winy, winw, winh,
-                      embedid);
+                      video_prate, embedid);
 
     // Set resolution/measurements (check XRandR, Xinerama, config settings)
     InitDisplayMeasurements(width, height);
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videoout_xv.h mythtv/libs/libmythtv/videoout_xv.h
--- mythtv.opengl/libs/libmythtv/videoout_xv.h	2009-05-15 16:58:35.000000000 +1000
+++ mythtv/libs/libmythtv/videoout_xv.h	2009-05-16 20:29:46.000000000 +1000
@@ -62,7 +62,8 @@
    ~VideoOutputXv();
 
     bool Init(int width, int height, float aspect, WId winid,
-              int winx, int winy, int winw, int winh, WId embedid = 0);
+              int winx, int winy, int winw, int winh, 
+              float video_prate, WId embedid = 0);
 
     bool SetDeinterlacingEnabled(bool);
     bool SetupDeinterlace(bool interlaced, const QString& ovrf="");
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videooutbase.cpp mythtv/libs/libmythtv/videooutbase.cpp
--- mythtv.opengl/libs/libmythtv/videooutbase.cpp	2009-05-15 16:58:35.000000000 +1000
+++ mythtv/libs/libmythtv/videooutbase.cpp	2009-05-16 20:53:44.000000000 +1000
@@ -71,7 +71,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;
 
@@ -170,10 +170,12 @@
 
         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(),
-                    display_rect.width(), display_rect.height(), embed_id))
+                    display_rect.width(), display_rect.height(),
+                    video_prate, embed_id))
             {
                 return vo;
             }
@@ -367,7 +369,8 @@
  * \return true if successful, false otherwise.
  */
 bool VideoOutput::Init(int width, int height, float aspect, WId winid,
-                       int winx, int winy, int winw, int winh, WId embedid)
+                       int winx, int winy, int winw, int winh,
+                       float video_prate, WId embedid)
 {
     (void)winid;
     (void)embedid;
@@ -409,6 +412,7 @@
 
 void VideoOutput::SetVideoFrameRate(float playback_fps)
 {
+    video_prate = playback_fps;
     db_vdisp_profile->SetOutput(playback_fps);
 }
 
diff -Naur --exclude=.svn mythtv.opengl/libs/libmythtv/videooutbase.h mythtv/libs/libmythtv/videooutbase.h
--- mythtv.opengl/libs/libmythtv/videooutbase.h	2009-05-15 16:58:35.000000000 +1000
+++ mythtv/libs/libmythtv/videooutbase.h	2009-05-16 20:49:57.000000000 +1000
@@ -36,14 +36,14 @@
         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();
 
     virtual bool Init(int width, int height, float aspect,
                       WId winid, int winx, int winy, int winw, 
-                      int winh, WId embedid = 0);
+                      int winh, float video_prate, WId embedid = 0);
     virtual void InitOSD(OSD *osd);
     virtual void SetVideoFrameRate(float);
 
@@ -279,6 +279,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.
diff -Naur --exclude=.svn mythtv.opengl/programs/mythfrontend/globalsettings.cpp mythtv/programs/mythfrontend/globalsettings.cpp
--- mythtv.opengl/programs/mythfrontend/globalsettings.cpp	2009-05-02 07:32:18.000000000 +1000
+++ mythtv/programs/mythfrontend/globalsettings.cpp	2009-05-15 16:57:30.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,16 @@
                     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));

