diff -pruN mythtv-0.19/contrib/mythrename.pl mythtv/contrib/mythrename.pl
--- mythtv-0.19/contrib/mythrename.pl	2006-02-07 13:05:03.000000000 +1000
+++ mythtv/contrib/mythrename.pl	2006-02-07 13:05:03.000000000 +1000
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 #
-# $Date: 2006-02-06 22:05:03 -0500 (Mon, 06 Feb 2006) $
+# $Date: 2006-02-07 13:05:03 +1000 (Tue, 07 Feb 2006) $
 # $Revision: 8888 $
 # $Author: xris $
 #
diff -pruN mythtv-0.19/contrib/optimize_mythdb.pl mythtv/contrib/optimize_mythdb.pl
--- mythtv-0.19/contrib/optimize_mythdb.pl	2005-08-21 06:21:40.000000000 +1000
+++ mythtv/contrib/optimize_mythdb.pl	2005-08-21 06:21:40.000000000 +1000
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 #
-# $Date: 2005-08-20 16:21:40 -0400 (Sat, 20 Aug 2005) $
+# $Date: 2005-08-21 06:21:40 +1000 (Sun, 21 Aug 2005) $
 # $Revision: 7095 $
 # $Author: xris $
 #
diff -pruN mythtv-0.19/libs/libavcodec/libavcodec.pro mythtv/libs/libavcodec/libavcodec.pro
--- mythtv-0.19/libs/libavcodec/libavcodec.pro	2006-01-16 17:14:43.000000000 +1000
+++ mythtv/libs/libavcodec/libavcodec.pro	2006-04-16 17:27:30.000000000 +1000
@@ -430,4 +430,5 @@ macx {
     LIBS               += -lz
     QMAKE_LFLAGS_SHLIB += -single_module
     QMAKE_LFLAGS_SHLIB += -seg1addr 0xC3000000
+    QMAKE_LFLAGS_SHLIB += -read_only_relocs warning
 }
diff -pruN mythtv-0.19/libs/libavformat/aviobuf.c mythtv/libs/libavformat/aviobuf.c
--- mythtv-0.19/libs/libavformat/aviobuf.c	2006-01-16 17:14:43.000000000 +1000
+++ mythtv/libs/libavformat/aviobuf.c	2006-02-23 17:54:05.000000000 +1000
@@ -164,7 +164,13 @@ offset_t url_fseek(ByteIOContext *s, off
 
 void url_fskip(ByteIOContext *s, offset_t offset)
 {
-    url_fseek(s, offset, SEEK_CUR);
+    if (offset < 16384) 
+    {
+        static unsigned char fskipbuf[16384];
+        get_buffer(s, fskipbuf, offset);
+    }
+    else
+        url_fseek(s, offset, SEEK_CUR);
 }
 
 offset_t url_ftell(ByteIOContext *s)
diff -pruN mythtv-0.19/libs/libmyth/audiooutputca.cpp mythtv/libs/libmyth/audiooutputca.cpp
--- mythtv-0.19/libs/libmyth/audiooutputca.cpp	2005-10-11 10:30:51.000000000 +1000
+++ mythtv/libs/libmyth/audiooutputca.cpp	2006-04-16 17:23:48.000000000 +1000
@@ -7,7 +7,7 @@
  * This plays MythTV audio through the default output device on OS X.
  *
  * = REVISION
- * $Id: audiooutputca.cpp 7441 2005-10-11 00:30:51Z ijr $
+ * $Id: audiooutputca.cpp 9721 2006-04-16 07:23:48Z nigel $
  *
  * = AUTHORS
  * Jeremiah Morris
@@ -107,8 +107,10 @@ bool AudioOutputCA::OpenDevice()
     bzero(&conv_in_desc, sizeof(AudioStreamBasicDescription));
     conv_in_desc.mSampleRate       = audio_samplerate;
     conv_in_desc.mFormatID         = kAudioFormatLinearPCM;
-    conv_in_desc.mFormatFlags      = kLinearPCMFormatFlagIsSignedInteger
-                                     | kLinearPCMFormatFlagIsBigEndian;
+    conv_in_desc.mFormatFlags      = kLinearPCMFormatFlagIsSignedInteger;
+#ifdef WORDS_BIGENDIAN
+    conv_in_desc.mFormatFlags     |= kLinearPCMFormatFlagIsBigEndian;
+#endif
     conv_in_desc.mBytesPerPacket   = audio_bytes_per_sample;
     conv_in_desc.mFramesPerPacket  = 1;
     conv_in_desc.mBytesPerFrame    = audio_bytes_per_sample;
diff -pruN mythtv-0.19/libs/libmyth/lcddevice.cpp mythtv/libs/libmyth/lcddevice.cpp
--- mythtv-0.19/libs/libmyth/lcddevice.cpp	2006-01-26 03:11:56.000000000 +1000
+++ mythtv/libs/libmyth/lcddevice.cpp	2006-04-10 06:00:15.000000000 +1000
@@ -150,7 +150,7 @@ bool LCD::connectToHost(const QString &l
 
     if (!connected)
     {
-        QTextStream os(socket);
+        QTextStream os(socket->socketDevice());
 
         int count = 0;
         do
@@ -213,7 +213,7 @@ void LCD::sendToServer(const QString &so
         return;
     }
 
-    QTextStream os(socket);
+    QTextStream os(socket->socketDevice());
    
     last_command = someText;
  
@@ -224,7 +224,7 @@ void LCD::sendToServer(const QString &so
 #endif
         // Just stream the text out the socket
 
-        os << someText << "\n" << flush;
+        os << someText << "\n";
     }
     else
     {
diff -pruN mythtv-0.19/libs/libmyth/mythcontext.cpp mythtv/libs/libmyth/mythcontext.cpp
--- mythtv-0.19/libs/libmyth/mythcontext.cpp	2006-01-25 20:22:57.000000000 +1000
+++ mythtv/libs/libmyth/mythcontext.cpp	2006-03-17 17:06:55.000000000 +1000
@@ -2621,9 +2621,13 @@ void MythContext::LogEntry(const QString
         d->LoadLogSettings();
     if (d->m_logenable == 1)
     {
+        QString fullMsg = message;
+        if (!details.isEmpty())
+            fullMsg += ": " + details;
+
         if (message.left(21) != "Last message repeated")
         {
-            if (message == d->lastLogStrings[module])
+            if (fullMsg == d->lastLogStrings[module])
             {
                 d->lastLogCounts[module] += 1;
                 return;
@@ -2639,7 +2643,7 @@ void MythContext::LogEntry(const QString
                 }
 
                 d->lastLogCounts[module] = 0;
-                d->lastLogStrings[module] = message;
+                d->lastLogStrings[module] = fullMsg;
             }
         }
 
@@ -2693,7 +2697,7 @@ void MythContext::LogEntry(const QString
         }
 
         if (priority <= d->m_logprintlevel)
-            VERBOSE(VB_IMPORTANT, module + ": " + message);
+            VERBOSE(VB_IMPORTANT, module + ": " + fullMsg);
     }
 }
 
diff -pruN mythtv-0.19/libs/libmyth/mythdialogs.cpp mythtv/libs/libmyth/mythdialogs.cpp
--- mythtv-0.19/libs/libmyth/mythdialogs.cpp	2006-01-16 16:45:15.000000000 +1000
+++ mythtv/libs/libmyth/mythdialogs.cpp	2006-02-22 13:44:43.000000000 +1000
@@ -2617,6 +2617,7 @@ MythPasswordDialog::MythPasswordDialog(Q
     password_editor->setEchoMode(QLineEdit::Password);
     password_editor->setGeometry(textWidth + 20,10,135,30);
     password_editor->setBackgroundOrigin(ParentOrigin);
+    password_editor->setAllowVirtualKeyboard(false);
     connect(password_editor, SIGNAL(textChanged(const QString &)),
             this, SLOT(checkPassword(const QString &)));
 
diff -pruN mythtv-0.19/libs/libmyth/mythwidgets.cpp mythtv/libs/libmyth/mythwidgets.cpp
--- mythtv-0.19/libs/libmyth/mythwidgets.cpp	2005-11-22 18:51:53.000000000 +1000
+++ mythtv/libs/libmyth/mythwidgets.cpp	2006-03-17 17:32:14.000000000 +1000
@@ -353,7 +353,8 @@ void MythLineEdit::keyPressEvent(QKeyEve
                     (e->key() == Qt::Key_Enter) ||
                     (e->key() == Qt::Key_Return)))
             {
-                if (gContext->GetNumSetting("UseVirtualKeyboard", 1) == 1)
+                if ((allowVirtualKeyboard) &&
+				    (gContext->GetNumSetting("UseVirtualKeyboard", 1) == 1))
                 {
                     popup = new VirtualKeyboard(gContext->GetMainWindow(), this);
                     gContext->GetMainWindow()->detach(popup);
@@ -726,10 +727,11 @@ void MythRemoteLineEdit::keyPressEvent(Q
                 QWidget::focusNextPrevChild(true);
                 emit tryingToLooseFocus(true);
             }
-            else if (action == "SELECT" &&
-                    (e->text().isNull() ||
-                    (e->key() == Qt::Key_Enter) || 
-                    (e->key() == Qt::Key_Return)))
+            else if ((action == "SELECT") &&
+                     (!active_cycle) &&
+                     ((e->text().isNull()) ||
+                      (e->key() == Qt::Key_Enter) || 
+                      (e->key() == Qt::Key_Return)))
             {
                 if (gContext->GetNumSetting("UseVirtualKeyboard", 1) == 1)
                 {
@@ -749,7 +751,7 @@ void MythRemoteLineEdit::keyPressEvent(Q
     if (handled)
         return;
 
-    if (!handled && popup && popup->isShown())
+    if (popup && popup->isShown())
     {
         endCycle();
         QTextEdit::keyPressEvent(e);
diff -pruN mythtv-0.19/libs/libmyth/mythwidgets.h mythtv/libs/libmyth/mythwidgets.h
--- mythtv-0.19/libs/libmyth/mythwidgets.h	2005-10-30 21:41:09.000000000 +1000
+++ mythtv/libs/libmyth/mythwidgets.h	2006-02-22 13:44:43.000000000 +1000
@@ -122,17 +122,21 @@ class MythLineEdit : public QLineEdit 
     Q_OBJECT
   public:
     MythLineEdit(QWidget *parent=NULL, const char* widgetName=0) :
-      QLineEdit(parent, widgetName) { rw = true; Init(); };
+      QLineEdit(parent, widgetName)
+	    { rw = true; allowVirtualKeyboard = true; Init(); };
 
     MythLineEdit(const QString& contents, QWidget *parent=NULL, 
                  const char* widgetName=0) :
-      QLineEdit(contents, parent, widgetName) { rw = true; Init(); };
+      QLineEdit(contents, parent, widgetName)
+	    { rw = true; allowVirtualKeyboard = true; Init(); };
 
     virtual ~MythLineEdit();
 
     void setHelpText(QString help) { helptext = help; };
     void setRW(bool readwrite = true) { rw = readwrite; };
     void setRO() { rw = false; };
+    void setAllowVirtualKeyboard(bool allowKbd = true)
+	       { allowVirtualKeyboard = allowKbd; }
     void setPopupPosition(PopupPosition pos) { popupPosition = pos; }
     PopupPosition getPopupPosition(void) { return popupPosition; }
 
@@ -154,6 +158,7 @@ class MythLineEdit : public QLineEdit 
     VirtualKeyboard *popup;
     QString helptext;
     bool rw;
+    bool allowVirtualKeyboard;
     PopupPosition popupPosition;
 };
 
diff -pruN mythtv-0.19/libs/libmyth/remotefile.cpp mythtv/libs/libmyth/remotefile.cpp
--- mythtv-0.19/libs/libmyth/remotefile.cpp	2005-12-08 06:49:24.000000000 +1000
+++ mythtv/libs/libmyth/remotefile.cpp	2006-02-23 17:54:05.000000000 +1000
@@ -15,6 +15,7 @@ RemoteFile::RemoteFile(const QString &ur
     path = url;
     readposition = 0;
     filesize = -1;
+    timeoutisfast = false;
 
     query = "QUERY_FILETRANSFER %1";
 
@@ -295,4 +296,34 @@ bool RemoteFile::SaveAs(QByteArray &data
     Read(data.data(), filesize);
 
     return true;
-} 
+}
+
+void RemoteFile::SetTimeout(bool fast)
+{
+    if (timeoutisfast == fast)
+        return;
+
+    if (!sock)
+    {
+        VERBOSE(VB_NETWORK, "RemoteFile::Seek(): Called with no socket");
+        return;
+    }
+
+    if (!sock->isOpen() || sock->error())
+        return;
+
+    if (!controlSock->isOpen() || controlSock->error())
+        return;
+
+    QStringList strlist = QString(query).arg(recordernum);
+    strlist << "SET_TIMEOUT";
+    strlist << QString::number((int)fast);
+
+    lock.lock();
+    WriteStringList(controlSock, strlist);
+    ReadStringList(controlSock, strlist);
+    lock.unlock();
+
+    timeoutisfast = fast;
+}
+
diff -pruN mythtv-0.19/libs/libmyth/remotefile.h mythtv/libs/libmyth/remotefile.h
--- mythtv-0.19/libs/libmyth/remotefile.h	2005-12-08 06:49:24.000000000 +1000
+++ mythtv/libs/libmyth/remotefile.h	2006-02-23 17:54:05.000000000 +1000
@@ -27,6 +27,8 @@ class RemoteFile
 
     long long GetFileSize(void);
 
+    void SetTimeout(bool fast);
+
   private:
     QSocketDevice *openSocket(bool control);
 
@@ -43,6 +45,7 @@ class RemoteFile
     QMutex lock;
 
     long long filesize;
+    bool timeoutisfast;
 };
 
 #endif
diff -pruN mythtv-0.19/libs/libmyth/util.cpp mythtv/libs/libmyth/util.cpp
--- mythtv-0.19/libs/libmyth/util.cpp	2006-02-08 07:52:26.000000000 +1000
+++ mythtv/libs/libmyth/util.cpp	2006-03-19 05:32:52.000000000 +1000
@@ -1006,16 +1006,20 @@ long long getDiskSpace(const QString &fi
     long long freespace = -1;
     QCString cstr = file_on_disk.local8Bit();
 
-    if (statfs(cstr, &statbuf) == 0)
+    total = used = -1;
+
+    // there are cases where statfs will return 0 (good), but f_blocks and
+    // others are invalid and set to 0 (such as when an automounted directory
+    // is not mounted but still visible because --ghost was used),
+    // so check to make sure we can have a total size > 0
+    if ((statfs(cstr, &statbuf) == 0) &&
+        (statbuf.f_blocks > 0) &&
+        (statbuf.f_bsize > 0))
     {
         freespace = statbuf.f_bsize * (statbuf.f_bavail >> 10);
         total = statbuf.f_bsize * (statbuf.f_blocks >> 10);
         used  = total - freespace;
     }
-    else
-    {
-        freespace = total = used = -1;
-    }
 
     return freespace;
 }
diff -pruN mythtv-0.19/libs/libmythsoundtouch/AAFilter.cpp mythtv/libs/libmythsoundtouch/AAFilter.cpp
--- mythtv-0.19/libs/libmythsoundtouch/AAFilter.cpp	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/AAFilter.cpp	2004-11-14 08:29:45.000000000 +1000
@@ -12,7 +12,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: AAFilter.cpp 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/AAFilter.h mythtv/libs/libmythsoundtouch/AAFilter.h
--- mythtv-0.19/libs/libmythsoundtouch/AAFilter.h	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/AAFilter.h	2004-11-14 08:29:45.000000000 +1000
@@ -13,7 +13,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: AAFilter.h 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/BPMDetect.h mythtv/libs/libmythsoundtouch/BPMDetect.h
--- mythtv-0.19/libs/libmythsoundtouch/BPMDetect.h	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/BPMDetect.h	2004-11-14 08:29:45.000000000 +1000
@@ -26,7 +26,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: BPMDetect.h 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/cpu_detect.h mythtv/libs/libmythsoundtouch/cpu_detect.h
--- mythtv-0.19/libs/libmythsoundtouch/cpu_detect.h	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/cpu_detect.h	2004-11-14 08:29:45.000000000 +1000
@@ -12,7 +12,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: cpu_detect.h 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/cpu_detect_x86_gcc.cpp mythtv/libs/libmythsoundtouch/cpu_detect_x86_gcc.cpp
--- mythtv-0.19/libs/libmythsoundtouch/cpu_detect_x86_gcc.cpp	2005-01-24 16:42:19.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/cpu_detect_x86_gcc.cpp	2005-01-24 16:42:19.000000000 +1000
@@ -12,7 +12,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2005-01-24 01:42:19 -0500 (Mon, 24 Jan 2005) $
+// Last changed  : $Date: 2005-01-24 16:42:19 +1000 (Mon, 24 Jan 2005) $
 // File revision : $Revision: 5151 $
 //
 // $Id: cpu_detect_x86_gcc.cpp 5151 2005-01-24 06:42:19Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/FIFOSampleBuffer.cpp mythtv/libs/libmythsoundtouch/FIFOSampleBuffer.cpp
--- mythtv-0.19/libs/libmythsoundtouch/FIFOSampleBuffer.cpp	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/FIFOSampleBuffer.cpp	2004-11-14 08:29:45.000000000 +1000
@@ -15,7 +15,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: FIFOSampleBuffer.cpp 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/FIFOSampleBuffer.h mythtv/libs/libmythsoundtouch/FIFOSampleBuffer.h
--- mythtv-0.19/libs/libmythsoundtouch/FIFOSampleBuffer.h	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/FIFOSampleBuffer.h	2004-11-14 08:29:45.000000000 +1000
@@ -15,7 +15,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: FIFOSampleBuffer.h 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/FIFOSamplePipe.h mythtv/libs/libmythsoundtouch/FIFOSamplePipe.h
--- mythtv-0.19/libs/libmythsoundtouch/FIFOSamplePipe.h	2005-05-24 06:39:12.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/FIFOSamplePipe.h	2005-05-24 06:39:12.000000000 +1000
@@ -17,7 +17,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2005-05-23 16:39:12 -0400 (Mon, 23 May 2005) $
+// Last changed  : $Date: 2005-05-24 06:39:12 +1000 (Tue, 24 May 2005) $
 // File revision : $Revision: 6468 $
 //
 // $Id: FIFOSamplePipe.h 6468 2005-05-23 20:39:12Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/FIRFilter.cpp mythtv/libs/libmythsoundtouch/FIRFilter.cpp
--- mythtv-0.19/libs/libmythsoundtouch/FIRFilter.cpp	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/FIRFilter.cpp	2004-11-14 08:29:45.000000000 +1000
@@ -11,7 +11,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: FIRFilter.cpp 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/FIRFilter.h mythtv/libs/libmythsoundtouch/FIRFilter.h
--- mythtv-0.19/libs/libmythsoundtouch/FIRFilter.h	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/FIRFilter.h	2004-11-14 08:29:45.000000000 +1000
@@ -11,7 +11,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: FIRFilter.h 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/mmx_gcc.cpp mythtv/libs/libmythsoundtouch/mmx_gcc.cpp
--- mythtv-0.19/libs/libmythsoundtouch/mmx_gcc.cpp	2005-06-30 07:41:57.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/mmx_gcc.cpp	2005-06-30 07:41:57.000000000 +1000
@@ -15,7 +15,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2005-06-29 17:41:57 -0400 (Wed, 29 Jun 2005) $
+// Last changed  : $Date: 2005-06-30 07:41:57 +1000 (Thu, 30 Jun 2005) $
 // File revision : $Revision: 6741 $
 //
 // $Id: mmx_gcc.cpp 6741 2005-06-29 21:41:57Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/RateTransposer.cpp mythtv/libs/libmythsoundtouch/RateTransposer.cpp
--- mythtv-0.19/libs/libmythsoundtouch/RateTransposer.cpp	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/RateTransposer.cpp	2004-11-14 08:29:45.000000000 +1000
@@ -10,7 +10,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: RateTransposer.cpp 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/RateTransposer.h mythtv/libs/libmythsoundtouch/RateTransposer.h
--- mythtv-0.19/libs/libmythsoundtouch/RateTransposer.h	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/RateTransposer.h	2004-11-14 08:29:45.000000000 +1000
@@ -14,7 +14,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: RateTransposer.h 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/SoundTouch.cpp mythtv/libs/libmythsoundtouch/SoundTouch.cpp
--- mythtv-0.19/libs/libmythsoundtouch/SoundTouch.cpp	2005-11-12 09:19:13.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/SoundTouch.cpp	2005-11-12 09:19:13.000000000 +1000
@@ -41,7 +41,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2005-11-11 18:19:13 -0500 (Fri, 11 Nov 2005) $
+// Last changed  : $Date: 2005-11-12 09:19:13 +1000 (Sat, 12 Nov 2005) $
 // File revision : $Revision: 7850 $
 //
 // $Id: SoundTouch.cpp 7850 2005-11-11 23:19:13Z danielk $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/SoundTouch.h mythtv/libs/libmythsoundtouch/SoundTouch.h
--- mythtv-0.19/libs/libmythsoundtouch/SoundTouch.h	2005-11-12 09:19:13.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/SoundTouch.h	2005-11-12 09:19:13.000000000 +1000
@@ -41,7 +41,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2005-11-11 18:19:13 -0500 (Fri, 11 Nov 2005) $
+// Last changed  : $Date: 2005-11-12 09:19:13 +1000 (Sat, 12 Nov 2005) $
 // File revision : $Revision: 7850 $
 //
 // $Id: SoundTouch.h 7850 2005-11-11 23:19:13Z danielk $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/STTypes.h mythtv/libs/libmythsoundtouch/STTypes.h
--- mythtv-0.19/libs/libmythsoundtouch/STTypes.h	2005-01-21 16:08:36.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/STTypes.h	2005-01-21 16:08:36.000000000 +1000
@@ -8,7 +8,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2005-01-21 01:08:36 -0500 (Fri, 21 Jan 2005) $
+// Last changed  : $Date: 2005-01-21 16:08:36 +1000 (Fri, 21 Jan 2005) $
 // File revision : $Revision: 5097 $
 //
 // $Id: STTypes.h 5097 2005-01-21 06:08:36Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/TDStretch.cpp mythtv/libs/libmythsoundtouch/TDStretch.cpp
--- mythtv-0.19/libs/libmythsoundtouch/TDStretch.cpp	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/TDStretch.cpp	2004-11-14 08:29:45.000000000 +1000
@@ -13,7 +13,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: TDStretch.cpp 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythsoundtouch/TDStretch.h mythtv/libs/libmythsoundtouch/TDStretch.h
--- mythtv-0.19/libs/libmythsoundtouch/TDStretch.h	2004-11-14 08:29:45.000000000 +1000
+++ mythtv/libs/libmythsoundtouch/TDStretch.h	2004-11-14 08:29:45.000000000 +1000
@@ -13,7 +13,7 @@
 ///
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Last changed  : $Date: 2004-11-13 17:29:45 -0500 (Sat, 13 Nov 2004) $
+// Last changed  : $Date: 2004-11-14 08:29:45 +1000 (Sun, 14 Nov 2004) $
 // File revision : $Revision: 4714 $
 //
 // $Id: TDStretch.h 4714 2004-11-13 22:29:45Z ijr $
diff -pruN mythtv-0.19/libs/libmythtv/avformatdecoder.cpp mythtv/libs/libmythtv/avformatdecoder.cpp
--- mythtv-0.19/libs/libmythtv/avformatdecoder.cpp	2006-02-07 04:09:58.000000000 +1000
+++ mythtv/libs/libmythtv/avformatdecoder.cpp	2006-03-31 11:55:22.000000000 +1000
@@ -725,7 +725,12 @@ int AvFormatDecoder::OpenFile(RingBuffer
         return -1;
     }
 
+    /* av_find_stream_info() eventually makes calls to avcodec_open() and avcodec_close() 
+       so we have to use the avcodeclock */
+    avcodeclock.lock();
     int ret = av_find_stream_info(ic);
+    avcodeclock.unlock();
+
     if (ret < 0)
     {
         VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not find codec parameters. " +
diff -pruN mythtv-0.19/libs/libmythtv/dummydtvrecorder.cpp mythtv/libs/libmythtv/dummydtvrecorder.cpp
--- mythtv-0.19/libs/libmythtv/dummydtvrecorder.cpp	2005-12-15 01:54:48.000000000 +1000
+++ mythtv/libs/libmythtv/dummydtvrecorder.cpp	2006-04-20 23:52:51.000000000 +1000
@@ -125,7 +125,8 @@ void DummyDTVRecorder::StartRecording(vo
     // TRANSFER DATA
     while (_request_recording || _frames_seen_count <= 5)
     {
-        len = read(_stream_fd, &(_buffer[remainder]), _buffer_size - remainder);
+        len = read(_stream_fd, &(_buffer[remainder]),
+                   _buffer_size - remainder);
 
         if (len == 0)
         {
@@ -137,9 +138,8 @@ void DummyDTVRecorder::StartRecording(vo
 
         len += remainder;
         remainder = ProcessData(_buffer, len);
-        if (remainder > 0) // leftover bytes
-            memmove(_buffer, &(_buffer[_buffer_size - remainder]),
-                    remainder);
+        if (remainder > 0 && (len > remainder)) // leftover bytes
+            memmove(_buffer, &(_buffer[len - remainder]), remainder);
     }
 
     FinishRecording();
diff -pruN mythtv-0.19/libs/libmythtv/dvbconfparser.cpp mythtv/libs/libmythtv/dvbconfparser.cpp
--- mythtv-0.19/libs/libmythtv/dvbconfparser.cpp	2006-02-08 07:56:06.000000000 +1000
+++ mythtv/libs/libmythtv/dvbconfparser.cpp	2006-03-12 14:33:39.000000000 +1000
@@ -1,5 +1,5 @@
 /*
- * $Id: dvbconfparser.cpp 8901 2006-02-07 21:56:06Z danielk $
+ * $Id: dvbconfparser.cpp 9335 2006-03-12 04:33:39Z danielk $
  * vim: set expandtab tabstop=4 shiftwidth=4:
  *
  * Original Project
@@ -193,10 +193,10 @@ bool DVBConfParser::parseConfQPSK(QStrin
     QStringList::Iterator end = tokens.end();
 
     if (i != end) c.name = *i++; else return false;
-    if (i != end) c.frequency = (*i++).toInt(); else return false;
+    if (i != end) c.frequency = (*i++).toUInt()*1000; else return false;
     if (i == end || !c.polarity.parseConf(*i++)) return false;
     if (i == end ) return false; else i++; //Sat num
-    if (i != end) c.symbolrate = (*i++).toInt(); else return false;
+    if (i != end) c.symbolrate = (*i++).toUInt()*1000; else return false;
     if (i == end ) return false; else i++;
     if (i == end ) return false; else i++;
     if (i != end) c.serviceid = (*i++).toInt(); else return false;
diff -pruN mythtv-0.19/libs/libmythtv/dvbsignalmonitor.cpp mythtv/libs/libmythtv/dvbsignalmonitor.cpp
--- mythtv-0.19/libs/libmythtv/dvbsignalmonitor.cpp	2006-02-08 07:56:06.000000000 +1000
+++ mythtv/libs/libmythtv/dvbsignalmonitor.cpp	2006-04-20 23:46:13.000000000 +1000
@@ -348,8 +348,8 @@ void DVBSignalMonitor::RunTableMonitorTS
 
         len += remainder;
         remainder = GetStreamData()->ProcessData(buffer, len);
-        if (remainder > 0) // leftover bytes
-            memmove(buffer, &(buffer[buffer_size - remainder]), remainder);
+        if (remainder > 0 && (len > remainder)) // leftover bytes
+            memmove(buffer, &(buffer[len - remainder]), remainder);
     }
     VERBOSE(VB_CHANNEL, LOC + "RunTableMonitorTS(): " + "shutdown");
 
diff -pruN mythtv-0.19/libs/libmythtv/dvbtypes.cpp mythtv/libs/libmythtv/dvbtypes.cpp
--- mythtv-0.19/libs/libmythtv/dvbtypes.cpp	2005-12-16 10:23:00.000000000 +1000
+++ mythtv/libs/libmythtv/dvbtypes.cpp	2006-02-17 08:41:02.000000000 +1000
@@ -202,7 +202,7 @@ DVBParamHelper<fe_transmit_mode_t>::Tabl
 {
    {"TRANSMISSION_MODE_AUTO",TRANSMISSION_MODE_AUTO},
    {"TRANSMISSION_MODE_2K",TRANSMISSION_MODE_2K},
-   {"TRANSMISSION_MODE_8K",TRANSMISSION_MODE_2K},
+   {"TRANSMISSION_MODE_8K",TRANSMISSION_MODE_8K},
    {NULL,TRANSMISSION_MODE_AUTO},
 };
 
@@ -210,7 +210,7 @@ DVBParamHelper<fe_transmit_mode_t>::Tabl
 {
    {"999",TRANSMISSION_MODE_AUTO},
    {"2",TRANSMISSION_MODE_2K},
-   {"8",TRANSMISSION_MODE_2K},
+   {"8",TRANSMISSION_MODE_8K},
    {NULL,TRANSMISSION_MODE_AUTO},
 };
 
@@ -218,7 +218,7 @@ DVBParamHelper<fe_transmit_mode_t>::Tabl
 {
    {"auto",TRANSMISSION_MODE_AUTO},
    {"2",TRANSMISSION_MODE_2K},
-   {"8",TRANSMISSION_MODE_2K},
+   {"8",TRANSMISSION_MODE_8K},
    {NULL,TRANSMISSION_MODE_AUTO},
 };
 
diff -pruN mythtv-0.19/libs/libmythtv/frequencytables.cpp mythtv/libs/libmythtv/frequencytables.cpp
--- mythtv-0.19/libs/libmythtv/frequencytables.cpp	2006-01-19 02:46:14.000000000 +1000
+++ mythtv/libs/libmythtv/frequencytables.cpp	2006-04-13 00:21:41.000000000 +1000
@@ -283,104 +283,52 @@ static void init_freq_tables(freq_table_
         "ATSC Channel %1", 70, 809000000, 887000000, 6000000, VSB_8);
 #endif // USING_DVB
 
-    // USA Cable, QAM 256
-    fmap["atsc_qam256_uscable0"] = new FrequencyTable(
-        "QAM-256 Channel %1",   1, 75000000,1005000000, 6000000, QAM_256);
-    fmap["atsc_qam256_uscable1"] = new FrequencyTable(
-        "QAM-256 Channel T-%1", 7, 10000000,  52000000, 6000000, QAM_256);
-
-    // USA Cable, QAM 256 ch 78+
-    fmap["atsc_qam256_uscablehigh0"] = new FrequencyTable(
-        "QAM-256 Channel %1",  78,472000000,1005000000, 6000000, QAM_256);
-
-    // USA Cable HRC, QAM 256
-    fmap["atsc_qam256_ushrc0"] = new FrequencyTable(
-        "QAM-256 HRC %1",   1,  73750000,  73750001, 6000000, QAM_256);
-    fmap["atsc_qam256_ushrc1"] = new FrequencyTable(
-        "QAM-256 HRC %1",   2,  55750000,  67750000, 6000000, QAM_256);
-    fmap["atsc_qam256_ushrc2"] = new FrequencyTable(
-        "QAM-256 HRC %1",   5,  79750000,  85750000, 6000000, QAM_256);
-    fmap["atsc_qam256_ushrc3"] = new FrequencyTable(
-        "QAM-256 HRC %1",   7, 175750000, 643750000, 6000000, QAM_256);
-    fmap["atsc_qam256_ushrc4"] = new FrequencyTable(
-        "QAM-256 HRC %1",  95,  91750000, 114000000, 6000000, QAM_256);
-    fmap["atsc_qam256_ushrc5"] = new FrequencyTable(
-        "QAM-256 HRC %1", 100, 649750000, 799750000, 6000000, QAM_256);
-    fmap["atsc_qam256_ushrc6"] = new FrequencyTable(
-        "QAM-256 HRC T-%1", 7,   8175000,  50750000, 6000000, QAM_256);
-
-    // USA Cable HRC, QAM 256 ch 78+
-    fmap["atsc_qam256_ushrchigh0"] = new FrequencyTable(
-        "QAM-256 HRC %1",  78, 601750000, 643750000, 6000000, QAM_256);
-    fmap["atsc_qam256_ushrchigh1"] = new FrequencyTable(
-        "QAM-256 HRC %1", 100, 649750000, 799750000, 6000000, QAM_256);
-
-
-
-    // USA Cable, QAM 128
-    fmap["atsc_qam128_uscable0"] = new FrequencyTable(
-        "QAM-128 Channel %1",   1, 75000000,1005000000, 6000000, QAM_128);
-    fmap["atsc_qam128_uscable1"] = new FrequencyTable(
-        "QAM-128 Channel T-%1", 7, 10000000,  52000000, 6000000, QAM_128);
-
-    // USA Cable, QAM 128 ch 78+
-    fmap["atsc_qam128_uscablehigh0"] = new FrequencyTable(
-        "QAM-128 Channel %1",  78,472000000,1005000000, 6000000, QAM_128);
-
-    // USA Cable HRC, QAM 128
-    fmap["atsc_qam128_ushrc0"] = new FrequencyTable(
-        "QAM-128 HRC %1",   1,  73750000,  73750001, 6000000, QAM_128);
-    fmap["atsc_qam128_ushrc1"] = new FrequencyTable(
-        "QAM-128 HRC %1",   2,  55750000,  67750000, 6000000, QAM_128);
-    fmap["atsc_qam128_ushrc2"] = new FrequencyTable(
-        "QAM-128 HRC %1",   5,  79750000,  85750000, 6000000, QAM_128);
-    fmap["atsc_qam128_ushrc3"] = new FrequencyTable(
-        "QAM-128 HRC %1",   7, 175750000, 643750000, 6000000, QAM_128);
-    fmap["atsc_qam128_ushrc4"] = new FrequencyTable(
-        "QAM-128 HRC %1",  95,  91750000, 114000000, 6000000, QAM_128);
-    fmap["atsc_qam128_ushrc5"] = new FrequencyTable(
-        "QAM-128 HRC %1", 100, 649750000, 799750000, 6000000, QAM_128);
-    fmap["atsc_qam128_ushrc6"] = new FrequencyTable(
-        "QAM-128 HRC T-%1", 7,   8175000,  50750000, 6000000, QAM_128);
-
-    // USA Cable HRC, QAM 128 ch 78+
-    fmap["atsc_qam128_ushrchigh0"] = new FrequencyTable(
-        "QAM-128 HRC %1",  78, 601750000, 643750000, 6000000, QAM_128);
-    fmap["atsc_qam128_ushrchigh1"] = new FrequencyTable(
-        "QAM-128 HRC %1", 100, 649750000, 799750000, 6000000, QAM_128);
-
-
-
-
-    // USA Cable, QAM 64
-    fmap["atsc_qam64_uscable0"] = new FrequencyTable(
-        "QAM-64 Channel %1",    1, 75000000,1005000000, 6000000, QAM_64);
-    fmap["atsc_qam64_uscable1"] = new FrequencyTable(
-        "QAM-64 Channel T-%1",  7, 10000000,  52000000, 6000000, QAM_64);
-
-    // USA Cable, QAM 64 ch 78+
-    fmap["atsc_qam64_uscablehigh0"] = new FrequencyTable(
-        "QAM-64 Channel %1",   78,472000000,1005000000, 6000000, QAM_64);
-
-    // USA Cable HRC, QAM 64
-    fmap["atsc_qam64_ushrc0"] = new FrequencyTable(
-        "QAM-64 HRC %1",   1,  73750000,  73750001, 6000000, QAM_64);
-    fmap["atsc_qam64_ushrc1"] = new FrequencyTable(
-        "QAM-64 HRC %1",   2,  55750000,  67750000, 6000000, QAM_64);
-    fmap["atsc_qam64_ushrc2"] = new FrequencyTable(
-        "QAM-64 HRC %1",   5,  79750000,  85750000, 6000000, QAM_64);
-    fmap["atsc_qam64_ushrc3"] = new FrequencyTable(
-        "QAM-64 HRC %1",   7, 175750000, 643750000, 6000000, QAM_64);
-    fmap["atsc_qam64_ushrc4"] = new FrequencyTable(
-        "QAM-64 HRC %1",  95,  91750000, 114000000, 6000000, QAM_64);
-    fmap["atsc_qam64_ushrc5"] = new FrequencyTable(
-        "QAM-64 HRC %1", 100, 649750000, 799750000, 6000000, QAM_64);
-    fmap["atsc_qam64_ushrc6"] = new FrequencyTable(
-        "QAM-64 HRC T-%1", 7,   8175000,  50750000, 6000000, QAM_64);
-
-    // USA Cable HRC, QAM 64 ch 78+
-    fmap["atsc_qam64_ushrchigh0"] = new FrequencyTable(
-        "QAM-64 HRC %1",  78, 601750000, 643750000, 6000000, QAM_64);
-    fmap["atsc_qam64_ushrchigh1"] = new FrequencyTable(
-        "QAM-64 HRC %1", 100, 649750000, 799750000, 6000000, QAM_64);
+    QString modStr[] = { "vsb8",  "qam256",   "qam128",   "qam64",   };
+    uint    mod[]    = { VSB_8,    QAM_256,    QAM_128,    QAM_64,   };
+    QString desc[]   = { "ATSC ", "QAM-256 ", "QAM-128 ", "QAM-64 ", };
+
+#define FREQ(A,B, C,D, E,F,G, H) \
+    fmap[QString("atsc_%1_us%2").arg(A).arg(B)] = \
+        new FrequencyTable(C+D, E, F, G, 6000000, H);
+
+    for (uint i = 0; i < 3; i++)
+    {
+        // USA Cable, ch 1 to 155 and T.7 to T.14
+        FREQ(modStr[i], "cable0", desc[i], "Channel %1",
+             1, 75000000, 1005000000, mod[i]);
+        FREQ(modStr[i], "cable1", desc[i], "Channel T-%1",
+             7, 10000000,   52000000, mod[i]);
+        // USA Cable, QAM 256 ch 78 to 155
+        FREQ(modStr[i], "cablehigh0", desc[i], "Channel %1",
+             78, 537000000,1005000000, mod[i]);
+
+        QString std[]   = { "hrc",  "irc"   };
+        QString sdesc[] = { "HRC ", "IRC "  };
+        int     off[]   = { 0,      1250000 };
+
+        for (uint j = 0; j < 2; j++)
+        {
+            // USA Cable HRC/IRC, ch 1 to 125
+            FREQ(modStr[i], std[j] + "0", desc[i], sdesc[j] + "%1",
+                 1,   73750000 + off[j],  73750001 + off[j], mod[i]);
+            FREQ(modStr[i], std[j] + "1", desc[i], sdesc[j] + "%1",
+                 2,   55750000 + off[j],  67750000 + off[j], mod[i]);
+            FREQ(modStr[i], std[j] + "2", desc[i], sdesc[j] + "%1",
+                 5,   79750000 + off[j],  85750000 + off[j], mod[i]);
+            FREQ(modStr[i], std[j] + "3", desc[i], sdesc[j] + "%1",
+                 7,  175750000 + off[j], 643750000 + off[j], mod[i]);
+            FREQ(modStr[i], std[j] + "4", desc[i], sdesc[j] + "%1",
+                 95,  91750000 + off[j], 114000000 + off[j], mod[i]);
+            FREQ(modStr[i], std[j] + "5", desc[i], sdesc[j] + "%1",
+                 100, 649750000 + off[j], 799750000 + off[j], mod[i]);
+            FREQ(modStr[i], std[j] + "6", desc[i], sdesc[j] + "T-%1",
+                 7,     8175000 + off[j],  50750000 + off[j], mod[i]);
+
+            // USA Cable HRC/IRC, ch 67-125
+            FREQ(modStr[i], std[j] + "high0", desc[i], sdesc[j] + "%1",
+                 67,  535750000 + off[j], 643750000 + off[j], mod[i]);
+            FREQ(modStr[i], std[j] + "high1", desc[i], sdesc[j] + "%1",
+                 100, 649750000 + off[j], 799750000 + off[j], mod[i]);
+        }
+    }
 }
diff -pruN mythtv-0.19/libs/libmythtv/hdtvrecorder.cpp mythtv/libs/libmythtv/hdtvrecorder.cpp
--- mythtv-0.19/libs/libmythtv/hdtvrecorder.cpp	2005-12-24 00:59:28.000000000 +1000
+++ mythtv/libs/libmythtv/hdtvrecorder.cpp	2006-04-20 23:46:13.000000000 +1000
@@ -627,9 +627,8 @@ void HDTVRecorder::StartRecording(void)
 
         len += remainder;
         remainder = ProcessData(_buffer, len);
-        if (remainder > 0) // leftover bytes
-            memmove(_buffer, &(_buffer[_buffer_size - remainder]),
-                    remainder);
+        if (remainder > 0 && (len > remainder)) // leftover bytes
+            memmove(_buffer, &(_buffer[len - remainder]), remainder);
     }
 
     FinishRecording();
diff -pruN mythtv-0.19/libs/libmythtv/ivtvdecoder.cpp mythtv/libs/libmythtv/ivtvdecoder.cpp
--- mythtv-0.19/libs/libmythtv/ivtvdecoder.cpp	2006-02-09 01:40:42.000000000 +1000
+++ mythtv/libs/libmythtv/ivtvdecoder.cpp	2006-03-23 00:35:05.000000000 +1000
@@ -270,7 +270,9 @@ int IvtvDecoder::OpenFile(RingBuffer *rb
 
     GetNVP()->SetVideoParams(720 /*width*/, (ntsc) ? 480 : 576 /*height*/,
                              (ntsc) ? 29.97f : 25.0f, keyframedist, 1.33);
-     
+
+    fps = (ntsc) ? 29.97f : 25.0f; // save for later length calculations
+
     ringBuffer->UpdateRawBitrate(8000);
 
     if (m_playbackinfo || livetv || watchingrecording)
diff -pruN mythtv-0.19/libs/libmythtv/jobqueue.cpp mythtv/libs/libmythtv/jobqueue.cpp
--- mythtv-0.19/libs/libmythtv/jobqueue.cpp	2005-12-16 15:17:00.000000000 +1000
+++ mythtv/libs/libmythtv/jobqueue.cpp	2006-02-19 05:58:41.000000000 +1000
@@ -275,6 +275,11 @@ void JobQueue::ProcessQueue(void)
                     (hostname != "") &&
                     (hostname != m_hostname))
                 {
+                    // Setting the status here will prevent us from processing
+                    // any other jobs for this recording until this one is
+                    // completed on the remote host.
+                    jobStatus[key] = status;
+
                     message = QString("JobQueue: Skipping '%1' job for chanid "
                                       "%2 @ %3, should run on '%4' instead")
                                       .arg(JobText(type))
diff -pruN mythtv-0.19/libs/libmythtv/libmythtv.pro mythtv/libs/libmythtv/libmythtv.pro
--- mythtv-0.19/libs/libmythtv/libmythtv.pro	2006-01-13 18:11:45.000000000 +1000
+++ mythtv/libs/libmythtv/libmythtv.pro	2006-03-15 05:52:59.000000000 +1000
@@ -144,10 +144,10 @@ using_frontend {
     # On screen display (video output overlay)
     HEADERS += osd.h                    osdtypes.h
     HEADERS += osdsurface.h             osdlistbtntype.h
-    HEADERS += udpnotify.h 
+    HEADERS += osdimagecache.h          udpnotify.h 
     SOURCES += osd.cpp                  osdtypes.cpp
     SOURCES += osdsurface.cpp           osdlistbtntype.cpp
-    SOURCES += udpnotify.cpp 
+    SOURCES += osdimagecache.cpp        udpnotify.cpp 
 
     # Video output
     HEADERS += videooutbase.h           videoout_null.h
diff -pruN mythtv-0.19/libs/libmythtv/mpegrecorder.cpp mythtv/libs/libmythtv/mpegrecorder.cpp
--- mythtv-0.19/libs/libmythtv/mpegrecorder.cpp	2005-12-24 00:59:28.000000000 +1000
+++ mythtv/libs/libmythtv/mpegrecorder.cpp	2006-05-11 15:51:20.000000000 +1000
@@ -363,9 +363,9 @@ bool MpegRecorder::OpenV4L2DeviceAsInput
 
     if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
     {
-        cerr << "Error setting codec params\n";
+        cerr << "Warning, unable to set recording volume\n";
+        cerr << "This is normal if you have an AVerMedia M179 card.\n";
         perror("VIDIOC_S_CTRL:");
-        return false;
     }
 
     if (vbimode) {
@@ -481,6 +481,9 @@ void MpegRecorder::StartRecording(void)
                 continue;
             case 0:
                 printf("select timeout - ivtv driver has stopped responding\n");
+                if(close(readfd) != 0)
+                    perror("close");
+                readfd = -1; // Force PVR card to be reopened on next iteration
                 continue;
            default: break;
         }
diff -pruN mythtv-0.19/libs/libmythtv/NuppelVideoPlayer.cpp mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
--- mythtv-0.19/libs/libmythtv/NuppelVideoPlayer.cpp	2006-02-08 07:56:06.000000000 +1000
+++ mythtv/libs/libmythtv/NuppelVideoPlayer.cpp	2006-04-27 01:23:01.000000000 +1000
@@ -147,6 +147,7 @@ NuppelVideoPlayer::NuppelVideoPlayer(QSt
       hascommbreaktable(false),
       deleteIter(deleteMap.end()),  blankIter(blankMap.end()),
       commBreakIter(commBreakMap.end()),
+      forcePositionMapSync(false),
       // Playback (output) speed control
       decoder_lock(true),
       next_play_speed(1.0f),        next_normal_speed(true),
@@ -747,6 +748,8 @@ int NuppelVideoPlayer::OpenFile(bool ski
         SetDecoder(new IvtvDecoder(this, m_playbackinfo));
         no_audio_out = true; // no audio with ivtv.
         audio_bits = 16;
+        audio_samplerate = 44100;
+        audio_channels = 2;
     }
     else if (forceVideoOutput == kVideoOutput_IVTV)
     {
@@ -1113,7 +1116,7 @@ void NuppelVideoPlayer::ShutdownYUVResiz
 const unsigned char *NuppelVideoPlayer::GetScaledFrame(QSize &size)
 {
     QMutexLocker locker(&yuv_lock);
-    yuv_desired_size = size = QSize(size.width() & ~0x3, size.height() & ~0x3);
+    yuv_desired_size = size = QSize(size.width() & ~0x7, size.height() & ~0x7);
 
     if ((size.width() > 0) && (size.height() > 0))
     {
@@ -1920,7 +1923,7 @@ void NuppelVideoPlayer::DisplayNormalFra
         ShowText();
         DisplaySubtitles();
     }
-    else if (osdHasSubtitles || nonDisplayedSubtitles.size() > 20)
+    else if (osdHasSubtitles)
     {
         ClearSubtitles();
     }
@@ -2176,7 +2179,10 @@ void NuppelVideoPlayer::SwitchToProgram(
     }
 
     if (eof)
+    {
         discontinuity = true;
+        ClearSubtitles();
+    }
 
     livetvchain->SetProgram(pginfo);
 
@@ -2199,6 +2205,7 @@ void NuppelVideoPlayer::SwitchToProgram(
     }
     if (IsErrored())
     {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "SwitchToProgram failed.");
         eof = true;
         return;
     }
@@ -2265,6 +2272,8 @@ void NuppelVideoPlayer::JumpToProgram(vo
     ringBuffer->Pause();
     ringBuffer->WaitForPause();
 
+    ClearSubtitles();
+
     livetvchain->SetProgram(pginfo);
 
     ringBuffer->Reset(true);
@@ -2284,6 +2293,7 @@ void NuppelVideoPlayer::JumpToProgram(vo
 
     if (errored || !GetDecoder())
     {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "JumpToProgram failed.");
         errored = true;
         return;
     }
@@ -2471,6 +2481,12 @@ void NuppelVideoPlayer::StartPlaying(voi
                 JumpToProgram();
         }
 
+        if (forcePositionMapSync)
+        {
+            forcePositionMapSync = false;
+            GetDecoder()->SyncPositionMap();
+        }
+
         if (IsErrored() || (nvr_enc && nvr_enc->GetErrorStatus()))
         {
             VERBOSE(VB_IMPORTANT, LOC_ERR + "Unknown error, exiting decoder");
@@ -4398,6 +4414,8 @@ void NuppelVideoPlayer::SetCommBreakMap(
     hascommbreaktable = !commBreakMap.isEmpty();
     SetCommBreakIter();
     commBreakMapLock.unlock();
+
+    forcePositionMapSync = true;
 }
 
 bool NuppelVideoPlayer::RebuildSeekTable(bool showPercentage, StatusCallback cb, void* cbData)
@@ -4541,7 +4559,8 @@ int NuppelVideoPlayer::GetSecondsBehind(
     return (int)((float)(written - played) / video_frame_rate);
 }
 
-void NuppelVideoPlayer::calcSliderPos(struct StatusPosInfo &posInfo)
+void NuppelVideoPlayer::calcSliderPos(struct StatusPosInfo &posInfo,
+                                      bool paddedFields)
 {
     posInfo.desc = "";
     posInfo.position = 0;
@@ -4588,15 +4607,23 @@ void NuppelVideoPlayer::calcSliderPos(st
     int ssecs = (playbackLen - shours * 3600 - smins * 60);
 
     QString text1, text2;
-    if (shours > 0)
+    if (paddedFields)
     {
-        text1.sprintf("%d:%02d:%02d", phours, pmins, psecs);
-        text2.sprintf("%d:%02d:%02d", shours, smins, ssecs);
+        text1.sprintf("%02d:%02d:%02d", phours, pmins, psecs);
+        text2.sprintf("%02d:%02d:%02d", shours, smins, ssecs);
     }
     else
     {
-        text1.sprintf("%d:%02d", pmins, psecs);
-        text2.sprintf("%d:%02d", smins, ssecs);
+        if (shours > 0)
+        {
+            text1.sprintf("%d:%02d:%02d", phours, pmins, psecs);
+            text2.sprintf("%d:%02d:%02d", shours, smins, ssecs);
+        }
+        else
+        {
+            text1.sprintf("%d:%02d", pmins, psecs);
+            text2.sprintf("%d:%02d", smins, ssecs);
+        }
     }
 
     posInfo.desc = QObject::tr("%1 of %2").arg(text1).arg(text2);
@@ -4654,6 +4681,7 @@ void NuppelVideoPlayer::AutoCommercialSk
 
             if (commBreakIter.key() == totalFrames)
             {
+                VERBOSE(VB_IMPORTANT, LOC + "Skipping commercial to end of file");
                 eof = true;
             }
             else
@@ -4721,7 +4749,7 @@ bool NuppelVideoPlayer::DoSkipCommercial
 
         QString message = "COMMFLAG_REQUEST ";
         message += m_playbackinfo->chanid + " " +
-                   m_playbackinfo->startts.toString(Qt::ISODate);
+                   m_playbackinfo->recstartts.toString(Qt::ISODate);
         RemoteSendMessage(message);
 
         return false;
@@ -5018,7 +5046,7 @@ void NuppelVideoPlayer::DisplaySubtitles
                 QImage scaledImage = qImage.smoothScale(rect->w, rect->h);
 
                 OSDTypeImage* image = new OSDTypeImage();
-                image->SetPosition(QPoint(rect->x, rect->y));
+                image->SetPosition(QPoint(rect->x, rect->y), hmult, vmult);
                 image->LoadFromQImage(scaledImage);
 
                 subtitleOSD->AddType(image);
diff -pruN mythtv-0.19/libs/libmythtv/NuppelVideoPlayer.h mythtv/libs/libmythtv/NuppelVideoPlayer.h
--- mythtv-0.19/libs/libmythtv/NuppelVideoPlayer.h	2006-02-03 04:06:32.000000000 +1000
+++ mythtv/libs/libmythtv/NuppelVideoPlayer.h	2006-03-18 08:22:45.000000000 +1000
@@ -150,7 +150,8 @@ class NuppelVideoPlayer
     // Complicated gets
     long long CalcMaxFFTime(long long ff, bool setjump = true) const;
     long long CalcRWTime(long long rw) const;
-    void      calcSliderPos(struct StatusPosInfo &posInfo);
+    void      calcSliderPos(struct StatusPosInfo &posInfo,
+                            bool paddedFields = false);
 
     /// Non-const gets
     OSD         *GetOSD(void)                 { return osd; }
@@ -543,6 +544,7 @@ class NuppelVideoPlayer
     QMap<long long, int>::Iterator deleteIter;
     QMap<long long, int>::Iterator blankIter;
     QMap<long long, int>::Iterator commBreakIter;
+    bool       forcePositionMapSync;
 
     // Playback (output) speed control
     /// Lock for next_play_speed and next_normal_speed
diff -pruN mythtv-0.19/libs/libmythtv/NuppelVideoRecorder.cpp mythtv/libs/libmythtv/NuppelVideoRecorder.cpp
--- mythtv-0.19/libs/libmythtv/NuppelVideoRecorder.cpp	2006-01-21 02:31:04.000000000 +1000
+++ mythtv/libs/libmythtv/NuppelVideoRecorder.cpp	2006-03-31 11:55:22.000000000 +1000
@@ -216,7 +216,10 @@ NuppelVideoRecorder::~NuppelVideoRecorde
     }
 
     if (mpa_codec)
+    {
+        QMutexLocker locker(&avcodeclock);
         avcodec_close(mpa_ctx);
+    }
 
     if (mpa_ctx)
         av_free(mpa_ctx);
@@ -453,8 +456,11 @@ bool NuppelVideoRecorder::SetupAVCodec(v
         useavcodec = true;
 
     if (mpa_codec)
+    {
+        QMutexLocker locker(&avcodeclock);
         avcodec_close(mpa_ctx);
-    
+    }
+
     if (mpa_ctx)
         av_free(mpa_ctx);
     mpa_ctx = NULL;
@@ -626,13 +632,14 @@ int NuppelVideoRecorder::AudioInit(bool 
     int frag, blocksize = 4096;
     int tmp;
 
-#if !defined (HAVE_SYS_SOUNDCARD_H) && !defined(HAVE_SOUNDCARD_H)
-    VERBOSE(VB_IMPORTANT, QString("NVR::AudioInit() This Unix doesn't support"
-                                  " device files for audio access. Skipping"));
-    return 1;
-#else
     if (!skipdevice)
     {
+#if !defined (HAVE_SYS_SOUNDCARD_H) && !defined(HAVE_SOUNDCARD_H)
+        VERBOSE(VB_IMPORTANT,
+                QString("NVR::AudioInit() This Unix doesn't support"
+                        " device files for audio access. Skipping"));
+        return 1;
+#else
         if (-1 == (afd = open(audiodevice.ascii(), O_RDONLY | O_NONBLOCK)))
         {
             VERBOSE(VB_IMPORTANT, QString("NVR: Error, cannot open DSP '%1'").
@@ -678,8 +685,8 @@ int NuppelVideoRecorder::AudioInit(bool 
         }
 
         close(afd);
-    }
 #endif
+    }
 
     audio_bytes_per_sample = audio_channels * audio_bits / 8;
     blocksize *= 4;
diff -pruN mythtv-0.19/libs/libmythtv/osd.cpp mythtv/libs/libmythtv/osd.cpp
--- mythtv-0.19/libs/libmythtv/osd.cpp	2006-01-27 14:55:51.000000000 +1000
+++ mythtv/libs/libmythtv/osd.cpp	2006-02-19 07:26:06.000000000 +1000
@@ -154,7 +154,8 @@ void OSD::SetDefaults(void)
         }
 
         OSDTypeCC *ccpage = new OSDTypeCC(name, ccfont, sub_xoff, sub_yoff,
-                                          sub_dispw, sub_disph);
+                                          sub_dispw, sub_disph,
+                                          wmult, hmult);
         container->AddType(ccpage);
     }
 
@@ -517,7 +518,7 @@ void OSD::parseBox(OSDSet *container, QD
         }
     }
 
-    OSDTypeBox *box = new OSDTypeBox(name, area);
+    OSDTypeBox *box = new OSDTypeBox(name, area, wmult, hmult);
     container->AddType(box);
 }
 
@@ -658,7 +659,7 @@ void OSD::parseTextArea(OSDSet *containe
         return;
     }
 
-    OSDTypeText *text = new OSDTypeText(name, ttffont, "", area);
+    OSDTypeText *text = new OSDTypeText(name, ttffont, "", area, wmult, hmult);
     container->AddType(text);
 
     text->SetMultiLine(multiline);
@@ -875,7 +876,7 @@ void OSD::parsePositionRects(OSDSet *con
                 QRect area = parseRect(getFirstText(info));
                 normalizeRect(area);
 
-                rects->AddPosition(area);
+                rects->AddPosition(area, wmult, hmult);
             }
             else
             {
@@ -919,7 +920,7 @@ void OSD::parsePositionImage(OSDSet *con
                 pos.setX((int)(pos.x() * wmult + xoffset));
                 pos.setY((int)(pos.y() * hmult + yoffset));
 
-                image->AddPosition(pos);
+                image->AddPosition(pos, wmult, hmult);
             }
             else if (info.tagName() == "staticsize")
             {
@@ -1925,7 +1926,7 @@ void OSD::ShowEditArrow(long long number
         image = new OSDTypeImage(*editarrowright);
     }
 
-    image->SetPosition(QPoint(xpos, ypos));
+    image->SetPosition(QPoint(xpos, ypos), wmult, hmult);
 
     set->AddType(image);
     set->Display();
diff -pruN mythtv-0.19/libs/libmythtv/osdimagecache.cpp mythtv/libs/libmythtv/osdimagecache.cpp
--- mythtv-0.19/libs/libmythtv/osdimagecache.cpp	1970-01-01 10:00:00.000000000 +1000
+++ mythtv/libs/libmythtv/osdimagecache.cpp	2006-05-10 09:54:43.000000000 +1000
@@ -0,0 +1,296 @@
+// -*- Mode: c++ -*-
+/** OSDImageCache
+ *  Copyright (c) 2006 by Pekka Jääskeläinen, Daniel Thor Kristjansson
+ *  Distributed as part of MythTV under GPL v2 and later.
+ */
+
+// POSIX headers
+#include <stdint.h>
+
+// Qt headers
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdatastream.h>
+#include <qdeepcopy.h>
+
+// MythTV headers
+#include "mythcontext.h"
+#include "osdimagecache.h"
+
+// Print statistics of OSD image access in the destructor of OSDImageCache
+//#define PRINT_OSD_IMAGE_CACHE_STATS
+
+#define LOC QString("OSDImgCache: ")
+#define LOC_ERR QString("OSDImgCache, Error: ")
+
+uint OSDImageCache::kMaximumMemoryCacheSize = 5 * 1024 * 1024;
+
+/** \fn OSDImageCacheValue::OSDImageCacheValue(unsigned char*,unsigned char*,unsighed char*,unsigned char*,unsighed char*, QRect)
+ *  \brief The main constructor that takes the image data as arguments.
+ *
+ *   The image data becomes property of the OSDImageCacheValue 
+ *   and will be deleted by it.
+ */
+OSDImageCacheValue::OSDImageCacheValue(
+    QString cacheKey,
+    unsigned char *yuv,     unsigned char *ybuffer,
+    unsigned char *ubuffer, unsigned char *vbuffer,
+    unsigned char *alpha,   QRect imagesize) :
+    m_yuv(yuv),         m_ybuffer(ybuffer),
+    m_ubuffer(ubuffer), m_vbuffer(vbuffer),
+    m_alpha(alpha),     m_imagesize(imagesize),
+    m_cacheKey(QDeepCopy<QString>(cacheKey))
+{
+    uint yuv_size = m_imagesize.width() * m_imagesize.height() * 3 / 2;
+    m_size_in_bytes =
+        (sizeof(OSDImageCacheValue)) + yuv_size + 
+        (m_imagesize.width() * m_imagesize.height());
+}
+
+/** \fn OSDImageCacheValue::~OSDImageCacheValue()
+ *  \brief Destructor, frees the cached bitmaps.
+ */
+OSDImageCacheValue::~OSDImageCacheValue()
+{
+    delete [] m_yuv;
+    m_yuv = NULL;
+    delete [] m_alpha;
+    m_alpha = NULL;
+}
+
+/** \fn OSDImageCache::OSDImageCache()
+ *  \brief Constructor, initializes the internal cache structures.
+ */
+OSDImageCache::OSDImageCache() : 
+    m_cacheLock(true), m_imageCache(kMaximumMemoryCacheSize, 50),
+    m_memHits(0), m_diskHits(0), m_misses(0) 
+{
+    // When the cache gets too large, items are
+    // automatically deleted from it in LRU order.
+    m_imageCache.setAutoDelete(true);
+}
+
+/** \fn OSDImageCache::~OSDImageCache()
+ *  \brief Destructor, frees all cached OSD images.
+ */
+OSDImageCache::~OSDImageCache() 
+{
+#ifdef PRINT_OSD_IMAGE_CACHE_STATS
+    int totalAccess = m_memHits + m_diskHits + m_misses;
+    if (totalAccess == 0)
+        return;
+
+#define LOG_PREFIX "OSDImageCache: "
+    VERBOSE(VB_IMPORTANT, LOC << " Statistics: " << endl
+            << LOG_PREFIX << m_imageCache.totalCost() << " bytes in cache\n" 
+            << LOG_PREFIX << " memory hits: " 
+            << m_memHits << ", " << m_memHits*100.0/totalAccess << "%\n"
+            << LOG_PREFIX << "   disk hits: " 
+            << m_diskHits << ", " << m_diskHits*100.0/totalAccess << "%\n"
+            << LOG_PREFIX << "      misses: " 
+            << m_misses << ", " << m_misses*100.0/totalAccess << "%");
+#undef LOC_PREFIX
+#endif
+    Reset();
+}
+
+/** \fn OSDImageCache::Contains(const QString&,bool)
+ *  \brief Returns true if cached OSD image was found in the cache.
+ *
+ *  \param key The key for this image.
+ *  \param useFile If true, also look from the disk cache.
+ */
+bool OSDImageCache::Contains(const QString &key, bool useFile) const
+{
+    QMutexLocker locker(&m_cacheLock);
+
+    if (m_imageCache.find(key) != NULL)
+        return true;
+
+    if (!useFile)
+        return false;
+
+    return InFileCache(key);
+}
+
+bool OSDImageCache::InFileCache(const QString &key) const
+{
+    // check if cache file exists
+    QDir dir(MythContext::GetConfDir() + "/osdcache/");
+    QFileInfo cFile(dir.path() + "/" + key);
+    if (!cFile.exists() || !cFile.isReadable())
+        return false;
+
+    // check if backing file exists
+    QString orig = ExtractOriginal(key);
+    if (orig.isEmpty())
+        return false;
+
+    QFileInfo oFile(orig);
+    if (!oFile.exists())
+    {
+        VERBOSE(VB_IMPORTANT, LOC + QString("Can't find '%1'").arg(orig));
+        return false;
+    }
+
+    // if cache file is older than backing file, delete cache file
+    if (cFile.lastModified() < oFile.lastModified())
+    {
+        cFile.dir().remove(cFile.baseName(true));
+        return false;
+    } 
+
+    return true;
+}
+
+/** \fn OSDImageCache::Get(const QString&,bool)
+ *  \brief Returns OSD image data from cache.
+ *
+ *   This also removes the image from the cache so it won't be deleted
+ *   while in use. The deletion of the taken item becomes responsibility
+ *   of the client. Returns NULL if item with the given key is not found.
+ *
+ *  \param key The key for this image.
+ *  \param useFile If true, also check the disk cache.
+ */
+OSDImageCacheValue *OSDImageCache::Get(const QString &key, bool useFile)
+{
+    QMutexLocker locker(&m_cacheLock);
+    OSDImageCacheValue* item = m_imageCache.find(key);
+    if (item)
+    {
+        m_memHits++;
+        return m_imageCache.take(key);
+    }
+
+    if (!useFile || !InFileCache(key))
+    {
+        m_misses++;
+        return NULL;
+    }
+
+    QDir dir(MythContext::GetConfDir() + "/osdcache/");
+    QFile cacheFile(dir.path() + "/" + key);
+    cacheFile.open(IO_ReadOnly);
+    uint32_t imwidth  = 0;
+    uint32_t imheight = 0;
+
+    QDataStream stream(&cacheFile);
+    stream >> imwidth >> imheight;   
+
+    uint yuv_size = imwidth * imheight * 3 / 2;
+    uint tot_size = (sizeof(imwidth) * 2) + yuv_size + (imwidth * imheight);
+
+    if (cacheFile.size() != tot_size)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + key + " wrong cache file size!"
+                << cacheFile.size() << " != " << tot_size);
+        return NULL;
+    }
+
+    unsigned char *yuv = new unsigned char[yuv_size];
+    unsigned char *alpha = new unsigned char[imwidth * imheight];
+    stream.readRawBytes((char*)yuv,   yuv_size);
+    stream.readRawBytes((char*)alpha, imwidth * imheight);
+    cacheFile.close();
+
+    OSDImageCacheValue* value = 
+        new OSDImageCacheValue(
+            key,
+            yuv, yuv,
+            yuv + (imwidth * imheight),
+            yuv + (imwidth * imheight * 5 / 4),
+            alpha, QRect(0, 0, imwidth, imheight));
+
+    m_diskHits++;
+    return value;
+}
+
+/** \fn OSDImageCache::Insert(OSDImageCacheValue*)
+ *  \brief Inserts OSD image data to memory cache.
+ *
+ *   The item becomes property of the OSDImageCache and may be 
+ *   deleted any time by it.
+ *
+ *  \param value The cache item.
+ */
+void OSDImageCache::Insert(OSDImageCacheValue *value)
+{
+    if (!value)
+        return;
+
+    QMutexLocker locker(&m_cacheLock);
+    if (!m_imageCache.insert(value->GetKey(), value, value->GetSize()))
+    {
+        VERBOSE(VB_IMPORTANT, 
+                LOC_ERR + QString("inserting image to memory cache failed"));
+    }
+}
+
+
+/** \fn OSDImageCache::SaveToDisk(const OSDImageCacheValue*)
+ *  \brief Saves OSD image data to disk cache.
+ *
+ *   Item is not written to the memory cache, i.e., it stays as
+ *   property of the client.
+ *
+ *  \param value The cached OSD image to save.
+ */
+void OSDImageCache::SaveToDisk(const OSDImageCacheValue *value)
+{
+    if (InFileCache(value->GetKey()))
+        return;
+
+    QDir dir(MythContext::GetConfDir() + "/osdcache/");
+    if (!dir.exists() && !dir.mkdir(dir.path()))
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Creating osdcache directory failed.");
+        return;
+    }
+
+    QFile cacheFile(dir.path() + "/" + value->GetKey());
+    if (!cacheFile.open(IO_WriteOnly | IO_Truncate))
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Creating osdcache file failed.");
+        return;
+    }
+
+    uint32_t imwidth  = value->m_imagesize.width();
+    uint32_t imheight = value->m_imagesize.height();
+    uint     yuv_size = imwidth * imheight * 3 / 2;
+
+    QDataStream stream(&cacheFile);
+    stream << imwidth << imheight;   
+    stream.writeRawBytes((const char*)value->m_yuv, yuv_size);
+    stream.writeRawBytes((const char*)value->m_alpha, imwidth * imheight);
+    cacheFile.close();
+}
+
+/** \fn OSDImageCache::CreateKey(const QString&,float,float,int,int)
+ *  \brief Generates a cache key from the given OSD image parameters.
+ *
+ *   The returned key is a string that can be safely used as a file name.
+ */
+QString OSDImageCache::CreateKey(const QString &filename, float wmult, 
+                                 float hmult, int scalew, int scaleh)
+{
+    QString tmp = filename;
+    return QString("cache_%1@%2_%3_%4_%5").arg(tmp.replace(QChar('/'), "+"))
+        .arg(wmult).arg(hmult).arg(scalew).arg(scaleh);
+}
+
+QString OSDImageCache::ExtractOriginal(const QString &key)
+{
+    QString tmp0 = key.mid(6);
+    QString tmp1 = tmp0.left(tmp0.find("@"));
+    QString tmp2 = tmp1.replace(QChar('+'), "/");
+    return tmp2;
+}
+
+void OSDImageCache::Reset(void)
+{
+    QMutexLocker locker(&m_cacheLock);
+    // this also deletes the images due to setAutoDelete(true)
+    m_imageCache.clear();
+}
diff -pruN mythtv-0.19/libs/libmythtv/osdimagecache.h mythtv/libs/libmythtv/osdimagecache.h
--- mythtv-0.19/libs/libmythtv/osdimagecache.h	1970-01-01 10:00:00.000000000 +1000
+++ mythtv/libs/libmythtv/osdimagecache.h	2006-05-10 09:54:43.000000000 +1000
@@ -0,0 +1,74 @@
+// -*- Mode: c++ -*-
+
+// POSIX headers
+#include <stdint.h>
+
+// Qt headers
+#include <qmap.h>
+#include <qrect.h>
+#include <qmutex.h>
+#include <qstring.h>
+#include <qasciicache.h>
+
+class OSDImageCacheValue
+{
+  public:
+    OSDImageCacheValue(QString cacheKey,
+		       unsigned char *yuv,     unsigned char *ybuffer,
+                       unsigned char *ubuffer, unsigned char *vbuffer,
+                       unsigned char *alpha,   QRect imagesize);
+
+    virtual ~OSDImageCacheValue();
+
+    uint    GetSize(void) const { return m_size_in_bytes; }
+    QString GetKey(void)  const { return m_cacheKey;      }
+
+  public:
+    unsigned char *m_yuv;
+    unsigned char *m_ybuffer;
+    unsigned char *m_ubuffer;
+    unsigned char *m_vbuffer;
+    unsigned char *m_alpha;
+    QRect          m_imagesize;
+
+  private:
+    uint           m_size_in_bytes;
+    QString        m_cacheKey;
+};
+
+typedef QAsciiCache<OSDImageCacheValue> img_cache_t;
+
+class OSDImageCache
+{
+  public:
+    OSDImageCache();
+    virtual ~OSDImageCache();
+
+    bool InFileCache(const QString &key) const;
+
+    bool Contains(const QString &key, bool useFile) const;
+
+    OSDImageCacheValue *Get(const QString &key, bool useFile);
+
+    void Insert(OSDImageCacheValue* value);
+
+    void SaveToDisk(const OSDImageCacheValue *value);
+
+    void Reset(void);
+
+    static QString CreateKey(const QString &filename,
+                             float wmult, float hmult,
+                             int scalew,  int scaleh);
+
+    static QString ExtractOriginal(const QString &key);
+
+  private:
+    mutable QMutex m_cacheLock;
+    img_cache_t    m_imageCache;
+    int            m_memHits;
+    int            m_diskHits;
+    int            m_misses;
+
+    /// Limit on the maximum total size of OSD images cached in *memory*.
+    static uint    kMaximumMemoryCacheSize;
+};
diff -pruN mythtv-0.19/libs/libmythtv/osdlistbtntype.cpp mythtv/libs/libmythtv/osdlistbtntype.cpp
--- mythtv-0.19/libs/libmythtv/osdlistbtntype.cpp	2005-12-05 11:39:09.000000000 +1000
+++ mythtv/libs/libmythtv/osdlistbtntype.cpp	2006-02-19 07:26:06.000000000 +1000
@@ -19,206 +19,148 @@
  * 
  * ============================================================ */
 
-#include <iostream>
+// ANSI C headers
+#include <cmath>
 
+// C++ headers
+#include <algorithm>
+using namespace std;
+
+// Qt headers
 #include <qapplication.h>
 #include <qpixmap.h>
 #include <qpainter.h>
 #include <qimage.h>
 #include <qcolor.h>
 
+// MythTV headers
 #include "mythcontext.h"
 #include "mythdialogs.h"
-
 #include "osdlistbtntype.h"
 
+#define LOC QString("OSDListTreeType: ")
+#define LOC_ERR QString("OSDListTreeType, Error: ")
 
-OSDGenericTree::OSDGenericTree(OSDGenericTree *parent, const QString &name, 
-                               const QString &action, int check, 
-                               OSDTypeImage *image, QString group)
-              : GenericTree(name)
-{
-    m_checkable = check;
-    m_action = action;
-    m_image = image;
-    m_parentButton = NULL;
-
-    if (group != "")
-        m_group = group;
-    else
-        m_group = action;
-
-    if (!action.isEmpty() && !action.isNull())
-        setSelectable(true);
-
-    if (parent)
-        parent->addNode(this);
-}
-
-////////////////////////////////////////////////////////////////////////////
-
-OSDListTreeType::OSDListTreeType(const QString &name, const QRect &area,
-                                 const QRect &levelsize, int levelspacing,
-                                 float wmult, float hmult)
-               : OSDType(name)
+static QRect unbias(QRect rect, float wmult, float hmult)
 {
-    m_wmult = wmult;
-    m_hmult = hmult;
-
-    m_totalarea = area;
-    m_levelsize = levelsize;
-    m_levelspacing = levelspacing;
-
-    if (gContext->GetNumSetting("UseArrowAccels", 1))
-        m_arrowAccel = true;
-    else
-        m_arrowAccel = false;
-    
-    levels = 0;
-    curlevel = -1;
-
-    treetop = NULL;
-    currentpos = NULL;
-
-    currentlevel = NULL;
-
-    listLevels.setAutoDelete(true);
-
-    m_active = NULL;
-    m_inactive = NULL;
+    return QRect((int)round(rect.x()      / wmult),
+                 (int)round(rect.y()      / hmult),
+                 (int)ceil( rect.width()  / wmult),
+                 (int)ceil( rect.height() / hmult));
+}
+
+static QRect bias(QRect rect, float wmult, float hmult)
+{
+    return QRect((int)round(rect.x()      * wmult),
+                 (int)round(rect.y()      * hmult),
+                 (int)ceil( rect.width()  * wmult),
+                 (int)ceil( rect.height() * hmult));
+}
+
+OSDListTreeType::OSDListTreeType(
+    const QString &name,      const QRect &area,
+    const QRect   &levelsize, int          levelspacing,
+    float          wmult,     float        hmult)
+    : OSDType(name),
+      treetop(NULL),                    currentpos(NULL),
+      m_active(NULL),                   m_inactive(NULL),
+      m_itemRegBeg(Qt::black),          m_itemRegEnd(QColor(80,80,80)),
+      m_itemSelBeg(QColor(82,202,56)),  m_itemSelEnd(QColor(52,152,56)),
+      m_itemRegAlpha(100),              m_itemSelAlpha(255),
+      m_spacing(0),                     m_margin(0),
+      m_levelspacing(levelspacing),
+      m_totalarea(area),                m_levelsize(levelsize),
+      m_unbiasedspacing(1.0f),          m_unbiasedmargin(1.0f),
+      m_unbiasedarea(0,0,0,0),          m_unbiasedsize(0,0,0,0),
+      m_wmult(wmult),                   m_hmult(hmult),
+      m_depth(0),                        m_levelnum(-1),
+      m_visible(true),
+      m_arrowAccel(gContext->GetNumSetting("UseArrowAccels", 1))
+{
+    m_wmult        = (wmult == 0.0f) ? 1.0f : wmult;
+    m_hmult        = (hmult == 0.0f) ? 1.0f : hmult;
+    m_unbiasedarea = unbias(area,      wmult, hmult);
+    m_unbiasedsize = unbias(levelsize, wmult, hmult);
+}
+
+OSDListTreeType::~OSDListTreeType()
+{
+    OSDListBtnList::iterator it = listLevels.begin();
+    for (; it != listLevels.end(); ++it)
+        delete *it;    
+}
+
+void OSDListTreeType::Reinit(float wmult, float hmult)
+{
+    m_wmult     = (wmult == 0.0f) ? 1.0f : wmult;
+    m_hmult     = (hmult == 0.0f) ? 1.0f : hmult;
+    m_spacing   = (uint) round(m_unbiasedspacing * wmult);
+    m_margin    = (uint) round(m_unbiasedmargin  * wmult);
+    m_totalarea = bias(m_unbiasedarea, wmult, hmult);
+    m_levelsize = bias(m_unbiasedsize, wmult, hmult);
+
+    if (!treetop || m_levelnum < 0)
+        return;
+
+    // Save item indices
+    vector<uint> list;
+    for (uint i = 0; i <= (uint)m_levelnum; i++)
+        list.push_back(listLevels[i]->GetItemCurrentPos());
+
+    // Delete old OSD items
+    OSDListBtnList clone = listLevels;
+    listLevels.clear();
+    OSDListBtnList::iterator it = clone.begin();
+    for (; it != clone.end(); ++it)
+        delete *it;
 
-    SetItemRegColor(Qt::black,QColor(80,80,80),100);
-    SetItemSelColor(QColor(82,202,56),QColor(52,152,56),255);
-
-    m_spacing = 0;
-    m_margin = 0;
-}
-
-void OSDListTreeType::Reinit(float wchange, float hchange, float wmult,
-                             float hmult)
-{
-    m_wmult = wmult;
-    m_hmult = hmult;
-
-    m_spacing = (int)(m_spacing * wchange);
-    m_margin = (int)(m_margin * wchange);
-
-    int width = (int)(m_totalarea.width() * wchange);
-    int height = (int)(m_totalarea.height() * hchange);
-    int x = (int)(m_totalarea.x() * wchange);
-    int y = (int)(m_totalarea.y() * hchange);
-
-    m_totalarea = QRect(x, y, width, height);
-
-    width = (int)(m_levelsize.width() * wchange);
-    height = (int)(m_levelsize.height() * hchange);
-    x = (int)(m_levelsize.x() * wchange);
-    y = (int)(m_levelsize.y() * hchange);
-
-    m_levelsize = QRect(x, y, width, height);
-
-    QPtrListIterator<OSDListBtnType> it(listLevels);
-    OSDListBtnType *child;
-
-    while ((child = it.current()) != 0)
-    {
-        child->Reinit(wchange, hchange, wmult, hmult);
-        ++it;
-    }
+    // Create new OSD items
+    SetAsTree(treetop, &list);
 }
 
 void OSDListTreeType::SetGroupCheckState(QString group, int newState)
 {
-    QPtrListIterator<OSDListBtnType> it(listLevels);
-    OSDListBtnType *child;
-    while ((child = it.current()) != 0)
-    {
-        child->SetGroupCheckState(group, newState);
-        ++it;
-    }
+    OSDListBtnList::iterator it = listLevels.begin();
+    for (; it != listLevels.end(); ++it)
+        (*it)->SetGroupCheckState(group, newState);
 }
 
-void OSDListTreeType::SetItemRegColor(const QColor& beg, const QColor& end,
-                                      uint alpha)
-{
-    m_itemRegBeg   = beg;
-    m_itemRegEnd   = end;
-    m_itemRegAlpha = alpha;
-}
-
-void OSDListTreeType::SetItemSelColor(const QColor& beg, const QColor& end,
-                                      uint alpha)
-{
-    m_itemSelBeg   = beg;
-    m_itemSelEnd   = end;
-    m_itemSelAlpha = alpha;
-}
-
-void OSDListTreeType::SetFontActive(TTFFont *font)
-{
-    m_active = font;
-}
-
-void OSDListTreeType::SetFontInactive(TTFFont *font)
-{
-    m_inactive = font;
-}
-
-void OSDListTreeType::SetSpacing(int spacing)
-{
-    m_spacing = spacing;
-}
-
-void OSDListTreeType::SetMargin(int margin)
-{
-    m_margin = margin;
-}
-
-void OSDListTreeType::SetAsTree(OSDGenericTree *toplevel)
+void OSDListTreeType::SetAsTree(OSDGenericTree *toplevel,
+                                vector<uint> *select_list)
 {
     if (treetop)
     {
         listLevels.clear();
-        currentlevel = NULL;
-        treetop = NULL;
-        currentpos = NULL;
-        levels = 0;
-        curlevel = -1;
+        treetop      = NULL;
+        currentpos   = NULL;
+        m_depth      = 0;
+        m_levelnum   = -1;
     }
 
-    levels = toplevel->calculateDepth(0) - 1;
-
-    if (levels <= 0)
+    m_depth = toplevel->calculateDepth(0) - 1;
+    if (m_depth <= 0)
     {
-        cerr << "Need at least one level\n";
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "SetAsTree: Need at least one level");
         return;
     }
 
-    currentpos = (OSDGenericTree *)toplevel->getChildAt(0);
-
+    currentpos = (OSDGenericTree*) toplevel->getChildAt(0);
     if (!currentpos)
     {
-        cerr << "No top-level children?\n";
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "SetAsTree: Need top-level children");
         return;
     }
 
-    treetop = toplevel;
-
-    // just for now, remove later
-    if (levels > 2)
-        levels = 3;
-
-    for (int i = 0; i < levels; i++)
+    // Create OSD buttons for all levels
+    for (uint i = 0; i < (uint)m_depth; i++)
     {
         QString levelname = QString("level%1").arg(i + 1);
-
         QRect curlevelarea = m_levelsize;
         curlevelarea.moveBy(m_totalarea.x(), m_totalarea.y());
-
         curlevelarea.moveBy((m_levelsize.width() + m_levelspacing) * i, 0);
 
-        OSDListBtnType *newlevel = new OSDListBtnType(levelname, curlevelarea,
-                                                      m_wmult, m_hmult, true);
+        OSDListBtnType *newlevel = new OSDListBtnType(
+            levelname, curlevelarea, m_wmult, m_hmult, true);
 
         newlevel->SetFontActive(m_active);
         newlevel->SetFontInactive(m_inactive);
@@ -227,229 +169,200 @@ void OSDListTreeType::SetAsTree(OSDGener
         newlevel->SetSpacing(m_spacing);
         newlevel->SetMargin(m_margin);
 
-        listLevels.append(newlevel);
+        listLevels.push_back(newlevel);
     }
 
-    currentlevel = GetLevel(0);
+    // Set up needed levels and selects
+    vector<uint> slist;
+    slist.push_back(0);
+    if (select_list)
+        slist = *select_list;
 
-    if (!currentlevel)
+    currentpos = treetop = toplevel;
+    for (m_levelnum = 0; m_levelnum < (int)slist.size(); m_levelnum++)
     {
-        cerr << "Something is seriously wrong (currentlevel = NULL)\n";
-        return;
+        FillLevelFromTree(currentpos, m_levelnum);
+        GetLevel(m_levelnum)->SetActive(true);
+        GetLevel(m_levelnum)->SetVisible(true);
+        if (slist[m_levelnum])
+            GetLevel(m_levelnum)->SetItemCurrent(slist[m_levelnum]);
+        EnterItem(); // updates currentpos
     }
-
-    FillLevelFromTree(toplevel, currentlevel);
-
-    currentlevel->SetVisible(true);
-    currentlevel->SetActive(true);
-
-    currentpos = (OSDGenericTree *)(currentlevel->GetItemFirst()->getData());
-    curlevel = 0;
-
-    emit itemEntered(this, currentpos);
+    m_levelnum--;
 }
 
-OSDGenericTree *OSDListTreeType::GetCurrentPosition(void)
+static bool has_action(QString action, const QStringList &actions)
 {
-    return currentpos;
+    QStringList::const_iterator it;
+    for (it = actions.begin(); it != actions.end(); ++it)
+    {
+        if (action == *it)
+            return true;
+    }
+    return false;
 }
 
 bool OSDListTreeType::HandleKeypress(QKeyEvent *e)
 {
-    if (!currentlevel)
+    QStringList actions;
+    bool ok = gContext->GetMainWindow()->TranslateKeyPress(
+        "TV Playback", e, actions);
+
+    if (!ok || ((uint)m_levelnum >= listLevels.size()))
         return false;
+    else if (has_action("UP", actions))
+    {
+        GetLevel(m_levelnum)->MoveUp();
+        EnterItem();
+    }
+    else if (has_action("DOWN", actions))
+    {
+        GetLevel(m_levelnum)->MoveDown();
+        EnterItem();
+    }
+    else if (has_action("LEFT", actions) && (m_levelnum > 0))
+    {
+        GetLevel(m_levelnum)->Reset();
+        GetLevel(m_levelnum)->SetVisible(false);
 
-    bool handled = false;
-    QStringList actions;
-    if (gContext->GetMainWindow()->TranslateKeyPress("TV Playback", e, 
-                                                     actions))
+        m_levelnum--;
+        EnterItem();
+    }
+    else if ((has_action("LEFT", actions) && m_arrowAccel) ||
+             has_action("ESCAPE",   actions) ||
+             has_action("CLEAROSD", actions) ||
+             has_action("MENU",     actions))
     {
-        for (unsigned int i = 0; i < actions.size() && !handled; i++)
-        {
-            QString action = actions[i];
-            handled = true;
+        m_visible = false;
+    }
+    else if (has_action("RIGHT", actions) &&
+             (m_levelnum + 1 < m_depth) &&
+             (currentpos->childCount() > 0))
+    {
+        GetLevel(m_levelnum)->SetActive(false);
+        m_levelnum++;
 
-            if (action == "UP")
-            {
-                currentlevel->MoveUp();
-                SetCurrentPosition();
-            }
-            else if (action == "DOWN")
-            {
-                currentlevel->MoveDown();
-                SetCurrentPosition();
-            }
-            else if (action == "LEFT")
-            {
-                if (curlevel > 0)
-                {
-                    currentlevel->Reset();
-                    currentlevel->SetVisible(false);
-
-                    curlevel--;
-
-                    currentlevel = GetLevel(curlevel);
-                    currentlevel->SetActive(true);
-                    SetCurrentPosition();
-                }
-                else if (m_arrowAccel)
-                {
-                    m_visible = false;
-                }
-            }
-            else if (action == "RIGHT")
-            {
-                // FIXME: create new levels if needed..
-                if (curlevel + 1 < levels && currentpos->childCount() > 0)
-                {
-                    currentlevel->SetActive(false);
-
-                    curlevel++;
-
-                    currentlevel = GetLevel(curlevel);
-
-                    FillLevelFromTree(currentpos, currentlevel);
-
-                    currentlevel->SetVisible(true);
-                    currentlevel->SetActive(true);
-                    SetCurrentPosition();
-                }
-                else if (m_arrowAccel)
-                {
-                    SetGroupCheckState(currentpos->getGroup(),
-                                       OSDListBtnTypeItem::NotChecked);
-                    currentpos->getParentButton()->setChecked(
-                                       OSDListBtnTypeItem::FullChecked);
-                    emit itemSelected(this, currentpos);
-                }
-            }
-            else if (action == "ESCAPE" || action == "MENU" ||
-                     action == "CLEAROSD")
-                m_visible = false;
-            else if (action == "SELECT")
-            {
-                SetGroupCheckState(currentpos->getGroup(),
-                                   OSDListBtnTypeItem::NotChecked);
-                currentpos->getParentButton()->setChecked(
-                                   OSDListBtnTypeItem::FullChecked);
-                emit itemSelected(this, currentpos);
-            }
-            else
-                handled = false;
-        }
+        FillLevelFromTree(currentpos, m_levelnum);
+        GetLevel(m_levelnum)->SetVisible(true);
+        EnterItem();
+    }
+    else if ((has_action("RIGHT", actions) && m_arrowAccel) ||
+             has_action("SELECT", actions))
+    {
+        SelectItem();
+    }
+    else
+    {
+        return false;
     }
 
-    return handled;
+    return true;
 }
 
 void OSDListTreeType::Draw(OSDSurface *surface, int fade, int maxfade, 
                            int xoff, int yoff)
 {
-    QPtrListIterator<OSDListBtnType> it(listLevels);
-    OSDListBtnType *child;
-
-    while ((child = it.current()) != 0)
-    {
-        child->Draw(surface, fade, maxfade, xoff, yoff);
-        ++it;
-    }
+    OSDListBtnList::iterator it = listLevels.begin();
+    for (; it != listLevels.end(); ++it)
+        (*it)->Draw(surface, fade, maxfade, xoff, yoff);
 }
 
 void OSDListTreeType::FillLevelFromTree(OSDGenericTree *item, 
-                                        OSDListBtnType *list)
+                                        uint level_num)
 {
+    OSDListBtnType *list = GetLevel(level_num);
     if (!list)
     {
-        VERBOSE(VB_IMPORTANT, "OSDListTreeType::FillLevelFromTree() "
-                "called with no list. Ignoring call.");
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "FillLevelFromTree() "
+                "called with no list, ignoring.");
         return;
     }
     list->Reset();
 
     QPtrList<GenericTree> *itemlist = item->getAllChildren();
-
     QPtrListIterator<GenericTree> it(*itemlist);
-    GenericTree *child;
 
-    while ((child = it.current()) != 0)
-    {
-        OSDGenericTree *osdchild = (OSDGenericTree *)child;
+    OSDGenericTree     *child   = (OSDGenericTree*) it.current();
+    OSDListBtnTypeItem *newitem = NULL;
+    for (;(child = (OSDGenericTree*) it.current()); ++it)
+    {
+        OSDTypeImage *im = child->getImage();
+        QString label    = child->getString();
+        QString group    = child->getGroup();
+        bool    canCheck = child->getCheckable() >= 0;
+        bool    hasCheck = child->getCheckable() == 1;
+        bool    hasChild = child->childCount()   >  0;
 
-        OSDListBtnTypeItem *newitem;
-        newitem = new OSDListBtnTypeItem(list, child->getString(),
-                                         osdchild->getImage(), 
-                                         (osdchild->getCheckable() >= 0),
-                                         (child->childCount() > 0));
-        if (osdchild->getCheckable() == 1)
+        newitem = new OSDListBtnTypeItem(list, label, im, canCheck, hasChild);
+
+        if (hasCheck)
             newitem->setChecked(OSDListBtnTypeItem::FullChecked);
-        newitem->setGroup(osdchild->getGroup());
-        newitem->setData(osdchild);
-        osdchild->setParentButton(newitem);
+        newitem->setGroup(group);
+        newitem->setData(child);
 
-        ++it;
+        child->setParentButton(newitem);
     }
 }
 
-OSDListBtnType *OSDListTreeType::GetLevel(int levelnum)
+OSDListBtnType *OSDListTreeType::GetLevel(uint levelnum)
 {
-    if ((uint)levelnum > listLevels.count())
-    {
-        cerr << "OOB GetLevel call\n";
-        return NULL;
-    }
+    if (levelnum < listLevels.size())
+        return listLevels[levelnum];
 
-    return listLevels.at(levelnum);
+    VERBOSE(VB_IMPORTANT, LOC_ERR + "GetLevel("<<levelnum<<") "
+            "listLevels.size() is only "<<listLevels.size());
+    return NULL;
 }
 
-void OSDListTreeType::SetCurrentPosition(void)
+void OSDListTreeType::EnterItem(void)
 {
-    if (!currentlevel)
+    if ((uint)m_levelnum >= listLevels.size())
         return;
 
-    OSDListBtnTypeItem *lbt = currentlevel->GetItemCurrent();
+    listLevels[m_levelnum]->SetActive(true);
+    OSDListBtnTypeItem *lbt = listLevels[m_levelnum]->GetItemCurrent();
+    if (lbt)
+    {
+        currentpos = (OSDGenericTree*) (lbt->getData());
+        emit itemEntered(this, currentpos);
+    }
+}
 
-    if (!lbt)
+void OSDListTreeType::SelectItem(void)
+{
+    if (!currentpos)
         return;
 
-    currentpos = (OSDGenericTree *)(lbt->getData());
-    emit itemEntered(this, currentpos);
+    SetGroupCheckState(currentpos->getGroup(), OSDListBtnTypeItem::NotChecked);
+    currentpos->getParentButton()->setChecked(OSDListBtnTypeItem::FullChecked);
+    emit itemSelected(this, currentpos);
 }
- 
+
+#undef LOC_ERR
+#undef LOC
+
 //////////////////////////////////////////////////////////////////////////
 
 OSDListBtnType::OSDListBtnType(const QString &name, const QRect &area,
                                float wmult, float hmult,
                                bool showScrollArrows)
-              : OSDType(name)
+    : OSDType(name),
+      m_order(0),                       m_rect(area),
+      m_contentsRect(0,0,0,0),          m_arrowsRect(0,0,0,0),
+      m_wmult(wmult),                   m_hmult(hmult),
+      m_itemHeight(0),                  m_itemSpacing(0),
+      m_itemMargin(0),                  m_itemsVisible(0),
+      m_active(false),                  m_showScrollArrows(showScrollArrows),
+      m_showUpArrow(false),             m_showDnArrow(false),
+      m_initialized(false),             m_clearing(false),
+      m_visible(false),
+      m_itemRegBeg(Qt::black),          m_itemRegEnd(QColor(80,80,80)),
+      m_itemSelBeg(QColor(82,202,56)),  m_itemSelEnd(QColor(52,152,56)),
+      m_itemRegAlpha(100),              m_itemSelAlpha(255),
+      m_fontActive(NULL),               m_fontInactive(NULL),
+      m_topIndx(0),                     m_selIndx(0),
+      m_update(true)
 {
-    m_rect             = area;
-
-    m_wmult            = wmult;
-    m_hmult            = hmult;
-
-    m_showScrollArrows = showScrollArrows;
-
-    m_active           = false;
-    m_showUpArrow      = false;
-    m_showDnArrow      = false;
-
-    m_itemList.setAutoDelete(false);
-    m_topItem = 0;
-    m_selItem = 0;
-
-    m_initialized     = false;
-    m_clearing        = false;
-    m_itemSpacing     = 0;
-    m_itemMargin      = 0;
-    m_itemHeight      = 0;
-    m_itemsVisible    = 0;
-    m_fontActive      = 0;
-    m_fontInactive    = 0;
-
-    SetItemRegColor(Qt::black,QColor(80,80,80),100);
-    SetItemSelColor(QColor(82,202,56),QColor(52,152,56),255);
-
-    m_visible = false;
 }
 
 OSDListBtnType::~OSDListBtnType()
@@ -457,316 +370,198 @@ OSDListBtnType::~OSDListBtnType()
     Reset();
 }
 
-void OSDListBtnType::Reinit(float wchange, float hchange, float wmult,
-                            float hmult)
-{
-    m_wmult = wmult;
-    m_hmult = hmult;
-
-    m_itemHeight = (int)(m_itemHeight * hchange);
-    m_itemSpacing = (int)(m_itemSpacing * wchange);
-    m_itemMargin = (int)(m_itemMargin * wchange);
-
-    int width = (int)(m_rect.width() * wchange);
-    int height = (int)(m_rect.height() * hchange);
-    int x = (int)(m_rect.x() * wchange);
-    int y = (int)(m_rect.y() * hchange);
-
-    m_rect = QRect(x, y, width, height);
-
-    Init();
-
-    OSDListBtnTypeItem* item = 0;
-    for (item = m_itemList.first(); item; item = m_itemList.next()) {
-        item->Reinit(wchange, hchange, wmult, hmult);
-    }
-
-}
-
 void OSDListBtnType::SetGroupCheckState(QString group, int newState)
 {
-    OSDListBtnTypeItem* item = 0;
-    for (item = m_itemList.first(); item; item = m_itemList.next()) {
-        if (item->getGroup() == group)
-            item->setChecked((OSDListBtnTypeItem::CheckState)newState);
-    }
-}
-
-void OSDListBtnType::SetItemRegColor(const QColor& beg, const QColor& end, 
-                                     uint alpha)
-{
-    m_itemRegBeg   = beg;
-    m_itemRegEnd   = end;
-    m_itemRegAlpha = alpha;
-}
-
-void OSDListBtnType::SetItemSelColor(const QColor& beg, const QColor& end,
-                                     uint alpha)
-{
-    m_itemSelBeg   = beg;
-    m_itemSelEnd   = end;
-    m_itemSelAlpha = alpha;
-}
-
-void OSDListBtnType::SetFontActive(TTFFont *font)
-{
-    m_fontActive   = font;
-}
-
-void OSDListBtnType::SetFontInactive(TTFFont *font)
-{
-    m_fontInactive = font;
-}
-
-void OSDListBtnType::SetSpacing(int spacing)
-{
-    m_itemSpacing = spacing;    
-}
-
-void OSDListBtnType::SetMargin(int margin)
-{
-    m_itemMargin = margin;    
+    OSDListBtnItemList::iterator it;
+    for (it = m_itemList.begin(); it != m_itemList.end(); ++it)
+        if ((*it)->getGroup() == group)
+            (*it)->setChecked((OSDListBtnTypeItem::CheckState) newState);
 }
 
-void OSDListBtnType::SetActive(bool active)
-{
-    m_active = active;
-}
-
-void OSDListBtnType::Reset()
+void OSDListBtnType::Reset(void)
 {
     QMutexLocker lock(&m_update);
 
     m_clearing = true;
-
-    OSDListBtnTypeItem* item = 0;
-    for (item = m_itemList.first(); item; item = m_itemList.next()) {
-        delete item;
-    }
-
-    m_clearing = false;
+    OSDListBtnItemList::iterator it;
+    OSDListBtnItemList clone = m_itemList;
     m_itemList.clear();
-    
-    m_topItem     = 0;
-    m_selItem     = 0;
+    for (it = clone.begin(); it != clone.end(); ++it)
+        delete (*it);
+    m_clearing = false;
+
+    m_topIndx     = 0;
+    m_selIndx     = 0;
     m_showUpArrow = false;
     m_showDnArrow = false;
 }
 
 void OSDListBtnType::InsertItem(OSDListBtnTypeItem *item)
 {
-    OSDListBtnTypeItem* lastItem = m_itemList.last();
-    m_itemList.append(item);
-
-    if (m_showScrollArrows && m_itemList.count() > m_itemsVisible)
-        m_showDnArrow = true;
-    else
-        m_showDnArrow = false;
-
-    if (!lastItem) 
-    {
-        m_topItem = item;
-        m_selItem = item;
+    QMutexLocker lock(&m_update);
+    m_itemList.push_back(item);
+    m_showDnArrow = m_showScrollArrows && m_itemList.size() > m_itemsVisible;
+    if (m_itemList.size() == 1)
         emit itemSelected(item);
-    }
+}
+
+int find(const OSDListBtnItemList &list, const OSDListBtnTypeItem *item)
+{
+    for (uint i = 0; i < list.size(); i++)
+        if (list[i] == item)
+            return i;
+    return -1;
 }
 
 void OSDListBtnType::RemoveItem(OSDListBtnTypeItem *item)
 {
+    QMutexLocker lock(&m_update);
     if (m_clearing)
         return;
-    
-    if (m_itemList.find(item) == -1)
-        return;
 
-    m_topItem = m_itemList.first();
-    m_selItem = m_itemList.first();
+    int i = find(m_itemList, item);
+    if (i < 0)
+        return;
 
-    m_itemList.remove(item);
+    m_itemList.erase(m_itemList.begin()+i);
 
     m_showUpArrow = false;
-    
-    if (m_showScrollArrows && m_itemList.count() > m_itemsVisible)
-        m_showDnArrow = true;
-    else
-        m_showDnArrow = false;
+    m_showDnArrow = m_itemList.size() > m_itemsVisible;
+    m_selIndx     = 0;
+    m_topIndx     = 0;
 
-    if (m_selItem) {
-        emit itemSelected(m_selItem);
-    }
+    if (m_itemList.size())
+        emit itemSelected(m_itemList[m_selIndx]);
 }
 
-void OSDListBtnType::SetItemCurrent(OSDListBtnTypeItem* item)
+void OSDListBtnType::SetItemCurrent(const OSDListBtnTypeItem* item)
 {
-    bool locked = m_update.tryLock();
+    QMutexLocker lock(&m_update);
+    int i = find(m_itemList, item);
+    if (i >= 0)
+        SetItemCurrent(i);
+}
 
-    if (m_itemList.find(item) == -1)
+void OSDListBtnType::SetItemCurrent(uint current)
+{
+    QMutexLocker lock(&m_update);
+    if (current >= m_itemList.size())
         return;
 
-    m_topItem = item;
-    m_selItem = item;
-
-    if (m_showScrollArrows && m_itemList.count() > m_itemsVisible)
-        m_showDnArrow = true;
-    else
-        m_showDnArrow = false;
-
-    emit itemSelected(m_selItem);
-
-    if (locked)
-        m_update.unlock();
+    m_selIndx     = current;
+    m_topIndx     = max(m_selIndx - (int)m_itemsVisible, 0);
+    m_showUpArrow = m_topIndx;
+    m_showDnArrow = m_topIndx + m_itemsVisible < m_itemList.size();
+    emit itemSelected(m_itemList[m_selIndx]);
 }
 
-void OSDListBtnType::SetItemCurrent(int current)
+int OSDListBtnType::GetItemCurrentPos(void) const
 {
     QMutexLocker lock(&m_update);
-
-    OSDListBtnTypeItem* item = m_itemList.at(current);
-    if (!item)
-        item = m_itemList.first();
-
-    SetItemCurrent(item);
+    return (m_itemList.size()) ? m_selIndx : -1;
 }
 
-OSDListBtnTypeItem* OSDListBtnType::GetItemCurrent()
+OSDListBtnTypeItem* OSDListBtnType::GetItemCurrent(void)
 {
-    return m_selItem;
+    QMutexLocker lock(&m_update);
+    if (!m_itemList.size())
+        return NULL;
+    return m_itemList[m_selIndx];
 }
 
-OSDListBtnTypeItem* OSDListBtnType::GetItemFirst()
+OSDListBtnTypeItem* OSDListBtnType::GetItemFirst(void)
 {
-    return m_itemList.first();    
+    QMutexLocker lock(&m_update);
+    if (!m_itemList.size())
+        return NULL;
+    return m_itemList[0];    
 }
 
-OSDListBtnTypeItem* OSDListBtnType::GetItemNext(OSDListBtnTypeItem *item)
+OSDListBtnTypeItem* OSDListBtnType::GetItemNext(const OSDListBtnTypeItem *item)
 {
     QMutexLocker lock(&m_update);
-
-    if (m_itemList.find(item) == -1)
-        return 0;
-
-    return m_itemList.next();
+    int i = find(m_itemList, item) + 1;
+    if (i <= 0 || i >= (int)m_itemList.size())
+        return NULL;
+    return m_itemList[i];
 }
 
-int OSDListBtnType::GetCount()
+int OSDListBtnType::GetCount(void) const
 {
-    return m_itemList.count();
+    QMutexLocker lock(&m_update);
+    return m_itemList.size();
 }
 
 OSDListBtnTypeItem* OSDListBtnType::GetItemAt(int pos)
 {
-    return m_itemList.at(pos);    
+    QMutexLocker lock(&m_update);
+    return m_itemList[pos];    
 }
 
-int OSDListBtnType::GetItemPos(OSDListBtnTypeItem* item)
+int OSDListBtnType::GetItemPos(const OSDListBtnTypeItem *item) const
 {
     QMutexLocker lock(&m_update);
-
-    return m_itemList.find(item);    
+    return find(m_itemList, item);
 }
 
-void OSDListBtnType::MoveUp()
+void OSDListBtnType::MoveUp(void)
 {
     QMutexLocker lock(&m_update);
-
-    if (m_itemList.find(m_selItem) == -1)
+    if (!m_itemList.size())
         return;
 
-    OSDListBtnTypeItem *item = m_itemList.prev();
-    if (!item)
+    if (--m_selIndx < 0)
     {
-        item = m_itemList.last();
-        if (!item)
-            return;
-
-        if (m_itemList.count() > m_itemsVisible)
-            m_topItem = m_itemList.at(m_itemList.count() - m_itemsVisible);
-        else
-            m_topItem = m_itemList.first();
+        m_selIndx = m_itemList.size() - 1;
+        m_topIndx = (m_itemList.size() > m_itemsVisible) ?
+            m_itemList.size() - m_itemsVisible : 0;
     }
 
-    m_selItem = item;
-
-    if (m_itemList.find(m_selItem) < m_itemList.find(m_topItem))
-        m_topItem = m_selItem;
-
-    if (m_topItem != m_itemList.first())
-        m_showUpArrow = true;
-    else
-        m_showUpArrow = false;
-
-    if (m_itemList.find(m_topItem) + m_itemsVisible < m_itemList.count())
-        m_showDnArrow = true;
-    else
-        m_showDnArrow = false;
+    m_topIndx     = (m_selIndx < m_topIndx) ? m_selIndx : m_topIndx;
+    m_showUpArrow = m_topIndx;
+    m_showDnArrow = m_topIndx + m_itemsVisible < m_itemList.size();
 
-    emit itemSelected(m_selItem);
+    emit itemSelected(m_itemList[m_selIndx]);
 }
 
-void OSDListBtnType::MoveDown()
+void OSDListBtnType::MoveDown(void)
 {
     QMutexLocker lock(&m_update);
-
-    if (m_itemList.find(m_selItem) == -1)
+    if (!m_itemList.size())
         return;
 
-    OSDListBtnTypeItem *item = m_itemList.next();
-    if (!item)
-    {
-        item = m_itemList.first();
-        if (!item)
-            return;
-
-        m_topItem = item;
-    }
-
-    m_selItem = item;
+    if (++m_selIndx >= (int)m_itemList.size())
+        m_selIndx = m_topIndx = 0;
 
-    if (m_itemList.find(m_topItem) + m_itemsVisible <=
-        (unsigned int)m_itemList.find(m_selItem)) 
-    {
-        m_topItem = m_itemList.at(m_itemList.find(m_topItem) + 1);
-    }
-    
-    if (m_topItem != m_itemList.first())
-        m_showUpArrow = true;
-    else
-        m_showUpArrow = false;
-
-    if (m_itemList.find(m_topItem) + m_itemsVisible < m_itemList.count())
-        m_showDnArrow = true;
-    else
-        m_showDnArrow = false;
+    bool scroll_down = m_topIndx + (int)m_itemsVisible <= m_selIndx;
+    m_topIndx = (scroll_down) ? m_topIndx + 1 : m_topIndx;
+        
+    m_showUpArrow = m_topIndx;
+    m_showDnArrow = m_topIndx + m_itemsVisible < m_itemList.size();
     
-    emit itemSelected(m_selItem);
+    emit itemSelected(m_itemList[m_selIndx]);
 }
 
-void OSDListBtnType::Draw(OSDSurface *surface, int fade, int maxfade, int xoff,
-                          int yoff)
+void OSDListBtnType::Draw(OSDSurface *surface,
+                          int fade, int maxfade,
+                          int xoff, int yoff)
 {
-    (void)xoff;
-    (void)yoff;
-
+    QMutexLocker lock(&m_update);
     if (!m_visible)
         return;
-
-    QMutexLocker lock(&m_update);
-
     if (!m_initialized)
         Init();
 
     TTFFont *font = m_active ? m_fontActive : m_fontInactive;
     
     int y = m_rect.y();
-    m_itemList.find(m_topItem);
-    OSDListBtnTypeItem *it = m_itemList.current();
-    while (it && (y - m_rect.y()) <= (m_contentsRect.height() - m_itemHeight)) 
+    for (uint i = m_topIndx; i < m_itemList.size(); i++)
     {
-        it->paint(surface, font, fade, maxfade, m_rect.x()+ xoff, y + yoff);
-
+        if (!((y - m_rect.y()) <= (m_contentsRect.height() - m_itemHeight)))
+            break;
+        m_itemList[i]->paint(surface, font, fade, maxfade,
+                             m_rect.x() + xoff, y + yoff);
         y += m_itemHeight + m_itemSpacing;
-
-        it = m_itemList.next();
     }
 
     if (m_showScrollArrows) 
@@ -792,13 +587,12 @@ void OSDListBtnType::Draw(OSDSurface *su
     }
 }
 
-void OSDListBtnType::Init()
+void OSDListBtnType::Init(void)
 {
     int sz1 = m_fontActive->Size() * 3 / 2;
     int sz2 = m_fontInactive->Size() * 3 / 2;
-    m_itemHeight = QMAX(sz1, sz2) + (int)(2 * m_itemMargin);
-
-    m_itemHeight = (m_itemHeight / 2) * 2;
+    m_itemHeight = max(sz1, sz2) + (int)(2 * m_itemMargin);
+    m_itemHeight = m_itemHeight & ~0x1;
 
     if (m_showScrollArrows) 
     {
@@ -838,11 +632,7 @@ void OSDListBtnType::Init()
     InitItem(m_itemSelActPix,   itemWidth,    m_itemHeight,
              m_itemSelBeg,      m_itemSelEnd, 255);
 
-    if (m_itemList.count() > m_itemsVisible && m_showScrollArrows)
-        m_showDnArrow = true;
-    else
-        m_showDnArrow = false;
-
+    m_showDnArrow = m_itemList.size() > m_itemsVisible && m_showScrollArrows;
     m_initialized = true;
 }
 
@@ -885,68 +675,57 @@ void OSDListBtnType::InitItem(
 
 void OSDListBtnType::LoadPixmap(OSDTypeImage& pix, const QString& fileName)
 {
-    QString file = gContext->GetThemesParentDir() + "default/lb-" + fileName + ".png";
-    pix.LoadImage(file, m_wmult, m_hmult);
+    QString path = gContext->GetThemesParentDir() + "default/lb-";
+    pix.LoadImage(path + fileName + ".png", m_wmult, m_hmult);
 }
 
 /////////////////////////////////////////////////////////////////////////////
-OSDListBtnTypeItem::OSDListBtnTypeItem(OSDListBtnType* lbtype, 
-                                       const QString& text,
-                                       OSDTypeImage *pixmap, bool checkable,
-                                       bool showArrow, CheckState state)
-{
-    m_parent    = lbtype;
-    m_text      = text;
-    m_pixmap    = pixmap;
-    m_checkable = checkable;
-    m_state     = state;
-    m_showArrow = showArrow;
-    m_data      = 0;
-
+OSDListBtnTypeItem::OSDListBtnTypeItem(
+    OSDListBtnType *lbtype,     const QString  &text,
+    OSDTypeImage   *pixmap,     bool            checkable,
+    bool            showArrow,  CheckState      state)
+    : m_parent(lbtype),       m_pixmap(pixmap),
+      m_data(NULL),           m_text(text),
+      m_group(QString::null), m_state(state),
+      m_showArrow(showArrow), m_checkable(checkable),
+      m_checkRect(0,0,0,0),   m_arrowRect(0,0,0,0),
+      m_pixmapRect(0,0,0,0),  m_textRect(0,0,0,0)
+{
     if (!m_parent->m_initialized)
         m_parent->Init();
 
-    int  margin    = m_parent->m_itemMargin;
-    int  width     = m_parent->m_rect.width();
-    int  height    = m_parent->m_itemHeight;
+    OSDTypeImage &checkPix = m_parent->m_checkNonePix;
+    OSDTypeImage &arrowPix = m_parent->m_arrowPix;
+
+    int margin = m_parent->m_itemMargin;
+    int width  = m_parent->m_rect.width();
+    int height = m_parent->m_itemHeight;
+    int cw     = checkPix.ImageSize().width();
+    int ch     = checkPix.ImageSize().height();
+    int aw     = arrowPix.ImageSize().width();
+    int ah     = arrowPix.ImageSize().height();
+    int pw     = m_pixmap ? m_pixmap->ImageSize().width() : 0;
+    int ph     = m_pixmap ? m_pixmap->ImageSize().height() : 0;
 
-    OSDTypeImage& checkPix = m_parent->m_checkNonePix;
-    OSDTypeImage& arrowPix = m_parent->m_arrowPix;
-    
-    int cw = checkPix.ImageSize().width();
-    int ch = checkPix.ImageSize().height();
-    int aw = arrowPix.ImageSize().width();
-    int ah = arrowPix.ImageSize().height();
-    int pw = m_pixmap ? m_pixmap->ImageSize().width() : 0;
-    int ph = m_pixmap ? m_pixmap->ImageSize().height() : 0;
-    
     if (m_checkable) 
-        m_checkRect = QRect(margin, (height - ch)/2, cw, ch);
-    else
-        m_checkRect = QRect(0,0,0,0);
+        m_checkRect  = QRect(margin, (height - ch)/2, cw, ch);
 
     if (m_showArrow) 
-        m_arrowRect = QRect(width - aw - margin, (height - ah)/2,
-                            aw, ah);
-    else
-        m_arrowRect = QRect(0,0,0,0);
+        m_arrowRect  = QRect(width - aw - margin, (height - ah)/2, aw, ah);
 
-    if (m_pixmap) 
-        m_pixmapRect = QRect(m_checkable ? (2*margin + m_checkRect.width()) :
-                             margin, (height - ph)/2,
-                             pw, ph);
-    else
-        m_pixmapRect = QRect(0,0,0,0);
+    if (m_pixmap)
+    {
+        int tmp = (m_checkable) ? (2 * margin + m_checkRect.width()) : margin;
+        m_pixmapRect = QRect(tmp, (height - ph)/2, pw, ph);
+    }
 
-    m_textRect = QRect(margin +
-                       (m_checkable ? m_checkRect.width() + margin : 0) +
-                       (m_pixmap    ? m_pixmapRect.width() + margin : 0),
-                       0,
-                       width - 2*margin -
-                       (m_checkable ? m_checkRect.width() + margin : 0) -
-                       (m_showArrow ? m_arrowRect.width() + margin : 0) -
-                       (m_pixmap ? m_pixmapRect.width() + margin : 0),
-                       height);
+    int tx = margin, tw = width - (2 * margin);
+    tx += (m_checkable) ? m_checkRect.width()  + margin : 0;
+    tx += (m_pixmap)    ? m_pixmapRect.width() + margin : 0;
+    tw -= (m_checkable) ? m_checkRect.width()  + margin : 0;
+    tw -= (m_showArrow) ? m_arrowRect.width()  + margin : 0;
+    tw -= (m_pixmap)    ? m_pixmapRect.width() + margin : 0;
+    m_textRect = QRect(tx, 0, tw, height);
 
     m_parent->InsertItem(this);
 }
@@ -957,52 +736,10 @@ OSDListBtnTypeItem::~OSDListBtnTypeItem(
         m_parent->RemoveItem(this);
 }
 
-QString OSDListBtnTypeItem::text() const
-{
-    return m_text;
-}
-
-const OSDTypeImage* OSDListBtnTypeItem::pixmap() const
-{
-    return m_pixmap;
-}
-
-bool OSDListBtnTypeItem::checkable() const
-{
-    return m_checkable;
-}
-
-OSDListBtnTypeItem::CheckState OSDListBtnTypeItem::state() const
-{
-    return m_state;
-}
-
-OSDListBtnType* OSDListBtnTypeItem::parent() const
-{
-    return m_parent;
-}
-
-void OSDListBtnTypeItem::setChecked(CheckState state)
-{
-    if (!m_checkable)
-        return;
-    m_state = state;
-}
-
-void OSDListBtnTypeItem::setData(void *data)
-{
-    m_data = data;    
-}
-
-void* OSDListBtnTypeItem::getData()
-{
-    return m_data;
-}
-
 void OSDListBtnTypeItem::paint(OSDSurface *surface, TTFFont *font, 
                                int fade, int maxfade, int x, int y)
 {
-    if (this == m_parent->m_selItem)
+    if (this == m_parent->GetItemCurrent())
     {
         if (m_parent->m_active)
             m_parent->m_itemSelActPix.Draw(surface, fade, maxfade, x, y);
@@ -1030,11 +767,14 @@ void OSDListBtnTypeItem::paint(OSDSurfac
         cr.moveBy(x, y);
         
         if (m_state == HalfChecked)
-            m_parent->m_checkHalfPix.Draw(surface, fade, maxfade, cr.x(), cr.y());
+            m_parent->m_checkHalfPix.Draw(surface, fade, maxfade,
+                                          cr.x(), cr.y());
         else if (m_state == FullChecked)
-            m_parent->m_checkFullPix.Draw(surface, fade, maxfade, cr.x(), cr.y());
+            m_parent->m_checkFullPix.Draw(surface, fade, maxfade,
+                                          cr.x(), cr.y());
         else
-            m_parent->m_checkNonePix.Draw(surface, fade, maxfade, cr.x(), cr.y());
+            m_parent->m_checkNonePix.Draw(surface, fade, maxfade,
+                                          cr.x(), cr.y());
     }
 
     if (m_pixmap)
@@ -1049,39 +789,3 @@ void OSDListBtnTypeItem::paint(OSDSurfac
     tr.moveBy(0, font->Size() / 4);
     font->DrawString(surface, tr.x(), tr.y(), m_text, tr.right(), tr.bottom());
 }
-
-void OSDListBtnTypeItem::Reinit(float wchange, float hchange, 
-                                float wmult, float hmult)
-{
-    (void)wmult;
-    (void)hmult;
-
-    int width = (int)(m_checkRect.width() * wchange);
-    int height = (int)(m_checkRect.height() * hchange);
-    int x = (int)(m_checkRect.x() * wchange);
-    int y = (int)(m_checkRect.y() * hchange);
-
-    m_checkRect = QRect(x, y, width, height);
-
-    width = (int)(m_pixmapRect.width() * wchange);
-    height = (int)(m_pixmapRect.height() * hchange);
-    x = (int)(m_pixmapRect.x() * wchange);
-    y = (int)(m_pixmapRect.y() * hchange);
-
-    m_pixmapRect = QRect(x, y, width, height);
-
-    width = (int)(m_textRect.width() * wchange);
-    height = (int)(m_textRect.height() * hchange);
-    x = (int)(m_textRect.x() * wchange);
-    y = (int)(m_textRect.y() * hchange);
-
-    m_textRect = QRect(x, y, width, height);
-
-    width = (int)(m_arrowRect.width() * wchange);
-    height = (int)(m_arrowRect.height() * hchange);
-    x = (int)(m_arrowRect.x() * wchange);
-    y = (int)(m_arrowRect.y() * hchange);
-
-    m_arrowRect = QRect(x, y, width, height);
-}
-
diff -pruN mythtv-0.19/libs/libmythtv/osdlistbtntype.h mythtv/libs/libmythtv/osdlistbtntype.h
--- mythtv-0.19/libs/libmythtv/osdlistbtntype.h	2005-12-05 11:39:09.000000000 +1000
+++ mythtv/libs/libmythtv/osdlistbtntype.h	2006-02-19 07:26:06.000000000 +1000
@@ -1,3 +1,4 @@
+// -*- Mode: c++ -*-
 /* ============================================================
  * File  : uilistbtntype.h
  * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
@@ -22,38 +23,57 @@
 #ifndef OSDLISTBTNTYPE_H
 #define OSDLISTBTNTYPE_H
 
-#include "osdtypes.h"
-#include "ttfont.h"
+#include <vector>
+using namespace std;
+
+// Qt headers
 #include <qcolor.h>
 #include <qptrlist.h>
 #include <qevent.h>
 #include <qmutex.h>
+#include <qptrvector.h>
+
+// MythTV headers
+#include "osdtypes.h"
+#include "ttfont.h"
 #include "generictree.h"
 
-class OSDListBtnTypeItem;
 class OSDListBtnType;
+class OSDListBtnTypeItem;
+typedef vector<OSDListBtnType*> OSDListBtnList;
+typedef vector<OSDListBtnTypeItem*> OSDListBtnItemList;
 
 class OSDGenericTree : public GenericTree
 {
   public:
     // This class will _not_ delete the image it's given, if any.
-    OSDGenericTree(OSDGenericTree *parent, const QString &name, 
-                   const QString &action = "", int check = -1, 
-                   OSDTypeImage *image = NULL, QString group = "");
-
-    OSDTypeImage *getImage(void) { return m_image; }
-    QString getAction(void) { return m_action; }
-    int getCheckable(void) { return m_checkable; }
-    QString getGroup(void) { return m_group; }
+    OSDGenericTree(OSDGenericTree *parent,        const QString &name, 
+                   const QString  &action = "",   int            check = -1, 
+                   OSDTypeImage   *image  = NULL, QString        group = "") :
+        GenericTree(name), m_image(image),     m_action(action),
+        m_group(group),    m_checkable(check), m_parentButton(NULL)
+    {
+        m_group = (m_group.isEmpty()) ? action : m_group;
+        setSelectable(!action.isEmpty());
+        if (parent)
+            parent->addNode(this);
+    }
+
+    QString getAction(void)    const { return m_action;    }
+    QString getGroup(void)     const { return m_group;     }
+    int     getCheckable(void) const { return m_checkable; }
+
+    OSDTypeImage       *getImage(void)        { return m_image;        }
+    OSDListBtnTypeItem *getParentButton(void) { return m_parentButton; }
+
     void setParentButton(OSDListBtnTypeItem *button)
-                         { m_parentButton = button; };
-    OSDListBtnTypeItem *getParentButton(void) { return m_parentButton; };
+        { m_parentButton = button; }
 
   private:
-    OSDTypeImage *m_image;
-    QString m_action;
-    int m_checkable;
-    QString m_group;
+    OSDTypeImage       *m_image;
+    QString             m_action;
+    QString             m_group;
+    int                 m_checkable;
     OSDListBtnTypeItem *m_parentButton;
 };
 
@@ -62,52 +82,48 @@ class OSDListTreeType : public OSDType
 {
     Q_OBJECT
   public:
-    OSDListTreeType(const QString &name, const QRect &area, 
-                    const QRect &levelsize, int levelspacing,
-                    float wmult, float hmult);
+    OSDListTreeType(const QString &name,      const QRect &area,
+                    const QRect   &levelsize, int          levelspacing,
+                    float          wmult,     float        hmult);
+    ~OSDListTreeType();
 
-    void Reinit(float wchange, float hchange, float wmult, float hmult);
-    void SetGroupCheckState(QString group, int newState = 0);
-
-    void SetFontActive(TTFFont *font);
-    void SetFontInactive(TTFFont *font);
-    void SetSpacing(int spacing);
-    void SetMargin(int margin);
-    void SetItemRegColor(const QColor& beg, const QColor& end, uint alpha);
-    void SetItemSelColor(const QColor& beg, const QColor& end, uint alpha);
+    bool IsVisible(void)          const { return m_visible;  }
+ 
+    void SetFontActive(TTFFont *font)   { m_active   = font; }
+    void SetFontInactive(TTFFont *font) { m_inactive = font; }
 
-    void SetAsTree(OSDGenericTree *toplevel);
+    void SetGroupCheckState(QString group, int newState = 0);
+    void SetSpacing(uint spacing)
+        { m_unbiasedspacing = (m_spacing = spacing) / m_wmult; }
+    void SetMargin(uint margin)
+        { m_unbiasedmargin  = (m_margin  = margin)  / m_wmult; }
+    void SetItemRegColor(const QColor& beg, const QColor& end, uint alpha)
+        { m_itemRegBeg = beg; m_itemRegEnd = end; m_itemRegAlpha = alpha; }
+    void SetItemSelColor(const QColor& beg, const QColor& end, uint alpha)
+        { m_itemSelBeg = beg; m_itemSelEnd = end; m_itemSelAlpha = alpha; }
+    void SetVisible(bool visible) { m_visible = visible; }
+    void SetAsTree(OSDGenericTree *toplevel, vector<uint> *select = NULL);
 
-    OSDGenericTree *GetCurrentPosition(void);
- 
+    void Reinit(float wmult, float hmult);
     bool HandleKeypress(QKeyEvent *e);
-
     void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
 
-    bool IsVisible(void) { return m_visible; }
-    void SetVisible(bool visible) { m_visible = visible; }
-
   signals:
     void itemSelected(OSDListTreeType *parent, OSDGenericTree *item);
     void itemEntered(OSDListTreeType *parent, OSDGenericTree *item);
 
   private:
-    void FillLevelFromTree(OSDGenericTree *item, OSDListBtnType *list);
-    OSDListBtnType *GetLevel(int levelnum);
-    void SetCurrentPosition(void);
-
-    int levels;
-    int curlevel;
+    void FillLevelFromTree(OSDGenericTree *item, uint levelnum);
+    OSDListBtnType *GetLevel(uint levelnum);
+    void EnterItem(void);
+    void SelectItem(void);
 
     OSDGenericTree *treetop;
     OSDGenericTree *currentpos;
+    TTFFont        *m_active;
+    TTFFont        *m_inactive;
 
-    QPtrList<OSDListBtnType> listLevels;
-
-    OSDListBtnType *currentlevel;
-
-    TTFFont *m_active;
-    TTFFont *m_inactive;
+    OSDListBtnList  listLevels;
 
     QColor    m_itemRegBeg;
     QColor    m_itemRegEnd;
@@ -116,62 +132,76 @@ class OSDListTreeType : public OSDType
     uint      m_itemRegAlpha;
     uint      m_itemSelAlpha;
    
-    int m_spacing;
-    int m_margin;
-
-    QRect m_totalarea;
-    QRect m_levelsize;
-    int m_levelspacing;
+    uint      m_spacing;
+    uint      m_margin;
+    int       m_levelspacing;
+
+    QRect     m_totalarea;
+    QRect     m_levelsize;
+
+    float     m_unbiasedspacing;
+    float     m_unbiasedmargin;
+    QRect     m_unbiasedarea;
+    QRect     m_unbiasedsize;
 
-    float m_wmult;
-    float m_hmult;
+    float     m_wmult;
+    float     m_hmult;
 
-    bool m_visible;
-    bool m_arrowAccel;
+    int       m_depth;
+    int       m_levelnum;
+    bool      m_visible;
+    bool      m_arrowAccel;
 };
  
 class OSDListBtnType : public OSDType
 {
+    friend class OSDListBtnTypeItem;
     Q_OBJECT
+
   public:
     OSDListBtnType(const QString &name, const QRect& area,
                    float wmult, float hmult,
                    bool showScrollArrows = false);
     ~OSDListBtnType();
 
-    void  Reinit(float wchange, float hchange, float wmult, float hmult);
-    void  SetGroupCheckState(QString group, int newState = 0);
+    // General Gets
+    bool  IsVisible() const { return m_visible; }
 
-    void  SetFontActive(TTFFont *font);
-    void  SetFontInactive(TTFFont *font);
-    void  SetSpacing(int spacing);
-    void  SetMargin(int margin);
-    void  SetItemRegColor(const QColor& beg, const QColor& end, uint alpha);
-    void  SetItemSelColor(const QColor& beg, const QColor& end, uint alpha);
-    
-    void  Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
-
-    void  SetActive(bool active);
-    void  Reset();
+    // General Sets
+    void  SetFontActive(TTFFont *font)   { m_fontActive   = font;    }
+    void  SetFontInactive(TTFFont *font) { m_fontInactive = font;    }
+    void  SetSpacing(int spacing)        { m_itemSpacing  = spacing; }
+    void  SetMargin(int margin)          { m_itemMargin   = margin;  }
+    void  SetActive(bool active)         { m_active       = active;  }
+    void  SetVisible(bool vis)           { m_visible = vis; }
+    void  SetItemRegColor(const QColor& beg, const QColor& end, uint alpha)
+        { m_itemRegBeg = beg; m_itemRegEnd = end; m_itemRegAlpha = alpha; }
+    void  SetItemSelColor(const QColor& beg, const QColor& end, uint alpha)
+        { m_itemSelBeg = beg; m_itemSelEnd = end; m_itemSelAlpha = alpha; }
+    void  SetGroupCheckState(QString group, int newState = 0);
+    void  SetItemCurrent(const OSDListBtnTypeItem* item);
+    void  SetItemCurrent(uint pos);
 
-    void  SetItemCurrent(OSDListBtnTypeItem* item);
-    void  SetItemCurrent(int pos);
-    OSDListBtnTypeItem* GetItemCurrent();
-    OSDListBtnTypeItem* GetItemFirst();
-    OSDListBtnTypeItem* GetItemNext(OSDListBtnTypeItem *item);
+    // Item Gets
+    int   GetCount(void) const;
+    int   GetItemPos(const OSDListBtnTypeItem* item) const;
+    int   GetItemCurrentPos() const;
+    OSDListBtnTypeItem* GetItemCurrent(void);
+    OSDListBtnTypeItem* GetItemFirst(void);
+    OSDListBtnTypeItem* GetItemNext(const OSDListBtnTypeItem *item);
     OSDListBtnTypeItem* GetItemAt(int pos);
-    int   GetItemPos(OSDListBtnTypeItem* item);
-    int   GetCount();
 
-    void  MoveDown();
-    void  MoveUp();
+    // Item Sets/Commands
+    void  MoveDown(void);
+    void  MoveUp(void);
 
-    bool  IsVisible() { return m_visible; }
-    void  SetVisible(bool vis) { m_visible = vis; }
+    // General Commands
+    void  Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
+    void  Reinit(float,float) {}
+    void  Reset(void);
 
   private:
-
-    void  Init();
+    void  Init(void);
     void  InitItem(OSDTypeImage &osdImg, uint width, uint height,
                    QColor beg, QColor end, int alpha);
     void  LoadPixmap(OSDTypeImage& pix, const QString& fileName);
@@ -179,23 +209,34 @@ class OSDListBtnType : public OSDType
     void  InsertItem(OSDListBtnTypeItem *item);
     void  RemoveItem(OSDListBtnTypeItem *item);
 
-    int   m_order;
-    QRect m_rect;
-    QRect m_contentsRect;
-    QRect m_arrowsRect;
-
-    float m_wmult;
-    float m_hmult;
-
-    int   m_itemHeight;
-    int   m_itemSpacing;
-    int   m_itemMargin;
-    uint  m_itemsVisible;
-
-    bool  m_active;
-    bool  m_showScrollArrows;
-    bool  m_showUpArrow;
-    bool  m_showDnArrow;
+  private:
+    int            m_order;
+    QRect          m_rect;
+    QRect          m_contentsRect;
+    QRect          m_arrowsRect;
+
+    float          m_wmult;
+    float          m_hmult;
+
+    int            m_itemHeight;
+    int            m_itemSpacing;
+    int            m_itemMargin;
+    uint           m_itemsVisible;
+
+    bool           m_active;
+    bool           m_showScrollArrows;
+    bool           m_showUpArrow;
+    bool           m_showDnArrow;
+    bool           m_initialized;
+    bool           m_clearing;
+    bool           m_visible;
+
+    QColor         m_itemRegBeg;
+    QColor         m_itemRegEnd;
+    QColor         m_itemSelBeg;
+    QColor         m_itemSelEnd;
+    uint           m_itemRegAlpha;
+    uint           m_itemSelAlpha;
 
     OSDTypeImage   m_itemRegPix;
     OSDTypeImage   m_itemSelActPix;
@@ -209,43 +250,30 @@ class OSDListBtnType : public OSDType
     OSDTypeImage   m_checkHalfPix;
     OSDTypeImage   m_checkFullPix;
 
-    QColor    m_itemRegBeg;
-    QColor    m_itemRegEnd;
-    QColor    m_itemSelBeg;
-    QColor    m_itemSelEnd;
-    uint      m_itemRegAlpha;
-    uint      m_itemSelAlpha;
-
-    TTFFont* m_fontActive;
-    TTFFont* m_fontInactive;
-
-    bool      m_initialized;
-    bool      m_clearing;
+    TTFFont       *m_fontActive;
+    TTFFont       *m_fontInactive;
 
-    OSDListBtnTypeItem* m_topItem;
-    OSDListBtnTypeItem* m_selItem;
-    QPtrList<OSDListBtnTypeItem> m_itemList;
+    int            m_topIndx;
+    int            m_selIndx;
 
-    QMutex    m_update;
+    OSDListBtnItemList m_itemList;
 
-    bool      m_visible;
+    mutable QMutex m_update;
 
-    friend class OSDListBtnTypeItem;
-    
   signals:
-
     void itemSelected(OSDListBtnTypeItem* item);
 };
 
 class OSDListBtnTypeItem
 {
+    friend class OSDListBtnType;
 
   public:
-
-    enum CheckState {
-        NotChecked=0,
+    enum CheckState
+    {
+        NotChecked  = 0,
         HalfChecked,
-        FullChecked
+        FullChecked,
     };
 
     OSDListBtnTypeItem(OSDListBtnType* lbtype, const QString& text,
@@ -253,41 +281,36 @@ class OSDListBtnTypeItem
                        bool showArrow = false, CheckState state = NotChecked);
     ~OSDListBtnTypeItem();
 
-    OSDListBtnType*   parent() const;
-    QString           text() const;
-    const OSDTypeImage*   pixmap() const;
-    bool              checkable() const;
-    CheckState        state() const;
-
-    void  setChecked(CheckState state);
-    void  setData(void *data);
-    void* getData();
-    void  setGroup(QString group) { m_group = group; };
-    QString getGroup(void) { return m_group; }
+    OSDListBtnType*     parent(void)    const { return m_parent;    }
+    QString             text(void)      const { return m_text;      }
+    const OSDTypeImage* pixmap(void)    const { return m_pixmap;    }
+    bool                checkable(void) const { return m_checkable; }
+    CheckState          state(void)     const { return m_state;     }
+    QString             getGroup(void)  const { return m_group;     }
+    void               *getData(void)         { return m_data;      }
+
+    void setData(void *data)          { m_data = data; }
+    void setGroup(QString grp)        { m_group = grp; }
+    void setChecked(CheckState state)
+        { m_state = (m_checkable) ? state : m_state; }
 
-    void  Reinit(float wchange, float hchange, float wmult, float hmult);
-    
+    void  Reinit(float,float) {}
     void  paint(OSDSurface *surface, TTFFont *font, int fade, int maxfade, 
                 int x, int y);
     
   protected:
-
     OSDListBtnType *m_parent;
-    QString        m_text;
-    OSDTypeImage  *m_pixmap;
-    bool           m_checkable;
-    CheckState     m_state;
-    void          *m_data;
-    QString        m_group;
-
-    QRect          m_checkRect;
-    QRect          m_pixmapRect;
-    QRect          m_textRect;
-    QRect          m_arrowRect;
-
-    bool           m_showArrow;    
-
-    friend class OSDListBtnType;
+    OSDTypeImage   *m_pixmap;
+    void           *m_data;
+    QString         m_text;
+    QString         m_group;
+    CheckState      m_state;
+    bool            m_showArrow;
+    bool            m_checkable;
+    QRect           m_checkRect;
+    QRect           m_arrowRect;
+    QRect           m_pixmapRect;
+    QRect           m_textRect;
 };
 
 
diff -pruN mythtv-0.19/libs/libmythtv/osdtypes.cpp mythtv/libs/libmythtv/osdtypes.cpp
--- mythtv-0.19/libs/libmythtv/osdtypes.cpp	2005-12-05 16:40:28.000000000 +1000
+++ mythtv/libs/libmythtv/osdtypes.cpp	2006-05-14 01:45:17.000000000 +1000
@@ -14,6 +14,9 @@ using namespace std;
 
 #include "mythcontext.h"
 
+/// Shared OSD image cache
+OSDImageCache OSDTypeImage::c_cache;
+
 OSDSet::OSDSet(const QString &name, bool cache, int screenwidth, 
                int screenheight, float wmult, float hmult, int frint)
       : QObject()
@@ -160,9 +163,6 @@ void OSDSet::Reinit(int screenwidth, int
                     int displaywidth, int displayheight, 
                     float wmult, float hmult, int frint)
 {
-    float wchange = wmult / m_wmult;
-    float hchange = hmult / m_hmult;
-
     m_frameint = frint;
 
     m_screenwidth = screenwidth;
@@ -175,57 +175,12 @@ void OSDSet::Reinit(int screenwidth, int
     vector<OSDType *>::iterator iter = allTypes->begin();
     for (;iter != allTypes->end(); iter++)
     {
-        OSDType *type = (*iter);
-        if (OSDTypeText *item = dynamic_cast<OSDTypeText*>(type))
-        {
-            item->Reinit(wchange, hchange);
-        }
-        else if (OSDTypePositionImage *item =
-                 dynamic_cast<OSDTypePositionImage*>(type))
-        {
-            item->Reinit(wchange, hchange, wmult, hmult);
-        }
-        else if (OSDTypePosSlider *item = dynamic_cast<OSDTypePosSlider*>(type))
-        {
-            item->Reinit(wchange, hchange, wmult, hmult);
-        }
-        else if (OSDTypeFillSlider *item = 
-                 dynamic_cast<OSDTypeFillSlider*>(type))
-        {
-            item->Reinit(wchange, hchange, wmult, hmult);
-        }
-        else if (OSDTypeEditSlider *item =
-                 dynamic_cast<OSDTypeEditSlider*>(type))
-        {
-            item->Reinit(wchange, hchange, wmult, hmult);
-        }
-        else if (OSDTypeImage *item = dynamic_cast<OSDTypeImage*>(type))
-        {
-            item->Reinit(wchange, hchange, wmult, hmult);
-        }
-        else if (OSDTypeBox *item = dynamic_cast<OSDTypeBox*>(type))
-        {
-            item->Reinit(wchange, hchange);
-        }
-        else if (OSDTypePositionRectangle *item =
-                  dynamic_cast<OSDTypePositionRectangle*>(type))
-        {
-            item->Reinit(wchange, hchange);
-        }
-        else if (OSDTypeCC *item = dynamic_cast<OSDTypeCC*>(type))
-        {
-            item->Reinit(xoff, yoff, displaywidth, displayheight);
-        }
-        else if (OSDListTreeType *item = dynamic_cast<OSDListTreeType*>(type))
-        {
-            item->Reinit(wchange, hchange, wmult, hmult);
-        }
+        if (OSDTypeCC *cc608 = dynamic_cast<OSDTypeCC*>(*iter))
+            cc608->Reinit(xoff, yoff, displaywidth, displayheight,
+                          wmult, hmult);
         else
-        {
-            cerr << "Unknown conversion\n";
-        }
+            (*iter)->Reinit(wmult, hmult);
     }
-
 }
 
 OSDType *OSDSet::GetType(const QString &name)
@@ -443,7 +398,8 @@ OSDType::~OSDType()
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 OSDTypeText::OSDTypeText(const QString &name, TTFFont *font, 
-                         const QString &text, QRect displayrect)
+                         const QString &text, QRect displayrect,
+                         float wmult, float hmult)
            : OSDType(name)
 {
     m_message = text;
@@ -464,6 +420,12 @@ OSDTypeText::OSDTypeText(const QString &
     m_scrollinit = false;
 
     m_linespacing = 1.5;
+
+    m_unbiasedsize =
+        QRect((int)round(m_screensize.x()      / wmult),
+              (int)round(m_screensize.y()      / hmult),
+              (int)ceil( m_screensize.width()  / wmult),
+              (int)ceil( m_screensize.height() / hmult));
 }
 
 OSDTypeText::OSDTypeText(const OSDTypeText &other)
@@ -507,14 +469,13 @@ void OSDTypeText::SetDefaultText(const Q
     m_scrollinit = false;
 }
 
-void OSDTypeText::Reinit(float wchange, float hchange)
+void OSDTypeText::Reinit(float wmult, float hmult)
 {
-    int width = (int)(m_screensize.width() * wchange);
-    int height = (int)(m_screensize.height() * hchange);
-    int x = (int)(m_screensize.x() * wchange);
-    int y = (int)(m_screensize.y() * hchange);
-
-    m_displaysize = m_screensize = QRect(x, y, width, height);
+    m_displaysize = m_screensize =
+        QRect((int)round(m_unbiasedsize.x()      * wmult),
+              (int)round(m_unbiasedsize.y()      * hmult),
+              (int)ceil( m_unbiasedsize.width()  * wmult),
+              (int)ceil( m_unbiasedsize.height() * hmult));
 }
 
 void OSDTypeText::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, 
@@ -708,7 +669,7 @@ OSDTypeImage::OSDTypeImage(const QString
     m_onlyusefirst = false;
 
     m_filename = filename;
-    m_displaypos = displaypos;
+    SetPosition(displaypos, wmult, hmult);
 
     m_yuv = m_alpha = NULL;
     m_isvalid = false;
@@ -716,6 +677,7 @@ OSDTypeImage::OSDTypeImage(const QString
 
     m_scalew = scalew;
     m_scaleh = scaleh;
+    m_cacheitem = NULL;
 
     LoadImage(filename, wmult, hmult, scalew, scaleh);
 }
@@ -733,6 +695,7 @@ OSDTypeImage::OSDTypeImage(const OSDType
     m_name = other.m_name;
     m_scalew = other.m_scalew;
     m_scaleh = other.m_scaleh;
+    m_cacheitem = NULL;
 
     m_alpha = m_yuv = NULL;
     if (m_isvalid)
@@ -760,6 +723,8 @@ OSDTypeImage::OSDTypeImage(const QString
     m_onlyusefirst = false;
 
     m_displaypos = QPoint(0, 0);
+    m_unbiasedpos = QPoint(0, 0);
+    m_cacheitem = NULL;
 
     m_yuv = NULL;
     m_alpha = NULL;
@@ -778,6 +743,8 @@ OSDTypeImage::OSDTypeImage(void)
     m_onlyusefirst = false;
 
     m_displaypos = QPoint(0, 0);
+    m_unbiasedpos = QPoint(0, 0);
+    m_cacheitem = NULL;
 
     m_yuv = NULL;
     m_alpha = NULL;
@@ -790,10 +757,14 @@ OSDTypeImage::OSDTypeImage(void)
 
 OSDTypeImage::~OSDTypeImage()
 {
-    if (m_yuv)
-        delete [] m_yuv;
-    if (m_alpha)
-        delete [] m_alpha;
+    // In case we have a cache item in hand, it's safe to delete it,
+    // as it should not be in OSDImageCache anymore and it should have
+    // been written to the file cache for faster access in the future.
+    if (m_cacheitem)
+    {
+        delete m_cacheitem;
+        m_cacheitem = NULL;
+    }
 }
 
 void OSDTypeImage::SetName(const QString &name)
@@ -801,13 +772,19 @@ void OSDTypeImage::SetName(const QString
     m_name = name;
 }
 
-void OSDTypeImage::Reinit(float wchange, float hchange, float wmult, float hmult)
+void OSDTypeImage::SetPosition(QPoint pos, float wmult, float hmult)
 {
-    int x = (int)(m_displaypos.x() * wchange);
-    int y = (int)(m_displaypos.y() * hchange);
+    m_displaypos  = pos;
+    m_unbiasedpos =
+        QPoint((int)round(pos.x() / wmult),
+               (int)round(pos.y() / hmult));
+}
 
-    m_displaypos.setX(x);
-    m_displaypos.setY(y);
+void OSDTypeImage::Reinit(float wmult, float hmult)
+{
+    m_displaypos =
+        QPoint((int)round(m_unbiasedpos.x() * wmult),
+               (int)round(m_unbiasedpos.y() * hmult));
 
     LoadImage(m_filename, wmult, hmult, m_scalew, m_scaleh);
 }
@@ -815,20 +792,44 @@ void OSDTypeImage::Reinit(float wchange,
 void OSDTypeImage::LoadImage(const QString &filename, float wmult, float hmult,
                              int scalew, int scaleh)
 {
-    if (m_isvalid)
+    QString ckey;
+   
+    if (!filename.isEmpty() && filename.length() >= 2)
     {
-        if (m_yuv)
-            delete [] m_yuv;
-        if (m_alpha)
-            delete [] m_alpha;
-
-        m_isvalid = false;
-        m_yuv = NULL;
-        m_alpha = NULL;
+        ckey = OSDImageCache::CreateKey(
+            filename, wmult, hmult, scalew, scaleh);
+    }
+    else 
+    {
+        // this method requires a backing file
+        return;
     }
+  
+    // Get the item from the cache so it's not freed while in use
+    OSDImageCacheValue* value = c_cache.Get(ckey, true);
+  
+    if (value != NULL)
+    {
+        m_yuv       = value->m_yuv;
+        m_ybuffer   = value->m_ybuffer;
+        m_ubuffer   = value->m_ubuffer;
+        m_vbuffer   = value->m_vbuffer;
+        m_alpha     = value->m_alpha;
+        m_imagesize = value->m_imagesize;
+        m_isvalid   = true;
+
+        // Put the old image back to the cache so it can be reused in the
+        // future, and possibly freed by the cache system if the size limit
+        // is reached
+        if (!m_cacheitem)
+            c_cache.Insert(m_cacheitem);
+        m_cacheitem = value;
 
-    if (filename.length() < 2)
         return;
+    }
+   
+    // scaled image was not found in cache, have to create it
+  
 
     QImage tmpimage(filename);
 
@@ -867,17 +868,32 @@ void OSDTypeImage::LoadImage(const QStri
                      imwidth, imheight, tmp2.width());
 
     m_imagesize = QRect(0, 0, imwidth, imheight);
+
+    // put the old image back to the cache so it can be reused in the
+    // future, and possibly freed by the cache system if the size limit
+    // is reached
+    if (m_cacheitem)
+        c_cache.Insert(m_cacheitem);
+  
+    m_cacheitem = new OSDImageCacheValue(
+        ckey,
+        m_yuv,     m_ybuffer, m_ubuffer,
+        m_vbuffer, m_alpha,   m_imagesize);
+ 
+    // save the new cache item to the file cache
+    if (!filename.isEmpty())
+        c_cache.SaveToDisk(m_cacheitem);
 }
 
 void OSDTypeImage::LoadFromQImage(const QImage &img)
 {
+    // this method is not cached as it's used mostly for
+    // subtitles which are displayed only once anyways, caching
+    // would probably only slow things down overall
     if (m_isvalid)
     {
-        if (m_yuv)
-            delete [] m_yuv;
-        if (m_alpha)
-            delete [] m_alpha;
-
+        delete m_cacheitem;
+        m_cacheitem = NULL;
         m_isvalid = false;
         m_yuv = NULL;
         m_alpha = NULL;
@@ -1043,23 +1059,25 @@ OSDTypePosSlider::OSDTypePosSlider(const
     m_maxval = 1000;
     m_curval = 0;
     m_displayrect = displayrect;
+    m_unbiasedrect =
+        QRect((int)round(m_displayrect.x()      / wmult),
+              (int)round(m_displayrect.y()      / hmult),
+              (int)ceil( m_displayrect.width()  / wmult),
+              (int)ceil( m_displayrect.height() / hmult));
 }
 
 OSDTypePosSlider::~OSDTypePosSlider()
 {
 }
 
-void OSDTypePosSlider::Reinit(float wchange, float hchange, float wmult,
-                              float hmult)
+void OSDTypePosSlider::Reinit(float wmult, float hmult)
 {
-    int width = (int)(m_displayrect.width() * wchange);
-    int height = (int)(m_displayrect.height() * hchange);
-    int x = (int)(m_displayrect.x() * wchange);
-    int y = (int)(m_displayrect.y() * hchange);
-
-    m_displayrect = QRect(x, y, width, height);
-
-    OSDTypeImage::Reinit(wchange, hchange, wmult, hmult);
+    m_displayrect =
+        QRect((int)round(m_unbiasedrect.x()      * wmult),
+              (int)round(m_unbiasedrect.y()      * hmult),
+              (int)ceil( m_unbiasedrect.width()  * wmult),
+              (int)ceil( m_unbiasedrect.height() * hmult));
+    OSDTypeImage::Reinit(wmult, hmult);
 }
 
 void OSDTypePosSlider::SetPosition(int pos)
@@ -1092,23 +1110,25 @@ OSDTypeFillSlider::OSDTypeFillSlider(con
     m_drawwidth = 0;
     m_onlyusefirst = true;
     m_displayrect = displayrect;
+    m_unbiasedrect =
+        QRect((int)round(m_displayrect.x()      / wmult),
+              (int)round(m_displayrect.y()      / hmult),
+              (int)ceil( m_displayrect.width()  / wmult),
+              (int)ceil( m_displayrect.height() / hmult));
 }
 
 OSDTypeFillSlider::~OSDTypeFillSlider()
 {
 }
 
-void OSDTypeFillSlider::Reinit(float wchange, float hchange, float wmult,
-                               float hmult)
+void OSDTypeFillSlider::Reinit(float wmult, float hmult)
 {
-    int width = (int)(m_displayrect.width() * wchange);
-    int height = (int)(m_displayrect.height() * hchange);
-    int x = (int)(m_displayrect.x() * wchange);
-    int y = (int)(m_displayrect.y() * hchange);
-
-    m_displayrect = QRect(x, y, width, height);
-
-    OSDTypeImage::Reinit(wchange, hchange, wmult, hmult);
+    m_displayrect =
+        QRect((int)round(m_unbiasedrect.x()      * wmult),
+              (int)round(m_unbiasedrect.y()      * hmult),
+              (int)ceil( m_unbiasedrect.width()  * wmult),
+              (int)ceil( m_unbiasedrect.height() * hmult));
+    OSDTypeImage::Reinit(wmult, hmult);
 }
 
 void OSDTypeFillSlider::SetPosition(int pos)
@@ -1143,6 +1163,11 @@ OSDTypeEditSlider::OSDTypeEditSlider(con
     m_maxval = 1000;
     m_curval = 0;
     m_displayrect = displayrect;
+    m_unbiasedrect =
+        QRect((int)round(m_displayrect.x()      / wmult),
+              (int)round(m_displayrect.y()      / hmult),
+              (int)ceil( m_displayrect.width()  / wmult),
+              (int)ceil( m_displayrect.height() / hmult));
     m_drawwidth = displayrect.width();
 
     m_drawMap = new unsigned char[m_drawwidth + 1];
@@ -1162,6 +1187,7 @@ OSDTypeEditSlider::OSDTypeEditSlider(con
 
     m_scalew = scalew;
     m_scaleh = scaleh;
+    m_cacheitem = NULL;
 
     LoadImage(m_redname, wmult, hmult, scalew, scaleh);
     if (m_isvalid)
@@ -1184,22 +1210,16 @@ OSDTypeEditSlider::OSDTypeEditSlider(con
 OSDTypeEditSlider::~OSDTypeEditSlider()
 {
     delete [] m_drawMap;
-
-    if (m_ryuv)
-        delete [] m_ryuv;
-    if (m_ralpha)
-        delete [] m_ralpha;
 }
 
-void OSDTypeEditSlider::Reinit(float wchange, float hchange, float wmult,
-                               float hmult)
+void OSDTypeEditSlider::Reinit(float wmult, float hmult)
 {
-    int width = (int)(m_displayrect.width() * wchange);
-    int height = (int)(m_displayrect.height() * hchange);
-    int x = (int)(m_displayrect.x() * wchange);
-    int y = (int)(m_displayrect.y() * hchange);
+    m_displayrect =
+        QRect((int)round(m_unbiasedrect.x()      * wmult),
+              (int)round(m_unbiasedrect.y()      * hmult),
+              (int)ceil( m_unbiasedrect.width()  * wmult),
+              (int)ceil( m_unbiasedrect.height() * hmult));
 
-    m_displayrect = QRect(x, y, width, height);
     m_drawwidth = m_displayrect.width();
 
     delete [] m_drawMap;
@@ -1210,11 +1230,6 @@ void OSDTypeEditSlider::Reinit(float wch
 
     m_displaypos = m_displayrect.topLeft();
 
-    if (m_ryuv)
-        delete [] m_ryuv;
-    if (m_ralpha)
-        delete [] m_ralpha;
-
     LoadImage(m_redname, wmult, hmult, m_scalew, m_scaleh);
     if (m_isvalid)
     {
@@ -1360,30 +1375,46 @@ void OSDTypeEditSlider::Draw(OSDSurface 
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-OSDTypeBox::OSDTypeBox(const QString &name, QRect displayrect) 
-          : OSDType(name)
+OSDTypeBox::OSDTypeBox(const QString &name, QRect displayrect,
+                       float wmult, float hmult)
+    : OSDType(name)
 {
     size = displayrect;
+    m_unbiasedsize =
+        QRect((int)round(size.x()      / wmult),
+              (int)round(size.y()      / hmult),
+              (int)ceil( size.width()  / wmult),
+              (int)ceil( size.height() / hmult));
+}
+
+void OSDTypeBox::SetRect(QRect newrect, float wmult, float hmult)
+{
+    size = newrect;
+    m_unbiasedsize =
+        QRect((int)round(size.x()      / wmult),
+              (int)round(size.y()      / hmult),
+              (int)ceil( size.width()  / wmult),
+              (int)ceil( size.height() / hmult));
 }
 
 OSDTypeBox::OSDTypeBox(const OSDTypeBox &other)
           : OSDType(other.m_name)
 {
     size = other.size;
+    m_unbiasedsize = other.m_unbiasedsize;
 }
 
 OSDTypeBox::~OSDTypeBox()
 {
 }
 
-void OSDTypeBox::Reinit(float wchange, float hchange)
+void OSDTypeBox::Reinit(float wmult, float hmult)
 {
-    int width = (int)(size.width() * wchange);
-    int height = (int)(size.height() * hchange);
-    int x = (int)(size.x() * wchange);
-    int y = (int)(size.y() * hchange);
-
-    size = QRect(x, y, width, height);
+    size =
+        QRect((int)round(m_unbiasedsize.x()      * wmult),
+              (int)round(m_unbiasedsize.y()      * hmult),
+              (int)ceil( m_unbiasedsize.width()  * wmult),
+              (int)ceil( m_unbiasedsize.height() * hmult));
 }
 
 void OSDTypeBox::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, 
@@ -1498,44 +1529,52 @@ OSDTypePositionRectangle::OSDTypePositio
 }       
    
 OSDTypePositionRectangle::OSDTypePositionRectangle(
-                                        const OSDTypePositionRectangle &other) 
-                        : OSDType(other.m_name), OSDTypePositionIndicator(other)
+    const OSDTypePositionRectangle &other) 
+    : OSDType(other.m_name), OSDTypePositionIndicator(other)
 {
     for (int i = 0; i < m_numpositions; i++)
     {
         QRect tmp = other.positions[i];
         positions.push_back(tmp);
     }
+    for (int i = 0; i < m_numpositions; i++)
+    {
+        QRect tmp = other.unbiasedpos[i];
+        unbiasedpos.push_back(tmp);
+    }
 }
 
 OSDTypePositionRectangle::~OSDTypePositionRectangle()
 {
 }
 
-void OSDTypePositionRectangle::Reinit(float wchange, float hchange)
+void OSDTypePositionRectangle::Reinit(float wmult, float hmult)
 {
     for (int i = 0; i < m_numpositions; i++)
     {
-        QRect tmp = positions[i];
-
-        int width = (int)(tmp.width() * wchange);
-        int height = (int)(tmp.height() * hchange);
-        int x = (int)(tmp.x() * wchange);
-        int y = (int)(tmp.y() * hchange);
-
-        tmp = QRect(x, y, width, height);
-        positions[i] = tmp;
+        QRect tmp = unbiasedpos[i];
+        positions[i] =
+            QRect((int)round(tmp.x()      * wmult),
+                  (int)round(tmp.y()      * hmult),
+                  (int)ceil( tmp.width()  * wmult),
+                  (int)ceil( tmp.height() * hmult));
     }
 }
 
-void OSDTypePositionRectangle::AddPosition(QRect rect)
+void OSDTypePositionRectangle::AddPosition(
+    QRect rect, float wmult, float hmult)
 {
     positions.push_back(rect);
+    unbiasedpos.push_back(
+        QRect((int)round(rect.x()      / wmult),
+              (int)round(rect.y()      / hmult),
+              (int)ceil( rect.width()  / wmult),
+              (int)ceil( rect.height() / hmult)));
     m_numpositions++;
 }
 
-void OSDTypePositionRectangle::Draw(OSDSurface *surface, int fade, int maxfade, 
-                                    int xoff, int yoff)
+void OSDTypePositionRectangle::Draw(
+    OSDSurface *surface, int fade, int maxfade, int xoff, int yoff)
 {
     fade = fade;
     maxfade = maxfade;
@@ -1618,17 +1657,21 @@ void OSDTypePositionRectangle::Draw(OSDS
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 OSDTypePositionImage::OSDTypePositionImage(const QString &name)
-                    : OSDTypeImage(name), OSDTypePositionIndicator()
+    : OSDTypeImage(name), OSDTypePositionIndicator(),
+      m_wmult(0.0f), m_hmult(0.0f)
 {
 }
 
 OSDTypePositionImage::OSDTypePositionImage(const OSDTypePositionImage &other)
                     : OSDTypeImage(other), OSDTypePositionIndicator(other)
 {
+    m_wmult = other.m_wmult;
+    m_hmult = other.m_hmult;
+
     for (int i = 0; i < m_numpositions; i++)
     {
-        QPoint tmp = other.positions[i];
-        positions.push_back(tmp);
+        positions.push_back(other.positions[i]);
+        unbiasedpos.push_back(other.unbiasedpos[i]);
     }
 }
 
@@ -1636,45 +1679,61 @@ OSDTypePositionImage::~OSDTypePositionIm
 {
 }
 
-void OSDTypePositionImage::Reinit(float wchange, float hchange, float wmult, 
-                                  float hmult)
+void OSDTypePositionImage::Reinit(float wmult, float hmult)
 {
-    OSDTypeImage::Reinit(wchange, hchange, wmult, hmult);
+    m_wmult = wmult;
+    m_hmult = hmult;
+    
+    OSDTypeImage::Reinit(wmult, hmult);
 
     for (int i = 0; i < m_numpositions; i++)
     {
-        QPoint tmp = positions[i];
-
-        int x = (int)(tmp.x() * wchange);
-        int y = (int)(tmp.y() * hchange);
-
-        positions[i].setX(x);
-        positions[i].setY(y);
+        positions[i] =
+            QPoint((int)round(unbiasedpos[i].x() * wmult),
+                   (int)round(unbiasedpos[i].y() * hmult));
     }
 }
 
-void OSDTypePositionImage::AddPosition(QPoint pos)
+void OSDTypePositionImage::AddPosition(QPoint pos, float wmult, float hmult)
 {
+    if (m_wmult == 0.0f || m_hmult == 0.0f)
+    {
+        m_wmult = wmult;
+        m_hmult = hmult;
+    }
     positions.push_back(pos);
+    unbiasedpos.push_back(
+        QPoint((int)round(pos.x() / wmult),
+               (int)round(pos.y() / hmult)));
+
+    VERBOSE(VB_IMPORTANT,
+            "OSDTypePositionImage::AddPosition["<<m_numpositions<<"]("
+            <<pos.x()<<"x"<<pos.y()
+            <<"  "<<wmult<<", "<<hmult<<")");
+
     m_numpositions++;
 }
 
 void OSDTypePositionImage::Draw(OSDSurface *surface, int fade, int maxfade,
                                 int xoff, int yoff)
 {
+    VERBOSE(VB_IMPORTANT,
+            "OSDTypePositionImage::Draw["<<m_curposition<<"]("
+            <<m_wmult<<", "<<m_hmult<<")");
+
     if (m_curposition < 0 || m_curposition >= m_numpositions)
         return;
 
     QPoint pos = positions[m_curposition];
 
-    OSDTypeImage::SetPosition(pos);
+    OSDTypeImage::SetPosition(pos, m_wmult, m_hmult);
     OSDTypeImage::Draw(surface, fade, maxfade, xoff, yoff);
 }
 
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 OSDTypeCC::OSDTypeCC(const QString &name, TTFFont *font, int xoff, int yoff,
-                     int dispw, int disph)
+                     int dispw, int disph, float wmult, float hmult)
          : OSDType(name)
 {
     m_font = font;
@@ -1683,9 +1742,11 @@ OSDTypeCC::OSDTypeCC(const QString &name
     yoffset = yoff;
     displaywidth = dispw;
     displayheight = disph;
+    m_wmult = wmult;
+    m_hmult = hmult;
 
     QRect rect = QRect(0, 0, 0, 0);
-    m_box = new OSDTypeBox("cc_background", rect);
+    m_box = new OSDTypeBox("cc_background", rect, wmult, hmult);
     m_ccbackground = gContext->GetNumSetting("CCBackground", 0);
 }
 
@@ -1695,12 +1756,23 @@ OSDTypeCC::~OSDTypeCC()
     delete m_box;
 }
 
-void OSDTypeCC::Reinit(int x, int y, int dispw, int disph)
+void OSDTypeCC::Reinit(float wmult, float hmult)
+{
+    (void) wmult;
+    (void) hmult;
+    VERBOSE(VB_IMPORTANT, "Programmer error: "
+            "Call to OSDTypeCC::Reinit(float,float)");
+}
+
+void OSDTypeCC::Reinit(int x, int y, int dispw, int disph,
+                       float wmult, float hmult)
 {
     xoffset = x;
     yoffset = y;
     displaywidth = dispw;
     displayheight = disph;
+    m_wmult = wmult;
+    m_hmult = hmult;    
 }
 
 void OSDTypeCC::AddCCText(const QString &text, int x, int y, int color, 
@@ -1875,7 +1947,7 @@ void OSDTypeCC::Draw(OSDSurface *surface
             {
                 QRect rect = QRect(0, 0, textlength + 4, 
                                    (m_font->Size() * 3 / 2) + 3);
-                m_box->SetRect(rect);
+                m_box->SetRect(rect, m_wmult, m_hmult);
                 m_box->Draw(surface, 0, 0, x - 2, y - 2);
             }
 
diff -pruN mythtv-0.19/libs/libmythtv/osdtypes.h mythtv/libs/libmythtv/osdtypes.h
--- mythtv-0.19/libs/libmythtv/osdtypes.h	2005-12-05 16:40:28.000000000 +1000
+++ mythtv/libs/libmythtv/osdtypes.h	2006-05-10 09:54:43.000000000 +1000
@@ -8,6 +8,7 @@
 #include <vector>
 #include <qobject.h>
 #include <qregexp.h>
+#include "osdimagecache.h"
 
 using namespace std;
 
@@ -137,6 +138,8 @@ class OSDType : public QObject
 
     QString Name() { return m_name; }
 
+    virtual void Reinit(float wmult, float hmult) = 0;
+
     virtual void Draw(OSDSurface *surface, int fade, int maxfade, int xoff,
                       int yoff) = 0;
 
@@ -150,11 +153,11 @@ class OSDTypeText : public OSDType
 {
   public:
     OSDTypeText(const QString &name, TTFFont *font, const QString &text,
-                QRect displayrect);
+                QRect displayrect, float wmult, float hmult);
     OSDTypeText(const OSDTypeText &text);
    ~OSDTypeText();
 
-    void Reinit(float wchange, float hchange);
+    void Reinit(float wmult, float hmult);
 
     void SetAltFont(TTFFont *font);
     void SetUseAlt(bool usealt) { m_usingalt = usealt; }
@@ -190,6 +193,7 @@ class OSDTypeText : public OSDType
 
     QRect m_displaysize;
     QRect m_screensize;
+    QRect m_unbiasedsize;
     QString m_message;
     QString m_default_msg;
 
@@ -231,7 +235,7 @@ class OSDTypeImage : public OSDType
     virtual ~OSDTypeImage();
 
     void SetName(const QString &name);
-    void Reinit(float wchange, float hchange, float wmult, float hmult);
+    void Reinit(float wmult, float hmult);
 
     void LoadImage(const QString &filename, float wmult, float hmult, 
                    int scalew = -1, int scaleh = -1);
@@ -239,14 +243,12 @@ class OSDTypeImage : public OSDType
 
     void SetStaticSize(int scalew, int scaleh) { m_scalew = scalew;
                                                  m_scaleh = scaleh; }
+    void SetPosition(QPoint pos, float wmult, float hmult);
 
-    QPoint DisplayPos() { return m_displaypos; }
-    void SetPosition(QPoint pos) { m_displaypos = pos; }
-
-    QRect ImageSize() { return m_imagesize; }
-
-    int width() { return m_imagesize.width(); }
-    int height() { return m_imagesize.height(); }
+    QPoint DisplayPos() const { return m_displaypos;         }
+    QRect  ImageSize()  const { return m_imagesize;          }
+    int    width()      const { return m_imagesize.width();  }
+    int    height()     const { return m_imagesize.height(); }
 
     virtual void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, 
                       int yoff);
@@ -254,6 +256,7 @@ class OSDTypeImage : public OSDType
   protected:
     QRect m_imagesize;
     QPoint m_displaypos;
+    QPoint m_unbiasedpos;
 
     QString m_filename;
 
@@ -270,6 +273,9 @@ class OSDTypeImage : public OSDType
 
     int m_drawwidth;
     bool m_onlyusefirst;
+
+    static OSDImageCache  c_cache;
+    OSDImageCacheValue   *m_cacheitem;
 };
 
 class OSDTypePosSlider : public OSDTypeImage
@@ -280,7 +286,7 @@ class OSDTypePosSlider : public OSDTypeI
                       int scalew = -1, int scaleh = -1);
    ~OSDTypePosSlider();
 
-    void Reinit(float wchange, float hchange, float wmult, float hmult);
+    void Reinit(float wmult, float hmult);
 
     void SetRectangle(QRect rect) { m_displayrect = rect; }
     QRect ImageSize() { return m_imagesize; }
@@ -290,6 +296,7 @@ class OSDTypePosSlider : public OSDTypeI
 
   private:
     QRect m_displayrect;
+    QRect m_unbiasedrect;
     int m_maxval;
     int m_curval;
 };
@@ -302,7 +309,7 @@ class OSDTypeFillSlider : public OSDType
                       int scalew = -1, int scaleh = -1);
    ~OSDTypeFillSlider();
 
-    void Reinit(float wchange, float hchange, float wmult, float hmult);
+    void Reinit(float wmult, float hmult);
 
     void SetRectangle(QRect rect) { m_displayrect = rect; }
     QRect ImageSize() { return m_imagesize; }
@@ -314,6 +321,7 @@ class OSDTypeFillSlider : public OSDType
 
   private:
     QRect m_displayrect;
+    QRect m_unbiasedrect;
     int m_maxval;
     int m_curval;
 };
@@ -327,7 +335,7 @@ class OSDTypeEditSlider : public OSDType
                       int scalew = -1, int scaleh = -1);
    ~OSDTypeEditSlider();
 
-    void Reinit(float wchange, float hchange, float wmult, float hmult);
+    void Reinit(float wmult, float hmult);
 
     void SetRectangle(QRect rect) { m_displayrect = rect; }
     QRect ImageSize() { return m_imagesize; }
@@ -339,6 +347,7 @@ class OSDTypeEditSlider : public OSDType
 
   private:
     QRect m_displayrect;
+    QRect m_unbiasedrect;
     int m_maxval;
     int m_curval;
 
@@ -360,17 +369,19 @@ class OSDTypeEditSlider : public OSDType
 class OSDTypeBox : public OSDType
 {
   public:
-    OSDTypeBox(const QString &name, QRect displayrect); 
+    OSDTypeBox(const QString &name, QRect displayrect,
+               float wmult, float hmult);
     OSDTypeBox(const OSDTypeBox &other);
    ~OSDTypeBox();
 
-    void Reinit(float wchange, float hchange);
-    void SetRect(QRect newrect) { size = newrect; }
+    void Reinit(float wmult, float hmult);
+    void SetRect(QRect newrect, float wmult, float hmult);
 
     void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
 
   private:
     QRect size;
+    QRect m_unbiasedsize;
 };
 
 class OSDTypePositionIndicator
@@ -403,14 +414,15 @@ class OSDTypePositionRectangle : public 
     OSDTypePositionRectangle(const OSDTypePositionRectangle &other);
    ~OSDTypePositionRectangle();
 
-    void AddPosition(QRect rect);
+    void AddPosition(QRect rect, float wmult, float hmult);
 
-    void Reinit(float wchange, float hchange);
+    void Reinit(float wmult, float hmult);
 
     void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
 
   private:
-    vector<QRect> positions; 
+    vector<QRect> positions;
+    vector<QRect> unbiasedpos;
 };
 
 class OSDTypePositionImage : public virtual OSDTypeImage, 
@@ -421,14 +433,17 @@ class OSDTypePositionImage : public virt
     OSDTypePositionImage(const OSDTypePositionImage &other);
    ~OSDTypePositionImage();
 
-    void Reinit(float wchange, float hchange, float wmult, float hmult);
+    void Reinit(float wmult, float hmult);
 
-    void AddPosition(QPoint pos);
+    void AddPosition(QPoint pos, float wmult, float hmult);
 
     void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
 
   private:
     vector<QPoint> positions;
+    vector<QPoint> unbiasedpos;
+    float m_wmult;
+    float m_hmult;
 };
 
 class ccText
@@ -445,10 +460,14 @@ class OSDTypeCC : public OSDType
 {
   public:
     OSDTypeCC(const QString &name, TTFFont *font, int xoff, int yoff,
-              int dispw, int disph);
+              int dispw, int disph, float wmult, float hmult);
    ~OSDTypeCC();
 
-    void Reinit(int xoff, int yoff, int dispw, int disph);
+    void Reinit(float wmult, float hmult);
+
+    void Reinit(int xoff, int yoff,
+                int dispw, int disph,
+                float wmult, float hmult);
 
     void AddCCText(const QString &text, int x, int y, int color, 
                    bool teletextmode = false);
@@ -464,7 +483,7 @@ class OSDTypeCC : public OSDType
     vector<ccText *> *m_textlist;
     OSDTypeBox *m_box;
     int m_ccbackground;
-
+    float m_wmult, m_hmult;
     int xoffset, yoffset, displaywidth, displayheight;
 };
 
diff -pruN mythtv-0.19/libs/libmythtv/pchdtvsignalmonitor.cpp mythtv/libs/libmythtv/pchdtvsignalmonitor.cpp
--- mythtv-0.19/libs/libmythtv/pchdtvsignalmonitor.cpp	2006-02-08 07:56:06.000000000 +1000
+++ mythtv/libs/libmythtv/pchdtvsignalmonitor.cpp	2006-04-20 23:46:13.000000000 +1000
@@ -108,8 +108,8 @@ void pcHDTVSignalMonitor::RunTableMonito
 
         len += remainder;
         remainder = GetStreamData()->ProcessData(buffer, len);
-        if (remainder > 0) // leftover bytes
-            memmove(buffer, &(buffer[buffer_size - remainder]), remainder);
+        if (remainder > 0 && (len > remainder)) // leftover bytes
+            memmove(buffer, &(buffer[len - remainder]), remainder);
     }
     DBG_SM("RunTableMonitor()", "end");
 }
diff -pruN mythtv-0.19/libs/libmythtv/RingBuffer.cpp mythtv/libs/libmythtv/RingBuffer.cpp
--- mythtv-0.19/libs/libmythtv/RingBuffer.cpp	2006-02-08 07:56:06.000000000 +1000
+++ mythtv/libs/libmythtv/RingBuffer.cpp	2006-04-13 11:22:30.000000000 +1000
@@ -145,6 +145,12 @@ void RingBuffer::OpenFile(const QString 
     VERBOSE(VB_PLAYBACK, LOC + QString("OpenFile(%1, %1)")
             .arg(lfilename).arg(retryCount));
 
+    if ((filename.right(4).lower() == ".png") ||
+        (filename.right(4).lower() == ".gif"))
+    {
+        retryCount = 0;
+    }
+
     uint openAttempts = retryCount + 1;
 
     filename = lfilename;
@@ -162,6 +168,7 @@ void RingBuffer::OpenFile(const QString 
 
     bool is_local = false;
     bool is_dvd = false;
+
     if ((filename.left(7) == "myth://") &&
         (filename.length() > 7 ))
     {
@@ -271,6 +278,11 @@ void RingBuffer::OpenFile(const QString 
             remotefile = NULL;
         }
     }
+
+    setswitchtonext = false;
+    ateof = false;
+    commserror = false;
+    numfailures = 0;
 }
 
 /** \fn RingBuffer::IsOpen(void) const
@@ -727,7 +739,7 @@ void RingBuffer::ReadAheadThread(void)
         loops = 0;
 
         pthread_rwlock_rdlock(&rwlock);
-        if (totfree > readblocksize && !commserror)
+        if (totfree > readblocksize && !commserror && !ateof && !setswitchtonext)
         {
             // limit the read size
             totfree = readblocksize;
@@ -737,6 +749,9 @@ void RingBuffer::ReadAheadThread(void)
 
             if (remotefile)
             {
+                if (livetvchain && livetvchain->HasNext())
+                    remotefile->SetTimeout(true);
+
                 ret = safe_read(remotefile, readAheadBuffer + rbwpos,
                                 totfree);
                 internalreadpos += ret;
@@ -785,8 +800,16 @@ void RingBuffer::ReadAheadThread(void)
             totfree = 0;
         }
 
-        if (!readsallowed && used >= fill_min)
+        if (!readsallowed && (used >= fill_min || setswitchtonext))
+        {
             readsallowed = true;
+            VERBOSE(VB_PLAYBACK, QString("reads allowed (%1 %2)").arg(used)
+                                                                .arg(fill_min));
+        }
+        else if (!readsallowed)
+            VERBOSE(VB_PLAYBACK, QString("buffering (%1 %2 %3)").arg(used)
+                                                                .arg(fill_min)
+                                                                .arg(ret));
 
         if (readsallowed && used < fill_min && !ateof && !setswitchtonext)
         {
@@ -808,8 +831,11 @@ void RingBuffer::ReadAheadThread(void)
 
         pthread_rwlock_unlock(&rwlock);
 
-        if ((used >= fill_threshold || wantseek) && !pausereadthread)
+        if ((used >= fill_threshold || wantseek || ateof || setswitchtonext) &&
+            !pausereadthread)
+        {
             usleep(500);
+        }
     }
 
     delete [] readAheadBuffer;
@@ -853,15 +879,15 @@ int RingBuffer::ReadFromBuf(void *buf, i
                  VERBOSE(VB_IMPORTANT,
                          LOC + "Taking too long to be allowed to read..");
                  readErr++;
-                 
+
                  // HACK Sometimes the readhead thread gets borked on startup.
-               /*  if ((readErr % 2) && (rbrpos ==0))
+                 if ((readErr > 2 && readErr % 2) && (rbrpos ==0))
                  {
                     VERBOSE(VB_IMPORTANT, "restarting readhead thread..");
                     KillReadAheadThread();
                     StartupReadAheadThread();
                  }                    
-                   */ 
+ 
                  if (readErr > 10)
                  {
                      VERBOSE(VB_IMPORTANT, LOC_ERR + "Took more than "
@@ -895,6 +921,12 @@ int RingBuffer::ReadFromBuf(void *buf, i
                 VERBOSE(VB_IMPORTANT, LOC + "Waited " +
                         QString("%1").arg(elapsed/1000) +
                         " seconds for data to become available...");
+                if (livetvchain)
+                {
+                    VERBOSE(VB_IMPORTANT, "Checking to see if there's a "
+                                          "new livetv program to switch to..");
+                    livetvchain->ReloadAll();
+                }
             }
 
             bool quit = livetvchain && (livetvchain->NeedsToSwitch() || 
@@ -923,7 +955,7 @@ int RingBuffer::ReadFromBuf(void *buf, i
         availWaitMutex.unlock();
 
         avail = ReadBufAvail();
-        if (ateof && avail < count)
+        if ((ateof || setswitchtonext) && avail < count)
             count = avail;
 
         if (commserror)
diff -pruN mythtv-0.19/libs/libmythtv/RingBuffer.h mythtv/libs/libmythtv/RingBuffer.h
--- mythtv-0.19/libs/libmythtv/RingBuffer.h	2006-02-07 14:31:49.000000000 +1000
+++ mythtv/libs/libmythtv/RingBuffer.h	2006-02-23 17:54:05.000000000 +1000
@@ -91,6 +91,7 @@ class RingBuffer
     long long GetTotalReadPosition(void);
 
     long long SetAdjustFilesize(void);
+    void SetTimeout(bool fast) { oldfile = fast; }
     
   protected:
     static void *StartReader(void *type);
diff -pruN mythtv-0.19/libs/libmythtv/scanwizard.cpp mythtv/libs/libmythtv/scanwizard.cpp
--- mythtv-0.19/libs/libmythtv/scanwizard.cpp	2005-12-17 05:58:46.000000000 +1000
+++ mythtv/libs/libmythtv/scanwizard.cpp	2006-04-26 05:50:59.000000000 +1000
@@ -1,5 +1,5 @@
 /*
- * $Id: scanwizard.cpp 8292 2005-12-16 19:58:46Z danielk $
+ * $Id: scanwizard.cpp 9799 2006-04-25 19:50:59Z danielk $
  * vim: set expandtab tabstop=4 shiftwidth=4:
  *
  * Original Project
@@ -518,7 +518,9 @@ void ScanWizardScanner::scan()
                     "SELECT dvb_diseqc_type, diseqc_port,  diseqc_pos, "
                     "       lnb_lof_switch,  lnb_lof_hi,   lnb_lof_lo "
                     "FROM cardinput, capturecard "
-                    "WHERE capturecard.cardid=%1 and cardinput.sourceid=%2")
+                    "WHERE capturecard.cardid = %1 AND "
+                    "      cardinput.sourceid = %2 AND "
+                    "      capturecard.cardid = cardinput.cardid")
                 .arg(parent->captureCard()).arg(nVideoSource));
 
             if (query.exec() && query.isActive() && query.size() > 0)
diff -pruN mythtv-0.19/libs/libmythtv/scanwizardhelpers.h mythtv/libs/libmythtv/scanwizardhelpers.h
--- mythtv-0.19/libs/libmythtv/scanwizardhelpers.h	2006-02-02 02:56:06.000000000 +1000
+++ mythtv/libs/libmythtv/scanwizardhelpers.h	2006-04-13 00:21:41.000000000 +1000
@@ -1,5 +1,5 @@
 /* -*- Mode: c++ -*-
- * $Id: scanwizardhelpers.h 8817 2006-02-01 16:56:06Z danielk $
+ * $Id: scanwizardhelpers.h 9685 2006-04-12 14:21:41Z danielk $
  * vim: set expandtab tabstop=4 shiftwidth=4:
  *
  * Original Project
@@ -272,11 +272,13 @@ class ScanFrequencyTable: public ComboBo
   public:
     ScanFrequencyTable()
     {
-        addSelection(QObject::tr("Broadcast"),        "us",            true);
-        addSelection(QObject::tr("Cable")    +" 78+", "uscablehigh",   false);
-        addSelection(QObject::tr("Cable HRC")+" 78+", "uscablehrchigh",false);
-        addSelection(QObject::tr("Cable"),            "uscable",       false);
-        addSelection(QObject::tr("Cable HRC"),        "ushrc",         false);
+        addSelection(QObject::tr("Broadcast"),        "us",          true);
+        addSelection(QObject::tr("Cable")    +" 78+", "uscablehigh", false);
+        addSelection(QObject::tr("Cable HRC")+" 67+", "ushrchigh",   false);
+        addSelection(QObject::tr("Cable IRC")+" 67+", "usirchigh",   false);
+        addSelection(QObject::tr("Cable"),            "uscable",     false);
+        addSelection(QObject::tr("Cable HRC"),        "ushrc",       false);
+        addSelection(QObject::tr("Cable IRC"),        "usirc",       false);
 
         setLabel(QObject::tr("Frequency Table"));
         setHelpText(QObject::tr("Frequency table to use.") + " " +
diff -pruN mythtv-0.19/libs/libmythtv/tv_play.cpp mythtv/libs/libmythtv/tv_play.cpp
--- mythtv-0.19/libs/libmythtv/tv_play.cpp	2006-02-08 07:56:06.000000000 +1000
+++ mythtv/libs/libmythtv/tv_play.cpp	2006-04-22 07:08:11.000000000 +1000
@@ -247,7 +247,7 @@ TV::TV(void)
       browsechannum(""), browsechanid(""), browsestarttime(""),
       // Program Info for currently playing video
       recorderPlaybackInfo(NULL),
-      playbackinfo(NULL), inputFilename(""), playbackLen(0),
+      playbackinfo(NULL), playbackLen(0),
       lastProgram(NULL), jumpToProgram(false),
       // Video Players
       nvp(NULL), pipnvp(NULL), activenvp(NULL),
@@ -578,19 +578,7 @@ bool TV::RequestNextRecorder(bool showDi
     if (!testrec->IsValidRecorder())
     {
         if (showDialogs)
-        {
-            QString title = tr("MythTV is already using all available "
-                               "inputs for recording.  If you want to "
-                               "watch an in-progress recording, select one "
-                               "from the playback menu.  If you want to "
-                               "watch live TV, cancel one of the "
-                               "in-progress recordings from the delete "
-                               "menu.");
-            
-            DialogBox diag(gContext->GetMainWindow(), title);
-            diag.AddButton(tr("Cancel and go back to the TV menu"));
-            diag.exec();
-        }        
+            ShowNoRecorderDialog();
         
         delete testrec;
         
@@ -659,8 +647,6 @@ int TV::Playback(ProgramInfo *rcinfo)
     if (internalState != kState_None)
         return 0;
 
-    inputFilename = rcinfo->pathname;
-
     playbackLen = rcinfo->CalculateLength();
     playbackinfo = new ProgramInfo(*rcinfo);
 
@@ -844,9 +830,10 @@ void TV::HandleStateChange(void)
         }
         else
         {
-            tvchain->SetProgram(playbackinfo);
+            QString playbackURL = playbackinfo->GetPlaybackURL();
 
-            prbuffer = new RingBuffer(playbackinfo->pathname, false);
+            tvchain->SetProgram(playbackinfo);
+            prbuffer = new RingBuffer(playbackURL, false);
             prbuffer->SetLiveMode(tvchain);
         }
 
@@ -895,7 +882,14 @@ void TV::HandleStateChange(void)
     else if (TRANSITION(kState_None, kState_WatchingPreRecorded) ||
              TRANSITION(kState_None, kState_WatchingRecording))
     {
-        prbuffer = new RingBuffer(inputFilename, false);
+        QString playbackURL;
+        if ((playbackinfo->pathname.left(4) == "dvd:") ||
+            (playbackinfo->isVideo))
+            playbackURL = playbackinfo->pathname;
+        else
+            playbackURL = playbackinfo->GetPlaybackURL();
+
+        prbuffer = new RingBuffer(playbackURL, false);
         if (prbuffer->IsOpen())
         {
             gContext->DisableScreensaver();
@@ -924,7 +918,7 @@ void TV::HandleStateChange(void)
             {
                 QString message = "COMMFLAG_REQUEST ";
                 message += playbackinfo->chanid + " " +
-                           playbackinfo->startts.toString(Qt::ISODate);
+                           playbackinfo->recstartts.toString(Qt::ISODate);
                 RemoteSendMessage(message);
             }                
         }
@@ -1222,10 +1216,10 @@ void TV::SetupPlayer(bool isWatchingReco
     nvp->SetParentPlayer(this);
     nvp->SetRingBuffer(prbuffer);
     nvp->SetRecorder(recorder);
-    nvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate"));
+    nvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate", 44100));
     nvp->SetAudioDevice(gContext->GetSetting("AudioOutputDevice"));
     nvp->SetLength(playbackLen);
-    nvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking"));
+    nvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking", 0));
     nvp->SetAutoCommercialSkip(autoCommercialSkip);
     nvp->SetLiveTVChain(tvchain);
 
@@ -1296,9 +1290,9 @@ void TV::SetupPipPlayer(void)
     pipnvp->SetAsPIP();
     pipnvp->SetRingBuffer(piprbuffer);
     pipnvp->SetRecorder(piprecorder);
-    pipnvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate"));
+    pipnvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate", 44100));
     pipnvp->SetAudioDevice(gContext->GetSetting("AudioOutputDevice"));
-    pipnvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking"));
+    pipnvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking", 0));
     pipnvp->SetLiveTVChain(piptvchain);
 
     pipnvp->SetLength(playbackLen);
@@ -1454,6 +1448,30 @@ void TV::RunTV(void)
                 lastSignalMsg.clear();
             }
             UpdateOSDTimeoutMessage();
+
+            if (!tvchainUpdate.isEmpty())
+            {
+                tvchainUpdateLock.lock();
+                for (QStringList::Iterator it = tvchainUpdate.begin();
+                     it != tvchainUpdate.end(); ++it)
+                {
+                    if (tvchain && nvp && *it == tvchain->GetID())
+                    {
+                        tvchain->ReloadAll();
+                        if (nvp->GetTVChain())
+                            nvp->CheckTVChain();
+                    }
+                    if (piptvchain && pipnvp && *it == piptvchain->GetID())
+                    {
+                        piptvchain->ReloadAll();
+                        if (pipnvp->GetTVChain())
+                            pipnvp->CheckTVChain();
+                    }
+                }
+                tvchainUpdate.clear();
+                tvchainUpdateLock.unlock();
+            }
+
             osdlock.unlock();
         }
 
@@ -2743,7 +2761,7 @@ void TV::processNetworkControlCommand(QS
                 speedStr = QString("%1X").arg(normal_speed);
 
             struct StatusPosInfo posInfo;
-            nvp->calcSliderPos(posInfo);
+            nvp->calcSliderPos(posInfo, true);
 
             QDateTime respDate = mythCurrentDateTime();
             QString infoStr = "";
@@ -2806,8 +2824,10 @@ void TV::TogglePIPView(void)
         }
         else
         {
+            QString playbackURL = playbackinfo->GetPlaybackURL();
+
             piptvchain->SetProgram(playbackinfo);
-            piprbuffer = new RingBuffer(playbackinfo->pathname, false);
+            piprbuffer = new RingBuffer(playbackURL, false);
             piprbuffer->SetLiveMode(piptvchain);
         }
 
@@ -3472,8 +3492,10 @@ void TV::SwitchCards(uint chanid, QStrin
         }
         else
         {
+            QString playbackURL = playbackinfo->GetPlaybackURL();
+
             tvchain->SetProgram(playbackinfo);
-            prbuffer = new RingBuffer(playbackinfo->pathname, false);
+            prbuffer = new RingBuffer(playbackURL, false);
             prbuffer->SetLiveMode(tvchain);
         }
 
@@ -4627,7 +4649,8 @@ void TV::ChangeTimeStretch(int dir, bool
 
     normal_speed = new_normal_speed;
 
-    activenvp->Play(normal_speed, true);
+    if (!paused)
+        activenvp->Play(normal_speed, true);
 
     QString text = QString(tr("Time Stretch %1X")).arg(normal_speed);
 
@@ -4911,29 +4934,14 @@ void TV::customEvent(QCustomEvent *e)
         }
         else if (tvchain && message.left(12) == "LIVETV_CHAIN")
         {
-            // Get osdlock, while intended for the OSD this ensures that
-            // the nvp & pipnvp are not deleted while we are using it..
-            while (!osdlock.tryLock() && nvp)
-                usleep(2500);
-
             message = message.simplifyWhiteSpace();
             QStringList tokens = QStringList::split(" ", message);
             if (tokens[1] == "UPDATE")
             {
-                if (tvchain && nvp && tokens[2] == tvchain->GetID())
-                {
-                    tvchain->ReloadAll();
-                    if (nvp->GetTVChain())
-                        nvp->CheckTVChain();
-                }
-                if (piptvchain && pipnvp && tokens[2] == piptvchain->GetID())
-                {
-                    piptvchain->ReloadAll();
-                    if (pipnvp->GetTVChain())
-                        pipnvp->CheckTVChain();
-                }
+                tvchainUpdateLock.lock();
+                tvchainUpdate += QDeepCopy<QString>(tokens[2]);
+                tvchainUpdateLock.unlock();
             }
-            osdlock.unlock();
         }
         else if (nvp && message.left(12) == "EXIT_TO_MENU")
         {
@@ -4983,7 +4991,7 @@ void TV::customEvent(QCustomEvent *e)
             QDateTime evstartts = QDateTime::fromString(tokens[2], Qt::ISODate);
 
             if ((playbackinfo->chanid == evchanid) &&
-                (playbackinfo->startts == evstartts))
+                (playbackinfo->recstartts == evstartts))
             {
                 QString msg = "COMMFLAG_REQUEST ";
                 msg += tokens[1] + " " + tokens[2];
@@ -5000,7 +5008,7 @@ void TV::customEvent(QCustomEvent *e)
             QDateTime evstartts = QDateTime::fromString(tokens[2], Qt::ISODate);
 
             if ((playbackinfo->chanid == evchanid) &&
-                (playbackinfo->startts == evstartts))
+                (playbackinfo->recstartts == evstartts))
             {
                 QMap<long long, int> newMap;
                 QStringList mark;
@@ -6067,9 +6075,22 @@ void TV::ShowNoRecorderDialog(void)
                            "in-progress recordings from the delete "
                            "menu.");
 
-    MythPopupBox::showOkPopup(
+    if (embedWinID)
+    {
+        VERBOSE(VB_IMPORTANT, errorText);
+    }
+    else if (GetOSD())
+    {
+        dialogname = "infobox";
+        QStringList options("OK");
+        GetOSD()->NewDialogBox(dialogname, errorText, options, 0);
+    }
+    else
+    {
+        MythPopupBox::showOkPopup(
             gContext->GetMainWindow(), QObject::tr("Channel Change Error"),
             errorText);
+    }
 }
 
 /** \fn TV::PauseLiveTV(void)
diff -pruN mythtv-0.19/libs/libmythtv/tv_play.h mythtv/libs/libmythtv/tv_play.h
--- mythtv-0.19/libs/libmythtv/tv_play.h	2006-02-02 02:40:46.000000000 +1000
+++ mythtv/libs/libmythtv/tv_play.h	2006-02-23 17:54:05.000000000 +1000
@@ -456,7 +456,6 @@ class TV : public QObject
     ProgramInfo *recorderPlaybackInfo; ///< info requested from recorder
     ProgramInfo *playbackinfo;  ///< info sent in via Playback()
     QMutex       pbinfoLock;
-    QString      inputFilename; ///< playbackinfo->pathname
     int          playbackLen;   ///< initial playbackinfo->CalculateLength()
     ProgramInfo *lastProgram;   ///< last program played with this player
     bool         jumpToProgram;
@@ -485,6 +484,8 @@ class TV : public QObject
     // LiveTVChain
     LiveTVChain *tvchain;
     LiveTVChain *piptvchain;
+    QStringList tvchainUpdate;
+    QMutex tvchainUpdateLock;
 
     // RingBuffers
     RingBuffer *prbuffer;
diff -pruN mythtv-0.19/libs/libmythtv/videosource.cpp mythtv/libs/libmythtv/videosource.cpp
--- mythtv-0.19/libs/libmythtv/videosource.cpp	2006-02-08 07:56:06.000000000 +1000
+++ mythtv/libs/libmythtv/videosource.cpp	2006-04-13 00:21:41.000000000 +1000
@@ -32,6 +32,7 @@
 #include "videosource.h"
 #include "datadirect.h"
 #include "scanwizard.h"
+#include "frequencies.h"
 
 #ifdef USING_DVB
 #include <linux/dvb/frontend.h>
@@ -574,22 +575,10 @@ FreqTableSelector::FreqTableSelector(con
 {
     setLabel(QObject::tr("Channel frequency table"));
     addSelection("default");
-    addSelection("us-cable");
-    addSelection("us-bcast");
-    addSelection("us-cable-hrc");
-    addSelection("japan-bcast");
-    addSelection("japan-cable");
-    addSelection("europe-west");
-    addSelection("europe-east");
-    addSelection("italy");
-    addSelection("newzealand");
-    addSelection("australia");
-    addSelection("ireland");
-    addSelection("france");
-    addSelection("china-bcast");
-    addSelection("southafrica");
-    addSelection("argentina");
-    addSelection("australia-optus");
+
+    for (uint i = 0; chanlists[i].name; i++)
+        addSelection(chanlists[i].name);
+
     setHelpText(QObject::tr("Use default unless this source uses a "
                 "different frequency table than the system wide table "
                 "defined in the General settings."));
diff -pruN mythtv-0.19/programs/mythbackend/autoexpire.cpp mythtv/programs/mythbackend/autoexpire.cpp
--- mythtv-0.19/programs/mythbackend/autoexpire.cpp	2006-02-08 07:53:46.000000000 +1000
+++ mythtv/programs/mythbackend/autoexpire.cpp	2006-03-19 05:32:52.000000000 +1000
@@ -291,7 +291,8 @@ void AutoExpire::ExpireLiveTV(int type)
 
     if ((availFreeKB = getDiskSpace(record_file_prefix, tKB, uKB)) < 0)
     {
-        QString msg = QString("ERROR: Could not calculate free space.");
+        QString msg = QString("ERROR: Could not calculate free space for %1.")
+                              .arg(record_file_prefix);
         VERBOSE(VB_IMPORTANT, LOC + msg);
         gContext->LogEntry("mythbackend", LP_WARNING,
                            "Autoexpire Recording", msg);
diff -pruN mythtv-0.19/programs/mythbackend/filetransfer.cpp mythtv/programs/mythbackend/filetransfer.cpp
--- mythtv-0.19/programs/mythbackend/filetransfer.cpp	2006-02-07 01:35:33.000000000 +1000
+++ mythtv/programs/mythbackend/filetransfer.cpp	2006-02-23 17:54:05.000000000 +1000
@@ -131,3 +131,9 @@ long long FileTransfer::GetFileSize(void
 
     return size;
 }
+
+void FileTransfer::SetTimeout(bool fast)
+{
+    rbuffer->SetTimeout(fast);
+}
+
diff -pruN mythtv-0.19/programs/mythbackend/filetransfer.h mythtv/programs/mythbackend/filetransfer.h
--- mythtv-0.19/programs/mythbackend/filetransfer.h	2006-02-07 01:35:33.000000000 +1000
+++ mythtv/programs/mythbackend/filetransfer.h	2006-02-23 17:54:05.000000000 +1000
@@ -35,6 +35,8 @@ class FileTransfer
 
     long long GetFileSize(void);
 
+    void SetTimeout(bool fast);
+
   private:
     bool readthreadlive;
     QMutex readthreadLock;
diff -pruN mythtv-0.19/programs/mythbackend/housekeeper.cpp mythtv/programs/mythbackend/housekeeper.cpp
--- mythtv-0.19/programs/mythbackend/housekeeper.cpp	2005-12-27 15:20:47.000000000 +1000
+++ mythtv/programs/mythbackend/housekeeper.cpp	2006-03-14 03:52:00.000000000 +1000
@@ -138,7 +138,6 @@ void HouseKeeper::RunHouseKeeping(void)
 
     while (1)
     {
-        VERBOSE(VB_IMPORTANT, "Running HouseKeeping");
         gContext->LogEntry("mythbackend", LP_DEBUG,
                            "Running housekeeping thread", "");
 
diff -pruN mythtv-0.19/programs/mythbackend/mainserver.cpp mythtv/programs/mythbackend/mainserver.cpp
--- mythtv-0.19/programs/mythbackend/mainserver.cpp	2006-01-29 09:49:24.000000000 +1000
+++ mythtv/programs/mythbackend/mainserver.cpp	2006-03-06 12:41:13.000000000 +1000
@@ -1919,11 +1919,8 @@ void MainServer::HandleGetPendingRecordi
     if (m_sched) {
         if (table == "") m_sched->getAllPending(strList);
         else {
-            // We need a different connection from the scheduler proper
-            // DDCon exists, although it's designed for other purposes.
-            MSqlQueryInfo dbconn = MSqlQuery::DDCon();
-            Scheduler *sched = new Scheduler(false, encoderList,
-                                             table, &dbconn, m_sched);
+            Scheduler *sched = new Scheduler(false, encoderList, 
+                                             table, m_sched);
             sched->FillRecordListFromDB(recordid);
             sched->getAllPending(strList);
             delete sched;
@@ -2940,6 +2937,12 @@ void MainServer::HandleFileTransferQuery
         long long ret = ft->Seek(curpos, pos, whence);
         encodeLongLong(retlist, ret);
     }
+    else if (command == "SET_TIMEOUT")
+    {
+        bool fast = slist[2].toInt();
+        ft->SetTimeout(fast);
+        retlist << "ok";
+    }
     else 
     {
         VERBOSE(VB_IMPORTANT, QString("Unknown command: %1").arg(command));
diff -pruN mythtv-0.19/programs/mythbackend/scheduler.cpp mythtv/programs/mythbackend/scheduler.cpp
--- mythtv-0.19/programs/mythbackend/scheduler.cpp	2006-02-09 16:27:56.000000000 +1000
+++ mythtv/programs/mythbackend/scheduler.cpp	2006-03-06 14:05:21.000000000 +1000
@@ -35,8 +35,7 @@ using namespace std;
 #define LOC_ERR QString("Scheduler, Error: ")
 
 Scheduler::Scheduler(bool runthread, QMap<int, EncoderLink *> *tvList,
-                     QString recordTbl, MSqlQueryInfo *databaseConnection,
-                     Scheduler *master_sched)
+                     QString recordTbl, Scheduler *master_sched)
 {
     hasconflicts = false;
     m_tvList = tvList;
@@ -48,8 +47,11 @@ Scheduler::Scheduler(bool runthread, QMa
         master_sched->getAllPending(&reclist);
     }
 
-    if (databaseConnection) dbConn = *databaseConnection;
-    else dbConn = MSqlQuery::SchedCon();
+    // Only the master scheduler should use SchedCon()
+    if (runthread)
+        dbConn = MSqlQuery::SchedCon();
+    else
+        dbConn = MSqlQuery::DDCon();
 
     recordTable = recordTbl;
 
@@ -1136,6 +1138,10 @@ void Scheduler::RunScheduler(void)
             
         if (reschedQueue.count())
         {
+            // We might have been inactive for a long time, so make
+            // sure our DB connection is fresh before continuing.
+            dbConn = MSqlQuery::SchedCon();
+
             gettimeofday(&fillstart, NULL);
             QString msg;
             while (reschedQueue.count())
@@ -1827,10 +1833,10 @@ void Scheduler::UpdateMatches(int record
         QString query = QString(
 "INSERT INTO recordmatch (recordid, chanid, starttime, manualid) "
 "SELECT RECTABLE.recordid, program.chanid, program.starttime, "
-" IF(search = %1, recordid, 0) "
-"FROM RECTABLE, program ").arg(kManualSearch) + fromclauses[clause] + QString(
-" INNER JOIN channel ON (channel.chanid = program.chanid) "
-"WHERE ") + whereclauses[clause] + QString(" AND channel.visible = 1 AND "
+" IF(search = %1, recordid, 0) ").arg(kManualSearch) + QString(
+"FROM (RECTABLE, program INNER JOIN channel "
+"      ON channel.chanid = program.chanid) ") + fromclauses[clause] + QString(
+" WHERE ") + whereclauses[clause] + QString(" AND channel.visible = 1 AND "
 "((RECTABLE.type = %1 " // allrecord
 "OR RECTABLE.type = %2 " // findonerecord
 "OR RECTABLE.type = %3 " // finddailyrecord
diff -pruN mythtv-0.19/programs/mythbackend/scheduler.h mythtv/programs/mythbackend/scheduler.h
--- mythtv-0.19/programs/mythbackend/scheduler.h	2006-02-08 07:53:46.000000000 +1000
+++ mythtv/programs/mythbackend/scheduler.h	2006-03-06 12:41:13.000000000 +1000
@@ -23,8 +23,7 @@ class Scheduler : public QObject
 {
   public:
     Scheduler(bool runthread, QMap<int, EncoderLink *> *tvList,
-              QString recordTbl = "record", MSqlQueryInfo *dbConnUse = NULL,
-              Scheduler *master_sched = NULL);
+              QString recordTbl = "record", Scheduler *master_sched = NULL);
     ~Scheduler();
 
     void Reschedule(int recordid);
diff -pruN mythtv-0.19/programs/mythcommflag/main.cpp mythtv/programs/mythcommflag/main.cpp
--- mythtv-0.19/programs/mythcommflag/main.cpp	2006-02-08 16:42:13.000000000 +1000
+++ mythtv/programs/mythcommflag/main.cpp	2006-02-28 16:58:05.000000000 +1000
@@ -895,9 +895,6 @@ int main(int argc, char *argv[])
         return COMMFLAG_EXIT_INVALID_CMDLINE;
     }
 
-    if (queueJobInstead)
-        return QueueCommFlagJob(chanid, starttime);
-
     if (copyToCutlist)
         return CopySkipListToCutList(chanid, starttime);
 
@@ -1009,7 +1006,10 @@ int main(int argc, char *argv[])
 
                 if ( allRecorded )
                 {
-                    FlagCommercials(chanid, starttime);
+                    if (queueJobInstead)
+                        QueueCommFlagJob(chanid, starttime);
+                    else
+                        FlagCommercials(chanid, starttime);
                 }
                 else
                 {
@@ -1063,7 +1063,12 @@ int main(int argc, char *argv[])
 
                             if ((flagStatus == COMM_FLAG_NOT_FLAGGED) &&
                                 (marksFound == 0))
-                                FlagCommercials(chanid, starttime);
+                            {
+                                if (queueJobInstead)
+                                    QueueCommFlagJob(chanid, starttime);
+                                else
+                                    FlagCommercials(chanid, starttime);
+                            }
                         }
                     }
                 }
diff -pruN mythtv-0.19/programs/mythfilldatabase/filldata.cpp mythtv/programs/mythfilldatabase/filldata.cpp
--- mythtv-0.19/programs/mythfilldatabase/filldata.cpp	2006-02-08 07:53:46.000000000 +1000
+++ mythtv/programs/mythfilldatabase/filldata.cpp	2006-05-12 07:07:54.000000000 +1000
@@ -337,7 +337,7 @@ void UpdateSourceIcons(int sourceid)
 
     MSqlQuery query(MSqlQuery::InitCon());
     query.prepare("SELECT ch.chanid, nim.url "
-            "FROM channel ch, callsignnetworkmap csm "
+            "FROM (channel ch, callsignnetworkmap csm) "
             "RIGHT JOIN networkiconmap nim ON csm.network = nim.network "
             "WHERE ch.callsign = csm.callsign AND "
             "(icon = :NOICON OR icon = '') AND ch.sourceid = :SOURCEID");
@@ -2174,7 +2174,8 @@ void handleChannels(int id, QValueList<C
                         0 /*service id*/, major,            minor,
                         false /*use on air guide*/, false /*hidden*/,
                         false /*hidden in guide*/,
-                        freqid,           localfile,        (*i).tvformat))
+                        freqid,           localfile,        (*i).tvformat,
+                        (*i).xmltvid))
                 {
                     cout << "### " << endl;
                     cout << "### Channel inserted" << endl;
@@ -3851,7 +3852,6 @@ int main(int argc, char *argv[])
              VERBOSE(VB_IMPORTANT, "Failed to fetch some program info");
              gContext->LogEntry("mythfilldatabase", LP_WARNING,
                                 "Failed to fetch some program info", "");
-             return FILLDB_EXIT_DB_ERROR;
         }
         else
             VERBOSE(VB_IMPORTANT, "Data fetching complete.");
diff -pruN mythtv-0.19/programs/mythfrontend/customrecord.cpp mythtv/programs/mythfrontend/customrecord.cpp
--- mythtv-0.19/programs/mythfrontend/customrecord.cpp	2006-01-22 14:16:48.000000000 +1000
+++ mythtv/programs/mythfrontend/customrecord.cpp	2006-03-06 14:05:21.000000000 +1000
@@ -149,7 +149,7 @@ CustomRecord::CustomRecord(MythMainWindo
     m_cfrom << "";
     m_csql << "program.stars >= 0.75 ";
 
-    m_clause->insertItem(tr("Person named in the credits"));
+    m_clause->insertItem(tr("Person named in the credits (Data Direct)"));
     m_cfrom << ", people, credits";
     m_csql << QString("people.name = 'Tom Hanks' \n"
                       "AND credits.person = people.person \n"
@@ -447,8 +447,8 @@ bool CustomRecord::checkSyntax(void)
     else
     {
         MSqlQuery query(MSqlQuery::InitCon());
-        query.prepare(QString("SELECT NULL FROM program,channel %1 WHERE\n%2") 
-                              .arg(from).arg(desc));
+        query.prepare(QString("SELECT NULL FROM (program,channel) "
+                              "%1 WHERE\n%2").arg(from).arg(desc));
 
         if (query.exec() && query.isActive())
         {
diff -pruN mythtv-0.19/programs/mythfrontend/networkcontrol.cpp mythtv/programs/mythfrontend/networkcontrol.cpp
--- mythtv-0.19/programs/mythfrontend/networkcontrol.cpp	2006-02-10 06:21:59.000000000 +1000
+++ mythtv/programs/mythfrontend/networkcontrol.cpp	2006-03-17 19:17:32.000000000 +1000
@@ -469,7 +469,7 @@ QString NetworkControl::processPlay(QStr
             message = "NETWORK_CONTROL SEEK BACKWARD";
         else if (tokens[2].contains(QRegExp("^\\d\\d:\\d\\d:\\d\\d$")))
         {
-            int hours = tokens[2].left(0).toInt();
+            int hours   = tokens[2].mid(0, 2).toInt();
             int minutes = tokens[2].mid(3, 2).toInt();
             int seconds = tokens[2].mid(6, 2).toInt();
             message = QString("NETWORK_CONTROL SEEK POSITION %1")
diff -pruN mythtv-0.19/programs/mythfrontend/playbackbox.cpp mythtv/programs/mythfrontend/playbackbox.cpp
--- mythtv-0.19/programs/mythfrontend/playbackbox.cpp	2006-02-08 03:21:33.000000000 +1000
+++ mythtv/programs/mythfrontend/playbackbox.cpp	2006-04-01 02:11:33.000000000 +1000
@@ -17,6 +17,7 @@
 #include <qsqldatabase.h>
 #include <qmap.h>
 
+#include <cmath>
 #include <unistd.h>
 
 #include <iostream>
@@ -140,6 +141,7 @@ PlaybackBox::PlaybackBox(BoxType ltype, 
       // Main Recording List support
       fillListTimer(new QTimer(this)),  connected(false),
       titleIndex(0),                    progIndex(0),
+      progsInDB(0),
       // Other state
       curitem(NULL),                    delitem(NULL),
       lastProgram(NULL),
@@ -261,7 +263,9 @@ PlaybackBox::PlaybackBox(BoxType ltype, 
     setNoErase();
     gContext->addListener(this);
 
-    if (!recGroupPassword.isEmpty() || (titleList.count() <= 1) || initialFilt)
+    if ((!recGroupPassword.isEmpty()) ||
+        ((titleList.count() <= 1) && (progsInDB > 0)) ||
+        (initialFilt))
         showRecGroupChooser();
 
     gContext->addCurrentLocation((type == Delete)? "DeleteBox":"PlaybackBox");
@@ -890,9 +894,13 @@ void PlaybackBox::updateVideo(QPainter *
         !playingSomething)
     {
         QSize size = drawVideoBounds.size();
+        float saspect = ((float)size.width()) / ((float)size.height());
+        float vaspect = previewVideoNVP->GetVideoAspect();
+        size.setHeight((int) ceil(size.height() * (saspect / vaspect)));
+        size.setHeight(((size.height() + 7) / 8) * 8);
+        size.setWidth( ((size.width()  + 7) / 8) * 8);
         const QImage &img = previewVideoNVP->GetARGBFrame(size);
-        uint xoff = max((size.width() - drawVideoBounds.width()) / 2, 0);
-        p->drawImage(drawVideoBounds.x() + xoff, drawVideoBounds.y(), img);
+        p->drawImage(drawVideoBounds.x(), drawVideoBounds.y(), img);
     }
 
     /* have we timed out waiting for nvp to start? */
@@ -1380,6 +1388,7 @@ bool PlaybackBox::FillList()
         asCache[asKey] = p->availableStatus;
     }
 
+    progsInDB = 0;
     titleList.clear();
     progLists.clear();
     // Clear autoDelete for the "all" list since it will share the
@@ -1402,6 +1411,7 @@ bool PlaybackBox::FillList()
         vector<ProgramInfo *>::iterator i = infoList->begin();
         for ( ; i != infoList->end(); i++)
         {
+            progsInDB++;
             p = *i;
             if ((((p->recgroup == recGroup) ||
                   ((recGroup == "All Programs") &&
@@ -4129,8 +4139,7 @@ void PlaybackBox::recGroupChooserListBox
     if (!recGroupListBox)
         return;
 
-    QString item = 
-        recGroupListBox->currentText().section('[', 0, 0).simplifyWhiteSpace();
+    QString item = recGroupListBox->currentText().section(" [", 0, 0);
 
     if (item.left(5) == "-----")
     {
@@ -4147,8 +4156,7 @@ void PlaybackBox::recGroupChooserListBox
 
 void PlaybackBox::setGroupFilter(void)
 {
-    recGroup =
-        recGroupListBox->currentText().section('[', 0, 0).simplifyWhiteSpace();
+    recGroup = recGroupListBox->currentText().section(" [", 0, 0);
 
     if (groupnameAsAllProg)
         groupDisplayName = recGroup;
diff -pruN mythtv-0.19/programs/mythfrontend/playbackbox.h mythtv/programs/mythfrontend/playbackbox.h
--- mythtv-0.19/programs/mythfrontend/playbackbox.h	2006-02-02 12:43:31.000000000 +1000
+++ mythtv/programs/mythfrontend/playbackbox.h	2006-02-28 11:06:40.000000000 +1000
@@ -337,6 +337,7 @@ class PlaybackBox : public MythDialog
     int                 progIndex;  ///< Index of selected item index on page
     QStringList         titleList;  ///< list of pages
     ProgramMap          progLists;  ///< lists of programs by page        
+    int                 progsInDB;  ///< total number of recordings in DB
 
     // Play List support
     QStringList         playList;   ///< list of selected items "play list"
diff -pruN mythtv-0.19/programs/mythfrontend/tv_schedule.xml mythtv/programs/mythfrontend/tv_schedule.xml
--- mythtv-0.19/programs/mythfrontend/tv_schedule.xml	2006-02-02 01:28:40.000000000 +1000
+++ mythtv/programs/mythfrontend/tv_schedule.xml	2006-03-11 10:52:28.000000000 +1000
@@ -26,7 +26,7 @@
       <alttext lang="CA">Guia</alttext>
       <alttext lang="DE">EPG</alttext>
       <alttext lang="DK">Guide</alttext>
-      <alttext lang="DK">DagskrÃ¡</alttext>
+      <alttext lang="IS">DagskrÃ¡</alttext>
       <alttext lang="NL">Gids</alttext>
       <alttext lang="SV">Guide</alttext>
       <alttext lang="JA">ã‚¬ã‚¤ãƒ‰</alttext>
diff -pruN mythtv-0.19/programs/mythtranscode/mpeg2fix.cpp mythtv/programs/mythtranscode/mpeg2fix.cpp
--- mythtv-0.19/programs/mythtranscode/mpeg2fix.cpp	2006-01-27 02:42:44.000000000 +1000
+++ mythtv/programs/mythtranscode/mpeg2fix.cpp	2006-03-07 11:49:33.000000000 +1000
@@ -1776,6 +1776,7 @@ int MPEG2fixup::Start()
 
         if (vFrame.count() && (file_end || vFrame.getLast()->isSequence))
         {
+            MPEG2frame *seqFrame;
             if (ptsIncrement != vFrame.first()->mpeg2_seq.frame_period / 300)
             {
                 VERBOSE(MPF_IMPORTANT,
@@ -1786,6 +1787,11 @@ int MPEG2fixup::Start()
             }
             displayFrame->toFirst();
 
+            // since we might reorder the frames when coming out of a cutpoint
+            // me need to save the first frame here, as it is gauranteed to
+            // have a sequence header.
+            seqFrame = vFrame.current();
+
             while (vFrame.current() != vFrame.getLast())
             {
                 bool ptsorder_eq_dtsorder = false;
@@ -1941,7 +1947,7 @@ int MPEG2fixup::Start()
 
                         if (! new_discard_state)
                         {
-                            AddSequence(markedFrame, vFrame.first());
+                            AddSequence(markedFrame, seqFrame);
                             RenumberFrames(frame_pos + Lreorder.at(),
                                             - GetFrameNum(markedFrame));
                         }
diff -pruN mythtv-0.19/programs/mythtv/main.cpp mythtv/programs/mythtv/main.cpp
--- mythtv-0.19/programs/mythtv/main.cpp	2006-01-05 01:45:55.000000000 +1000
+++ mythtv/programs/mythtv/main.cpp	2006-02-19 05:56:39.000000000 +1000
@@ -132,6 +132,7 @@ int main(int argc, char *argv[])
         ProgramInfo *pginfo = new ProgramInfo();
         pginfo->endts = QDateTime::currentDateTime().addSecs(-180);
         pginfo->pathname = filename;
+        pginfo->isVideo = true;
     
         tv->Playback(pginfo);
     }
diff -pruN mythtv-0.19/setup/backendsettings.cpp mythtv/setup/backendsettings.cpp
--- mythtv-0.19/setup/backendsettings.cpp	2005-12-30 04:16:07.000000000 +1000
+++ mythtv/setup/backendsettings.cpp	2006-04-13 00:21:41.000000000 +1000
@@ -1,6 +1,7 @@
 #include <cstdio>
 
 #include "backendsettings.h"
+#include "frequencies.h"
 #include "libmyth/mythcontext.h"
 #include "libmyth/settings.h"
 #include <unistd.h>
@@ -110,23 +111,10 @@ static GlobalComboBox *FreqTable()
 {
     GlobalComboBox *gc = new GlobalComboBox("FreqTable");
     gc->setLabel(QObject::tr("Channel frequency table"));
-    gc->addSelection("us-cable");
-    gc->addSelection("us-bcast");
-    gc->addSelection("us-cable-hrc");
-    gc->addSelection("us-cable-irc");
-    gc->addSelection("japan-bcast");
-    gc->addSelection("japan-cable");
-    gc->addSelection("europe-west");
-    gc->addSelection("europe-east");
-    gc->addSelection("italy");
-    gc->addSelection("newzealand");
-    gc->addSelection("australia");
-    gc->addSelection("ireland");
-    gc->addSelection("france");
-    gc->addSelection("china-bcast");
-    gc->addSelection("southafrica");
-    gc->addSelection("argentina");
-    gc->addSelection("australia-optus");
+
+    for (uint i = 0; chanlists[i].name; i++)
+        gc->addSelection(chanlists[i].name);
+
     gc->setHelpText(QObject::tr("Select the appropriate frequency table for "
                     "your system.  If you have an antenna, use a \"-bcast\" "
                     "frequency."));
