]> git.pld-linux.org Git - packages/mythtv.git/commitdiff
This commit was manufactured by cvs2git to create branch 'DEVEL'.
authorcvs2git <feedback@pld-linux.org>
Tue, 7 Oct 2008 15:00:01 +0000 (15:00 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Cherrypick from master 2007-11-11 11:41:08 UTC Elan Ruusamäe <glen@pld-linux.org> '- missing libs link':
    mythtv-branch.diff -> 1.3
    mythtv-configure.patch -> 1.3
    mythtv-dvdnav-shared.patch -> 1.2
    mythtv-ldconfig.patch -> 1.1
    mythtv-libs.patch -> 1.1
    mythtv-mythstream.patch -> 1.1
    mythtv-optflags.patch -> 1.2
Cherrypick from master 2006-02-05 14:36:18 UTC Elan Ruusamäe <glen@pld-linux.org> '- move programs not useful for users to sbin':
    mythtv-sbinpath.patch -> 1.1
Cherrypick from master 2008-10-07 15:00:01 UTC shadzik <shadzik@pld-linux.org> '- ffmpeg suuport fix (new API)':
    mythtv.spec -> 1.73

mythtv-branch.diff [new file with mode: 0644]
mythtv-configure.patch [new file with mode: 0644]
mythtv-dvdnav-shared.patch [new file with mode: 0644]
mythtv-ldconfig.patch [new file with mode: 0644]
mythtv-libs.patch [new file with mode: 0644]
mythtv-mythstream.patch [new file with mode: 0644]
mythtv-optflags.patch [new file with mode: 0644]
mythtv-sbinpath.patch [new file with mode: 0644]
mythtv.spec [new file with mode: 0644]

diff --git a/mythtv-branch.diff b/mythtv-branch.diff
new file mode 100644 (file)
index 0000000..4b5108a
--- /dev/null
@@ -0,0 +1,7356 @@
+Index: mythplugins/mythweb/themes/wml/header.php
+===================================================================
+--- mythplugins/mythweb/themes/wml/header.php  (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/themes/wml/header.php  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -26,4 +26,4 @@
+ <p><a href="<?php echo root ?>tv/upcoming"><?php echo t('Upcoming Recordings') ?></a></p>
+ <p><a href="<?php echo root ?>tv/recorded"><?php echo t('Recorded Programs') ?></a></p>
+ <p><a href="<?php echo root ?>tv/search"><?php echo t('Search') ?></a></p>
+-<p><a href="<?php echo root ?>status?xml"><?php echo t('Backend Status') ?></a></p>
++<p><a href="<?php echo root ?>status/xml"><?php echo t('Backend Status') ?></a></p>
+Index: mythplugins/mythweb/themes/default/weather/weather.php
+===================================================================
+--- mythplugins/mythweb/themes/default/weather/weather.php     (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/themes/default/weather/weather.php     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -93,13 +93,13 @@
+                 $tomorrow = date("m/d/Y", mktime(0, 0, 0, date("m")  , date("d")+1, date("Y")));
+                 switch($forecast->dayofweek) {
++                    case 0:  $day = t('Sunday');        break;
+                     case 1:  $day = t('Monday');        break;
+                     case 2:  $day = t('Tuesday');       break;
+                     case 3:  $day = t('Wednesday');     break;
+                     case 4:  $day = t('Thursday');      break;
+                     case 5:  $day = t('Friday');        break;
+                     case 6:  $day = t('Saturday');      break;
+-                    case 7:  $day = t('Sunday');        break;
+                     default: $day = $forecast->date;    break;
+                 }
+Index: mythplugins/mythweb/themes/default/music/music.php
+===================================================================
+--- mythplugins/mythweb/themes/default/music/music.php (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/themes/default/music/music.php (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -164,10 +164,12 @@
+     function print_header($filterPlaylist,$filterArtist,$filterAlbum,$filterGenre) {
+         $this->filterPlaylist=$filterPlaylist;
+-// Set the desired page title
+-    $page_title = 'MythWeb - '.t('Music');
+-// Print the page header
+-    require_once theme_dir.'/header.php';
++    // Set the desired page title
++        global $page_title, $Modules, $headers;
++        $page_title = 'MythWeb - '.t('Music');
++    // Print the page header
++        require_once theme_dir.'/header.php';
++
+         printf("<form  action=\"".root."music\" method=\"GET\" >\n");
+         printf("<input type=\"hidden\" name=\"mode\" value=\"music\" />\n");
+Index: mythplugins/mythweb/themes/default/tv/detail.php
+===================================================================
+--- mythplugins/mythweb/themes/default/tv/detail.php   (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/themes/default/tv/detail.php   (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -51,7 +51,7 @@
+ <?php   } ?>
+             <div id="program_title">
+                 <h1>
+-                    <a href="<?php echo root ?>tv/search/<?php echo urlencode($program->title) ?>&search_title=yes"><?php echo $schedule->title ?></a>
++                    <a href="<?php echo root ?>tv/search/<?php echo str_replace('%2F', '/', rawurlencode($schedule->title)) ?>?search_title=1"><?php echo $schedule->title ?></a>
+                 </h1>
+                 <div id="program_time">
+ <?php
+Index: mythplugins/mythweb/includes/mythbackend.php
+===================================================================
+--- mythplugins/mythweb/includes/mythbackend.php       (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/includes/mythbackend.php       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -15,10 +15,6 @@
+ // The character string used by the backend to separate records
+     define('backend_sep', '[]:[]');
+-// A couple of global variables to keep duplicate queries to a minimum
+-    $Scheduled_Recordings = array();
+-    $Recorded_Programs    = array();
+-
+ // MYTH_PROTO_VERSION is defined in libmyth in mythtv/libs/libmyth/mythcontext.h
+ // and should be the current MythTV protocol version.
+     define('MYTH_PROTO_VERSION', 26);
+Index: mythplugins/mythweb/includes/programs.php
+===================================================================
+--- mythplugins/mythweb/includes/programs.php  (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/includes/programs.php  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -81,7 +81,9 @@
+ /**/
+     function &load_all_program_data($start_time, $end_time, $chanid = false, $single_program = false, $extra_query = '') {
+         global $Channels, $db;
+-    // Make a local hash of channel chanid's with references to the actual channel data
++    // Make a local hash of channel chanid's with references to the actual
++    // channel data (Channels are not indexed by anything in particular, so
++    // that the user can sort by chanid or channum).
+         $channel_hash = array();
+     // An array (that later gets converted to a string) containing the id's of channels we want to load
+         $these_channels = array();
+@@ -104,7 +106,7 @@
+             load_all_channels();
+     // Scan through the channels array and actually assign those references
+         foreach (array_keys($Channels) as $key) {
+-            $channel_hash[$Channels[$key]->chanid] = &$Channels[$key];
++            $channel_hash[$Channels[$key]->chanid] =& $Channels[$key];
+         // Reinitialize the programs array for this channel
+             $Channels[$key]->programs = array();
+         // Keep track of this channel id in case we're only grabbing info for certain channels - workound included to avoid blank chanid's
+@@ -130,11 +132,13 @@
+                        LEFT JOIN programrating USING (chanid, starttime)
+                        LEFT JOIN oldrecorded
+                                  ON oldrecorded.recstatus IN (-3, 11)
+-                                    AND IF(oldrecorded.programid OR oldrecorded.seriesid,
++                                    AND IF(oldrecorded.programid AND oldrecorded.seriesid,
+                                            oldrecorded.programid = program.programid
+                                              AND oldrecorded.seriesid = program.seriesid,
+-                                           oldrecorded.title = program.title
+-                                             AND oldrecorded.subtitle = program.subtitle
++                                           oldrecorded.title AND oldrecorded.subtitle
++                                             AND oldrecorded.description
++                                             AND oldrecorded.title       = program.title
++                                             AND oldrecorded.subtitle    = program.subtitle
+                                              AND oldrecorded.description = program.description
+                                           )
+                        LEFT JOIN channel ON program.chanid = channel.chanid
+@@ -156,8 +160,12 @@
+     // The extra query, if there is one
+         if ($extra_query)
+             $query .= ' AND '.$extra_query;
+-    // Group, sort and query
++    // Group and sort
+         $query .= ' GROUP BY program.chanid, program.starttime ORDER BY program.starttime';
++    // Limit
++        if ($single_program)
++            $query .= ' LIMIT 1';
++    // Query
+         $sh = $db->query($query,
+                          star_character, max_stars, max_stars);
+     // No results
+@@ -188,12 +196,8 @@
+     // Cleanup
+         $sh->finish();
+     // If channel-specific information was requested, return an array of those programs, or just the first/only one
+-        if ($chanid) {
+-            if ($single_program)
+-                return $channel_hash[$chanid]->programs[0];
+-            else
+-                return $channel_hash[$chanid]->programs;
+-        }
++        if ($chanid && $single_program)
++            return $these_programs[0];
+     // Just in case, return an array of all programs found
+         return $these_programs;
+     }
+@@ -272,18 +276,18 @@
+             $this->endtime     = $data[12];  # show end-time
+         // Is this a previously-recorded program?  Calculate the filesize
+             if (!empty($this->filename)) {
+-                $this->filesize = ($fs_high + ($fs_low < 0)) * 4294967296 + $fs_low;
+-            }
+-        // Ah, a scheduled recording - let's load more information about it, to be parsed in below
+-            elseif ($this->chanid) {
+-                unset($this->filename);
+-            // Kludge to avoid redefining the object, which doesn't work in php5
+-                $tmp = @get_object_vars(load_one_program($this->starttime, $this->chanid));
+-                if (is_array($tmp) && count($tmp) > 0) {
+-                    foreach ($tmp as $key => $value) {
+-                        $this->$key = $value;
+-                    }
++                if (function_exists('gmp_add')) {
++                // GMP functions should work better with 64 bit numbers.
++                    $size = gmp_add($fs_low,
++                                     gmp_mul('4294967296',
++                                             gmp_add($fs_high, $fs_low < 0 ? '1' : '0'))
++                                   );
++                    $this->filesize = gmp_strval($size);
+                 }
++                else {
++                // This is inaccurate, but it's the best we can get without GMP.
++                    $this->filesize = ($fs_high + ($fs_low < 0)) * 4294967296 + $fs_low;
++                }
+             }
+         // Load the remaining info we got from mythbackend
+             $this->title           = $data[0];                  # program name/title
+@@ -291,14 +295,14 @@
+             $this->description     = $data[2];                  # episode description
+             $this->category        = $data[3];
+             #$chanid               = $data[4];   # Extracted a few lines earlier
+-            #$channum              = $data[5];
+-            #$callsign             = $data[6];
++            $this->channum         = $data[5];
++            $this->callsign        = $data[6];
+             $this->channame        = $data[7];
+             #$pathname             = $data[8];   # Extracted a few lines earlier
+             #$fs_high              = $data[9];   # Extracted a few lines earlier
+             #$fs_low               = $data[10];  # Extracted a few lines earlier
+-            #$starttime            = $data[11];  # Extracted a few lines earlier
+-            #$endtime              = $data[12];  # Extracted a few lines earlier
++            #$this->starttime      = $data[11];  # Extracted a few lines earlier
++            #$this->endtime        = $data[12];  # Extracted a few lines earlier
+             $this->hostname        = $data[16];
+             #$this->sourceid       = $data[17];
+             $this->cardid          = $data[18];
+@@ -320,9 +324,9 @@
+             $this->programid       = $data[34];
+             $this->lastmodified    = $data[35];
+             $this->recpriority     = $data[36];
+-            #$this->airdate        = $data[37];
+-            #$this->hasairdate     = $data[38];
+-            $this->timestretch     = $program_data[39];
++            $this->airdate         = date('Y-m-d', $data[37]);
++            $this->hasairdate      = $data[38];
++            $this->timestretch     = $data[39];
+             $this->recpriority2    = $data[40];
+         // Assign the program flags
+             $this->has_commflag = ($progflags & 0x01) ? true : false;    // FL_COMMFLAG  = 0x01
+@@ -363,8 +367,8 @@
+             $this->title_pronounce         = $data['title_pronounce'];
+             $this->recstatus               = $data['recstatus'];
+-            if ($program_data['tsdefault']) {
+-                $this->timestretch = $program_data['tsdefault'];
++            if ($data['tsdefault']) {
++                $this->timestretch = $data['tsdefault'];
+             } else {
+                 $this->timestretch = 1.0;
+             }
+@@ -387,12 +391,14 @@
+         // Now we really should scan the $Channel array and add a link to this program's channel
+             foreach (array_keys($Channels) as $key) {
+                 if ($Channels[$key]->chanid == $this->chanid) {
+-                    $this->channel = &$Channels[$key];
++                    $this->channel =& $Channels[$key];
+                     break;
+                 }
+             }
++        // Not found
++            if (!$this->channel)
++                $this->channel =& load_one_channel($this->chanid);
+         }
+-
+     // Calculate the duration
+         if ($this->recendts)
+             $this->length = $this->recendts - $this->recstartts;
+Index: mythplugins/mythweb/includes/utils.php
+===================================================================
+--- mythplugins/mythweb/includes/utils.php     (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/includes/utils.php     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -276,7 +276,7 @@
+         static $first_run=true;
+         if($first_run) {
+             $first_run=false;
+-            echo '<script type="text/javascript" src="/js/debug.js"></script>';
++            echo '<script type="text/javascript" src="'.root.'js/debug.js"></script>';
+         }
+     // Put our data into a string
+         if (is_array($data) || is_object($data))
+Index: mythplugins/mythweb/includes/init.php
+===================================================================
+--- mythplugins/mythweb/includes/init.php      (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/includes/init.php      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -16,28 +16,15 @@
+  *
+ /**/
+-/**
+- * $Path is an array of PATH_INFO passed into the script via mod_rewrite or some
+- * other lesser means.  It contains most of the information required for
+- * figuring out what functions the user wants to access.
+- *
+- * @global  array   $GLOBALS['Path']
+- * @name    $Path
+-/**/
+-    global $Path;
+-    $Path = explode('/', preg_replace('/^\/+/',   '',    // Remove leading slashes
+-                         preg_replace('/[\s]+/', ' ',    // Convert extra whitespace
+-                                                         // Grab the path info from various different places.
+-                             array_key_exists('PATH_INFO', $_SERVER)
+-                             && $_SERVER['PATH_INFO']
+-                                ? $_SERVER['PATH_INFO']
+-                                : (array_key_exists('PATH_INFO', $_ENV)
+-                                   && $_ENV['PATH_INFO']
+-                                    ? $_ENV['PATH_INFO']
+-                                    : $_GET['PATH_INFO']
+-                                  )
+-                         ))
+-                   );
++// mod_redirect can do some weird things when php is run in cgi mode
++    $keys = preg_grep('/^REDIRECT_/', array_keys($_SERVER));
++    if (!empty($keys)) {
++        foreach ($keys as $key) {
++            $key = substr($key, 9);
++            if (!array_key_exists($key, $_SERVER))
++                $_SERVER[$key] = $_SERVER["REDIRECT_$key"];
++        }
++    }
+ // Clean the document root variable and make sure it doesn't have a trailing slash
+     $_SERVER['DOCUMENT_ROOT'] = preg_replace('/\/+$/', '', $_SERVER['DOCUMENT_ROOT']);
+@@ -94,6 +81,29 @@
+         exit;
+     }
++/**
++ * $Path is an array of PATH_INFO passed into the script via mod_rewrite or some
++ * other lesser means.  It contains most of the information required for
++ * figuring out what functions the user wants to access.
++ *
++ * @global  array   $GLOBALS['Path']
++ * @name    $Path
++/**/
++    global $Path;
++    $Path = explode('/', preg_replace('/^\/+/',   '',    // Remove leading slashes
++                         preg_replace('/[\s]+/', ' ',    // Convert extra whitespace
++                                                         // Grab the path info from various different places.
++                             array_key_exists('PATH_INFO', $_SERVER)
++                             && $_SERVER['PATH_INFO']
++                                ? $_SERVER['PATH_INFO']
++                                : (array_key_exists('PATH_INFO', $_ENV)
++                                   && $_ENV['PATH_INFO']
++                                    ? $_ENV['PATH_INFO']
++                                    : $_GET['PATH_INFO']
++                                  )
++                         ))
++                   );
++
+ // Load the database connection routines
+     require_once 'includes/db.php';
+Index: mythplugins/mythweb/includes/mobile.php
+===================================================================
+--- mythplugins/mythweb/includes/mobile.php    (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/includes/mobile.php    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -74,58 +74,56 @@
+      * If you don't know the screensize of some mobile terminal then use
+      * an empty array or approximate dimensions.
+      */
+-    $mobiles = array(/* Phones using the Series 60 platform, e.g. Nokia 3650 and 6600. */
+-             'Series 60' => array('width' => 176, 'height' => 208),
+-             'Series60' => array('width' => 176, 'height' => 208),
+-             'C500' => array('width'=>176, 'height'=> 220), // SPV C500
++    $mobiles = array(
++                /* Phones using the Series 60 platform, e.g. Nokia 3650 and 6600. */
++                     'Series 60' => array('width' => 176, 'height' => 208),
++                     'Series60'  => array('width' => 176, 'height' => 208),
++                     'C500'      => array('width'=>176, 'height'=> 220), // SPV C500
++                /* Phones using the Series 90 platform, e.g. Nokia 7710. */
++                     'Series 90' => array('width' => 640, 'height' => 320),
++                     'Series90' => array('width' => 640, 'height' => 320),
++                /* The following strings are added for the Palm browser WebPro
++                 * WebPro sometimes supplies the screen dimensions, but sometimes not
++                 * but we try to detect the best as possible */
++                     '240x320'    => array('width' => 240, 'height' => 320), // PocketPC IE
++                     '320x320'    => array('width' => 320, 'height' => 320), // For all Palm Tungsten models
++                     '320x480'    => array('width' => 320, 'height' => 480), // For Palm Tungsten T
++                     '480x320'    => array('width' => 480, 'height' => 320), // For Palm Tungsten T
++                     '320x480x16' => array('width' => 320, 'height' => 480), // For Palm Tungsten T
++                     '480x320x16' => array('width' => 480, 'height' => 320), // For Palm Tungsten T
++                     '320x320x16' => array('width' => 320, 'height' => 320),
++                     'WebPro'     => array('width' => 320, 'height' => 320), // For all Palm Tungsten models
++                 /* A generic mobile phone using Symbian OS. All Symbian phones don't
++                  * necessarily have the same screen size so if you want to include
++                  * some specific Symbian phones then place them above this line. */
++                     'Symbian' => array('width' => 176, 'height' => 208),
+-             /* Phones using the Series 90 platform, e.g. Nokia 7710. */
+-             'Series 90' => array('width' => 640, 'height' => 320),
+-             'Series90' => array('width' => 640, 'height' => 320),
++                     'Nokia' => array(), // Nokia phones and emulators
++                     'Eric' => array(), // Ericsson WAP phones and emulators
++                     'WapI' => array(), // Ericsson WapIDE 2.0
++                     'MC21' => array(), // Ericsson MC218
++                     'AUR ' => array(), // Ericsson R320
++                     'R380' => array(), // Ericsson R380
++                     'UP.B' => array(), // UP.Browser
++                     'WinW' => array(), // WinWAP browser
++                     'UPG1' => array(), // UP.SDK 4.0
++                     'upsi' => array(), // another kind of UP.Browser ??
++                     'QWAP' => array(), // unknown QWAPPER browser
++                     'Jigs' => array(), // unknown JigSaw browser
++                     'Java' => array(), // unknown Java based browser
++                     'Alca' => array(), // unknown Alcatel-BE3 browser (UP based?)
++                     'MITS' => array(), // unknown Mitsubishi browser
++                     'MOT-' => array(), // unknown browser (UP based?)
++                     'My S' => array(), // unknown Ericsson devkit browser ?
++                     'WAPJ' => array(), // Virtual WAPJAG www.wapjag.de
++                     'fetc' => array(), // fetchpage.cgi Perl script from www.wapcab.de
++                     'ALAV' => array(), // yet another unknown UP based browser ?
++                     'Wapa' => array(), // another unknown browser (Web based "Wapalyzer"?)
++                     'LGE-' => array(), // LG phones
+-           /* The following strings are added for the Palm browser WebPro
+-              * WebPro sometimes supplies the screen dimensions, but sometimes not
+-            * but we try to detect the best as possible
+-              */
+-           '320x480' => array('width' => 320, 'height' => 480), // For Palm Tungsten T
+-           '480x320' => array('width' => 480, 'height' => 320), // For Palm Tungsten T
+-           '320x320' => array('width' => 320, 'height' => 320), // For all Palm Tungsten models
+-           '320x480x16' => array('width' => 320, 'height' => 480), // For Palm Tungsten T
+-           '480x320x16' => array('width' => 480, 'height' => 320), // For Palm Tungsten T
+-           '320x320x16' => array('width' => 320, 'height' => 320),
+-           'WebPro' => array('width' => 320, 'height' => 320), // For all Palm Tungsten models
+-
+-             /* A generic mobile phone using Symbian OS. All Symbian phones don't
+-              * necessarily have the same screen size so if you want to include
+-              * some specific Symbian phones then place them above this line. */
+-             'Symbian' => array('width' => 176, 'height' => 208),
+-
+-             'Nokia' => array(), // Nokia phones and emulators
+-             'Eric' => array(), // Ericsson WAP phones and emulators
+-             'WapI' => array(), // Ericsson WapIDE 2.0
+-             'MC21' => array(), // Ericsson MC218
+-             'AUR ' => array(), // Ericsson R320
+-             'R380' => array(), // Ericsson R380
+-             'UP.B' => array(), // UP.Browser
+-             'WinW' => array(), // WinWAP browser
+-             'UPG1' => array(), // UP.SDK 4.0
+-             'upsi' => array(), // another kind of UP.Browser ??
+-             'QWAP' => array(), // unknown QWAPPER browser
+-             'Jigs' => array(), // unknown JigSaw browser
+-             'Java' => array(), // unknown Java based browser
+-             'Alca' => array(), // unknown Alcatel-BE3 browser (UP based?)
+-             'MITS' => array(), // unknown Mitsubishi browser
+-             'MOT-' => array(), // unknown browser (UP based?)
+-             'My S' => array(), // unknown Ericsson devkit browser ?
+-             'WAPJ' => array(), // Virtual WAPJAG www.wapjag.de
+-             'fetc' => array(), // fetchpage.cgi Perl script from www.wapcab.de
+-             'ALAV' => array(), // yet another unknown UP based browser ?
+-             'Wapa' => array(), // another unknown browser (Web based "Wapalyzer"?)
+-             'LGE-' => array(), // LG phones
+-
+-             /* For debugging: you can try out the mobile mode without a mobile phone.
+-              * Replace 'Opera' with your browser. Comment out for release version. */
+-             //'Opera' => array('width' => 176, 'height' => 208)
++                 /* For debugging: you can try out the mobile mode without a mobile phone.
++                  * Replace 'Opera' with your browser. Comment out for release version. */
++                     //'Opera' => array('width' => 176, 'height' => 208)
+              );
+     /* Scan through $mobiles and try to find matching user agent. */
+Index: mythplugins/mythweb/includes/recording_schedules.php
+===================================================================
+--- mythplugins/mythweb/includes/recording_schedules.php       (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/includes/recording_schedules.php       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -68,10 +68,14 @@
+ // Cleanup
+     mysql_free_result($result);
++// Initialize
++    global $Scheduled_Recordings, $Num_Conflicts, $Num_Scheduled;
++    $Scheduled_Recordings = array();
++    $Num_Conflicts        = 0;
++    $Num_Scheduled        = 0;
++
+ // Load all of the scheduled recordings.  We will need them at some point, so we
+ // might as well get it overwith here.
+-    global $Scheduled_Recordings, $Num_Conflicts, $Num_Scheduled;
+-    $Scheduled_Recordings = array();
+     foreach (get_backend_rows('QUERY_GETALLPENDING', 2) as $key => $program) {
+     // The offset entry
+         if ($key === 'offset') {
+Index: mythplugins/mythweb/includes/session.php
+===================================================================
+--- mythplugins/mythweb/includes/session.php   (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/includes/session.php   (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -19,8 +19,8 @@
+ // Start the session
+     session_name('mythweb_id');
+-    session_set_cookie_params(60 * 60 * 30, '/');       // 30 day timeout on cookies
+-    ini_set('session.gc_maxlifetime', 60 * 60 * 30);    // ... and sessions
++    session_set_cookie_params(60 * 60 * 24 * 365, '/');     // 1 year timeout on cookies
++    ini_set('session.gc_maxlifetime', 60 * 60 * 24 * 30);   // 30 day timeout on sessions
+     session_set_save_handler('sess_do_nothing', 'sess_do_nothing', 'sess_read', 'sess_write', 'sess_destroy', 'sess_gc');
+     session_start();
+Index: mythplugins/mythweb/modules/weather/handler.php
+===================================================================
+--- mythplugins/mythweb/modules/weather/handler.php    (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/modules/weather/handler.php    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -222,8 +222,10 @@
+     $data = explode("|", $data);
+     for($i = 0;$i<5;$i++) {
+-        $forecast = new Forecast($data[5 + $i],$data[$i]);
+-        $forecast->dayofweek = $data[$i];
++      # mktime uses 0-6;  msnbc gives us 1-7;  adjust msnbc to match mktime
++      $dayofweek = $data[$i] - 1;
++        $forecast = new Forecast($data[5 + $i],$dayofweek);
++        $forecast->dayofweek = $dayofweek;
+         list($forecast->DescImage,$forecast->DescText) = getImageAndDescFromId($data[15 + $i]);
+         $forecast->DescImage = (strlen($forecast->DescImage) > 0) ? $forecast->DescImage : "unknown.png";
+         $forecast->DescText = (strlen($forecast->DescText) > 0) ? $forecast->DescText : t('Unknown') . " (" . $data[15+$i] . ")";
+Index: mythplugins/mythweb/modules/status/handler.php
+===================================================================
+--- mythplugins/mythweb/modules/status/handler.php     (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/modules/status/handler.php     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -18,14 +18,17 @@
+     $masterhost = get_backend_setting('MasterServerIP');
+     $statusport = get_backend_setting('BackendStatusPort');
++// XML mode?
++    $xml_param = ($Path[1] == 'xml') ? '/xml' : '';
++
+ // Make sure the content is interpreted as UTF-8
+     header('Content-Type:  text/html; charset=UTF-8');
+ // Load the status page
+     if (function_exists('file_get_contents'))
+-        $status = file_get_contents("http://$masterhost:$statusport");
++        $status = file_get_contents("http://$masterhost:$statusport$xml_param");
+     else
+-        $status = implode("\n", file("http://$masterhost:$statusport"));
++        $status = implode("\n", file("http://$masterhost:$statusport$xml_param"));
+ // Extract the page title
+     preg_match('#<title>(.+?)</title>#s', $status, $title);
+Index: mythplugins/mythweb/modules/backend_log/handler.php
+===================================================================
+--- mythplugins/mythweb/modules/backend_log/handler.php        (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/modules/backend_log/handler.php        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -16,7 +16,7 @@
+ // Where to start searching from
+     $_GET['start'] = intVal($_GET['start']);
+     if ($_GET['start'] < 1)
+-        $_GET['start'] = 1;
++        $_GET['start'] = 0;
+ // How many entries to show?
+     $_GET['show'] = intVal($_GET['show']);
+Index: mythplugins/mythweb/modules/tv/upcoming.php
+===================================================================
+--- mythplugins/mythweb/modules/tv/upcoming.php        (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/modules/tv/upcoming.php        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -103,8 +103,9 @@
+                         continue;
+                 }
+             // Skip deactivated shows?
+-                elseif (!$_SESSION['scheduled_recordings']['disp_deactivated']) {
+-                    continue;
++                elseif ($show->recstatus != 'Recording') {
++                    if (!$_SESSION['scheduled_recordings']['disp_deactivated'])
++                        continue;
+                 }
+             // Assign a reference to this show to the various arrays
+                 $all_shows[] =& $Scheduled_Recordings[$channum][$starttime][$key];
+Index: mythplugins/mythweb/modules/tv/recorded.php
+===================================================================
+--- mythplugins/mythweb/modules/tv/recorded.php        (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/modules/tv/recorded.php        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -128,9 +128,21 @@
+                 continue;
+         // Get the length (27 == recendts; 26 == recstartts)
+             $length = $record[27] - $record[26];
+-        // Keep track of the total time and disk space used
++        // Keep track of the total time and disk space used (9 == fs_high; 10 == fs_low)
+             $Total_Time += $length;
+-            $Total_Used += ($record[9] + ($record[10] < 0)) * 4294967296 + $record[10];  // 9 == fs_high; 10 == fs_low;
++            if (function_exists('gmp_add')) {
++            // GMP functions should work better with 64 bit numbers.
++                $size = gmp_add($record[10],
++                                gmp_mul('4294967296',
++                                        gmp_add($record[9], $record[10] < 0 ? '1' : '0')
++                                       )
++                               );
++                $Total_Used = gmp_strval(gmp_add($Total_Used, $size));
++            }
++            else {
++            // This is inaccurate, but it's the best we can get without GMP.
++                $Total_Used += ($record[9] + ($record[10] < 0)) * 4294967296 + $record[10];
++            }
+         // keep track of their names and how many episodes we have recorded
+             $Total_Programs++;
+             $Groups[$record[30]]++;
+@@ -223,8 +235,28 @@
+ // How much free disk space on the backend machine?
+     list($size_high, $size_low, $used_high, $used_low) = explode(backend_sep, backend_command('QUERY_FREE_SPACE'));
+-    define(disk_size, (($size_high + ($size_low < 0)) * 4294967296 + $size_low) * 1024);
+-    define(disk_used, (($used_high + ($used_low < 0)) * 4294967296 + $used_low) * 1024);
++    if (function_exists('gmp_add')) {
++    // GMP functions should work better with 64 bit numbers.
++        $size = gmp_mul('1024',
++                        gmp_add($size_low,
++                                gmp_mul('4294967296',
++                                        gmp_add($size_high, $size_low < 0 ? '1' : '0'))
++                               )
++                       );
++        define(disk_size, gmp_strval($size));
++        $size = gmp_mul('1024',
++                        gmp_add($used_low,
++                                gmp_mul('4294967296',
++                                        gmp_add($used_high, $used_low < 0 ? '1' : '0'))
++                               )
++                       );
++        define(disk_used, gmp_strval($size));
++    }
++    else {
++    // This is inaccurate, but it's the best we can get without GMP.
++        define(disk_size, (($size_high + ($size_low < 0)) * 4294967296 + $size_low) * 1024);
++        define(disk_used, (($used_high + ($used_low < 0)) * 4294967296 + $used_low) * 1024);
++    }
+ // Load the class for this page
+     require_once theme_dir.'tv/recorded.php';
+Index: mythplugins/mythweb/.htaccess
+===================================================================
+--- mythplugins/mythweb/.htaccess      (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/.htaccess      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -22,6 +22,7 @@
+ #    AuthName           "MythTV"
+ #    AuthDigestFile     /var/www/htdigest
+ #    Require            valid-user
++#    BrowserMatch       "MSIE"      AuthDigestEnableQueryStringHack=On
+ # MythTV now uses the correct file suffix for mpeg files, so all .nuv files
+ # should actually be NuppleVideo.  However, apache probably doesn't know what
+@@ -66,8 +67,6 @@
+         php_value memory_limit                  32M
+-        php_value session.save_path             php_sessions
+-
+         php_value output_buffering              4096
+         php_value register_globals              0
+         php_value magic_quotes_gpc              0
+Index: mythplugins/mythweb/js/debug.js
+===================================================================
+--- mythplugins/mythweb/js/debug.js    (.../tags/release-0-19) (revision 0)
++++ mythplugins/mythweb/js/debug.js    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -0,0 +1,24 @@
++/**
++ * A random assortment of javascript debug routines
++ *
++ * @url         $URL$
++ * @date        $Date$
++ * @version     $Revision$
++ * @author      $Author$
++ * @copyright   Silicon Mechanics
++ * @license     LGPL
++ *
++ * @package     SiMech
++ * @subpackage  Javascript
++ *
++/**/
++
++    var debug_window_handle;
++// Create a debug window and debug into it
++    function debug_window(string) {
++        if (!debug_window_handle || debug_window_handle.closed) {
++            debug_window_handle = window.open('', 'Debug Window','scrollbars, resizable, width=400, height=600');
++            debug_window_handle.document.write('<html><body style="font-size: 9pt; background-color: #f88;">');
++        }
++        debug_window_handle.document.write('<pre>'+string+'</pre><hr>');
++    }
+
+Property changes on: mythplugins/mythweb/js/debug.js
+___________________________________________________________________
+Name: svn:eol-style
+   + native
+Name: svn:mime-type
+   + text/x-javascript
+Name: svn:keywords
+   + Date Revision Author HeadURL
+
+Index: mythplugins/mythweb/js/browser.js
+===================================================================
+--- mythplugins/mythweb/js/browser.js  (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/js/browser.js  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -215,14 +215,18 @@
+     browser.is_css = (document.body  && document.body.style)
+     browser.is_w3c = (browser.is_css && browser.getElementById)
+-// Cookie support
+-    var tmp = document.cookie;
+-      document.cookie = 'cookies=true';
+-      browser.cookies = (document.cookie) ? true : false;
+-    document.cookie = tmp;
++// Cookie support -- only create a cookie if there isn't one already.  It seems
++// that doing this can override the exipiration info in existing cookies.
++    browser.cookies = (document.cookie) ? true : false;
++    if (!browser.cookies) {
++        var tmp = document.cookie;
++        document.cookie = 'cookie_test=true';
++        browser.cookies = (document.cookie) ? true : false;
++        document.cookie = tmp;
++    }
+ // Java support
+-      browser.java = navigator.javaEnabled();
++    browser.java = navigator.javaEnabled();
+ /****************************** Plugin Support ******************************/
+Index: mythplugins/mythweb/README
+===================================================================
+--- mythplugins/mythweb/README (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweb/README (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -1,18 +1,12 @@
+ This is the README file for the MythWeb package.
+-January 17, 2006
++March 6, 2006
+-Version: .19 pre
+-(c) 2002-2006  Thor Sigvaldason <mythtv(a)lamedomainname(o)com>
++Version: .19
++(c) 2002-2006  Chris Petersen   <mythweb(a)forevermore(o)net>
+                Isaac Richards   <ijr(a)po(o)cwru(o)edu>
+-               Chris Petersen   <mythweb(a)forevermore(o)net>
++               Thor Sigvaldason <mythtv(a)lamedomainname(o)com>
++               and others... (see mythtv.org commit logs for details)
+-with contributions from many people including:
+-
+-Michael Kedl   <kedlm(a)knology(o)net>
+-Jonathan Kolb  <jkolb(a)greyshift(o)net
+-Ed Wildgoose   <edward(o)wildgoose(a)frmhedge(o)com>
+-Kenneth Aafloy <ke-aa(a)frisurf(o)no>
+-
+ MythWeb is distributed under the GNU GENERAL PUBLIC LICENSE version 2, and where
+ noted with the @license tag, the LESSER GENERAL PUBLIC LICENSE version 2.
+ Please see http://www.gnu.org for details and the specific text of the license.
+@@ -63,10 +57,22 @@
+     In order for the included .htaccess to work properly, you will need to
+ set apache's "AllowOverride" setting to "All" (or at least "Options") for
+-the root mythweb directory.  This directive lives within <Directory/> tags,
+-so make sure you're changing the setting for the correct directory.  You will
+-also need to make sure that the following apache modules are enabled:
++the root mythweb directory.  This directive lives within <Directory> tags,
++so make sure you're changing the setting for the correct directory.  Please
++keep in mind that most distros correctly disable everything for <Directory />,
++and then later override those with something like <Directory /var/www/html>.
++The simplest way to do this is to put a file into /etc/httpd/conf.d (or
++whatever your distro calls it) containing something like:
++    <Directory "/var/www/html/mythweb" >
++        Options         FollowSymLinks
++        AllowOverride   All
++    </Directory>
++
++Just make sure that the path points to your MythWeb installation, since that
++will likely differ from system to system.  You will also need to make sure that
++the following apache modules are enabled:
++
+     mod_env
+     mod_rewrite
+Index: mythplugins/mythdvd/mtd/jobthread.cpp
+===================================================================
+--- mythplugins/mythdvd/mtd/jobthread.cpp      (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythdvd/mtd/jobthread.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -11,6 +11,7 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
++#include <unistd.h>
+ #include <iostream>
+ using namespace std;
+Index: mythplugins/mythdvd/mtd/mtd.cpp
+===================================================================
+--- mythplugins/mythdvd/mtd/mtd.cpp    (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythdvd/mtd/mtd.cpp    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -8,6 +8,7 @@
+ */
++#include <unistd.h>
+ #include <qstringlist.h>
+ #include <qregexp.h>
+ #include <qdir.h>
+Index: mythplugins/mythdvd/mtd/logging.cpp
+===================================================================
+--- mythplugins/mythdvd/mtd/logging.cpp        (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythdvd/mtd/logging.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -9,6 +9,7 @@
+ */
+ #include "logging.h"
++#include <unistd.h>
+ #include <qdatetime.h>
+ #include <mythtv/mythcontext.h>
+Index: mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp
+===================================================================
+--- mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp  (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -12,6 +12,7 @@
+ #include "metadata.h"
+ #include "metaiooggvorbiscomment.h"
++#include <mythtv/mythconfig.h>
+ #include <mythtv/mythcontext.h>
+ // static functions for OggVorbis
+@@ -240,8 +241,13 @@
+             seekTime = -1.0;
+         }
++#ifdef WORDS_BIGENDIAN
++        len = ov_read(&oggfile, (char *) (output_buf + output_at), bks, 1, 2, 1,
++                      &section);
++#else
+         len = ov_read(&oggfile, (char *) (output_buf + output_at), bks, 0, 2, 1,
+                       &section);
++#endif
+         if (len > 0) {
+             bitrate = ov_bitrate_instant(&oggfile) / 1000;
+Index: mythplugins/mythmusic/mythmusic/flacdecoder.cpp
+===================================================================
+--- mythplugins/mythmusic/mythmusic/flacdecoder.cpp    (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythmusic/mythmusic/flacdecoder.cpp    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -12,6 +12,7 @@
+ #include "metadata.h"
+ #include "metaioflacvorbiscomment.h"
++#include <mythtv/mythconfig.h>
+ #include <mythtv/mythcontext.h>
+ #include <qtimer.h>
+@@ -102,7 +103,11 @@
+             for (channel = 0; channel < chan; channel++)
+             {
+                sample = (FLAC__int8)buffer[channel][cursamp];
++#ifdef WORDS_BIGENDIAN
++               *(output_buf + output_at++) = ((sample >> 8) & 0xff);
++#else
+                *(output_buf + output_at++) = ((sample >> 0) & 0xff);
++#endif
+                output_bytes += 1;
+             }
+         }   
+@@ -114,8 +119,13 @@
+             for (channel = 0; channel < chan; channel++)
+             { 
+                sample = (FLAC__int16)buffer[channel][cursamp];             
++#ifdef WORDS_BIGENDIAN
++               *(output_buf + output_at++) = ((sample >> 8) & 0xff);
+                *(output_buf + output_at++) = ((sample >> 0) & 0xff);
++#else
++               *(output_buf + output_at++) = ((sample >> 0) & 0xff);
+                *(output_buf + output_at++) = ((sample >> 8) & 0xff);
++#endif
+                output_bytes += 2;
+             }
+         }
+Index: mythplugins/mythmusic/mythmusic/maddecoder.cpp
+===================================================================
+--- mythplugins/mythmusic/mythmusic/maddecoder.cpp     (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythmusic/mythmusic/maddecoder.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -16,6 +16,7 @@
+ #include <mythtv/audiooutput.h>
+ #include "metaioid3v2.h"
++#include <mythtv/mythconfig.h>
+ #include <mythtv/mythcontext.h>
+ #define XING_MAGIC     (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')
+@@ -407,7 +408,7 @@
+         flush(TRUE);
+         if (output()) {
+-          output()->Drain();
++            output()->Drain();
+         }
+         done = TRUE;
+@@ -488,15 +489,25 @@
+             flush();
+         }
+         sample = fix_sample(16, *left++);
++#ifdef WORDS_BIGENDIAN
++        *(output_buf + output_at++) = ((sample >> 8) & 0xff);
+         *(output_buf + output_at++) = ((sample >> 0) & 0xff);
++#else
++        *(output_buf + output_at++) = ((sample >> 0) & 0xff);
+         *(output_buf + output_at++) = ((sample >> 8) & 0xff);
++#endif
+         output_bytes += 2;
+         if (channels == 2)
+         {
+             sample = fix_sample(16, *right++);
++#ifdef WORDS_BIGENDIAN
++            *(output_buf + output_at++) = ((sample >> 8) & 0xff);
+             *(output_buf + output_at++) = ((sample >> 0) & 0xff);
++#else
++            *(output_buf + output_at++) = ((sample >> 0) & 0xff);
+             *(output_buf + output_at++) = ((sample >> 8) & 0xff);
++#endif
+             output_bytes += 2;
+         }
+     }
+Index: mythplugins/mythweather/mythweather/weather.cpp
+===================================================================
+--- mythplugins/mythweather/mythweather/weather.cpp    (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythweather/mythweather/weather.cpp    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -2571,6 +2571,14 @@
+          return false;
+      }
++     int imageCount = 5;
++     QString imagesList = parseData(tempData, "imagenames = new Array( '", ";");
++     if (imagesList != "<NULL>")
++     {
++         QStringList imageURLs = QStringList::split(",", imagesList);
++         imageCount = imageURLs.size();
++     }
++
+      QString fileprefix = MythContext::GetConfDir();
+      QDir dir(fileprefix);
+@@ -2587,13 +2595,13 @@
+          cerr << "MythWeather: Map File Prefix: " << fileprefix << endl;
+      // delete existing radar maps
+-     for (int x = 1; x <= 6; x++)
++     for (int x = 1; x <= 10; x++)
+          QFile::remove(QString(fileprefix + "/radar%1.jpg").arg(x));
+      if (debug)
+          cerr << "MythWeather: Copying Map Files from Server (" << imageLoc << ")...\n";
+-     for (int x = 1; x <= 6; x++)
++     for (int x = 1; x <= imageCount; x++)
+      {
+          QString sFile = QString(fileprefix + "/radar%1.jpg").arg(x);
+          sURL = QString("http://image.weather.com" + imageLoc + "%1L.jpg").arg(x);
+Index: mythplugins/mythcontrols/mythcontrols/mythcontrols.cpp
+===================================================================
+--- mythplugins/mythcontrols/mythcontrols/mythcontrols.cpp     (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythcontrols/mythcontrols/mythcontrols.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -46,22 +46,6 @@
+ #include "keygrabber.h"
+-static QMap<int,QString> FindContexts(const QString &context)
+-{
+-    QMap<int,QString> retval;
+-    retval.clear();
+-    if (context != JUMP_CONTEXT) retval[-1] = JUMP_CONTEXT;
+-    retval[0] = context;
+-    if (context != JUMP_CONTEXT && context != GLOBAL_CONTEXT)
+-    {
+-        if (context == "TV Editting")
+-            retval[1] = "TV Playback";
+-        retval[2] = GLOBAL_CONTEXT;
+-        if (context != "qt")
+-            retval[3] = "qt";
+-    }
+-    return retval;
+-}
+ static const QString KeyToDisplay(const QString key)
+ {
+@@ -838,7 +822,11 @@
+     refreshKeyInformation();
+ }
+-void MythControls::addBindings(QDict<binding_t> &bindings, const QString &context, const QString &contextParent, int bindlevel)
++
++
++void MythControls::addBindings(QDict<binding_t> &bindings,
++                               const QString &context,
++                               const QString &contextParent, int bindlevel)
+ {
+     QStringList *actions = key_bindings->getActions(context);
+@@ -872,18 +860,13 @@
+ BindingList *MythControls::getKeyBindings(const QString &context)
+ {
++    QStringList keys;
+     QDict<binding_t> bindings;
+     bindings.clear();
+-    QMap<int,QString> contextList = FindContexts(context);
+-    for (QMap<int,QString>::iterator it = contextList.begin(); it != contextList.end(); ++it)
+-    {
+-        int level = it.key();
+-        QString curcontext = it.data();
+-        addBindings(bindings, curcontext, context, level);
+-    }
++    for (size_t i = 0; i < contexts.size(); i++)
++        addBindings(bindings, contexts[i], context, i);
+-    QStringList keys;
+     for (QDictIterator<binding_t> it(bindings); it.current(); ++it)
+     {
+Index: mythplugins/mythcontrols/mythcontrols/actionset.cpp
+===================================================================
+--- mythplugins/mythcontrols/mythcontrols/actionset.cpp        (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythcontrols/mythcontrols/actionset.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -139,13 +139,19 @@
+ /* method description in header */
+ QStringList * ActionSet::actionStrings(const QString &context_name) const
+ {
+-    QStringList *action_strings = new QStringList();
+-    QDictIterator<Action> it(*(_contexts[context_name]));
++    Context *c = _contexts[context_name];
+-    for (; it.current(); ++it)
+-        action_strings->append(it.currentKey());
++    if (c == NULL) return NULL;
++    else
++    {
++        QStringList *action_strings = new QStringList();
++        QDictIterator<Action> it(*(_contexts[context_name]));
++
++        for (; it.current(); ++it)
++            action_strings->append(it.currentKey());
+     
+-    return action_strings;
++        return action_strings;
++    }
+ }
+Index: mythplugins/mythcontrols/mythcontrols/keybindings.h
+===================================================================
+--- mythplugins/mythcontrols/mythcontrols/keybindings.h        (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythcontrols/mythcontrols/keybindings.h        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -65,6 +65,8 @@
+     /**
+      * @brief Get a list of the context names.
+      * @return A list of the context names.
++     * @note The returned list is a copy and can be modified without
++     * side-effects.
+      */
+     inline QStringList * getContexts() const
+     {
+Index: mythplugins/mythvideo/mythvideo/videomanager.h
+===================================================================
+--- mythplugins/mythvideo/mythvideo/videomanager.h     (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythvideo/mythvideo/videomanager.h     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -30,7 +30,7 @@
+   public:
+     VideoManager(MythMainWindow *parent, const char *name = 0);
+     ~VideoManager(void);
+-    void VideoManager::processEvents() { qApp->processEvents(); }
++    void processEvents() { qApp->processEvents(); }
+     
+   public slots:
+     void slotManualIMDB();
+Index: mythplugins/mythvideo/mythvideo/videoselected.h
+===================================================================
+--- mythplugins/mythvideo/mythvideo/videoselected.h    (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythvideo/mythvideo/videoselected.h    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -35,7 +35,7 @@
+     VideoSelected(VideoList *lvideolist,
+                  MythMainWindow *parent, const char *name = 0, int index = 0);
+     ~VideoSelected();
+-    void VideoSelected::processEvents() { qApp->processEvents(); }
++    void processEvents() { qApp->processEvents(); }
+     
+   protected slots:
+Index: mythplugins/mythphone/mythphone/sipfsm.h
+===================================================================
+--- mythplugins/mythphone/mythphone/sipfsm.h   (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythphone/mythphone/sipfsm.h   (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -618,7 +618,7 @@
+     SipWatcher *CreateWatcherFsm(QString Url);
+     SipIM *CreateIMFsm(QString Url="", QString callIdStr="");
+     void StopWatchers();
+-    void SipFsm::KickWatcher(SipUrl *Url);
++    void KickWatcher(SipUrl *Url);
+     void SendIM(QString destUrl, QString CallId, QString imMsg);
+     int numCalls();
+     int getPrimaryCall() { return primaryCall; };
+Index: mythplugins/mythphone/mythphone/vxml.h
+===================================================================
+--- mythplugins/mythphone/mythphone/vxml.h     (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythphone/mythphone/vxml.h     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -10,7 +10,7 @@
+ {
+   public:
+     vxmlVariable(QString N, QString V);             
+-    vxmlVariable::vxmlVariable(QString N, short *wav, int S);
++    vxmlVariable(QString N, short *wav, int S);
+     virtual ~vxmlVariable() {}; 
+     bool isType(QString t) { return (t == Type); };
+     QString getName() { return Name; };
+Index: mythplugins/mythgame/mythgame/gamehandler.h
+===================================================================
+--- mythplugins/mythgame/mythgame/gamehandler.h        (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythgame/mythgame/gamehandler.h        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -106,7 +106,7 @@
+   protected:
+     static GameHandler* GetHandler(RomInfo *rominfo);
+-    static GameHandler* GameHandler::GetHandlerByName(QString systemname);
++    static GameHandler* GetHandlerByName(QString systemname);
+     bool rebuild;
+     int spandisks;
+Index: mythplugins/mythnews/mythnews/news-sites.xml
+===================================================================
+--- mythplugins/mythnews/mythnews/news-sites.xml       (.../tags/release-0-19) (revision 10931)
++++ mythplugins/mythnews/mythnews/news-sites.xml       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -119,7 +119,7 @@
+     <item>
+         <title>Slashdot</title>
+-        <url>http://slashdot.org/slashdot.rss</url>
++        <url>http://rss.slashdot.org/Slashdot/slashdot</url>
+         <ico>http://slashdot.org/favicon.ico</ico>
+     </item>
+Index: mythtv/libs/libmythtv/dvbchannel.h
+===================================================================
+--- mythtv/libs/libmythtv/dvbchannel.h (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/dvbchannel.h (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -60,11 +60,13 @@
+         { return chan_opts.pmt.HasTelevisionService(); }
+     /// Returns true iff we have a faulty DVB driver that munges PMT
+     bool HasCRCBug(void)                const { return has_crc_bug; }
++    uint GetMinSignalMonitorDelay(void) const { return sigmon_delay; }
+     // Commands
+     bool SwitchToInput(const QString &inputname, const QString &chan);
+     bool SwitchToInput(int newcapchannel, bool setstarting);
+     bool Tune(const dvb_channel_t& channel, bool force_reset=false);
++    bool Retune(void);
+     // Set/Get/Command just for SIScan/ScanWizardScanner
+     void SetMultiplexID(int mplexid)          { currentTID = mplexid; };
+@@ -109,11 +111,18 @@
+     volatile int      fd_frontend; ///< File descriptor for tuning hardware
+     int               cardnum;     ///< DVB Card number
+     bool              has_crc_bug; ///< true iff our driver munges PMT
++    uint              tuning_delay;///< Extra delay to add for broken drivers
++    uint              sigmon_delay;///< Minimum delay between FE_LOCK checks
+     int               currentTID;  ///< Stores mplexid from database
+     bool              first_tune;  ///< Used to force hardware reset
+     int               nextcapchannel; ///< Signal an input change
++
++    /// Last tuning options sent to hardware for retuning
++    DVBTuning         retune_tuning;
++    /// Retuning adjustment, required so drivers don't ignore retune request
++    int               retune_adj;
+ };
+ #endif
+Index: mythtv/libs/libmythtv/NuppelVideoPlayer.h
+===================================================================
+--- mythtv/libs/libmythtv/NuppelVideoPlayer.h  (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/NuppelVideoPlayer.h  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -150,7 +150,8 @@
+     // 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; }
+@@ -297,6 +298,7 @@
+     bool DecodeFrame(struct rtframeheader *frameheader,
+                      unsigned char *strm, unsigned char *outbuf);
++    bool PrebufferEnoughFrames(void);
+     void CheckPrebuffering(void);
+     bool GetFrameNormal(int onlyvideo);
+     bool GetFrameFFREW(void);
+@@ -309,7 +311,7 @@
+     bool DoRewind(void);
+     // Private seeking stuff
+-    void ClearAfterSeek(void);
++    void ClearAfterSeek(bool clearvideobuffers = true);
+     bool FrameIsInMap(long long frameNumber, QMap<long long, int> &breakMap);
+     void JumpToFrame(long long frame);
+     void JumpToNetFrame(long long net) { JumpToFrame(framesPlayed + net); }
+@@ -543,6 +545,7 @@
+     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
+Index: mythtv/libs/libmythtv/osdlistbtntype.h
+===================================================================
+--- mythtv/libs/libmythtv/osdlistbtntype.h     (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/osdlistbtntype.h     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -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 OSDListBtnType;
+ class OSDListBtnTypeItem;
+-class OSDListBtnType;
++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 = "");
++    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);
++    }
+-    OSDTypeImage *getImage(void) { return m_image; }
+-    QString getAction(void) { return m_action; }
+-    int getCheckable(void) { return m_checkable; }
+-    QString getGroup(void) { return m_group; }
++    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,53 +82,49 @@
+ {
+     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);
++    bool IsVisible(void)          const { return m_visible;  }
++ 
++    void SetFontActive(TTFFont *font)   { m_active   = font; }
++    void SetFontInactive(TTFFont *font) { m_inactive = font; }
++
+     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);
+-    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 SetAsTree(OSDGenericTree *toplevel);
+-
+-    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);
++    void FillLevelFromTree(OSDGenericTree *item, uint levelnum);
++    OSDListBtnType *GetLevel(uint levelnum);
++    void EnterItem(void);
++    void SelectItem(void);
+-    int levels;
+-    int curlevel;
+-
+     OSDGenericTree *treetop;
+     OSDGenericTree *currentpos;
++    TTFFont        *m_active;
++    TTFFont        *m_inactive;
+-    QPtrList<OSDListBtnType> listLevels;
++    OSDListBtnList  listLevels;
+-    OSDListBtnType *currentlevel;
+-
+-    TTFFont *m_active;
+-    TTFFont *m_inactive;
+-
+     QColor    m_itemRegBeg;
+     QColor    m_itemRegEnd;
+     QColor    m_itemSelBeg;
+@@ -116,62 +132,76 @@
+     uint      m_itemRegAlpha;
+     uint      m_itemSelAlpha;
+    
+-    int m_spacing;
+-    int m_margin;
++    uint      m_spacing;
++    uint      m_margin;
++    int       m_levelspacing;
+-    QRect m_totalarea;
+-    QRect m_levelsize;
+-    int m_levelspacing;
++    QRect     m_totalarea;
++    QRect     m_levelsize;
+-    float m_wmult;
+-    float m_hmult;
++    float     m_unbiasedspacing;
++    float     m_unbiasedmargin;
++    QRect     m_unbiasedarea;
++    QRect     m_unbiasedsize;
+-    bool m_visible;
+-    bool m_arrowAccel;
++    float     m_wmult;
++    float     m_hmult;
++
++    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);
++    // General Gets
++    bool  IsVisible() const { return m_visible; }
++
++    // 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  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();
+-
+-    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,24 +209,35 @@
+     void  InsertItem(OSDListBtnTypeItem *item);
+     void  RemoveItem(OSDListBtnTypeItem *item);
+-    int   m_order;
+-    QRect m_rect;
+-    QRect m_contentsRect;
+-    QRect m_arrowsRect;
++  private:
++    int            m_order;
++    QRect          m_rect;
++    QRect          m_contentsRect;
++    QRect          m_arrowsRect;
+-    float m_wmult;
+-    float m_hmult;
++    float          m_wmult;
++    float          m_hmult;
+-    int   m_itemHeight;
+-    int   m_itemSpacing;
+-    int   m_itemMargin;
+-    uint  m_itemsVisible;
++    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_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;
+     OSDTypeImage   m_itemSelInactPix;
+@@ -209,43 +250,30 @@
+     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;
+-    TTFFont* m_fontActive;
+-    TTFFont* m_fontInactive;
++    int            m_topIndx;
++    int            m_selIndx;
+-    bool      m_initialized;
+-    bool      m_clearing;
++    OSDListBtnItemList m_itemList;
+-    OSDListBtnTypeItem* m_topItem;
+-    OSDListBtnTypeItem* m_selItem;
+-    QPtrList<OSDListBtnTypeItem> m_itemList;
++    mutable QMutex m_update;
+-    QMutex    m_update;
+-
+-    bool      m_visible;
+-
+-    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 @@
+                        bool showArrow = false, CheckState state = NotChecked);
+     ~OSDListBtnTypeItem();
+-    OSDListBtnType*   parent() const;
+-    QString           text() const;
+-    const OSDTypeImage*   pixmap() const;
+-    bool              checkable() const;
+-    CheckState        state() const;
++    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  setChecked(CheckState state);
+-    void  setData(void *data);
+-    void* getData();
+-    void  setGroup(QString group) { m_group = group; };
+-    QString getGroup(void) { return m_group; }
++    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;
+ };
+Index: mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
+===================================================================
+--- mythtv/libs/libmythtv/NuppelVideoPlayer.cpp        (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/NuppelVideoPlayer.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -147,6 +147,7 @@
+       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 @@
+         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 @@
+ 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))
+     {
+@@ -1626,8 +1629,8 @@
+         {
+             // If we are using hardware decoding, so we've already done the
+             // decoding; display the frame, but don't wait for A/V Sync.
+-            videoOutput->PrepareFrame(buffer, ps);
+-            videoOutput->Show(m_scan);
++            videoOutput->PrepareFrame(buffer, kScan_Intr2ndField);
++            videoOutput->Show(kScan_Intr2ndField);
+             VERBOSE(VB_PLAYBACK, LOC + dbg + "skipping A/V wait.");
+         }
+         else
+@@ -1685,14 +1688,14 @@
+     if (diverge > MAXDIVERGE)
+     {
+-        // If audio is way ahead of video, adjust for it...
++        // If audio is way behind of video, adjust for it...
+         // by cutting the frame rate in half for the length of this frame
+         avsync_adjustment = frame_interval;
+         lastsync = true;
+         VERBOSE(VB_PLAYBACK, LOC + 
+-                QString("Audio is %1 frames ahead of video,\n"
+-                        "\t\t\tdoubling video frame interval.").arg(diverge));
++                QString("Video is %1 frames ahead of audio,\n"
++                        "\t\t\tdoubling video frame interval to slow down.").arg(diverge));
+     }
+     if (audioOutput && normal_speed)
+@@ -1811,11 +1814,8 @@
+     videosync->Start();
+ }
+-void NuppelVideoPlayer::DisplayNormalFrame(void)
++bool NuppelVideoPlayer::PrebufferEnoughFrames(void)
+ {
+-    video_actually_paused = false;
+-    resetvideo = false;
+-
+     prebuffering_lock.lock();
+     if (prebuffering)
+     {
+@@ -1843,14 +1843,29 @@
+         }
+         prebuffering_lock.unlock();
+         videosync->Start();
+-        return;
++
++        return false;
+     }
+     prebuffering_lock.unlock();
+     //VERBOSE(VB_PLAYBACK, LOC + "fs: " + videoOutput->GetFrameStatus());
+     if (!videoOutput->EnoughPrebufferedFrames())
+     {
+-        VERBOSE(VB_GENERAL, LOC + "prebuffering pause");
++        if (videoOutput)
++        {
++            videoOutput->CheckFrameStates();
++            if (videoOutput->hasMCAcceleration()   ||
++                videoOutput->hasIDCTAcceleration() ||
++                videoOutput->hasVLDAcceleration())
++            {
++                // Prebuffering fails w/XvMC's 8 surfaces..
++                usleep(5000);
++                return false;
++            }
++        }
++        VERBOSE(VB_GENERAL, LOC + "prebuffering pause" +
++                videoOutput->GetFrameStatus());
++
+         SetPrebuffering(true);
+ #if FAST_RESTART
+         if (!m_playing_slower && audio_channels <= 2)
+@@ -1861,7 +1876,7 @@
+             VERBOSE(VB_GENERAL, "playing slower due to falling behind...");
+         }
+ #endif
+-        return;
++        return false;
+     }
+ #if FAST_RESTART
+@@ -1877,6 +1892,25 @@
+     prebuffer_tries = 0;
+     prebuffering_lock.unlock();
++    return true;
++}
++
++void NuppelVideoPlayer::DisplayNormalFrame(void)
++{
++    video_actually_paused = false;
++    resetvideo = false;
++
++    if (!PrebufferEnoughFrames())
++    {
++        // When going to switch channels
++        if (paused)
++        {
++            usleep(frame_interval);
++            DisplayPauseFrame();
++        }
++        return;
++    }
++
+     videoOutput->StartDisplayingFrame();
+     VideoFrame *frame = videoOutput->GetLastShownFrame();
+@@ -1920,7 +1954,7 @@
+         ShowText();
+         DisplaySubtitles();
+     }
+-    else if (osdHasSubtitles || nonDisplayedSubtitles.size() > 20)
++    else if (osdHasSubtitles)
+     {
+         ClearSubtitles();
+     }
+@@ -2176,7 +2210,10 @@
+     }
+     if (eof)
++    {
+         discontinuity = true;
++        ClearSubtitles();
++    }
+     livetvchain->SetProgram(pginfo);
+@@ -2199,6 +2236,7 @@
+     }
+     if (IsErrored())
+     {
++        VERBOSE(VB_IMPORTANT, LOC_ERR + "SwitchToProgram failed.");
+         eof = true;
+         return;
+     }
+@@ -2265,6 +2303,8 @@
+     ringBuffer->Pause();
+     ringBuffer->WaitForPause();
++    ClearSubtitles();
++
+     livetvchain->SetProgram(pginfo);
+     ringBuffer->Reset(true);
+@@ -2284,6 +2324,7 @@
+     if (errored || !GetDecoder())
+     {
++        VERBOSE(VB_IMPORTANT, LOC_ERR + "JumpToProgram failed.");
+         errored = true;
+         return;
+     }
+@@ -2471,6 +2512,12 @@
+                 JumpToProgram();
+         }
++        if (forcePositionMapSync)
++        {
++            forcePositionMapSync = false;
++            GetDecoder()->SyncPositionMap();
++        }
++
+         if (IsErrored() || (nvr_enc && nvr_enc->GetErrorStatus()))
+         {
+             VERBOSE(VB_IMPORTANT, LOC_ERR + "Unknown error, exiting decoder");
+@@ -3246,7 +3293,10 @@
+     GetDecoder()->DoFastForward(desiredFrame);
+     GetDecoder()->setExactSeeks(exactseeks);
+-    ClearAfterSeek();
++    // Note: The video output will be reset by what the the decoder 
++    //       does, so we only need to reset the audio, subtitles, etc.
++    ClearAfterSeek(false);
++
+     lastSkipTime = time(NULL);
+     return true;
+ }
+@@ -3291,19 +3341,24 @@
+ }
+ #endif
+-/** \fn NuppelVideoPlayer::ClearAfterSeek(void)
++/** \fn NuppelVideoPlayer::ClearAfterSeek(bool)
+  *  \brief This is to support seeking...
+  *
+  *   This resets the output classes and discards all
+  *   frames no longer being used by the decoder class.
+  *
+  *   Note: caller should not hold any locks
++ *
++ *  \param clearvideobuffers This clears the videooutput buffers as well,
++ *                           this is only safe if no old frames are
++ *                           required to continue decoding.
+  */
+-void NuppelVideoPlayer::ClearAfterSeek(void)
++void NuppelVideoPlayer::ClearAfterSeek(bool clearvideobuffers)
+ {
+-    VERBOSE(VB_PLAYBACK, LOC + "ClearAfterSeek()");
++    VERBOSE(VB_PLAYBACK, LOC + "ClearAfterSeek("<<clearvideobuffers<<")");
+-    videoOutput->ClearAfterSeek();
++    if (clearvideobuffers)
++        videoOutput->ClearAfterSeek();
+     for (int i = 0; i < MAXTBUFFER; i++)
+         txtbuffers[i].timecode = 0;
+@@ -4398,6 +4453,8 @@
+     hascommbreaktable = !commBreakMap.isEmpty();
+     SetCommBreakIter();
+     commBreakMapLock.unlock();
++
++    forcePositionMapSync = true;
+ }
+ bool NuppelVideoPlayer::RebuildSeekTable(bool showPercentage, StatusCallback cb, void* cbData)
+@@ -4541,7 +4598,8 @@
+     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 +4646,23 @@
+     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 +4720,7 @@
+             if (commBreakIter.key() == totalFrames)
+             {
++                VERBOSE(VB_IMPORTANT, LOC + "Skipping commercial to end of file");
+                 eof = true;
+             }
+             else
+@@ -4721,7 +4788,7 @@
+         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 +5085,7 @@
+                 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);
+Index: mythtv/libs/libmythtv/NuppelVideoRecorder.cpp
+===================================================================
+--- mythtv/libs/libmythtv/NuppelVideoRecorder.cpp      (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/NuppelVideoRecorder.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -216,7 +216,10 @@
+     }
+     if (mpa_codec)
++    {
++        QMutexLocker locker(&avcodeclock);
+         avcodec_close(mpa_ctx);
++    }
+     if (mpa_ctx)
+         av_free(mpa_ctx);
+@@ -453,8 +456,11 @@
+         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 frag, blocksize = 4096;
+     int tmp;
++    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;
++        VERBOSE(VB_IMPORTANT,
++                QString("NVR::AudioInit() This Unix doesn't support"
++                        " device files for audio access. Skipping"));
++        return 1;
+ #else
+-    if (!skipdevice)
+-    {
+         if (-1 == (afd = open(audiodevice.ascii(), O_RDONLY | O_NONBLOCK)))
+         {
+             VERBOSE(VB_IMPORTANT, QString("NVR: Error, cannot open DSP '%1'").
+@@ -678,8 +685,8 @@
+         }
+         close(afd);
++#endif
+     }
+-#endif
+     audio_bytes_per_sample = audio_channels * audio_bits / 8;
+     blocksize *= 4;
+Index: mythtv/libs/libmythtv/signalmonitor.cpp
+===================================================================
+--- mythtv/libs/libmythtv/signalmonitor.cpp    (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/signalmonitor.cpp    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -100,9 +100,9 @@
+                              uint wait_for_mask,  const char *name)
+     : QObject(NULL, name),             channel(_channel),
+       capturecardnum(_capturecardnum), flags(wait_for_mask),
+-      update_rate(25),                 running(false),
+-      exit(false),                     update_done(false),
+-      notify_frontend(true),
++      update_rate(25),                 minimum_update_rate(5),
++      running(false),                  exit(false),
++      update_done(false),              notify_frontend(true),
+       signalLock    (QObject::tr("Signal Lock"),  "slock",
+                      1, true, 0,   1, 0),
+       signalStrength(QObject::tr("Signal Power"), "signal",
+Index: mythtv/libs/libmythtv/osdlistbtntype.cpp
+===================================================================
+--- mythtv/libs/libmythtv/osdlistbtntype.cpp   (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/osdlistbtntype.cpp   (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -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)
++static QRect unbias(QRect rect, float wmult, float hmult)
+ {
+-    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);
++    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)
++static QRect bias(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;
+-
+-    SetItemRegColor(Qt::black,QColor(80,80,80),100);
+-    SetItemSelColor(QColor(82,202,56),QColor(52,152,56),255);
+-
+-    m_spacing = 0;
+-    m_margin = 0;
++    return QRect((int)round(rect.x()      * wmult),
++                 (int)round(rect.y()      * hmult),
++                 (int)ceil( rect.width()  * wmult),
++                 (int)ceil( rect.height() * hmult));
+ }
+-void OSDListTreeType::Reinit(float wchange, float hchange, float wmult,
+-                             float 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;
+-    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;
+-    }
++    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);
+ }
+-void OSDListTreeType::SetGroupCheckState(QString group, int newState)
++OSDListTreeType::~OSDListTreeType()
+ {
+-    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)
++        delete *it;    
+ }
+-void OSDListTreeType::SetItemRegColor(const QColor& beg, const QColor& end,
+-                                      uint alpha)
++void OSDListTreeType::Reinit(float wmult, float hmult)
+ {
+-    m_itemRegBeg   = beg;
+-    m_itemRegEnd   = end;
+-    m_itemRegAlpha = alpha;
+-}
++    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);
+-void OSDListTreeType::SetItemSelColor(const QColor& beg, const QColor& end,
+-                                      uint alpha)
+-{
+-    m_itemSelBeg   = beg;
+-    m_itemSelEnd   = end;
+-    m_itemSelAlpha = alpha;
+-}
++    if (!treetop || m_levelnum < 0)
++        return;
+-void OSDListTreeType::SetFontActive(TTFFont *font)
+-{
+-    m_active = font;
+-}
++    // Save item indices
++    vector<uint> list;
++    for (uint i = 0; i <= (uint)m_levelnum; i++)
++        list.push_back(listLevels[i]->GetItemCurrentPos());
+-void OSDListTreeType::SetFontInactive(TTFFont *font)
+-{
+-    m_inactive = font;
+-}
++    // Delete old OSD items
++    OSDListBtnList clone = listLevels;
++    listLevels.clear();
++    OSDListBtnList::iterator it = clone.begin();
++    for (; it != clone.end(); ++it)
++        delete *it;
+-void OSDListTreeType::SetSpacing(int spacing)
+-{
+-    m_spacing = spacing;
++    // Create new OSD items
++    SetAsTree(treetop, &list);
+ }
+-void OSDListTreeType::SetMargin(int margin)
++void OSDListTreeType::SetGroupCheckState(QString group, int newState)
+ {
+-    m_margin = margin;
++    OSDListBtnList::iterator it = listLevels.begin();
++    for (; it != listLevels.end(); ++it)
++        (*it)->SetGroupCheckState(group, newState);
+ }
+-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 @@
+         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     *child   = (OSDGenericTree*) it.current();
++    OSDListBtnTypeItem *newitem = NULL;
++    for (;(child = (OSDGenericTree*) it.current()); ++it)
+     {
+-        OSDGenericTree *osdchild = (OSDGenericTree *)child;
++        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 @@
+     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);
+-    }
++    OSDListBtnItemList::iterator it;
++    for (it = m_itemList.begin(); it != m_itemList.end(); ++it)
++        if ((*it)->getGroup() == group)
++            (*it)->setChecked((OSDListBtnTypeItem::CheckState) newState);
+ }
+-void OSDListBtnType::SetItemRegColor(const QColor& beg, const QColor& end, 
+-                                     uint alpha)
++void OSDListBtnType::Reset(void)
+ {
+-    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;    
+-}
+-
+-void OSDListBtnType::SetActive(bool active)
+-{
+-    m_active = active;
+-}
+-
+-void OSDListBtnType::Reset()
+-{
+     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)
++
++    int i = find(m_itemList, item);
++    if (i < 0)
+         return;
+-    m_topItem = m_itemList.first();
+-    m_selItem = m_itemList.first();
++    m_itemList.erase(m_itemList.begin()+i);
+-    m_itemList.remove(item);
+-
+     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;
++    m_topIndx     = (m_selIndx < m_topIndx) ? m_selIndx : m_topIndx;
++    m_showUpArrow = m_topIndx;
++    m_showDnArrow = m_topIndx + m_itemsVisible < m_itemList.size();
+-    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;
+-
+-    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;
++    if (++m_selIndx >= (int)m_itemList.size())
++        m_selIndx = m_topIndx = 0;
+-        m_topItem = item;
+-    }
+-
+-    m_selItem = item;
+-
+-    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);
+-    }
++    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();
+     
+-    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;
+-    
+-    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,14 +587,13 @@
+     }
+ }
+-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 = max(sz1, sz2) + (int)(2 * m_itemMargin);
++    m_itemHeight = m_itemHeight & ~0x1;
+-    m_itemHeight = (m_itemHeight / 2) * 2;
+-
+     if (m_showScrollArrows) 
+     {
+         LoadPixmap(m_upArrowRegPix, "uparrow-reg");
+@@ -838,11 +632,7 @@
+     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::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)
++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)
+ {
+-    m_parent    = lbtype;
+-    m_text      = text;
+-    m_pixmap    = pixmap;
+-    m_checkable = checkable;
+-    m_state     = state;
+-    m_showArrow = showArrow;
+-    m_data      = 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;
+-    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;
+-    
++    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;
++
+     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 @@
+         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 @@
+         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 @@
+     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);
+-}
+-
+Index: mythtv/libs/libmythtv/RingBuffer.cpp
+===================================================================
+--- mythtv/libs/libmythtv/RingBuffer.cpp       (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/RingBuffer.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -145,6 +145,12 @@
+     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 @@
+     bool is_local = false;
+     bool is_dvd = false;
++
+     if ((filename.left(7) == "myth://") &&
+         (filename.length() > 7 ))
+     {
+@@ -271,6 +278,11 @@
+             remotefile = NULL;
+         }
+     }
++
++    setswitchtonext = false;
++    ateof = false;
++    commserror = false;
++    numfailures = 0;
+ }
+ /** \fn RingBuffer::IsOpen(void) const
+@@ -727,7 +739,7 @@
+         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 @@
+             if (remotefile)
+             {
++                if (livetvchain && livetvchain->HasNext())
++                    remotefile->SetTimeout(true);
++
+                 ret = safe_read(remotefile, readAheadBuffer + rbwpos,
+                                 totfree);
+                 internalreadpos += ret;
+@@ -785,8 +800,16 @@
+             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 @@
+         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 @@
+                  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 @@
+                 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 @@
+         availWaitMutex.unlock();
+         avail = ReadBufAvail();
+-        if (ateof && avail < count)
++        if ((ateof || setswitchtonext) && avail < count)
+             count = avail;
+         if (commserror)
+Index: mythtv/libs/libmythtv/hdtvrecorder.cpp
+===================================================================
+--- mythtv/libs/libmythtv/hdtvrecorder.cpp     (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/hdtvrecorder.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -627,9 +627,8 @@
+         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();
+Index: mythtv/libs/libmythtv/dummydtvrecorder.cpp
+===================================================================
+--- mythtv/libs/libmythtv/dummydtvrecorder.cpp (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/dummydtvrecorder.cpp (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -125,7 +125,8 @@
+     // 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 @@
+         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();
+Index: mythtv/libs/libmythtv/avformatdecoder.cpp
+===================================================================
+--- mythtv/libs/libmythtv/avformatdecoder.cpp  (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/avformatdecoder.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -725,7 +725,12 @@
+         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. " +
+Index: mythtv/libs/libmythtv/osdtypes.cpp
+===================================================================
+--- mythtv/libs/libmythtv/osdtypes.cpp (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/osdtypes.cpp (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -14,6 +14,9 @@
+ #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 @@
+                     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 @@
+     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 @@
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 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 @@
+     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 @@
+     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 @@
+     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 @@
+     m_scalew = scalew;
+     m_scaleh = scaleh;
++    m_cacheitem = NULL;
+     LoadImage(filename, wmult, hmult, scalew, scaleh);
+ }
+@@ -733,6 +695,7 @@
+     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 @@
+     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 @@
+     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()
+ {
+-    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 @@
+     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::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;
+-    if (filename.length() < 2)
++        // 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;
++
+         return;
++    }
++   
++    // scaled image was not found in cache, have to create it
++  
+     QImage tmpimage(filename);
+@@ -867,17 +868,32 @@
+                      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 @@
+     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 @@
+     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 @@
+     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 @@
+     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()
+ {
+     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 @@
+     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 @@
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-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::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 @@
+ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 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 @@
+ {
+ }
+-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 @@
+     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 @@
+     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 @@
+             {
+                 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);
+             }
+Index: mythtv/libs/libmythtv/tv_play.cpp
+===================================================================
+--- mythtv/libs/libmythtv/tv_play.cpp  (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/tv_play.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -247,7 +247,7 @@
+       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 @@
+     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 @@
+     if (internalState != kState_None)
+         return 0;
+-    inputFilename = rcinfo->pathname;
+-
+     playbackLen = rcinfo->CalculateLength();
+     playbackinfo = new ProgramInfo(*rcinfo);
+@@ -844,9 +830,10 @@
+         }
+         else
+         {
++            QString playbackURL = playbackinfo->GetPlaybackURL();
++
+             tvchain->SetProgram(playbackinfo);
+-
+-            prbuffer = new RingBuffer(playbackinfo->pathname, false);
++            prbuffer = new RingBuffer(playbackURL, false);
+             prbuffer->SetLiveMode(tvchain);
+         }
+@@ -895,7 +882,14 @@
+     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 @@
+             {
+                 QString message = "COMMFLAG_REQUEST ";
+                 message += playbackinfo->chanid + " " +
+-                           playbackinfo->startts.toString(Qt::ISODate);
++                           playbackinfo->recstartts.toString(Qt::ISODate);
+                 RemoteSendMessage(message);
+             }                
+         }
+@@ -1222,10 +1216,10 @@
+     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 @@
+     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 @@
+                 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 @@
+                 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 @@
+         }
+         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 @@
+         }
+         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 @@
+     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 @@
+         }
+         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 @@
+             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 @@
+             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 @@
+                            "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)
+Index: mythtv/libs/libmythtv/jobqueue.cpp
+===================================================================
+--- mythtv/libs/libmythtv/jobqueue.cpp (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/jobqueue.cpp (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -275,6 +275,11 @@
+                     (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))
+Index: mythtv/libs/libmythtv/dvbdev/dvbdev.c
+===================================================================
+--- mythtv/libs/libmythtv/dvbdev/dvbdev.c      (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/dvbdev/dvbdev.c      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -29,55 +29,79 @@
+ const char* dvbdevice(int type, int cardnum)
+ {
+-    char* frontenddev[4] =
++    char* frontenddev[8] =
+     {
+         "/dev/dvb/adapter0/frontend0",
+         "/dev/dvb/adapter1/frontend0",
+         "/dev/dvb/adapter2/frontend0",
+-        "/dev/dvb/adapter3/frontend0"
++        "/dev/dvb/adapter3/frontend0",
++        "/dev/dvb/adapter4/frontend0",
++        "/dev/dvb/adapter5/frontend0",
++        "/dev/dvb/adapter6/frontend0",
++        "/dev/dvb/adapter7/frontend0",
+     };
+-    char* dvrdev[4] =
++    char* dvrdev[8] =
+     {
+         "/dev/dvb/adapter0/dvr0",
+         "/dev/dvb/adapter1/dvr0",
+         "/dev/dvb/adapter2/dvr0",
+-        "/dev/dvb/adapter3/dvr0"
++        "/dev/dvb/adapter3/dvr0",
++        "/dev/dvb/adapter4/dvr0",
++        "/dev/dvb/adapter5/dvr0",
++        "/dev/dvb/adapter6/dvr0",
++        "/dev/dvb/adapter7/dvr0",
+     };
+-    char* demuxdev[4] =
++    char* demuxdev[8] =
+     {
+         "/dev/dvb/adapter0/demux0",
+         "/dev/dvb/adapter1/demux0",
+         "/dev/dvb/adapter2/demux0",
+-        "/dev/dvb/adapter3/demux0"
++        "/dev/dvb/adapter3/demux0",
++        "/dev/dvb/adapter4/demux0",
++        "/dev/dvb/adapter5/demux0",
++        "/dev/dvb/adapter6/demux0",
++        "/dev/dvb/adapter7/demux0",
+     };
+-    char* cadev[4] =
++    char* cadev[8] =
+     {
+         "/dev/dvb/adapter0/ca0",
+         "/dev/dvb/adapter1/ca0",
+         "/dev/dvb/adapter2/ca0",
+-        "/dev/dvb/adapter3/ca0"
++        "/dev/dvb/adapter3/ca0",
++        "/dev/dvb/adapter4/ca0",
++        "/dev/dvb/adapter5/ca0",
++        "/dev/dvb/adapter6/ca0",
++        "/dev/dvb/adapter7/ca0",
+     };
+-    char* audiodev[4] =
++    char* audiodev[8] =
+     {
+         "/dev/dvb/adapter0/audio0",
+         "/dev/dvb/adapter1/audio0",
+         "/dev/dvb/adapter2/audio0",
+-        "/dev/dvb/adapter3/audio0"
++        "/dev/dvb/adapter3/audio0",
++        "/dev/dvb/adapter4/audio0",
++        "/dev/dvb/adapter5/audio0",
++        "/dev/dvb/adapter6/audio0",
++        "/dev/dvb/adapter7/audio0",
+     };
+-    char* videodev[4] =
++    char* videodev[8] =
+     {
+         "/dev/dvb/adapter0/video0",
+         "/dev/dvb/adapter1/video0",
+         "/dev/dvb/adapter2/video0",
+-        "/dev/dvb/adapter3/video0"
++        "/dev/dvb/adapter3/video0",
++        "/dev/dvb/adapter4/video0",
++        "/dev/dvb/adapter5/video0",
++        "/dev/dvb/adapter6/video0",
++        "/dev/dvb/adapter7/video0",
+     };
+-    if (cardnum > 3)
++    if (cardnum > 7)
+         return 0;
+     switch(type)
+Index: mythtv/libs/libmythtv/videosource.h
+===================================================================
+--- mythtv/libs/libmythtv/videosource.h        (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/videosource.h        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -75,6 +75,7 @@
+     static CARD_TYPES   GetDVBType(uint device, QString &name, QString &card_type);
+     static bool         HasDVBCRCBug(uint device);
++    static uint         GetMinSignalMonitoringDelay(uint device);
+     static QString      GetDefaultInput(uint cardid);
+     static bool         IgnoreEncrypted(uint cardid, const QString &inputname);
+Index: mythtv/libs/libmythtv/libmythtv.pro
+===================================================================
+--- mythtv/libs/libmythtv/libmythtv.pro        (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/libmythtv.pro        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -119,6 +119,10 @@
+ SOURCES += playgroup.cpp
+ SOURCES += progdetails.cpp
++# C stuff
++HEADERS += frequencies.h
++SOURCES += frequencies.c
++
+ using_frontend {
+     # Recording profile stuff
+     HEADERS += profilegroup.h
+@@ -144,10 +148,10 @@
+     # 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
+@@ -303,10 +307,6 @@
+         }
+     }
+-    # C stuff
+-    HEADERS += frequencies.h
+-    SOURCES += frequencies.c
+-
+     DEFINES += USING_BACKEND
+ }
+Index: mythtv/libs/libmythtv/dvbchannel.cpp
+===================================================================
+--- mythtv/libs/libmythtv/dvbchannel.cpp       (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/dvbchannel.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -74,14 +74,27 @@
+  *  \bug Only supports single input cards.
+  */
+ DVBChannel::DVBChannel(int aCardNum, TVRec *parent)
+-    : QObject(NULL, "DVBChannel"), ChannelBase(parent),
+-      diseqc(NULL),    dvbcam(NULL),
+-      fd_frontend(-1), cardnum(aCardNum), has_crc_bug(false),
+-      currentTID(-1),  first_tune(true)
++    : QObject(NULL, "DVBChannel"),  ChannelBase(parent),
++      diseqc(NULL),                 dvbcam(NULL),
++      fd_frontend(-1),              cardnum(aCardNum),
++      has_crc_bug(false),
++      tuning_delay(0),              sigmon_delay(25),
++      currentTID(-1),               first_tune(true),
++      retune_adj(-10)
+ {
+     dvbcam = new DVBCam(cardnum);
+     bzero(&info, sizeof(info));
+     has_crc_bug = CardUtil::HasDVBCRCBug(aCardNum);
++
++    QString name(""), type("");
++    CardUtil::GetDVBType(aCardNum, name, type);
++    if ((name == "DiBcom 3000P/M-C DVB-T") ||
++        (name == "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
++    {
++        tuning_delay = 200;
++    }
++
++    sigmon_delay = CardUtil::GetMinSignalMonitoringDelay(aCardNum);
+ }
+ DVBChannel::~DVBChannel()
+@@ -367,7 +380,7 @@
+     }
+     bool found = false;
+-    int mplexid;
++    int mplexid = 0;
+     while (query.next())
+     {
+         int this_inputid = query.value(4).toInt();
+@@ -633,7 +646,8 @@
+  *   This is used by DVB Channel Scanner, the EIT Parser, and by TVRec.
+  *
+  *  \param channel     Info on transport to tune to
+- *  \param force_reset If true frequency tuning is done even if not strictly needed
++ *  \param force_reset If true, frequency tuning is done
++ *                     even if it should not be needed.
+  *  \return true on success, false on failure
+  */
+ bool DVBChannel::Tune(const dvb_channel_t& channel, bool force_reset)
+@@ -642,6 +656,8 @@
+     bool has_diseq = (FE_QPSK == info.type) && diseqc;
+     struct dvb_frontend_parameters params = channel.tuning.params;
++    retune_tuning = channel.tuning;
++
+     if (fd_frontend < 0)
+     {
+         ERROR("DVBChannel::Tune: Card not open!");
+@@ -669,15 +685,22 @@
+         // Adjust for Satelite recievers which offset the frequency.
+         params.frequency = tuned_frequency(channel.tuning, info.type, NULL);
++        params.frequency = params.frequency + (retune_adj = -retune_adj);
++
+         if (ioctl(fd_frontend, FE_SET_FRONTEND, &params) < 0)
+         {
+             ERRNO("DVBChannel::Tune: "
+                   "Setting Frontend tuning parameters failed.");
+             return false;
+         }
++
++        // Extra delay to add for broken DVB drivers
++        if (tuning_delay)
++            usleep(tuning_delay * 1000);
++
+         wait_for_backend(fd_frontend, 5 /* msec */);
+-        prev_tuning.params = params;
++        prev_tuning.params = channel.tuning.params;
+         first_tune = false;
+     }
+@@ -686,6 +709,24 @@
+     return true;
+ }
++/** \fn DVBChannel::Retune(void)
++ *  \brief Calls DVBChannel::Tune() with the last known parameters
++ *
++ *   This is used to retune DVB-C hardware. DVB-C hardware
++ *   sometimes does not successfully tune the first time
++ *   despite reports of success from the drivers. This is
++ *   probably a hardware problem and not a driver problem
++ *   per say, so it is unlikely to be fixed at a lower level.
++ *
++ *  \return true iff drivers report that tuning was successful
++ */
++bool DVBChannel::Retune(void)
++{
++    dvb_channel_t retune_channel;
++    retune_channel.tuning = retune_tuning;
++    return Tune(retune_channel, true);
++}
++
+ /** \fn DVBChannel::GetTuningParams(DVBTuning& tuning) const
+  *  \brief Fetches DVBTuning params from driver
+  *  \return true on success, false on failure
+@@ -855,6 +896,9 @@
+     for (uint i = 0; i < 64 && !tuned; i++)
+         if (!diseqc->Set(t, reset, tuned))
+             return false;
+-        
++
++    // Wait 10 ms, recommended by Marcus Metzler, see #1552
++    usleep(10 * 1000);
++
+     return true;
+ }
+Index: mythtv/libs/libmythtv/osdtypes.h
+===================================================================
+--- mythtv/libs/libmythtv/osdtypes.h   (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/osdtypes.h   (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -8,6 +8,7 @@
+ #include <vector>
+ #include <qobject.h>
+ #include <qregexp.h>
++#include "osdimagecache.h"
+ using namespace std;
+@@ -137,6 +138,8 @@
+     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 @@
+ {
+   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 @@
+     QRect m_displaysize;
+     QRect m_screensize;
++    QRect m_unbiasedsize;
+     QString m_message;
+     QString m_default_msg;
+@@ -231,7 +235,7 @@
+     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,21 +243,20 @@
+     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; }
++    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(); }
+-    QRect ImageSize() { return m_imagesize; }
+-
+-    int width() { return m_imagesize.width(); }
+-    int height() { return m_imagesize.height(); }
+-
+     virtual void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, 
+                       int yoff);
+   protected:
+     QRect m_imagesize;
+     QPoint m_displaypos;
++    QPoint m_unbiasedpos;
+     QString m_filename;
+@@ -270,6 +273,9 @@
+     int m_drawwidth;
+     bool m_onlyusefirst;
++
++    static OSDImageCache  c_cache;
++    OSDImageCacheValue   *m_cacheitem;
+ };
+ class OSDTypePosSlider : public OSDTypeImage
+@@ -280,7 +286,7 @@
+                       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 @@
+   private:
+     QRect m_displayrect;
++    QRect m_unbiasedrect;
+     int m_maxval;
+     int m_curval;
+ };
+@@ -302,7 +309,7 @@
+                       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 @@
+   private:
+     QRect m_displayrect;
++    QRect m_unbiasedrect;
+     int m_maxval;
+     int m_curval;
+ };
+@@ -327,7 +335,7 @@
+                       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 @@
+   private:
+     QRect m_displayrect;
++    QRect m_unbiasedrect;
+     int m_maxval;
+     int m_curval;
+@@ -360,17 +369,19 @@
+ 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 @@
+     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 @@
+     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,11 +460,15 @@
+ {
+   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);
+     void ClearAllCCText();
+@@ -464,7 +483,7 @@
+     vector<ccText *> *m_textlist;
+     OSDTypeBox *m_box;
+     int m_ccbackground;
+-
++    float m_wmult, m_hmult;
+     int xoffset, yoffset, displaywidth, displayheight;
+ };
+Index: mythtv/libs/libmythtv/videoout_xv.h
+===================================================================
+--- mythtv/libs/libmythtv/videoout_xv.h        (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/videoout_xv.h        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -80,6 +80,8 @@
+     virtual bool hasVLDAcceleration(void) const
+         { return XVideoVLD == VideoOutputSubType(); }
++    void CheckFrameStates(void);
++
+     static MythCodecID GetBestSupportedCodec(uint width, uint height,
+                                              uint osd_width, uint osd_height,
+                                              uint stream_type, int xvmc_chroma,
+@@ -141,7 +143,7 @@
+     static bool IsRendering(VideoFrame* frame);
+     static void SyncSurface(VideoFrame* frame, int past_future = 0);
+     static void FlushSurface(VideoFrame* frame);
+-    void CheckDisplayedFramesForAvailability(void);
++
+ #ifdef USING_XVMC 
+     XvMCOSD* GetAvailableOSD();
+     void ReturnAvailableOSD(XvMCOSD*);
+Index: mythtv/libs/libmythtv/osdimagecache.h
+===================================================================
+--- mythtv/libs/libmythtv/osdimagecache.h      (.../tags/release-0-19) (revision 0)
++++ mythtv/libs/libmythtv/osdimagecache.h      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -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;
++};
+Index: mythtv/libs/libmythtv/tv_play.h
+===================================================================
+--- mythtv/libs/libmythtv/tv_play.h    (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/tv_play.h    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -456,7 +456,6 @@
+     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 @@
+     // LiveTVChain
+     LiveTVChain *tvchain;
+     LiveTVChain *piptvchain;
++    QStringList tvchainUpdate;
++    QMutex tvchainUpdateLock;
+     // RingBuffers
+     RingBuffer *prbuffer;
+Index: mythtv/libs/libmythtv/videosource.cpp
+===================================================================
+--- mythtv/libs/libmythtv/videosource.cpp      (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/videosource.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -32,6 +32,7 @@
+ #include "videosource.h"
+ #include "datadirect.h"
+ #include "scanwizard.h"
++#include "frequencies.h"
+ #ifdef USING_DVB
+ #include <linux/dvb/frontend.h>
+@@ -156,6 +157,17 @@
+             (name == "ST STV0299 DVB-S"));         // munges PAT
+ }
++uint CardUtil::GetMinSignalMonitoringDelay(uint device)
++{
++    QString name(""), type("");
++    GetDVBType(device, name, type);
++    if (name.find("DVB-S") >= 0)
++        return 300;
++    if (name == "DiBcom 3000P/M-C DVB-T")
++        return 100;
++    return 25;
++}
++
+ /** \fn CardUtil::GetCardType(uint, QString&, QString&)
+  *  \brief Returns the card type from the video device
+  *  \param nCardID   cardid of card to be checked
+@@ -574,22 +586,10 @@
+ {
+     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."));
+Index: mythtv/libs/libmythtv/frequencytables.cpp
+===================================================================
+--- mythtv/libs/libmythtv/frequencytables.cpp  (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/frequencytables.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -283,104 +283,52 @@
+         "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);
++    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 ", };
+-    // USA Cable, QAM 256 ch 78+
+-    fmap["atsc_qam256_uscablehigh0"] = new FrequencyTable(
+-        "QAM-256 Channel %1",  78,472000000,1005000000, 6000000, QAM_256);
++#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);
+-    // 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);
++    for (uint i = 0; i < 4; 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]);
+-    // 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);
++        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, 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);
++            // 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]);
++        }
++    }
+ }
+Index: mythtv/libs/libmythtv/scanwizardhelpers.h
+===================================================================
+--- mythtv/libs/libmythtv/scanwizardhelpers.h  (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/scanwizardhelpers.h  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -272,11 +272,13 @@
+   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.") + " " +
+Index: mythtv/libs/libmythtv/scanwizard.cpp
+===================================================================
+--- mythtv/libs/libmythtv/scanwizard.cpp       (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/scanwizard.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -518,7 +518,9 @@
+                     "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)
+Index: mythtv/libs/libmythtv/videoout_xv.cpp
+===================================================================
+--- mythtv/libs/libmythtv/videoout_xv.cpp      (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/videoout_xv.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -1089,6 +1089,9 @@
+     bool use_xv = true, use_shm = true;
+     QString dec = gContext->GetSetting("PreferredMPEG2Decoder", "ffmpeg");
++    if (dec != "libmpeg2" && height < 720 && 
++        gContext->GetNumSetting("UseXvMCForHDOnly", 0))
++        dec = "ffmpeg";
+     if (dec == "xvmc")
+         use_xvmc_idct = use_xvmc = true;
+     else if (dec == "xvmc-vld")
+@@ -1335,40 +1338,39 @@
+     if (attributes)
+         X11S(XFree(attributes));
+-    if (xv_draw_colorkey)
++    if (!xv_draw_colorkey)
++        return;
++
++    QString msg = LOC + "Chromakeying not possible with this XVideo port.";
++    X11S(xv_atom = XInternAtom(XJ_disp, "XV_COLORKEY", False));
++    if (xv_atom == None)
+     {
+-        X11S(xv_atom = XInternAtom(XJ_disp, "XV_COLORKEY", False));
+-        if (xv_atom != None)
+-        {
+-            X11S(ret = XvGetPortAttribute(XJ_disp, xv_port, xv_atom, 
+-                                          &xv_colorkey));
++        VERBOSE(VB_PLAYBACK, msg);
++        xv_colorkey = 0;
++        return;
++    }
+-            if (ret == Success && xv_colorkey == 0)
+-            {
+-                const int default_colorkey = 1;
+-                X11S(ret = XvSetPortAttribute(XJ_disp, xv_port, xv_atom,
+-                                              default_colorkey));
+-                if (ret == Success)
+-                {
+-                    VERBOSE(VB_PLAYBACK, LOC +
+-                            "0,0,0 is the only bad color key for MythTV, "
+-                            "using "<<default_colorkey<<" instead.");
+-                    xv_colorkey = default_colorkey;
+-                }
+-                ret = Success;
+-            }
+-
+-            if (ret != Success)
+-            {
+-                VERBOSE(VB_IMPORTANT, LOC_ERR +
+-                        "Couldn't get the color key color,"
+-                        "\n\t\t\tprobably due to a driver bug or limitation."
+-                        "\n\t\t\tYou might not get any video, "
+-                        "but we'll try anyway.");
+-                xv_colorkey = 0;
+-            }
++    X11S(ret = XvGetPortAttribute(XJ_disp, xv_port, xv_atom, &xv_colorkey));
++    if (ret == Success && xv_colorkey == 0)
++    {
++        const int default_colorkey = 1;
++        X11S(ret = XvSetPortAttribute(XJ_disp, xv_port, xv_atom,
++                                      default_colorkey));
++        if (ret == Success)
++        {
++            VERBOSE(VB_PLAYBACK, LOC +
++                    "0,0,0 is the only bad color key for MythTV, "
++                    "using "<<default_colorkey<<" instead.");
++            xv_colorkey = default_colorkey;
+         }
++        ret = Success;
+     }
++
++    if (ret != Success)
++    {
++        VERBOSE(VB_PLAYBACK, msg);
++        xv_colorkey = 0;
++    }
+ }
+ bool VideoOutputXv::SetupDeinterlace(bool interlaced,
+@@ -1955,86 +1957,75 @@
+     } while (0)
+ void VideoOutputXv::DiscardFrames(bool next_frame_keyframe)
+-{ 
++{
++    VERBOSE(VB_PLAYBACK, LOC + "DiscardFrames("<<next_frame_keyframe<<")");
+     if (VideoOutputSubType() <= XVideo)
+     {
+         vbuffers.DiscardFrames(next_frame_keyframe);
++        VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 3: %1 -- done()")
++                .arg(vbuffers.GetStatus()));
+         return;
+     }
+ #ifdef USING_XVMC
+     frame_queue_t::iterator it;
+     frame_queue_t syncs;
+-    frame_queue_t ula;
+-    frame_queue_t discards;
+-    {
+-        vbuffers.begin_lock(kVideoBuffer_displayed); // Lock X
+-        VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 1: %1")
+-                .arg(vbuffers.GetStatus()));
+-        vbuffers.end_lock(); // Lock X
+-    }
++    // Print some debugging
++    vbuffers.begin_lock(kVideoBuffer_displayed); // Lock X
++    VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 1: %1")
++            .arg(vbuffers.GetStatus()));
++    vbuffers.end_lock(); // Lock X
+-    CheckDisplayedFramesForAvailability();
+-
++    // Finish rendering all these surfaces and move them
++    // from the used queue to the displayed queue.
++    // This allows us to reuse these surfaces, if they
++    // get moved to the used list in CheckFrameStates().
++    // This will only happen if avlib isn't using them
++    // either and they are not currently being displayed.
++    vbuffers.begin_lock(kVideoBuffer_displayed); // Lock Y
++    DQ_COPY(syncs, kVideoBuffer_used);
++    for (it = syncs.begin(); it != syncs.end(); ++it)
+     {
+-        vbuffers.begin_lock(kVideoBuffer_displayed); // Lock Y
+-
+-        DQ_COPY(syncs, kVideoBuffer_displayed);
+-        DQ_COPY(syncs, kVideoBuffer_pause);
+-        for (it = syncs.begin(); it != syncs.end(); ++it)
+-        {
+-            SyncSurface(*it, -1); // sync past
+-            SyncSurface(*it, +1); // sync future
+-            SyncSurface(*it,  0); // sync current
+-            //GetRender(*it)->p_past_surface   = NULL;
+-            //GetRender(*it)->p_future_surface = NULL;
+-        }
+-        VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 2: %1")
+-                .arg(vbuffers.GetStatus()));
+-#if 0
+-        // Remove inheritence of all frames not in displayed or pause
+-        DQ_COPY(ula, kVideoBuffer_used);
+-        DQ_COPY(ula, kVideoBuffer_limbo);
+-        DQ_COPY(ula, kVideoBuffer_avail);
+-        
+-        for (it = ula.begin(); it != ula.end(); ++it)
+-            vbuffers.RemoveInheritence(*it);
+-#endif
+-
+-        VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 3: %1")
+-                .arg(vbuffers.GetStatus()));
+-        // create discard frame list
+-        DQ_COPY(discards, kVideoBuffer_used);
+-        DQ_COPY(discards, kVideoBuffer_limbo);
+-
+-        vbuffers.end_lock(); // Lock Y
++        SyncSurface(*it, -1); // sync past
++        SyncSurface(*it, +1); // sync future
++        SyncSurface(*it,  0); // sync current
++        vbuffers.safeEnqueue(kVideoBuffer_displayed, *it);
+     }
++    syncs.clear();
++    vbuffers.end_lock(); // Lock Y
+-    for (it = discards.begin(); it != discards.end(); ++it)
+-        DiscardFrame(*it);
++    CheckFrameStates();
++    // If the next frame is a keyframe we can clear out a lot more...
++    if (next_frame_keyframe)
+     {
+         vbuffers.begin_lock(kVideoBuffer_displayed); // Lock Z
+-        syncs.clear();
+-        DQ_COPY(syncs, kVideoBuffer_displayed);
+-        DQ_COPY(syncs, kVideoBuffer_pause);
++        // Move all the limbo and pause frames to displayed
++        DQ_COPY(syncs, kVideoBuffer_limbo);
+         for (it = syncs.begin(); it != syncs.end(); ++it)
+         {
+             SyncSurface(*it, -1); // sync past
+             SyncSurface(*it, +1); // sync future
+             SyncSurface(*it,  0); // sync current
+-            //GetRender(*it)->p_past_surface   = NULL;
+-            //GetRender(*it)->p_future_surface = NULL;
++            vbuffers.safeEnqueue(kVideoBuffer_displayed, *it);
+         }
+-        VERBOSE(VB_PLAYBACK, LOC +
+-                QString("DiscardFrames() 4: %1 -- done() ")
++        VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 2: %1")
+                 .arg(vbuffers.GetStatus()));
+-        
++
+         vbuffers.end_lock(); // Lock Z
++
++        // Now call CheckFrameStates() to remove inheritence and
++        // move the surfaces to the used list if possible (i.e.
++        // if avlib is not using them and they are not currently
++        // being displayed on screen).
++        CheckFrameStates();
+     }
++    VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 3: %1 -- done()")
++            .arg(vbuffers.GetStatus()));
++        
+ #endif // USING_XVMC
+ }
+@@ -2071,7 +2062,7 @@
+         if (osdframe)
+             DiscardFrame(osdframe);
+     }
+-    CheckDisplayedFramesForAvailability();
++    CheckFrameStates();
+ #endif
+ }
+@@ -2411,7 +2402,7 @@
+             DiscardFrame(vbuffers.dequeue(kVideoBuffer_pause));
+     }
+     // clear any displayed frames not on screen
+-    CheckDisplayedFramesForAvailability();
++    CheckFrameStates();
+     // unlock the frame[s]
+     vbuffers.UnlockFrame(osdframe, "ShowXvMC -- OSD");
+@@ -2659,7 +2650,7 @@
+                     .arg(vbuffers.size(kVideoBuffer_pause)));
+             while (vbuffers.size(kVideoBuffer_pause))
+                 DiscardFrame(vbuffers.dequeue(kVideoBuffer_pause));
+-            CheckDisplayedFramesForAvailability();
++            CheckFrameStates();
+         } else if (1 == vbuffers.size(kVideoBuffer_pause))
+         {
+             VideoFrame *frame = vbuffers.dequeue(kVideoBuffer_used);
+@@ -2791,7 +2782,7 @@
+             // If there are no available buffer, try to toss old
+             // displayed frames.
+             if (!vbuffers.size(kVideoBuffer_avail))
+-                CheckDisplayedFramesForAvailability();
++                CheckFrameStates();
+             // If tossing doesn't work try hiding showing frames,
+             // then tossing displayed frames.
+@@ -2805,7 +2796,7 @@
+                                              GetRender(*it)->p_surface));
+                 vbuffers.end_lock();
+-                CheckDisplayedFramesForAvailability();
++                CheckFrameStates();
+             }
+             // If there is an available buffer grab it.
+@@ -3013,7 +3004,7 @@
+     return -1;
+ }
+-void VideoOutputXv::CheckDisplayedFramesForAvailability(void)
++void VideoOutputXv::CheckFrameStates(void)
+ {
+ #ifdef USING_XVMC
+     frame_queue_t::iterator it;
+@@ -3084,6 +3075,13 @@
+                     }
+                 }
+             }
++            else if (vbuffers.contains(kVideoBuffer_decode, pframe))
++            {
++                VERBOSE(VB_PLAYBACK, LOC + QString(
++                            "Frame %1 is in use by avlib and so is "
++                            "being held for later discarding.")
++                        .arg(DebugString(pframe, true)));
++            }
+             else
+             {
+                 vbuffers.RemoveInheritence(pframe);
+Index: mythtv/libs/libmythtv/signalmonitor.h
+===================================================================
+--- mythtv/libs/libmythtv/signalmonitor.h      (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/signalmonitor.h      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -7,6 +7,10 @@
+ // C headers
+ #include <pthread.h>
++// C++ headers
++#include <algorithm>
++using namespace std;
++
+ // Qt headers
+ #include <qobject.h>
+ #include <qmutex.h>
+@@ -125,7 +129,8 @@
+      *   Defaults to 25 milliseconds.
+      *  \param msec Milliseconds between signal monitoring events.
+      */
+-    void SetUpdateRate(int msec) { update_rate = msec; }
++    void SetUpdateRate(int msec)
++        { update_rate = max(msec, (int)minimum_update_rate); }
+   public slots:
+     virtual void deleteLater(void);
+@@ -164,6 +169,7 @@
+     int          capturecardnum;
+     uint         flags;
+     int          update_rate;
++    uint         minimum_update_rate;
+     bool         running;
+     bool         exit;
+     bool         update_done;
+Index: mythtv/libs/libmythtv/RingBuffer.h
+===================================================================
+--- mythtv/libs/libmythtv/RingBuffer.h (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/RingBuffer.h (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -91,6 +91,7 @@
+     long long GetTotalReadPosition(void);
+     long long SetAdjustFilesize(void);
++    void SetTimeout(bool fast) { oldfile = fast; }
+     
+   protected:
+     static void *StartReader(void *type);
+Index: mythtv/libs/libmythtv/dvbtypes.cpp
+===================================================================
+--- mythtv/libs/libmythtv/dvbtypes.cpp (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/dvbtypes.cpp (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -202,7 +202,7 @@
+ {
+    {"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 @@
+ {
+    {"999",TRANSMISSION_MODE_AUTO},
+    {"2",TRANSMISSION_MODE_2K},
+-   {"8",TRANSMISSION_MODE_2K},
++   {"8",TRANSMISSION_MODE_8K},
+    {NULL,TRANSMISSION_MODE_AUTO},
+ };
+@@ -218,7 +218,7 @@
+ {
+    {"auto",TRANSMISSION_MODE_AUTO},
+    {"2",TRANSMISSION_MODE_2K},
+-   {"8",TRANSMISSION_MODE_2K},
++   {"8",TRANSMISSION_MODE_8K},
+    {NULL,TRANSMISSION_MODE_AUTO},
+ };
+Index: mythtv/libs/libmythtv/mpegrecorder.cpp
+===================================================================
+--- mythtv/libs/libmythtv/mpegrecorder.cpp     (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/mpegrecorder.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -363,9 +363,9 @@
+     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 @@
+                 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;
+         }
+Index: mythtv/libs/libmythtv/ivtvdecoder.cpp
+===================================================================
+--- mythtv/libs/libmythtv/ivtvdecoder.cpp      (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/ivtvdecoder.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -270,7 +270,9 @@
+     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)
+Index: mythtv/libs/libmythtv/dvbsignalmonitor.cpp
+===================================================================
+--- mythtv/libs/libmythtv/dvbsignalmonitor.cpp (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/dvbsignalmonitor.cpp (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -100,6 +100,10 @@
+ #undef DVB_IO
+     AddFlags(newflags);
+     DBG_SM("constructor()", QString("initial flags 0x%1").arg(newflags,0,16));
++
++    minimum_update_rate = _channel->GetMinSignalMonitorDelay();
++    if (minimum_update_rate > 30)
++        usleep(minimum_update_rate * 1000);
+ }
+ /** \fn DVBSignalMonitor::~DVBSignalMonitor()
+@@ -348,8 +352,8 @@
+         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");
+Index: mythtv/libs/libmythtv/tv_rec.cpp
+===================================================================
+--- mythtv/libs/libmythtv/tv_rec.cpp   (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/tv_rec.cpp   (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -130,6 +130,11 @@
+       // RingBuffer info
+       ringBuffer(NULL), rbFilePrefix(""), rbFileExt("mpg")
+ {
++      // Retune stuff
++      retune_timer = new TuningTimer();
++      retune_timer->setTimeout(10000);
++      retune_timer->start();
++      retune_requests = 0;
+ }
+ /** \fn TVRec::Init()
+@@ -3221,6 +3226,8 @@
+  */
+ void TVRec::HandleTuning(void)
+ {
++    bool handle_done = false;
++
+     if (tuningRequests.size())
+     {
+         const TuningRequest *request = &tuningRequests.front();
+@@ -3232,7 +3239,12 @@
+                               kFlagEITScan|kFlagAntennaAdjust))
+         {
+             if (!recorder)
++            {
+                 TuningFrequency(*request);
++                retune_timer->restart();
++                retune_timer->addMSecs(1);
++                retune_requests = 0;
++            }
+             else
+                 SetFlags(kFlagWaitingForRecPause);
+         }
+@@ -3261,15 +3273,29 @@
+     if (HasFlags(kFlagWaitingForSignal))
+     {
+         if (!TuningSignalCheck())
+-            return;
++            handle_done = true;
+     }
+     if (HasFlags(kFlagWaitingForSIParser))
+     {
+         if (!TuningPMTCheck())
+-            return;
++            handle_done = true;
+     }
++#ifdef USING_DVB
++    // Just because we have signal, we may not have the right transponder
++    if ((HasFlags(kFlagWaitingForSignal) ||
++         HasFlags(kFlagWaitingForSIParser)) &&
++        (!retune_timer->elapsed() && (retune_requests < 30)))
++    {
++        RetuneChannel();
++        retune_requests++;
++    }
++#endif // USING_DVB
++
++    if (handle_done)
++        return;
++
+     if (HasFlags(kFlagNeedToStartRecorder))
+     { 
+         if (recorder)
+@@ -3354,6 +3380,19 @@
+     ClearFlags(kFlagPendingActions);
+ }
++/** \fn TVRec::RetuneChannel(void)
++ *  \brief Retunes a DVB channel
++ *  \return DVBChannel::Retune() or false if ifndef USING_DVB
++ */
++bool TVRec::RetuneChannel(void)
++{
++#ifdef USING_DVB
++    if (GetDVBChannel())
++        return GetDVBChannel()->Retune();
++#endif // USING_DVB
++    return false;
++}
++
+ /** \fn TVRec::TuningFrequency(const TuningRequest&)
+  *  \brief Performs initial tuning required for any tuning event.
+  *
+Index: mythtv/libs/libmythtv/videooutbase.h
+===================================================================
+--- mythtv/libs/libmythtv/videooutbase.h       (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/videooutbase.h       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -256,6 +256,8 @@
+     ///        onto the queue of frames ready for decoding onto.
+     virtual void DiscardFrames(bool kf) { vbuffers.DiscardFrames(kf); }
++    virtual void CheckFrameStates(void) { }
++
+     /// \bug not implemented correctly. vpos is not updated.
+     VideoFrame *GetLastDecodedFrame(void) { return vbuffers.GetLastDecodedFrame(); }
+Index: mythtv/libs/libmythtv/osdimagecache.cpp
+===================================================================
+--- mythtv/libs/libmythtv/osdimagecache.cpp    (.../tags/release-0-19) (revision 0)
++++ mythtv/libs/libmythtv/osdimagecache.cpp    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -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();
++}
+Index: mythtv/libs/libmythtv/osd.cpp
+===================================================================
+--- mythtv/libs/libmythtv/osd.cpp      (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/osd.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -154,7 +154,8 @@
+         }
+         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 @@
+         }
+     }
+-    OSDTypeBox *box = new OSDTypeBox(name, area);
++    OSDTypeBox *box = new OSDTypeBox(name, area, wmult, hmult);
+     container->AddType(box);
+ }
+@@ -658,7 +659,7 @@
+         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 @@
+                 QRect area = parseRect(getFirstText(info));
+                 normalizeRect(area);
+-                rects->AddPosition(area);
++                rects->AddPosition(area, wmult, hmult);
+             }
+             else
+             {
+@@ -919,7 +920,7 @@
+                 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 @@
+         image = new OSDTypeImage(*editarrowright);
+     }
+-    image->SetPosition(QPoint(xpos, ypos));
++    image->SetPosition(QPoint(xpos, ypos), wmult, hmult);
+     set->AddType(image);
+     set->Display();
+Index: mythtv/libs/libmythtv/tv_rec.h
+===================================================================
+--- mythtv/libs/libmythtv/tv_rec.h     (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/tv_rec.h     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -13,6 +13,7 @@
+ #include "mythdeque.h"
+ #include "programinfo.h"
+ #include "tv.h"
++#include "util.h"
+ class QSocket;
+ class NuppelVideoRecorder;
+@@ -48,6 +49,30 @@
+     BROWSE_FAVORITE ///< Fetch information on the next favorite channel
+ } BrowseDirections;
++class TuningTimer
++{
++  public:
++    TuningTimer() {}
++
++    void setTimeout(long t) { _timeout = t; }
++    long timeout(void) { return _timeout; }
++    void start() { t_timer.start(); }
++    int restart() { int ret = elapsed();
++                    t_timer.restart();
++                    return ret;
++                  }
++    int elapsed() { int ret = t_timer.elapsed();
++                    if (ret > _timeout) { ret = 0;  t_timer.restart(); }
++                    return ret;
++                  }
++
++    void addMSecs(int ms) { t_timer.addMSecs(ms); }
++
++  private:
++    QTime t_timer;
++    long _timeout;
++};
++
+ class GeneralDBOptions
+ {
+   public:
+@@ -275,6 +300,7 @@
+     bool TuningPMTCheck(void);
+     void TuningNewRecorder(void);
+     void TuningRestartRecorder(void);
++    bool RetuneChannel(void);
+     void HandleStateChange(void);
+     void ChangeState(TVState nextState);
+@@ -362,6 +388,10 @@
+     QString      rbFilePrefix;
+     QString      rbFileExt;
++    // Retune stuff
++    TuningTimer *retune_timer;
++    int          retune_requests;
++
+   public:
+     static const uint kEITScanStartTimeout;
+     static const uint kSignalMonitoringRate;
+Index: mythtv/libs/libmythtv/videobuffers.h
+===================================================================
+--- mythtv/libs/libmythtv/videobuffers.h       (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/videobuffers.h       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -40,6 +40,7 @@
+     kVideoBuffer_used      = 0x00000004,
+     kVideoBuffer_pause     = 0x00000008,
+     kVideoBuffer_displayed = 0x00000010,
++    kVideoBuffer_decode    = 0x00000020,
+     kVideoBuffer_all       = 0x0000001F,
+ };
+@@ -159,7 +160,6 @@
+     uint                   vpos;
+     mutable QMutex         global_lock;
+-    QMutex                 inheritence_lock;
+     bool                   use_frame_locks;
+     QMutex                 frame_lock;
+Index: mythtv/libs/libmythtv/dvbconfparser.cpp
+===================================================================
+--- mythtv/libs/libmythtv/dvbconfparser.cpp    (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/dvbconfparser.cpp    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -193,10 +193,10 @@
+     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;
+Index: mythtv/libs/libmythtv/pchdtvsignalmonitor.cpp
+===================================================================
+--- mythtv/libs/libmythtv/pchdtvsignalmonitor.cpp      (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/pchdtvsignalmonitor.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -108,8 +108,8 @@
+         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");
+ }
+Index: mythtv/libs/libmythtv/videobuffers.cpp
+===================================================================
+--- mythtv/libs/libmythtv/videobuffers.cpp     (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmythtv/videobuffers.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -84,7 +84,7 @@
+     : numbuffers(0), needfreeframes(0), needprebufferframes(0),
+       needprebufferframes_normal(0), needprebufferframes_small(0),
+       keepprebufferframes(0), need_extra_for_pause(false), rpos(0), vpos(0),
+-      global_lock(true), inheritence_lock(false), use_frame_locks(true),
++      global_lock(true), use_frame_locks(true),
+       frame_lock(true)
+ {
+ }
+@@ -125,6 +125,8 @@
+ {
+     global_lock.lock();
++    Reset();
++
+     uint numcreate = numdecode + ((extra_for_pause) ? 1 : 0);
+     // make a big reservation, so that things that depend on
+@@ -409,6 +411,8 @@
+         q = &limbo;
+     else if (type == kVideoBuffer_pause)
+         q = &pause;
++    else if (type == kVideoBuffer_decode)
++        q = &decode;
+     global_lock.unlock();
+     return q;
+@@ -429,6 +433,8 @@
+         q = &limbo;
+     else if (type == kVideoBuffer_pause)
+         q = &pause;
++    else if (type == kVideoBuffer_decode)
++        q = &decode;
+     global_lock.unlock();
+     return q;
+@@ -503,6 +509,8 @@
+             limbo.remove(frame);
+         if ((type & kVideoBuffer_pause) == kVideoBuffer_pause)
+             pause.remove(frame);
++        if ((type & kVideoBuffer_decode) == kVideoBuffer_decode)
++            decode.remove(frame);
+         global_lock.unlock();
+     }
+ }
+@@ -857,7 +865,7 @@
+ {
+     (void)frame;
+ #ifdef USING_XVMC
+-    inheritence_lock.lock();
++    global_lock.lock();
+     
+     frame_map_t::iterator it = parents.find(frame);
+     if (it == parents.end())
+@@ -902,18 +910,18 @@
+             children[*it].push_back((VideoFrame*)frame);
+     }
+-    inheritence_lock.unlock();
++    global_lock.unlock();
+ #endif // USING_XVMC
+ }
+ void VideoBuffers::RemoveInheritence(const VideoFrame *frame)
+ {
+-    inheritence_lock.lock();
++    global_lock.lock();
+     frame_map_t::iterator it = parents.find(frame);
+     if (it == parents.end())
+     {
+-        inheritence_lock.unlock();
++        global_lock.unlock();
+         return;
+     }
+@@ -945,7 +953,7 @@
+                     .arg(i).arg(DebugString(*pit)));
+     }
+-    inheritence_lock.unlock();
++    global_lock.unlock();
+ }
+ frame_queue_t VideoBuffers::Children(const VideoFrame *frame)
+Index: mythtv/libs/libavformat/aviobuf.c
+===================================================================
+--- mythtv/libs/libavformat/aviobuf.c  (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libavformat/aviobuf.c  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -164,7 +164,13 @@
+ 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)
+Index: mythtv/libs/libmyth/lcddevice.cpp
+===================================================================
+--- mythtv/libs/libmyth/lcddevice.cpp  (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmyth/lcddevice.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -150,7 +150,7 @@
+     if (!connected)
+     {
+-        QTextStream os(socket);
++        QTextStream os(socket->socketDevice());
+         int count = 0;
+         do
+@@ -213,7 +213,7 @@
+         return;
+     }
+-    QTextStream os(socket);
++    QTextStream os(socket->socketDevice());
+    
+     last_command = someText;
+  
+@@ -224,7 +224,7 @@
+ #endif
+         // Just stream the text out the socket
+-        os << someText << "\n" << flush;
++        os << someText << "\n";
+     }
+     else
+     {
+Index: mythtv/libs/libmyth/audiooutputca.cpp
+===================================================================
+--- mythtv/libs/libmyth/audiooutputca.cpp      (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmyth/audiooutputca.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -21,6 +21,7 @@
+ #include "mythcontext.h"
+ #include "audiooutputca.h"
++#include "config.h"
+ // this holds Core Audio member variables
+ struct CoreAudioData {
+@@ -107,8 +108,10 @@
+     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;
+Index: mythtv/libs/libmyth/util.cpp
+===================================================================
+--- mythtv/libs/libmyth/util.cpp       (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmyth/util.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -1006,16 +1006,20 @@
+     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;
+ }
+Index: mythtv/libs/libmyth/mythdialogs.cpp
+===================================================================
+--- mythtv/libs/libmyth/mythdialogs.cpp        (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmyth/mythdialogs.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -2617,6 +2617,7 @@
+     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 &)));
+Index: mythtv/libs/libmyth/mythwidgets.cpp
+===================================================================
+--- mythtv/libs/libmyth/mythwidgets.cpp        (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmyth/mythwidgets.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -353,7 +353,8 @@
+                     (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 @@
+                 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 @@
+     if (handled)
+         return;
+-    if (!handled && popup && popup->isShown())
++    if (popup && popup->isShown())
+     {
+         endCycle();
+         QTextEdit::keyPressEvent(e);
+Index: mythtv/libs/libmyth/remotefile.h
+===================================================================
+--- mythtv/libs/libmyth/remotefile.h   (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmyth/remotefile.h   (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -27,6 +27,8 @@
+     long long GetFileSize(void);
++    void SetTimeout(bool fast);
++
+   private:
+     QSocketDevice *openSocket(bool control);
+@@ -43,6 +45,7 @@
+     QMutex lock;
+     long long filesize;
++    bool timeoutisfast;
+ };
+ #endif
+Index: mythtv/libs/libmyth/mythwidgets.h
+===================================================================
+--- mythtv/libs/libmyth/mythwidgets.h  (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmyth/mythwidgets.h  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -122,17 +122,21 @@
+     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 @@
+     VirtualKeyboard *popup;
+     QString helptext;
+     bool rw;
++    bool allowVirtualKeyboard;
+     PopupPosition popupPosition;
+ };
+Index: mythtv/libs/libmyth/mythcontext.cpp
+===================================================================
+--- mythtv/libs/libmyth/mythcontext.cpp        (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmyth/mythcontext.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -2621,9 +2621,13 @@
+         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 @@
+                 }
+                 d->lastLogCounts[module] = 0;
+-                d->lastLogStrings[module] = message;
++                d->lastLogStrings[module] = fullMsg;
+             }
+         }
+@@ -2693,7 +2697,7 @@
+         }
+         if (priority <= d->m_logprintlevel)
+-            VERBOSE(VB_IMPORTANT, module + ": " + message);
++            VERBOSE(VB_IMPORTANT, module + ": " + fullMsg);
+     }
+ }
+Index: mythtv/libs/libmyth/remotefile.cpp
+===================================================================
+--- mythtv/libs/libmyth/remotefile.cpp (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libmyth/remotefile.cpp (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -15,6 +15,7 @@
+     path = url;
+     readposition = 0;
+     filesize = -1;
++    timeoutisfast = false;
+     query = "QUERY_FILETRANSFER %1";
+@@ -295,4 +296,34 @@
+     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;
++}
++
+Index: mythtv/libs/libavcodec/libavcodec.pro
+===================================================================
+--- mythtv/libs/libavcodec/libavcodec.pro      (.../tags/release-0-19) (revision 10931)
++++ mythtv/libs/libavcodec/libavcodec.pro      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -430,4 +430,5 @@
+     LIBS               += -lz
+     QMAKE_LFLAGS_SHLIB += -single_module
+     QMAKE_LFLAGS_SHLIB += -seg1addr 0xC3000000
++    QMAKE_LFLAGS_SHLIB += -read_only_relocs warning
+ }
+Index: mythtv/programs/mythfrontend/playbackbox.cpp
+===================================================================
+--- mythtv/programs/mythfrontend/playbackbox.cpp       (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythfrontend/playbackbox.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -17,6 +17,7 @@
+ #include <qsqldatabase.h>
+ #include <qmap.h>
++#include <cmath>
+ #include <unistd.h>
+ #include <iostream>
+@@ -140,6 +141,7 @@
+       // 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 @@
+     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 @@
+         !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? */
+@@ -1272,10 +1280,10 @@
+         paintSkipUpdate = false;
+         update(drawTotalBounds);
+     }
++    else if (arrowAccel)
++        showActionsSelected();
+     else if (curitem && curitem->availableStatus != asAvailable)
+         showAvailablePopup(curitem);
+-    else if (arrowAccel)
+-        showActionsSelected();    
+ }
+ void PlaybackBox::cursorDown(bool page, bool newview)
+@@ -1380,6 +1388,7 @@
+         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 @@
+         vector<ProgramInfo *>::iterator i = infoList->begin();
+         for ( ; i != infoList->end(); i++)
+         {
++            progsInDB++;
+             p = *i;
+             if ((((p->recgroup == recGroup) ||
+                   ((recGroup == "All Programs") &&
+@@ -1886,7 +1896,8 @@
+     if (inTitle && haveGroupInfoSet)
+         return;
+-    if (curitem->availableStatus != asAvailable)
++    if ((curitem->availableStatus != asAvailable) &&
++        (curitem->availableStatus != asFileNotFound))
+         showAvailablePopup(curitem);
+     else
+         showActions(curitem);
+@@ -2068,7 +2079,21 @@
+     delitem = new ProgramInfo(*toExp);
+-    if (delitem->availableStatus != asAvailable)
++    if (fileExists(delitem) == false)
++    {
++        QString msg =
++            QString("PlaybackBox::showActions(): Error, %1 file not found")
++            .arg(delitem->pathname);
++        VERBOSE(VB_IMPORTANT, msg);
++
++        ProgramInfo *tmpItem = findMatchingProg(delitem);
++        if (tmpItem)
++        {
++            tmpItem->availableStatus = asFileNotFound;
++            showFileNotFoundActionPopup(delitem);
++        }
++    }
++    else if (delitem->availableStatus != asAvailable)
+         showAvailablePopup(delitem);
+     else
+         showActionPopup(delitem);
+@@ -2647,6 +2672,34 @@
+     expectingPopup = true;
+ }
++void PlaybackBox::showFileNotFoundActionPopup(ProgramInfo *program)
++{
++    if (!curitem || !program)
++        return;
++
++    popup = new MythPopupBox(gContext->GetMainWindow(), drawPopupSolid,
++                             drawPopupFgColor, drawPopupBgColor,
++                             drawPopupSelColor, "action popup");
++
++    QString msg = QObject::tr("Recording Unavailable") + "\n";
++    msg += QObject::tr("The file for this recording can "
++                       "not be found") + "\n";
++
++    initPopup(popup, program, "", msg);
++
++    QButton *detailsButton;
++    detailsButton = popup->addButton(tr("Show Program Details"), this,
++                                     SLOT(showProgramDetails()));
++
++    popup->addButton(tr("Delete"), this, SLOT(askDelete()));
++
++    popup->ShowPopup(this, SLOT(doCancel()));
++
++    detailsButton->setFocus();
++
++    expectingPopup = true;
++}
++
+ void PlaybackBox::initPopup(MythPopupBox *popup, ProgramInfo *program,
+                             QString message, QString message2)
+ {
+@@ -4129,8 +4182,7 @@
+     if (!recGroupListBox)
+         return;
+-    QString item = 
+-        recGroupListBox->currentText().section('[', 0, 0).simplifyWhiteSpace();
++    QString item = recGroupListBox->currentText().section(" [", 0, 0);
+     if (item.left(5) == "-----")
+     {
+@@ -4147,8 +4199,7 @@
+ void PlaybackBox::setGroupFilter(void)
+ {
+-    recGroup =
+-        recGroupListBox->currentText().section('[', 0, 0).simplifyWhiteSpace();
++    recGroup = recGroupListBox->currentText().section(" [", 0, 0);
+     if (groupnameAsAllProg)
+         groupDisplayName = recGroup;
+Index: mythtv/programs/mythfrontend/customrecord.cpp
+===================================================================
+--- mythtv/programs/mythfrontend/customrecord.cpp      (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythfrontend/customrecord.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -149,7 +149,7 @@
+     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 @@
+     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())
+         {
+Index: mythtv/programs/mythfrontend/tv_schedule.xml
+===================================================================
+--- mythtv/programs/mythfrontend/tv_schedule.xml       (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythfrontend/tv_schedule.xml       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -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>
+Index: mythtv/programs/mythfrontend/playbackbox.h
+===================================================================
+--- mythtv/programs/mythfrontend/playbackbox.h (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythfrontend/playbackbox.h (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -237,6 +237,7 @@
+     void promptEndOfRecording(ProgramInfo *);
+     void showDeletePopup(ProgramInfo *, deletePopupType);
+     void showActionPopup(ProgramInfo *program);
++    void showFileNotFoundActionPopup(ProgramInfo *program);
+     void initPopup(MythPopupBox *popup, ProgramInfo *program, 
+                    QString message, QString message2);
+     void cancelPopup();
+@@ -337,6 +338,7 @@
+     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"
+Index: mythtv/programs/mythfrontend/networkcontrol.cpp
+===================================================================
+--- mythtv/programs/mythfrontend/networkcontrol.cpp    (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythfrontend/networkcontrol.cpp    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -469,7 +469,7 @@
+             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")
+Index: mythtv/programs/mythtranscode/mpeg2fix.cpp
+===================================================================
+--- mythtv/programs/mythtranscode/mpeg2fix.cpp (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythtranscode/mpeg2fix.cpp (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -1776,6 +1776,7 @@
+         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 @@
+             }
+             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 @@
+                         if (! new_discard_state)
+                         {
+-                            AddSequence(markedFrame, vFrame.first());
++                            AddSequence(markedFrame, seqFrame);
+                             RenumberFrames(frame_pos + Lreorder.at(),
+                                             - GetFrameNum(markedFrame));
+                         }
+Index: mythtv/programs/mythcommflag/main.cpp
+===================================================================
+--- mythtv/programs/mythcommflag/main.cpp      (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythcommflag/main.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -895,9 +895,6 @@
+         return COMMFLAG_EXIT_INVALID_CMDLINE;
+     }
+-    if (queueJobInstead)
+-        return QueueCommFlagJob(chanid, starttime);
+-
+     if (copyToCutlist)
+         return CopySkipListToCutList(chanid, starttime);
+@@ -1009,7 +1006,10 @@
+                 if ( allRecorded )
+                 {
+-                    FlagCommercials(chanid, starttime);
++                    if (queueJobInstead)
++                        QueueCommFlagJob(chanid, starttime);
++                    else
++                        FlagCommercials(chanid, starttime);
+                 }
+                 else
+                 {
+@@ -1063,7 +1063,12 @@
+                             if ((flagStatus == COMM_FLAG_NOT_FLAGGED) &&
+                                 (marksFound == 0))
+-                                FlagCommercials(chanid, starttime);
++                            {
++                                if (queueJobInstead)
++                                    QueueCommFlagJob(chanid, starttime);
++                                else
++                                    FlagCommercials(chanid, starttime);
++                            }
+                         }
+                     }
+                 }
+Index: mythtv/programs/mythbackend/mainserver.cpp
+===================================================================
+--- mythtv/programs/mythbackend/mainserver.cpp (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythbackend/mainserver.cpp (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -1919,11 +1919,8 @@
+     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 @@
+         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));
+Index: mythtv/programs/mythbackend/scheduler.cpp
+===================================================================
+--- mythtv/programs/mythbackend/scheduler.cpp  (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythbackend/scheduler.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -35,8 +35,7 @@
+ #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 @@
+         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 @@
+             
+         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 @@
+         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
+Index: mythtv/programs/mythbackend/housekeeper.cpp
+===================================================================
+--- mythtv/programs/mythbackend/housekeeper.cpp        (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythbackend/housekeeper.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -138,7 +138,6 @@
+     while (1)
+     {
+-        VERBOSE(VB_IMPORTANT, "Running HouseKeeping");
+         gContext->LogEntry("mythbackend", LP_DEBUG,
+                            "Running housekeeping thread", "");
+Index: mythtv/programs/mythbackend/scheduler.h
+===================================================================
+--- mythtv/programs/mythbackend/scheduler.h    (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythbackend/scheduler.h    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -23,8 +23,7 @@
+ {
+   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);
+Index: mythtv/programs/mythbackend/filetransfer.cpp
+===================================================================
+--- mythtv/programs/mythbackend/filetransfer.cpp       (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythbackend/filetransfer.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -131,3 +131,9 @@
+     return size;
+ }
++
++void FileTransfer::SetTimeout(bool fast)
++{
++    rbuffer->SetTimeout(fast);
++}
++
+Index: mythtv/programs/mythbackend/autoexpire.cpp
+===================================================================
+--- mythtv/programs/mythbackend/autoexpire.cpp (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythbackend/autoexpire.cpp (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -291,7 +291,8 @@
+     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);
+Index: mythtv/programs/mythbackend/filetransfer.h
+===================================================================
+--- mythtv/programs/mythbackend/filetransfer.h (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythbackend/filetransfer.h (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -35,6 +35,8 @@
+     long long GetFileSize(void);
++    void SetTimeout(bool fast);
++
+   private:
+     bool readthreadlive;
+     QMutex readthreadLock;
+Index: mythtv/programs/mythtv/main.cpp
+===================================================================
+--- mythtv/programs/mythtv/main.cpp    (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythtv/main.cpp    (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -13,8 +13,6 @@
+ #include <iostream>
+ using namespace std;
+-MythContext *gContext;
+-
+ static void *run_priv_thread(void *data)
+ {
+     (void)data;
+@@ -102,6 +100,9 @@
+     
+     gContext->LoadQtConfig();
++#if defined(Q_OS_MACX) 
++    // Mac OS X doesn't define the AudioOutputDevice setting 
++#else
+     QString auddevice = gContext->GetSetting("AudioOutputDevice");
+     if (auddevice == "" || auddevice == QString::null)
+     {
+@@ -109,6 +110,7 @@
+                 "to run 'mythfrontend', not 'mythtv'.");
+         return TV_EXIT_NO_AUDIO;
+     }
++#endif
+     print_verbose_messages |= VB_PLAYBACK | VB_LIBAV;// | VB_AUDIO;
+@@ -132,6 +134,7 @@
+         ProgramInfo *pginfo = new ProgramInfo();
+         pginfo->endts = QDateTime::currentDateTime().addSecs(-180);
+         pginfo->pathname = filename;
++        pginfo->isVideo = true;
+     
+         tv->Playback(pginfo);
+     }
+Index: mythtv/programs/mythfilldatabase/filldata.cpp
+===================================================================
+--- mythtv/programs/mythfilldatabase/filldata.cpp      (.../tags/release-0-19) (revision 10931)
++++ mythtv/programs/mythfilldatabase/filldata.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -337,7 +337,7 @@
+     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 @@
+                         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 @@
+              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.");
+Index: mythtv/setup/backendsettings.cpp
+===================================================================
+--- mythtv/setup/backendsettings.cpp   (.../tags/release-0-19) (revision 10931)
++++ mythtv/setup/backendsettings.cpp   (.../branches/release-0-19-fixes)       (revision 10931)
+@@ -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 @@
+ {
+     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."));
diff --git a/mythtv-configure.patch b/mythtv-configure.patch
new file mode 100644 (file)
index 0000000..66fb78c
--- /dev/null
@@ -0,0 +1,11 @@
+--- mythtv-0.20/configure      2006-09-14 15:58:26.000000000 +0300
++++ mythtv/configure   2006-09-05 05:09:59.000000000 +0300
+@@ -452,7 +452,7 @@
+             x"$processor" = x"unknown" -o x"$processor" = x"powerpc" ; then 
+         processor=`/usr/bin/hostinfo | grep "Processor type:"` 
+         processor=${processor#Processor type: *} 
+-        processor=${processor% (*} 
++        processor="${processor% \(*}"
+         if test x"`echo $processor | cut -c1-3`" = x"ppc" ; then
+             tune=$processor 
+         else 
diff --git a/mythtv-dvdnav-shared.patch b/mythtv-dvdnav-shared.patch
new file mode 100644 (file)
index 0000000..e4b1b4a
--- /dev/null
@@ -0,0 +1,64 @@
+diff -urN mythtv-0.20/libs/libmythdvdnav/libmythdvdnav.pro mythtv-0.20.new/libs/libmythdvdnav/libmythdvdnav.pro
+--- mythtv-0.20/libs/libmythdvdnav/libmythdvdnav.pro   2006-02-17 11:27:03.000000000 +0100
++++ mythtv-0.20.new/libs/libmythdvdnav/libmythdvdnav.pro       2006-10-06 09:12:47.000000000 +0200
+@@ -3,7 +3,7 @@
+ TEMPLATE = lib
+ TARGET = mythdvdnav-$$LIBVERSION
+-CONFIG += thread staticlib warn_off
++CONFIG += thread dll warn_off
+ target.path = $${LIBDIR}
+ INCLUDEPATH += ../../
+diff -urN mythtv-0.20/libs/libmythtv/libmythtv.pro mythtv-0.20.new/libs/libmythtv/libmythtv.pro
+--- mythtv-0.20/libs/libmythtv/libmythtv.pro   2006-07-18 14:35:04.000000000 +0200
++++ mythtv-0.20.new/libs/libmythtv/libmythtv.pro       2006-10-06 09:13:19.000000000 +0200
+@@ -45,7 +45,7 @@
+ TARGETDEPS += ../libavcodec/libmythavcodec-$${LIBVERSION}.$${QMAKE_EXTENSION_SHLIB}
+ TARGETDEPS += ../libavformat/libmythavformat-$${LIBVERSION}.$${QMAKE_EXTENSION_SHLIB}
+ TARGETDEPS += ../libmythmpeg2/libmythmpeg2-$${LIBVERSION}.$${QMAKE_EXTENSION_LIB}
+-TARGETDEPS += ../libmythdvdnav/libmythdvdnav-$${LIBVERSION}.$${QMAKE_EXTENSION_LIB}
++TARGETDEPS += ../libmythdvdnav/libmythdvdnav-$${LIBVERSION}.$${QMAKE_EXTENSION_SHLIB}
+ DEFINES += _LARGEFILE_SOURCE
+diff -urN mythtv-0.20/programs/programs-libs.pro mythtv-0.20.new/programs/programs-libs.pro
+--- mythtv-0.20/programs/programs-libs.pro     2006-07-09 01:44:07.000000000 +0200
++++ mythtv-0.20.new/programs/programs-libs.pro 2006-10-06 10:03:45.000000000 +0200
+@@ -1,16 +1,16 @@
+-INCLUDEPATH += ../.. ../../libs/ ../../libs/libmyth ../../libs/libmythtv
++INCLUDEPATH += ../.. ../../libs/ ../../libs/libmythdvdnav ../../libs/libmyth ../../libs/libmythtv
+ INCLUDEPATH += ../../libs/libavutil ../../libs/libavformat ../../libs/libavcodec
+ INCLUDEPATH += ../../libs/libmythupnp ../../libs/libmythui
+ INCLUDEPATH += ../../libs/libmythlivemedia
+-LIBS += -L../../libs/libmyth -L../../libs/libmythtv
++LIBS += -L../../libs/libmythdvdnav -L../../libs/libmyth -L../../libs/libmythtv
+ LIBS += -L../../libs/libavutil -L../../libs/libavcodec -L../../libs/libavformat
+ LIBS += -L../../libs/libmythfreemheg
+ LIBS += -L../../libs/libmythui
+ LIBS += -L../../libs/libmythupnp
+ LIBS += -L../../libs/libmythlivemedia
+-LIBS += -lmythtv-$$LIBVERSION -lmythavformat-$$LIBVERSION
++LIBS += -lmythdvdnav-$$LIBVERSION -lmythtv-$$LIBVERSION -lmythavformat-$$LIBVERSION
+ LIBS += -lmythavutil-$$LIBVERSION -lmythavcodec-$$LIBVERSION 
+ LIBS += -lmythfreemheg-$$LIBVERSION
+ LIBS += -lmythupnp-$$LIBVERSION 
+@@ -25,6 +25,7 @@
+ }
+ TARGETDEPS += ../../libs/libmythui/libmythui-$${LIBVERSION}.$${QMAKE_EXTENSION_SHLIB}
+ TARGETDEPS += ../../libs/libmyth/libmyth-$${LIBVERSION}.$${QMAKE_EXTENSION_SHLIB}
++TARGETDEPS += ../../libs/libmythdvdnav/libmythdvdnav-$${LIBVERSION}.$${QMAKE_EXTENSION_SHLIB}
+ TARGETDEPS += ../../libs/libmythtv/libmythtv-$${LIBVERSION}.$${QMAKE_EXTENSION_SHLIB}
+ TARGETDEPS += ../../libs/libavutil/libmythavutil-$${LIBVERSION}.$${QMAKE_EXTENSION_SHLIB}
+ TARGETDEPS += ../../libs/libavcodec/libmythavcodec-$${LIBVERSION}.$${QMAKE_EXTENSION_SHLIB}
+@@ -32,7 +33,7 @@
+ TARGETDEPS += ../../libs/libmythupnp/libmythupnp-$${LIBVERSION}.$${QMAKE_EXTENSION_SHLIB}
+ TARGETDEPS += ../../libs/libmythlivemedia/libmythlivemedia-$${LIBVERSION}.$${QMAKE_EXTENSION_SHLIB}
+-DEPENDPATH += ../.. ../../libs ../../libs/libmyth ../../libs/libmythtv
++DEPENDPATH += ../.. ../../libs ../../libs/libmyth ../../libs/libmythdvdnav ../../libs/libmythtv
+ DEPENDPATH += ../../libs/libavutil ../../libs/libavformat ../../libs/libsavcodec
+ DEPENDPATH += ../../libs/libmythupnp ../../libs/libmythui
+ DEPENDPATH += ../../libs/libmythlivemedia
diff --git a/mythtv-ldconfig.patch b/mythtv-ldconfig.patch
new file mode 100644 (file)
index 0000000..93a80b9
--- /dev/null
@@ -0,0 +1,10 @@
+--- mythtv/programs/mythfrontend/mythfrontend.pro~     2006-01-29 18:31:32.000000000 +0200
++++ mythtv/programs/mythfrontend/mythfrontend.pro      2006-02-03 21:45:41.000000000 +0200
+@@ -16,7 +16,6 @@
+ setting.files += recpriorities_settings.xml tv_search.xml tv_lists.xml
+ setting.files += library.xml manage_recordings.xml optical_menu.xml tvmenu.xml
+ setting.files += tv_settings.xml
+-setting.extra = -ldconfig
+ INSTALLS += setting
diff --git a/mythtv-libs.patch b/mythtv-libs.patch
new file mode 100644 (file)
index 0000000..36af010
--- /dev/null
@@ -0,0 +1,11 @@
+--- mythtv-0.20.2/libs/libmythdvdnav/libmythdvdnav.pro~        2007-11-07 19:02:19.000000000 +0200
++++ mythtv-0.20.2/libs/libmythdvdnav/libmythdvdnav.pro 2007-11-07 19:44:28.909056577 +0200
+@@ -29,6 +29,8 @@
+ inc.files = dvdnav_events.h dvd_reader.h ifo_types.h nav_read.h dvdnav.h
+ inc.files += dvd_types.h ifo_read.h nav_print.h nav_types.h
++LIBS += $$EXTRA_LIBS
++
+ INSTALLS += target inc
diff --git a/mythtv-mythstream.patch b/mythtv-mythstream.patch
new file mode 100644 (file)
index 0000000..4ecbd82
--- /dev/null
@@ -0,0 +1,28 @@
+--- mythtv-0.18.1/programs/mythfrontend/library.xml.fix        2006-01-31 14:33:25.867459000 +0100
++++ mythtv-0.18.1/programs/mythfrontend/library.xml    2006-01-31 14:33:39.987459000 +0100
+@@ -106,4 +106,11 @@
+      <depends>mythgame</depends>
+    </button>
++   <button>
++      <type>STREAM</type>
++      <text>Play Internet streams</text>
++      <action>PLUGIN mythstream</action>
++      <depends>mythstream</depends>
++   </button>
++
+ </mythmenu>
+--- mythtv-0.18.1/programs/mythfrontend/media_settings.xml.fix 2006-01-31 14:34:05.447459000 +0100
++++ mythtv-0.18.1/programs/mythfrontend/media_settings.xml     2006-01-31 14:34:16.337459000 +0100
+@@ -100,4 +100,11 @@
+      <depends>mythfm</depends>
+    </button>
++   <button>
++      <type>STREAM</type>
++      <text>Stream settings</text>
++      <action>CONFIGPLUGIN mythstream</action>
++      <depends>mythstream</depends>
++   </button>
++
+ </mythmenu>
diff --git a/mythtv-optflags.patch b/mythtv-optflags.patch
new file mode 100644 (file)
index 0000000..816e4a1
--- /dev/null
@@ -0,0 +1,11 @@
+--- mythtv/configure~  2006-09-05 04:59:27.000000000 +0300
++++ mythtv/configure   2006-09-05 05:00:45.000000000 +0300
+@@ -2261,8 +2261,6 @@
+     if test -n "`$cc -v 2>&1 | grep xlc`"; then
+         CFLAGS="$CFLAGS -O5"
+         LDFLAGS="$LDFLAGS -O5"
+-    else
+-        CFLAGS="-O3 $CFLAGS"
+     fi
+ fi
diff --git a/mythtv-sbinpath.patch b/mythtv-sbinpath.patch
new file mode 100644 (file)
index 0000000..a6e27a2
--- /dev/null
@@ -0,0 +1,55 @@
+--- mythtv/libs/libmythtv/jobqueue.cpp~        2005-12-21 00:35:51.000000000 +0200
++++ mythtv/libs/libmythtv/jobqueue.cpp 2006-02-05 16:17:49.000000000 +0200
+@@ -2008,7 +2008,7 @@
+     gContext->LogEntry("commflag", LP_NOTICE, msg, logDesc);
+     int breaksFound = 0;
+-    QString path = gContext->GetInstallPrefix() + "/bin/mythcommflag";
++    QString path = gContext->GetInstallPrefix() + "/sbin/mythcommflag";
+     QString cmd = QString("%1 -j %2 -V %3")
+                           .arg(path).arg(jobID).arg(print_verbose_messages);
+--- mythtv/programs/mythcommflag/mythcommflag.pro~     2005-10-18 02:33:37.000000000 +0300
++++ mythtv/programs/mythcommflag/mythcommflag.pro      2006-02-05 16:20:01.000000000 +0200
+@@ -4,7 +4,7 @@
+ TEMPLATE = app
+ CONFIG += thread
+-target.path = $${PREFIX}/bin
++target.path = $${PREFIX}/sbin
+ INSTALLS = target
+ QMAKE_CLEAN += $(TARGET)
+--- mythtv/programs/mythbackend/mythbackend.pro~       2006-01-29 18:32:00.000000000 +0200
++++ mythtv/programs/mythbackend/mythbackend.pro        2006-02-05 16:20:52.000000000 +0200
+@@ -6,7 +6,7 @@
+ TEMPLATE = app
+ CONFIG += thread
+ TARGET = mythbackend
+-target.path = $${PREFIX}/bin
++target.path = $${PREFIX}/sbin
+ INSTALLS = target
+ QMAKE_CLEAN += $(TARGET)
+--- mythtv/programs/mythjobqueue/mythjobqueue.pro~     2005-10-18 02:33:36.000000000 +0300
++++ mythtv/programs/mythjobqueue/mythjobqueue.pro      2006-02-05 16:21:08.000000000 +0200
+@@ -4,7 +4,7 @@
+ TEMPLATE = app
+ CONFIG += thread
+-target.path = $${PREFIX}/bin
++target.path = $${PREFIX}/sbin
+ INSTALLS = target
+ QMAKE_CLEAN += $(TARGET)
+--- mythtv/programs/mythlcdserver/mythlcdserver.pro~   2005-10-18 02:33:38.000000000 +0300
++++ mythtv/programs/mythlcdserver/mythlcdserver.pro    2006-02-05 16:21:25.000000000 +0200
+@@ -5,7 +5,7 @@
+ TEMPLATE = app
+ CONFIG += thread
+ TARGET = mythlcdserver
+-target.path = $${PREFIX}/bin
++target.path = $${PREFIX}/sbin
+ INSTALLS += target
diff --git a/mythtv.spec b/mythtv.spec
new file mode 100644 (file)
index 0000000..113b51b
--- /dev/null
@@ -0,0 +1,530 @@
+# TODO
+# - bconds: altivec joystick lcd
+# - lcd? (app-misc/lcdproc)
+# - icons for desktop entries
+# - alpha, sparc, ppc arches?
+#
+# Specfile for MythTV
+#
+#  MythTV now uses a fairly intelligent cpu-detection script, so if you are
+#  building an rpm by hand on the machine it will be used on, I encourage you
+#  to use "--with cpu_autodetect" to let mythtv decide for you.
+#
+# Conditional build:
+%bcond_with    cpu_autodetect  # enable CPU autodetection at compile time (sets "-march", "-mcpu" compile flags really)
+%bcond_without lirc            # lirc support
+%bcond_without alsa            # alsa support
+%bcond_without oss             # oss support
+%bcond_without arts            # arts support
+%bcond_without jack            # jack audio connection kit
+%bcond_without opengl          # opengl vsync
+%bcond_without dvb             # DVB support
+%bcond_without xrandr          # disable X11 resolution switching
+%bcond_with    ivtv            # ivtv support (PVR-250, PVR-350) NFY
+%bcond_with    firewire        # ieee1394 (NFY)
+%bcond_without xvmc            # do not use XvMCW
+%bcond_with    mmx                     # enable mmx
+
+# enable mmx automatically on arches having it
+%ifarch %{ix86} %{x8664}
+%ifnarch i386 i486 i586 i686
+%define        with_mmx 1
+%endif
+%endif
+
+Summary:       A personal video recorder (PVR) application
+Summary(pl.UTF-8):     Osobista aplikacja do nagrywania obrazu (PVR)
+Name:          mythtv
+Version:       0.21
+Release:       5
+License:       GPL v2
+Group:         Applications/Multimedia
+Source0:       http://www.mythtv.org/mc/%{name}-%{version}.tar.bz2
+# Source0-md5: 49fc135e1cde90cd935c1229467fa37e
+Source1:       mythbackend.sysconfig
+Source2:       mythbackend.init
+Source3:       mythbackend.logrotate
+Source5:       mythfrontend.desktop
+#Patch100:             %{name}-branch.diff
+Patch0:                %{name}-lib64.patch
+Patch1:                mythtv-configure.patch
+Patch2:                %{name}-mythstream.patch
+Patch3:                %{name}-ldconfig.patch
+#Patch4:               %{name}-pl.patch
+Patch5:                %{name}-sbinpath.patch
+Patch6:                mythtv-dvdnav-shared.patch
+Patch7:                %{name}-libs.patch
+Patch8:                %{name}-fixes.patch
+Patch9:                %{name}-ffmpeg-API.patch
+URL:           http://www.mythtv.org/
+#BuildRequires:        DirectFB-devel
+#BuildRequires:        XFree86-devel
+BuildRequires: OpenGL-devel
+BuildRequires: OpenGL-GLU-devel
+%{?with_alsa:BuildRequires:    alsa-lib-devel}
+%{?with_arts:BuildRequires:    arts-devel >= 13:0.9.5}
+BuildRequires: ffmpeg-devel
+BuildRequires: freetype-devel >= 1:2.0.0
+%{?with_jack:BuildRequires:    jack-audio-connection-kit-devel}
+BuildRequires: lame-libs-devel
+%{?with_xvmc:BuildRequires:    xorg-lib-libXvMC-devel}
+%{?with_firewire:BuildRequires:        libavc1394-devel}
+%{?with_dvb:BuildRequires:     libdvb-devel}
+BuildRequires: libdvdnav-devel
+%{?with_firewire:BuildRequires:        libiec61883-devel}
+%{?with_firewire:BuildRequires:        libraw1394-devel}
+BuildRequires: linux-libc-headers >= 7:2.6.10
+%{?with_lirc:BuildRequires:    lirc-devel}
+BuildRequires: mysql-devel
+BuildRequires: qmake >= 6:3.2.1-4
+BuildRequires: qt-devel >= 6:3.2.1-4
+BuildRequires: rpmbuild(macros) >= 1.228
+BuildRequires: sed >= 4.0
+# for bundled libavcodec
+BuildRequires: libdts-devel
+#BuildConflicts:       libmyth-devel
+BuildRequires: xorg-lib-libXext-devel
+BuildRequires: xorg-lib-libXxf86vm-devel
+ExclusiveArch: %{ix86} %{x8664} ppc
+BuildRoot:     %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
+
+%define        myth_api_version %(echo %{version} | cut -d. -f1,2)
+
+%description
+MythTV implements the following PVR features, and more, with a unified
+graphical interface:
+- Basic 'live-tv' functionality. Pause/Fast Forward/Rewind "live" TV.
+- Video compression using RTjpeg or MPEG-4
+- Program listing retrieval using XMLTV
+- Themable, semi-transparent on-screen display
+- Electronic program guide
+- Scheduled recording of TV programs
+- Resolution of conflicts between scheduled recordings
+- Basic video editing
+
+%description -l pl.UTF-8
+MythTV implementuje następujące możliwości PVR, a nawet więcej, wraz z
+ujednoliconym interfejsem graficznym:
+- podstawowa funkcjonalność "live-tv"; pauza, szybkie przewijanie,
+  przewijanie "żywej" telewizji
+- kompresja obrazu przy użyciu RTjpeg lub MPEG-4
+- odczyt listy programów przy użyciu XMLTV
+- pseudoprzezroczyste wyświetlanie na obrazie (OSD) z obsługą motywów
+- elektroniczny przewodnik po programie
+- planowane nagrywanie programów telewizyjnych
+- rozwiązywanie konfliktów między planowanymi nagraniami
+- podstawowa edycja obrazu
+
+%package backend
+Summary:       Server component of mythtv (a PVR)
+Summary(pl.UTF-8):     Część serwerowa mythtv (PVR)
+Group:         Applications/Multimedia
+Requires(post,preun):  /sbin/chkconfig
+Requires(postun):      /usr/sbin/groupdel
+Requires(postun):      /usr/sbin/userdel
+Requires(pre): /bin/id
+Requires(pre): /usr/bin/getgid
+Requires(pre): /usr/sbin/groupadd
+Requires(pre): /usr/sbin/useradd
+Requires:      libmyth = %{version}-%{release}
+Requires:      mythtv = %{version}-%{release}
+Provides:      group(mythtv)
+Provides:      user(mythtv)
+
+%description backend
+MythTV provides a unified graphical interface for recording and
+viewing television programs. Refer to the mythtv package for more
+information.
+
+This package contains only the server software, which provides video
+and audio capture and encoding services. In order to be useful, it
+requires a mythtv-frontend installation, either on the same system or
+one reachable via the network.
+
+%description backend -l pl.UTF-8
+MythTV dostarcza ujednolicony interfejs graficzny do nagrywania i
+oglądania programów telewizyjnych. Więcej informacji w pakiecie
+mythtv.
+
+Ten pakiet zawiera tylko oprogramowanie serwerowe, udostępniające
+usługi przechwytywania i kodowania obrazu i dźwięku. Aby było
+przydatne, wymaga instalacji mythtv-frontend - na tym samym systemie,
+albo innym osiągalnym po sieci.
+
+%package frontend
+Summary:       Client component of mythtv (a PVR)
+Summary(pl.UTF-8):     Część kliencka mythtv (PVR)
+Group:         Applications/Multimedia
+Requires:      libmyth = %{version}-%{release}
+Requires:      mythtv = %{version}-%{release}
+Requires:      mythtv-themes = %{version}-%{release}
+Provides:      mythtv-frontend-api = %{myth_api_version}
+
+%description frontend
+MythTV provides a unified graphical interface for recording and
+viewing television programs. Refer to the mythtv package for more
+information.
+
+This package contains only the client software, which provides a
+front-end for playback and configuration. It requires access to a
+mythtv-backend installation, either on the same system or one
+reachable via the network.
+
+%description frontend -l pl.UTF-8
+MythTV dostarcza ujednolicony interfejs graficzny do nagrywania i
+oglądania programów telewizyjnych. Więcej informacji w pakiecie
+mythtv.
+
+Ten pakiet zawiera tylko oprogramowanie klienckie, dostarczające
+frontend do odtwarzania i konfiguracji. Wymaga dostępu do instalacji
+mythtv-backend - na tym samym systemie, albo innym osiągalnym po
+sieci.
+
+%package setup
+Summary:       Setup the mythtv backend
+Summary(pl.UTF-8):     Konfigurator backendu mythtv
+Group:         Applications/Multimedia
+Requires:      libmyth = %{version}-%{release}
+
+%description setup
+MythTV provides a unified graphical interface for recording and
+viewing television programs. Refer to the mythtv package for more
+information.
+
+This package contains only the setup software for configuring the
+mythtv backend.
+
+%description setup -l pl.UTF-8
+MythTV dostarcza ujednolicony interfejs graficzny do nagrywania i
+oglądania programów telewizyjnych. Więcej informacji w pakiecie
+mythtv.
+
+Ten pakiet zawiera tylko program do konfigurowania backendu mythtv.
+
+%package themes
+Summary:       Base themes for mythtv's frontend
+Summary(pl.UTF-8):     Podstawowe motywy dla frontendu mythtv
+Requires:      %{name}-frontend = %{version}-%{release}
+Group:         Themes
+
+%description themes
+MythTV provides a unified graphical interface for recording and
+viewing television programs. Refer to the mythtv package for more
+information.
+
+This package contains only the base themes used by the frontend and
+mythtvsetup.
+
+%description themes -l pl.UTF-8
+MythTV dostarcza ujednolicony interfejs graficzny do nagrywania i
+oglądania programów telewizyjnych. Więcej informacji w pakiecie
+mythtv.
+
+Ten pakiet zawiera tylko podstawowe motywy używane przez frontend oraz
+mythtvsetup.
+
+%package -n libmyth
+Summary:       Library providing mythtv support
+Summary(pl.UTF-8):     Biblioteka udostępniająca obsługę mythtv
+Group:         Libraries
+Requires:      freetype >= 1:2.0.0
+Requires:      lame
+Requires:      qt >= 6:3.2.1-4
+Requires:      qt-plugin-mysql >= 6:3.2.1-4
+
+%description -n libmyth
+Common library code for MythTV and add-on modules (development) MythTV
+provides a unified graphical interface for recording and viewing
+television programs. Refer to the mythtv package for more information.
+
+%description -n libmyth -l pl.UTF-8
+Wspólny kod biblioteki dla MythTV i dodatkowych modułów MythTV
+dostarczający ujednolicony interfejs graficzny do nagrywania i
+oglądania programów telewizyjnych. Więcej informacji w pakiecie
+mythtv.
+
+%package -n libmyth-devel
+Summary:       Development files for libmyth
+Summary(pl.UTF-8):     Pliki nagłówkowe libmyth
+Group:         Development/Libraries
+Requires:      libmyth = %{version}-%{release}
+
+%description -n libmyth-devel
+This package contains the header files for developing add-ons for
+mythtv.
+
+%description -n libmyth-devel -l pl.UTF-8
+Ten pakiet zawiera pliki nagłówkowe do tworzenia dodatków dla mythtv.
+
+%package -n libmyth-static
+Summary:       Static libmyth library
+Summary(pl.UTF-8):     Statyczna biblioteka libmyth
+Group:         Development/Libraries
+Requires:      libmyth-devel = %{version}-%{release}
+
+%description -n libmyth-static
+Static libmyth library.
+
+%description -n libmyth-static -l pl.UTF-8
+Statyczna biblioteka libmyth.
+
+%prep
+%setup -q %{?_rev:-n %{name}}
+%if %{_lib} != "lib"
+#%patch0 -p1
+%endif
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
+#%patch4 -p1 REDIFF and submit
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+
+rm -rf database/old # not supported in PLD
+
+# lib64 fix - enable to update patch
+%if %{_lib} != "lib" && 0
+find '(' -name '*.[ch]' -o -name '*.cpp' -o -name '*.pro' ')' | \
+xargs grep -l /lib . | xargs sed -i -e '
+       s,/''usr/lib/,/%{_libdir}/,g
+       s,/''lib/mythtv,/%{_lib}/mythtv,g
+       s,{PREFIX}/lib$,{PREFIX}/%{_lib},g
+'
+exit 1
+%endif
+
+# Assigning null to QMAKE_LIBDIR_QT will prevent makefiles contain
+# -L$(QTDIR)/%{_lib} and -Wl,-rpath,$(QTDIR)/%{_lib}. And that will
+# prevent compiler finding libs from system when they should be looked
+# from current buildtree.
+# but that made it link with -lqt which doesn't exist, instead of -lqt-mt
+# so we make QMAKE wrapper which will do sed subst after calling
+# qmake. this is the wrapper.
+cat > qmake-wrapper.sh <<'EOF'
+#!/bin/sh
+getmakefile() {
+       while [ $# -gt 0 ]; do
+               case "$1" in
+               -o)
+                       shift
+                       makefile="$1"
+                       return
+                       ;;
+               esac
+               shift
+       done
+}
+
+qmake "$@"
+getmakefile "$@"
+if [ "$makefile" ]; then
+       %{__sed} -i -e '
+               s;-Wl,-rpath,$(QTDIR)/%{_lib};;
+               s;-L$(QTDIR)/%{_lib};;
+       ' $makefile
+fi
+EOF
+chmod +x qmake-wrapper.sh
+
+%build
+%if %{with cpu_autodetect}
+# Make sure we have /proc mounted
+if [ ! -r /proc/cpuinfo ]; then
+       echo "You need to have /proc mounted in order to build with cpu_autodetect!"
+       exit 1
+fi
+%endif
+
+# NB: not autoconf configure
+# help configure::has_library() to locate libs
+LD_LIBRARY_PATH=%{_libdir} \
+CC="%{__cc}" \
+CXX="%{__cxx}" \
+./configure \
+       --prefix=%{_prefix} \
+       --libdir=%{_libdir} \
+       --mandir=%{_mandir} \
+       --disable-distcc --disable-ccache \
+       --compile-type=%{?debug:debug}%{!?debug:release} \
+       --extra-cflags="%{rpmcflags} -fomit-frame-pointer" \
+       --extra-cxxflags="%{rpmcxxflags} -fomit-frame-pointer" \
+%if %{with cpu_autodetect}
+       --enable-proc-opt \
+%else
+       %ifarch %{ix86}
+               %ifarch athlon
+                       --arch=athlon \
+               %else
+                       --cpu=i386 --tune=pentium4 \
+               %endif
+       %endif
+       %ifarch %{x8664}
+       --arch=x86_64 \
+       %endif
+       %{?with_mmx:--enable-mmx} \
+%endif
+       %{?with_dvb:--enable-dvb --dvb-path=%{_includedir}} \
+       --%{?with_arts:en}%{!?with_arts:dis}able-audio-arts \
+       --%{?with_alsa:en}%{!?with_alsa:dis}able-audio-alsa \
+       --%{?with_oss:en}%{!?with_oss:dis}able-audio-oss \
+       --%{?with_jack:en}%{!?with_jack:dis}able-audio-jack \
+       --%{?with_opengl:en}%{!?with_opengl:dis}able-opengl-vsync \
+       --%{?with_lirc:en}%{!?with_lirc:dis}able-lirc \
+       --%{?with_firewire:en}%{!?with_firewire:dis}able-firewire \
+       --%{?with_xrandr:en}%{!?with_xrandr:dis}able-xrandr \
+       --%{?with_xvmc:en}%{!?with_xvmc:dis}able-xvmc \
+       --enable-xv \
+       --enable-x11 \
+
+qmake mythtv.pro \
+QTDIR="%{_prefix}" \
+QMAKE_LIBDIR_X11=%{?_x_libraries}%{!?_x_libraries:%{_libdir}}
+
+%{__make} \
+       QTDIR="%{_prefix}" \
+       QMAKE=$(pwd)/qmake-wrapper.sh
+
+%install
+rm -rf $RPM_BUILD_ROOT
+install -d $RPM_BUILD_ROOT/etc/{logrotate.d,sysconfig} \
+               $RPM_BUILD_ROOT{/etc/rc.d/init.d,%{_desktopdir}} \
+               $RPM_BUILD_ROOT/var/{cache,lib,log,run}/mythtv \
+               $RPM_BUILD_ROOT%{_libdir}/mythtv/plugins
+
+export QTDIR="%{_prefix}"
+%{__make} install \
+       INSTALL_ROOT=$RPM_BUILD_ROOT
+
+# Install the files that we added on top of mythtv's own stuff
+install %{SOURCE2} $RPM_BUILD_ROOT/etc/rc.d/init.d/mythbackend
+install %{SOURCE3} $RPM_BUILD_ROOT/etc/logrotate.d/mythbackend
+install %{SOURCE1} $RPM_BUILD_ROOT/etc/sysconfig/mythbackend
+
+# desktop entries
+install %{SOURCE5} $RPM_BUILD_ROOT%{_desktopdir}
+
+# Install settings.pro so people can see the build options we used
+install -d $RPM_BUILD_ROOT%{_datadir}/mythtv/build
+install config.mak settings.pro $RPM_BUILD_ROOT%{_datadir}/mythtv/build
+
+for p in mythfrontend; do
+       for l in $RPM_BUILD_ROOT%{_datadir}/mythtv/i18n/${p}_*.qm; do
+               echo $l | sed -e "s,^$RPM_BUILD_ROOT\(.*${p}_\(.*\).qm\),%%lang(\2) \1,"
+       done > $p.lang
+done
+
+# glibc language codes. attempt was made to change it on libmyth side,
+# but that was just asking for trouble due large coverage of
+# language.lower() usage.
+sed -i -e '
+s,%%lang(en_gb),%%lang(en_GB),
+s,%%lang(zh_tw),%%lang(zh_TW),
+s,%%lang(pt_br),%%lang(pt_BR),
+' *.lang
+
+rm -rf mythtvosd mythwelcome mythlcdserver
+install -d mythtvosd mythwelcome
+cp -a programs/mythtvosd/{README,*.xml} mythtvosd
+cp -a programs/mythwelcome/README mythwelcome
+cp -a programs/mythlcdserver/README mythlcdserver
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%pre backend
+%groupadd -g 149 %{name}
+%useradd -u 149 -d /var/lib/mythtv -g %{name} -c "MythTV User" %{name}
+%addusertogroup %{name} video
+%addusertogroup %{name} audio
+
+%post backend
+/sbin/chkconfig --add mythbackend
+
+%preun backend
+if [ "$1" = "0" ]; then
+       %service -q mythbackend stop
+       /sbin/chkconfig --del mythbackend
+fi
+
+%postun backend
+if [ "$1" = "0" ]; then
+       %userremove %{name}
+       %groupremove %{name}
+fi
+
+%post  -n libmyth -p /sbin/ldconfig
+%postun        -n libmyth -p /sbin/ldconfig
+
+%post setup
+if [ "$1" = 1 ]; then
+%banner -e %{name}-setup <<EOF
+To grant mysql permissions to mythtv, please run
+zcat %{_docdir}/%{name}-setup-%{version}/database/mc.sql.gz | mysql
+EOF
+fi
+
+%files
+%defattr(644,root,root,755)
+%doc README* UPGRADING AUTHORS FAQ
+#%doc docs contrib configfiles
+%doc keys.txt mythtvosd mythwelcome mythlcdserver
+
+%files backend
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_sbindir}/mythbackend
+%attr(755,root,root) %{_sbindir}/mythcommflag
+%attr(755,root,root) %{_bindir}/mythfilldatabase
+%attr(755,root,root) %{_sbindir}/mythjobqueue
+%attr(755,root,root) %{_sbindir}/mythlcdserver
+%attr(755,root,root) %{_bindir}/mythtranscode
+%attr(755,root,root) %{_bindir}/mythreplex
+%attr(775,root,mythtv) %dir /var/lib/mythtv
+%attr(775,root,mythtv) %dir /var/cache/mythtv
+%attr(775,root,mythtv) %dir /var/run/mythtv
+%attr(754,root,root) /etc/rc.d/init.d/mythbackend
+%attr(640,root,root) %config(noreplace) %verify(not md5 mtime size) /etc/sysconfig/mythbackend
+%attr(640,root,root) %config(noreplace) %verify(not md5 mtime size) /etc/logrotate.d/mythbackend
+%attr(775,root,mythtv) %dir %{_localstatedir}/log/mythtv
+
+%files frontend -f mythfrontend.lang
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/mythfrontend
+%attr(755,root,root) %{_bindir}/mythshutdown
+%attr(755,root,root) %{_bindir}/mythtv
+%attr(755,root,root) %{_bindir}/mythtvosd
+%attr(755,root,root) %{_bindir}/mythwelcome
+%dir %{_datadir}/mythtv
+%dir %{_datadir}/mythtv/themes
+%dir %{_libdir}/mythtv
+%{_datadir}/mythtv/*.xml
+%dir %{_libdir}/mythtv/filters
+%dir %{_libdir}/mythtv/plugins
+%attr(755,root,root) %{_libdir}/mythtv/filters/*.so
+%{_datadir}/mythtv/*.ttf
+%dir %{_datadir}/mythtv/i18n
+%{_desktopdir}/*.desktop
+
+%files setup
+%defattr(644,root,root,755)
+%doc database
+%attr(755,root,root) %{_bindir}/mythtv-setup
+
+%files themes
+%defattr(644,root,root,755)
+%{_datadir}/mythtv/themes/*
+
+%files -n libmyth
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_libdir}/lib*.so.*.*.*
+
+%files -n libmyth-devel
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_libdir}/*.so
+%{_includedir}/*
+%{_datadir}/mythtv/build
+
+%files -n libmyth-static
+%defattr(644,root,root,755)
This page took 0.293791 seconds and 4 git commands to generate.