]> git.pld-linux.org Git - packages/mythplugins.git/blob - mythtv-branch.diff
- up to svn 10931
[packages/mythplugins.git] / mythtv-branch.diff
1 Index: mythplugins/mythweb/themes/wml/header.php
2 ===================================================================
3 --- mythplugins/mythweb/themes/wml/header.php   (.../tags/release-0-19) (revision 10931)
4 +++ mythplugins/mythweb/themes/wml/header.php   (.../branches/release-0-19-fixes)       (revision 10931)
5 @@ -26,4 +26,4 @@
6  <p><a href="<?php echo root ?>tv/upcoming"><?php echo t('Upcoming Recordings') ?></a></p>
7  <p><a href="<?php echo root ?>tv/recorded"><?php echo t('Recorded Programs') ?></a></p>
8  <p><a href="<?php echo root ?>tv/search"><?php echo t('Search') ?></a></p>
9 -<p><a href="<?php echo root ?>status?xml"><?php echo t('Backend Status') ?></a></p>
10 +<p><a href="<?php echo root ?>status/xml"><?php echo t('Backend Status') ?></a></p>
11 Index: mythplugins/mythweb/themes/default/weather/weather.php
12 ===================================================================
13 --- mythplugins/mythweb/themes/default/weather/weather.php      (.../tags/release-0-19) (revision 10931)
14 +++ mythplugins/mythweb/themes/default/weather/weather.php      (.../branches/release-0-19-fixes)       (revision 10931)
15 @@ -93,13 +93,13 @@
16                  $tomorrow = date("m/d/Y", mktime(0, 0, 0, date("m")  , date("d")+1, date("Y")));
17  
18                  switch($forecast->dayofweek) {
19 +                    case 0:  $day = t('Sunday');        break;
20                      case 1:  $day = t('Monday');        break;
21                      case 2:  $day = t('Tuesday');       break;
22                      case 3:  $day = t('Wednesday');     break;
23                      case 4:  $day = t('Thursday');      break;
24                      case 5:  $day = t('Friday');        break;
25                      case 6:  $day = t('Saturday');      break;
26 -                    case 7:  $day = t('Sunday');        break;
27                      default: $day = $forecast->date;    break;
28                  }
29  
30 Index: mythplugins/mythweb/themes/default/music/music.php
31 ===================================================================
32 --- mythplugins/mythweb/themes/default/music/music.php  (.../tags/release-0-19) (revision 10931)
33 +++ mythplugins/mythweb/themes/default/music/music.php  (.../branches/release-0-19-fixes)       (revision 10931)
34 @@ -164,10 +164,12 @@
35  
36      function print_header($filterPlaylist,$filterArtist,$filterAlbum,$filterGenre) {
37          $this->filterPlaylist=$filterPlaylist;
38 -// Set the desired page title
39 -    $page_title = 'MythWeb - '.t('Music');
40 -// Print the page header
41 -    require_once theme_dir.'/header.php';
42 +    // Set the desired page title
43 +        global $page_title, $Modules, $headers;
44 +        $page_title = 'MythWeb - '.t('Music');
45 +    // Print the page header
46 +        require_once theme_dir.'/header.php';
47 +
48          printf("<form  action=\"".root."music\" method=\"GET\" >\n");
49          printf("<input type=\"hidden\" name=\"mode\" value=\"music\" />\n");
50  
51 Index: mythplugins/mythweb/themes/default/tv/detail.php
52 ===================================================================
53 --- mythplugins/mythweb/themes/default/tv/detail.php    (.../tags/release-0-19) (revision 10931)
54 +++ mythplugins/mythweb/themes/default/tv/detail.php    (.../branches/release-0-19-fixes)       (revision 10931)
55 @@ -51,7 +51,7 @@
56  <?php   } ?>
57              <div id="program_title">
58                  <h1>
59 -                    <a href="<?php echo root ?>tv/search/<?php echo urlencode($program->title) ?>&search_title=yes"><?php echo $schedule->title ?></a>
60 +                    <a href="<?php echo root ?>tv/search/<?php echo str_replace('%2F', '/', rawurlencode($schedule->title)) ?>?search_title=1"><?php echo $schedule->title ?></a>
61                  </h1>
62                  <div id="program_time">
63  <?php
64 Index: mythplugins/mythweb/includes/mythbackend.php
65 ===================================================================
66 --- mythplugins/mythweb/includes/mythbackend.php        (.../tags/release-0-19) (revision 10931)
67 +++ mythplugins/mythweb/includes/mythbackend.php        (.../branches/release-0-19-fixes)       (revision 10931)
68 @@ -15,10 +15,6 @@
69  // The character string used by the backend to separate records
70      define('backend_sep', '[]:[]');
71  
72 -// A couple of global variables to keep duplicate queries to a minimum
73 -    $Scheduled_Recordings = array();
74 -    $Recorded_Programs    = array();
75 -
76  // MYTH_PROTO_VERSION is defined in libmyth in mythtv/libs/libmyth/mythcontext.h
77  // and should be the current MythTV protocol version.
78      define('MYTH_PROTO_VERSION', 26);
79 Index: mythplugins/mythweb/includes/programs.php
80 ===================================================================
81 --- mythplugins/mythweb/includes/programs.php   (.../tags/release-0-19) (revision 10931)
82 +++ mythplugins/mythweb/includes/programs.php   (.../branches/release-0-19-fixes)       (revision 10931)
83 @@ -81,7 +81,9 @@
84  /**/
85      function &load_all_program_data($start_time, $end_time, $chanid = false, $single_program = false, $extra_query = '') {
86          global $Channels, $db;
87 -    // Make a local hash of channel chanid's with references to the actual channel data
88 +    // Make a local hash of channel chanid's with references to the actual
89 +    // channel data (Channels are not indexed by anything in particular, so
90 +    // that the user can sort by chanid or channum).
91          $channel_hash = array();
92      // An array (that later gets converted to a string) containing the id's of channels we want to load
93          $these_channels = array();
94 @@ -104,7 +106,7 @@
95              load_all_channels();
96      // Scan through the channels array and actually assign those references
97          foreach (array_keys($Channels) as $key) {
98 -            $channel_hash[$Channels[$key]->chanid] = &$Channels[$key];
99 +            $channel_hash[$Channels[$key]->chanid] =& $Channels[$key];
100          // Reinitialize the programs array for this channel
101              $Channels[$key]->programs = array();
102          // Keep track of this channel id in case we're only grabbing info for certain channels - workound included to avoid blank chanid's
103 @@ -130,11 +132,13 @@
104                         LEFT JOIN programrating USING (chanid, starttime)
105                         LEFT JOIN oldrecorded
106                                   ON oldrecorded.recstatus IN (-3, 11)
107 -                                    AND IF(oldrecorded.programid OR oldrecorded.seriesid,
108 +                                    AND IF(oldrecorded.programid AND oldrecorded.seriesid,
109                                             oldrecorded.programid = program.programid
110                                               AND oldrecorded.seriesid = program.seriesid,
111 -                                           oldrecorded.title = program.title
112 -                                             AND oldrecorded.subtitle = program.subtitle
113 +                                           oldrecorded.title AND oldrecorded.subtitle
114 +                                             AND oldrecorded.description
115 +                                             AND oldrecorded.title       = program.title
116 +                                             AND oldrecorded.subtitle    = program.subtitle
117                                               AND oldrecorded.description = program.description
118                                            )
119                         LEFT JOIN channel ON program.chanid = channel.chanid
120 @@ -156,8 +160,12 @@
121      // The extra query, if there is one
122          if ($extra_query)
123              $query .= ' AND '.$extra_query;
124 -    // Group, sort and query
125 +    // Group and sort
126          $query .= ' GROUP BY program.chanid, program.starttime ORDER BY program.starttime';
127 +    // Limit
128 +        if ($single_program)
129 +            $query .= ' LIMIT 1';
130 +    // Query
131          $sh = $db->query($query,
132                           star_character, max_stars, max_stars);
133      // No results
134 @@ -188,12 +196,8 @@
135      // Cleanup
136          $sh->finish();
137      // If channel-specific information was requested, return an array of those programs, or just the first/only one
138 -        if ($chanid) {
139 -            if ($single_program)
140 -                return $channel_hash[$chanid]->programs[0];
141 -            else
142 -                return $channel_hash[$chanid]->programs;
143 -        }
144 +        if ($chanid && $single_program)
145 +            return $these_programs[0];
146      // Just in case, return an array of all programs found
147          return $these_programs;
148      }
149 @@ -272,18 +276,18 @@
150              $this->endtime     = $data[12];  # show end-time
151          // Is this a previously-recorded program?  Calculate the filesize
152              if (!empty($this->filename)) {
153 -                $this->filesize = ($fs_high + ($fs_low < 0)) * 4294967296 + $fs_low;
154 -            }
155 -        // Ah, a scheduled recording - let's load more information about it, to be parsed in below
156 -            elseif ($this->chanid) {
157 -                unset($this->filename);
158 -            // Kludge to avoid redefining the object, which doesn't work in php5
159 -                $tmp = @get_object_vars(load_one_program($this->starttime, $this->chanid));
160 -                if (is_array($tmp) && count($tmp) > 0) {
161 -                    foreach ($tmp as $key => $value) {
162 -                        $this->$key = $value;
163 -                    }
164 +                if (function_exists('gmp_add')) {
165 +                // GMP functions should work better with 64 bit numbers.
166 +                    $size = gmp_add($fs_low,
167 +                                     gmp_mul('4294967296',
168 +                                             gmp_add($fs_high, $fs_low < 0 ? '1' : '0'))
169 +                                   );
170 +                    $this->filesize = gmp_strval($size);
171                  }
172 +                else {
173 +                // This is inaccurate, but it's the best we can get without GMP.
174 +                    $this->filesize = ($fs_high + ($fs_low < 0)) * 4294967296 + $fs_low;
175 +                }
176              }
177          // Load the remaining info we got from mythbackend
178              $this->title           = $data[0];                  # program name/title
179 @@ -291,14 +295,14 @@
180              $this->description     = $data[2];                  # episode description
181              $this->category        = $data[3];
182              #$chanid               = $data[4];   # Extracted a few lines earlier
183 -            #$channum              = $data[5];
184 -            #$callsign             = $data[6];
185 +            $this->channum         = $data[5];
186 +            $this->callsign        = $data[6];
187              $this->channame        = $data[7];
188              #$pathname             = $data[8];   # Extracted a few lines earlier
189              #$fs_high              = $data[9];   # Extracted a few lines earlier
190              #$fs_low               = $data[10];  # Extracted a few lines earlier
191 -            #$starttime            = $data[11];  # Extracted a few lines earlier
192 -            #$endtime              = $data[12];  # Extracted a few lines earlier
193 +            #$this->starttime      = $data[11];  # Extracted a few lines earlier
194 +            #$this->endtime        = $data[12];  # Extracted a few lines earlier
195              $this->hostname        = $data[16];
196              #$this->sourceid       = $data[17];
197              $this->cardid          = $data[18];
198 @@ -320,9 +324,9 @@
199              $this->programid       = $data[34];
200              $this->lastmodified    = $data[35];
201              $this->recpriority     = $data[36];
202 -            #$this->airdate        = $data[37];
203 -            #$this->hasairdate     = $data[38];
204 -            $this->timestretch     = $program_data[39];
205 +            $this->airdate         = date('Y-m-d', $data[37]);
206 +            $this->hasairdate      = $data[38];
207 +            $this->timestretch     = $data[39];
208              $this->recpriority2    = $data[40];
209          // Assign the program flags
210              $this->has_commflag = ($progflags & 0x01) ? true : false;    // FL_COMMFLAG  = 0x01
211 @@ -363,8 +367,8 @@
212              $this->title_pronounce         = $data['title_pronounce'];
213              $this->recstatus               = $data['recstatus'];
214  
215 -            if ($program_data['tsdefault']) {
216 -                $this->timestretch = $program_data['tsdefault'];
217 +            if ($data['tsdefault']) {
218 +                $this->timestretch = $data['tsdefault'];
219              } else {
220                  $this->timestretch = 1.0;
221              }
222 @@ -387,12 +391,14 @@
223          // Now we really should scan the $Channel array and add a link to this program's channel
224              foreach (array_keys($Channels) as $key) {
225                  if ($Channels[$key]->chanid == $this->chanid) {
226 -                    $this->channel = &$Channels[$key];
227 +                    $this->channel =& $Channels[$key];
228                      break;
229                  }
230              }
231 +        // Not found
232 +            if (!$this->channel)
233 +                $this->channel =& load_one_channel($this->chanid);
234          }
235 -
236      // Calculate the duration
237          if ($this->recendts)
238              $this->length = $this->recendts - $this->recstartts;
239 Index: mythplugins/mythweb/includes/utils.php
240 ===================================================================
241 --- mythplugins/mythweb/includes/utils.php      (.../tags/release-0-19) (revision 10931)
242 +++ mythplugins/mythweb/includes/utils.php      (.../branches/release-0-19-fixes)       (revision 10931)
243 @@ -276,7 +276,7 @@
244          static $first_run=true;
245          if($first_run) {
246              $first_run=false;
247 -            echo '<script type="text/javascript" src="/js/debug.js"></script>';
248 +            echo '<script type="text/javascript" src="'.root.'js/debug.js"></script>';
249          }
250      // Put our data into a string
251          if (is_array($data) || is_object($data))
252 Index: mythplugins/mythweb/includes/init.php
253 ===================================================================
254 --- mythplugins/mythweb/includes/init.php       (.../tags/release-0-19) (revision 10931)
255 +++ mythplugins/mythweb/includes/init.php       (.../branches/release-0-19-fixes)       (revision 10931)
256 @@ -16,28 +16,15 @@
257   *
258  /**/
259  
260 -/**
261 - * $Path is an array of PATH_INFO passed into the script via mod_rewrite or some
262 - * other lesser means.  It contains most of the information required for
263 - * figuring out what functions the user wants to access.
264 - *
265 - * @global  array   $GLOBALS['Path']
266 - * @name    $Path
267 -/**/
268 -    global $Path;
269 -    $Path = explode('/', preg_replace('/^\/+/',   '',    // Remove leading slashes
270 -                         preg_replace('/[\s]+/', ' ',    // Convert extra whitespace
271 -                                                         // Grab the path info from various different places.
272 -                             array_key_exists('PATH_INFO', $_SERVER)
273 -                             && $_SERVER['PATH_INFO']
274 -                                ? $_SERVER['PATH_INFO']
275 -                                : (array_key_exists('PATH_INFO', $_ENV)
276 -                                   && $_ENV['PATH_INFO']
277 -                                    ? $_ENV['PATH_INFO']
278 -                                    : $_GET['PATH_INFO']
279 -                                  )
280 -                         ))
281 -                   );
282 +// mod_redirect can do some weird things when php is run in cgi mode
283 +    $keys = preg_grep('/^REDIRECT_/', array_keys($_SERVER));
284 +    if (!empty($keys)) {
285 +        foreach ($keys as $key) {
286 +            $key = substr($key, 9);
287 +            if (!array_key_exists($key, $_SERVER))
288 +                $_SERVER[$key] = $_SERVER["REDIRECT_$key"];
289 +        }
290 +    }
291  
292  // Clean the document root variable and make sure it doesn't have a trailing slash
293      $_SERVER['DOCUMENT_ROOT'] = preg_replace('/\/+$/', '', $_SERVER['DOCUMENT_ROOT']);
294 @@ -94,6 +81,29 @@
295          exit;
296      }
297  
298 +/**
299 + * $Path is an array of PATH_INFO passed into the script via mod_rewrite or some
300 + * other lesser means.  It contains most of the information required for
301 + * figuring out what functions the user wants to access.
302 + *
303 + * @global  array   $GLOBALS['Path']
304 + * @name    $Path
305 +/**/
306 +    global $Path;
307 +    $Path = explode('/', preg_replace('/^\/+/',   '',    // Remove leading slashes
308 +                         preg_replace('/[\s]+/', ' ',    // Convert extra whitespace
309 +                                                         // Grab the path info from various different places.
310 +                             array_key_exists('PATH_INFO', $_SERVER)
311 +                             && $_SERVER['PATH_INFO']
312 +                                ? $_SERVER['PATH_INFO']
313 +                                : (array_key_exists('PATH_INFO', $_ENV)
314 +                                   && $_ENV['PATH_INFO']
315 +                                    ? $_ENV['PATH_INFO']
316 +                                    : $_GET['PATH_INFO']
317 +                                  )
318 +                         ))
319 +                   );
320 +
321  // Load the database connection routines
322      require_once 'includes/db.php';
323  
324 Index: mythplugins/mythweb/includes/mobile.php
325 ===================================================================
326 --- mythplugins/mythweb/includes/mobile.php     (.../tags/release-0-19) (revision 10931)
327 +++ mythplugins/mythweb/includes/mobile.php     (.../branches/release-0-19-fixes)       (revision 10931)
328 @@ -74,58 +74,56 @@
329       * If you don't know the screensize of some mobile terminal then use
330       * an empty array or approximate dimensions.
331       */
332 -    $mobiles = array(/* Phones using the Series 60 platform, e.g. Nokia 3650 and 6600. */
333 -             'Series 60' => array('width' => 176, 'height' => 208),
334 -             'Series60' => array('width' => 176, 'height' => 208),
335 -             'C500' => array('width'=>176, 'height'=> 220), // SPV C500
336 +    $mobiles = array(
337 +                /* Phones using the Series 60 platform, e.g. Nokia 3650 and 6600. */
338 +                     'Series 60' => array('width' => 176, 'height' => 208),
339 +                     'Series60'  => array('width' => 176, 'height' => 208),
340 +                     'C500'      => array('width'=>176, 'height'=> 220), // SPV C500
341 +                /* Phones using the Series 90 platform, e.g. Nokia 7710. */
342 +                     'Series 90' => array('width' => 640, 'height' => 320),
343 +                     'Series90' => array('width' => 640, 'height' => 320),
344 +                /* The following strings are added for the Palm browser WebPro
345 +                 * WebPro sometimes supplies the screen dimensions, but sometimes not
346 +                 * but we try to detect the best as possible */
347 +                     '240x320'    => array('width' => 240, 'height' => 320), // PocketPC IE
348 +                     '320x320'    => array('width' => 320, 'height' => 320), // For all Palm Tungsten models
349 +                     '320x480'    => array('width' => 320, 'height' => 480), // For Palm Tungsten T
350 +                     '480x320'    => array('width' => 480, 'height' => 320), // For Palm Tungsten T
351 +                     '320x480x16' => array('width' => 320, 'height' => 480), // For Palm Tungsten T
352 +                     '480x320x16' => array('width' => 480, 'height' => 320), // For Palm Tungsten T
353 +                     '320x320x16' => array('width' => 320, 'height' => 320),
354 +                     'WebPro'     => array('width' => 320, 'height' => 320), // For all Palm Tungsten models
355 +                 /* A generic mobile phone using Symbian OS. All Symbian phones don't
356 +                  * necessarily have the same screen size so if you want to include
357 +                  * some specific Symbian phones then place them above this line. */
358 +                     'Symbian' => array('width' => 176, 'height' => 208),
359  
360 -             /* Phones using the Series 90 platform, e.g. Nokia 7710. */
361 -             'Series 90' => array('width' => 640, 'height' => 320),
362 -             'Series90' => array('width' => 640, 'height' => 320),
363 +                     'Nokia' => array(), // Nokia phones and emulators
364 +                     'Eric' => array(), // Ericsson WAP phones and emulators
365 +                     'WapI' => array(), // Ericsson WapIDE 2.0
366 +                     'MC21' => array(), // Ericsson MC218
367 +                     'AUR ' => array(), // Ericsson R320
368 +                     'R380' => array(), // Ericsson R380
369 +                     'UP.B' => array(), // UP.Browser
370 +                     'WinW' => array(), // WinWAP browser
371 +                     'UPG1' => array(), // UP.SDK 4.0
372 +                     'upsi' => array(), // another kind of UP.Browser ??
373 +                     'QWAP' => array(), // unknown QWAPPER browser
374 +                     'Jigs' => array(), // unknown JigSaw browser
375 +                     'Java' => array(), // unknown Java based browser
376 +                     'Alca' => array(), // unknown Alcatel-BE3 browser (UP based?)
377 +                     'MITS' => array(), // unknown Mitsubishi browser
378 +                     'MOT-' => array(), // unknown browser (UP based?)
379 +                     'My S' => array(), // unknown Ericsson devkit browser ?
380 +                     'WAPJ' => array(), // Virtual WAPJAG www.wapjag.de
381 +                     'fetc' => array(), // fetchpage.cgi Perl script from www.wapcab.de
382 +                     'ALAV' => array(), // yet another unknown UP based browser ?
383 +                     'Wapa' => array(), // another unknown browser (Web based "Wapalyzer"?)
384 +                     'LGE-' => array(), // LG phones
385  
386 -            /* The following strings are added for the Palm browser WebPro
387 -              * WebPro sometimes supplies the screen dimensions, but sometimes not
388 -             * but we try to detect the best as possible
389 -              */
390 -            '320x480' => array('width' => 320, 'height' => 480), // For Palm Tungsten T
391 -            '480x320' => array('width' => 480, 'height' => 320), // For Palm Tungsten T
392 -            '320x320' => array('width' => 320, 'height' => 320), // For all Palm Tungsten models
393 -            '320x480x16' => array('width' => 320, 'height' => 480), // For Palm Tungsten T
394 -            '480x320x16' => array('width' => 480, 'height' => 320), // For Palm Tungsten T
395 -            '320x320x16' => array('width' => 320, 'height' => 320),
396 -            'WebPro' => array('width' => 320, 'height' => 320), // For all Palm Tungsten models
397 -
398 -             /* A generic mobile phone using Symbian OS. All Symbian phones don't
399 -              * necessarily have the same screen size so if you want to include
400 -              * some specific Symbian phones then place them above this line. */
401 -             'Symbian' => array('width' => 176, 'height' => 208),
402 -
403 -             'Nokia' => array(), // Nokia phones and emulators
404 -             'Eric' => array(), // Ericsson WAP phones and emulators
405 -             'WapI' => array(), // Ericsson WapIDE 2.0
406 -             'MC21' => array(), // Ericsson MC218
407 -             'AUR ' => array(), // Ericsson R320
408 -             'R380' => array(), // Ericsson R380
409 -             'UP.B' => array(), // UP.Browser
410 -             'WinW' => array(), // WinWAP browser
411 -             'UPG1' => array(), // UP.SDK 4.0
412 -             'upsi' => array(), // another kind of UP.Browser ??
413 -             'QWAP' => array(), // unknown QWAPPER browser
414 -             'Jigs' => array(), // unknown JigSaw browser
415 -             'Java' => array(), // unknown Java based browser
416 -             'Alca' => array(), // unknown Alcatel-BE3 browser (UP based?)
417 -             'MITS' => array(), // unknown Mitsubishi browser
418 -             'MOT-' => array(), // unknown browser (UP based?)
419 -             'My S' => array(), // unknown Ericsson devkit browser ?
420 -             'WAPJ' => array(), // Virtual WAPJAG www.wapjag.de
421 -             'fetc' => array(), // fetchpage.cgi Perl script from www.wapcab.de
422 -             'ALAV' => array(), // yet another unknown UP based browser ?
423 -             'Wapa' => array(), // another unknown browser (Web based "Wapalyzer"?)
424 -             'LGE-' => array(), // LG phones
425 -
426 -             /* For debugging: you can try out the mobile mode without a mobile phone.
427 -              * Replace 'Opera' with your browser. Comment out for release version. */
428 -             //'Opera' => array('width' => 176, 'height' => 208)
429 +                 /* For debugging: you can try out the mobile mode without a mobile phone.
430 +                  * Replace 'Opera' with your browser. Comment out for release version. */
431 +                     //'Opera' => array('width' => 176, 'height' => 208)
432               );
433  
434      /* Scan through $mobiles and try to find matching user agent. */
435 Index: mythplugins/mythweb/includes/recording_schedules.php
436 ===================================================================
437 --- mythplugins/mythweb/includes/recording_schedules.php        (.../tags/release-0-19) (revision 10931)
438 +++ mythplugins/mythweb/includes/recording_schedules.php        (.../branches/release-0-19-fixes)       (revision 10931)
439 @@ -68,10 +68,14 @@
440  // Cleanup
441      mysql_free_result($result);
442  
443 +// Initialize
444 +    global $Scheduled_Recordings, $Num_Conflicts, $Num_Scheduled;
445 +    $Scheduled_Recordings = array();
446 +    $Num_Conflicts        = 0;
447 +    $Num_Scheduled        = 0;
448 +
449  // Load all of the scheduled recordings.  We will need them at some point, so we
450  // might as well get it overwith here.
451 -    global $Scheduled_Recordings, $Num_Conflicts, $Num_Scheduled;
452 -    $Scheduled_Recordings = array();
453      foreach (get_backend_rows('QUERY_GETALLPENDING', 2) as $key => $program) {
454      // The offset entry
455          if ($key === 'offset') {
456 Index: mythplugins/mythweb/includes/session.php
457 ===================================================================
458 --- mythplugins/mythweb/includes/session.php    (.../tags/release-0-19) (revision 10931)
459 +++ mythplugins/mythweb/includes/session.php    (.../branches/release-0-19-fixes)       (revision 10931)
460 @@ -19,8 +19,8 @@
461  
462  // Start the session
463      session_name('mythweb_id');
464 -    session_set_cookie_params(60 * 60 * 30, '/');       // 30 day timeout on cookies
465 -    ini_set('session.gc_maxlifetime', 60 * 60 * 30);    // ... and sessions
466 +    session_set_cookie_params(60 * 60 * 24 * 365, '/');     // 1 year timeout on cookies
467 +    ini_set('session.gc_maxlifetime', 60 * 60 * 24 * 30);   // 30 day timeout on sessions
468      session_set_save_handler('sess_do_nothing', 'sess_do_nothing', 'sess_read', 'sess_write', 'sess_destroy', 'sess_gc');
469      session_start();
470  
471 Index: mythplugins/mythweb/modules/weather/handler.php
472 ===================================================================
473 --- mythplugins/mythweb/modules/weather/handler.php     (.../tags/release-0-19) (revision 10931)
474 +++ mythplugins/mythweb/modules/weather/handler.php     (.../branches/release-0-19-fixes)       (revision 10931)
475 @@ -222,8 +222,10 @@
476  
477      $data = explode("|", $data);
478      for($i = 0;$i<5;$i++) {
479 -        $forecast = new Forecast($data[5 + $i],$data[$i]);
480 -        $forecast->dayofweek = $data[$i];
481 +       # mktime uses 0-6;  msnbc gives us 1-7;  adjust msnbc to match mktime
482 +       $dayofweek = $data[$i] - 1;
483 +        $forecast = new Forecast($data[5 + $i],$dayofweek);
484 +        $forecast->dayofweek = $dayofweek;
485          list($forecast->DescImage,$forecast->DescText) = getImageAndDescFromId($data[15 + $i]);
486          $forecast->DescImage = (strlen($forecast->DescImage) > 0) ? $forecast->DescImage : "unknown.png";
487          $forecast->DescText = (strlen($forecast->DescText) > 0) ? $forecast->DescText : t('Unknown') . " (" . $data[15+$i] . ")";
488 Index: mythplugins/mythweb/modules/status/handler.php
489 ===================================================================
490 --- mythplugins/mythweb/modules/status/handler.php      (.../tags/release-0-19) (revision 10931)
491 +++ mythplugins/mythweb/modules/status/handler.php      (.../branches/release-0-19-fixes)       (revision 10931)
492 @@ -18,14 +18,17 @@
493      $masterhost = get_backend_setting('MasterServerIP');
494      $statusport = get_backend_setting('BackendStatusPort');
495  
496 +// XML mode?
497 +    $xml_param = ($Path[1] == 'xml') ? '/xml' : '';
498 +
499  // Make sure the content is interpreted as UTF-8
500      header('Content-Type:  text/html; charset=UTF-8');
501  
502  // Load the status page
503      if (function_exists('file_get_contents'))
504 -        $status = file_get_contents("http://$masterhost:$statusport");
505 +        $status = file_get_contents("http://$masterhost:$statusport$xml_param");
506      else
507 -        $status = implode("\n", file("http://$masterhost:$statusport"));
508 +        $status = implode("\n", file("http://$masterhost:$statusport$xml_param"));
509  
510  // Extract the page title
511      preg_match('#<title>(.+?)</title>#s', $status, $title);
512 Index: mythplugins/mythweb/modules/backend_log/handler.php
513 ===================================================================
514 --- mythplugins/mythweb/modules/backend_log/handler.php (.../tags/release-0-19) (revision 10931)
515 +++ mythplugins/mythweb/modules/backend_log/handler.php (.../branches/release-0-19-fixes)       (revision 10931)
516 @@ -16,7 +16,7 @@
517  // Where to start searching from
518      $_GET['start'] = intVal($_GET['start']);
519      if ($_GET['start'] < 1)
520 -        $_GET['start'] = 1;
521 +        $_GET['start'] = 0;
522  
523  // How many entries to show?
524      $_GET['show'] = intVal($_GET['show']);
525 Index: mythplugins/mythweb/modules/tv/upcoming.php
526 ===================================================================
527 --- mythplugins/mythweb/modules/tv/upcoming.php (.../tags/release-0-19) (revision 10931)
528 +++ mythplugins/mythweb/modules/tv/upcoming.php (.../branches/release-0-19-fixes)       (revision 10931)
529 @@ -103,8 +103,9 @@
530                          continue;
531                  }
532              // Skip deactivated shows?
533 -                elseif (!$_SESSION['scheduled_recordings']['disp_deactivated']) {
534 -                    continue;
535 +                elseif ($show->recstatus != 'Recording') {
536 +                    if (!$_SESSION['scheduled_recordings']['disp_deactivated'])
537 +                        continue;
538                  }
539              // Assign a reference to this show to the various arrays
540                  $all_shows[] =& $Scheduled_Recordings[$channum][$starttime][$key];
541 Index: mythplugins/mythweb/modules/tv/recorded.php
542 ===================================================================
543 --- mythplugins/mythweb/modules/tv/recorded.php (.../tags/release-0-19) (revision 10931)
544 +++ mythplugins/mythweb/modules/tv/recorded.php (.../branches/release-0-19-fixes)       (revision 10931)
545 @@ -128,9 +128,21 @@
546                  continue;
547          // Get the length (27 == recendts; 26 == recstartts)
548              $length = $record[27] - $record[26];
549 -        // Keep track of the total time and disk space used
550 +        // Keep track of the total time and disk space used (9 == fs_high; 10 == fs_low)
551              $Total_Time += $length;
552 -            $Total_Used += ($record[9] + ($record[10] < 0)) * 4294967296 + $record[10];  // 9 == fs_high; 10 == fs_low;
553 +            if (function_exists('gmp_add')) {
554 +            // GMP functions should work better with 64 bit numbers.
555 +                $size = gmp_add($record[10],
556 +                                gmp_mul('4294967296',
557 +                                        gmp_add($record[9], $record[10] < 0 ? '1' : '0')
558 +                                       )
559 +                               );
560 +                $Total_Used = gmp_strval(gmp_add($Total_Used, $size));
561 +            }
562 +            else {
563 +            // This is inaccurate, but it's the best we can get without GMP.
564 +                $Total_Used += ($record[9] + ($record[10] < 0)) * 4294967296 + $record[10];
565 +            }
566          // keep track of their names and how many episodes we have recorded
567              $Total_Programs++;
568              $Groups[$record[30]]++;
569 @@ -223,8 +235,28 @@
570  
571  // How much free disk space on the backend machine?
572      list($size_high, $size_low, $used_high, $used_low) = explode(backend_sep, backend_command('QUERY_FREE_SPACE'));
573 -    define(disk_size, (($size_high + ($size_low < 0)) * 4294967296 + $size_low) * 1024);
574 -    define(disk_used, (($used_high + ($used_low < 0)) * 4294967296 + $used_low) * 1024);
575 +    if (function_exists('gmp_add')) {
576 +    // GMP functions should work better with 64 bit numbers.
577 +        $size = gmp_mul('1024',
578 +                        gmp_add($size_low,
579 +                                gmp_mul('4294967296',
580 +                                        gmp_add($size_high, $size_low < 0 ? '1' : '0'))
581 +                               )
582 +                       );
583 +        define(disk_size, gmp_strval($size));
584 +        $size = gmp_mul('1024',
585 +                        gmp_add($used_low,
586 +                                gmp_mul('4294967296',
587 +                                        gmp_add($used_high, $used_low < 0 ? '1' : '0'))
588 +                               )
589 +                       );
590 +        define(disk_used, gmp_strval($size));
591 +    }
592 +    else {
593 +    // This is inaccurate, but it's the best we can get without GMP.
594 +        define(disk_size, (($size_high + ($size_low < 0)) * 4294967296 + $size_low) * 1024);
595 +        define(disk_used, (($used_high + ($used_low < 0)) * 4294967296 + $used_low) * 1024);
596 +    }
597  
598  // Load the class for this page
599      require_once theme_dir.'tv/recorded.php';
600 Index: mythplugins/mythweb/.htaccess
601 ===================================================================
602 --- mythplugins/mythweb/.htaccess       (.../tags/release-0-19) (revision 10931)
603 +++ mythplugins/mythweb/.htaccess       (.../branches/release-0-19-fixes)       (revision 10931)
604 @@ -22,6 +22,7 @@
605  #    AuthName           "MythTV"
606  #    AuthDigestFile     /var/www/htdigest
607  #    Require            valid-user
608 +#    BrowserMatch       "MSIE"      AuthDigestEnableQueryStringHack=On
609  
610  # MythTV now uses the correct file suffix for mpeg files, so all .nuv files
611  # should actually be NuppleVideo.  However, apache probably doesn't know what
612 @@ -66,8 +67,6 @@
613  
614          php_value memory_limit                  32M
615  
616 -        php_value session.save_path             php_sessions
617 -
618          php_value output_buffering              4096
619          php_value register_globals              0
620          php_value magic_quotes_gpc              0
621 Index: mythplugins/mythweb/js/debug.js
622 ===================================================================
623 --- mythplugins/mythweb/js/debug.js     (.../tags/release-0-19) (revision 0)
624 +++ mythplugins/mythweb/js/debug.js     (.../branches/release-0-19-fixes)       (revision 10931)
625 @@ -0,0 +1,24 @@
626 +/**
627 + * A random assortment of javascript debug routines
628 + *
629 + * @url         $URL$
630 + * @date        $Date$
631 + * @version     $Revision$
632 + * @author      $Author$
633 + * @copyright   Silicon Mechanics
634 + * @license     LGPL
635 + *
636 + * @package     SiMech
637 + * @subpackage  Javascript
638 + *
639 +/**/
640 +
641 +    var debug_window_handle;
642 +// Create a debug window and debug into it
643 +    function debug_window(string) {
644 +        if (!debug_window_handle || debug_window_handle.closed) {
645 +            debug_window_handle = window.open('', 'Debug Window','scrollbars, resizable, width=400, height=600');
646 +            debug_window_handle.document.write('<html><body style="font-size: 9pt; background-color: #f88;">');
647 +        }
648 +        debug_window_handle.document.write('<pre>'+string+'</pre><hr>');
649 +    }
650
651 Property changes on: mythplugins/mythweb/js/debug.js
652 ___________________________________________________________________
653 Name: svn:eol-style
654    + native
655 Name: svn:mime-type
656    + text/x-javascript
657 Name: svn:keywords
658    + Date Revision Author HeadURL
659
660 Index: mythplugins/mythweb/js/browser.js
661 ===================================================================
662 --- mythplugins/mythweb/js/browser.js   (.../tags/release-0-19) (revision 10931)
663 +++ mythplugins/mythweb/js/browser.js   (.../branches/release-0-19-fixes)       (revision 10931)
664 @@ -215,14 +215,18 @@
665      browser.is_css = (document.body  && document.body.style)
666      browser.is_w3c = (browser.is_css && browser.getElementById)
667  
668 -// Cookie support
669 -    var tmp = document.cookie;
670 -       document.cookie = 'cookies=true';
671 -       browser.cookies = (document.cookie) ? true : false;
672 -    document.cookie = tmp;
673 +// Cookie support -- only create a cookie if there isn't one already.  It seems
674 +// that doing this can override the exipiration info in existing cookies.
675 +    browser.cookies = (document.cookie) ? true : false;
676 +    if (!browser.cookies) {
677 +        var tmp = document.cookie;
678 +        document.cookie = 'cookie_test=true';
679 +        browser.cookies = (document.cookie) ? true : false;
680 +        document.cookie = tmp;
681 +    }
682  
683  // Java support
684 -       browser.java = navigator.javaEnabled();
685 +    browser.java = navigator.javaEnabled();
686  
687  /****************************** Plugin Support ******************************/
688  
689 Index: mythplugins/mythweb/README
690 ===================================================================
691 --- mythplugins/mythweb/README  (.../tags/release-0-19) (revision 10931)
692 +++ mythplugins/mythweb/README  (.../branches/release-0-19-fixes)       (revision 10931)
693 @@ -1,18 +1,12 @@
694  This is the README file for the MythWeb package.
695 -January 17, 2006
696 +March 6, 2006
697  
698 -Version: .19 pre
699 -(c) 2002-2006  Thor Sigvaldason <mythtv(a)lamedomainname(o)com>
700 +Version: .19
701 +(c) 2002-2006  Chris Petersen   <mythweb(a)forevermore(o)net>
702                 Isaac Richards   <ijr(a)po(o)cwru(o)edu>
703 -               Chris Petersen   <mythweb(a)forevermore(o)net>
704 +               Thor Sigvaldason <mythtv(a)lamedomainname(o)com>
705 +               and others... (see mythtv.org commit logs for details)
706  
707 -with contributions from many people including:
708 -
709 -Michael Kedl   <kedlm(a)knology(o)net>
710 -Jonathan Kolb  <jkolb(a)greyshift(o)net
711 -Ed Wildgoose   <edward(o)wildgoose(a)frmhedge(o)com>
712 -Kenneth Aafloy <ke-aa(a)frisurf(o)no>
713 -
714  MythWeb is distributed under the GNU GENERAL PUBLIC LICENSE version 2, and where
715  noted with the @license tag, the LESSER GENERAL PUBLIC LICENSE version 2.
716  Please see http://www.gnu.org for details and the specific text of the license.
717 @@ -63,10 +57,22 @@
718  
719      In order for the included .htaccess to work properly, you will need to
720  set apache's "AllowOverride" setting to "All" (or at least "Options") for
721 -the root mythweb directory.  This directive lives within <Directory/> tags,
722 -so make sure you're changing the setting for the correct directory.  You will
723 -also need to make sure that the following apache modules are enabled:
724 +the root mythweb directory.  This directive lives within <Directory> tags,
725 +so make sure you're changing the setting for the correct directory.  Please
726 +keep in mind that most distros correctly disable everything for <Directory />,
727 +and then later override those with something like <Directory /var/www/html>.
728 +The simplest way to do this is to put a file into /etc/httpd/conf.d (or
729 +whatever your distro calls it) containing something like:
730  
731 +    <Directory "/var/www/html/mythweb" >
732 +        Options         FollowSymLinks
733 +        AllowOverride   All
734 +    </Directory>
735 +
736 +Just make sure that the path points to your MythWeb installation, since that
737 +will likely differ from system to system.  You will also need to make sure that
738 +the following apache modules are enabled:
739 +
740      mod_env
741      mod_rewrite
742  
743 Index: mythplugins/mythdvd/mtd/jobthread.cpp
744 ===================================================================
745 --- mythplugins/mythdvd/mtd/jobthread.cpp       (.../tags/release-0-19) (revision 10931)
746 +++ mythplugins/mythdvd/mtd/jobthread.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
747 @@ -11,6 +11,7 @@
748  #include <sys/types.h>
749  #include <sys/stat.h>
750  #include <fcntl.h>
751 +#include <unistd.h>
752  
753  #include <iostream>
754  using namespace std;
755 Index: mythplugins/mythdvd/mtd/mtd.cpp
756 ===================================================================
757 --- mythplugins/mythdvd/mtd/mtd.cpp     (.../tags/release-0-19) (revision 10931)
758 +++ mythplugins/mythdvd/mtd/mtd.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
759 @@ -8,6 +8,7 @@
760  
761  */
762  
763 +#include <unistd.h>
764  #include <qstringlist.h>
765  #include <qregexp.h>
766  #include <qdir.h>
767 Index: mythplugins/mythdvd/mtd/logging.cpp
768 ===================================================================
769 --- mythplugins/mythdvd/mtd/logging.cpp (.../tags/release-0-19) (revision 10931)
770 +++ mythplugins/mythdvd/mtd/logging.cpp (.../branches/release-0-19-fixes)       (revision 10931)
771 @@ -9,6 +9,7 @@
772  */
773  #include "logging.h"
774  
775 +#include <unistd.h>
776  #include <qdatetime.h>
777  
778  #include <mythtv/mythcontext.h>
779 Index: mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp
780 ===================================================================
781 --- mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp   (.../tags/release-0-19) (revision 10931)
782 +++ mythplugins/mythmusic/mythmusic/vorbisdecoder.cpp   (.../branches/release-0-19-fixes)       (revision 10931)
783 @@ -12,6 +12,7 @@
784  #include "metadata.h"
785  #include "metaiooggvorbiscomment.h"
786  
787 +#include <mythtv/mythconfig.h>
788  #include <mythtv/mythcontext.h>
789  
790  // static functions for OggVorbis
791 @@ -240,8 +241,13 @@
792              seekTime = -1.0;
793          }
794  
795 +#ifdef WORDS_BIGENDIAN
796 +        len = ov_read(&oggfile, (char *) (output_buf + output_at), bks, 1, 2, 1,
797 +                      &section);
798 +#else
799          len = ov_read(&oggfile, (char *) (output_buf + output_at), bks, 0, 2, 1,
800                        &section);
801 +#endif
802  
803          if (len > 0) {
804              bitrate = ov_bitrate_instant(&oggfile) / 1000;
805 Index: mythplugins/mythmusic/mythmusic/flacdecoder.cpp
806 ===================================================================
807 --- mythplugins/mythmusic/mythmusic/flacdecoder.cpp     (.../tags/release-0-19) (revision 10931)
808 +++ mythplugins/mythmusic/mythmusic/flacdecoder.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
809 @@ -12,6 +12,7 @@
810  #include "metadata.h"
811  #include "metaioflacvorbiscomment.h"
812  
813 +#include <mythtv/mythconfig.h>
814  #include <mythtv/mythcontext.h>
815  
816  #include <qtimer.h>
817 @@ -102,7 +103,11 @@
818              for (channel = 0; channel < chan; channel++)
819              {
820                 sample = (FLAC__int8)buffer[channel][cursamp];
821 +#ifdef WORDS_BIGENDIAN
822 +               *(output_buf + output_at++) = ((sample >> 8) & 0xff);
823 +#else
824                 *(output_buf + output_at++) = ((sample >> 0) & 0xff);
825 +#endif
826                 output_bytes += 1;
827              }
828          }   
829 @@ -114,8 +119,13 @@
830              for (channel = 0; channel < chan; channel++)
831              { 
832                 sample = (FLAC__int16)buffer[channel][cursamp];             
833 +#ifdef WORDS_BIGENDIAN
834 +               *(output_buf + output_at++) = ((sample >> 8) & 0xff);
835                 *(output_buf + output_at++) = ((sample >> 0) & 0xff);
836 +#else
837 +               *(output_buf + output_at++) = ((sample >> 0) & 0xff);
838                 *(output_buf + output_at++) = ((sample >> 8) & 0xff);
839 +#endif
840                 output_bytes += 2;
841              }
842          }
843 Index: mythplugins/mythmusic/mythmusic/maddecoder.cpp
844 ===================================================================
845 --- mythplugins/mythmusic/mythmusic/maddecoder.cpp      (.../tags/release-0-19) (revision 10931)
846 +++ mythplugins/mythmusic/mythmusic/maddecoder.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
847 @@ -16,6 +16,7 @@
848  #include <mythtv/audiooutput.h>
849  #include "metaioid3v2.h"
850  
851 +#include <mythtv/mythconfig.h>
852  #include <mythtv/mythcontext.h>
853  
854  #define XING_MAGIC     (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g')
855 @@ -407,7 +408,7 @@
856          flush(TRUE);
857  
858          if (output()) {
859 -           output()->Drain();
860 +            output()->Drain();
861          }
862  
863          done = TRUE;
864 @@ -488,15 +489,25 @@
865              flush();
866          }
867          sample = fix_sample(16, *left++);
868 +#ifdef WORDS_BIGENDIAN
869 +        *(output_buf + output_at++) = ((sample >> 8) & 0xff);
870          *(output_buf + output_at++) = ((sample >> 0) & 0xff);
871 +#else
872 +        *(output_buf + output_at++) = ((sample >> 0) & 0xff);
873          *(output_buf + output_at++) = ((sample >> 8) & 0xff);
874 +#endif
875          output_bytes += 2;
876  
877          if (channels == 2)
878          {
879              sample = fix_sample(16, *right++);
880 +#ifdef WORDS_BIGENDIAN
881 +            *(output_buf + output_at++) = ((sample >> 8) & 0xff);
882              *(output_buf + output_at++) = ((sample >> 0) & 0xff);
883 +#else
884 +            *(output_buf + output_at++) = ((sample >> 0) & 0xff);
885              *(output_buf + output_at++) = ((sample >> 8) & 0xff);
886 +#endif
887              output_bytes += 2;
888          }
889      }
890 Index: mythplugins/mythweather/mythweather/weather.cpp
891 ===================================================================
892 --- mythplugins/mythweather/mythweather/weather.cpp     (.../tags/release-0-19) (revision 10931)
893 +++ mythplugins/mythweather/mythweather/weather.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
894 @@ -2571,6 +2571,14 @@
895           return false;
896       }
897  
898 +     int imageCount = 5;
899 +     QString imagesList = parseData(tempData, "imagenames = new Array( '", ";");
900 +     if (imagesList != "<NULL>")
901 +     {
902 +         QStringList imageURLs = QStringList::split(",", imagesList);
903 +         imageCount = imageURLs.size();
904 +     }
905 +
906       QString fileprefix = MythContext::GetConfDir();
907  
908       QDir dir(fileprefix);
909 @@ -2587,13 +2595,13 @@
910           cerr << "MythWeather: Map File Prefix: " << fileprefix << endl;
911  
912       // delete existing radar maps
913 -     for (int x = 1; x <= 6; x++)
914 +     for (int x = 1; x <= 10; x++)
915           QFile::remove(QString(fileprefix + "/radar%1.jpg").arg(x));
916  
917       if (debug)
918           cerr << "MythWeather: Copying Map Files from Server (" << imageLoc << ")...\n";
919  
920 -     for (int x = 1; x <= 6; x++)
921 +     for (int x = 1; x <= imageCount; x++)
922       {
923           QString sFile = QString(fileprefix + "/radar%1.jpg").arg(x);
924           sURL = QString("http://image.weather.com" + imageLoc + "%1L.jpg").arg(x);
925 Index: mythplugins/mythcontrols/mythcontrols/mythcontrols.cpp
926 ===================================================================
927 --- mythplugins/mythcontrols/mythcontrols/mythcontrols.cpp      (.../tags/release-0-19) (revision 10931)
928 +++ mythplugins/mythcontrols/mythcontrols/mythcontrols.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
929 @@ -46,22 +46,6 @@
930  #include "keygrabber.h"
931  
932  
933 -static QMap<int,QString> FindContexts(const QString &context)
934 -{
935 -    QMap<int,QString> retval;
936 -    retval.clear();
937 -    if (context != JUMP_CONTEXT) retval[-1] = JUMP_CONTEXT;
938 -    retval[0] = context;
939 -    if (context != JUMP_CONTEXT && context != GLOBAL_CONTEXT)
940 -    {
941 -        if (context == "TV Editting")
942 -            retval[1] = "TV Playback";
943 -        retval[2] = GLOBAL_CONTEXT;
944 -        if (context != "qt")
945 -            retval[3] = "qt";
946 -    }
947 -    return retval;
948 -}
949  
950  static const QString KeyToDisplay(const QString key)
951  {
952 @@ -838,7 +822,11 @@
953      refreshKeyInformation();
954  }
955  
956 -void MythControls::addBindings(QDict<binding_t> &bindings, const QString &context, const QString &contextParent, int bindlevel)
957 +
958 +
959 +void MythControls::addBindings(QDict<binding_t> &bindings,
960 +                               const QString &context,
961 +                               const QString &contextParent, int bindlevel)
962  {
963      QStringList *actions = key_bindings->getActions(context);
964  
965 @@ -872,18 +860,13 @@
966  
967  BindingList *MythControls::getKeyBindings(const QString &context)
968  {
969 +    QStringList keys;
970      QDict<binding_t> bindings;
971      bindings.clear();
972  
973 -    QMap<int,QString> contextList = FindContexts(context);
974 -    for (QMap<int,QString>::iterator it = contextList.begin(); it != contextList.end(); ++it)
975 -    {
976 -        int level = it.key();
977 -        QString curcontext = it.data();
978 -        addBindings(bindings, curcontext, context, level);
979 -    }
980 +    for (size_t i = 0; i < contexts.size(); i++)
981 +        addBindings(bindings, contexts[i], context, i);
982  
983 -    QStringList keys;
984  
985      for (QDictIterator<binding_t> it(bindings); it.current(); ++it)
986      {
987 Index: mythplugins/mythcontrols/mythcontrols/actionset.cpp
988 ===================================================================
989 --- mythplugins/mythcontrols/mythcontrols/actionset.cpp (.../tags/release-0-19) (revision 10931)
990 +++ mythplugins/mythcontrols/mythcontrols/actionset.cpp (.../branches/release-0-19-fixes)       (revision 10931)
991 @@ -139,13 +139,19 @@
992  /* method description in header */
993  QStringList * ActionSet::actionStrings(const QString &context_name) const
994  {
995 -    QStringList *action_strings = new QStringList();
996 -    QDictIterator<Action> it(*(_contexts[context_name]));
997 +    Context *c = _contexts[context_name];
998  
999 -    for (; it.current(); ++it)
1000 -        action_strings->append(it.currentKey());
1001 +    if (c == NULL) return NULL;
1002 +    else
1003 +    {
1004 +        QStringList *action_strings = new QStringList();
1005 +        QDictIterator<Action> it(*(_contexts[context_name]));
1006 +
1007 +        for (; it.current(); ++it)
1008 +            action_strings->append(it.currentKey());
1009      
1010 -    return action_strings;
1011 +        return action_strings;
1012 +    }
1013  }
1014  
1015  
1016 Index: mythplugins/mythcontrols/mythcontrols/keybindings.h
1017 ===================================================================
1018 --- mythplugins/mythcontrols/mythcontrols/keybindings.h (.../tags/release-0-19) (revision 10931)
1019 +++ mythplugins/mythcontrols/mythcontrols/keybindings.h (.../branches/release-0-19-fixes)       (revision 10931)
1020 @@ -65,6 +65,8 @@
1021      /**
1022       * @brief Get a list of the context names.
1023       * @return A list of the context names.
1024 +     * @note The returned list is a copy and can be modified without
1025 +     * side-effects.
1026       */
1027      inline QStringList * getContexts() const
1028      {
1029 Index: mythplugins/mythvideo/mythvideo/videomanager.h
1030 ===================================================================
1031 --- mythplugins/mythvideo/mythvideo/videomanager.h      (.../tags/release-0-19) (revision 10931)
1032 +++ mythplugins/mythvideo/mythvideo/videomanager.h      (.../branches/release-0-19-fixes)       (revision 10931)
1033 @@ -30,7 +30,7 @@
1034    public:
1035      VideoManager(MythMainWindow *parent, const char *name = 0);
1036      ~VideoManager(void);
1037 -    void VideoManager::processEvents() { qApp->processEvents(); }
1038 +    void processEvents() { qApp->processEvents(); }
1039      
1040    public slots:
1041      void slotManualIMDB();
1042 Index: mythplugins/mythvideo/mythvideo/videoselected.h
1043 ===================================================================
1044 --- mythplugins/mythvideo/mythvideo/videoselected.h     (.../tags/release-0-19) (revision 10931)
1045 +++ mythplugins/mythvideo/mythvideo/videoselected.h     (.../branches/release-0-19-fixes)       (revision 10931)
1046 @@ -35,7 +35,7 @@
1047      VideoSelected(VideoList *lvideolist,
1048                   MythMainWindow *parent, const char *name = 0, int index = 0);
1049      ~VideoSelected();
1050 -    void VideoSelected::processEvents() { qApp->processEvents(); }
1051 +    void processEvents() { qApp->processEvents(); }
1052      
1053  
1054    protected slots:
1055 Index: mythplugins/mythphone/mythphone/sipfsm.h
1056 ===================================================================
1057 --- mythplugins/mythphone/mythphone/sipfsm.h    (.../tags/release-0-19) (revision 10931)
1058 +++ mythplugins/mythphone/mythphone/sipfsm.h    (.../branches/release-0-19-fixes)       (revision 10931)
1059 @@ -618,7 +618,7 @@
1060      SipWatcher *CreateWatcherFsm(QString Url);
1061      SipIM *CreateIMFsm(QString Url="", QString callIdStr="");
1062      void StopWatchers();
1063 -    void SipFsm::KickWatcher(SipUrl *Url);
1064 +    void KickWatcher(SipUrl *Url);
1065      void SendIM(QString destUrl, QString CallId, QString imMsg);
1066      int numCalls();
1067      int getPrimaryCall() { return primaryCall; };
1068 Index: mythplugins/mythphone/mythphone/vxml.h
1069 ===================================================================
1070 --- mythplugins/mythphone/mythphone/vxml.h      (.../tags/release-0-19) (revision 10931)
1071 +++ mythplugins/mythphone/mythphone/vxml.h      (.../branches/release-0-19-fixes)       (revision 10931)
1072 @@ -10,7 +10,7 @@
1073  {
1074    public:
1075      vxmlVariable(QString N, QString V);             
1076 -    vxmlVariable::vxmlVariable(QString N, short *wav, int S);
1077 +    vxmlVariable(QString N, short *wav, int S);
1078      virtual ~vxmlVariable() {}; 
1079      bool isType(QString t) { return (t == Type); };
1080      QString getName() { return Name; };
1081 Index: mythplugins/mythgame/mythgame/gamehandler.h
1082 ===================================================================
1083 --- mythplugins/mythgame/mythgame/gamehandler.h (.../tags/release-0-19) (revision 10931)
1084 +++ mythplugins/mythgame/mythgame/gamehandler.h (.../branches/release-0-19-fixes)       (revision 10931)
1085 @@ -106,7 +106,7 @@
1086  
1087    protected:
1088      static GameHandler* GetHandler(RomInfo *rominfo);
1089 -    static GameHandler* GameHandler::GetHandlerByName(QString systemname);
1090 +    static GameHandler* GetHandlerByName(QString systemname);
1091  
1092      bool rebuild;
1093      int spandisks;
1094 Index: mythplugins/mythnews/mythnews/news-sites.xml
1095 ===================================================================
1096 --- mythplugins/mythnews/mythnews/news-sites.xml        (.../tags/release-0-19) (revision 10931)
1097 +++ mythplugins/mythnews/mythnews/news-sites.xml        (.../branches/release-0-19-fixes)       (revision 10931)
1098 @@ -119,7 +119,7 @@
1099  
1100      <item>
1101          <title>Slashdot</title>
1102 -        <url>http://slashdot.org/slashdot.rss</url>
1103 +        <url>http://rss.slashdot.org/Slashdot/slashdot</url>
1104          <ico>http://slashdot.org/favicon.ico</ico>
1105      </item>
1106  
1107 Index: mythtv/libs/libmythtv/dvbchannel.h
1108 ===================================================================
1109 --- mythtv/libs/libmythtv/dvbchannel.h  (.../tags/release-0-19) (revision 10931)
1110 +++ mythtv/libs/libmythtv/dvbchannel.h  (.../branches/release-0-19-fixes)       (revision 10931)
1111 @@ -60,11 +60,13 @@
1112          { return chan_opts.pmt.HasTelevisionService(); }
1113      /// Returns true iff we have a faulty DVB driver that munges PMT
1114      bool HasCRCBug(void)                const { return has_crc_bug; }
1115 +    uint GetMinSignalMonitorDelay(void) const { return sigmon_delay; }
1116  
1117      // Commands
1118      bool SwitchToInput(const QString &inputname, const QString &chan);
1119      bool SwitchToInput(int newcapchannel, bool setstarting);
1120      bool Tune(const dvb_channel_t& channel, bool force_reset=false);
1121 +    bool Retune(void);
1122  
1123      // Set/Get/Command just for SIScan/ScanWizardScanner
1124      void SetMultiplexID(int mplexid)          { currentTID = mplexid; };
1125 @@ -109,11 +111,18 @@
1126      volatile int      fd_frontend; ///< File descriptor for tuning hardware
1127      int               cardnum;     ///< DVB Card number
1128      bool              has_crc_bug; ///< true iff our driver munges PMT
1129 +    uint              tuning_delay;///< Extra delay to add for broken drivers
1130 +    uint              sigmon_delay;///< Minimum delay between FE_LOCK checks
1131      int               currentTID;  ///< Stores mplexid from database
1132  
1133      bool              first_tune;  ///< Used to force hardware reset
1134  
1135      int               nextcapchannel; ///< Signal an input change
1136 +
1137 +    /// Last tuning options sent to hardware for retuning
1138 +    DVBTuning         retune_tuning;
1139 +    /// Retuning adjustment, required so drivers don't ignore retune request
1140 +    int               retune_adj;
1141  };
1142  
1143  #endif
1144 Index: mythtv/libs/libmythtv/NuppelVideoPlayer.h
1145 ===================================================================
1146 --- mythtv/libs/libmythtv/NuppelVideoPlayer.h   (.../tags/release-0-19) (revision 10931)
1147 +++ mythtv/libs/libmythtv/NuppelVideoPlayer.h   (.../branches/release-0-19-fixes)       (revision 10931)
1148 @@ -150,7 +150,8 @@
1149      // Complicated gets
1150      long long CalcMaxFFTime(long long ff, bool setjump = true) const;
1151      long long CalcRWTime(long long rw) const;
1152 -    void      calcSliderPos(struct StatusPosInfo &posInfo);
1153 +    void      calcSliderPos(struct StatusPosInfo &posInfo,
1154 +                            bool paddedFields = false);
1155  
1156      /// Non-const gets
1157      OSD         *GetOSD(void)                 { return osd; }
1158 @@ -297,6 +298,7 @@
1159      bool DecodeFrame(struct rtframeheader *frameheader,
1160                       unsigned char *strm, unsigned char *outbuf);
1161  
1162 +    bool PrebufferEnoughFrames(void);
1163      void CheckPrebuffering(void);
1164      bool GetFrameNormal(int onlyvideo);
1165      bool GetFrameFFREW(void);
1166 @@ -309,7 +311,7 @@
1167      bool DoRewind(void);
1168  
1169      // Private seeking stuff
1170 -    void ClearAfterSeek(void);
1171 +    void ClearAfterSeek(bool clearvideobuffers = true);
1172      bool FrameIsInMap(long long frameNumber, QMap<long long, int> &breakMap);
1173      void JumpToFrame(long long frame);
1174      void JumpToNetFrame(long long net) { JumpToFrame(framesPlayed + net); }
1175 @@ -543,6 +545,7 @@
1176      QMap<long long, int>::Iterator deleteIter;
1177      QMap<long long, int>::Iterator blankIter;
1178      QMap<long long, int>::Iterator commBreakIter;
1179 +    bool       forcePositionMapSync;
1180  
1181      // Playback (output) speed control
1182      /// Lock for next_play_speed and next_normal_speed
1183 Index: mythtv/libs/libmythtv/osdlistbtntype.h
1184 ===================================================================
1185 --- mythtv/libs/libmythtv/osdlistbtntype.h      (.../tags/release-0-19) (revision 10931)
1186 +++ mythtv/libs/libmythtv/osdlistbtntype.h      (.../branches/release-0-19-fixes)       (revision 10931)
1187 @@ -1,3 +1,4 @@
1188 +// -*- Mode: c++ -*-
1189  /* ============================================================
1190   * File  : uilistbtntype.h
1191   * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
1192 @@ -22,38 +23,57 @@
1193  #ifndef OSDLISTBTNTYPE_H
1194  #define OSDLISTBTNTYPE_H
1195  
1196 -#include "osdtypes.h"
1197 -#include "ttfont.h"
1198 +#include <vector>
1199 +using namespace std;
1200 +
1201 +// Qt headers
1202  #include <qcolor.h>
1203  #include <qptrlist.h>
1204  #include <qevent.h>
1205  #include <qmutex.h>
1206 +#include <qptrvector.h>
1207 +
1208 +// MythTV headers
1209 +#include "osdtypes.h"
1210 +#include "ttfont.h"
1211  #include "generictree.h"
1212  
1213 +class OSDListBtnType;
1214  class OSDListBtnTypeItem;
1215 -class OSDListBtnType;
1216 +typedef vector<OSDListBtnType*> OSDListBtnList;
1217 +typedef vector<OSDListBtnTypeItem*> OSDListBtnItemList;
1218  
1219  class OSDGenericTree : public GenericTree
1220  {
1221    public:
1222      // This class will _not_ delete the image it's given, if any.
1223 -    OSDGenericTree(OSDGenericTree *parent, const QString &name, 
1224 -                   const QString &action = "", int check = -1, 
1225 -                   OSDTypeImage *image = NULL, QString group = "");
1226 +    OSDGenericTree(OSDGenericTree *parent,        const QString &name, 
1227 +                   const QString  &action = "",   int            check = -1, 
1228 +                   OSDTypeImage   *image  = NULL, QString        group = "") :
1229 +        GenericTree(name), m_image(image),     m_action(action),
1230 +        m_group(group),    m_checkable(check), m_parentButton(NULL)
1231 +    {
1232 +        m_group = (m_group.isEmpty()) ? action : m_group;
1233 +        setSelectable(!action.isEmpty());
1234 +        if (parent)
1235 +            parent->addNode(this);
1236 +    }
1237  
1238 -    OSDTypeImage *getImage(void) { return m_image; }
1239 -    QString getAction(void) { return m_action; }
1240 -    int getCheckable(void) { return m_checkable; }
1241 -    QString getGroup(void) { return m_group; }
1242 +    QString getAction(void)    const { return m_action;    }
1243 +    QString getGroup(void)     const { return m_group;     }
1244 +    int     getCheckable(void) const { return m_checkable; }
1245 +
1246 +    OSDTypeImage       *getImage(void)        { return m_image;        }
1247 +    OSDListBtnTypeItem *getParentButton(void) { return m_parentButton; }
1248 +
1249      void setParentButton(OSDListBtnTypeItem *button)
1250 -                         { m_parentButton = button; };
1251 -    OSDListBtnTypeItem *getParentButton(void) { return m_parentButton; };
1252 +        { m_parentButton = button; }
1253  
1254    private:
1255 -    OSDTypeImage *m_image;
1256 -    QString m_action;
1257 -    int m_checkable;
1258 -    QString m_group;
1259 +    OSDTypeImage       *m_image;
1260 +    QString             m_action;
1261 +    QString             m_group;
1262 +    int                 m_checkable;
1263      OSDListBtnTypeItem *m_parentButton;
1264  };
1265  
1266 @@ -62,53 +82,49 @@
1267  {
1268      Q_OBJECT
1269    public:
1270 -    OSDListTreeType(const QString &name, const QRect &area, 
1271 -                    const QRect &levelsize, int levelspacing,
1272 -                    float wmult, float hmult);
1273 +    OSDListTreeType(const QString &name,      const QRect &area,
1274 +                    const QRect   &levelsize, int          levelspacing,
1275 +                    float          wmult,     float        hmult);
1276 +    ~OSDListTreeType();
1277  
1278 -    void Reinit(float wchange, float hchange, float wmult, float hmult);
1279 +    bool IsVisible(void)          const { return m_visible;  }
1280
1281 +    void SetFontActive(TTFFont *font)   { m_active   = font; }
1282 +    void SetFontInactive(TTFFont *font) { m_inactive = font; }
1283 +
1284      void SetGroupCheckState(QString group, int newState = 0);
1285 +    void SetSpacing(uint spacing)
1286 +        { m_unbiasedspacing = (m_spacing = spacing) / m_wmult; }
1287 +    void SetMargin(uint margin)
1288 +        { m_unbiasedmargin  = (m_margin  = margin)  / m_wmult; }
1289 +    void SetItemRegColor(const QColor& beg, const QColor& end, uint alpha)
1290 +        { m_itemRegBeg = beg; m_itemRegEnd = end; m_itemRegAlpha = alpha; }
1291 +    void SetItemSelColor(const QColor& beg, const QColor& end, uint alpha)
1292 +        { m_itemSelBeg = beg; m_itemSelEnd = end; m_itemSelAlpha = alpha; }
1293 +    void SetVisible(bool visible) { m_visible = visible; }
1294 +    void SetAsTree(OSDGenericTree *toplevel, vector<uint> *select = NULL);
1295  
1296 -    void SetFontActive(TTFFont *font);
1297 -    void SetFontInactive(TTFFont *font);
1298 -    void SetSpacing(int spacing);
1299 -    void SetMargin(int margin);
1300 -    void SetItemRegColor(const QColor& beg, const QColor& end, uint alpha);
1301 -    void SetItemSelColor(const QColor& beg, const QColor& end, uint alpha);
1302 -
1303 -    void SetAsTree(OSDGenericTree *toplevel);
1304 -
1305 -    OSDGenericTree *GetCurrentPosition(void);
1306
1307 +    void Reinit(float wmult, float hmult);
1308      bool HandleKeypress(QKeyEvent *e);
1309 -
1310      void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
1311  
1312 -    bool IsVisible(void) { return m_visible; }
1313 -    void SetVisible(bool visible) { m_visible = visible; }
1314 -
1315    signals:
1316      void itemSelected(OSDListTreeType *parent, OSDGenericTree *item);
1317      void itemEntered(OSDListTreeType *parent, OSDGenericTree *item);
1318  
1319    private:
1320 -    void FillLevelFromTree(OSDGenericTree *item, OSDListBtnType *list);
1321 -    OSDListBtnType *GetLevel(int levelnum);
1322 -    void SetCurrentPosition(void);
1323 +    void FillLevelFromTree(OSDGenericTree *item, uint levelnum);
1324 +    OSDListBtnType *GetLevel(uint levelnum);
1325 +    void EnterItem(void);
1326 +    void SelectItem(void);
1327  
1328 -    int levels;
1329 -    int curlevel;
1330 -
1331      OSDGenericTree *treetop;
1332      OSDGenericTree *currentpos;
1333 +    TTFFont        *m_active;
1334 +    TTFFont        *m_inactive;
1335  
1336 -    QPtrList<OSDListBtnType> listLevels;
1337 +    OSDListBtnList  listLevels;
1338  
1339 -    OSDListBtnType *currentlevel;
1340 -
1341 -    TTFFont *m_active;
1342 -    TTFFont *m_inactive;
1343 -
1344      QColor    m_itemRegBeg;
1345      QColor    m_itemRegEnd;
1346      QColor    m_itemSelBeg;
1347 @@ -116,62 +132,76 @@
1348      uint      m_itemRegAlpha;
1349      uint      m_itemSelAlpha;
1350     
1351 -    int m_spacing;
1352 -    int m_margin;
1353 +    uint      m_spacing;
1354 +    uint      m_margin;
1355 +    int       m_levelspacing;
1356  
1357 -    QRect m_totalarea;
1358 -    QRect m_levelsize;
1359 -    int m_levelspacing;
1360 +    QRect     m_totalarea;
1361 +    QRect     m_levelsize;
1362  
1363 -    float m_wmult;
1364 -    float m_hmult;
1365 +    float     m_unbiasedspacing;
1366 +    float     m_unbiasedmargin;
1367 +    QRect     m_unbiasedarea;
1368 +    QRect     m_unbiasedsize;
1369  
1370 -    bool m_visible;
1371 -    bool m_arrowAccel;
1372 +    float     m_wmult;
1373 +    float     m_hmult;
1374 +
1375 +    int       m_depth;
1376 +    int       m_levelnum;
1377 +    bool      m_visible;
1378 +    bool      m_arrowAccel;
1379  };
1380   
1381  class OSDListBtnType : public OSDType
1382  {
1383 +    friend class OSDListBtnTypeItem;
1384      Q_OBJECT
1385 +
1386    public:
1387      OSDListBtnType(const QString &name, const QRect& area,
1388                     float wmult, float hmult,
1389                     bool showScrollArrows = false);
1390      ~OSDListBtnType();
1391  
1392 -    void  Reinit(float wchange, float hchange, float wmult, float hmult);
1393 +    // General Gets
1394 +    bool  IsVisible() const { return m_visible; }
1395 +
1396 +    // General Sets
1397 +    void  SetFontActive(TTFFont *font)   { m_fontActive   = font;    }
1398 +    void  SetFontInactive(TTFFont *font) { m_fontInactive = font;    }
1399 +    void  SetSpacing(int spacing)        { m_itemSpacing  = spacing; }
1400 +    void  SetMargin(int margin)          { m_itemMargin   = margin;  }
1401 +    void  SetActive(bool active)         { m_active       = active;  }
1402 +    void  SetVisible(bool vis)           { m_visible = vis; }
1403 +    void  SetItemRegColor(const QColor& beg, const QColor& end, uint alpha)
1404 +        { m_itemRegBeg = beg; m_itemRegEnd = end; m_itemRegAlpha = alpha; }
1405 +    void  SetItemSelColor(const QColor& beg, const QColor& end, uint alpha)
1406 +        { m_itemSelBeg = beg; m_itemSelEnd = end; m_itemSelAlpha = alpha; }
1407      void  SetGroupCheckState(QString group, int newState = 0);
1408 +    void  SetItemCurrent(const OSDListBtnTypeItem* item);
1409 +    void  SetItemCurrent(uint pos);
1410  
1411 -    void  SetFontActive(TTFFont *font);
1412 -    void  SetFontInactive(TTFFont *font);
1413 -    void  SetSpacing(int spacing);
1414 -    void  SetMargin(int margin);
1415 -    void  SetItemRegColor(const QColor& beg, const QColor& end, uint alpha);
1416 -    void  SetItemSelColor(const QColor& beg, const QColor& end, uint alpha);
1417 -    
1418 -    void  Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
1419 -
1420 -    void  SetActive(bool active);
1421 -    void  Reset();
1422 -
1423 -    void  SetItemCurrent(OSDListBtnTypeItem* item);
1424 -    void  SetItemCurrent(int pos);
1425 -    OSDListBtnTypeItem* GetItemCurrent();
1426 -    OSDListBtnTypeItem* GetItemFirst();
1427 -    OSDListBtnTypeItem* GetItemNext(OSDListBtnTypeItem *item);
1428 +    // Item Gets
1429 +    int   GetCount(void) const;
1430 +    int   GetItemPos(const OSDListBtnTypeItem* item) const;
1431 +    int   GetItemCurrentPos() const;
1432 +    OSDListBtnTypeItem* GetItemCurrent(void);
1433 +    OSDListBtnTypeItem* GetItemFirst(void);
1434 +    OSDListBtnTypeItem* GetItemNext(const OSDListBtnTypeItem *item);
1435      OSDListBtnTypeItem* GetItemAt(int pos);
1436 -    int   GetItemPos(OSDListBtnTypeItem* item);
1437 -    int   GetCount();
1438  
1439 -    void  MoveDown();
1440 -    void  MoveUp();
1441 +    // Item Sets/Commands
1442 +    void  MoveDown(void);
1443 +    void  MoveUp(void);
1444  
1445 -    bool  IsVisible() { return m_visible; }
1446 -    void  SetVisible(bool vis) { m_visible = vis; }
1447 +    // General Commands
1448 +    void  Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
1449 +    void  Reinit(float,float) {}
1450 +    void  Reset(void);
1451  
1452    private:
1453 -
1454 -    void  Init();
1455 +    void  Init(void);
1456      void  InitItem(OSDTypeImage &osdImg, uint width, uint height,
1457                     QColor beg, QColor end, int alpha);
1458      void  LoadPixmap(OSDTypeImage& pix, const QString& fileName);
1459 @@ -179,24 +209,35 @@
1460      void  InsertItem(OSDListBtnTypeItem *item);
1461      void  RemoveItem(OSDListBtnTypeItem *item);
1462  
1463 -    int   m_order;
1464 -    QRect m_rect;
1465 -    QRect m_contentsRect;
1466 -    QRect m_arrowsRect;
1467 +  private:
1468 +    int            m_order;
1469 +    QRect          m_rect;
1470 +    QRect          m_contentsRect;
1471 +    QRect          m_arrowsRect;
1472  
1473 -    float m_wmult;
1474 -    float m_hmult;
1475 +    float          m_wmult;
1476 +    float          m_hmult;
1477  
1478 -    int   m_itemHeight;
1479 -    int   m_itemSpacing;
1480 -    int   m_itemMargin;
1481 -    uint  m_itemsVisible;
1482 +    int            m_itemHeight;
1483 +    int            m_itemSpacing;
1484 +    int            m_itemMargin;
1485 +    uint           m_itemsVisible;
1486  
1487 -    bool  m_active;
1488 -    bool  m_showScrollArrows;
1489 -    bool  m_showUpArrow;
1490 -    bool  m_showDnArrow;
1491 +    bool           m_active;
1492 +    bool           m_showScrollArrows;
1493 +    bool           m_showUpArrow;
1494 +    bool           m_showDnArrow;
1495 +    bool           m_initialized;
1496 +    bool           m_clearing;
1497 +    bool           m_visible;
1498  
1499 +    QColor         m_itemRegBeg;
1500 +    QColor         m_itemRegEnd;
1501 +    QColor         m_itemSelBeg;
1502 +    QColor         m_itemSelEnd;
1503 +    uint           m_itemRegAlpha;
1504 +    uint           m_itemSelAlpha;
1505 +
1506      OSDTypeImage   m_itemRegPix;
1507      OSDTypeImage   m_itemSelActPix;
1508      OSDTypeImage   m_itemSelInactPix;
1509 @@ -209,43 +250,30 @@
1510      OSDTypeImage   m_checkHalfPix;
1511      OSDTypeImage   m_checkFullPix;
1512  
1513 -    QColor    m_itemRegBeg;
1514 -    QColor    m_itemRegEnd;
1515 -    QColor    m_itemSelBeg;
1516 -    QColor    m_itemSelEnd;
1517 -    uint      m_itemRegAlpha;
1518 -    uint      m_itemSelAlpha;
1519 +    TTFFont       *m_fontActive;
1520 +    TTFFont       *m_fontInactive;
1521  
1522 -    TTFFont* m_fontActive;
1523 -    TTFFont* m_fontInactive;
1524 +    int            m_topIndx;
1525 +    int            m_selIndx;
1526  
1527 -    bool      m_initialized;
1528 -    bool      m_clearing;
1529 +    OSDListBtnItemList m_itemList;
1530  
1531 -    OSDListBtnTypeItem* m_topItem;
1532 -    OSDListBtnTypeItem* m_selItem;
1533 -    QPtrList<OSDListBtnTypeItem> m_itemList;
1534 +    mutable QMutex m_update;
1535  
1536 -    QMutex    m_update;
1537 -
1538 -    bool      m_visible;
1539 -
1540 -    friend class OSDListBtnTypeItem;
1541 -    
1542    signals:
1543 -
1544      void itemSelected(OSDListBtnTypeItem* item);
1545  };
1546  
1547  class OSDListBtnTypeItem
1548  {
1549 +    friend class OSDListBtnType;
1550  
1551    public:
1552 -
1553 -    enum CheckState {
1554 -        NotChecked=0,
1555 +    enum CheckState
1556 +    {
1557 +        NotChecked  = 0,
1558          HalfChecked,
1559 -        FullChecked
1560 +        FullChecked,
1561      };
1562  
1563      OSDListBtnTypeItem(OSDListBtnType* lbtype, const QString& text,
1564 @@ -253,41 +281,36 @@
1565                         bool showArrow = false, CheckState state = NotChecked);
1566      ~OSDListBtnTypeItem();
1567  
1568 -    OSDListBtnType*   parent() const;
1569 -    QString           text() const;
1570 -    const OSDTypeImage*   pixmap() const;
1571 -    bool              checkable() const;
1572 -    CheckState        state() const;
1573 +    OSDListBtnType*     parent(void)    const { return m_parent;    }
1574 +    QString             text(void)      const { return m_text;      }
1575 +    const OSDTypeImage* pixmap(void)    const { return m_pixmap;    }
1576 +    bool                checkable(void) const { return m_checkable; }
1577 +    CheckState          state(void)     const { return m_state;     }
1578 +    QString             getGroup(void)  const { return m_group;     }
1579 +    void               *getData(void)         { return m_data;      }
1580  
1581 -    void  setChecked(CheckState state);
1582 -    void  setData(void *data);
1583 -    void* getData();
1584 -    void  setGroup(QString group) { m_group = group; };
1585 -    QString getGroup(void) { return m_group; }
1586 +    void setData(void *data)          { m_data = data; }
1587 +    void setGroup(QString grp)        { m_group = grp; }
1588 +    void setChecked(CheckState state)
1589 +        { m_state = (m_checkable) ? state : m_state; }
1590  
1591 -    void  Reinit(float wchange, float hchange, float wmult, float hmult);
1592 -    
1593 +    void  Reinit(float,float) {}
1594      void  paint(OSDSurface *surface, TTFFont *font, int fade, int maxfade, 
1595                  int x, int y);
1596      
1597    protected:
1598 -
1599      OSDListBtnType *m_parent;
1600 -    QString        m_text;
1601 -    OSDTypeImage  *m_pixmap;
1602 -    bool           m_checkable;
1603 -    CheckState     m_state;
1604 -    void          *m_data;
1605 -    QString        m_group;
1606 -
1607 -    QRect          m_checkRect;
1608 -    QRect          m_pixmapRect;
1609 -    QRect          m_textRect;
1610 -    QRect          m_arrowRect;
1611 -
1612 -    bool           m_showArrow;    
1613 -
1614 -    friend class OSDListBtnType;
1615 +    OSDTypeImage   *m_pixmap;
1616 +    void           *m_data;
1617 +    QString         m_text;
1618 +    QString         m_group;
1619 +    CheckState      m_state;
1620 +    bool            m_showArrow;
1621 +    bool            m_checkable;
1622 +    QRect           m_checkRect;
1623 +    QRect           m_arrowRect;
1624 +    QRect           m_pixmapRect;
1625 +    QRect           m_textRect;
1626  };
1627  
1628  
1629 Index: mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
1630 ===================================================================
1631 --- mythtv/libs/libmythtv/NuppelVideoPlayer.cpp (.../tags/release-0-19) (revision 10931)
1632 +++ mythtv/libs/libmythtv/NuppelVideoPlayer.cpp (.../branches/release-0-19-fixes)       (revision 10931)
1633 @@ -147,6 +147,7 @@
1634        hascommbreaktable(false),
1635        deleteIter(deleteMap.end()),  blankIter(blankMap.end()),
1636        commBreakIter(commBreakMap.end()),
1637 +      forcePositionMapSync(false),
1638        // Playback (output) speed control
1639        decoder_lock(true),
1640        next_play_speed(1.0f),        next_normal_speed(true),
1641 @@ -747,6 +748,8 @@
1642          SetDecoder(new IvtvDecoder(this, m_playbackinfo));
1643          no_audio_out = true; // no audio with ivtv.
1644          audio_bits = 16;
1645 +        audio_samplerate = 44100;
1646 +        audio_channels = 2;
1647      }
1648      else if (forceVideoOutput == kVideoOutput_IVTV)
1649      {
1650 @@ -1113,7 +1116,7 @@
1651  const unsigned char *NuppelVideoPlayer::GetScaledFrame(QSize &size)
1652  {
1653      QMutexLocker locker(&yuv_lock);
1654 -    yuv_desired_size = size = QSize(size.width() & ~0x3, size.height() & ~0x3);
1655 +    yuv_desired_size = size = QSize(size.width() & ~0x7, size.height() & ~0x7);
1656  
1657      if ((size.width() > 0) && (size.height() > 0))
1658      {
1659 @@ -1626,8 +1629,8 @@
1660          {
1661              // If we are using hardware decoding, so we've already done the
1662              // decoding; display the frame, but don't wait for A/V Sync.
1663 -            videoOutput->PrepareFrame(buffer, ps);
1664 -            videoOutput->Show(m_scan);
1665 +            videoOutput->PrepareFrame(buffer, kScan_Intr2ndField);
1666 +            videoOutput->Show(kScan_Intr2ndField);
1667              VERBOSE(VB_PLAYBACK, LOC + dbg + "skipping A/V wait.");
1668          }
1669          else
1670 @@ -1685,14 +1688,14 @@
1671  
1672      if (diverge > MAXDIVERGE)
1673      {
1674 -        // If audio is way ahead of video, adjust for it...
1675 +        // If audio is way behind of video, adjust for it...
1676          // by cutting the frame rate in half for the length of this frame
1677  
1678          avsync_adjustment = frame_interval;
1679          lastsync = true;
1680          VERBOSE(VB_PLAYBACK, LOC + 
1681 -                QString("Audio is %1 frames ahead of video,\n"
1682 -                        "\t\t\tdoubling video frame interval.").arg(diverge));
1683 +                QString("Video is %1 frames ahead of audio,\n"
1684 +                        "\t\t\tdoubling video frame interval to slow down.").arg(diverge));
1685      }
1686  
1687      if (audioOutput && normal_speed)
1688 @@ -1811,11 +1814,8 @@
1689      videosync->Start();
1690  }
1691  
1692 -void NuppelVideoPlayer::DisplayNormalFrame(void)
1693 +bool NuppelVideoPlayer::PrebufferEnoughFrames(void)
1694  {
1695 -    video_actually_paused = false;
1696 -    resetvideo = false;
1697 -
1698      prebuffering_lock.lock();
1699      if (prebuffering)
1700      {
1701 @@ -1843,14 +1843,29 @@
1702          }
1703          prebuffering_lock.unlock();
1704          videosync->Start();
1705 -        return;
1706 +
1707 +        return false;
1708      }
1709      prebuffering_lock.unlock();
1710  
1711      //VERBOSE(VB_PLAYBACK, LOC + "fs: " + videoOutput->GetFrameStatus());
1712      if (!videoOutput->EnoughPrebufferedFrames())
1713      {
1714 -        VERBOSE(VB_GENERAL, LOC + "prebuffering pause");
1715 +        if (videoOutput)
1716 +        {
1717 +            videoOutput->CheckFrameStates();
1718 +            if (videoOutput->hasMCAcceleration()   ||
1719 +                videoOutput->hasIDCTAcceleration() ||
1720 +                videoOutput->hasVLDAcceleration())
1721 +            {
1722 +                // Prebuffering fails w/XvMC's 8 surfaces..
1723 +                usleep(5000);
1724 +                return false;
1725 +            }
1726 +        }
1727 +        VERBOSE(VB_GENERAL, LOC + "prebuffering pause" +
1728 +                videoOutput->GetFrameStatus());
1729 +
1730          SetPrebuffering(true);
1731  #if FAST_RESTART
1732          if (!m_playing_slower && audio_channels <= 2)
1733 @@ -1861,7 +1876,7 @@
1734              VERBOSE(VB_GENERAL, "playing slower due to falling behind...");
1735          }
1736  #endif
1737 -        return;
1738 +        return false;
1739      }
1740  
1741  #if FAST_RESTART
1742 @@ -1877,6 +1892,25 @@
1743      prebuffer_tries = 0;
1744      prebuffering_lock.unlock();
1745  
1746 +    return true;
1747 +}
1748 +
1749 +void NuppelVideoPlayer::DisplayNormalFrame(void)
1750 +{
1751 +    video_actually_paused = false;
1752 +    resetvideo = false;
1753 +
1754 +    if (!PrebufferEnoughFrames())
1755 +    {
1756 +        // When going to switch channels
1757 +        if (paused)
1758 +        {
1759 +            usleep(frame_interval);
1760 +            DisplayPauseFrame();
1761 +        }
1762 +        return;
1763 +    }
1764 +
1765      videoOutput->StartDisplayingFrame();
1766  
1767      VideoFrame *frame = videoOutput->GetLastShownFrame();
1768 @@ -1920,7 +1954,7 @@
1769          ShowText();
1770          DisplaySubtitles();
1771      }
1772 -    else if (osdHasSubtitles || nonDisplayedSubtitles.size() > 20)
1773 +    else if (osdHasSubtitles)
1774      {
1775          ClearSubtitles();
1776      }
1777 @@ -2176,7 +2210,10 @@
1778      }
1779  
1780      if (eof)
1781 +    {
1782          discontinuity = true;
1783 +        ClearSubtitles();
1784 +    }
1785  
1786      livetvchain->SetProgram(pginfo);
1787  
1788 @@ -2199,6 +2236,7 @@
1789      }
1790      if (IsErrored())
1791      {
1792 +        VERBOSE(VB_IMPORTANT, LOC_ERR + "SwitchToProgram failed.");
1793          eof = true;
1794          return;
1795      }
1796 @@ -2265,6 +2303,8 @@
1797      ringBuffer->Pause();
1798      ringBuffer->WaitForPause();
1799  
1800 +    ClearSubtitles();
1801 +
1802      livetvchain->SetProgram(pginfo);
1803  
1804      ringBuffer->Reset(true);
1805 @@ -2284,6 +2324,7 @@
1806  
1807      if (errored || !GetDecoder())
1808      {
1809 +        VERBOSE(VB_IMPORTANT, LOC_ERR + "JumpToProgram failed.");
1810          errored = true;
1811          return;
1812      }
1813 @@ -2471,6 +2512,12 @@
1814                  JumpToProgram();
1815          }
1816  
1817 +        if (forcePositionMapSync)
1818 +        {
1819 +            forcePositionMapSync = false;
1820 +            GetDecoder()->SyncPositionMap();
1821 +        }
1822 +
1823          if (IsErrored() || (nvr_enc && nvr_enc->GetErrorStatus()))
1824          {
1825              VERBOSE(VB_IMPORTANT, LOC_ERR + "Unknown error, exiting decoder");
1826 @@ -3246,7 +3293,10 @@
1827      GetDecoder()->DoFastForward(desiredFrame);
1828      GetDecoder()->setExactSeeks(exactseeks);
1829  
1830 -    ClearAfterSeek();
1831 +    // Note: The video output will be reset by what the the decoder 
1832 +    //       does, so we only need to reset the audio, subtitles, etc.
1833 +    ClearAfterSeek(false);
1834 +
1835      lastSkipTime = time(NULL);
1836      return true;
1837  }
1838 @@ -3291,19 +3341,24 @@
1839  }
1840  #endif
1841  
1842 -/** \fn NuppelVideoPlayer::ClearAfterSeek(void)
1843 +/** \fn NuppelVideoPlayer::ClearAfterSeek(bool)
1844   *  \brief This is to support seeking...
1845   *
1846   *   This resets the output classes and discards all
1847   *   frames no longer being used by the decoder class.
1848   *
1849   *   Note: caller should not hold any locks
1850 + *
1851 + *  \param clearvideobuffers This clears the videooutput buffers as well,
1852 + *                           this is only safe if no old frames are
1853 + *                           required to continue decoding.
1854   */
1855 -void NuppelVideoPlayer::ClearAfterSeek(void)
1856 +void NuppelVideoPlayer::ClearAfterSeek(bool clearvideobuffers)
1857  {
1858 -    VERBOSE(VB_PLAYBACK, LOC + "ClearAfterSeek()");
1859 +    VERBOSE(VB_PLAYBACK, LOC + "ClearAfterSeek("<<clearvideobuffers<<")");
1860  
1861 -    videoOutput->ClearAfterSeek();
1862 +    if (clearvideobuffers)
1863 +        videoOutput->ClearAfterSeek();
1864  
1865      for (int i = 0; i < MAXTBUFFER; i++)
1866          txtbuffers[i].timecode = 0;
1867 @@ -4398,6 +4453,8 @@
1868      hascommbreaktable = !commBreakMap.isEmpty();
1869      SetCommBreakIter();
1870      commBreakMapLock.unlock();
1871 +
1872 +    forcePositionMapSync = true;
1873  }
1874  
1875  bool NuppelVideoPlayer::RebuildSeekTable(bool showPercentage, StatusCallback cb, void* cbData)
1876 @@ -4541,7 +4598,8 @@
1877      return (int)((float)(written - played) / video_frame_rate);
1878  }
1879  
1880 -void NuppelVideoPlayer::calcSliderPos(struct StatusPosInfo &posInfo)
1881 +void NuppelVideoPlayer::calcSliderPos(struct StatusPosInfo &posInfo,
1882 +                                      bool paddedFields)
1883  {
1884      posInfo.desc = "";
1885      posInfo.position = 0;
1886 @@ -4588,15 +4646,23 @@
1887      int ssecs = (playbackLen - shours * 3600 - smins * 60);
1888  
1889      QString text1, text2;
1890 -    if (shours > 0)
1891 +    if (paddedFields)
1892      {
1893 -        text1.sprintf("%d:%02d:%02d", phours, pmins, psecs);
1894 -        text2.sprintf("%d:%02d:%02d", shours, smins, ssecs);
1895 +        text1.sprintf("%02d:%02d:%02d", phours, pmins, psecs);
1896 +        text2.sprintf("%02d:%02d:%02d", shours, smins, ssecs);
1897      }
1898      else
1899      {
1900 -        text1.sprintf("%d:%02d", pmins, psecs);
1901 -        text2.sprintf("%d:%02d", smins, ssecs);
1902 +        if (shours > 0)
1903 +        {
1904 +            text1.sprintf("%d:%02d:%02d", phours, pmins, psecs);
1905 +            text2.sprintf("%d:%02d:%02d", shours, smins, ssecs);
1906 +        }
1907 +        else
1908 +        {
1909 +            text1.sprintf("%d:%02d", pmins, psecs);
1910 +            text2.sprintf("%d:%02d", smins, ssecs);
1911 +        }
1912      }
1913  
1914      posInfo.desc = QObject::tr("%1 of %2").arg(text1).arg(text2);
1915 @@ -4654,6 +4720,7 @@
1916  
1917              if (commBreakIter.key() == totalFrames)
1918              {
1919 +                VERBOSE(VB_IMPORTANT, LOC + "Skipping commercial to end of file");
1920                  eof = true;
1921              }
1922              else
1923 @@ -4721,7 +4788,7 @@
1924  
1925          QString message = "COMMFLAG_REQUEST ";
1926          message += m_playbackinfo->chanid + " " +
1927 -                   m_playbackinfo->startts.toString(Qt::ISODate);
1928 +                   m_playbackinfo->recstartts.toString(Qt::ISODate);
1929          RemoteSendMessage(message);
1930  
1931          return false;
1932 @@ -5018,7 +5085,7 @@
1933                  QImage scaledImage = qImage.smoothScale(rect->w, rect->h);
1934  
1935                  OSDTypeImage* image = new OSDTypeImage();
1936 -                image->SetPosition(QPoint(rect->x, rect->y));
1937 +                image->SetPosition(QPoint(rect->x, rect->y), hmult, vmult);
1938                  image->LoadFromQImage(scaledImage);
1939  
1940                  subtitleOSD->AddType(image);
1941 Index: mythtv/libs/libmythtv/NuppelVideoRecorder.cpp
1942 ===================================================================
1943 --- mythtv/libs/libmythtv/NuppelVideoRecorder.cpp       (.../tags/release-0-19) (revision 10931)
1944 +++ mythtv/libs/libmythtv/NuppelVideoRecorder.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
1945 @@ -216,7 +216,10 @@
1946      }
1947  
1948      if (mpa_codec)
1949 +    {
1950 +        QMutexLocker locker(&avcodeclock);
1951          avcodec_close(mpa_ctx);
1952 +    }
1953  
1954      if (mpa_ctx)
1955          av_free(mpa_ctx);
1956 @@ -453,8 +456,11 @@
1957          useavcodec = true;
1958  
1959      if (mpa_codec)
1960 +    {
1961 +        QMutexLocker locker(&avcodeclock);
1962          avcodec_close(mpa_ctx);
1963 -    
1964 +    }
1965 +
1966      if (mpa_ctx)
1967          av_free(mpa_ctx);
1968      mpa_ctx = NULL;
1969 @@ -626,13 +632,14 @@
1970      int frag, blocksize = 4096;
1971      int tmp;
1972  
1973 +    if (!skipdevice)
1974 +    {
1975  #if !defined (HAVE_SYS_SOUNDCARD_H) && !defined(HAVE_SOUNDCARD_H)
1976 -    VERBOSE(VB_IMPORTANT, QString("NVR::AudioInit() This Unix doesn't support"
1977 -                                  " device files for audio access. Skipping"));
1978 -    return 1;
1979 +        VERBOSE(VB_IMPORTANT,
1980 +                QString("NVR::AudioInit() This Unix doesn't support"
1981 +                        " device files for audio access. Skipping"));
1982 +        return 1;
1983  #else
1984 -    if (!skipdevice)
1985 -    {
1986          if (-1 == (afd = open(audiodevice.ascii(), O_RDONLY | O_NONBLOCK)))
1987          {
1988              VERBOSE(VB_IMPORTANT, QString("NVR: Error, cannot open DSP '%1'").
1989 @@ -678,8 +685,8 @@
1990          }
1991  
1992          close(afd);
1993 +#endif
1994      }
1995 -#endif
1996  
1997      audio_bytes_per_sample = audio_channels * audio_bits / 8;
1998      blocksize *= 4;
1999 Index: mythtv/libs/libmythtv/signalmonitor.cpp
2000 ===================================================================
2001 --- mythtv/libs/libmythtv/signalmonitor.cpp     (.../tags/release-0-19) (revision 10931)
2002 +++ mythtv/libs/libmythtv/signalmonitor.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
2003 @@ -100,9 +100,9 @@
2004                               uint wait_for_mask,  const char *name)
2005      : QObject(NULL, name),             channel(_channel),
2006        capturecardnum(_capturecardnum), flags(wait_for_mask),
2007 -      update_rate(25),                 running(false),
2008 -      exit(false),                     update_done(false),
2009 -      notify_frontend(true),
2010 +      update_rate(25),                 minimum_update_rate(5),
2011 +      running(false),                  exit(false),
2012 +      update_done(false),              notify_frontend(true),
2013        signalLock    (QObject::tr("Signal Lock"),  "slock",
2014                       1, true, 0,   1, 0),
2015        signalStrength(QObject::tr("Signal Power"), "signal",
2016 Index: mythtv/libs/libmythtv/osdlistbtntype.cpp
2017 ===================================================================
2018 --- mythtv/libs/libmythtv/osdlistbtntype.cpp    (.../tags/release-0-19) (revision 10931)
2019 +++ mythtv/libs/libmythtv/osdlistbtntype.cpp    (.../branches/release-0-19-fixes)       (revision 10931)
2020 @@ -19,206 +19,148 @@
2021   * 
2022   * ============================================================ */
2023  
2024 -#include <iostream>
2025 +// ANSI C headers
2026 +#include <cmath>
2027  
2028 +// C++ headers
2029 +#include <algorithm>
2030 +using namespace std;
2031 +
2032 +// Qt headers
2033  #include <qapplication.h>
2034  #include <qpixmap.h>
2035  #include <qpainter.h>
2036  #include <qimage.h>
2037  #include <qcolor.h>
2038  
2039 +// MythTV headers
2040  #include "mythcontext.h"
2041  #include "mythdialogs.h"
2042 -
2043  #include "osdlistbtntype.h"
2044  
2045 +#define LOC QString("OSDListTreeType: ")
2046 +#define LOC_ERR QString("OSDListTreeType, Error: ")
2047  
2048 -OSDGenericTree::OSDGenericTree(OSDGenericTree *parent, const QString &name, 
2049 -                               const QString &action, int check, 
2050 -                               OSDTypeImage *image, QString group)
2051 -              : GenericTree(name)
2052 +static QRect unbias(QRect rect, float wmult, float hmult)
2053  {
2054 -    m_checkable = check;
2055 -    m_action = action;
2056 -    m_image = image;
2057 -    m_parentButton = NULL;
2058 -
2059 -    if (group != "")
2060 -        m_group = group;
2061 -    else
2062 -        m_group = action;
2063 -
2064 -    if (!action.isEmpty() && !action.isNull())
2065 -        setSelectable(true);
2066 -
2067 -    if (parent)
2068 -        parent->addNode(this);
2069 +    return QRect((int)round(rect.x()      / wmult),
2070 +                 (int)round(rect.y()      / hmult),
2071 +                 (int)ceil( rect.width()  / wmult),
2072 +                 (int)ceil( rect.height() / hmult));
2073  }
2074  
2075 -////////////////////////////////////////////////////////////////////////////
2076 -
2077 -OSDListTreeType::OSDListTreeType(const QString &name, const QRect &area,
2078 -                                 const QRect &levelsize, int levelspacing,
2079 -                                 float wmult, float hmult)
2080 -               : OSDType(name)
2081 +static QRect bias(QRect rect, float wmult, float hmult)
2082  {
2083 -    m_wmult = wmult;
2084 -    m_hmult = hmult;
2085 -
2086 -    m_totalarea = area;
2087 -    m_levelsize = levelsize;
2088 -    m_levelspacing = levelspacing;
2089 -
2090 -    if (gContext->GetNumSetting("UseArrowAccels", 1))
2091 -        m_arrowAccel = true;
2092 -    else
2093 -        m_arrowAccel = false;
2094 -    
2095 -    levels = 0;
2096 -    curlevel = -1;
2097 -
2098 -    treetop = NULL;
2099 -    currentpos = NULL;
2100 -
2101 -    currentlevel = NULL;
2102 -
2103 -    listLevels.setAutoDelete(true);
2104 -
2105 -    m_active = NULL;
2106 -    m_inactive = NULL;
2107 -
2108 -    SetItemRegColor(Qt::black,QColor(80,80,80),100);
2109 -    SetItemSelColor(QColor(82,202,56),QColor(52,152,56),255);
2110 -
2111 -    m_spacing = 0;
2112 -    m_margin = 0;
2113 +    return QRect((int)round(rect.x()      * wmult),
2114 +                 (int)round(rect.y()      * hmult),
2115 +                 (int)ceil( rect.width()  * wmult),
2116 +                 (int)ceil( rect.height() * hmult));
2117  }
2118  
2119 -void OSDListTreeType::Reinit(float wchange, float hchange, float wmult,
2120 -                             float hmult)
2121 +OSDListTreeType::OSDListTreeType(
2122 +    const QString &name,      const QRect &area,
2123 +    const QRect   &levelsize, int          levelspacing,
2124 +    float          wmult,     float        hmult)
2125 +    : OSDType(name),
2126 +      treetop(NULL),                    currentpos(NULL),
2127 +      m_active(NULL),                   m_inactive(NULL),
2128 +      m_itemRegBeg(Qt::black),          m_itemRegEnd(QColor(80,80,80)),
2129 +      m_itemSelBeg(QColor(82,202,56)),  m_itemSelEnd(QColor(52,152,56)),
2130 +      m_itemRegAlpha(100),              m_itemSelAlpha(255),
2131 +      m_spacing(0),                     m_margin(0),
2132 +      m_levelspacing(levelspacing),
2133 +      m_totalarea(area),                m_levelsize(levelsize),
2134 +      m_unbiasedspacing(1.0f),          m_unbiasedmargin(1.0f),
2135 +      m_unbiasedarea(0,0,0,0),          m_unbiasedsize(0,0,0,0),
2136 +      m_wmult(wmult),                   m_hmult(hmult),
2137 +      m_depth(0),                        m_levelnum(-1),
2138 +      m_visible(true),
2139 +      m_arrowAccel(gContext->GetNumSetting("UseArrowAccels", 1))
2140  {
2141 -    m_wmult = wmult;
2142 -    m_hmult = hmult;
2143 -
2144 -    m_spacing = (int)(m_spacing * wchange);
2145 -    m_margin = (int)(m_margin * wchange);
2146 -
2147 -    int width = (int)(m_totalarea.width() * wchange);
2148 -    int height = (int)(m_totalarea.height() * hchange);
2149 -    int x = (int)(m_totalarea.x() * wchange);
2150 -    int y = (int)(m_totalarea.y() * hchange);
2151 -
2152 -    m_totalarea = QRect(x, y, width, height);
2153 -
2154 -    width = (int)(m_levelsize.width() * wchange);
2155 -    height = (int)(m_levelsize.height() * hchange);
2156 -    x = (int)(m_levelsize.x() * wchange);
2157 -    y = (int)(m_levelsize.y() * hchange);
2158 -
2159 -    m_levelsize = QRect(x, y, width, height);
2160 -
2161 -    QPtrListIterator<OSDListBtnType> it(listLevels);
2162 -    OSDListBtnType *child;
2163 -
2164 -    while ((child = it.current()) != 0)
2165 -    {
2166 -        child->Reinit(wchange, hchange, wmult, hmult);
2167 -        ++it;
2168 -    }
2169 +    m_wmult        = (wmult == 0.0f) ? 1.0f : wmult;
2170 +    m_hmult        = (hmult == 0.0f) ? 1.0f : hmult;
2171 +    m_unbiasedarea = unbias(area,      wmult, hmult);
2172 +    m_unbiasedsize = unbias(levelsize, wmult, hmult);
2173  }
2174  
2175 -void OSDListTreeType::SetGroupCheckState(QString group, int newState)
2176 +OSDListTreeType::~OSDListTreeType()
2177  {
2178 -    QPtrListIterator<OSDListBtnType> it(listLevels);
2179 -    OSDListBtnType *child;
2180 -    while ((child = it.current()) != 0)
2181 -    {
2182 -        child->SetGroupCheckState(group, newState);
2183 -        ++it;
2184 -    }
2185 +    OSDListBtnList::iterator it = listLevels.begin();
2186 +    for (; it != listLevels.end(); ++it)
2187 +        delete *it;    
2188  }
2189  
2190 -void OSDListTreeType::SetItemRegColor(const QColor& beg, const QColor& end,
2191 -                                      uint alpha)
2192 +void OSDListTreeType::Reinit(float wmult, float hmult)
2193  {
2194 -    m_itemRegBeg   = beg;
2195 -    m_itemRegEnd   = end;
2196 -    m_itemRegAlpha = alpha;
2197 -}
2198 +    m_wmult     = (wmult == 0.0f) ? 1.0f : wmult;
2199 +    m_hmult     = (hmult == 0.0f) ? 1.0f : hmult;
2200 +    m_spacing   = (uint) round(m_unbiasedspacing * wmult);
2201 +    m_margin    = (uint) round(m_unbiasedmargin  * wmult);
2202 +    m_totalarea = bias(m_unbiasedarea, wmult, hmult);
2203 +    m_levelsize = bias(m_unbiasedsize, wmult, hmult);
2204  
2205 -void OSDListTreeType::SetItemSelColor(const QColor& beg, const QColor& end,
2206 -                                      uint alpha)
2207 -{
2208 -    m_itemSelBeg   = beg;
2209 -    m_itemSelEnd   = end;
2210 -    m_itemSelAlpha = alpha;
2211 -}
2212 +    if (!treetop || m_levelnum < 0)
2213 +        return;
2214  
2215 -void OSDListTreeType::SetFontActive(TTFFont *font)
2216 -{
2217 -    m_active = font;
2218 -}
2219 +    // Save item indices
2220 +    vector<uint> list;
2221 +    for (uint i = 0; i <= (uint)m_levelnum; i++)
2222 +        list.push_back(listLevels[i]->GetItemCurrentPos());
2223  
2224 -void OSDListTreeType::SetFontInactive(TTFFont *font)
2225 -{
2226 -    m_inactive = font;
2227 -}
2228 +    // Delete old OSD items
2229 +    OSDListBtnList clone = listLevels;
2230 +    listLevels.clear();
2231 +    OSDListBtnList::iterator it = clone.begin();
2232 +    for (; it != clone.end(); ++it)
2233 +        delete *it;
2234  
2235 -void OSDListTreeType::SetSpacing(int spacing)
2236 -{
2237 -    m_spacing = spacing;
2238 +    // Create new OSD items
2239 +    SetAsTree(treetop, &list);
2240  }
2241  
2242 -void OSDListTreeType::SetMargin(int margin)
2243 +void OSDListTreeType::SetGroupCheckState(QString group, int newState)
2244  {
2245 -    m_margin = margin;
2246 +    OSDListBtnList::iterator it = listLevels.begin();
2247 +    for (; it != listLevels.end(); ++it)
2248 +        (*it)->SetGroupCheckState(group, newState);
2249  }
2250  
2251 -void OSDListTreeType::SetAsTree(OSDGenericTree *toplevel)
2252 +void OSDListTreeType::SetAsTree(OSDGenericTree *toplevel,
2253 +                                vector<uint> *select_list)
2254  {
2255      if (treetop)
2256      {
2257          listLevels.clear();
2258 -        currentlevel = NULL;
2259 -        treetop = NULL;
2260 -        currentpos = NULL;
2261 -        levels = 0;
2262 -        curlevel = -1;
2263 +        treetop      = NULL;
2264 +        currentpos   = NULL;
2265 +        m_depth      = 0;
2266 +        m_levelnum   = -1;
2267      }
2268  
2269 -    levels = toplevel->calculateDepth(0) - 1;
2270 -
2271 -    if (levels <= 0)
2272 +    m_depth = toplevel->calculateDepth(0) - 1;
2273 +    if (m_depth <= 0)
2274      {
2275 -        cerr << "Need at least one level\n";
2276 +        VERBOSE(VB_IMPORTANT, LOC_ERR + "SetAsTree: Need at least one level");
2277          return;
2278      }
2279  
2280 -    currentpos = (OSDGenericTree *)toplevel->getChildAt(0);
2281 -
2282 +    currentpos = (OSDGenericTree*) toplevel->getChildAt(0);
2283      if (!currentpos)
2284      {
2285 -        cerr << "No top-level children?\n";
2286 +        VERBOSE(VB_IMPORTANT, LOC_ERR + "SetAsTree: Need top-level children");
2287          return;
2288      }
2289  
2290 -    treetop = toplevel;
2291 -
2292 -    // just for now, remove later
2293 -    if (levels > 2)
2294 -        levels = 3;
2295 -
2296 -    for (int i = 0; i < levels; i++)
2297 +    // Create OSD buttons for all levels
2298 +    for (uint i = 0; i < (uint)m_depth; i++)
2299      {
2300          QString levelname = QString("level%1").arg(i + 1);
2301 -
2302          QRect curlevelarea = m_levelsize;
2303          curlevelarea.moveBy(m_totalarea.x(), m_totalarea.y());
2304 -
2305          curlevelarea.moveBy((m_levelsize.width() + m_levelspacing) * i, 0);
2306  
2307 -        OSDListBtnType *newlevel = new OSDListBtnType(levelname, curlevelarea,
2308 -                                                      m_wmult, m_hmult, true);
2309 +        OSDListBtnType *newlevel = new OSDListBtnType(
2310 +            levelname, curlevelarea, m_wmult, m_hmult, true);
2311  
2312          newlevel->SetFontActive(m_active);
2313          newlevel->SetFontInactive(m_inactive);
2314 @@ -227,229 +169,200 @@
2315          newlevel->SetSpacing(m_spacing);
2316          newlevel->SetMargin(m_margin);
2317  
2318 -        listLevels.append(newlevel);
2319 +        listLevels.push_back(newlevel);
2320      }
2321  
2322 -    currentlevel = GetLevel(0);
2323 +    // Set up needed levels and selects
2324 +    vector<uint> slist;
2325 +    slist.push_back(0);
2326 +    if (select_list)
2327 +        slist = *select_list;
2328  
2329 -    if (!currentlevel)
2330 +    currentpos = treetop = toplevel;
2331 +    for (m_levelnum = 0; m_levelnum < (int)slist.size(); m_levelnum++)
2332      {
2333 -        cerr << "Something is seriously wrong (currentlevel = NULL)\n";
2334 -        return;
2335 +        FillLevelFromTree(currentpos, m_levelnum);
2336 +        GetLevel(m_levelnum)->SetActive(true);
2337 +        GetLevel(m_levelnum)->SetVisible(true);
2338 +        if (slist[m_levelnum])
2339 +            GetLevel(m_levelnum)->SetItemCurrent(slist[m_levelnum]);
2340 +        EnterItem(); // updates currentpos
2341      }
2342 -
2343 -    FillLevelFromTree(toplevel, currentlevel);
2344 -
2345 -    currentlevel->SetVisible(true);
2346 -    currentlevel->SetActive(true);
2347 -
2348 -    currentpos = (OSDGenericTree *)(currentlevel->GetItemFirst()->getData());
2349 -    curlevel = 0;
2350 -
2351 -    emit itemEntered(this, currentpos);
2352 +    m_levelnum--;
2353  }
2354  
2355 -OSDGenericTree *OSDListTreeType::GetCurrentPosition(void)
2356 +static bool has_action(QString action, const QStringList &actions)
2357  {
2358 -    return currentpos;
2359 +    QStringList::const_iterator it;
2360 +    for (it = actions.begin(); it != actions.end(); ++it)
2361 +    {
2362 +        if (action == *it)
2363 +            return true;
2364 +    }
2365 +    return false;
2366  }
2367  
2368  bool OSDListTreeType::HandleKeypress(QKeyEvent *e)
2369  {
2370 -    if (!currentlevel)
2371 +    QStringList actions;
2372 +    bool ok = gContext->GetMainWindow()->TranslateKeyPress(
2373 +        "TV Playback", e, actions);
2374 +
2375 +    if (!ok || ((uint)m_levelnum >= listLevels.size()))
2376          return false;
2377 +    else if (has_action("UP", actions))
2378 +    {
2379 +        GetLevel(m_levelnum)->MoveUp();
2380 +        EnterItem();
2381 +    }
2382 +    else if (has_action("DOWN", actions))
2383 +    {
2384 +        GetLevel(m_levelnum)->MoveDown();
2385 +        EnterItem();
2386 +    }
2387 +    else if (has_action("LEFT", actions) && (m_levelnum > 0))
2388 +    {
2389 +        GetLevel(m_levelnum)->Reset();
2390 +        GetLevel(m_levelnum)->SetVisible(false);
2391  
2392 -    bool handled = false;
2393 -    QStringList actions;
2394 -    if (gContext->GetMainWindow()->TranslateKeyPress("TV Playback", e, 
2395 -                                                     actions))
2396 +        m_levelnum--;
2397 +        EnterItem();
2398 +    }
2399 +    else if ((has_action("LEFT", actions) && m_arrowAccel) ||
2400 +             has_action("ESCAPE",   actions) ||
2401 +             has_action("CLEAROSD", actions) ||
2402 +             has_action("MENU",     actions))
2403      {
2404 -        for (unsigned int i = 0; i < actions.size() && !handled; i++)
2405 -        {
2406 -            QString action = actions[i];
2407 -            handled = true;
2408 +        m_visible = false;
2409 +    }
2410 +    else if (has_action("RIGHT", actions) &&
2411 +             (m_levelnum + 1 < m_depth) &&
2412 +             (currentpos->childCount() > 0))
2413 +    {
2414 +        GetLevel(m_levelnum)->SetActive(false);
2415 +        m_levelnum++;
2416  
2417 -            if (action == "UP")
2418 -            {
2419 -                currentlevel->MoveUp();
2420 -                SetCurrentPosition();
2421 -            }
2422 -            else if (action == "DOWN")
2423 -            {
2424 -                currentlevel->MoveDown();
2425 -                SetCurrentPosition();
2426 -            }
2427 -            else if (action == "LEFT")
2428 -            {
2429 -                if (curlevel > 0)
2430 -                {
2431 -                    currentlevel->Reset();
2432 -                    currentlevel->SetVisible(false);
2433 -
2434 -                    curlevel--;
2435 -
2436 -                    currentlevel = GetLevel(curlevel);
2437 -                    currentlevel->SetActive(true);
2438 -                    SetCurrentPosition();
2439 -                }
2440 -                else if (m_arrowAccel)
2441 -                {
2442 -                    m_visible = false;
2443 -                }
2444 -            }
2445 -            else if (action == "RIGHT")
2446 -            {
2447 -                // FIXME: create new levels if needed..
2448 -                if (curlevel + 1 < levels && currentpos->childCount() > 0)
2449 -                {
2450 -                    currentlevel->SetActive(false);
2451 -
2452 -                    curlevel++;
2453 -
2454 -                    currentlevel = GetLevel(curlevel);
2455 -
2456 -                    FillLevelFromTree(currentpos, currentlevel);
2457 -
2458 -                    currentlevel->SetVisible(true);
2459 -                    currentlevel->SetActive(true);
2460 -                    SetCurrentPosition();
2461 -                }
2462 -                else if (m_arrowAccel)
2463 -                {
2464 -                    SetGroupCheckState(currentpos->getGroup(),
2465 -                                       OSDListBtnTypeItem::NotChecked);
2466 -                    currentpos->getParentButton()->setChecked(
2467 -                                       OSDListBtnTypeItem::FullChecked);
2468 -                    emit itemSelected(this, currentpos);
2469 -                }
2470 -            }
2471 -            else if (action == "ESCAPE" || action == "MENU" ||
2472 -                     action == "CLEAROSD")
2473 -                m_visible = false;
2474 -            else if (action == "SELECT")
2475 -            {
2476 -                SetGroupCheckState(currentpos->getGroup(),
2477 -                                   OSDListBtnTypeItem::NotChecked);
2478 -                currentpos->getParentButton()->setChecked(
2479 -                                   OSDListBtnTypeItem::FullChecked);
2480 -                emit itemSelected(this, currentpos);
2481 -            }
2482 -            else
2483 -                handled = false;
2484 -        }
2485 +        FillLevelFromTree(currentpos, m_levelnum);
2486 +        GetLevel(m_levelnum)->SetVisible(true);
2487 +        EnterItem();
2488      }
2489 +    else if ((has_action("RIGHT", actions) && m_arrowAccel) ||
2490 +             has_action("SELECT", actions))
2491 +    {
2492 +        SelectItem();
2493 +    }
2494 +    else
2495 +    {
2496 +        return false;
2497 +    }
2498  
2499 -    return handled;
2500 +    return true;
2501  }
2502  
2503  void OSDListTreeType::Draw(OSDSurface *surface, int fade, int maxfade, 
2504                             int xoff, int yoff)
2505  {
2506 -    QPtrListIterator<OSDListBtnType> it(listLevels);
2507 -    OSDListBtnType *child;
2508 -
2509 -    while ((child = it.current()) != 0)
2510 -    {
2511 -        child->Draw(surface, fade, maxfade, xoff, yoff);
2512 -        ++it;
2513 -    }
2514 +    OSDListBtnList::iterator it = listLevels.begin();
2515 +    for (; it != listLevels.end(); ++it)
2516 +        (*it)->Draw(surface, fade, maxfade, xoff, yoff);
2517  }
2518  
2519  void OSDListTreeType::FillLevelFromTree(OSDGenericTree *item, 
2520 -                                        OSDListBtnType *list)
2521 +                                        uint level_num)
2522  {
2523 +    OSDListBtnType *list = GetLevel(level_num);
2524      if (!list)
2525      {
2526 -        VERBOSE(VB_IMPORTANT, "OSDListTreeType::FillLevelFromTree() "
2527 -                "called with no list. Ignoring call.");
2528 +        VERBOSE(VB_IMPORTANT, LOC_ERR + "FillLevelFromTree() "
2529 +                "called with no list, ignoring.");
2530          return;
2531      }
2532      list->Reset();
2533  
2534      QPtrList<GenericTree> *itemlist = item->getAllChildren();
2535 -
2536      QPtrListIterator<GenericTree> it(*itemlist);
2537 -    GenericTree *child;
2538  
2539 -    while ((child = it.current()) != 0)
2540 +    OSDGenericTree     *child   = (OSDGenericTree*) it.current();
2541 +    OSDListBtnTypeItem *newitem = NULL;
2542 +    for (;(child = (OSDGenericTree*) it.current()); ++it)
2543      {
2544 -        OSDGenericTree *osdchild = (OSDGenericTree *)child;
2545 +        OSDTypeImage *im = child->getImage();
2546 +        QString label    = child->getString();
2547 +        QString group    = child->getGroup();
2548 +        bool    canCheck = child->getCheckable() >= 0;
2549 +        bool    hasCheck = child->getCheckable() == 1;
2550 +        bool    hasChild = child->childCount()   >  0;
2551  
2552 -        OSDListBtnTypeItem *newitem;
2553 -        newitem = new OSDListBtnTypeItem(list, child->getString(),
2554 -                                         osdchild->getImage(), 
2555 -                                         (osdchild->getCheckable() >= 0),
2556 -                                         (child->childCount() > 0));
2557 -        if (osdchild->getCheckable() == 1)
2558 +        newitem = new OSDListBtnTypeItem(list, label, im, canCheck, hasChild);
2559 +
2560 +        if (hasCheck)
2561              newitem->setChecked(OSDListBtnTypeItem::FullChecked);
2562 -        newitem->setGroup(osdchild->getGroup());
2563 -        newitem->setData(osdchild);
2564 -        osdchild->setParentButton(newitem);
2565 +        newitem->setGroup(group);
2566 +        newitem->setData(child);
2567  
2568 -        ++it;
2569 +        child->setParentButton(newitem);
2570      }
2571  }
2572  
2573 -OSDListBtnType *OSDListTreeType::GetLevel(int levelnum)
2574 +OSDListBtnType *OSDListTreeType::GetLevel(uint levelnum)
2575  {
2576 -    if ((uint)levelnum > listLevels.count())
2577 -    {
2578 -        cerr << "OOB GetLevel call\n";
2579 -        return NULL;
2580 -    }
2581 +    if (levelnum < listLevels.size())
2582 +        return listLevels[levelnum];
2583  
2584 -    return listLevels.at(levelnum);
2585 +    VERBOSE(VB_IMPORTANT, LOC_ERR + "GetLevel("<<levelnum<<") "
2586 +            "listLevels.size() is only "<<listLevels.size());
2587 +    return NULL;
2588  }
2589  
2590 -void OSDListTreeType::SetCurrentPosition(void)
2591 +void OSDListTreeType::EnterItem(void)
2592  {
2593 -    if (!currentlevel)
2594 +    if ((uint)m_levelnum >= listLevels.size())
2595          return;
2596  
2597 -    OSDListBtnTypeItem *lbt = currentlevel->GetItemCurrent();
2598 +    listLevels[m_levelnum]->SetActive(true);
2599 +    OSDListBtnTypeItem *lbt = listLevels[m_levelnum]->GetItemCurrent();
2600 +    if (lbt)
2601 +    {
2602 +        currentpos = (OSDGenericTree*) (lbt->getData());
2603 +        emit itemEntered(this, currentpos);
2604 +    }
2605 +}
2606  
2607 -    if (!lbt)
2608 +void OSDListTreeType::SelectItem(void)
2609 +{
2610 +    if (!currentpos)
2611          return;
2612  
2613 -    currentpos = (OSDGenericTree *)(lbt->getData());
2614 -    emit itemEntered(this, currentpos);
2615 +    SetGroupCheckState(currentpos->getGroup(), OSDListBtnTypeItem::NotChecked);
2616 +    currentpos->getParentButton()->setChecked(OSDListBtnTypeItem::FullChecked);
2617 +    emit itemSelected(this, currentpos);
2618  }
2619
2620 +
2621 +#undef LOC_ERR
2622 +#undef LOC
2623 +
2624  //////////////////////////////////////////////////////////////////////////
2625  
2626  OSDListBtnType::OSDListBtnType(const QString &name, const QRect &area,
2627                                 float wmult, float hmult,
2628                                 bool showScrollArrows)
2629 -              : OSDType(name)
2630 +    : OSDType(name),
2631 +      m_order(0),                       m_rect(area),
2632 +      m_contentsRect(0,0,0,0),          m_arrowsRect(0,0,0,0),
2633 +      m_wmult(wmult),                   m_hmult(hmult),
2634 +      m_itemHeight(0),                  m_itemSpacing(0),
2635 +      m_itemMargin(0),                  m_itemsVisible(0),
2636 +      m_active(false),                  m_showScrollArrows(showScrollArrows),
2637 +      m_showUpArrow(false),             m_showDnArrow(false),
2638 +      m_initialized(false),             m_clearing(false),
2639 +      m_visible(false),
2640 +      m_itemRegBeg(Qt::black),          m_itemRegEnd(QColor(80,80,80)),
2641 +      m_itemSelBeg(QColor(82,202,56)),  m_itemSelEnd(QColor(52,152,56)),
2642 +      m_itemRegAlpha(100),              m_itemSelAlpha(255),
2643 +      m_fontActive(NULL),               m_fontInactive(NULL),
2644 +      m_topIndx(0),                     m_selIndx(0),
2645 +      m_update(true)
2646  {
2647 -    m_rect             = area;
2648 -
2649 -    m_wmult            = wmult;
2650 -    m_hmult            = hmult;
2651 -
2652 -    m_showScrollArrows = showScrollArrows;
2653 -
2654 -    m_active           = false;
2655 -    m_showUpArrow      = false;
2656 -    m_showDnArrow      = false;
2657 -
2658 -    m_itemList.setAutoDelete(false);
2659 -    m_topItem = 0;
2660 -    m_selItem = 0;
2661 -
2662 -    m_initialized     = false;
2663 -    m_clearing        = false;
2664 -    m_itemSpacing     = 0;
2665 -    m_itemMargin      = 0;
2666 -    m_itemHeight      = 0;
2667 -    m_itemsVisible    = 0;
2668 -    m_fontActive      = 0;
2669 -    m_fontInactive    = 0;
2670 -
2671 -    SetItemRegColor(Qt::black,QColor(80,80,80),100);
2672 -    SetItemSelColor(QColor(82,202,56),QColor(52,152,56),255);
2673 -
2674 -    m_visible = false;
2675  }
2676  
2677  OSDListBtnType::~OSDListBtnType()
2678 @@ -457,316 +370,198 @@
2679      Reset();
2680  }
2681  
2682 -void OSDListBtnType::Reinit(float wchange, float hchange, float wmult,
2683 -                            float hmult)
2684 -{
2685 -    m_wmult = wmult;
2686 -    m_hmult = hmult;
2687 -
2688 -    m_itemHeight = (int)(m_itemHeight * hchange);
2689 -    m_itemSpacing = (int)(m_itemSpacing * wchange);
2690 -    m_itemMargin = (int)(m_itemMargin * wchange);
2691 -
2692 -    int width = (int)(m_rect.width() * wchange);
2693 -    int height = (int)(m_rect.height() * hchange);
2694 -    int x = (int)(m_rect.x() * wchange);
2695 -    int y = (int)(m_rect.y() * hchange);
2696 -
2697 -    m_rect = QRect(x, y, width, height);
2698 -
2699 -    Init();
2700 -
2701 -    OSDListBtnTypeItem* item = 0;
2702 -    for (item = m_itemList.first(); item; item = m_itemList.next()) {
2703 -        item->Reinit(wchange, hchange, wmult, hmult);
2704 -    }
2705 -
2706 -}
2707 -
2708  void OSDListBtnType::SetGroupCheckState(QString group, int newState)
2709  {
2710 -    OSDListBtnTypeItem* item = 0;
2711 -    for (item = m_itemList.first(); item; item = m_itemList.next()) {
2712 -        if (item->getGroup() == group)
2713 -            item->setChecked((OSDListBtnTypeItem::CheckState)newState);
2714 -    }
2715 +    OSDListBtnItemList::iterator it;
2716 +    for (it = m_itemList.begin(); it != m_itemList.end(); ++it)
2717 +        if ((*it)->getGroup() == group)
2718 +            (*it)->setChecked((OSDListBtnTypeItem::CheckState) newState);
2719  }
2720  
2721 -void OSDListBtnType::SetItemRegColor(const QColor& beg, const QColor& end, 
2722 -                                     uint alpha)
2723 +void OSDListBtnType::Reset(void)
2724  {
2725 -    m_itemRegBeg   = beg;
2726 -    m_itemRegEnd   = end;
2727 -    m_itemRegAlpha = alpha;
2728 -}
2729 -
2730 -void OSDListBtnType::SetItemSelColor(const QColor& beg, const QColor& end,
2731 -                                     uint alpha)
2732 -{
2733 -    m_itemSelBeg   = beg;
2734 -    m_itemSelEnd   = end;
2735 -    m_itemSelAlpha = alpha;
2736 -}
2737 -
2738 -void OSDListBtnType::SetFontActive(TTFFont *font)
2739 -{
2740 -    m_fontActive   = font;
2741 -}
2742 -
2743 -void OSDListBtnType::SetFontInactive(TTFFont *font)
2744 -{
2745 -    m_fontInactive = font;
2746 -}
2747 -
2748 -void OSDListBtnType::SetSpacing(int spacing)
2749 -{
2750 -    m_itemSpacing = spacing;    
2751 -}
2752 -
2753 -void OSDListBtnType::SetMargin(int margin)
2754 -{
2755 -    m_itemMargin = margin;    
2756 -}
2757 -
2758 -void OSDListBtnType::SetActive(bool active)
2759 -{
2760 -    m_active = active;
2761 -}
2762 -
2763 -void OSDListBtnType::Reset()
2764 -{
2765      QMutexLocker lock(&m_update);
2766  
2767      m_clearing = true;
2768 -
2769 -    OSDListBtnTypeItem* item = 0;
2770 -    for (item = m_itemList.first(); item; item = m_itemList.next()) {
2771 -        delete item;
2772 -    }
2773 -
2774 -    m_clearing = false;
2775 +    OSDListBtnItemList::iterator it;
2776 +    OSDListBtnItemList clone = m_itemList;
2777      m_itemList.clear();
2778 -    
2779 -    m_topItem     = 0;
2780 -    m_selItem     = 0;
2781 +    for (it = clone.begin(); it != clone.end(); ++it)
2782 +        delete (*it);
2783 +    m_clearing = false;
2784 +
2785 +    m_topIndx     = 0;
2786 +    m_selIndx     = 0;
2787      m_showUpArrow = false;
2788      m_showDnArrow = false;
2789  }
2790  
2791  void OSDListBtnType::InsertItem(OSDListBtnTypeItem *item)
2792  {
2793 -    OSDListBtnTypeItem* lastItem = m_itemList.last();
2794 -    m_itemList.append(item);
2795 -
2796 -    if (m_showScrollArrows && m_itemList.count() > m_itemsVisible)
2797 -        m_showDnArrow = true;
2798 -    else
2799 -        m_showDnArrow = false;
2800 -
2801 -    if (!lastItem) 
2802 -    {
2803 -        m_topItem = item;
2804 -        m_selItem = item;
2805 +    QMutexLocker lock(&m_update);
2806 +    m_itemList.push_back(item);
2807 +    m_showDnArrow = m_showScrollArrows && m_itemList.size() > m_itemsVisible;
2808 +    if (m_itemList.size() == 1)
2809          emit itemSelected(item);
2810 -    }
2811  }
2812  
2813 +int find(const OSDListBtnItemList &list, const OSDListBtnTypeItem *item)
2814 +{
2815 +    for (uint i = 0; i < list.size(); i++)
2816 +        if (list[i] == item)
2817 +            return i;
2818 +    return -1;
2819 +}
2820 +
2821  void OSDListBtnType::RemoveItem(OSDListBtnTypeItem *item)
2822  {
2823 +    QMutexLocker lock(&m_update);
2824      if (m_clearing)
2825          return;
2826 -    
2827 -    if (m_itemList.find(item) == -1)
2828 +
2829 +    int i = find(m_itemList, item);
2830 +    if (i < 0)
2831          return;
2832  
2833 -    m_topItem = m_itemList.first();
2834 -    m_selItem = m_itemList.first();
2835 +    m_itemList.erase(m_itemList.begin()+i);
2836  
2837 -    m_itemList.remove(item);
2838 -
2839      m_showUpArrow = false;
2840 -    
2841 -    if (m_showScrollArrows && m_itemList.count() > m_itemsVisible)
2842 -        m_showDnArrow = true;
2843 -    else
2844 -        m_showDnArrow = false;
2845 +    m_showDnArrow = m_itemList.size() > m_itemsVisible;
2846 +    m_selIndx     = 0;
2847 +    m_topIndx     = 0;
2848  
2849 -    if (m_selItem) {
2850 -        emit itemSelected(m_selItem);
2851 -    }
2852 +    if (m_itemList.size())
2853 +        emit itemSelected(m_itemList[m_selIndx]);
2854  }
2855  
2856 -void OSDListBtnType::SetItemCurrent(OSDListBtnTypeItem* item)
2857 +void OSDListBtnType::SetItemCurrent(const OSDListBtnTypeItem* item)
2858  {
2859 -    bool locked = m_update.tryLock();
2860 +    QMutexLocker lock(&m_update);
2861 +    int i = find(m_itemList, item);
2862 +    if (i >= 0)
2863 +        SetItemCurrent(i);
2864 +}
2865  
2866 -    if (m_itemList.find(item) == -1)
2867 +void OSDListBtnType::SetItemCurrent(uint current)
2868 +{
2869 +    QMutexLocker lock(&m_update);
2870 +    if (current >= m_itemList.size())
2871          return;
2872  
2873 -    m_topItem = item;
2874 -    m_selItem = item;
2875 -
2876 -    if (m_showScrollArrows && m_itemList.count() > m_itemsVisible)
2877 -        m_showDnArrow = true;
2878 -    else
2879 -        m_showDnArrow = false;
2880 -
2881 -    emit itemSelected(m_selItem);
2882 -
2883 -    if (locked)
2884 -        m_update.unlock();
2885 +    m_selIndx     = current;
2886 +    m_topIndx     = max(m_selIndx - (int)m_itemsVisible, 0);
2887 +    m_showUpArrow = m_topIndx;
2888 +    m_showDnArrow = m_topIndx + m_itemsVisible < m_itemList.size();
2889 +    emit itemSelected(m_itemList[m_selIndx]);
2890  }
2891  
2892 -void OSDListBtnType::SetItemCurrent(int current)
2893 +int OSDListBtnType::GetItemCurrentPos(void) const
2894  {
2895      QMutexLocker lock(&m_update);
2896 -
2897 -    OSDListBtnTypeItem* item = m_itemList.at(current);
2898 -    if (!item)
2899 -        item = m_itemList.first();
2900 -
2901 -    SetItemCurrent(item);
2902 +    return (m_itemList.size()) ? m_selIndx : -1;
2903  }
2904  
2905 -OSDListBtnTypeItem* OSDListBtnType::GetItemCurrent()
2906 +OSDListBtnTypeItem* OSDListBtnType::GetItemCurrent(void)
2907  {
2908 -    return m_selItem;
2909 +    QMutexLocker lock(&m_update);
2910 +    if (!m_itemList.size())
2911 +        return NULL;
2912 +    return m_itemList[m_selIndx];
2913  }
2914  
2915 -OSDListBtnTypeItem* OSDListBtnType::GetItemFirst()
2916 +OSDListBtnTypeItem* OSDListBtnType::GetItemFirst(void)
2917  {
2918 -    return m_itemList.first();    
2919 +    QMutexLocker lock(&m_update);
2920 +    if (!m_itemList.size())
2921 +        return NULL;
2922 +    return m_itemList[0];    
2923  }
2924  
2925 -OSDListBtnTypeItem* OSDListBtnType::GetItemNext(OSDListBtnTypeItem *item)
2926 +OSDListBtnTypeItem* OSDListBtnType::GetItemNext(const OSDListBtnTypeItem *item)
2927  {
2928      QMutexLocker lock(&m_update);
2929 -
2930 -    if (m_itemList.find(item) == -1)
2931 -        return 0;
2932 -
2933 -    return m_itemList.next();
2934 +    int i = find(m_itemList, item) + 1;
2935 +    if (i <= 0 || i >= (int)m_itemList.size())
2936 +        return NULL;
2937 +    return m_itemList[i];
2938  }
2939  
2940 -int OSDListBtnType::GetCount()
2941 +int OSDListBtnType::GetCount(void) const
2942  {
2943 -    return m_itemList.count();
2944 +    QMutexLocker lock(&m_update);
2945 +    return m_itemList.size();
2946  }
2947  
2948  OSDListBtnTypeItem* OSDListBtnType::GetItemAt(int pos)
2949  {
2950 -    return m_itemList.at(pos);    
2951 +    QMutexLocker lock(&m_update);
2952 +    return m_itemList[pos];    
2953  }
2954  
2955 -int OSDListBtnType::GetItemPos(OSDListBtnTypeItem* item)
2956 +int OSDListBtnType::GetItemPos(const OSDListBtnTypeItem *item) const
2957  {
2958      QMutexLocker lock(&m_update);
2959 -
2960 -    return m_itemList.find(item);    
2961 +    return find(m_itemList, item);
2962  }
2963  
2964 -void OSDListBtnType::MoveUp()
2965 +void OSDListBtnType::MoveUp(void)
2966  {
2967      QMutexLocker lock(&m_update);
2968 -
2969 -    if (m_itemList.find(m_selItem) == -1)
2970 +    if (!m_itemList.size())
2971          return;
2972  
2973 -    OSDListBtnTypeItem *item = m_itemList.prev();
2974 -    if (!item)
2975 +    if (--m_selIndx < 0)
2976      {
2977 -        item = m_itemList.last();
2978 -        if (!item)
2979 -            return;
2980 -
2981 -        if (m_itemList.count() > m_itemsVisible)
2982 -            m_topItem = m_itemList.at(m_itemList.count() - m_itemsVisible);
2983 -        else
2984 -            m_topItem = m_itemList.first();
2985 +        m_selIndx = m_itemList.size() - 1;
2986 +        m_topIndx = (m_itemList.size() > m_itemsVisible) ?
2987 +            m_itemList.size() - m_itemsVisible : 0;
2988      }
2989  
2990 -    m_selItem = item;
2991 +    m_topIndx     = (m_selIndx < m_topIndx) ? m_selIndx : m_topIndx;
2992 +    m_showUpArrow = m_topIndx;
2993 +    m_showDnArrow = m_topIndx + m_itemsVisible < m_itemList.size();
2994  
2995 -    if (m_itemList.find(m_selItem) < m_itemList.find(m_topItem))
2996 -        m_topItem = m_selItem;
2997 -
2998 -    if (m_topItem != m_itemList.first())
2999 -        m_showUpArrow = true;
3000 -    else
3001 -        m_showUpArrow = false;
3002 -
3003 -    if (m_itemList.find(m_topItem) + m_itemsVisible < m_itemList.count())
3004 -        m_showDnArrow = true;
3005 -    else
3006 -        m_showDnArrow = false;
3007 -
3008 -    emit itemSelected(m_selItem);
3009 +    emit itemSelected(m_itemList[m_selIndx]);
3010  }
3011  
3012 -void OSDListBtnType::MoveDown()
3013 +void OSDListBtnType::MoveDown(void)
3014  {
3015      QMutexLocker lock(&m_update);
3016 -
3017 -    if (m_itemList.find(m_selItem) == -1)
3018 +    if (!m_itemList.size())
3019          return;
3020  
3021 -    OSDListBtnTypeItem *item = m_itemList.next();
3022 -    if (!item)
3023 -    {
3024 -        item = m_itemList.first();
3025 -        if (!item)
3026 -            return;
3027 +    if (++m_selIndx >= (int)m_itemList.size())
3028 +        m_selIndx = m_topIndx = 0;
3029  
3030 -        m_topItem = item;
3031 -    }
3032 -
3033 -    m_selItem = item;
3034 -
3035 -    if (m_itemList.find(m_topItem) + m_itemsVisible <=
3036 -        (unsigned int)m_itemList.find(m_selItem)) 
3037 -    {
3038 -        m_topItem = m_itemList.at(m_itemList.find(m_topItem) + 1);
3039 -    }
3040 +    bool scroll_down = m_topIndx + (int)m_itemsVisible <= m_selIndx;
3041 +    m_topIndx = (scroll_down) ? m_topIndx + 1 : m_topIndx;
3042 +        
3043 +    m_showUpArrow = m_topIndx;
3044 +    m_showDnArrow = m_topIndx + m_itemsVisible < m_itemList.size();
3045      
3046 -    if (m_topItem != m_itemList.first())
3047 -        m_showUpArrow = true;
3048 -    else
3049 -        m_showUpArrow = false;
3050 -
3051 -    if (m_itemList.find(m_topItem) + m_itemsVisible < m_itemList.count())
3052 -        m_showDnArrow = true;
3053 -    else
3054 -        m_showDnArrow = false;
3055 -    
3056 -    emit itemSelected(m_selItem);
3057 +    emit itemSelected(m_itemList[m_selIndx]);
3058  }
3059  
3060 -void OSDListBtnType::Draw(OSDSurface *surface, int fade, int maxfade, int xoff,
3061 -                          int yoff)
3062 +void OSDListBtnType::Draw(OSDSurface *surface,
3063 +                          int fade, int maxfade,
3064 +                          int xoff, int yoff)
3065  {
3066 -    (void)xoff;
3067 -    (void)yoff;
3068 -
3069 +    QMutexLocker lock(&m_update);
3070      if (!m_visible)
3071          return;
3072 -
3073 -    QMutexLocker lock(&m_update);
3074 -
3075      if (!m_initialized)
3076          Init();
3077  
3078      TTFFont *font = m_active ? m_fontActive : m_fontInactive;
3079      
3080      int y = m_rect.y();
3081 -    m_itemList.find(m_topItem);
3082 -    OSDListBtnTypeItem *it = m_itemList.current();
3083 -    while (it && (y - m_rect.y()) <= (m_contentsRect.height() - m_itemHeight)) 
3084 +    for (uint i = m_topIndx; i < m_itemList.size(); i++)
3085      {
3086 -        it->paint(surface, font, fade, maxfade, m_rect.x()+ xoff, y + yoff);
3087 -
3088 +        if (!((y - m_rect.y()) <= (m_contentsRect.height() - m_itemHeight)))
3089 +            break;
3090 +        m_itemList[i]->paint(surface, font, fade, maxfade,
3091 +                             m_rect.x() + xoff, y + yoff);
3092          y += m_itemHeight + m_itemSpacing;
3093 -
3094 -        it = m_itemList.next();
3095      }
3096  
3097      if (m_showScrollArrows) 
3098 @@ -792,14 +587,13 @@
3099      }
3100  }
3101  
3102 -void OSDListBtnType::Init()
3103 +void OSDListBtnType::Init(void)
3104  {
3105      int sz1 = m_fontActive->Size() * 3 / 2;
3106      int sz2 = m_fontInactive->Size() * 3 / 2;
3107 -    m_itemHeight = QMAX(sz1, sz2) + (int)(2 * m_itemMargin);
3108 +    m_itemHeight = max(sz1, sz2) + (int)(2 * m_itemMargin);
3109 +    m_itemHeight = m_itemHeight & ~0x1;
3110  
3111 -    m_itemHeight = (m_itemHeight / 2) * 2;
3112 -
3113      if (m_showScrollArrows) 
3114      {
3115          LoadPixmap(m_upArrowRegPix, "uparrow-reg");
3116 @@ -838,11 +632,7 @@
3117      InitItem(m_itemSelActPix,   itemWidth,    m_itemHeight,
3118               m_itemSelBeg,      m_itemSelEnd, 255);
3119  
3120 -    if (m_itemList.count() > m_itemsVisible && m_showScrollArrows)
3121 -        m_showDnArrow = true;
3122 -    else
3123 -        m_showDnArrow = false;
3124 -
3125 +    m_showDnArrow = m_itemList.size() > m_itemsVisible && m_showScrollArrows;
3126      m_initialized = true;
3127  }
3128  
3129 @@ -885,68 +675,57 @@
3130  
3131  void OSDListBtnType::LoadPixmap(OSDTypeImage& pix, const QString& fileName)
3132  {
3133 -    QString file = gContext->GetThemesParentDir() + "default/lb-" + fileName + ".png";
3134 -    pix.LoadImage(file, m_wmult, m_hmult);
3135 +    QString path = gContext->GetThemesParentDir() + "default/lb-";
3136 +    pix.LoadImage(path + fileName + ".png", m_wmult, m_hmult);
3137  }
3138  
3139  /////////////////////////////////////////////////////////////////////////////
3140 -OSDListBtnTypeItem::OSDListBtnTypeItem(OSDListBtnType* lbtype, 
3141 -                                       const QString& text,
3142 -                                       OSDTypeImage *pixmap, bool checkable,
3143 -                                       bool showArrow, CheckState state)
3144 +OSDListBtnTypeItem::OSDListBtnTypeItem(
3145 +    OSDListBtnType *lbtype,     const QString  &text,
3146 +    OSDTypeImage   *pixmap,     bool            checkable,
3147 +    bool            showArrow,  CheckState      state)
3148 +    : m_parent(lbtype),       m_pixmap(pixmap),
3149 +      m_data(NULL),           m_text(text),
3150 +      m_group(QString::null), m_state(state),
3151 +      m_showArrow(showArrow), m_checkable(checkable),
3152 +      m_checkRect(0,0,0,0),   m_arrowRect(0,0,0,0),
3153 +      m_pixmapRect(0,0,0,0),  m_textRect(0,0,0,0)
3154  {
3155 -    m_parent    = lbtype;
3156 -    m_text      = text;
3157 -    m_pixmap    = pixmap;
3158 -    m_checkable = checkable;
3159 -    m_state     = state;
3160 -    m_showArrow = showArrow;
3161 -    m_data      = 0;
3162 -
3163      if (!m_parent->m_initialized)
3164          m_parent->Init();
3165  
3166 -    int  margin    = m_parent->m_itemMargin;
3167 -    int  width     = m_parent->m_rect.width();
3168 -    int  height    = m_parent->m_itemHeight;
3169 +    OSDTypeImage &checkPix = m_parent->m_checkNonePix;
3170 +    OSDTypeImage &arrowPix = m_parent->m_arrowPix;
3171  
3172 -    OSDTypeImage& checkPix = m_parent->m_checkNonePix;
3173 -    OSDTypeImage& arrowPix = m_parent->m_arrowPix;
3174 -    
3175 -    int cw = checkPix.ImageSize().width();
3176 -    int ch = checkPix.ImageSize().height();
3177 -    int aw = arrowPix.ImageSize().width();
3178 -    int ah = arrowPix.ImageSize().height();
3179 -    int pw = m_pixmap ? m_pixmap->ImageSize().width() : 0;
3180 -    int ph = m_pixmap ? m_pixmap->ImageSize().height() : 0;
3181 -    
3182 +    int margin = m_parent->m_itemMargin;
3183 +    int width  = m_parent->m_rect.width();
3184 +    int height = m_parent->m_itemHeight;
3185 +    int cw     = checkPix.ImageSize().width();
3186 +    int ch     = checkPix.ImageSize().height();
3187 +    int aw     = arrowPix.ImageSize().width();
3188 +    int ah     = arrowPix.ImageSize().height();
3189 +    int pw     = m_pixmap ? m_pixmap->ImageSize().width() : 0;
3190 +    int ph     = m_pixmap ? m_pixmap->ImageSize().height() : 0;
3191 +
3192      if (m_checkable) 
3193 -        m_checkRect = QRect(margin, (height - ch)/2, cw, ch);
3194 -    else
3195 -        m_checkRect = QRect(0,0,0,0);
3196 +        m_checkRect  = QRect(margin, (height - ch)/2, cw, ch);
3197  
3198      if (m_showArrow) 
3199 -        m_arrowRect = QRect(width - aw - margin, (height - ah)/2,
3200 -                            aw, ah);
3201 -    else
3202 -        m_arrowRect = QRect(0,0,0,0);
3203 +        m_arrowRect  = QRect(width - aw - margin, (height - ah)/2, aw, ah);
3204  
3205 -    if (m_pixmap) 
3206 -        m_pixmapRect = QRect(m_checkable ? (2*margin + m_checkRect.width()) :
3207 -                             margin, (height - ph)/2,
3208 -                             pw, ph);
3209 -    else
3210 -        m_pixmapRect = QRect(0,0,0,0);
3211 +    if (m_pixmap)
3212 +    {
3213 +        int tmp = (m_checkable) ? (2 * margin + m_checkRect.width()) : margin;
3214 +        m_pixmapRect = QRect(tmp, (height - ph)/2, pw, ph);
3215 +    }
3216  
3217 -    m_textRect = QRect(margin +
3218 -                       (m_checkable ? m_checkRect.width() + margin : 0) +
3219 -                       (m_pixmap    ? m_pixmapRect.width() + margin : 0),
3220 -                       0,
3221 -                       width - 2*margin -
3222 -                       (m_checkable ? m_checkRect.width() + margin : 0) -
3223 -                       (m_showArrow ? m_arrowRect.width() + margin : 0) -
3224 -                       (m_pixmap ? m_pixmapRect.width() + margin : 0),
3225 -                       height);
3226 +    int tx = margin, tw = width - (2 * margin);
3227 +    tx += (m_checkable) ? m_checkRect.width()  + margin : 0;
3228 +    tx += (m_pixmap)    ? m_pixmapRect.width() + margin : 0;
3229 +    tw -= (m_checkable) ? m_checkRect.width()  + margin : 0;
3230 +    tw -= (m_showArrow) ? m_arrowRect.width()  + margin : 0;
3231 +    tw -= (m_pixmap)    ? m_pixmapRect.width() + margin : 0;
3232 +    m_textRect = QRect(tx, 0, tw, height);
3233  
3234      m_parent->InsertItem(this);
3235  }
3236 @@ -957,52 +736,10 @@
3237          m_parent->RemoveItem(this);
3238  }
3239  
3240 -QString OSDListBtnTypeItem::text() const
3241 -{
3242 -    return m_text;
3243 -}
3244 -
3245 -const OSDTypeImage* OSDListBtnTypeItem::pixmap() const
3246 -{
3247 -    return m_pixmap;
3248 -}
3249 -
3250 -bool OSDListBtnTypeItem::checkable() const
3251 -{
3252 -    return m_checkable;
3253 -}
3254 -
3255 -OSDListBtnTypeItem::CheckState OSDListBtnTypeItem::state() const
3256 -{
3257 -    return m_state;
3258 -}
3259 -
3260 -OSDListBtnType* OSDListBtnTypeItem::parent() const
3261 -{
3262 -    return m_parent;
3263 -}
3264 -
3265 -void OSDListBtnTypeItem::setChecked(CheckState state)
3266 -{
3267 -    if (!m_checkable)
3268 -        return;
3269 -    m_state = state;
3270 -}
3271 -
3272 -void OSDListBtnTypeItem::setData(void *data)
3273 -{
3274 -    m_data = data;    
3275 -}
3276 -
3277 -void* OSDListBtnTypeItem::getData()
3278 -{
3279 -    return m_data;
3280 -}
3281 -
3282  void OSDListBtnTypeItem::paint(OSDSurface *surface, TTFFont *font, 
3283                                 int fade, int maxfade, int x, int y)
3284  {
3285 -    if (this == m_parent->m_selItem)
3286 +    if (this == m_parent->GetItemCurrent())
3287      {
3288          if (m_parent->m_active)
3289              m_parent->m_itemSelActPix.Draw(surface, fade, maxfade, x, y);
3290 @@ -1030,11 +767,14 @@
3291          cr.moveBy(x, y);
3292          
3293          if (m_state == HalfChecked)
3294 -            m_parent->m_checkHalfPix.Draw(surface, fade, maxfade, cr.x(), cr.y());
3295 +            m_parent->m_checkHalfPix.Draw(surface, fade, maxfade,
3296 +                                          cr.x(), cr.y());
3297          else if (m_state == FullChecked)
3298 -            m_parent->m_checkFullPix.Draw(surface, fade, maxfade, cr.x(), cr.y());
3299 +            m_parent->m_checkFullPix.Draw(surface, fade, maxfade,
3300 +                                          cr.x(), cr.y());
3301          else
3302 -            m_parent->m_checkNonePix.Draw(surface, fade, maxfade, cr.x(), cr.y());
3303 +            m_parent->m_checkNonePix.Draw(surface, fade, maxfade,
3304 +                                          cr.x(), cr.y());
3305      }
3306  
3307      if (m_pixmap)
3308 @@ -1049,39 +789,3 @@
3309      tr.moveBy(0, font->Size() / 4);
3310      font->DrawString(surface, tr.x(), tr.y(), m_text, tr.right(), tr.bottom());
3311  }
3312 -
3313 -void OSDListBtnTypeItem::Reinit(float wchange, float hchange, 
3314 -                                float wmult, float hmult)
3315 -{
3316 -    (void)wmult;
3317 -    (void)hmult;
3318 -
3319 -    int width = (int)(m_checkRect.width() * wchange);
3320 -    int height = (int)(m_checkRect.height() * hchange);
3321 -    int x = (int)(m_checkRect.x() * wchange);
3322 -    int y = (int)(m_checkRect.y() * hchange);
3323 -
3324 -    m_checkRect = QRect(x, y, width, height);
3325 -
3326 -    width = (int)(m_pixmapRect.width() * wchange);
3327 -    height = (int)(m_pixmapRect.height() * hchange);
3328 -    x = (int)(m_pixmapRect.x() * wchange);
3329 -    y = (int)(m_pixmapRect.y() * hchange);
3330 -
3331 -    m_pixmapRect = QRect(x, y, width, height);
3332 -
3333 -    width = (int)(m_textRect.width() * wchange);
3334 -    height = (int)(m_textRect.height() * hchange);
3335 -    x = (int)(m_textRect.x() * wchange);
3336 -    y = (int)(m_textRect.y() * hchange);
3337 -
3338 -    m_textRect = QRect(x, y, width, height);
3339 -
3340 -    width = (int)(m_arrowRect.width() * wchange);
3341 -    height = (int)(m_arrowRect.height() * hchange);
3342 -    x = (int)(m_arrowRect.x() * wchange);
3343 -    y = (int)(m_arrowRect.y() * hchange);
3344 -
3345 -    m_arrowRect = QRect(x, y, width, height);
3346 -}
3347 -
3348 Index: mythtv/libs/libmythtv/RingBuffer.cpp
3349 ===================================================================
3350 --- mythtv/libs/libmythtv/RingBuffer.cpp        (.../tags/release-0-19) (revision 10931)
3351 +++ mythtv/libs/libmythtv/RingBuffer.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
3352 @@ -145,6 +145,12 @@
3353      VERBOSE(VB_PLAYBACK, LOC + QString("OpenFile(%1, %1)")
3354              .arg(lfilename).arg(retryCount));
3355  
3356 +    if ((filename.right(4).lower() == ".png") ||
3357 +        (filename.right(4).lower() == ".gif"))
3358 +    {
3359 +        retryCount = 0;
3360 +    }
3361 +
3362      uint openAttempts = retryCount + 1;
3363  
3364      filename = lfilename;
3365 @@ -162,6 +168,7 @@
3366  
3367      bool is_local = false;
3368      bool is_dvd = false;
3369 +
3370      if ((filename.left(7) == "myth://") &&
3371          (filename.length() > 7 ))
3372      {
3373 @@ -271,6 +278,11 @@
3374              remotefile = NULL;
3375          }
3376      }
3377 +
3378 +    setswitchtonext = false;
3379 +    ateof = false;
3380 +    commserror = false;
3381 +    numfailures = 0;
3382  }
3383  
3384  /** \fn RingBuffer::IsOpen(void) const
3385 @@ -727,7 +739,7 @@
3386          loops = 0;
3387  
3388          pthread_rwlock_rdlock(&rwlock);
3389 -        if (totfree > readblocksize && !commserror)
3390 +        if (totfree > readblocksize && !commserror && !ateof && !setswitchtonext)
3391          {
3392              // limit the read size
3393              totfree = readblocksize;
3394 @@ -737,6 +749,9 @@
3395  
3396              if (remotefile)
3397              {
3398 +                if (livetvchain && livetvchain->HasNext())
3399 +                    remotefile->SetTimeout(true);
3400 +
3401                  ret = safe_read(remotefile, readAheadBuffer + rbwpos,
3402                                  totfree);
3403                  internalreadpos += ret;
3404 @@ -785,8 +800,16 @@
3405              totfree = 0;
3406          }
3407  
3408 -        if (!readsallowed && used >= fill_min)
3409 +        if (!readsallowed && (used >= fill_min || setswitchtonext))
3410 +        {
3411              readsallowed = true;
3412 +            VERBOSE(VB_PLAYBACK, QString("reads allowed (%1 %2)").arg(used)
3413 +                                                                .arg(fill_min));
3414 +        }
3415 +        else if (!readsallowed)
3416 +            VERBOSE(VB_PLAYBACK, QString("buffering (%1 %2 %3)").arg(used)
3417 +                                                                .arg(fill_min)
3418 +                                                                .arg(ret));
3419  
3420          if (readsallowed && used < fill_min && !ateof && !setswitchtonext)
3421          {
3422 @@ -808,8 +831,11 @@
3423  
3424          pthread_rwlock_unlock(&rwlock);
3425  
3426 -        if ((used >= fill_threshold || wantseek) && !pausereadthread)
3427 +        if ((used >= fill_threshold || wantseek || ateof || setswitchtonext) &&
3428 +            !pausereadthread)
3429 +        {
3430              usleep(500);
3431 +        }
3432      }
3433  
3434      delete [] readAheadBuffer;
3435 @@ -853,15 +879,15 @@
3436                   VERBOSE(VB_IMPORTANT,
3437                           LOC + "Taking too long to be allowed to read..");
3438                   readErr++;
3439 -                 
3440 +
3441                   // HACK Sometimes the readhead thread gets borked on startup.
3442 -               /*  if ((readErr % 2) && (rbrpos ==0))
3443 +                 if ((readErr > 2 && readErr % 2) && (rbrpos ==0))
3444                   {
3445                      VERBOSE(VB_IMPORTANT, "restarting readhead thread..");
3446                      KillReadAheadThread();
3447                      StartupReadAheadThread();
3448                   }                    
3449 -                   */ 
3450
3451                   if (readErr > 10)
3452                   {
3453                       VERBOSE(VB_IMPORTANT, LOC_ERR + "Took more than "
3454 @@ -895,6 +921,12 @@
3455                  VERBOSE(VB_IMPORTANT, LOC + "Waited " +
3456                          QString("%1").arg(elapsed/1000) +
3457                          " seconds for data to become available...");
3458 +                if (livetvchain)
3459 +                {
3460 +                    VERBOSE(VB_IMPORTANT, "Checking to see if there's a "
3461 +                                          "new livetv program to switch to..");
3462 +                    livetvchain->ReloadAll();
3463 +                }
3464              }
3465  
3466              bool quit = livetvchain && (livetvchain->NeedsToSwitch() || 
3467 @@ -923,7 +955,7 @@
3468          availWaitMutex.unlock();
3469  
3470          avail = ReadBufAvail();
3471 -        if (ateof && avail < count)
3472 +        if ((ateof || setswitchtonext) && avail < count)
3473              count = avail;
3474  
3475          if (commserror)
3476 Index: mythtv/libs/libmythtv/hdtvrecorder.cpp
3477 ===================================================================
3478 --- mythtv/libs/libmythtv/hdtvrecorder.cpp      (.../tags/release-0-19) (revision 10931)
3479 +++ mythtv/libs/libmythtv/hdtvrecorder.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
3480 @@ -627,9 +627,8 @@
3481  
3482          len += remainder;
3483          remainder = ProcessData(_buffer, len);
3484 -        if (remainder > 0) // leftover bytes
3485 -            memmove(_buffer, &(_buffer[_buffer_size - remainder]),
3486 -                    remainder);
3487 +        if (remainder > 0 && (len > remainder)) // leftover bytes
3488 +            memmove(_buffer, &(_buffer[len - remainder]), remainder);
3489      }
3490  
3491      FinishRecording();
3492 Index: mythtv/libs/libmythtv/dummydtvrecorder.cpp
3493 ===================================================================
3494 --- mythtv/libs/libmythtv/dummydtvrecorder.cpp  (.../tags/release-0-19) (revision 10931)
3495 +++ mythtv/libs/libmythtv/dummydtvrecorder.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
3496 @@ -125,7 +125,8 @@
3497      // TRANSFER DATA
3498      while (_request_recording || _frames_seen_count <= 5)
3499      {
3500 -        len = read(_stream_fd, &(_buffer[remainder]), _buffer_size - remainder);
3501 +        len = read(_stream_fd, &(_buffer[remainder]),
3502 +                   _buffer_size - remainder);
3503  
3504          if (len == 0)
3505          {
3506 @@ -137,9 +138,8 @@
3507  
3508          len += remainder;
3509          remainder = ProcessData(_buffer, len);
3510 -        if (remainder > 0) // leftover bytes
3511 -            memmove(_buffer, &(_buffer[_buffer_size - remainder]),
3512 -                    remainder);
3513 +        if (remainder > 0 && (len > remainder)) // leftover bytes
3514 +            memmove(_buffer, &(_buffer[len - remainder]), remainder);
3515      }
3516  
3517      FinishRecording();
3518 Index: mythtv/libs/libmythtv/avformatdecoder.cpp
3519 ===================================================================
3520 --- mythtv/libs/libmythtv/avformatdecoder.cpp   (.../tags/release-0-19) (revision 10931)
3521 +++ mythtv/libs/libmythtv/avformatdecoder.cpp   (.../branches/release-0-19-fixes)       (revision 10931)
3522 @@ -725,7 +725,12 @@
3523          return -1;
3524      }
3525  
3526 +    /* av_find_stream_info() eventually makes calls to avcodec_open() and avcodec_close() 
3527 +       so we have to use the avcodeclock */
3528 +    avcodeclock.lock();
3529      int ret = av_find_stream_info(ic);
3530 +    avcodeclock.unlock();
3531 +
3532      if (ret < 0)
3533      {
3534          VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not find codec parameters. " +
3535 Index: mythtv/libs/libmythtv/osdtypes.cpp
3536 ===================================================================
3537 --- mythtv/libs/libmythtv/osdtypes.cpp  (.../tags/release-0-19) (revision 10931)
3538 +++ mythtv/libs/libmythtv/osdtypes.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
3539 @@ -14,6 +14,9 @@
3540  
3541  #include "mythcontext.h"
3542  
3543 +/// Shared OSD image cache
3544 +OSDImageCache OSDTypeImage::c_cache;
3545 +
3546  OSDSet::OSDSet(const QString &name, bool cache, int screenwidth, 
3547                 int screenheight, float wmult, float hmult, int frint)
3548        : QObject()
3549 @@ -160,9 +163,6 @@
3550                      int displaywidth, int displayheight, 
3551                      float wmult, float hmult, int frint)
3552  {
3553 -    float wchange = wmult / m_wmult;
3554 -    float hchange = hmult / m_hmult;
3555 -
3556      m_frameint = frint;
3557  
3558      m_screenwidth = screenwidth;
3559 @@ -175,57 +175,12 @@
3560      vector<OSDType *>::iterator iter = allTypes->begin();
3561      for (;iter != allTypes->end(); iter++)
3562      {
3563 -        OSDType *type = (*iter);
3564 -        if (OSDTypeText *item = dynamic_cast<OSDTypeText*>(type))
3565 -        {
3566 -            item->Reinit(wchange, hchange);
3567 -        }
3568 -        else if (OSDTypePositionImage *item =
3569 -                 dynamic_cast<OSDTypePositionImage*>(type))
3570 -        {
3571 -            item->Reinit(wchange, hchange, wmult, hmult);
3572 -        }
3573 -        else if (OSDTypePosSlider *item = dynamic_cast<OSDTypePosSlider*>(type))
3574 -        {
3575 -            item->Reinit(wchange, hchange, wmult, hmult);
3576 -        }
3577 -        else if (OSDTypeFillSlider *item = 
3578 -                 dynamic_cast<OSDTypeFillSlider*>(type))
3579 -        {
3580 -            item->Reinit(wchange, hchange, wmult, hmult);
3581 -        }
3582 -        else if (OSDTypeEditSlider *item =
3583 -                 dynamic_cast<OSDTypeEditSlider*>(type))
3584 -        {
3585 -            item->Reinit(wchange, hchange, wmult, hmult);
3586 -        }
3587 -        else if (OSDTypeImage *item = dynamic_cast<OSDTypeImage*>(type))
3588 -        {
3589 -            item->Reinit(wchange, hchange, wmult, hmult);
3590 -        }
3591 -        else if (OSDTypeBox *item = dynamic_cast<OSDTypeBox*>(type))
3592 -        {
3593 -            item->Reinit(wchange, hchange);
3594 -        }
3595 -        else if (OSDTypePositionRectangle *item =
3596 -                  dynamic_cast<OSDTypePositionRectangle*>(type))
3597 -        {
3598 -            item->Reinit(wchange, hchange);
3599 -        }
3600 -        else if (OSDTypeCC *item = dynamic_cast<OSDTypeCC*>(type))
3601 -        {
3602 -            item->Reinit(xoff, yoff, displaywidth, displayheight);
3603 -        }
3604 -        else if (OSDListTreeType *item = dynamic_cast<OSDListTreeType*>(type))
3605 -        {
3606 -            item->Reinit(wchange, hchange, wmult, hmult);
3607 -        }
3608 +        if (OSDTypeCC *cc608 = dynamic_cast<OSDTypeCC*>(*iter))
3609 +            cc608->Reinit(xoff, yoff, displaywidth, displayheight,
3610 +                          wmult, hmult);
3611          else
3612 -        {
3613 -            cerr << "Unknown conversion\n";
3614 -        }
3615 +            (*iter)->Reinit(wmult, hmult);
3616      }
3617 -
3618  }
3619  
3620  OSDType *OSDSet::GetType(const QString &name)
3621 @@ -443,7 +398,8 @@
3622  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3623  
3624  OSDTypeText::OSDTypeText(const QString &name, TTFFont *font, 
3625 -                         const QString &text, QRect displayrect)
3626 +                         const QString &text, QRect displayrect,
3627 +                         float wmult, float hmult)
3628             : OSDType(name)
3629  {
3630      m_message = text;
3631 @@ -464,6 +420,12 @@
3632      m_scrollinit = false;
3633  
3634      m_linespacing = 1.5;
3635 +
3636 +    m_unbiasedsize =
3637 +        QRect((int)round(m_screensize.x()      / wmult),
3638 +              (int)round(m_screensize.y()      / hmult),
3639 +              (int)ceil( m_screensize.width()  / wmult),
3640 +              (int)ceil( m_screensize.height() / hmult));
3641  }
3642  
3643  OSDTypeText::OSDTypeText(const OSDTypeText &other)
3644 @@ -507,14 +469,13 @@
3645      m_scrollinit = false;
3646  }
3647  
3648 -void OSDTypeText::Reinit(float wchange, float hchange)
3649 +void OSDTypeText::Reinit(float wmult, float hmult)
3650  {
3651 -    int width = (int)(m_screensize.width() * wchange);
3652 -    int height = (int)(m_screensize.height() * hchange);
3653 -    int x = (int)(m_screensize.x() * wchange);
3654 -    int y = (int)(m_screensize.y() * hchange);
3655 -
3656 -    m_displaysize = m_screensize = QRect(x, y, width, height);
3657 +    m_displaysize = m_screensize =
3658 +        QRect((int)round(m_unbiasedsize.x()      * wmult),
3659 +              (int)round(m_unbiasedsize.y()      * hmult),
3660 +              (int)ceil( m_unbiasedsize.width()  * wmult),
3661 +              (int)ceil( m_unbiasedsize.height() * hmult));
3662  }
3663  
3664  void OSDTypeText::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, 
3665 @@ -708,7 +669,7 @@
3666      m_onlyusefirst = false;
3667  
3668      m_filename = filename;
3669 -    m_displaypos = displaypos;
3670 +    SetPosition(displaypos, wmult, hmult);
3671  
3672      m_yuv = m_alpha = NULL;
3673      m_isvalid = false;
3674 @@ -716,6 +677,7 @@
3675  
3676      m_scalew = scalew;
3677      m_scaleh = scaleh;
3678 +    m_cacheitem = NULL;
3679  
3680      LoadImage(filename, wmult, hmult, scalew, scaleh);
3681  }
3682 @@ -733,6 +695,7 @@
3683      m_name = other.m_name;
3684      m_scalew = other.m_scalew;
3685      m_scaleh = other.m_scaleh;
3686 +    m_cacheitem = NULL;
3687  
3688      m_alpha = m_yuv = NULL;
3689      if (m_isvalid)
3690 @@ -760,6 +723,8 @@
3691      m_onlyusefirst = false;
3692  
3693      m_displaypos = QPoint(0, 0);
3694 +    m_unbiasedpos = QPoint(0, 0);
3695 +    m_cacheitem = NULL;
3696  
3697      m_yuv = NULL;
3698      m_alpha = NULL;
3699 @@ -778,6 +743,8 @@
3700      m_onlyusefirst = false;
3701  
3702      m_displaypos = QPoint(0, 0);
3703 +    m_unbiasedpos = QPoint(0, 0);
3704 +    m_cacheitem = NULL;
3705  
3706      m_yuv = NULL;
3707      m_alpha = NULL;
3708 @@ -790,10 +757,14 @@
3709  
3710  OSDTypeImage::~OSDTypeImage()
3711  {
3712 -    if (m_yuv)
3713 -        delete [] m_yuv;
3714 -    if (m_alpha)
3715 -        delete [] m_alpha;
3716 +    // In case we have a cache item in hand, it's safe to delete it,
3717 +    // as it should not be in OSDImageCache anymore and it should have
3718 +    // been written to the file cache for faster access in the future.
3719 +    if (m_cacheitem)
3720 +    {
3721 +        delete m_cacheitem;
3722 +        m_cacheitem = NULL;
3723 +    }
3724  }
3725  
3726  void OSDTypeImage::SetName(const QString &name)
3727 @@ -801,13 +772,19 @@
3728      m_name = name;
3729  }
3730  
3731 -void OSDTypeImage::Reinit(float wchange, float hchange, float wmult, float hmult)
3732 +void OSDTypeImage::SetPosition(QPoint pos, float wmult, float hmult)
3733  {
3734 -    int x = (int)(m_displaypos.x() * wchange);
3735 -    int y = (int)(m_displaypos.y() * hchange);
3736 +    m_displaypos  = pos;
3737 +    m_unbiasedpos =
3738 +        QPoint((int)round(pos.x() / wmult),
3739 +               (int)round(pos.y() / hmult));
3740 +}
3741  
3742 -    m_displaypos.setX(x);
3743 -    m_displaypos.setY(y);
3744 +void OSDTypeImage::Reinit(float wmult, float hmult)
3745 +{
3746 +    m_displaypos =
3747 +        QPoint((int)round(m_unbiasedpos.x() * wmult),
3748 +               (int)round(m_unbiasedpos.y() * hmult));
3749  
3750      LoadImage(m_filename, wmult, hmult, m_scalew, m_scaleh);
3751  }
3752 @@ -815,20 +792,44 @@
3753  void OSDTypeImage::LoadImage(const QString &filename, float wmult, float hmult,
3754                               int scalew, int scaleh)
3755  {
3756 -    if (m_isvalid)
3757 +    QString ckey;
3758 +   
3759 +    if (!filename.isEmpty() && filename.length() >= 2)
3760      {
3761 -        if (m_yuv)
3762 -            delete [] m_yuv;
3763 -        if (m_alpha)
3764 -            delete [] m_alpha;
3765 -
3766 -        m_isvalid = false;
3767 -        m_yuv = NULL;
3768 -        m_alpha = NULL;
3769 +        ckey = OSDImageCache::CreateKey(
3770 +            filename, wmult, hmult, scalew, scaleh);
3771      }
3772 +    else 
3773 +    {
3774 +        // this method requires a backing file
3775 +        return;
3776 +    }
3777 +  
3778 +    // Get the item from the cache so it's not freed while in use
3779 +    OSDImageCacheValue* value = c_cache.Get(ckey, true);
3780 +  
3781 +    if (value != NULL)
3782 +    {
3783 +        m_yuv       = value->m_yuv;
3784 +        m_ybuffer   = value->m_ybuffer;
3785 +        m_ubuffer   = value->m_ubuffer;
3786 +        m_vbuffer   = value->m_vbuffer;
3787 +        m_alpha     = value->m_alpha;
3788 +        m_imagesize = value->m_imagesize;
3789 +        m_isvalid   = true;
3790  
3791 -    if (filename.length() < 2)
3792 +        // Put the old image back to the cache so it can be reused in the
3793 +        // future, and possibly freed by the cache system if the size limit
3794 +        // is reached
3795 +        if (!m_cacheitem)
3796 +            c_cache.Insert(m_cacheitem);
3797 +        m_cacheitem = value;
3798 +
3799          return;
3800 +    }
3801 +   
3802 +    // scaled image was not found in cache, have to create it
3803 +  
3804  
3805      QImage tmpimage(filename);
3806  
3807 @@ -867,17 +868,32 @@
3808                       imwidth, imheight, tmp2.width());
3809  
3810      m_imagesize = QRect(0, 0, imwidth, imheight);
3811 +
3812 +    // put the old image back to the cache so it can be reused in the
3813 +    // future, and possibly freed by the cache system if the size limit
3814 +    // is reached
3815 +    if (m_cacheitem)
3816 +        c_cache.Insert(m_cacheitem);
3817 +  
3818 +    m_cacheitem = new OSDImageCacheValue(
3819 +        ckey,
3820 +        m_yuv,     m_ybuffer, m_ubuffer,
3821 +        m_vbuffer, m_alpha,   m_imagesize);
3822
3823 +    // save the new cache item to the file cache
3824 +    if (!filename.isEmpty())
3825 +        c_cache.SaveToDisk(m_cacheitem);
3826  }
3827  
3828  void OSDTypeImage::LoadFromQImage(const QImage &img)
3829  {
3830 +    // this method is not cached as it's used mostly for
3831 +    // subtitles which are displayed only once anyways, caching
3832 +    // would probably only slow things down overall
3833      if (m_isvalid)
3834      {
3835 -        if (m_yuv)
3836 -            delete [] m_yuv;
3837 -        if (m_alpha)
3838 -            delete [] m_alpha;
3839 -
3840 +        delete m_cacheitem;
3841 +        m_cacheitem = NULL;
3842          m_isvalid = false;
3843          m_yuv = NULL;
3844          m_alpha = NULL;
3845 @@ -1043,23 +1059,25 @@
3846      m_maxval = 1000;
3847      m_curval = 0;
3848      m_displayrect = displayrect;
3849 +    m_unbiasedrect =
3850 +        QRect((int)round(m_displayrect.x()      / wmult),
3851 +              (int)round(m_displayrect.y()      / hmult),
3852 +              (int)ceil( m_displayrect.width()  / wmult),
3853 +              (int)ceil( m_displayrect.height() / hmult));
3854  }
3855  
3856  OSDTypePosSlider::~OSDTypePosSlider()
3857  {
3858  }
3859  
3860 -void OSDTypePosSlider::Reinit(float wchange, float hchange, float wmult,
3861 -                              float hmult)
3862 +void OSDTypePosSlider::Reinit(float wmult, float hmult)
3863  {
3864 -    int width = (int)(m_displayrect.width() * wchange);
3865 -    int height = (int)(m_displayrect.height() * hchange);
3866 -    int x = (int)(m_displayrect.x() * wchange);
3867 -    int y = (int)(m_displayrect.y() * hchange);
3868 -
3869 -    m_displayrect = QRect(x, y, width, height);
3870 -
3871 -    OSDTypeImage::Reinit(wchange, hchange, wmult, hmult);
3872 +    m_displayrect =
3873 +        QRect((int)round(m_unbiasedrect.x()      * wmult),
3874 +              (int)round(m_unbiasedrect.y()      * hmult),
3875 +              (int)ceil( m_unbiasedrect.width()  * wmult),
3876 +              (int)ceil( m_unbiasedrect.height() * hmult));
3877 +    OSDTypeImage::Reinit(wmult, hmult);
3878  }
3879  
3880  void OSDTypePosSlider::SetPosition(int pos)
3881 @@ -1092,23 +1110,25 @@
3882      m_drawwidth = 0;
3883      m_onlyusefirst = true;
3884      m_displayrect = displayrect;
3885 +    m_unbiasedrect =
3886 +        QRect((int)round(m_displayrect.x()      / wmult),
3887 +              (int)round(m_displayrect.y()      / hmult),
3888 +              (int)ceil( m_displayrect.width()  / wmult),
3889 +              (int)ceil( m_displayrect.height() / hmult));
3890  }
3891  
3892  OSDTypeFillSlider::~OSDTypeFillSlider()
3893  {
3894  }
3895  
3896 -void OSDTypeFillSlider::Reinit(float wchange, float hchange, float wmult,
3897 -                               float hmult)
3898 +void OSDTypeFillSlider::Reinit(float wmult, float hmult)
3899  {
3900 -    int width = (int)(m_displayrect.width() * wchange);
3901 -    int height = (int)(m_displayrect.height() * hchange);
3902 -    int x = (int)(m_displayrect.x() * wchange);
3903 -    int y = (int)(m_displayrect.y() * hchange);
3904 -
3905 -    m_displayrect = QRect(x, y, width, height);
3906 -
3907 -    OSDTypeImage::Reinit(wchange, hchange, wmult, hmult);
3908 +    m_displayrect =
3909 +        QRect((int)round(m_unbiasedrect.x()      * wmult),
3910 +              (int)round(m_unbiasedrect.y()      * hmult),
3911 +              (int)ceil( m_unbiasedrect.width()  * wmult),
3912 +              (int)ceil( m_unbiasedrect.height() * hmult));
3913 +    OSDTypeImage::Reinit(wmult, hmult);
3914  }
3915  
3916  void OSDTypeFillSlider::SetPosition(int pos)
3917 @@ -1143,6 +1163,11 @@
3918      m_maxval = 1000;
3919      m_curval = 0;
3920      m_displayrect = displayrect;
3921 +    m_unbiasedrect =
3922 +        QRect((int)round(m_displayrect.x()      / wmult),
3923 +              (int)round(m_displayrect.y()      / hmult),
3924 +              (int)ceil( m_displayrect.width()  / wmult),
3925 +              (int)ceil( m_displayrect.height() / hmult));
3926      m_drawwidth = displayrect.width();
3927  
3928      m_drawMap = new unsigned char[m_drawwidth + 1];
3929 @@ -1162,6 +1187,7 @@
3930  
3931      m_scalew = scalew;
3932      m_scaleh = scaleh;
3933 +    m_cacheitem = NULL;
3934  
3935      LoadImage(m_redname, wmult, hmult, scalew, scaleh);
3936      if (m_isvalid)
3937 @@ -1184,22 +1210,16 @@
3938  OSDTypeEditSlider::~OSDTypeEditSlider()
3939  {
3940      delete [] m_drawMap;
3941 -
3942 -    if (m_ryuv)
3943 -        delete [] m_ryuv;
3944 -    if (m_ralpha)
3945 -        delete [] m_ralpha;
3946  }
3947  
3948 -void OSDTypeEditSlider::Reinit(float wchange, float hchange, float wmult,
3949 -                               float hmult)
3950 +void OSDTypeEditSlider::Reinit(float wmult, float hmult)
3951  {
3952 -    int width = (int)(m_displayrect.width() * wchange);
3953 -    int height = (int)(m_displayrect.height() * hchange);
3954 -    int x = (int)(m_displayrect.x() * wchange);
3955 -    int y = (int)(m_displayrect.y() * hchange);
3956 +    m_displayrect =
3957 +        QRect((int)round(m_unbiasedrect.x()      * wmult),
3958 +              (int)round(m_unbiasedrect.y()      * hmult),
3959 +              (int)ceil( m_unbiasedrect.width()  * wmult),
3960 +              (int)ceil( m_unbiasedrect.height() * hmult));
3961  
3962 -    m_displayrect = QRect(x, y, width, height);
3963      m_drawwidth = m_displayrect.width();
3964  
3965      delete [] m_drawMap;
3966 @@ -1210,11 +1230,6 @@
3967  
3968      m_displaypos = m_displayrect.topLeft();
3969  
3970 -    if (m_ryuv)
3971 -        delete [] m_ryuv;
3972 -    if (m_ralpha)
3973 -        delete [] m_ralpha;
3974 -
3975      LoadImage(m_redname, wmult, hmult, m_scalew, m_scaleh);
3976      if (m_isvalid)
3977      {
3978 @@ -1360,30 +1375,46 @@
3979  
3980  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3981  
3982 -OSDTypeBox::OSDTypeBox(const QString &name, QRect displayrect) 
3983 -          : OSDType(name)
3984 +OSDTypeBox::OSDTypeBox(const QString &name, QRect displayrect,
3985 +                       float wmult, float hmult)
3986 +    : OSDType(name)
3987  {
3988      size = displayrect;
3989 +    m_unbiasedsize =
3990 +        QRect((int)round(size.x()      / wmult),
3991 +              (int)round(size.y()      / hmult),
3992 +              (int)ceil( size.width()  / wmult),
3993 +              (int)ceil( size.height() / hmult));
3994  }
3995  
3996 +void OSDTypeBox::SetRect(QRect newrect, float wmult, float hmult)
3997 +{
3998 +    size = newrect;
3999 +    m_unbiasedsize =
4000 +        QRect((int)round(size.x()      / wmult),
4001 +              (int)round(size.y()      / hmult),
4002 +              (int)ceil( size.width()  / wmult),
4003 +              (int)ceil( size.height() / hmult));
4004 +}
4005 +
4006  OSDTypeBox::OSDTypeBox(const OSDTypeBox &other)
4007            : OSDType(other.m_name)
4008  {
4009      size = other.size;
4010 +    m_unbiasedsize = other.m_unbiasedsize;
4011  }
4012  
4013  OSDTypeBox::~OSDTypeBox()
4014  {
4015  }
4016  
4017 -void OSDTypeBox::Reinit(float wchange, float hchange)
4018 +void OSDTypeBox::Reinit(float wmult, float hmult)
4019  {
4020 -    int width = (int)(size.width() * wchange);
4021 -    int height = (int)(size.height() * hchange);
4022 -    int x = (int)(size.x() * wchange);
4023 -    int y = (int)(size.y() * hchange);
4024 -
4025 -    size = QRect(x, y, width, height);
4026 +    size =
4027 +        QRect((int)round(m_unbiasedsize.x()      * wmult),
4028 +              (int)round(m_unbiasedsize.y()      * hmult),
4029 +              (int)ceil( m_unbiasedsize.width()  * wmult),
4030 +              (int)ceil( m_unbiasedsize.height() * hmult));
4031  }
4032  
4033  void OSDTypeBox::Draw(OSDSurface *surface, int fade, int maxfade, int xoff, 
4034 @@ -1498,44 +1529,52 @@
4035  }       
4036     
4037  OSDTypePositionRectangle::OSDTypePositionRectangle(
4038 -                                        const OSDTypePositionRectangle &other) 
4039 -                        : OSDType(other.m_name), OSDTypePositionIndicator(other)
4040 +    const OSDTypePositionRectangle &other) 
4041 +    : OSDType(other.m_name), OSDTypePositionIndicator(other)
4042  {
4043      for (int i = 0; i < m_numpositions; i++)
4044      {
4045          QRect tmp = other.positions[i];
4046          positions.push_back(tmp);
4047      }
4048 +    for (int i = 0; i < m_numpositions; i++)
4049 +    {
4050 +        QRect tmp = other.unbiasedpos[i];
4051 +        unbiasedpos.push_back(tmp);
4052 +    }
4053  }
4054  
4055  OSDTypePositionRectangle::~OSDTypePositionRectangle()
4056  {
4057  }
4058  
4059 -void OSDTypePositionRectangle::Reinit(float wchange, float hchange)
4060 +void OSDTypePositionRectangle::Reinit(float wmult, float hmult)
4061  {
4062      for (int i = 0; i < m_numpositions; i++)
4063      {
4064 -        QRect tmp = positions[i];
4065 -
4066 -        int width = (int)(tmp.width() * wchange);
4067 -        int height = (int)(tmp.height() * hchange);
4068 -        int x = (int)(tmp.x() * wchange);
4069 -        int y = (int)(tmp.y() * hchange);
4070 -
4071 -        tmp = QRect(x, y, width, height);
4072 -        positions[i] = tmp;
4073 +        QRect tmp = unbiasedpos[i];
4074 +        positions[i] =
4075 +            QRect((int)round(tmp.x()      * wmult),
4076 +                  (int)round(tmp.y()      * hmult),
4077 +                  (int)ceil( tmp.width()  * wmult),
4078 +                  (int)ceil( tmp.height() * hmult));
4079      }
4080  }
4081  
4082 -void OSDTypePositionRectangle::AddPosition(QRect rect)
4083 +void OSDTypePositionRectangle::AddPosition(
4084 +    QRect rect, float wmult, float hmult)
4085  {
4086      positions.push_back(rect);
4087 +    unbiasedpos.push_back(
4088 +        QRect((int)round(rect.x()      / wmult),
4089 +              (int)round(rect.y()      / hmult),
4090 +              (int)ceil( rect.width()  / wmult),
4091 +              (int)ceil( rect.height() / hmult)));
4092      m_numpositions++;
4093  }
4094  
4095 -void OSDTypePositionRectangle::Draw(OSDSurface *surface, int fade, int maxfade, 
4096 -                                    int xoff, int yoff)
4097 +void OSDTypePositionRectangle::Draw(
4098 +    OSDSurface *surface, int fade, int maxfade, int xoff, int yoff)
4099  {
4100      fade = fade;
4101      maxfade = maxfade;
4102 @@ -1618,17 +1657,21 @@
4103  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4104  
4105  OSDTypePositionImage::OSDTypePositionImage(const QString &name)
4106 -                    : OSDTypeImage(name), OSDTypePositionIndicator()
4107 +    : OSDTypeImage(name), OSDTypePositionIndicator(),
4108 +      m_wmult(0.0f), m_hmult(0.0f)
4109  {
4110  }
4111  
4112  OSDTypePositionImage::OSDTypePositionImage(const OSDTypePositionImage &other)
4113                      : OSDTypeImage(other), OSDTypePositionIndicator(other)
4114  {
4115 +    m_wmult = other.m_wmult;
4116 +    m_hmult = other.m_hmult;
4117 +
4118      for (int i = 0; i < m_numpositions; i++)
4119      {
4120 -        QPoint tmp = other.positions[i];
4121 -        positions.push_back(tmp);
4122 +        positions.push_back(other.positions[i]);
4123 +        unbiasedpos.push_back(other.unbiasedpos[i]);
4124      }
4125  }
4126  
4127 @@ -1636,45 +1679,61 @@
4128  {
4129  }
4130  
4131 -void OSDTypePositionImage::Reinit(float wchange, float hchange, float wmult, 
4132 -                                  float hmult)
4133 +void OSDTypePositionImage::Reinit(float wmult, float hmult)
4134  {
4135 -    OSDTypeImage::Reinit(wchange, hchange, wmult, hmult);
4136 +    m_wmult = wmult;
4137 +    m_hmult = hmult;
4138 +    
4139 +    OSDTypeImage::Reinit(wmult, hmult);
4140  
4141      for (int i = 0; i < m_numpositions; i++)
4142      {
4143 -        QPoint tmp = positions[i];
4144 -
4145 -        int x = (int)(tmp.x() * wchange);
4146 -        int y = (int)(tmp.y() * hchange);
4147 -
4148 -        positions[i].setX(x);
4149 -        positions[i].setY(y);
4150 +        positions[i] =
4151 +            QPoint((int)round(unbiasedpos[i].x() * wmult),
4152 +                   (int)round(unbiasedpos[i].y() * hmult));
4153      }
4154  }
4155  
4156 -void OSDTypePositionImage::AddPosition(QPoint pos)
4157 +void OSDTypePositionImage::AddPosition(QPoint pos, float wmult, float hmult)
4158  {
4159 +    if (m_wmult == 0.0f || m_hmult == 0.0f)
4160 +    {
4161 +        m_wmult = wmult;
4162 +        m_hmult = hmult;
4163 +    }
4164      positions.push_back(pos);
4165 +    unbiasedpos.push_back(
4166 +        QPoint((int)round(pos.x() / wmult),
4167 +               (int)round(pos.y() / hmult)));
4168 +
4169 +    VERBOSE(VB_IMPORTANT,
4170 +            "OSDTypePositionImage::AddPosition["<<m_numpositions<<"]("
4171 +            <<pos.x()<<"x"<<pos.y()
4172 +            <<"  "<<wmult<<", "<<hmult<<")");
4173 +
4174      m_numpositions++;
4175  }
4176  
4177  void OSDTypePositionImage::Draw(OSDSurface *surface, int fade, int maxfade,
4178                                  int xoff, int yoff)
4179  {
4180 +    VERBOSE(VB_IMPORTANT,
4181 +            "OSDTypePositionImage::Draw["<<m_curposition<<"]("
4182 +            <<m_wmult<<", "<<m_hmult<<")");
4183 +
4184      if (m_curposition < 0 || m_curposition >= m_numpositions)
4185          return;
4186  
4187      QPoint pos = positions[m_curposition];
4188  
4189 -    OSDTypeImage::SetPosition(pos);
4190 +    OSDTypeImage::SetPosition(pos, m_wmult, m_hmult);
4191      OSDTypeImage::Draw(surface, fade, maxfade, xoff, yoff);
4192  }
4193  
4194  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4195  
4196  OSDTypeCC::OSDTypeCC(const QString &name, TTFFont *font, int xoff, int yoff,
4197 -                     int dispw, int disph)
4198 +                     int dispw, int disph, float wmult, float hmult)
4199           : OSDType(name)
4200  {
4201      m_font = font;
4202 @@ -1683,9 +1742,11 @@
4203      yoffset = yoff;
4204      displaywidth = dispw;
4205      displayheight = disph;
4206 +    m_wmult = wmult;
4207 +    m_hmult = hmult;
4208  
4209      QRect rect = QRect(0, 0, 0, 0);
4210 -    m_box = new OSDTypeBox("cc_background", rect);
4211 +    m_box = new OSDTypeBox("cc_background", rect, wmult, hmult);
4212      m_ccbackground = gContext->GetNumSetting("CCBackground", 0);
4213  }
4214  
4215 @@ -1695,12 +1756,23 @@
4216      delete m_box;
4217  }
4218  
4219 -void OSDTypeCC::Reinit(int x, int y, int dispw, int disph)
4220 +void OSDTypeCC::Reinit(float wmult, float hmult)
4221  {
4222 +    (void) wmult;
4223 +    (void) hmult;
4224 +    VERBOSE(VB_IMPORTANT, "Programmer error: "
4225 +            "Call to OSDTypeCC::Reinit(float,float)");
4226 +}
4227 +
4228 +void OSDTypeCC::Reinit(int x, int y, int dispw, int disph,
4229 +                       float wmult, float hmult)
4230 +{
4231      xoffset = x;
4232      yoffset = y;
4233      displaywidth = dispw;
4234      displayheight = disph;
4235 +    m_wmult = wmult;
4236 +    m_hmult = hmult;    
4237  }
4238  
4239  void OSDTypeCC::AddCCText(const QString &text, int x, int y, int color, 
4240 @@ -1875,7 +1947,7 @@
4241              {
4242                  QRect rect = QRect(0, 0, textlength + 4, 
4243                                     (m_font->Size() * 3 / 2) + 3);
4244 -                m_box->SetRect(rect);
4245 +                m_box->SetRect(rect, m_wmult, m_hmult);
4246                  m_box->Draw(surface, 0, 0, x - 2, y - 2);
4247              }
4248  
4249 Index: mythtv/libs/libmythtv/tv_play.cpp
4250 ===================================================================
4251 --- mythtv/libs/libmythtv/tv_play.cpp   (.../tags/release-0-19) (revision 10931)
4252 +++ mythtv/libs/libmythtv/tv_play.cpp   (.../branches/release-0-19-fixes)       (revision 10931)
4253 @@ -247,7 +247,7 @@
4254        browsechannum(""), browsechanid(""), browsestarttime(""),
4255        // Program Info for currently playing video
4256        recorderPlaybackInfo(NULL),
4257 -      playbackinfo(NULL), inputFilename(""), playbackLen(0),
4258 +      playbackinfo(NULL), playbackLen(0),
4259        lastProgram(NULL), jumpToProgram(false),
4260        // Video Players
4261        nvp(NULL), pipnvp(NULL), activenvp(NULL),
4262 @@ -578,19 +578,7 @@
4263      if (!testrec->IsValidRecorder())
4264      {
4265          if (showDialogs)
4266 -        {
4267 -            QString title = tr("MythTV is already using all available "
4268 -                               "inputs for recording.  If you want to "
4269 -                               "watch an in-progress recording, select one "
4270 -                               "from the playback menu.  If you want to "
4271 -                               "watch live TV, cancel one of the "
4272 -                               "in-progress recordings from the delete "
4273 -                               "menu.");
4274 -            
4275 -            DialogBox diag(gContext->GetMainWindow(), title);
4276 -            diag.AddButton(tr("Cancel and go back to the TV menu"));
4277 -            diag.exec();
4278 -        }        
4279 +            ShowNoRecorderDialog();
4280          
4281          delete testrec;
4282          
4283 @@ -659,8 +647,6 @@
4284      if (internalState != kState_None)
4285          return 0;
4286  
4287 -    inputFilename = rcinfo->pathname;
4288 -
4289      playbackLen = rcinfo->CalculateLength();
4290      playbackinfo = new ProgramInfo(*rcinfo);
4291  
4292 @@ -844,9 +830,10 @@
4293          }
4294          else
4295          {
4296 +            QString playbackURL = playbackinfo->GetPlaybackURL();
4297 +
4298              tvchain->SetProgram(playbackinfo);
4299 -
4300 -            prbuffer = new RingBuffer(playbackinfo->pathname, false);
4301 +            prbuffer = new RingBuffer(playbackURL, false);
4302              prbuffer->SetLiveMode(tvchain);
4303          }
4304  
4305 @@ -895,7 +882,14 @@
4306      else if (TRANSITION(kState_None, kState_WatchingPreRecorded) ||
4307               TRANSITION(kState_None, kState_WatchingRecording))
4308      {
4309 -        prbuffer = new RingBuffer(inputFilename, false);
4310 +        QString playbackURL;
4311 +        if ((playbackinfo->pathname.left(4) == "dvd:") ||
4312 +            (playbackinfo->isVideo))
4313 +            playbackURL = playbackinfo->pathname;
4314 +        else
4315 +            playbackURL = playbackinfo->GetPlaybackURL();
4316 +
4317 +        prbuffer = new RingBuffer(playbackURL, false);
4318          if (prbuffer->IsOpen())
4319          {
4320              gContext->DisableScreensaver();
4321 @@ -924,7 +918,7 @@
4322              {
4323                  QString message = "COMMFLAG_REQUEST ";
4324                  message += playbackinfo->chanid + " " +
4325 -                           playbackinfo->startts.toString(Qt::ISODate);
4326 +                           playbackinfo->recstartts.toString(Qt::ISODate);
4327                  RemoteSendMessage(message);
4328              }                
4329          }
4330 @@ -1222,10 +1216,10 @@
4331      nvp->SetParentPlayer(this);
4332      nvp->SetRingBuffer(prbuffer);
4333      nvp->SetRecorder(recorder);
4334 -    nvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate"));
4335 +    nvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate", 44100));
4336      nvp->SetAudioDevice(gContext->GetSetting("AudioOutputDevice"));
4337      nvp->SetLength(playbackLen);
4338 -    nvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking"));
4339 +    nvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking", 0));
4340      nvp->SetAutoCommercialSkip(autoCommercialSkip);
4341      nvp->SetLiveTVChain(tvchain);
4342  
4343 @@ -1296,9 +1290,9 @@
4344      pipnvp->SetAsPIP();
4345      pipnvp->SetRingBuffer(piprbuffer);
4346      pipnvp->SetRecorder(piprecorder);
4347 -    pipnvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate"));
4348 +    pipnvp->SetAudioSampleRate(gContext->GetNumSetting("AudioSampleRate", 44100));
4349      pipnvp->SetAudioDevice(gContext->GetSetting("AudioOutputDevice"));
4350 -    pipnvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking"));
4351 +    pipnvp->SetExactSeeks(gContext->GetNumSetting("ExactSeeking", 0));
4352      pipnvp->SetLiveTVChain(piptvchain);
4353  
4354      pipnvp->SetLength(playbackLen);
4355 @@ -1454,6 +1448,30 @@
4356                  lastSignalMsg.clear();
4357              }
4358              UpdateOSDTimeoutMessage();
4359 +
4360 +            if (!tvchainUpdate.isEmpty())
4361 +            {
4362 +                tvchainUpdateLock.lock();
4363 +                for (QStringList::Iterator it = tvchainUpdate.begin();
4364 +                     it != tvchainUpdate.end(); ++it)
4365 +                {
4366 +                    if (tvchain && nvp && *it == tvchain->GetID())
4367 +                    {
4368 +                        tvchain->ReloadAll();
4369 +                        if (nvp->GetTVChain())
4370 +                            nvp->CheckTVChain();
4371 +                    }
4372 +                    if (piptvchain && pipnvp && *it == piptvchain->GetID())
4373 +                    {
4374 +                        piptvchain->ReloadAll();
4375 +                        if (pipnvp->GetTVChain())
4376 +                            pipnvp->CheckTVChain();
4377 +                    }
4378 +                }
4379 +                tvchainUpdate.clear();
4380 +                tvchainUpdateLock.unlock();
4381 +            }
4382 +
4383              osdlock.unlock();
4384          }
4385  
4386 @@ -2743,7 +2761,7 @@
4387                  speedStr = QString("%1X").arg(normal_speed);
4388  
4389              struct StatusPosInfo posInfo;
4390 -            nvp->calcSliderPos(posInfo);
4391 +            nvp->calcSliderPos(posInfo, true);
4392  
4393              QDateTime respDate = mythCurrentDateTime();
4394              QString infoStr = "";
4395 @@ -2806,8 +2824,10 @@
4396          }
4397          else
4398          {
4399 +            QString playbackURL = playbackinfo->GetPlaybackURL();
4400 +
4401              piptvchain->SetProgram(playbackinfo);
4402 -            piprbuffer = new RingBuffer(playbackinfo->pathname, false);
4403 +            piprbuffer = new RingBuffer(playbackURL, false);
4404              piprbuffer->SetLiveMode(piptvchain);
4405          }
4406  
4407 @@ -3472,8 +3492,10 @@
4408          }
4409          else
4410          {
4411 +            QString playbackURL = playbackinfo->GetPlaybackURL();
4412 +
4413              tvchain->SetProgram(playbackinfo);
4414 -            prbuffer = new RingBuffer(playbackinfo->pathname, false);
4415 +            prbuffer = new RingBuffer(playbackURL, false);
4416              prbuffer->SetLiveMode(tvchain);
4417          }
4418  
4419 @@ -4627,7 +4649,8 @@
4420  
4421      normal_speed = new_normal_speed;
4422  
4423 -    activenvp->Play(normal_speed, true);
4424 +    if (!paused)
4425 +        activenvp->Play(normal_speed, true);
4426  
4427      QString text = QString(tr("Time Stretch %1X")).arg(normal_speed);
4428  
4429 @@ -4911,29 +4934,14 @@
4430          }
4431          else if (tvchain && message.left(12) == "LIVETV_CHAIN")
4432          {
4433 -            // Get osdlock, while intended for the OSD this ensures that
4434 -            // the nvp & pipnvp are not deleted while we are using it..
4435 -            while (!osdlock.tryLock() && nvp)
4436 -                usleep(2500);
4437 -
4438              message = message.simplifyWhiteSpace();
4439              QStringList tokens = QStringList::split(" ", message);
4440              if (tokens[1] == "UPDATE")
4441              {
4442 -                if (tvchain && nvp && tokens[2] == tvchain->GetID())
4443 -                {
4444 -                    tvchain->ReloadAll();
4445 -                    if (nvp->GetTVChain())
4446 -                        nvp->CheckTVChain();
4447 -                }
4448 -                if (piptvchain && pipnvp && tokens[2] == piptvchain->GetID())
4449 -                {
4450 -                    piptvchain->ReloadAll();
4451 -                    if (pipnvp->GetTVChain())
4452 -                        pipnvp->CheckTVChain();
4453 -                }
4454 +                tvchainUpdateLock.lock();
4455 +                tvchainUpdate += QDeepCopy<QString>(tokens[2]);
4456 +                tvchainUpdateLock.unlock();
4457              }
4458 -            osdlock.unlock();
4459          }
4460          else if (nvp && message.left(12) == "EXIT_TO_MENU")
4461          {
4462 @@ -4983,7 +4991,7 @@
4463              QDateTime evstartts = QDateTime::fromString(tokens[2], Qt::ISODate);
4464  
4465              if ((playbackinfo->chanid == evchanid) &&
4466 -                (playbackinfo->startts == evstartts))
4467 +                (playbackinfo->recstartts == evstartts))
4468              {
4469                  QString msg = "COMMFLAG_REQUEST ";
4470                  msg += tokens[1] + " " + tokens[2];
4471 @@ -5000,7 +5008,7 @@
4472              QDateTime evstartts = QDateTime::fromString(tokens[2], Qt::ISODate);
4473  
4474              if ((playbackinfo->chanid == evchanid) &&
4475 -                (playbackinfo->startts == evstartts))
4476 +                (playbackinfo->recstartts == evstartts))
4477              {
4478                  QMap<long long, int> newMap;
4479                  QStringList mark;
4480 @@ -6067,9 +6075,22 @@
4481                             "in-progress recordings from the delete "
4482                             "menu.");
4483  
4484 -    MythPopupBox::showOkPopup(
4485 +    if (embedWinID)
4486 +    {
4487 +        VERBOSE(VB_IMPORTANT, errorText);
4488 +    }
4489 +    else if (GetOSD())
4490 +    {
4491 +        dialogname = "infobox";
4492 +        QStringList options("OK");
4493 +        GetOSD()->NewDialogBox(dialogname, errorText, options, 0);
4494 +    }
4495 +    else
4496 +    {
4497 +        MythPopupBox::showOkPopup(
4498              gContext->GetMainWindow(), QObject::tr("Channel Change Error"),
4499              errorText);
4500 +    }
4501  }
4502  
4503  /** \fn TV::PauseLiveTV(void)
4504 Index: mythtv/libs/libmythtv/jobqueue.cpp
4505 ===================================================================
4506 --- mythtv/libs/libmythtv/jobqueue.cpp  (.../tags/release-0-19) (revision 10931)
4507 +++ mythtv/libs/libmythtv/jobqueue.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
4508 @@ -275,6 +275,11 @@
4509                      (hostname != "") &&
4510                      (hostname != m_hostname))
4511                  {
4512 +                    // Setting the status here will prevent us from processing
4513 +                    // any other jobs for this recording until this one is
4514 +                    // completed on the remote host.
4515 +                    jobStatus[key] = status;
4516 +
4517                      message = QString("JobQueue: Skipping '%1' job for chanid "
4518                                        "%2 @ %3, should run on '%4' instead")
4519                                        .arg(JobText(type))
4520 Index: mythtv/libs/libmythtv/dvbdev/dvbdev.c
4521 ===================================================================
4522 --- mythtv/libs/libmythtv/dvbdev/dvbdev.c       (.../tags/release-0-19) (revision 10931)
4523 +++ mythtv/libs/libmythtv/dvbdev/dvbdev.c       (.../branches/release-0-19-fixes)       (revision 10931)
4524 @@ -29,55 +29,79 @@
4525  
4526  const char* dvbdevice(int type, int cardnum)
4527  {
4528 -    char* frontenddev[4] =
4529 +    char* frontenddev[8] =
4530      {
4531          "/dev/dvb/adapter0/frontend0",
4532          "/dev/dvb/adapter1/frontend0",
4533          "/dev/dvb/adapter2/frontend0",
4534 -        "/dev/dvb/adapter3/frontend0"
4535 +        "/dev/dvb/adapter3/frontend0",
4536 +        "/dev/dvb/adapter4/frontend0",
4537 +        "/dev/dvb/adapter5/frontend0",
4538 +        "/dev/dvb/adapter6/frontend0",
4539 +        "/dev/dvb/adapter7/frontend0",
4540      };
4541  
4542 -    char* dvrdev[4] =
4543 +    char* dvrdev[8] =
4544      {
4545          "/dev/dvb/adapter0/dvr0",
4546          "/dev/dvb/adapter1/dvr0",
4547          "/dev/dvb/adapter2/dvr0",
4548 -        "/dev/dvb/adapter3/dvr0"
4549 +        "/dev/dvb/adapter3/dvr0",
4550 +        "/dev/dvb/adapter4/dvr0",
4551 +        "/dev/dvb/adapter5/dvr0",
4552 +        "/dev/dvb/adapter6/dvr0",
4553 +        "/dev/dvb/adapter7/dvr0",
4554      };
4555  
4556 -    char* demuxdev[4] =
4557 +    char* demuxdev[8] =
4558      {
4559          "/dev/dvb/adapter0/demux0",
4560          "/dev/dvb/adapter1/demux0",
4561          "/dev/dvb/adapter2/demux0",
4562 -        "/dev/dvb/adapter3/demux0"
4563 +        "/dev/dvb/adapter3/demux0",
4564 +        "/dev/dvb/adapter4/demux0",
4565 +        "/dev/dvb/adapter5/demux0",
4566 +        "/dev/dvb/adapter6/demux0",
4567 +        "/dev/dvb/adapter7/demux0",
4568      };
4569  
4570 -    char* cadev[4] =
4571 +    char* cadev[8] =
4572      {
4573          "/dev/dvb/adapter0/ca0",
4574          "/dev/dvb/adapter1/ca0",
4575          "/dev/dvb/adapter2/ca0",
4576 -        "/dev/dvb/adapter3/ca0"
4577 +        "/dev/dvb/adapter3/ca0",
4578 +        "/dev/dvb/adapter4/ca0",
4579 +        "/dev/dvb/adapter5/ca0",
4580 +        "/dev/dvb/adapter6/ca0",
4581 +        "/dev/dvb/adapter7/ca0",
4582      };
4583  
4584 -    char* audiodev[4] =
4585 +    char* audiodev[8] =
4586      {
4587          "/dev/dvb/adapter0/audio0",
4588          "/dev/dvb/adapter1/audio0",
4589          "/dev/dvb/adapter2/audio0",
4590 -        "/dev/dvb/adapter3/audio0"
4591 +        "/dev/dvb/adapter3/audio0",
4592 +        "/dev/dvb/adapter4/audio0",
4593 +        "/dev/dvb/adapter5/audio0",
4594 +        "/dev/dvb/adapter6/audio0",
4595 +        "/dev/dvb/adapter7/audio0",
4596      };
4597  
4598 -    char* videodev[4] =
4599 +    char* videodev[8] =
4600      {
4601          "/dev/dvb/adapter0/video0",
4602          "/dev/dvb/adapter1/video0",
4603          "/dev/dvb/adapter2/video0",
4604 -        "/dev/dvb/adapter3/video0"
4605 +        "/dev/dvb/adapter3/video0",
4606 +        "/dev/dvb/adapter4/video0",
4607 +        "/dev/dvb/adapter5/video0",
4608 +        "/dev/dvb/adapter6/video0",
4609 +        "/dev/dvb/adapter7/video0",
4610      };
4611  
4612 -    if (cardnum > 3)
4613 +    if (cardnum > 7)
4614          return 0;
4615  
4616      switch(type)
4617 Index: mythtv/libs/libmythtv/videosource.h
4618 ===================================================================
4619 --- mythtv/libs/libmythtv/videosource.h (.../tags/release-0-19) (revision 10931)
4620 +++ mythtv/libs/libmythtv/videosource.h (.../branches/release-0-19-fixes)       (revision 10931)
4621 @@ -75,6 +75,7 @@
4622  
4623      static CARD_TYPES   GetDVBType(uint device, QString &name, QString &card_type);
4624      static bool         HasDVBCRCBug(uint device);
4625 +    static uint         GetMinSignalMonitoringDelay(uint device);
4626      static QString      GetDefaultInput(uint cardid);
4627  
4628      static bool         IgnoreEncrypted(uint cardid, const QString &inputname);
4629 Index: mythtv/libs/libmythtv/libmythtv.pro
4630 ===================================================================
4631 --- mythtv/libs/libmythtv/libmythtv.pro (.../tags/release-0-19) (revision 10931)
4632 +++ mythtv/libs/libmythtv/libmythtv.pro (.../branches/release-0-19-fixes)       (revision 10931)
4633 @@ -119,6 +119,10 @@
4634  SOURCES += playgroup.cpp
4635  SOURCES += progdetails.cpp
4636  
4637 +# C stuff
4638 +HEADERS += frequencies.h
4639 +SOURCES += frequencies.c
4640 +
4641  using_frontend {
4642      # Recording profile stuff
4643      HEADERS += profilegroup.h
4644 @@ -144,10 +148,10 @@
4645      # On screen display (video output overlay)
4646      HEADERS += osd.h                    osdtypes.h
4647      HEADERS += osdsurface.h             osdlistbtntype.h
4648 -    HEADERS += udpnotify.h 
4649 +    HEADERS += osdimagecache.h          udpnotify.h 
4650      SOURCES += osd.cpp                  osdtypes.cpp
4651      SOURCES += osdsurface.cpp           osdlistbtntype.cpp
4652 -    SOURCES += udpnotify.cpp 
4653 +    SOURCES += osdimagecache.cpp        udpnotify.cpp 
4654  
4655      # Video output
4656      HEADERS += videooutbase.h           videoout_null.h
4657 @@ -303,10 +307,6 @@
4658          }
4659      }
4660  
4661 -    # C stuff
4662 -    HEADERS += frequencies.h
4663 -    SOURCES += frequencies.c
4664 -
4665      DEFINES += USING_BACKEND
4666  }
4667  
4668 Index: mythtv/libs/libmythtv/dvbchannel.cpp
4669 ===================================================================
4670 --- mythtv/libs/libmythtv/dvbchannel.cpp        (.../tags/release-0-19) (revision 10931)
4671 +++ mythtv/libs/libmythtv/dvbchannel.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
4672 @@ -74,14 +74,27 @@
4673   *  \bug Only supports single input cards.
4674   */
4675  DVBChannel::DVBChannel(int aCardNum, TVRec *parent)
4676 -    : QObject(NULL, "DVBChannel"), ChannelBase(parent),
4677 -      diseqc(NULL),    dvbcam(NULL),
4678 -      fd_frontend(-1), cardnum(aCardNum), has_crc_bug(false),
4679 -      currentTID(-1),  first_tune(true)
4680 +    : QObject(NULL, "DVBChannel"),  ChannelBase(parent),
4681 +      diseqc(NULL),                 dvbcam(NULL),
4682 +      fd_frontend(-1),              cardnum(aCardNum),
4683 +      has_crc_bug(false),
4684 +      tuning_delay(0),              sigmon_delay(25),
4685 +      currentTID(-1),               first_tune(true),
4686 +      retune_adj(-10)
4687  {
4688      dvbcam = new DVBCam(cardnum);
4689      bzero(&info, sizeof(info));
4690      has_crc_bug = CardUtil::HasDVBCRCBug(aCardNum);
4691 +
4692 +    QString name(""), type("");
4693 +    CardUtil::GetDVBType(aCardNum, name, type);
4694 +    if ((name == "DiBcom 3000P/M-C DVB-T") ||
4695 +        (name == "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
4696 +    {
4697 +        tuning_delay = 200;
4698 +    }
4699 +
4700 +    sigmon_delay = CardUtil::GetMinSignalMonitoringDelay(aCardNum);
4701  }
4702  
4703  DVBChannel::~DVBChannel()
4704 @@ -367,7 +380,7 @@
4705      }
4706  
4707      bool found = false;
4708 -    int mplexid;
4709 +    int mplexid = 0;
4710      while (query.next())
4711      {
4712          int this_inputid = query.value(4).toInt();
4713 @@ -633,7 +646,8 @@
4714   *   This is used by DVB Channel Scanner, the EIT Parser, and by TVRec.
4715   *
4716   *  \param channel     Info on transport to tune to
4717 - *  \param force_reset If true frequency tuning is done even if not strictly needed
4718 + *  \param force_reset If true, frequency tuning is done
4719 + *                     even if it should not be needed.
4720   *  \return true on success, false on failure
4721   */
4722  bool DVBChannel::Tune(const dvb_channel_t& channel, bool force_reset)
4723 @@ -642,6 +656,8 @@
4724      bool has_diseq = (FE_QPSK == info.type) && diseqc;
4725      struct dvb_frontend_parameters params = channel.tuning.params;
4726  
4727 +    retune_tuning = channel.tuning;
4728 +
4729      if (fd_frontend < 0)
4730      {
4731          ERROR("DVBChannel::Tune: Card not open!");
4732 @@ -669,15 +685,22 @@
4733          // Adjust for Satelite recievers which offset the frequency.
4734          params.frequency = tuned_frequency(channel.tuning, info.type, NULL);
4735  
4736 +        params.frequency = params.frequency + (retune_adj = -retune_adj);
4737 +
4738          if (ioctl(fd_frontend, FE_SET_FRONTEND, &params) < 0)
4739          {
4740              ERRNO("DVBChannel::Tune: "
4741                    "Setting Frontend tuning parameters failed.");
4742              return false;
4743          }
4744 +
4745 +        // Extra delay to add for broken DVB drivers
4746 +        if (tuning_delay)
4747 +            usleep(tuning_delay * 1000);
4748 +
4749          wait_for_backend(fd_frontend, 5 /* msec */);
4750  
4751 -        prev_tuning.params = params;
4752 +        prev_tuning.params = channel.tuning.params;
4753          first_tune = false;
4754      }
4755  
4756 @@ -686,6 +709,24 @@
4757      return true;
4758  }
4759  
4760 +/** \fn DVBChannel::Retune(void)
4761 + *  \brief Calls DVBChannel::Tune() with the last known parameters
4762 + *
4763 + *   This is used to retune DVB-C hardware. DVB-C hardware
4764 + *   sometimes does not successfully tune the first time
4765 + *   despite reports of success from the drivers. This is
4766 + *   probably a hardware problem and not a driver problem
4767 + *   per say, so it is unlikely to be fixed at a lower level.
4768 + *
4769 + *  \return true iff drivers report that tuning was successful
4770 + */
4771 +bool DVBChannel::Retune(void)
4772 +{
4773 +    dvb_channel_t retune_channel;
4774 +    retune_channel.tuning = retune_tuning;
4775 +    return Tune(retune_channel, true);
4776 +}
4777 +
4778  /** \fn DVBChannel::GetTuningParams(DVBTuning& tuning) const
4779   *  \brief Fetches DVBTuning params from driver
4780   *  \return true on success, false on failure
4781 @@ -855,6 +896,9 @@
4782      for (uint i = 0; i < 64 && !tuned; i++)
4783          if (!diseqc->Set(t, reset, tuned))
4784              return false;
4785 -        
4786 +
4787 +    // Wait 10 ms, recommended by Marcus Metzler, see #1552
4788 +    usleep(10 * 1000);
4789 +
4790      return true;
4791  }
4792 Index: mythtv/libs/libmythtv/osdtypes.h
4793 ===================================================================
4794 --- mythtv/libs/libmythtv/osdtypes.h    (.../tags/release-0-19) (revision 10931)
4795 +++ mythtv/libs/libmythtv/osdtypes.h    (.../branches/release-0-19-fixes)       (revision 10931)
4796 @@ -8,6 +8,7 @@
4797  #include <vector>
4798  #include <qobject.h>
4799  #include <qregexp.h>
4800 +#include "osdimagecache.h"
4801  
4802  using namespace std;
4803  
4804 @@ -137,6 +138,8 @@
4805  
4806      QString Name() { return m_name; }
4807  
4808 +    virtual void Reinit(float wmult, float hmult) = 0;
4809 +
4810      virtual void Draw(OSDSurface *surface, int fade, int maxfade, int xoff,
4811                        int yoff) = 0;
4812  
4813 @@ -150,11 +153,11 @@
4814  {
4815    public:
4816      OSDTypeText(const QString &name, TTFFont *font, const QString &text,
4817 -                QRect displayrect);
4818 +                QRect displayrect, float wmult, float hmult);
4819      OSDTypeText(const OSDTypeText &text);
4820     ~OSDTypeText();
4821  
4822 -    void Reinit(float wchange, float hchange);
4823 +    void Reinit(float wmult, float hmult);
4824  
4825      void SetAltFont(TTFFont *font);
4826      void SetUseAlt(bool usealt) { m_usingalt = usealt; }
4827 @@ -190,6 +193,7 @@
4828  
4829      QRect m_displaysize;
4830      QRect m_screensize;
4831 +    QRect m_unbiasedsize;
4832      QString m_message;
4833      QString m_default_msg;
4834  
4835 @@ -231,7 +235,7 @@
4836      virtual ~OSDTypeImage();
4837  
4838      void SetName(const QString &name);
4839 -    void Reinit(float wchange, float hchange, float wmult, float hmult);
4840 +    void Reinit(float wmult, float hmult);
4841  
4842      void LoadImage(const QString &filename, float wmult, float hmult, 
4843                     int scalew = -1, int scaleh = -1);
4844 @@ -239,21 +243,20 @@
4845  
4846      void SetStaticSize(int scalew, int scaleh) { m_scalew = scalew;
4847                                                   m_scaleh = scaleh; }
4848 +    void SetPosition(QPoint pos, float wmult, float hmult);
4849  
4850 -    QPoint DisplayPos() { return m_displaypos; }
4851 -    void SetPosition(QPoint pos) { m_displaypos = pos; }
4852 +    QPoint DisplayPos() const { return m_displaypos;         }
4853 +    QRect  ImageSize()  const { return m_imagesize;          }
4854 +    int    width()      const { return m_imagesize.width();  }
4855 +    int    height()     const { return m_imagesize.height(); }
4856  
4857 -    QRect ImageSize() { return m_imagesize; }
4858 -
4859 -    int width() { return m_imagesize.width(); }
4860 -    int height() { return m_imagesize.height(); }
4861 -
4862      virtual void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, 
4863                        int yoff);
4864  
4865    protected:
4866      QRect m_imagesize;
4867      QPoint m_displaypos;
4868 +    QPoint m_unbiasedpos;
4869  
4870      QString m_filename;
4871  
4872 @@ -270,6 +273,9 @@
4873  
4874      int m_drawwidth;
4875      bool m_onlyusefirst;
4876 +
4877 +    static OSDImageCache  c_cache;
4878 +    OSDImageCacheValue   *m_cacheitem;
4879  };
4880  
4881  class OSDTypePosSlider : public OSDTypeImage
4882 @@ -280,7 +286,7 @@
4883                        int scalew = -1, int scaleh = -1);
4884     ~OSDTypePosSlider();
4885  
4886 -    void Reinit(float wchange, float hchange, float wmult, float hmult);
4887 +    void Reinit(float wmult, float hmult);
4888  
4889      void SetRectangle(QRect rect) { m_displayrect = rect; }
4890      QRect ImageSize() { return m_imagesize; }
4891 @@ -290,6 +296,7 @@
4892  
4893    private:
4894      QRect m_displayrect;
4895 +    QRect m_unbiasedrect;
4896      int m_maxval;
4897      int m_curval;
4898  };
4899 @@ -302,7 +309,7 @@
4900                        int scalew = -1, int scaleh = -1);
4901     ~OSDTypeFillSlider();
4902  
4903 -    void Reinit(float wchange, float hchange, float wmult, float hmult);
4904 +    void Reinit(float wmult, float hmult);
4905  
4906      void SetRectangle(QRect rect) { m_displayrect = rect; }
4907      QRect ImageSize() { return m_imagesize; }
4908 @@ -314,6 +321,7 @@
4909  
4910    private:
4911      QRect m_displayrect;
4912 +    QRect m_unbiasedrect;
4913      int m_maxval;
4914      int m_curval;
4915  };
4916 @@ -327,7 +335,7 @@
4917                        int scalew = -1, int scaleh = -1);
4918     ~OSDTypeEditSlider();
4919  
4920 -    void Reinit(float wchange, float hchange, float wmult, float hmult);
4921 +    void Reinit(float wmult, float hmult);
4922  
4923      void SetRectangle(QRect rect) { m_displayrect = rect; }
4924      QRect ImageSize() { return m_imagesize; }
4925 @@ -339,6 +347,7 @@
4926  
4927    private:
4928      QRect m_displayrect;
4929 +    QRect m_unbiasedrect;
4930      int m_maxval;
4931      int m_curval;
4932  
4933 @@ -360,17 +369,19 @@
4934  class OSDTypeBox : public OSDType
4935  {
4936    public:
4937 -    OSDTypeBox(const QString &name, QRect displayrect); 
4938 +    OSDTypeBox(const QString &name, QRect displayrect,
4939 +               float wmult, float hmult);
4940      OSDTypeBox(const OSDTypeBox &other);
4941     ~OSDTypeBox();
4942  
4943 -    void Reinit(float wchange, float hchange);
4944 -    void SetRect(QRect newrect) { size = newrect; }
4945 +    void Reinit(float wmult, float hmult);
4946 +    void SetRect(QRect newrect, float wmult, float hmult);
4947  
4948      void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
4949  
4950    private:
4951      QRect size;
4952 +    QRect m_unbiasedsize;
4953  };
4954  
4955  class OSDTypePositionIndicator
4956 @@ -403,14 +414,15 @@
4957      OSDTypePositionRectangle(const OSDTypePositionRectangle &other);
4958     ~OSDTypePositionRectangle();
4959  
4960 -    void AddPosition(QRect rect);
4961 +    void AddPosition(QRect rect, float wmult, float hmult);
4962  
4963 -    void Reinit(float wchange, float hchange);
4964 +    void Reinit(float wmult, float hmult);
4965  
4966      void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
4967  
4968    private:
4969 -    vector<QRect> positions; 
4970 +    vector<QRect> positions;
4971 +    vector<QRect> unbiasedpos;
4972  };
4973  
4974  class OSDTypePositionImage : public virtual OSDTypeImage, 
4975 @@ -421,14 +433,17 @@
4976      OSDTypePositionImage(const OSDTypePositionImage &other);
4977     ~OSDTypePositionImage();
4978  
4979 -    void Reinit(float wchange, float hchange, float wmult, float hmult);
4980 +    void Reinit(float wmult, float hmult);
4981  
4982 -    void AddPosition(QPoint pos);
4983 +    void AddPosition(QPoint pos, float wmult, float hmult);
4984  
4985      void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
4986  
4987    private:
4988      vector<QPoint> positions;
4989 +    vector<QPoint> unbiasedpos;
4990 +    float m_wmult;
4991 +    float m_hmult;
4992  };
4993  
4994  class ccText
4995 @@ -445,11 +460,15 @@
4996  {
4997    public:
4998      OSDTypeCC(const QString &name, TTFFont *font, int xoff, int yoff,
4999 -              int dispw, int disph);
5000 +              int dispw, int disph, float wmult, float hmult);
5001     ~OSDTypeCC();
5002  
5003 -    void Reinit(int xoff, int yoff, int dispw, int disph);
5004 +    void Reinit(float wmult, float hmult);
5005  
5006 +    void Reinit(int xoff, int yoff,
5007 +                int dispw, int disph,
5008 +                float wmult, float hmult);
5009 +
5010      void AddCCText(const QString &text, int x, int y, int color, 
5011                     bool teletextmode = false);
5012      void ClearAllCCText();
5013 @@ -464,7 +483,7 @@
5014      vector<ccText *> *m_textlist;
5015      OSDTypeBox *m_box;
5016      int m_ccbackground;
5017 -
5018 +    float m_wmult, m_hmult;
5019      int xoffset, yoffset, displaywidth, displayheight;
5020  };
5021  
5022 Index: mythtv/libs/libmythtv/videoout_xv.h
5023 ===================================================================
5024 --- mythtv/libs/libmythtv/videoout_xv.h (.../tags/release-0-19) (revision 10931)
5025 +++ mythtv/libs/libmythtv/videoout_xv.h (.../branches/release-0-19-fixes)       (revision 10931)
5026 @@ -80,6 +80,8 @@
5027      virtual bool hasVLDAcceleration(void) const
5028          { return XVideoVLD == VideoOutputSubType(); }
5029  
5030 +    void CheckFrameStates(void);
5031 +
5032      static MythCodecID GetBestSupportedCodec(uint width, uint height,
5033                                               uint osd_width, uint osd_height,
5034                                               uint stream_type, int xvmc_chroma,
5035 @@ -141,7 +143,7 @@
5036      static bool IsRendering(VideoFrame* frame);
5037      static void SyncSurface(VideoFrame* frame, int past_future = 0);
5038      static void FlushSurface(VideoFrame* frame);
5039 -    void CheckDisplayedFramesForAvailability(void);
5040 +
5041  #ifdef USING_XVMC 
5042      XvMCOSD* GetAvailableOSD();
5043      void ReturnAvailableOSD(XvMCOSD*);
5044 Index: mythtv/libs/libmythtv/osdimagecache.h
5045 ===================================================================
5046 --- mythtv/libs/libmythtv/osdimagecache.h       (.../tags/release-0-19) (revision 0)
5047 +++ mythtv/libs/libmythtv/osdimagecache.h       (.../branches/release-0-19-fixes)       (revision 10931)
5048 @@ -0,0 +1,74 @@
5049 +// -*- Mode: c++ -*-
5050 +
5051 +// POSIX headers
5052 +#include <stdint.h>
5053 +
5054 +// Qt headers
5055 +#include <qmap.h>
5056 +#include <qrect.h>
5057 +#include <qmutex.h>
5058 +#include <qstring.h>
5059 +#include <qasciicache.h>
5060 +
5061 +class OSDImageCacheValue
5062 +{
5063 +  public:
5064 +    OSDImageCacheValue(QString cacheKey,
5065 +                      unsigned char *yuv,     unsigned char *ybuffer,
5066 +                       unsigned char *ubuffer, unsigned char *vbuffer,
5067 +                       unsigned char *alpha,   QRect imagesize);
5068 +
5069 +    virtual ~OSDImageCacheValue();
5070 +
5071 +    uint    GetSize(void) const { return m_size_in_bytes; }
5072 +    QString GetKey(void)  const { return m_cacheKey;      }
5073 +
5074 +  public:
5075 +    unsigned char *m_yuv;
5076 +    unsigned char *m_ybuffer;
5077 +    unsigned char *m_ubuffer;
5078 +    unsigned char *m_vbuffer;
5079 +    unsigned char *m_alpha;
5080 +    QRect          m_imagesize;
5081 +
5082 +  private:
5083 +    uint           m_size_in_bytes;
5084 +    QString        m_cacheKey;
5085 +};
5086 +
5087 +typedef QAsciiCache<OSDImageCacheValue> img_cache_t;
5088 +
5089 +class OSDImageCache
5090 +{
5091 +  public:
5092 +    OSDImageCache();
5093 +    virtual ~OSDImageCache();
5094 +
5095 +    bool InFileCache(const QString &key) const;
5096 +
5097 +    bool Contains(const QString &key, bool useFile) const;
5098 +
5099 +    OSDImageCacheValue *Get(const QString &key, bool useFile);
5100 +
5101 +    void Insert(OSDImageCacheValue* value);
5102 +
5103 +    void SaveToDisk(const OSDImageCacheValue *value);
5104 +
5105 +    void Reset(void);
5106 +
5107 +    static QString CreateKey(const QString &filename,
5108 +                             float wmult, float hmult,
5109 +                             int scalew,  int scaleh);
5110 +
5111 +    static QString ExtractOriginal(const QString &key);
5112 +
5113 +  private:
5114 +    mutable QMutex m_cacheLock;
5115 +    img_cache_t    m_imageCache;
5116 +    int            m_memHits;
5117 +    int            m_diskHits;
5118 +    int            m_misses;
5119 +
5120 +    /// Limit on the maximum total size of OSD images cached in *memory*.
5121 +    static uint    kMaximumMemoryCacheSize;
5122 +};
5123 Index: mythtv/libs/libmythtv/tv_play.h
5124 ===================================================================
5125 --- mythtv/libs/libmythtv/tv_play.h     (.../tags/release-0-19) (revision 10931)
5126 +++ mythtv/libs/libmythtv/tv_play.h     (.../branches/release-0-19-fixes)       (revision 10931)
5127 @@ -456,7 +456,6 @@
5128      ProgramInfo *recorderPlaybackInfo; ///< info requested from recorder
5129      ProgramInfo *playbackinfo;  ///< info sent in via Playback()
5130      QMutex       pbinfoLock;
5131 -    QString      inputFilename; ///< playbackinfo->pathname
5132      int          playbackLen;   ///< initial playbackinfo->CalculateLength()
5133      ProgramInfo *lastProgram;   ///< last program played with this player
5134      bool         jumpToProgram;
5135 @@ -485,6 +484,8 @@
5136      // LiveTVChain
5137      LiveTVChain *tvchain;
5138      LiveTVChain *piptvchain;
5139 +    QStringList tvchainUpdate;
5140 +    QMutex tvchainUpdateLock;
5141  
5142      // RingBuffers
5143      RingBuffer *prbuffer;
5144 Index: mythtv/libs/libmythtv/videosource.cpp
5145 ===================================================================
5146 --- mythtv/libs/libmythtv/videosource.cpp       (.../tags/release-0-19) (revision 10931)
5147 +++ mythtv/libs/libmythtv/videosource.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
5148 @@ -32,6 +32,7 @@
5149  #include "videosource.h"
5150  #include "datadirect.h"
5151  #include "scanwizard.h"
5152 +#include "frequencies.h"
5153  
5154  #ifdef USING_DVB
5155  #include <linux/dvb/frontend.h>
5156 @@ -156,6 +157,17 @@
5157              (name == "ST STV0299 DVB-S"));         // munges PAT
5158  }
5159  
5160 +uint CardUtil::GetMinSignalMonitoringDelay(uint device)
5161 +{
5162 +    QString name(""), type("");
5163 +    GetDVBType(device, name, type);
5164 +    if (name.find("DVB-S") >= 0)
5165 +        return 300;
5166 +    if (name == "DiBcom 3000P/M-C DVB-T")
5167 +        return 100;
5168 +    return 25;
5169 +}
5170 +
5171  /** \fn CardUtil::GetCardType(uint, QString&, QString&)
5172   *  \brief Returns the card type from the video device
5173   *  \param nCardID   cardid of card to be checked
5174 @@ -574,22 +586,10 @@
5175  {
5176      setLabel(QObject::tr("Channel frequency table"));
5177      addSelection("default");
5178 -    addSelection("us-cable");
5179 -    addSelection("us-bcast");
5180 -    addSelection("us-cable-hrc");
5181 -    addSelection("japan-bcast");
5182 -    addSelection("japan-cable");
5183 -    addSelection("europe-west");
5184 -    addSelection("europe-east");
5185 -    addSelection("italy");
5186 -    addSelection("newzealand");
5187 -    addSelection("australia");
5188 -    addSelection("ireland");
5189 -    addSelection("france");
5190 -    addSelection("china-bcast");
5191 -    addSelection("southafrica");
5192 -    addSelection("argentina");
5193 -    addSelection("australia-optus");
5194 +
5195 +    for (uint i = 0; chanlists[i].name; i++)
5196 +        addSelection(chanlists[i].name);
5197 +
5198      setHelpText(QObject::tr("Use default unless this source uses a "
5199                  "different frequency table than the system wide table "
5200                  "defined in the General settings."));
5201 Index: mythtv/libs/libmythtv/frequencytables.cpp
5202 ===================================================================
5203 --- mythtv/libs/libmythtv/frequencytables.cpp   (.../tags/release-0-19) (revision 10931)
5204 +++ mythtv/libs/libmythtv/frequencytables.cpp   (.../branches/release-0-19-fixes)       (revision 10931)
5205 @@ -283,104 +283,52 @@
5206          "ATSC Channel %1", 70, 809000000, 887000000, 6000000, VSB_8);
5207  #endif // USING_DVB
5208  
5209 -    // USA Cable, QAM 256
5210 -    fmap["atsc_qam256_uscable0"] = new FrequencyTable(
5211 -        "QAM-256 Channel %1",   1, 75000000,1005000000, 6000000, QAM_256);
5212 -    fmap["atsc_qam256_uscable1"] = new FrequencyTable(
5213 -        "QAM-256 Channel T-%1", 7, 10000000,  52000000, 6000000, QAM_256);
5214 +    QString modStr[] = { "vsb8",  "qam256",   "qam128",   "qam64",   };
5215 +    uint    mod[]    = { VSB_8,    QAM_256,    QAM_128,    QAM_64,   };
5216 +    QString desc[]   = { "ATSC ", "QAM-256 ", "QAM-128 ", "QAM-64 ", };
5217  
5218 -    // USA Cable, QAM 256 ch 78+
5219 -    fmap["atsc_qam256_uscablehigh0"] = new FrequencyTable(
5220 -        "QAM-256 Channel %1",  78,472000000,1005000000, 6000000, QAM_256);
5221 +#define FREQ(A,B, C,D, E,F,G, H) \
5222 +    fmap[QString("atsc_%1_us%2").arg(A).arg(B)] = \
5223 +        new FrequencyTable(C+D, E, F, G, 6000000, H);
5224  
5225 -    // USA Cable HRC, QAM 256
5226 -    fmap["atsc_qam256_ushrc0"] = new FrequencyTable(
5227 -        "QAM-256 HRC %1",   1,  73750000,  73750001, 6000000, QAM_256);
5228 -    fmap["atsc_qam256_ushrc1"] = new FrequencyTable(
5229 -        "QAM-256 HRC %1",   2,  55750000,  67750000, 6000000, QAM_256);
5230 -    fmap["atsc_qam256_ushrc2"] = new FrequencyTable(
5231 -        "QAM-256 HRC %1",   5,  79750000,  85750000, 6000000, QAM_256);
5232 -    fmap["atsc_qam256_ushrc3"] = new FrequencyTable(
5233 -        "QAM-256 HRC %1",   7, 175750000, 643750000, 6000000, QAM_256);
5234 -    fmap["atsc_qam256_ushrc4"] = new FrequencyTable(
5235 -        "QAM-256 HRC %1",  95,  91750000, 114000000, 6000000, QAM_256);
5236 -    fmap["atsc_qam256_ushrc5"] = new FrequencyTable(
5237 -        "QAM-256 HRC %1", 100, 649750000, 799750000, 6000000, QAM_256);
5238 -    fmap["atsc_qam256_ushrc6"] = new FrequencyTable(
5239 -        "QAM-256 HRC T-%1", 7,   8175000,  50750000, 6000000, QAM_256);
5240 +    for (uint i = 0; i < 4; i++)
5241 +    {
5242 +        // USA Cable, ch 1 to 155 and T.7 to T.14
5243 +        FREQ(modStr[i], "cable0", desc[i], "Channel %1",
5244 +             1, 75000000, 1005000000, mod[i]);
5245 +        FREQ(modStr[i], "cable1", desc[i], "Channel T-%1",
5246 +             7, 10000000,   52000000, mod[i]);
5247 +        // USA Cable, QAM 256 ch 78 to 155
5248 +        FREQ(modStr[i], "cablehigh0", desc[i], "Channel %1",
5249 +             78, 537000000,1005000000, mod[i]);
5250  
5251 -    // USA Cable HRC, QAM 256 ch 78+
5252 -    fmap["atsc_qam256_ushrchigh0"] = new FrequencyTable(
5253 -        "QAM-256 HRC %1",  78, 601750000, 643750000, 6000000, QAM_256);
5254 -    fmap["atsc_qam256_ushrchigh1"] = new FrequencyTable(
5255 -        "QAM-256 HRC %1", 100, 649750000, 799750000, 6000000, QAM_256);
5256 +        QString std[]   = { "hrc",  "irc"   };
5257 +        QString sdesc[] = { "HRC ", "IRC "  };
5258 +        int     off[]   = { 0,      1250000 };
5259  
5260 +        for (uint j = 0; j < 2; j++)
5261 +        {
5262 +            // USA Cable HRC/IRC, ch 1 to 125
5263 +            FREQ(modStr[i], std[j] + "0", desc[i], sdesc[j] + "%1",
5264 +                 1,   73750000 + off[j],  73750001 + off[j], mod[i]);
5265 +            FREQ(modStr[i], std[j] + "1", desc[i], sdesc[j] + "%1",
5266 +                 2,   55750000 + off[j],  67750000 + off[j], mod[i]);
5267 +            FREQ(modStr[i], std[j] + "2", desc[i], sdesc[j] + "%1",
5268 +                 5,   79750000 + off[j],  85750000 + off[j], mod[i]);
5269 +            FREQ(modStr[i], std[j] + "3", desc[i], sdesc[j] + "%1",
5270 +                 7,  175750000 + off[j], 643750000 + off[j], mod[i]);
5271 +            FREQ(modStr[i], std[j] + "4", desc[i], sdesc[j] + "%1",
5272 +                 95,  91750000 + off[j], 114000000 + off[j], mod[i]);
5273 +            FREQ(modStr[i], std[j] + "5", desc[i], sdesc[j] + "%1",
5274 +                 100, 649750000 + off[j], 799750000 + off[j], mod[i]);
5275 +            FREQ(modStr[i], std[j] + "6", desc[i], sdesc[j] + "T-%1",
5276 +                 7,     8175000 + off[j],  50750000 + off[j], mod[i]);
5277  
5278 -
5279 -    // USA Cable, QAM 128
5280 -    fmap["atsc_qam128_uscable0"] = new FrequencyTable(
5281 -        "QAM-128 Channel %1",   1, 75000000,1005000000, 6000000, QAM_128);
5282 -    fmap["atsc_qam128_uscable1"] = new FrequencyTable(
5283 -        "QAM-128 Channel T-%1", 7, 10000000,  52000000, 6000000, QAM_128);
5284 -
5285 -    // USA Cable, QAM 128 ch 78+
5286 -    fmap["atsc_qam128_uscablehigh0"] = new FrequencyTable(
5287 -        "QAM-128 Channel %1",  78,472000000,1005000000, 6000000, QAM_128);
5288 -
5289 -    // USA Cable HRC, QAM 128
5290 -    fmap["atsc_qam128_ushrc0"] = new FrequencyTable(
5291 -        "QAM-128 HRC %1",   1,  73750000,  73750001, 6000000, QAM_128);
5292 -    fmap["atsc_qam128_ushrc1"] = new FrequencyTable(
5293 -        "QAM-128 HRC %1",   2,  55750000,  67750000, 6000000, QAM_128);
5294 -    fmap["atsc_qam128_ushrc2"] = new FrequencyTable(
5295 -        "QAM-128 HRC %1",   5,  79750000,  85750000, 6000000, QAM_128);
5296 -    fmap["atsc_qam128_ushrc3"] = new FrequencyTable(
5297 -        "QAM-128 HRC %1",   7, 175750000, 643750000, 6000000, QAM_128);
5298 -    fmap["atsc_qam128_ushrc4"] = new FrequencyTable(
5299 -        "QAM-128 HRC %1",  95,  91750000, 114000000, 6000000, QAM_128);
5300 -    fmap["atsc_qam128_ushrc5"] = new FrequencyTable(
5301 -        "QAM-128 HRC %1", 100, 649750000, 799750000, 6000000, QAM_128);
5302 -    fmap["atsc_qam128_ushrc6"] = new FrequencyTable(
5303 -        "QAM-128 HRC T-%1", 7,   8175000,  50750000, 6000000, QAM_128);
5304 -
5305 -    // USA Cable HRC, QAM 128 ch 78+
5306 -    fmap["atsc_qam128_ushrchigh0"] = new FrequencyTable(
5307 -        "QAM-128 HRC %1",  78, 601750000, 643750000, 6000000, QAM_128);
5308 -    fmap["atsc_qam128_ushrchigh1"] = new FrequencyTable(
5309 -        "QAM-128 HRC %1", 100, 649750000, 799750000, 6000000, QAM_128);
5310 -
5311 -
5312 -
5313 -
5314 -    // USA Cable, QAM 64
5315 -    fmap["atsc_qam64_uscable0"] = new FrequencyTable(
5316 -        "QAM-64 Channel %1",    1, 75000000,1005000000, 6000000, QAM_64);
5317 -    fmap["atsc_qam64_uscable1"] = new FrequencyTable(
5318 -        "QAM-64 Channel T-%1",  7, 10000000,  52000000, 6000000, QAM_64);
5319 -
5320 -    // USA Cable, QAM 64 ch 78+
5321 -    fmap["atsc_qam64_uscablehigh0"] = new FrequencyTable(
5322 -        "QAM-64 Channel %1",   78,472000000,1005000000, 6000000, QAM_64);
5323 -
5324 -    // USA Cable HRC, QAM 64
5325 -    fmap["atsc_qam64_ushrc0"] = new FrequencyTable(
5326 -        "QAM-64 HRC %1",   1,  73750000,  73750001, 6000000, QAM_64);
5327 -    fmap["atsc_qam64_ushrc1"] = new FrequencyTable(
5328 -        "QAM-64 HRC %1",   2,  55750000,  67750000, 6000000, QAM_64);
5329 -    fmap["atsc_qam64_ushrc2"] = new FrequencyTable(
5330 -        "QAM-64 HRC %1",   5,  79750000,  85750000, 6000000, QAM_64);
5331 -    fmap["atsc_qam64_ushrc3"] = new FrequencyTable(
5332 -        "QAM-64 HRC %1",   7, 175750000, 643750000, 6000000, QAM_64);
5333 -    fmap["atsc_qam64_ushrc4"] = new FrequencyTable(
5334 -        "QAM-64 HRC %1",  95,  91750000, 114000000, 6000000, QAM_64);
5335 -    fmap["atsc_qam64_ushrc5"] = new FrequencyTable(
5336 -        "QAM-64 HRC %1", 100, 649750000, 799750000, 6000000, QAM_64);
5337 -    fmap["atsc_qam64_ushrc6"] = new FrequencyTable(
5338 -        "QAM-64 HRC T-%1", 7,   8175000,  50750000, 6000000, QAM_64);
5339 -
5340 -    // USA Cable HRC, QAM 64 ch 78+
5341 -    fmap["atsc_qam64_ushrchigh0"] = new FrequencyTable(
5342 -        "QAM-64 HRC %1",  78, 601750000, 643750000, 6000000, QAM_64);
5343 -    fmap["atsc_qam64_ushrchigh1"] = new FrequencyTable(
5344 -        "QAM-64 HRC %1", 100, 649750000, 799750000, 6000000, QAM_64);
5345 +            // USA Cable HRC/IRC, ch 67-125
5346 +            FREQ(modStr[i], std[j] + "high0", desc[i], sdesc[j] + "%1",
5347 +                 67,  535750000 + off[j], 643750000 + off[j], mod[i]);
5348 +            FREQ(modStr[i], std[j] + "high1", desc[i], sdesc[j] + "%1",
5349 +                 100, 649750000 + off[j], 799750000 + off[j], mod[i]);
5350 +        }
5351 +    }
5352  }
5353 Index: mythtv/libs/libmythtv/scanwizardhelpers.h
5354 ===================================================================
5355 --- mythtv/libs/libmythtv/scanwizardhelpers.h   (.../tags/release-0-19) (revision 10931)
5356 +++ mythtv/libs/libmythtv/scanwizardhelpers.h   (.../branches/release-0-19-fixes)       (revision 10931)
5357 @@ -272,11 +272,13 @@
5358    public:
5359      ScanFrequencyTable()
5360      {
5361 -        addSelection(QObject::tr("Broadcast"),        "us",            true);
5362 -        addSelection(QObject::tr("Cable")    +" 78+", "uscablehigh",   false);
5363 -        addSelection(QObject::tr("Cable HRC")+" 78+", "uscablehrchigh",false);
5364 -        addSelection(QObject::tr("Cable"),            "uscable",       false);
5365 -        addSelection(QObject::tr("Cable HRC"),        "ushrc",         false);
5366 +        addSelection(QObject::tr("Broadcast"),        "us",          true);
5367 +        addSelection(QObject::tr("Cable")    +" 78+", "uscablehigh", false);
5368 +        addSelection(QObject::tr("Cable HRC")+" 67+", "ushrchigh",   false);
5369 +        addSelection(QObject::tr("Cable IRC")+" 67+", "usirchigh",   false);
5370 +        addSelection(QObject::tr("Cable"),            "uscable",     false);
5371 +        addSelection(QObject::tr("Cable HRC"),        "ushrc",       false);
5372 +        addSelection(QObject::tr("Cable IRC"),        "usirc",       false);
5373  
5374          setLabel(QObject::tr("Frequency Table"));
5375          setHelpText(QObject::tr("Frequency table to use.") + " " +
5376 Index: mythtv/libs/libmythtv/scanwizard.cpp
5377 ===================================================================
5378 --- mythtv/libs/libmythtv/scanwizard.cpp        (.../tags/release-0-19) (revision 10931)
5379 +++ mythtv/libs/libmythtv/scanwizard.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
5380 @@ -518,7 +518,9 @@
5381                      "SELECT dvb_diseqc_type, diseqc_port,  diseqc_pos, "
5382                      "       lnb_lof_switch,  lnb_lof_hi,   lnb_lof_lo "
5383                      "FROM cardinput, capturecard "
5384 -                    "WHERE capturecard.cardid=%1 and cardinput.sourceid=%2")
5385 +                    "WHERE capturecard.cardid = %1 AND "
5386 +                    "      cardinput.sourceid = %2 AND "
5387 +                    "      capturecard.cardid = cardinput.cardid")
5388                  .arg(parent->captureCard()).arg(nVideoSource));
5389  
5390              if (query.exec() && query.isActive() && query.size() > 0)
5391 Index: mythtv/libs/libmythtv/videoout_xv.cpp
5392 ===================================================================
5393 --- mythtv/libs/libmythtv/videoout_xv.cpp       (.../tags/release-0-19) (revision 10931)
5394 +++ mythtv/libs/libmythtv/videoout_xv.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
5395 @@ -1089,6 +1089,9 @@
5396      bool use_xv = true, use_shm = true;
5397  
5398      QString dec = gContext->GetSetting("PreferredMPEG2Decoder", "ffmpeg");
5399 +    if (dec != "libmpeg2" && height < 720 && 
5400 +        gContext->GetNumSetting("UseXvMCForHDOnly", 0))
5401 +        dec = "ffmpeg";
5402      if (dec == "xvmc")
5403          use_xvmc_idct = use_xvmc = true;
5404      else if (dec == "xvmc-vld")
5405 @@ -1335,40 +1338,39 @@
5406      if (attributes)
5407          X11S(XFree(attributes));
5408  
5409 -    if (xv_draw_colorkey)
5410 +    if (!xv_draw_colorkey)
5411 +        return;
5412 +
5413 +    QString msg = LOC + "Chromakeying not possible with this XVideo port.";
5414 +    X11S(xv_atom = XInternAtom(XJ_disp, "XV_COLORKEY", False));
5415 +    if (xv_atom == None)
5416      {
5417 -        X11S(xv_atom = XInternAtom(XJ_disp, "XV_COLORKEY", False));
5418 -        if (xv_atom != None)
5419 -        {
5420 -            X11S(ret = XvGetPortAttribute(XJ_disp, xv_port, xv_atom, 
5421 -                                          &xv_colorkey));
5422 +        VERBOSE(VB_PLAYBACK, msg);
5423 +        xv_colorkey = 0;
5424 +        return;
5425 +    }
5426  
5427 -            if (ret == Success && xv_colorkey == 0)
5428 -            {
5429 -                const int default_colorkey = 1;
5430 -                X11S(ret = XvSetPortAttribute(XJ_disp, xv_port, xv_atom,
5431 -                                              default_colorkey));
5432 -                if (ret == Success)
5433 -                {
5434 -                    VERBOSE(VB_PLAYBACK, LOC +
5435 -                            "0,0,0 is the only bad color key for MythTV, "
5436 -                            "using "<<default_colorkey<<" instead.");
5437 -                    xv_colorkey = default_colorkey;
5438 -                }
5439 -                ret = Success;
5440 -            }
5441 -
5442 -            if (ret != Success)
5443 -            {
5444 -                VERBOSE(VB_IMPORTANT, LOC_ERR +
5445 -                        "Couldn't get the color key color,"
5446 -                        "\n\t\t\tprobably due to a driver bug or limitation."
5447 -                        "\n\t\t\tYou might not get any video, "
5448 -                        "but we'll try anyway.");
5449 -                xv_colorkey = 0;
5450 -            }
5451 +    X11S(ret = XvGetPortAttribute(XJ_disp, xv_port, xv_atom, &xv_colorkey));
5452 +    if (ret == Success && xv_colorkey == 0)
5453 +    {
5454 +        const int default_colorkey = 1;
5455 +        X11S(ret = XvSetPortAttribute(XJ_disp, xv_port, xv_atom,
5456 +                                      default_colorkey));
5457 +        if (ret == Success)
5458 +        {
5459 +            VERBOSE(VB_PLAYBACK, LOC +
5460 +                    "0,0,0 is the only bad color key for MythTV, "
5461 +                    "using "<<default_colorkey<<" instead.");
5462 +            xv_colorkey = default_colorkey;
5463          }
5464 +        ret = Success;
5465      }
5466 +
5467 +    if (ret != Success)
5468 +    {
5469 +        VERBOSE(VB_PLAYBACK, msg);
5470 +        xv_colorkey = 0;
5471 +    }
5472  }
5473  
5474  bool VideoOutputXv::SetupDeinterlace(bool interlaced,
5475 @@ -1955,86 +1957,75 @@
5476      } while (0)
5477  
5478  void VideoOutputXv::DiscardFrames(bool next_frame_keyframe)
5479 -{ 
5480 +{
5481 +    VERBOSE(VB_PLAYBACK, LOC + "DiscardFrames("<<next_frame_keyframe<<")");
5482      if (VideoOutputSubType() <= XVideo)
5483      {
5484          vbuffers.DiscardFrames(next_frame_keyframe);
5485 +        VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 3: %1 -- done()")
5486 +                .arg(vbuffers.GetStatus()));
5487          return;
5488      }
5489  
5490  #ifdef USING_XVMC
5491      frame_queue_t::iterator it;
5492      frame_queue_t syncs;
5493 -    frame_queue_t ula;
5494 -    frame_queue_t discards;
5495  
5496 -    {
5497 -        vbuffers.begin_lock(kVideoBuffer_displayed); // Lock X
5498 -        VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 1: %1")
5499 -                .arg(vbuffers.GetStatus()));
5500 -        vbuffers.end_lock(); // Lock X
5501 -    }
5502 +    // Print some debugging
5503 +    vbuffers.begin_lock(kVideoBuffer_displayed); // Lock X
5504 +    VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 1: %1")
5505 +            .arg(vbuffers.GetStatus()));
5506 +    vbuffers.end_lock(); // Lock X
5507  
5508 -    CheckDisplayedFramesForAvailability();
5509 -
5510 +    // Finish rendering all these surfaces and move them
5511 +    // from the used queue to the displayed queue.
5512 +    // This allows us to reuse these surfaces, if they
5513 +    // get moved to the used list in CheckFrameStates().
5514 +    // This will only happen if avlib isn't using them
5515 +    // either and they are not currently being displayed.
5516 +    vbuffers.begin_lock(kVideoBuffer_displayed); // Lock Y
5517 +    DQ_COPY(syncs, kVideoBuffer_used);
5518 +    for (it = syncs.begin(); it != syncs.end(); ++it)
5519      {
5520 -        vbuffers.begin_lock(kVideoBuffer_displayed); // Lock Y
5521 -
5522 -        DQ_COPY(syncs, kVideoBuffer_displayed);
5523 -        DQ_COPY(syncs, kVideoBuffer_pause);
5524 -        for (it = syncs.begin(); it != syncs.end(); ++it)
5525 -        {
5526 -            SyncSurface(*it, -1); // sync past
5527 -            SyncSurface(*it, +1); // sync future
5528 -            SyncSurface(*it,  0); // sync current
5529 -            //GetRender(*it)->p_past_surface   = NULL;
5530 -            //GetRender(*it)->p_future_surface = NULL;
5531 -        }
5532 -        VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 2: %1")
5533 -                .arg(vbuffers.GetStatus()));
5534 -#if 0
5535 -        // Remove inheritence of all frames not in displayed or pause
5536 -        DQ_COPY(ula, kVideoBuffer_used);
5537 -        DQ_COPY(ula, kVideoBuffer_limbo);
5538 -        DQ_COPY(ula, kVideoBuffer_avail);
5539 -        
5540 -        for (it = ula.begin(); it != ula.end(); ++it)
5541 -            vbuffers.RemoveInheritence(*it);
5542 -#endif
5543 -
5544 -        VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 3: %1")
5545 -                .arg(vbuffers.GetStatus()));
5546 -        // create discard frame list
5547 -        DQ_COPY(discards, kVideoBuffer_used);
5548 -        DQ_COPY(discards, kVideoBuffer_limbo);
5549 -
5550 -        vbuffers.end_lock(); // Lock Y
5551 +        SyncSurface(*it, -1); // sync past
5552 +        SyncSurface(*it, +1); // sync future
5553 +        SyncSurface(*it,  0); // sync current
5554 +        vbuffers.safeEnqueue(kVideoBuffer_displayed, *it);
5555      }
5556 +    syncs.clear();
5557 +    vbuffers.end_lock(); // Lock Y
5558  
5559 -    for (it = discards.begin(); it != discards.end(); ++it)
5560 -        DiscardFrame(*it);
5561 +    CheckFrameStates();
5562  
5563 +    // If the next frame is a keyframe we can clear out a lot more...
5564 +    if (next_frame_keyframe)
5565      {
5566          vbuffers.begin_lock(kVideoBuffer_displayed); // Lock Z
5567  
5568 -        syncs.clear();
5569 -        DQ_COPY(syncs, kVideoBuffer_displayed);
5570 -        DQ_COPY(syncs, kVideoBuffer_pause);
5571 +        // Move all the limbo and pause frames to displayed
5572 +        DQ_COPY(syncs, kVideoBuffer_limbo);
5573          for (it = syncs.begin(); it != syncs.end(); ++it)
5574          {
5575              SyncSurface(*it, -1); // sync past
5576              SyncSurface(*it, +1); // sync future
5577              SyncSurface(*it,  0); // sync current
5578 -            //GetRender(*it)->p_past_surface   = NULL;
5579 -            //GetRender(*it)->p_future_surface = NULL;
5580 +            vbuffers.safeEnqueue(kVideoBuffer_displayed, *it);
5581          }
5582  
5583 -        VERBOSE(VB_PLAYBACK, LOC +
5584 -                QString("DiscardFrames() 4: %1 -- done() ")
5585 +        VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 2: %1")
5586                  .arg(vbuffers.GetStatus()));
5587 -        
5588 +
5589          vbuffers.end_lock(); // Lock Z
5590 +
5591 +        // Now call CheckFrameStates() to remove inheritence and
5592 +        // move the surfaces to the used list if possible (i.e.
5593 +        // if avlib is not using them and they are not currently
5594 +        // being displayed on screen).
5595 +        CheckFrameStates();
5596      }
5597 +    VERBOSE(VB_PLAYBACK, LOC + QString("DiscardFrames() 3: %1 -- done()")
5598 +            .arg(vbuffers.GetStatus()));
5599 +        
5600  #endif // USING_XVMC
5601  }
5602  
5603 @@ -2071,7 +2062,7 @@
5604          if (osdframe)
5605              DiscardFrame(osdframe);
5606      }
5607 -    CheckDisplayedFramesForAvailability();
5608 +    CheckFrameStates();
5609  #endif
5610  }
5611  
5612 @@ -2411,7 +2402,7 @@
5613              DiscardFrame(vbuffers.dequeue(kVideoBuffer_pause));
5614      }
5615      // clear any displayed frames not on screen
5616 -    CheckDisplayedFramesForAvailability();
5617 +    CheckFrameStates();
5618  
5619      // unlock the frame[s]
5620      vbuffers.UnlockFrame(osdframe, "ShowXvMC -- OSD");
5621 @@ -2659,7 +2650,7 @@
5622                      .arg(vbuffers.size(kVideoBuffer_pause)));
5623              while (vbuffers.size(kVideoBuffer_pause))
5624                  DiscardFrame(vbuffers.dequeue(kVideoBuffer_pause));
5625 -            CheckDisplayedFramesForAvailability();
5626 +            CheckFrameStates();
5627          } else if (1 == vbuffers.size(kVideoBuffer_pause))
5628          {
5629              VideoFrame *frame = vbuffers.dequeue(kVideoBuffer_used);
5630 @@ -2791,7 +2782,7 @@
5631              // If there are no available buffer, try to toss old
5632              // displayed frames.
5633              if (!vbuffers.size(kVideoBuffer_avail))
5634 -                CheckDisplayedFramesForAvailability();
5635 +                CheckFrameStates();
5636  
5637              // If tossing doesn't work try hiding showing frames,
5638              // then tossing displayed frames.
5639 @@ -2805,7 +2796,7 @@
5640                                               GetRender(*it)->p_surface));
5641                  vbuffers.end_lock();
5642  
5643 -                CheckDisplayedFramesForAvailability();
5644 +                CheckFrameStates();
5645              }
5646  
5647              // If there is an available buffer grab it.
5648 @@ -3013,7 +3004,7 @@
5649      return -1;
5650  }
5651  
5652 -void VideoOutputXv::CheckDisplayedFramesForAvailability(void)
5653 +void VideoOutputXv::CheckFrameStates(void)
5654  {
5655  #ifdef USING_XVMC
5656      frame_queue_t::iterator it;
5657 @@ -3084,6 +3075,13 @@
5658                      }
5659                  }
5660              }
5661 +            else if (vbuffers.contains(kVideoBuffer_decode, pframe))
5662 +            {
5663 +                VERBOSE(VB_PLAYBACK, LOC + QString(
5664 +                            "Frame %1 is in use by avlib and so is "
5665 +                            "being held for later discarding.")
5666 +                        .arg(DebugString(pframe, true)));
5667 +            }
5668              else
5669              {
5670                  vbuffers.RemoveInheritence(pframe);
5671 Index: mythtv/libs/libmythtv/signalmonitor.h
5672 ===================================================================
5673 --- mythtv/libs/libmythtv/signalmonitor.h       (.../tags/release-0-19) (revision 10931)
5674 +++ mythtv/libs/libmythtv/signalmonitor.h       (.../branches/release-0-19-fixes)       (revision 10931)
5675 @@ -7,6 +7,10 @@
5676  // C headers
5677  #include <pthread.h>
5678  
5679 +// C++ headers
5680 +#include <algorithm>
5681 +using namespace std;
5682 +
5683  // Qt headers
5684  #include <qobject.h>
5685  #include <qmutex.h>
5686 @@ -125,7 +129,8 @@
5687       *   Defaults to 25 milliseconds.
5688       *  \param msec Milliseconds between signal monitoring events.
5689       */
5690 -    void SetUpdateRate(int msec) { update_rate = msec; }
5691 +    void SetUpdateRate(int msec)
5692 +        { update_rate = max(msec, (int)minimum_update_rate); }
5693  
5694    public slots:
5695      virtual void deleteLater(void);
5696 @@ -164,6 +169,7 @@
5697      int          capturecardnum;
5698      uint         flags;
5699      int          update_rate;
5700 +    uint         minimum_update_rate;
5701      bool         running;
5702      bool         exit;
5703      bool         update_done;
5704 Index: mythtv/libs/libmythtv/RingBuffer.h
5705 ===================================================================
5706 --- mythtv/libs/libmythtv/RingBuffer.h  (.../tags/release-0-19) (revision 10931)
5707 +++ mythtv/libs/libmythtv/RingBuffer.h  (.../branches/release-0-19-fixes)       (revision 10931)
5708 @@ -91,6 +91,7 @@
5709      long long GetTotalReadPosition(void);
5710  
5711      long long SetAdjustFilesize(void);
5712 +    void SetTimeout(bool fast) { oldfile = fast; }
5713      
5714    protected:
5715      static void *StartReader(void *type);
5716 Index: mythtv/libs/libmythtv/dvbtypes.cpp
5717 ===================================================================
5718 --- mythtv/libs/libmythtv/dvbtypes.cpp  (.../tags/release-0-19) (revision 10931)
5719 +++ mythtv/libs/libmythtv/dvbtypes.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
5720 @@ -202,7 +202,7 @@
5721  {
5722     {"TRANSMISSION_MODE_AUTO",TRANSMISSION_MODE_AUTO},
5723     {"TRANSMISSION_MODE_2K",TRANSMISSION_MODE_2K},
5724 -   {"TRANSMISSION_MODE_8K",TRANSMISSION_MODE_2K},
5725 +   {"TRANSMISSION_MODE_8K",TRANSMISSION_MODE_8K},
5726     {NULL,TRANSMISSION_MODE_AUTO},
5727  };
5728  
5729 @@ -210,7 +210,7 @@
5730  {
5731     {"999",TRANSMISSION_MODE_AUTO},
5732     {"2",TRANSMISSION_MODE_2K},
5733 -   {"8",TRANSMISSION_MODE_2K},
5734 +   {"8",TRANSMISSION_MODE_8K},
5735     {NULL,TRANSMISSION_MODE_AUTO},
5736  };
5737  
5738 @@ -218,7 +218,7 @@
5739  {
5740     {"auto",TRANSMISSION_MODE_AUTO},
5741     {"2",TRANSMISSION_MODE_2K},
5742 -   {"8",TRANSMISSION_MODE_2K},
5743 +   {"8",TRANSMISSION_MODE_8K},
5744     {NULL,TRANSMISSION_MODE_AUTO},
5745  };
5746  
5747 Index: mythtv/libs/libmythtv/mpegrecorder.cpp
5748 ===================================================================
5749 --- mythtv/libs/libmythtv/mpegrecorder.cpp      (.../tags/release-0-19) (revision 10931)
5750 +++ mythtv/libs/libmythtv/mpegrecorder.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
5751 @@ -363,9 +363,9 @@
5752  
5753      if (ioctl(chanfd, VIDIOC_S_CTRL, &ctrl) < 0)
5754      {
5755 -        cerr << "Error setting codec params\n";
5756 +        cerr << "Warning, unable to set recording volume\n";
5757 +        cerr << "This is normal if you have an AVerMedia M179 card.\n";
5758          perror("VIDIOC_S_CTRL:");
5759 -        return false;
5760      }
5761  
5762      if (vbimode) {
5763 @@ -481,6 +481,9 @@
5764                  continue;
5765              case 0:
5766                  printf("select timeout - ivtv driver has stopped responding\n");
5767 +                if(close(readfd) != 0)
5768 +                    perror("close");
5769 +                readfd = -1; // Force PVR card to be reopened on next iteration
5770                  continue;
5771             default: break;
5772          }
5773 Index: mythtv/libs/libmythtv/ivtvdecoder.cpp
5774 ===================================================================
5775 --- mythtv/libs/libmythtv/ivtvdecoder.cpp       (.../tags/release-0-19) (revision 10931)
5776 +++ mythtv/libs/libmythtv/ivtvdecoder.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
5777 @@ -270,7 +270,9 @@
5778  
5779      GetNVP()->SetVideoParams(720 /*width*/, (ntsc) ? 480 : 576 /*height*/,
5780                               (ntsc) ? 29.97f : 25.0f, keyframedist, 1.33);
5781 -     
5782 +
5783 +    fps = (ntsc) ? 29.97f : 25.0f; // save for later length calculations
5784 +
5785      ringBuffer->UpdateRawBitrate(8000);
5786  
5787      if (m_playbackinfo || livetv || watchingrecording)
5788 Index: mythtv/libs/libmythtv/dvbsignalmonitor.cpp
5789 ===================================================================
5790 --- mythtv/libs/libmythtv/dvbsignalmonitor.cpp  (.../tags/release-0-19) (revision 10931)
5791 +++ mythtv/libs/libmythtv/dvbsignalmonitor.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
5792 @@ -100,6 +100,10 @@
5793  #undef DVB_IO
5794      AddFlags(newflags);
5795      DBG_SM("constructor()", QString("initial flags 0x%1").arg(newflags,0,16));
5796 +
5797 +    minimum_update_rate = _channel->GetMinSignalMonitorDelay();
5798 +    if (minimum_update_rate > 30)
5799 +        usleep(minimum_update_rate * 1000);
5800  }
5801  
5802  /** \fn DVBSignalMonitor::~DVBSignalMonitor()
5803 @@ -348,8 +352,8 @@
5804  
5805          len += remainder;
5806          remainder = GetStreamData()->ProcessData(buffer, len);
5807 -        if (remainder > 0) // leftover bytes
5808 -            memmove(buffer, &(buffer[buffer_size - remainder]), remainder);
5809 +        if (remainder > 0 && (len > remainder)) // leftover bytes
5810 +            memmove(buffer, &(buffer[len - remainder]), remainder);
5811      }
5812      VERBOSE(VB_CHANNEL, LOC + "RunTableMonitorTS(): " + "shutdown");
5813  
5814 Index: mythtv/libs/libmythtv/tv_rec.cpp
5815 ===================================================================
5816 --- mythtv/libs/libmythtv/tv_rec.cpp    (.../tags/release-0-19) (revision 10931)
5817 +++ mythtv/libs/libmythtv/tv_rec.cpp    (.../branches/release-0-19-fixes)       (revision 10931)
5818 @@ -130,6 +130,11 @@
5819        // RingBuffer info
5820        ringBuffer(NULL), rbFilePrefix(""), rbFileExt("mpg")
5821  {
5822 +      // Retune stuff
5823 +      retune_timer = new TuningTimer();
5824 +      retune_timer->setTimeout(10000);
5825 +      retune_timer->start();
5826 +      retune_requests = 0;
5827  }
5828  
5829  /** \fn TVRec::Init()
5830 @@ -3221,6 +3226,8 @@
5831   */
5832  void TVRec::HandleTuning(void)
5833  {
5834 +    bool handle_done = false;
5835 +
5836      if (tuningRequests.size())
5837      {
5838          const TuningRequest *request = &tuningRequests.front();
5839 @@ -3232,7 +3239,12 @@
5840                                kFlagEITScan|kFlagAntennaAdjust))
5841          {
5842              if (!recorder)
5843 +            {
5844                  TuningFrequency(*request);
5845 +                retune_timer->restart();
5846 +                retune_timer->addMSecs(1);
5847 +                retune_requests = 0;
5848 +            }
5849              else
5850                  SetFlags(kFlagWaitingForRecPause);
5851          }
5852 @@ -3261,15 +3273,29 @@
5853      if (HasFlags(kFlagWaitingForSignal))
5854      {
5855          if (!TuningSignalCheck())
5856 -            return;
5857 +            handle_done = true;
5858      }
5859  
5860      if (HasFlags(kFlagWaitingForSIParser))
5861      {
5862          if (!TuningPMTCheck())
5863 -            return;
5864 +            handle_done = true;
5865      }
5866  
5867 +#ifdef USING_DVB
5868 +    // Just because we have signal, we may not have the right transponder
5869 +    if ((HasFlags(kFlagWaitingForSignal) ||
5870 +         HasFlags(kFlagWaitingForSIParser)) &&
5871 +        (!retune_timer->elapsed() && (retune_requests < 30)))
5872 +    {
5873 +        RetuneChannel();
5874 +        retune_requests++;
5875 +    }
5876 +#endif // USING_DVB
5877 +
5878 +    if (handle_done)
5879 +        return;
5880 +
5881      if (HasFlags(kFlagNeedToStartRecorder))
5882      { 
5883          if (recorder)
5884 @@ -3354,6 +3380,19 @@
5885      ClearFlags(kFlagPendingActions);
5886  }
5887  
5888 +/** \fn TVRec::RetuneChannel(void)
5889 + *  \brief Retunes a DVB channel
5890 + *  \return DVBChannel::Retune() or false if ifndef USING_DVB
5891 + */
5892 +bool TVRec::RetuneChannel(void)
5893 +{
5894 +#ifdef USING_DVB
5895 +    if (GetDVBChannel())
5896 +        return GetDVBChannel()->Retune();
5897 +#endif // USING_DVB
5898 +    return false;
5899 +}
5900 +
5901  /** \fn TVRec::TuningFrequency(const TuningRequest&)
5902   *  \brief Performs initial tuning required for any tuning event.
5903   *
5904 Index: mythtv/libs/libmythtv/videooutbase.h
5905 ===================================================================
5906 --- mythtv/libs/libmythtv/videooutbase.h        (.../tags/release-0-19) (revision 10931)
5907 +++ mythtv/libs/libmythtv/videooutbase.h        (.../branches/release-0-19-fixes)       (revision 10931)
5908 @@ -256,6 +256,8 @@
5909      ///        onto the queue of frames ready for decoding onto.
5910      virtual void DiscardFrames(bool kf) { vbuffers.DiscardFrames(kf); }
5911  
5912 +    virtual void CheckFrameStates(void) { }
5913 +
5914      /// \bug not implemented correctly. vpos is not updated.
5915      VideoFrame *GetLastDecodedFrame(void) { return vbuffers.GetLastDecodedFrame(); }
5916  
5917 Index: mythtv/libs/libmythtv/osdimagecache.cpp
5918 ===================================================================
5919 --- mythtv/libs/libmythtv/osdimagecache.cpp     (.../tags/release-0-19) (revision 0)
5920 +++ mythtv/libs/libmythtv/osdimagecache.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
5921 @@ -0,0 +1,296 @@
5922 +// -*- Mode: c++ -*-
5923 +/** OSDImageCache
5924 + *  Copyright (c) 2006 by Pekka Jääskeläinen, Daniel Thor Kristjansson
5925 + *  Distributed as part of MythTV under GPL v2 and later.
5926 + */
5927 +
5928 +// POSIX headers
5929 +#include <stdint.h>
5930 +
5931 +// Qt headers
5932 +#include <qdir.h>
5933 +#include <qfile.h>
5934 +#include <qfileinfo.h>
5935 +#include <qdatastream.h>
5936 +#include <qdeepcopy.h>
5937 +
5938 +// MythTV headers
5939 +#include "mythcontext.h"
5940 +#include "osdimagecache.h"
5941 +
5942 +// Print statistics of OSD image access in the destructor of OSDImageCache
5943 +//#define PRINT_OSD_IMAGE_CACHE_STATS
5944 +
5945 +#define LOC QString("OSDImgCache: ")
5946 +#define LOC_ERR QString("OSDImgCache, Error: ")
5947 +
5948 +uint OSDImageCache::kMaximumMemoryCacheSize = 5 * 1024 * 1024;
5949 +
5950 +/** \fn OSDImageCacheValue::OSDImageCacheValue(unsigned char*,unsigned char*,unsighed char*,unsigned char*,unsighed char*, QRect)
5951 + *  \brief The main constructor that takes the image data as arguments.
5952 + *
5953 + *   The image data becomes property of the OSDImageCacheValue 
5954 + *   and will be deleted by it.
5955 + */
5956 +OSDImageCacheValue::OSDImageCacheValue(
5957 +    QString cacheKey,
5958 +    unsigned char *yuv,     unsigned char *ybuffer,
5959 +    unsigned char *ubuffer, unsigned char *vbuffer,
5960 +    unsigned char *alpha,   QRect imagesize) :
5961 +    m_yuv(yuv),         m_ybuffer(ybuffer),
5962 +    m_ubuffer(ubuffer), m_vbuffer(vbuffer),
5963 +    m_alpha(alpha),     m_imagesize(imagesize),
5964 +    m_cacheKey(QDeepCopy<QString>(cacheKey))
5965 +{
5966 +    uint yuv_size = m_imagesize.width() * m_imagesize.height() * 3 / 2;
5967 +    m_size_in_bytes =
5968 +        (sizeof(OSDImageCacheValue)) + yuv_size + 
5969 +        (m_imagesize.width() * m_imagesize.height());
5970 +}
5971 +
5972 +/** \fn OSDImageCacheValue::~OSDImageCacheValue()
5973 + *  \brief Destructor, frees the cached bitmaps.
5974 + */
5975 +OSDImageCacheValue::~OSDImageCacheValue()
5976 +{
5977 +    delete [] m_yuv;
5978 +    m_yuv = NULL;
5979 +    delete [] m_alpha;
5980 +    m_alpha = NULL;
5981 +}
5982 +
5983 +/** \fn OSDImageCache::OSDImageCache()
5984 + *  \brief Constructor, initializes the internal cache structures.
5985 + */
5986 +OSDImageCache::OSDImageCache() : 
5987 +    m_cacheLock(true), m_imageCache(kMaximumMemoryCacheSize, 50),
5988 +    m_memHits(0), m_diskHits(0), m_misses(0) 
5989 +{
5990 +    // When the cache gets too large, items are
5991 +    // automatically deleted from it in LRU order.
5992 +    m_imageCache.setAutoDelete(true);
5993 +}
5994 +
5995 +/** \fn OSDImageCache::~OSDImageCache()
5996 + *  \brief Destructor, frees all cached OSD images.
5997 + */
5998 +OSDImageCache::~OSDImageCache() 
5999 +{
6000 +#ifdef PRINT_OSD_IMAGE_CACHE_STATS
6001 +    int totalAccess = m_memHits + m_diskHits + m_misses;
6002 +    if (totalAccess == 0)
6003 +        return;
6004 +
6005 +#define LOG_PREFIX "OSDImageCache: "
6006 +    VERBOSE(VB_IMPORTANT, LOC << " Statistics: " << endl
6007 +            << LOG_PREFIX << m_imageCache.totalCost() << " bytes in cache\n" 
6008 +            << LOG_PREFIX << " memory hits: " 
6009 +            << m_memHits << ", " << m_memHits*100.0/totalAccess << "%\n"
6010 +            << LOG_PREFIX << "   disk hits: " 
6011 +            << m_diskHits << ", " << m_diskHits*100.0/totalAccess << "%\n"
6012 +            << LOG_PREFIX << "      misses: " 
6013 +            << m_misses << ", " << m_misses*100.0/totalAccess << "%");
6014 +#undef LOC_PREFIX
6015 +#endif
6016 +    Reset();
6017 +}
6018 +
6019 +/** \fn OSDImageCache::Contains(const QString&,bool)
6020 + *  \brief Returns true if cached OSD image was found in the cache.
6021 + *
6022 + *  \param key The key for this image.
6023 + *  \param useFile If true, also look from the disk cache.
6024 + */
6025 +bool OSDImageCache::Contains(const QString &key, bool useFile) const
6026 +{
6027 +    QMutexLocker locker(&m_cacheLock);
6028 +
6029 +    if (m_imageCache.find(key) != NULL)
6030 +        return true;
6031 +
6032 +    if (!useFile)
6033 +        return false;
6034 +
6035 +    return InFileCache(key);
6036 +}
6037 +
6038 +bool OSDImageCache::InFileCache(const QString &key) const
6039 +{
6040 +    // check if cache file exists
6041 +    QDir dir(MythContext::GetConfDir() + "/osdcache/");
6042 +    QFileInfo cFile(dir.path() + "/" + key);
6043 +    if (!cFile.exists() || !cFile.isReadable())
6044 +        return false;
6045 +
6046 +    // check if backing file exists
6047 +    QString orig = ExtractOriginal(key);
6048 +    if (orig.isEmpty())
6049 +        return false;
6050 +
6051 +    QFileInfo oFile(orig);
6052 +    if (!oFile.exists())
6053 +    {
6054 +        VERBOSE(VB_IMPORTANT, LOC + QString("Can't find '%1'").arg(orig));
6055 +        return false;
6056 +    }
6057 +
6058 +    // if cache file is older than backing file, delete cache file
6059 +    if (cFile.lastModified() < oFile.lastModified())
6060 +    {
6061 +        cFile.dir().remove(cFile.baseName(true));
6062 +        return false;
6063 +    } 
6064 +
6065 +    return true;
6066 +}
6067 +
6068 +/** \fn OSDImageCache::Get(const QString&,bool)
6069 + *  \brief Returns OSD image data from cache.
6070 + *
6071 + *   This also removes the image from the cache so it won't be deleted
6072 + *   while in use. The deletion of the taken item becomes responsibility
6073 + *   of the client. Returns NULL if item with the given key is not found.
6074 + *
6075 + *  \param key The key for this image.
6076 + *  \param useFile If true, also check the disk cache.
6077 + */
6078 +OSDImageCacheValue *OSDImageCache::Get(const QString &key, bool useFile)
6079 +{
6080 +    QMutexLocker locker(&m_cacheLock);
6081 +    OSDImageCacheValue* item = m_imageCache.find(key);
6082 +    if (item)
6083 +    {
6084 +        m_memHits++;
6085 +        return m_imageCache.take(key);
6086 +    }
6087 +
6088 +    if (!useFile || !InFileCache(key))
6089 +    {
6090 +        m_misses++;
6091 +        return NULL;
6092 +    }
6093 +
6094 +    QDir dir(MythContext::GetConfDir() + "/osdcache/");
6095 +    QFile cacheFile(dir.path() + "/" + key);
6096 +    cacheFile.open(IO_ReadOnly);
6097 +    uint32_t imwidth  = 0;
6098 +    uint32_t imheight = 0;
6099 +
6100 +    QDataStream stream(&cacheFile);
6101 +    stream >> imwidth >> imheight;   
6102 +
6103 +    uint yuv_size = imwidth * imheight * 3 / 2;
6104 +    uint tot_size = (sizeof(imwidth) * 2) + yuv_size + (imwidth * imheight);
6105 +
6106 +    if (cacheFile.size() != tot_size)
6107 +    {
6108 +        VERBOSE(VB_IMPORTANT, LOC_ERR + key + " wrong cache file size!"
6109 +                << cacheFile.size() << " != " << tot_size);
6110 +        return NULL;
6111 +    }
6112 +
6113 +    unsigned char *yuv = new unsigned char[yuv_size];
6114 +    unsigned char *alpha = new unsigned char[imwidth * imheight];
6115 +    stream.readRawBytes((char*)yuv,   yuv_size);
6116 +    stream.readRawBytes((char*)alpha, imwidth * imheight);
6117 +    cacheFile.close();
6118 +
6119 +    OSDImageCacheValue* value = 
6120 +        new OSDImageCacheValue(
6121 +            key,
6122 +            yuv, yuv,
6123 +            yuv + (imwidth * imheight),
6124 +            yuv + (imwidth * imheight * 5 / 4),
6125 +            alpha, QRect(0, 0, imwidth, imheight));
6126 +
6127 +    m_diskHits++;
6128 +    return value;
6129 +}
6130 +
6131 +/** \fn OSDImageCache::Insert(OSDImageCacheValue*)
6132 + *  \brief Inserts OSD image data to memory cache.
6133 + *
6134 + *   The item becomes property of the OSDImageCache and may be 
6135 + *   deleted any time by it.
6136 + *
6137 + *  \param value The cache item.
6138 + */
6139 +void OSDImageCache::Insert(OSDImageCacheValue *value)
6140 +{
6141 +    if (!value)
6142 +        return;
6143 +
6144 +    QMutexLocker locker(&m_cacheLock);
6145 +    if (!m_imageCache.insert(value->GetKey(), value, value->GetSize()))
6146 +    {
6147 +        VERBOSE(VB_IMPORTANT, 
6148 +                LOC_ERR + QString("inserting image to memory cache failed"));
6149 +    }
6150 +}
6151 +
6152 +
6153 +/** \fn OSDImageCache::SaveToDisk(const OSDImageCacheValue*)
6154 + *  \brief Saves OSD image data to disk cache.
6155 + *
6156 + *   Item is not written to the memory cache, i.e., it stays as
6157 + *   property of the client.
6158 + *
6159 + *  \param value The cached OSD image to save.
6160 + */
6161 +void OSDImageCache::SaveToDisk(const OSDImageCacheValue *value)
6162 +{
6163 +    if (InFileCache(value->GetKey()))
6164 +        return;
6165 +
6166 +    QDir dir(MythContext::GetConfDir() + "/osdcache/");
6167 +    if (!dir.exists() && !dir.mkdir(dir.path()))
6168 +    {
6169 +        VERBOSE(VB_IMPORTANT, LOC_ERR + "Creating osdcache directory failed.");
6170 +        return;
6171 +    }
6172 +
6173 +    QFile cacheFile(dir.path() + "/" + value->GetKey());
6174 +    if (!cacheFile.open(IO_WriteOnly | IO_Truncate))
6175 +    {
6176 +        VERBOSE(VB_IMPORTANT, LOC_ERR + "Creating osdcache file failed.");
6177 +        return;
6178 +    }
6179 +
6180 +    uint32_t imwidth  = value->m_imagesize.width();
6181 +    uint32_t imheight = value->m_imagesize.height();
6182 +    uint     yuv_size = imwidth * imheight * 3 / 2;
6183 +
6184 +    QDataStream stream(&cacheFile);
6185 +    stream << imwidth << imheight;   
6186 +    stream.writeRawBytes((const char*)value->m_yuv, yuv_size);
6187 +    stream.writeRawBytes((const char*)value->m_alpha, imwidth * imheight);
6188 +    cacheFile.close();
6189 +}
6190 +
6191 +/** \fn OSDImageCache::CreateKey(const QString&,float,float,int,int)
6192 + *  \brief Generates a cache key from the given OSD image parameters.
6193 + *
6194 + *   The returned key is a string that can be safely used as a file name.
6195 + */
6196 +QString OSDImageCache::CreateKey(const QString &filename, float wmult, 
6197 +                                 float hmult, int scalew, int scaleh)
6198 +{
6199 +    QString tmp = filename;
6200 +    return QString("cache_%1@%2_%3_%4_%5").arg(tmp.replace(QChar('/'), "+"))
6201 +        .arg(wmult).arg(hmult).arg(scalew).arg(scaleh);
6202 +}
6203 +
6204 +QString OSDImageCache::ExtractOriginal(const QString &key)
6205 +{
6206 +    QString tmp0 = key.mid(6);
6207 +    QString tmp1 = tmp0.left(tmp0.find("@"));
6208 +    QString tmp2 = tmp1.replace(QChar('+'), "/");
6209 +    return tmp2;
6210 +}
6211 +
6212 +void OSDImageCache::Reset(void)
6213 +{
6214 +    QMutexLocker locker(&m_cacheLock);
6215 +    // this also deletes the images due to setAutoDelete(true)
6216 +    m_imageCache.clear();
6217 +}
6218 Index: mythtv/libs/libmythtv/osd.cpp
6219 ===================================================================
6220 --- mythtv/libs/libmythtv/osd.cpp       (.../tags/release-0-19) (revision 10931)
6221 +++ mythtv/libs/libmythtv/osd.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
6222 @@ -154,7 +154,8 @@
6223          }
6224  
6225          OSDTypeCC *ccpage = new OSDTypeCC(name, ccfont, sub_xoff, sub_yoff,
6226 -                                          sub_dispw, sub_disph);
6227 +                                          sub_dispw, sub_disph,
6228 +                                          wmult, hmult);
6229          container->AddType(ccpage);
6230      }
6231  
6232 @@ -517,7 +518,7 @@
6233          }
6234      }
6235  
6236 -    OSDTypeBox *box = new OSDTypeBox(name, area);
6237 +    OSDTypeBox *box = new OSDTypeBox(name, area, wmult, hmult);
6238      container->AddType(box);
6239  }
6240  
6241 @@ -658,7 +659,7 @@
6242          return;
6243      }
6244  
6245 -    OSDTypeText *text = new OSDTypeText(name, ttffont, "", area);
6246 +    OSDTypeText *text = new OSDTypeText(name, ttffont, "", area, wmult, hmult);
6247      container->AddType(text);
6248  
6249      text->SetMultiLine(multiline);
6250 @@ -875,7 +876,7 @@
6251                  QRect area = parseRect(getFirstText(info));
6252                  normalizeRect(area);
6253  
6254 -                rects->AddPosition(area);
6255 +                rects->AddPosition(area, wmult, hmult);
6256              }
6257              else
6258              {
6259 @@ -919,7 +920,7 @@
6260                  pos.setX((int)(pos.x() * wmult + xoffset));
6261                  pos.setY((int)(pos.y() * hmult + yoffset));
6262  
6263 -                image->AddPosition(pos);
6264 +                image->AddPosition(pos, wmult, hmult);
6265              }
6266              else if (info.tagName() == "staticsize")
6267              {
6268 @@ -1925,7 +1926,7 @@
6269          image = new OSDTypeImage(*editarrowright);
6270      }
6271  
6272 -    image->SetPosition(QPoint(xpos, ypos));
6273 +    image->SetPosition(QPoint(xpos, ypos), wmult, hmult);
6274  
6275      set->AddType(image);
6276      set->Display();
6277 Index: mythtv/libs/libmythtv/tv_rec.h
6278 ===================================================================
6279 --- mythtv/libs/libmythtv/tv_rec.h      (.../tags/release-0-19) (revision 10931)
6280 +++ mythtv/libs/libmythtv/tv_rec.h      (.../branches/release-0-19-fixes)       (revision 10931)
6281 @@ -13,6 +13,7 @@
6282  #include "mythdeque.h"
6283  #include "programinfo.h"
6284  #include "tv.h"
6285 +#include "util.h"
6286  
6287  class QSocket;
6288  class NuppelVideoRecorder;
6289 @@ -48,6 +49,30 @@
6290      BROWSE_FAVORITE ///< Fetch information on the next favorite channel
6291  } BrowseDirections;
6292  
6293 +class TuningTimer
6294 +{
6295 +  public:
6296 +    TuningTimer() {}
6297 +
6298 +    void setTimeout(long t) { _timeout = t; }
6299 +    long timeout(void) { return _timeout; }
6300 +    void start() { t_timer.start(); }
6301 +    int restart() { int ret = elapsed();
6302 +                    t_timer.restart();
6303 +                    return ret;
6304 +                  }
6305 +    int elapsed() { int ret = t_timer.elapsed();
6306 +                    if (ret > _timeout) { ret = 0;  t_timer.restart(); }
6307 +                    return ret;
6308 +                  }
6309 +
6310 +    void addMSecs(int ms) { t_timer.addMSecs(ms); }
6311 +
6312 +  private:
6313 +    QTime t_timer;
6314 +    long _timeout;
6315 +};
6316 +
6317  class GeneralDBOptions
6318  {
6319    public:
6320 @@ -275,6 +300,7 @@
6321      bool TuningPMTCheck(void);
6322      void TuningNewRecorder(void);
6323      void TuningRestartRecorder(void);
6324 +    bool RetuneChannel(void);
6325  
6326      void HandleStateChange(void);
6327      void ChangeState(TVState nextState);
6328 @@ -362,6 +388,10 @@
6329      QString      rbFilePrefix;
6330      QString      rbFileExt;
6331  
6332 +    // Retune stuff
6333 +    TuningTimer *retune_timer;
6334 +    int          retune_requests;
6335 +
6336    public:
6337      static const uint kEITScanStartTimeout;
6338      static const uint kSignalMonitoringRate;
6339 Index: mythtv/libs/libmythtv/videobuffers.h
6340 ===================================================================
6341 --- mythtv/libs/libmythtv/videobuffers.h        (.../tags/release-0-19) (revision 10931)
6342 +++ mythtv/libs/libmythtv/videobuffers.h        (.../branches/release-0-19-fixes)       (revision 10931)
6343 @@ -40,6 +40,7 @@
6344      kVideoBuffer_used      = 0x00000004,
6345      kVideoBuffer_pause     = 0x00000008,
6346      kVideoBuffer_displayed = 0x00000010,
6347 +    kVideoBuffer_decode    = 0x00000020,
6348      kVideoBuffer_all       = 0x0000001F,
6349  };
6350  
6351 @@ -159,7 +160,6 @@
6352      uint                   vpos;
6353  
6354      mutable QMutex         global_lock;
6355 -    QMutex                 inheritence_lock;
6356  
6357      bool                   use_frame_locks;
6358      QMutex                 frame_lock;
6359 Index: mythtv/libs/libmythtv/dvbconfparser.cpp
6360 ===================================================================
6361 --- mythtv/libs/libmythtv/dvbconfparser.cpp     (.../tags/release-0-19) (revision 10931)
6362 +++ mythtv/libs/libmythtv/dvbconfparser.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
6363 @@ -193,10 +193,10 @@
6364      QStringList::Iterator end = tokens.end();
6365  
6366      if (i != end) c.name = *i++; else return false;
6367 -    if (i != end) c.frequency = (*i++).toInt(); else return false;
6368 +    if (i != end) c.frequency = (*i++).toUInt()*1000; else return false;
6369      if (i == end || !c.polarity.parseConf(*i++)) return false;
6370      if (i == end ) return false; else i++; //Sat num
6371 -    if (i != end) c.symbolrate = (*i++).toInt(); else return false;
6372 +    if (i != end) c.symbolrate = (*i++).toUInt()*1000; else return false;
6373      if (i == end ) return false; else i++;
6374      if (i == end ) return false; else i++;
6375      if (i != end) c.serviceid = (*i++).toInt(); else return false;
6376 Index: mythtv/libs/libmythtv/pchdtvsignalmonitor.cpp
6377 ===================================================================
6378 --- mythtv/libs/libmythtv/pchdtvsignalmonitor.cpp       (.../tags/release-0-19) (revision 10931)
6379 +++ mythtv/libs/libmythtv/pchdtvsignalmonitor.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
6380 @@ -108,8 +108,8 @@
6381  
6382          len += remainder;
6383          remainder = GetStreamData()->ProcessData(buffer, len);
6384 -        if (remainder > 0) // leftover bytes
6385 -            memmove(buffer, &(buffer[buffer_size - remainder]), remainder);
6386 +        if (remainder > 0 && (len > remainder)) // leftover bytes
6387 +            memmove(buffer, &(buffer[len - remainder]), remainder);
6388      }
6389      DBG_SM("RunTableMonitor()", "end");
6390  }
6391 Index: mythtv/libs/libmythtv/videobuffers.cpp
6392 ===================================================================
6393 --- mythtv/libs/libmythtv/videobuffers.cpp      (.../tags/release-0-19) (revision 10931)
6394 +++ mythtv/libs/libmythtv/videobuffers.cpp      (.../branches/release-0-19-fixes)       (revision 10931)
6395 @@ -84,7 +84,7 @@
6396      : numbuffers(0), needfreeframes(0), needprebufferframes(0),
6397        needprebufferframes_normal(0), needprebufferframes_small(0),
6398        keepprebufferframes(0), need_extra_for_pause(false), rpos(0), vpos(0),
6399 -      global_lock(true), inheritence_lock(false), use_frame_locks(true),
6400 +      global_lock(true), use_frame_locks(true),
6401        frame_lock(true)
6402  {
6403  }
6404 @@ -125,6 +125,8 @@
6405  {
6406      global_lock.lock();
6407  
6408 +    Reset();
6409 +
6410      uint numcreate = numdecode + ((extra_for_pause) ? 1 : 0);
6411  
6412      // make a big reservation, so that things that depend on
6413 @@ -409,6 +411,8 @@
6414          q = &limbo;
6415      else if (type == kVideoBuffer_pause)
6416          q = &pause;
6417 +    else if (type == kVideoBuffer_decode)
6418 +        q = &decode;
6419      global_lock.unlock();
6420  
6421      return q;
6422 @@ -429,6 +433,8 @@
6423          q = &limbo;
6424      else if (type == kVideoBuffer_pause)
6425          q = &pause;
6426 +    else if (type == kVideoBuffer_decode)
6427 +        q = &decode;
6428      global_lock.unlock();
6429  
6430      return q;
6431 @@ -503,6 +509,8 @@
6432              limbo.remove(frame);
6433          if ((type & kVideoBuffer_pause) == kVideoBuffer_pause)
6434              pause.remove(frame);
6435 +        if ((type & kVideoBuffer_decode) == kVideoBuffer_decode)
6436 +            decode.remove(frame);
6437          global_lock.unlock();
6438      }
6439  }
6440 @@ -857,7 +865,7 @@
6441  {
6442      (void)frame;
6443  #ifdef USING_XVMC
6444 -    inheritence_lock.lock();
6445 +    global_lock.lock();
6446      
6447      frame_map_t::iterator it = parents.find(frame);
6448      if (it == parents.end())
6449 @@ -902,18 +910,18 @@
6450              children[*it].push_back((VideoFrame*)frame);
6451      }
6452  
6453 -    inheritence_lock.unlock();
6454 +    global_lock.unlock();
6455  #endif // USING_XVMC
6456  }
6457  
6458  void VideoBuffers::RemoveInheritence(const VideoFrame *frame)
6459  {
6460 -    inheritence_lock.lock();
6461 +    global_lock.lock();
6462  
6463      frame_map_t::iterator it = parents.find(frame);
6464      if (it == parents.end())
6465      {
6466 -        inheritence_lock.unlock();
6467 +        global_lock.unlock();
6468          return;
6469      }
6470  
6471 @@ -945,7 +953,7 @@
6472                      .arg(i).arg(DebugString(*pit)));
6473      }
6474  
6475 -    inheritence_lock.unlock();
6476 +    global_lock.unlock();
6477  }
6478  
6479  frame_queue_t VideoBuffers::Children(const VideoFrame *frame)
6480 Index: mythtv/libs/libavformat/aviobuf.c
6481 ===================================================================
6482 --- mythtv/libs/libavformat/aviobuf.c   (.../tags/release-0-19) (revision 10931)
6483 +++ mythtv/libs/libavformat/aviobuf.c   (.../branches/release-0-19-fixes)       (revision 10931)
6484 @@ -164,7 +164,13 @@
6485  
6486  void url_fskip(ByteIOContext *s, offset_t offset)
6487  {
6488 -    url_fseek(s, offset, SEEK_CUR);
6489 +    if (offset < 16384) 
6490 +    {
6491 +        static unsigned char fskipbuf[16384];
6492 +        get_buffer(s, fskipbuf, offset);
6493 +    }
6494 +    else
6495 +        url_fseek(s, offset, SEEK_CUR);
6496  }
6497  
6498  offset_t url_ftell(ByteIOContext *s)
6499 Index: mythtv/libs/libmyth/lcddevice.cpp
6500 ===================================================================
6501 --- mythtv/libs/libmyth/lcddevice.cpp   (.../tags/release-0-19) (revision 10931)
6502 +++ mythtv/libs/libmyth/lcddevice.cpp   (.../branches/release-0-19-fixes)       (revision 10931)
6503 @@ -150,7 +150,7 @@
6504  
6505      if (!connected)
6506      {
6507 -        QTextStream os(socket);
6508 +        QTextStream os(socket->socketDevice());
6509  
6510          int count = 0;
6511          do
6512 @@ -213,7 +213,7 @@
6513          return;
6514      }
6515  
6516 -    QTextStream os(socket);
6517 +    QTextStream os(socket->socketDevice());
6518     
6519      last_command = someText;
6520   
6521 @@ -224,7 +224,7 @@
6522  #endif
6523          // Just stream the text out the socket
6524  
6525 -        os << someText << "\n" << flush;
6526 +        os << someText << "\n";
6527      }
6528      else
6529      {
6530 Index: mythtv/libs/libmyth/audiooutputca.cpp
6531 ===================================================================
6532 --- mythtv/libs/libmyth/audiooutputca.cpp       (.../tags/release-0-19) (revision 10931)
6533 +++ mythtv/libs/libmyth/audiooutputca.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
6534 @@ -21,6 +21,7 @@
6535  
6536  #include "mythcontext.h"
6537  #include "audiooutputca.h"
6538 +#include "config.h"
6539  
6540  // this holds Core Audio member variables
6541  struct CoreAudioData {
6542 @@ -107,8 +108,10 @@
6543      bzero(&conv_in_desc, sizeof(AudioStreamBasicDescription));
6544      conv_in_desc.mSampleRate       = audio_samplerate;
6545      conv_in_desc.mFormatID         = kAudioFormatLinearPCM;
6546 -    conv_in_desc.mFormatFlags      = kLinearPCMFormatFlagIsSignedInteger
6547 -                                     | kLinearPCMFormatFlagIsBigEndian;
6548 +    conv_in_desc.mFormatFlags      = kLinearPCMFormatFlagIsSignedInteger;
6549 +#ifdef WORDS_BIGENDIAN
6550 +    conv_in_desc.mFormatFlags     |= kLinearPCMFormatFlagIsBigEndian;
6551 +#endif
6552      conv_in_desc.mBytesPerPacket   = audio_bytes_per_sample;
6553      conv_in_desc.mFramesPerPacket  = 1;
6554      conv_in_desc.mBytesPerFrame    = audio_bytes_per_sample;
6555 Index: mythtv/libs/libmyth/util.cpp
6556 ===================================================================
6557 --- mythtv/libs/libmyth/util.cpp        (.../tags/release-0-19) (revision 10931)
6558 +++ mythtv/libs/libmyth/util.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
6559 @@ -1006,16 +1006,20 @@
6560      long long freespace = -1;
6561      QCString cstr = file_on_disk.local8Bit();
6562  
6563 -    if (statfs(cstr, &statbuf) == 0)
6564 +    total = used = -1;
6565 +
6566 +    // there are cases where statfs will return 0 (good), but f_blocks and
6567 +    // others are invalid and set to 0 (such as when an automounted directory
6568 +    // is not mounted but still visible because --ghost was used),
6569 +    // so check to make sure we can have a total size > 0
6570 +    if ((statfs(cstr, &statbuf) == 0) &&
6571 +        (statbuf.f_blocks > 0) &&
6572 +        (statbuf.f_bsize > 0))
6573      {
6574          freespace = statbuf.f_bsize * (statbuf.f_bavail >> 10);
6575          total = statbuf.f_bsize * (statbuf.f_blocks >> 10);
6576          used  = total - freespace;
6577      }
6578 -    else
6579 -    {
6580 -        freespace = total = used = -1;
6581 -    }
6582  
6583      return freespace;
6584  }
6585 Index: mythtv/libs/libmyth/mythdialogs.cpp
6586 ===================================================================
6587 --- mythtv/libs/libmyth/mythdialogs.cpp (.../tags/release-0-19) (revision 10931)
6588 +++ mythtv/libs/libmyth/mythdialogs.cpp (.../branches/release-0-19-fixes)       (revision 10931)
6589 @@ -2617,6 +2617,7 @@
6590      password_editor->setEchoMode(QLineEdit::Password);
6591      password_editor->setGeometry(textWidth + 20,10,135,30);
6592      password_editor->setBackgroundOrigin(ParentOrigin);
6593 +    password_editor->setAllowVirtualKeyboard(false);
6594      connect(password_editor, SIGNAL(textChanged(const QString &)),
6595              this, SLOT(checkPassword(const QString &)));
6596  
6597 Index: mythtv/libs/libmyth/mythwidgets.cpp
6598 ===================================================================
6599 --- mythtv/libs/libmyth/mythwidgets.cpp (.../tags/release-0-19) (revision 10931)
6600 +++ mythtv/libs/libmyth/mythwidgets.cpp (.../branches/release-0-19-fixes)       (revision 10931)
6601 @@ -353,7 +353,8 @@
6602                      (e->key() == Qt::Key_Enter) ||
6603                      (e->key() == Qt::Key_Return)))
6604              {
6605 -                if (gContext->GetNumSetting("UseVirtualKeyboard", 1) == 1)
6606 +                if ((allowVirtualKeyboard) &&
6607 +                                   (gContext->GetNumSetting("UseVirtualKeyboard", 1) == 1))
6608                  {
6609                      popup = new VirtualKeyboard(gContext->GetMainWindow(), this);
6610                      gContext->GetMainWindow()->detach(popup);
6611 @@ -726,10 +727,11 @@
6612                  QWidget::focusNextPrevChild(true);
6613                  emit tryingToLooseFocus(true);
6614              }
6615 -            else if (action == "SELECT" &&
6616 -                    (e->text().isNull() ||
6617 -                    (e->key() == Qt::Key_Enter) || 
6618 -                    (e->key() == Qt::Key_Return)))
6619 +            else if ((action == "SELECT") &&
6620 +                     (!active_cycle) &&
6621 +                     ((e->text().isNull()) ||
6622 +                      (e->key() == Qt::Key_Enter) || 
6623 +                      (e->key() == Qt::Key_Return)))
6624              {
6625                  if (gContext->GetNumSetting("UseVirtualKeyboard", 1) == 1)
6626                  {
6627 @@ -749,7 +751,7 @@
6628      if (handled)
6629          return;
6630  
6631 -    if (!handled && popup && popup->isShown())
6632 +    if (popup && popup->isShown())
6633      {
6634          endCycle();
6635          QTextEdit::keyPressEvent(e);
6636 Index: mythtv/libs/libmyth/remotefile.h
6637 ===================================================================
6638 --- mythtv/libs/libmyth/remotefile.h    (.../tags/release-0-19) (revision 10931)
6639 +++ mythtv/libs/libmyth/remotefile.h    (.../branches/release-0-19-fixes)       (revision 10931)
6640 @@ -27,6 +27,8 @@
6641  
6642      long long GetFileSize(void);
6643  
6644 +    void SetTimeout(bool fast);
6645 +
6646    private:
6647      QSocketDevice *openSocket(bool control);
6648  
6649 @@ -43,6 +45,7 @@
6650      QMutex lock;
6651  
6652      long long filesize;
6653 +    bool timeoutisfast;
6654  };
6655  
6656  #endif
6657 Index: mythtv/libs/libmyth/mythwidgets.h
6658 ===================================================================
6659 --- mythtv/libs/libmyth/mythwidgets.h   (.../tags/release-0-19) (revision 10931)
6660 +++ mythtv/libs/libmyth/mythwidgets.h   (.../branches/release-0-19-fixes)       (revision 10931)
6661 @@ -122,17 +122,21 @@
6662      Q_OBJECT
6663    public:
6664      MythLineEdit(QWidget *parent=NULL, const char* widgetName=0) :
6665 -      QLineEdit(parent, widgetName) { rw = true; Init(); };
6666 +      QLineEdit(parent, widgetName)
6667 +           { rw = true; allowVirtualKeyboard = true; Init(); };
6668  
6669      MythLineEdit(const QString& contents, QWidget *parent=NULL, 
6670                   const char* widgetName=0) :
6671 -      QLineEdit(contents, parent, widgetName) { rw = true; Init(); };
6672 +      QLineEdit(contents, parent, widgetName)
6673 +           { rw = true; allowVirtualKeyboard = true; Init(); };
6674  
6675      virtual ~MythLineEdit();
6676  
6677      void setHelpText(QString help) { helptext = help; };
6678      void setRW(bool readwrite = true) { rw = readwrite; };
6679      void setRO() { rw = false; };
6680 +    void setAllowVirtualKeyboard(bool allowKbd = true)
6681 +              { allowVirtualKeyboard = allowKbd; }
6682      void setPopupPosition(PopupPosition pos) { popupPosition = pos; }
6683      PopupPosition getPopupPosition(void) { return popupPosition; }
6684  
6685 @@ -154,6 +158,7 @@
6686      VirtualKeyboard *popup;
6687      QString helptext;
6688      bool rw;
6689 +    bool allowVirtualKeyboard;
6690      PopupPosition popupPosition;
6691  };
6692  
6693 Index: mythtv/libs/libmyth/mythcontext.cpp
6694 ===================================================================
6695 --- mythtv/libs/libmyth/mythcontext.cpp (.../tags/release-0-19) (revision 10931)
6696 +++ mythtv/libs/libmyth/mythcontext.cpp (.../branches/release-0-19-fixes)       (revision 10931)
6697 @@ -2621,9 +2621,13 @@
6698          d->LoadLogSettings();
6699      if (d->m_logenable == 1)
6700      {
6701 +        QString fullMsg = message;
6702 +        if (!details.isEmpty())
6703 +            fullMsg += ": " + details;
6704 +
6705          if (message.left(21) != "Last message repeated")
6706          {
6707 -            if (message == d->lastLogStrings[module])
6708 +            if (fullMsg == d->lastLogStrings[module])
6709              {
6710                  d->lastLogCounts[module] += 1;
6711                  return;
6712 @@ -2639,7 +2643,7 @@
6713                  }
6714  
6715                  d->lastLogCounts[module] = 0;
6716 -                d->lastLogStrings[module] = message;
6717 +                d->lastLogStrings[module] = fullMsg;
6718              }
6719          }
6720  
6721 @@ -2693,7 +2697,7 @@
6722          }
6723  
6724          if (priority <= d->m_logprintlevel)
6725 -            VERBOSE(VB_IMPORTANT, module + ": " + message);
6726 +            VERBOSE(VB_IMPORTANT, module + ": " + fullMsg);
6727      }
6728  }
6729  
6730 Index: mythtv/libs/libmyth/remotefile.cpp
6731 ===================================================================
6732 --- mythtv/libs/libmyth/remotefile.cpp  (.../tags/release-0-19) (revision 10931)
6733 +++ mythtv/libs/libmyth/remotefile.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
6734 @@ -15,6 +15,7 @@
6735      path = url;
6736      readposition = 0;
6737      filesize = -1;
6738 +    timeoutisfast = false;
6739  
6740      query = "QUERY_FILETRANSFER %1";
6741  
6742 @@ -295,4 +296,34 @@
6743      Read(data.data(), filesize);
6744  
6745      return true;
6746 -} 
6747 +}
6748 +
6749 +void RemoteFile::SetTimeout(bool fast)
6750 +{
6751 +    if (timeoutisfast == fast)
6752 +        return;
6753 +
6754 +    if (!sock)
6755 +    {
6756 +        VERBOSE(VB_NETWORK, "RemoteFile::Seek(): Called with no socket");
6757 +        return;
6758 +    }
6759 +
6760 +    if (!sock->isOpen() || sock->error())
6761 +        return;
6762 +
6763 +    if (!controlSock->isOpen() || controlSock->error())
6764 +        return;
6765 +
6766 +    QStringList strlist = QString(query).arg(recordernum);
6767 +    strlist << "SET_TIMEOUT";
6768 +    strlist << QString::number((int)fast);
6769 +
6770 +    lock.lock();
6771 +    WriteStringList(controlSock, strlist);
6772 +    ReadStringList(controlSock, strlist);
6773 +    lock.unlock();
6774 +
6775 +    timeoutisfast = fast;
6776 +}
6777 +
6778 Index: mythtv/libs/libavcodec/libavcodec.pro
6779 ===================================================================
6780 --- mythtv/libs/libavcodec/libavcodec.pro       (.../tags/release-0-19) (revision 10931)
6781 +++ mythtv/libs/libavcodec/libavcodec.pro       (.../branches/release-0-19-fixes)       (revision 10931)
6782 @@ -430,4 +430,5 @@
6783      LIBS               += -lz
6784      QMAKE_LFLAGS_SHLIB += -single_module
6785      QMAKE_LFLAGS_SHLIB += -seg1addr 0xC3000000
6786 +    QMAKE_LFLAGS_SHLIB += -read_only_relocs warning
6787  }
6788 Index: mythtv/programs/mythfrontend/playbackbox.cpp
6789 ===================================================================
6790 --- mythtv/programs/mythfrontend/playbackbox.cpp        (.../tags/release-0-19) (revision 10931)
6791 +++ mythtv/programs/mythfrontend/playbackbox.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
6792 @@ -17,6 +17,7 @@
6793  #include <qsqldatabase.h>
6794  #include <qmap.h>
6795  
6796 +#include <cmath>
6797  #include <unistd.h>
6798  
6799  #include <iostream>
6800 @@ -140,6 +141,7 @@
6801        // Main Recording List support
6802        fillListTimer(new QTimer(this)),  connected(false),
6803        titleIndex(0),                    progIndex(0),
6804 +      progsInDB(0),
6805        // Other state
6806        curitem(NULL),                    delitem(NULL),
6807        lastProgram(NULL),
6808 @@ -261,7 +263,9 @@
6809      setNoErase();
6810      gContext->addListener(this);
6811  
6812 -    if (!recGroupPassword.isEmpty() || (titleList.count() <= 1) || initialFilt)
6813 +    if ((!recGroupPassword.isEmpty()) ||
6814 +        ((titleList.count() <= 1) && (progsInDB > 0)) ||
6815 +        (initialFilt))
6816          showRecGroupChooser();
6817  
6818      gContext->addCurrentLocation((type == Delete)? "DeleteBox":"PlaybackBox");
6819 @@ -890,9 +894,13 @@
6820          !playingSomething)
6821      {
6822          QSize size = drawVideoBounds.size();
6823 +        float saspect = ((float)size.width()) / ((float)size.height());
6824 +        float vaspect = previewVideoNVP->GetVideoAspect();
6825 +        size.setHeight((int) ceil(size.height() * (saspect / vaspect)));
6826 +        size.setHeight(((size.height() + 7) / 8) * 8);
6827 +        size.setWidth( ((size.width()  + 7) / 8) * 8);
6828          const QImage &img = previewVideoNVP->GetARGBFrame(size);
6829 -        uint xoff = max((size.width() - drawVideoBounds.width()) / 2, 0);
6830 -        p->drawImage(drawVideoBounds.x() + xoff, drawVideoBounds.y(), img);
6831 +        p->drawImage(drawVideoBounds.x(), drawVideoBounds.y(), img);
6832      }
6833  
6834      /* have we timed out waiting for nvp to start? */
6835 @@ -1272,10 +1280,10 @@
6836          paintSkipUpdate = false;
6837          update(drawTotalBounds);
6838      }
6839 +    else if (arrowAccel)
6840 +        showActionsSelected();
6841      else if (curitem && curitem->availableStatus != asAvailable)
6842          showAvailablePopup(curitem);
6843 -    else if (arrowAccel)
6844 -        showActionsSelected();    
6845  }
6846  
6847  void PlaybackBox::cursorDown(bool page, bool newview)
6848 @@ -1380,6 +1388,7 @@
6849          asCache[asKey] = p->availableStatus;
6850      }
6851  
6852 +    progsInDB = 0;
6853      titleList.clear();
6854      progLists.clear();
6855      // Clear autoDelete for the "all" list since it will share the
6856 @@ -1402,6 +1411,7 @@
6857          vector<ProgramInfo *>::iterator i = infoList->begin();
6858          for ( ; i != infoList->end(); i++)
6859          {
6860 +            progsInDB++;
6861              p = *i;
6862              if ((((p->recgroup == recGroup) ||
6863                    ((recGroup == "All Programs") &&
6864 @@ -1886,7 +1896,8 @@
6865      if (inTitle && haveGroupInfoSet)
6866          return;
6867  
6868 -    if (curitem->availableStatus != asAvailable)
6869 +    if ((curitem->availableStatus != asAvailable) &&
6870 +        (curitem->availableStatus != asFileNotFound))
6871          showAvailablePopup(curitem);
6872      else
6873          showActions(curitem);
6874 @@ -2068,7 +2079,21 @@
6875  
6876      delitem = new ProgramInfo(*toExp);
6877  
6878 -    if (delitem->availableStatus != asAvailable)
6879 +    if (fileExists(delitem) == false)
6880 +    {
6881 +        QString msg =
6882 +            QString("PlaybackBox::showActions(): Error, %1 file not found")
6883 +            .arg(delitem->pathname);
6884 +        VERBOSE(VB_IMPORTANT, msg);
6885 +
6886 +        ProgramInfo *tmpItem = findMatchingProg(delitem);
6887 +        if (tmpItem)
6888 +        {
6889 +            tmpItem->availableStatus = asFileNotFound;
6890 +            showFileNotFoundActionPopup(delitem);
6891 +        }
6892 +    }
6893 +    else if (delitem->availableStatus != asAvailable)
6894          showAvailablePopup(delitem);
6895      else
6896          showActionPopup(delitem);
6897 @@ -2647,6 +2672,34 @@
6898      expectingPopup = true;
6899  }
6900  
6901 +void PlaybackBox::showFileNotFoundActionPopup(ProgramInfo *program)
6902 +{
6903 +    if (!curitem || !program)
6904 +        return;
6905 +
6906 +    popup = new MythPopupBox(gContext->GetMainWindow(), drawPopupSolid,
6907 +                             drawPopupFgColor, drawPopupBgColor,
6908 +                             drawPopupSelColor, "action popup");
6909 +
6910 +    QString msg = QObject::tr("Recording Unavailable") + "\n";
6911 +    msg += QObject::tr("The file for this recording can "
6912 +                       "not be found") + "\n";
6913 +
6914 +    initPopup(popup, program, "", msg);
6915 +
6916 +    QButton *detailsButton;
6917 +    detailsButton = popup->addButton(tr("Show Program Details"), this,
6918 +                                     SLOT(showProgramDetails()));
6919 +
6920 +    popup->addButton(tr("Delete"), this, SLOT(askDelete()));
6921 +
6922 +    popup->ShowPopup(this, SLOT(doCancel()));
6923 +
6924 +    detailsButton->setFocus();
6925 +
6926 +    expectingPopup = true;
6927 +}
6928 +
6929  void PlaybackBox::initPopup(MythPopupBox *popup, ProgramInfo *program,
6930                              QString message, QString message2)
6931  {
6932 @@ -4129,8 +4182,7 @@
6933      if (!recGroupListBox)
6934          return;
6935  
6936 -    QString item = 
6937 -        recGroupListBox->currentText().section('[', 0, 0).simplifyWhiteSpace();
6938 +    QString item = recGroupListBox->currentText().section(" [", 0, 0);
6939  
6940      if (item.left(5) == "-----")
6941      {
6942 @@ -4147,8 +4199,7 @@
6943  
6944  void PlaybackBox::setGroupFilter(void)
6945  {
6946 -    recGroup =
6947 -        recGroupListBox->currentText().section('[', 0, 0).simplifyWhiteSpace();
6948 +    recGroup = recGroupListBox->currentText().section(" [", 0, 0);
6949  
6950      if (groupnameAsAllProg)
6951          groupDisplayName = recGroup;
6952 Index: mythtv/programs/mythfrontend/customrecord.cpp
6953 ===================================================================
6954 --- mythtv/programs/mythfrontend/customrecord.cpp       (.../tags/release-0-19) (revision 10931)
6955 +++ mythtv/programs/mythfrontend/customrecord.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
6956 @@ -149,7 +149,7 @@
6957      m_cfrom << "";
6958      m_csql << "program.stars >= 0.75 ";
6959  
6960 -    m_clause->insertItem(tr("Person named in the credits"));
6961 +    m_clause->insertItem(tr("Person named in the credits (Data Direct)"));
6962      m_cfrom << ", people, credits";
6963      m_csql << QString("people.name = 'Tom Hanks' \n"
6964                        "AND credits.person = people.person \n"
6965 @@ -447,8 +447,8 @@
6966      else
6967      {
6968          MSqlQuery query(MSqlQuery::InitCon());
6969 -        query.prepare(QString("SELECT NULL FROM program,channel %1 WHERE\n%2") 
6970 -                              .arg(from).arg(desc));
6971 +        query.prepare(QString("SELECT NULL FROM (program,channel) "
6972 +                              "%1 WHERE\n%2").arg(from).arg(desc));
6973  
6974          if (query.exec() && query.isActive())
6975          {
6976 Index: mythtv/programs/mythfrontend/tv_schedule.xml
6977 ===================================================================
6978 --- mythtv/programs/mythfrontend/tv_schedule.xml        (.../tags/release-0-19) (revision 10931)
6979 +++ mythtv/programs/mythfrontend/tv_schedule.xml        (.../branches/release-0-19-fixes)       (revision 10931)
6980 @@ -26,7 +26,7 @@
6981        <alttext lang="CA">Guia</alttext>
6982        <alttext lang="DE">EPG</alttext>
6983        <alttext lang="DK">Guide</alttext>
6984 -      <alttext lang="DK">Dagskrá</alttext>
6985 +      <alttext lang="IS">Dagskrá</alttext>
6986        <alttext lang="NL">Gids</alttext>
6987        <alttext lang="SV">Guide</alttext>
6988        <alttext lang="JA">ガイド</alttext>
6989 Index: mythtv/programs/mythfrontend/playbackbox.h
6990 ===================================================================
6991 --- mythtv/programs/mythfrontend/playbackbox.h  (.../tags/release-0-19) (revision 10931)
6992 +++ mythtv/programs/mythfrontend/playbackbox.h  (.../branches/release-0-19-fixes)       (revision 10931)
6993 @@ -237,6 +237,7 @@
6994      void promptEndOfRecording(ProgramInfo *);
6995      void showDeletePopup(ProgramInfo *, deletePopupType);
6996      void showActionPopup(ProgramInfo *program);
6997 +    void showFileNotFoundActionPopup(ProgramInfo *program);
6998      void initPopup(MythPopupBox *popup, ProgramInfo *program, 
6999                     QString message, QString message2);
7000      void cancelPopup();
7001 @@ -337,6 +338,7 @@
7002      int                 progIndex;  ///< Index of selected item index on page
7003      QStringList         titleList;  ///< list of pages
7004      ProgramMap          progLists;  ///< lists of programs by page        
7005 +    int                 progsInDB;  ///< total number of recordings in DB
7006  
7007      // Play List support
7008      QStringList         playList;   ///< list of selected items "play list"
7009 Index: mythtv/programs/mythfrontend/networkcontrol.cpp
7010 ===================================================================
7011 --- mythtv/programs/mythfrontend/networkcontrol.cpp     (.../tags/release-0-19) (revision 10931)
7012 +++ mythtv/programs/mythfrontend/networkcontrol.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
7013 @@ -469,7 +469,7 @@
7014              message = "NETWORK_CONTROL SEEK BACKWARD";
7015          else if (tokens[2].contains(QRegExp("^\\d\\d:\\d\\d:\\d\\d$")))
7016          {
7017 -            int hours = tokens[2].left(0).toInt();
7018 +            int hours   = tokens[2].mid(0, 2).toInt();
7019              int minutes = tokens[2].mid(3, 2).toInt();
7020              int seconds = tokens[2].mid(6, 2).toInt();
7021              message = QString("NETWORK_CONTROL SEEK POSITION %1")
7022 Index: mythtv/programs/mythtranscode/mpeg2fix.cpp
7023 ===================================================================
7024 --- mythtv/programs/mythtranscode/mpeg2fix.cpp  (.../tags/release-0-19) (revision 10931)
7025 +++ mythtv/programs/mythtranscode/mpeg2fix.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
7026 @@ -1776,6 +1776,7 @@
7027  
7028          if (vFrame.count() && (file_end || vFrame.getLast()->isSequence))
7029          {
7030 +            MPEG2frame *seqFrame;
7031              if (ptsIncrement != vFrame.first()->mpeg2_seq.frame_period / 300)
7032              {
7033                  VERBOSE(MPF_IMPORTANT,
7034 @@ -1786,6 +1787,11 @@
7035              }
7036              displayFrame->toFirst();
7037  
7038 +            // since we might reorder the frames when coming out of a cutpoint
7039 +            // me need to save the first frame here, as it is gauranteed to
7040 +            // have a sequence header.
7041 +            seqFrame = vFrame.current();
7042 +
7043              while (vFrame.current() != vFrame.getLast())
7044              {
7045                  bool ptsorder_eq_dtsorder = false;
7046 @@ -1941,7 +1947,7 @@
7047  
7048                          if (! new_discard_state)
7049                          {
7050 -                            AddSequence(markedFrame, vFrame.first());
7051 +                            AddSequence(markedFrame, seqFrame);
7052                              RenumberFrames(frame_pos + Lreorder.at(),
7053                                              - GetFrameNum(markedFrame));
7054                          }
7055 Index: mythtv/programs/mythcommflag/main.cpp
7056 ===================================================================
7057 --- mythtv/programs/mythcommflag/main.cpp       (.../tags/release-0-19) (revision 10931)
7058 +++ mythtv/programs/mythcommflag/main.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
7059 @@ -895,9 +895,6 @@
7060          return COMMFLAG_EXIT_INVALID_CMDLINE;
7061      }
7062  
7063 -    if (queueJobInstead)
7064 -        return QueueCommFlagJob(chanid, starttime);
7065 -
7066      if (copyToCutlist)
7067          return CopySkipListToCutList(chanid, starttime);
7068  
7069 @@ -1009,7 +1006,10 @@
7070  
7071                  if ( allRecorded )
7072                  {
7073 -                    FlagCommercials(chanid, starttime);
7074 +                    if (queueJobInstead)
7075 +                        QueueCommFlagJob(chanid, starttime);
7076 +                    else
7077 +                        FlagCommercials(chanid, starttime);
7078                  }
7079                  else
7080                  {
7081 @@ -1063,7 +1063,12 @@
7082  
7083                              if ((flagStatus == COMM_FLAG_NOT_FLAGGED) &&
7084                                  (marksFound == 0))
7085 -                                FlagCommercials(chanid, starttime);
7086 +                            {
7087 +                                if (queueJobInstead)
7088 +                                    QueueCommFlagJob(chanid, starttime);
7089 +                                else
7090 +                                    FlagCommercials(chanid, starttime);
7091 +                            }
7092                          }
7093                      }
7094                  }
7095 Index: mythtv/programs/mythbackend/mainserver.cpp
7096 ===================================================================
7097 --- mythtv/programs/mythbackend/mainserver.cpp  (.../tags/release-0-19) (revision 10931)
7098 +++ mythtv/programs/mythbackend/mainserver.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
7099 @@ -1919,11 +1919,8 @@
7100      if (m_sched) {
7101          if (table == "") m_sched->getAllPending(strList);
7102          else {
7103 -            // We need a different connection from the scheduler proper
7104 -            // DDCon exists, although it's designed for other purposes.
7105 -            MSqlQueryInfo dbconn = MSqlQuery::DDCon();
7106 -            Scheduler *sched = new Scheduler(false, encoderList,
7107 -                                             table, &dbconn, m_sched);
7108 +            Scheduler *sched = new Scheduler(false, encoderList, 
7109 +                                             table, m_sched);
7110              sched->FillRecordListFromDB(recordid);
7111              sched->getAllPending(strList);
7112              delete sched;
7113 @@ -2940,6 +2937,12 @@
7114          long long ret = ft->Seek(curpos, pos, whence);
7115          encodeLongLong(retlist, ret);
7116      }
7117 +    else if (command == "SET_TIMEOUT")
7118 +    {
7119 +        bool fast = slist[2].toInt();
7120 +        ft->SetTimeout(fast);
7121 +        retlist << "ok";
7122 +    }
7123      else 
7124      {
7125          VERBOSE(VB_IMPORTANT, QString("Unknown command: %1").arg(command));
7126 Index: mythtv/programs/mythbackend/scheduler.cpp
7127 ===================================================================
7128 --- mythtv/programs/mythbackend/scheduler.cpp   (.../tags/release-0-19) (revision 10931)
7129 +++ mythtv/programs/mythbackend/scheduler.cpp   (.../branches/release-0-19-fixes)       (revision 10931)
7130 @@ -35,8 +35,7 @@
7131  #define LOC_ERR QString("Scheduler, Error: ")
7132  
7133  Scheduler::Scheduler(bool runthread, QMap<int, EncoderLink *> *tvList,
7134 -                     QString recordTbl, MSqlQueryInfo *databaseConnection,
7135 -                     Scheduler *master_sched)
7136 +                     QString recordTbl, Scheduler *master_sched)
7137  {
7138      hasconflicts = false;
7139      m_tvList = tvList;
7140 @@ -48,8 +47,11 @@
7141          master_sched->getAllPending(&reclist);
7142      }
7143  
7144 -    if (databaseConnection) dbConn = *databaseConnection;
7145 -    else dbConn = MSqlQuery::SchedCon();
7146 +    // Only the master scheduler should use SchedCon()
7147 +    if (runthread)
7148 +        dbConn = MSqlQuery::SchedCon();
7149 +    else
7150 +        dbConn = MSqlQuery::DDCon();
7151  
7152      recordTable = recordTbl;
7153  
7154 @@ -1136,6 +1138,10 @@
7155              
7156          if (reschedQueue.count())
7157          {
7158 +            // We might have been inactive for a long time, so make
7159 +            // sure our DB connection is fresh before continuing.
7160 +            dbConn = MSqlQuery::SchedCon();
7161 +
7162              gettimeofday(&fillstart, NULL);
7163              QString msg;
7164              while (reschedQueue.count())
7165 @@ -1827,10 +1833,10 @@
7166          QString query = QString(
7167  "INSERT INTO recordmatch (recordid, chanid, starttime, manualid) "
7168  "SELECT RECTABLE.recordid, program.chanid, program.starttime, "
7169 -" IF(search = %1, recordid, 0) "
7170 -"FROM RECTABLE, program ").arg(kManualSearch) + fromclauses[clause] + QString(
7171 -" INNER JOIN channel ON (channel.chanid = program.chanid) "
7172 -"WHERE ") + whereclauses[clause] + QString(" AND channel.visible = 1 AND "
7173 +" IF(search = %1, recordid, 0) ").arg(kManualSearch) + QString(
7174 +"FROM (RECTABLE, program INNER JOIN channel "
7175 +"      ON channel.chanid = program.chanid) ") + fromclauses[clause] + QString(
7176 +" WHERE ") + whereclauses[clause] + QString(" AND channel.visible = 1 AND "
7177  "((RECTABLE.type = %1 " // allrecord
7178  "OR RECTABLE.type = %2 " // findonerecord
7179  "OR RECTABLE.type = %3 " // finddailyrecord
7180 Index: mythtv/programs/mythbackend/housekeeper.cpp
7181 ===================================================================
7182 --- mythtv/programs/mythbackend/housekeeper.cpp (.../tags/release-0-19) (revision 10931)
7183 +++ mythtv/programs/mythbackend/housekeeper.cpp (.../branches/release-0-19-fixes)       (revision 10931)
7184 @@ -138,7 +138,6 @@
7185  
7186      while (1)
7187      {
7188 -        VERBOSE(VB_IMPORTANT, "Running HouseKeeping");
7189          gContext->LogEntry("mythbackend", LP_DEBUG,
7190                             "Running housekeeping thread", "");
7191  
7192 Index: mythtv/programs/mythbackend/scheduler.h
7193 ===================================================================
7194 --- mythtv/programs/mythbackend/scheduler.h     (.../tags/release-0-19) (revision 10931)
7195 +++ mythtv/programs/mythbackend/scheduler.h     (.../branches/release-0-19-fixes)       (revision 10931)
7196 @@ -23,8 +23,7 @@
7197  {
7198    public:
7199      Scheduler(bool runthread, QMap<int, EncoderLink *> *tvList,
7200 -              QString recordTbl = "record", MSqlQueryInfo *dbConnUse = NULL,
7201 -              Scheduler *master_sched = NULL);
7202 +              QString recordTbl = "record", Scheduler *master_sched = NULL);
7203      ~Scheduler();
7204  
7205      void Reschedule(int recordid);
7206 Index: mythtv/programs/mythbackend/filetransfer.cpp
7207 ===================================================================
7208 --- mythtv/programs/mythbackend/filetransfer.cpp        (.../tags/release-0-19) (revision 10931)
7209 +++ mythtv/programs/mythbackend/filetransfer.cpp        (.../branches/release-0-19-fixes)       (revision 10931)
7210 @@ -131,3 +131,9 @@
7211  
7212      return size;
7213  }
7214 +
7215 +void FileTransfer::SetTimeout(bool fast)
7216 +{
7217 +    rbuffer->SetTimeout(fast);
7218 +}
7219 +
7220 Index: mythtv/programs/mythbackend/autoexpire.cpp
7221 ===================================================================
7222 --- mythtv/programs/mythbackend/autoexpire.cpp  (.../tags/release-0-19) (revision 10931)
7223 +++ mythtv/programs/mythbackend/autoexpire.cpp  (.../branches/release-0-19-fixes)       (revision 10931)
7224 @@ -291,7 +291,8 @@
7225  
7226      if ((availFreeKB = getDiskSpace(record_file_prefix, tKB, uKB)) < 0)
7227      {
7228 -        QString msg = QString("ERROR: Could not calculate free space.");
7229 +        QString msg = QString("ERROR: Could not calculate free space for %1.")
7230 +                              .arg(record_file_prefix);
7231          VERBOSE(VB_IMPORTANT, LOC + msg);
7232          gContext->LogEntry("mythbackend", LP_WARNING,
7233                             "Autoexpire Recording", msg);
7234 Index: mythtv/programs/mythbackend/filetransfer.h
7235 ===================================================================
7236 --- mythtv/programs/mythbackend/filetransfer.h  (.../tags/release-0-19) (revision 10931)
7237 +++ mythtv/programs/mythbackend/filetransfer.h  (.../branches/release-0-19-fixes)       (revision 10931)
7238 @@ -35,6 +35,8 @@
7239  
7240      long long GetFileSize(void);
7241  
7242 +    void SetTimeout(bool fast);
7243 +
7244    private:
7245      bool readthreadlive;
7246      QMutex readthreadLock;
7247 Index: mythtv/programs/mythtv/main.cpp
7248 ===================================================================
7249 --- mythtv/programs/mythtv/main.cpp     (.../tags/release-0-19) (revision 10931)
7250 +++ mythtv/programs/mythtv/main.cpp     (.../branches/release-0-19-fixes)       (revision 10931)
7251 @@ -13,8 +13,6 @@
7252  #include <iostream>
7253  using namespace std;
7254  
7255 -MythContext *gContext;
7256 -
7257  static void *run_priv_thread(void *data)
7258  {
7259      (void)data;
7260 @@ -102,6 +100,9 @@
7261      
7262      gContext->LoadQtConfig();
7263  
7264 +#if defined(Q_OS_MACX) 
7265 +    // Mac OS X doesn't define the AudioOutputDevice setting 
7266 +#else
7267      QString auddevice = gContext->GetSetting("AudioOutputDevice");
7268      if (auddevice == "" || auddevice == QString::null)
7269      {
7270 @@ -109,6 +110,7 @@
7271                  "to run 'mythfrontend', not 'mythtv'.");
7272          return TV_EXIT_NO_AUDIO;
7273      }
7274 +#endif
7275  
7276      print_verbose_messages |= VB_PLAYBACK | VB_LIBAV;// | VB_AUDIO;
7277  
7278 @@ -132,6 +134,7 @@
7279          ProgramInfo *pginfo = new ProgramInfo();
7280          pginfo->endts = QDateTime::currentDateTime().addSecs(-180);
7281          pginfo->pathname = filename;
7282 +        pginfo->isVideo = true;
7283      
7284          tv->Playback(pginfo);
7285      }
7286 Index: mythtv/programs/mythfilldatabase/filldata.cpp
7287 ===================================================================
7288 --- mythtv/programs/mythfilldatabase/filldata.cpp       (.../tags/release-0-19) (revision 10931)
7289 +++ mythtv/programs/mythfilldatabase/filldata.cpp       (.../branches/release-0-19-fixes)       (revision 10931)
7290 @@ -337,7 +337,7 @@
7291  
7292      MSqlQuery query(MSqlQuery::InitCon());
7293      query.prepare("SELECT ch.chanid, nim.url "
7294 -            "FROM channel ch, callsignnetworkmap csm "
7295 +            "FROM (channel ch, callsignnetworkmap csm) "
7296              "RIGHT JOIN networkiconmap nim ON csm.network = nim.network "
7297              "WHERE ch.callsign = csm.callsign AND "
7298              "(icon = :NOICON OR icon = '') AND ch.sourceid = :SOURCEID");
7299 @@ -2174,7 +2174,8 @@
7300                          0 /*service id*/, major,            minor,
7301                          false /*use on air guide*/, false /*hidden*/,
7302                          false /*hidden in guide*/,
7303 -                        freqid,           localfile,        (*i).tvformat))
7304 +                        freqid,           localfile,        (*i).tvformat,
7305 +                        (*i).xmltvid))
7306                  {
7307                      cout << "### " << endl;
7308                      cout << "### Channel inserted" << endl;
7309 @@ -3851,7 +3852,6 @@
7310               VERBOSE(VB_IMPORTANT, "Failed to fetch some program info");
7311               gContext->LogEntry("mythfilldatabase", LP_WARNING,
7312                                  "Failed to fetch some program info", "");
7313 -             return FILLDB_EXIT_DB_ERROR;
7314          }
7315          else
7316              VERBOSE(VB_IMPORTANT, "Data fetching complete.");
7317 Index: mythtv/setup/backendsettings.cpp
7318 ===================================================================
7319 --- mythtv/setup/backendsettings.cpp    (.../tags/release-0-19) (revision 10931)
7320 +++ mythtv/setup/backendsettings.cpp    (.../branches/release-0-19-fixes)       (revision 10931)
7321 @@ -1,6 +1,7 @@
7322  #include <cstdio>
7323  
7324  #include "backendsettings.h"
7325 +#include "frequencies.h"
7326  #include "libmyth/mythcontext.h"
7327  #include "libmyth/settings.h"
7328  #include <unistd.h>
7329 @@ -110,23 +111,10 @@
7330  {
7331      GlobalComboBox *gc = new GlobalComboBox("FreqTable");
7332      gc->setLabel(QObject::tr("Channel frequency table"));
7333 -    gc->addSelection("us-cable");
7334 -    gc->addSelection("us-bcast");
7335 -    gc->addSelection("us-cable-hrc");
7336 -    gc->addSelection("us-cable-irc");
7337 -    gc->addSelection("japan-bcast");
7338 -    gc->addSelection("japan-cable");
7339 -    gc->addSelection("europe-west");
7340 -    gc->addSelection("europe-east");
7341 -    gc->addSelection("italy");
7342 -    gc->addSelection("newzealand");
7343 -    gc->addSelection("australia");
7344 -    gc->addSelection("ireland");
7345 -    gc->addSelection("france");
7346 -    gc->addSelection("china-bcast");
7347 -    gc->addSelection("southafrica");
7348 -    gc->addSelection("argentina");
7349 -    gc->addSelection("australia-optus");
7350 +
7351 +    for (uint i = 0; chanlists[i].name; i++)
7352 +        gc->addSelection(chanlists[i].name);
7353 +
7354      gc->setHelpText(QObject::tr("Select the appropriate frequency table for "
7355                      "your system.  If you have an antenna, use a \"-bcast\" "
7356                      "frequency."));
This page took 0.970811 seconds and 3 git commands to generate.