diff -ruN vdr-2.0.5/CONTRIBUTORS vdr-2.0.6/CONTRIBUTORS
--- vdr-2.0.5/CONTRIBUTORS	2013-12-25 12:41:06.000000000 +0100
+++ vdr-2.0.6/CONTRIBUTORS	2014-03-09 13:15:08.000000000 +0100
@@ -620,6 +620,8 @@
  command line option to be left empty to use the default values if only ENC shall be set
  for reporting an inconsistent behavior between opening the Recordings menu manually
  via the main menu and by pressing the Recordings key
+ for helping to debug a problem with frame detection in MPEG-2 streams that have "bottom fields"
+ or varying GOP structures
 
 Jeremy Hall <jhall@UU.NET>
  for fixing an incomplete initialization of the filter parameters in eit.c
@@ -704,6 +706,8 @@
  for reporting a problem with resuming replay of PES recordings
  for suggesting to make all bonded devices (except for the master) turn off their LNB
  power completely to avoid problems when receiving vertically polarized transponders
+ for reporting that there are channels that need even more than 10 TS packets in order
+ to detect the frame type
 
 Reinhard Walter Buchner <rw.buchner@freenet.de>
  for adding some satellites to 'sources.conf'
@@ -1171,6 +1175,9 @@
  for fixing the call to ChannelString() in cSkinLCARSDisplayChannel::SetChannel()
  for a patch that was used to rename the "plp id" to a more general "stream id"
  and add support for DVB-S2 "Input Stream Identifier" (ISI)
+ for fixing clearing non-editable members in the channel editor
+ for reporting a problem with adding new source types in case they are already
+ registered
 
 Ralf Klueber <ralf.klueber@vodafone.com>
  for reporting a bug in cutting a recording if there is only a single editing mark
@@ -2487,6 +2494,7 @@
 Antti Hartikainen <ami+vdr@ah.fi>
  for updating 'S13E' in 'sources.conf'
  for adding maximum SNR value for PCTV Systems nanoStick T2 290e
+ for updating 'sources.conf'
 
 Bernd Melcher <bernd@bernd-melcher.de>
  for reporting a problem with the 'servicedemo' plugin having no PLUGIN macro
@@ -2855,6 +2863,7 @@
  for reporting a possible crash if the recordings list is updated externally while the
  Recordings menu is open
  for reporting a missing closing ')' in the help entry of the --vfat option
+ for fixing learning keyboard remote control codes
 
 Alex Lasnier <alex@fepg.org>
  for adding tuning support for ATSC devices
@@ -2882,7 +2891,7 @@
  for suggesting to add handling MPEG audio type "ISO/IEC 14496-3 Audio with LATM
  transport syntax"
 
-Christopher Reimer <reimer.christopher@freenet.de>
+Christopher Reimer <vdr@creimer.net>
  for reporting a problem with external Dolby Digital processing via the '-a' option
  in live mode and with TS recordings
  for contributing to a patch that implements FHS support
@@ -2892,6 +2901,7 @@
  for making plugin Makefiles use DESTDIR and the 'install' program
  for suggesting to make sure that plugins include the VDR header files from the actual
  VDR source directory when doing "make plugins"
+ for reporting a possible crash in the OSD demo
 
 Stefan Huskamp <coca_cola1@gmx.de>
  for suggesting to make entering characters via the number keys
@@ -3187,3 +3197,20 @@
 
 Eike Edener <eike@edener.de>
  for reporting a bug in writing group separators to channels.conf that contain a comma
+
+Eike Sauer <EikeSauer@t-online.de>
+ for reporting a problem with channels that need more than 5 TS packets for detecting
+ frame borders
+ for reporting a problem in handling the frame detection buffer length
+
+Christian Paulick <cpaulick@xeatre.tv>
+ for reporting a problem with frame detection in MPEG-2 streams that have "bottom fields"
+ or varying GOP structures
+
+Mariusz Bialonczyk <manio@skyboo.net>
+ for reporting that acquiring the CA descriptors takes way too long on transponders
+ with many PAT entries, and his help in debugging this
+
+Christian Winkler <winkler_chr@yahoo.de>
+ for reporting a problem with transfer mode on full featured DVB cards for encrypted
+ channels that have no audio pid
diff -ruN vdr-2.0.5/HISTORY vdr-2.0.6/HISTORY
--- vdr-2.0.5/HISTORY	2014-01-07 10:28:31.000000000 +0100
+++ vdr-2.0.6/HISTORY	2014-03-22 12:03:39.000000000 +0100
@@ -7869,3 +7869,49 @@
 - Fixed setting the name of the video directory to avoid a crash when using --genindex,
   and also to use the correct directory with --edit (the latter reported by Marko
   Mäkelä).
+
+2014-03-16: Version 2.0.6
+
+- Updated 'sources.conf' (thanks to Antti Hartikainen).
+- cFont::CreateFont() now returns a dummy font in case there are no fonts installed.
+  This prevents a crash with the LCARS skin on a system that has no fonts.
+- Fixed detecting frame borders in MPEG-2 streams that have "bottom fields" or varying
+  GOP structures (reported by Christian Paulick, with help from Helmut Auer).
+- Fixed a wrong alignment in cCiDateTime::SendDateTime().
+- Now checking whether the primary device actually has a decoder before retuning the
+  current channel after a change in its parameters. This fixes broken recordings on
+  the primary device on "headless" systems.
+- Increased MIN_TS_PACKETS_FOR_FRAME_DETECTOR to 100 and introduced counting the number
+  of actual video TS packets in cTsPayload in order to be able to record channels that
+  sometimes need even more than 10 TS packets for detecting frame borders (reported by
+  Eike Sauer and Oliver Endriss).
+- Fixed sorting recordings by time in the Recordings menu if "Setup/OSD/Recording
+  directories" is set to "no".
+- Fixed clearing non-editable members in the channel editor (thanks to Rolf Ahrenberg).
+- Fixed flickering if subtitles are active while the OSD demo is running.
+- Fixed a possible crash in the OSD demo (reported by Christopher Reimer).
+- Fixed learning keyboard remote control codes (thanks to Lars Hanisch).
+- Fixed the replay progress display for very long recordings.
+- Improved PAT/PMT scanning to speed up initial tuning to encrypted channels on
+  transponders with many PAT entries (reported by Mariusz Bialonczyk).
+- Fixed detecting broken video data streams when recording.
+- Fixed handling frame detection buffer length (reported by Eike Sauer).
+- Fixed keeping the current position in the Recordings menu if a recording was
+  deleted in a sub folder.
+- Fixed handling transfer mode on full featured DVB cards for encrypted channels
+  that have no audio pid (reported by Christian Winkler).
+- Fixed a possible endless loop in cH264Parser::GetGolombUe(), which caused recordings
+  on some HD channels to get stuck and resulted in buffer overflows.
+- Fixed handling PAT packets when detecting frames, so that they can be properly
+  taken into account when regenerating the index of a recording.
+- Fixed adding new source types in case they are already registered (reported by Rolf
+  Ahrenberg).
+- Fixed drawing the live indicator in the LCARS skin in case there are no devices.
+- The SDT is now only parsed *after* the NIT has been read, and it explicitly uses
+  the source value derived from the NIT. This should prevent new channels from being
+  created with the wrong source.
+- Now initializing the isOnVideoDirectoryFileSystem member of cRecording when
+  scanning the video directory, so that it won't cause a delay when opening the menu
+  on a system with a large number of recordings.
+- The APIVERSION has been increased to 2.0.6 due to the changes to pat.h, sdt.h and
+  the functional modification to cFont::CreateFont().
diff -ruN vdr-2.0.5/PLUGINS/src/dvbhddevice/dvbhdffdevice.c vdr-2.0.6/PLUGINS/src/dvbhddevice/dvbhdffdevice.c
--- vdr-2.0.5/PLUGINS/src/dvbhddevice/dvbhdffdevice.c	2013-04-11 10:41:16.000000000 +0200
+++ vdr-2.0.6/PLUGINS/src/dvbhddevice/dvbhdffdevice.c	2014-02-27 18:09:59.000000000 +0100
@@ -377,8 +377,8 @@
 
   bool DoTune = !IsTunedToTransponder(Channel);
 
-  bool pidHandlesVideo = pidHandles[ptVideo].pid == vpid;
-  bool pidHandlesAudio = pidHandles[ptAudio].pid == apid;
+  bool pidHandlesVideo = vpid && pidHandles[ptVideo].pid == vpid;
+  bool pidHandlesAudio = apid && pidHandles[ptAudio].pid == apid;
 
   bool TurnOffLivePIDs = DoTune
                          || !IsPrimaryDevice()
diff -ruN vdr-2.0.5/PLUGINS/src/dvbsddevice/dvbsdffdevice.c vdr-2.0.6/PLUGINS/src/dvbsddevice/dvbsdffdevice.c
--- vdr-2.0.5/PLUGINS/src/dvbsddevice/dvbsdffdevice.c	2013-02-17 14:16:18.000000000 +0100
+++ vdr-2.0.6/PLUGINS/src/dvbsddevice/dvbsdffdevice.c	2014-02-27 18:10:51.000000000 +0100
@@ -3,7 +3,7 @@
  *
  * See the README file for copyright information and how to reach the author.
  *
- * $Id: dvbsdffdevice.c 2.35 2013/02/17 13:16:18 kls Exp $
+ * $Id: dvbsdffdevice.c 2.35.1.1 2014/02/27 17:10:51 kls Exp $
  */
 
 #include "dvbsdffdevice.h"
@@ -400,8 +400,8 @@
 
   bool DoTune = !IsTunedToTransponder(Channel);
 
-  bool pidHandlesVideo = pidHandles[ptVideo].pid == vpid;
-  bool pidHandlesAudio = pidHandles[ptAudio].pid == apid;
+  bool pidHandlesVideo = vpid && pidHandles[ptVideo].pid == vpid;
+  bool pidHandlesAudio = apid && pidHandles[ptAudio].pid == apid;
 
   bool TurnOffLivePIDs = DoTune
                          || !IsPrimaryDevice()
diff -ruN vdr-2.0.5/PLUGINS/src/osddemo/HISTORY vdr-2.0.6/PLUGINS/src/osddemo/HISTORY
--- vdr-2.0.5/PLUGINS/src/osddemo/HISTORY	2013-03-31 11:30:18.000000000 +0200
+++ vdr-2.0.6/PLUGINS/src/osddemo/HISTORY	2014-02-06 13:00:11.000000000 +0100
@@ -59,3 +59,8 @@
 2013-03-31: Version 2.0.0
 
 - Official release.
+
+2014-02-06: Version 2.0.1
+
+- Fixed flickering if subtitles are active while the OSD demo is running.
+- Fixed a possible crash in the OSD demo (reported by Christopher Reimer).
diff -ruN vdr-2.0.5/PLUGINS/src/osddemo/osddemo.c vdr-2.0.6/PLUGINS/src/osddemo/osddemo.c
--- vdr-2.0.5/PLUGINS/src/osddemo/osddemo.c	2013-03-31 11:30:18.000000000 +0200
+++ vdr-2.0.6/PLUGINS/src/osddemo/osddemo.c	2014-02-06 12:59:40.000000000 +0100
@@ -3,13 +3,13 @@
  *
  * See the README file for copyright information and how to reach the author.
  *
- * $Id: osddemo.c 2.12 2013/03/31 09:30:18 kls Exp $
+ * $Id: osddemo.c 2.12.1.2 2014/02/06 11:59:40 kls Exp $
  */
 
 #include <vdr/osd.h>
 #include <vdr/plugin.h>
 
-static const char *VERSION        = "2.0.0";
+static const char *VERSION        = "2.0.1";
 static const char *DESCRIPTION    = "Demo of arbitrary OSD setup";
 static const char *MAINMENUENTRY  = "Osd Demo";
 
@@ -119,7 +119,7 @@
 
 void cLineGame::Show(void)
 {
-  osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop(), 50);
+  osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
   if (osd) {
      int x1 = cOsd::OsdWidth() - 1;
      int y1 = cOsd::OsdHeight() - 1;
@@ -480,6 +480,8 @@
         if (Delta < FrameTime)
            cCondWait::SleepMs(FrameTime - Delta);
         }
+  destroyablePixmap = NULL;
+  toggleablePixmap = NULL;
   delete OsdFont;
   delete SmlFont;
   delete LrgFont;
@@ -496,7 +498,7 @@
 
 void cTrueColorDemo::Show(void)
 {
-  osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop(), 50);
+  osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
   if (osd) {
      if (SetArea()) {
         osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, clrGray50);
diff -ruN vdr-2.0.5/ci.c vdr-2.0.6/ci.c
--- vdr-2.0.5/ci.c	2013-02-17 14:17:28.000000000 +0100
+++ vdr-2.0.6/ci.c	2014-01-22 10:43:48.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: ci.c 2.12 2013/02/17 13:17:28 kls Exp $
+ * $Id: ci.c 2.12.1.1 2014/01/22 09:43:48 kls Exp $
  */
 
 #include "ci.h"
@@ -846,7 +846,9 @@
      int L = (M == 1 || M == 2) ? 1 : 0;
      int MJD = 14956 + D + int((Y - L) * 365.25) + int((M + 1 + L * 12) * 30.6001);
 #define DEC2BCD(d) uint8_t(((d / 10) << 4) + (d % 10))
+#pragma pack(1)
      struct tTime { uint16_t mjd; uint8_t h, m, s; short offset; };
+#pragma pack()
      tTime T = { mjd : htons(MJD), h : DEC2BCD(tm_gmt.tm_hour), m : DEC2BCD(tm_gmt.tm_min), s : DEC2BCD(tm_gmt.tm_sec), offset : short(htons(tm_loc.tm_gmtoff / 60)) };
      bool OldDumpTPDUDataTransfer = DumpTPDUDataTransfer;
      DumpTPDUDataTransfer &= DumpDateTime;
diff -ruN vdr-2.0.5/config.h vdr-2.0.6/config.h
--- vdr-2.0.5/config.h	2013-10-29 17:06:45.000000000 +0100
+++ vdr-2.0.6/config.h	2014-03-22 12:00:00.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: config.h 2.76.1.5 2013/10/29 16:06:45 kls Exp $
+ * $Id: config.h 2.76.1.7 2014/03/22 11:00:00 kls Exp $
  */
 
 #ifndef __CONFIG_H
@@ -22,13 +22,13 @@
 
 // VDR's own version number:
 
-#define VDRVERSION  "2.0.5"
-#define VDRVERSNUM   20005  // Version * 10000 + Major * 100 + Minor
+#define VDRVERSION  "2.0.6"
+#define VDRVERSNUM   20006  // Version * 10000 + Major * 100 + Minor
 
 // The plugin API's version number:
 
-#define APIVERSION  "2.0.0"
-#define APIVERSNUM   20000  // Version * 10000 + Major * 100 + Minor
+#define APIVERSION  "2.0.6"
+#define APIVERSNUM   20006  // Version * 10000 + Major * 100 + Minor
 
 // When loading plugins, VDR searches them by their APIVERSION, which
 // may be smaller than VDRVERSION in case there have been no changes to
diff -ruN vdr-2.0.5/device.c vdr-2.0.6/device.c
--- vdr-2.0.5/device.c	2013-08-22 12:35:30.000000000 +0200
+++ vdr-2.0.6/device.c	2014-03-11 10:29:52.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: device.c 2.74.1.2 2013/08/22 10:35:30 kls Exp $
+ * $Id: device.c 2.74.1.4 2014/03/11 09:29:52 kls Exp $
  */
 
 #include "device.h"
@@ -574,7 +574,7 @@
      AttachFilter(eitFilter = new cEitFilter);
      AttachFilter(patFilter = new cPatFilter);
      AttachFilter(sdtFilter = new cSdtFilter(patFilter));
-     AttachFilter(nitFilter = new cNitFilter);
+     AttachFilter(nitFilter = new cNitFilter(sdtFilter));
      }
 }
 
@@ -785,6 +785,7 @@
      if (SetChannelDevice(Channel, LiveView)) {
         // Start section handling:
         if (sectionHandler) {
+           patFilter->Trigger(Channel->Sid());
            sectionHandler->SetChannel(Channel);
            sectionHandler->SetStatus(true);
            }
diff -ruN vdr-2.0.5/font.c vdr-2.0.6/font.c
--- vdr-2.0.5/font.c	2013-04-07 16:54:15.000000000 +0200
+++ vdr-2.0.6/font.c	2014-01-25 15:25:29.000000000 +0100
@@ -6,7 +6,7 @@
  *
  * BiDi support by Osama Alrawab <alrawab@hotmail.com> @2008 Tripoli-Libya.
  *
- * $Id: font.c 2.13.1.1 2013/04/07 14:54:15 kls Exp $
+ * $Id: font.c 2.13.1.2 2014/01/25 14:25:29 kls Exp $
  */
 
 #include "font.h"
@@ -382,10 +382,13 @@
 // A dummy font, in case there are no fonts installed:
 
 class cDummyFont : public cFont {
+private:
+  int height;
 public:
-  virtual int Width(uint c) const { return 10; }
-  virtual int Width(const char *s) const { return 50; }
-  virtual int Height(void) const { return 20; }
+  cDummyFont(int CharHeight) { height = CharHeight; }
+  virtual int Width(uint c) const { return height; }
+  virtual int Width(const char *s) const { return height; }
+  virtual int Height(void) const { return height; }
   virtual void DrawText(cBitmap *Bitmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const {}
   virtual void DrawText(cPixmap *Pixmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const {};
   };
@@ -396,11 +399,8 @@
 
 void cFont::SetFont(eDvbFont Font, const char *Name, int CharHeight)
 {
-  cFont *f = CreateFont(Name, constrain(CharHeight, MINFONTSIZE, MAXFONTSIZE));
-  if (!f || !f->Height())
-     f = new cDummyFont;
   delete fonts[Font];
-  fonts[Font] = f;
+  fonts[Font] = CreateFont(Name, constrain(CharHeight, MINFONTSIZE, MAXFONTSIZE));
 }
 
 const cFont *cFont::GetFont(eDvbFont Font)
@@ -423,9 +423,10 @@
 cFont *cFont::CreateFont(const char *Name, int CharHeight, int CharWidth)
 {
   cString fn = GetFontFileName(Name);
-  if (*fn)
-     return new cFreetypeFont(fn, CharHeight, CharWidth);
-  return NULL;
+  cFont *f = *fn ? new cFreetypeFont(fn, CharHeight, CharWidth) : NULL;
+  if (!f || !f->Height())
+     f = new cDummyFont(CharHeight);
+  return f;
 }
 
 bool cFont::GetAvailableFontNames(cStringList *FontNames, bool Monospaced)
diff -ruN vdr-2.0.5/font.h vdr-2.0.6/font.h
--- vdr-2.0.5/font.h	2013-02-17 14:17:42.000000000 +0100
+++ vdr-2.0.6/font.h	2014-01-25 15:24:51.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: font.h 2.7 2013/02/17 13:17:42 kls Exp $
+ * $Id: font.h 2.7.1.1 2014/01/25 14:24:51 kls Exp $
  */
 
 #ifndef __FONT_H
@@ -75,7 +75,7 @@
           ///< default width. Name is of the form "Family:Style", for instance
           ///< "Verdana:Bold Italic" or "Times New Roman". See GetAvailableFontNames()
           ///< for how to get a list of all available font names.
-          ///< If the requested font can't be created, NULL is returned.
+          ///< If the requested font can't be created, a dummy font is returned.
           ///< The caller must delete the font when it is no longer needed.
   static bool GetAvailableFontNames(cStringList *FontNames, bool Monospaced = false);
           ///< Queries the font configuration for a list of available font names,
diff -ruN vdr-2.0.5/menu.c vdr-2.0.6/menu.c
--- vdr-2.0.5/menu.c	2013-10-16 11:46:24.000000000 +0200
+++ vdr-2.0.6/menu.c	2014-02-26 12:42:28.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: menu.c 2.82.1.5 2013/10/16 09:46:24 kls Exp $
+ * $Id: menu.c 2.82.1.8 2014/02/26 11:42:28 kls Exp $
  */
 
 #include "menu.h"
@@ -181,9 +181,13 @@
      strn0cpy(name, data.name, sizeof(name));
      if (New) {
         channel = NULL;
+        // clear non-editable members:
         data.nid = 0;
         data.tid = 0;
         data.rid = 0;
+        *data.shortName  = 0;
+        *data.provider   = 0;
+        *data.portalName = 0;
         }
      }
   Setup();
@@ -2185,6 +2189,7 @@
   const char *Name(void) { return name; }
   cRecording *Recording(void) { return recording; }
   bool IsDirectory(void) { return name != NULL; }
+  void SetRecording(cRecording *Recording) { recording = Recording; }
   virtual void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable);
   };
 
@@ -2416,6 +2421,7 @@
            Display();
            if (!Count())
               return osBack;
+           return osUser2;
            }
         else
            Skins.Message(mtError, tr("Error while deleting recording!"));
@@ -2481,6 +2487,14 @@
        default: break;
        }
      }
+  else if (state == osUser2) {
+     // a recording in a sub folder was deleted, so update the current item
+     cOsdMenu *m = HasSubMenu() ? SubMenu() : this;
+     if (cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current())) {
+        if (cMenuRecordingItem *riSub = (cMenuRecordingItem *)m->Get(m->Current()))
+           ri->SetRecording(riSub->Recording());
+        }
+     }
   if (Key == kYellow && HadSubMenu && !HasSubMenu()) {
      // the last recording in a subdirectory was deleted, so let's go back up
      cOsdMenu::Del(Current());
@@ -2648,7 +2662,7 @@
         ModifiedAppearance = true;
      if (strcmp(data.FontFix, Setup.FontFix) || !DoubleEqual(data.FontFixSizeP, Setup.FontFixSizeP))
         ModifiedAppearance = true;
-     if (data.AlwaysSortFoldersFirst != Setup.AlwaysSortFoldersFirst)
+     if (data.AlwaysSortFoldersFirst != Setup.AlwaysSortFoldersFirst || data.RecordingDirs != Setup.RecordingDirs)
         Recordings.ClearSortNames();
      }
 
diff -ruN vdr-2.0.5/nit.c vdr-2.0.6/nit.c
--- vdr-2.0.5/nit.c	2013-03-07 10:42:29.000000000 +0100
+++ vdr-2.0.6/nit.c	2014-03-11 10:29:59.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: nit.c 2.10 2013/03/07 09:42:29 kls Exp $
+ * $Id: nit.c 2.10.1.1 2014/03/11 09:29:59 kls Exp $
  */
 
 #include "nit.h"
@@ -19,8 +19,9 @@
 #define DVB_SYSTEM_1 0 // see also dvbdevice.c
 #define DVB_SYSTEM_2 1
 
-cNitFilter::cNitFilter(void)
+cNitFilter::cNitFilter(cSdtFilter *SdtFilter)
 {
+  sdtFilter = SdtFilter;
   numNits = 0;
   networkId = 0;
   Set(0x10, 0x40);  // NIT
@@ -183,6 +184,7 @@
                            }
                        }
                     }
+                 sdtFilter->Trigger(Source);
                  }
                  break;
             case SI::S2SatelliteDeliverySystemDescriptorTag: {
@@ -253,6 +255,7 @@
                            }
                        }
                     }
+                 sdtFilter->Trigger(Source);
                  }
                  break;
             case SI::TerrestrialDeliverySystemDescriptorTag: {
@@ -316,6 +319,7 @@
                            }
                         }
                     }
+                 sdtFilter->Trigger(Source);
                  }
                  break;
             case SI::ExtensionDescriptorTag: {
diff -ruN vdr-2.0.5/nit.h vdr-2.0.6/nit.h
--- vdr-2.0.5/nit.h	2007-06-10 10:50:21.000000000 +0200
+++ vdr-2.0.6/nit.h	2014-03-11 10:30:05.000000000 +0100
@@ -4,13 +4,14 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: nit.h 2.0 2007/06/10 08:50:21 kls Exp $
+ * $Id: nit.h 2.0.1.1 2014/03/11 09:30:05 kls Exp $
  */
 
 #ifndef __NIT_H
 #define __NIT_H
 
 #include "filter.h"
+#include "sdt.h"
 
 #define MAXNITS 16
 #define MAXNETWORKNAME Utf8BufSize(256)
@@ -26,13 +27,14 @@
     };
 
   cSectionSyncer sectionSyncer;
+  cSdtFilter *sdtFilter;
   cNit nits[MAXNITS];
   u_short networkId;
   int numNits;
 protected:
   virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
 public:
-  cNitFilter(void);
+  cNitFilter(cSdtFilter *SdtFilter);
   virtual void SetStatus(bool On);
   };
 
diff -ruN vdr-2.0.5/pat.c vdr-2.0.6/pat.c
--- vdr-2.0.5/pat.c	2012-11-25 15:12:21.000000000 +0100
+++ vdr-2.0.6/pat.c	2014-02-19 10:31:29.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: pat.c 2.19 2012/11/25 14:12:21 kls Exp $
+ * $Id: pat.c 2.19.1.2 2014/02/19 09:31:29 kls Exp $
  */
 
 #include "pat.h"
@@ -12,9 +12,8 @@
 #include "channels.h"
 #include "libsi/section.h"
 #include "libsi/descriptor.h"
-#include "thread.h"
 
-#define PMT_SCAN_TIMEOUT  10 // seconds
+#define PMT_SCAN_TIMEOUT  1000 // ms
 
 // --- cCaDescriptor ---------------------------------------------------------
 
@@ -229,94 +228,115 @@
 
 // --- cPatFilter ------------------------------------------------------------
 
+//#define DEBUG_PAT_PMT
+#ifdef DEBUG_PAT_PMT
+#define DBGLOG(a...) { cString s = cString::sprintf(a); fprintf(stderr, "%s\n", *s); dsyslog("%s", *s); }
+#else
+#define DBGLOG(a...)
+#endif
+
 cPatFilter::cPatFilter(void)
 {
-  pmtIndex = 0;
-  pmtPid = 0;
-  pmtSid = 0;
-  lastPmtScan = 0;
-  numPmtEntries = 0;
+  Trigger(0);
   Set(0x00, 0x00);  // PAT
 }
 
 void cPatFilter::SetStatus(bool On)
 {
+  cMutexLock MutexLock(&mutex);
+  DBGLOG("PAT filter set status %d", On);
   cFilter::SetStatus(On);
-  pmtIndex = 0;
-  pmtPid = 0;
-  pmtSid = 0;
-  lastPmtScan = 0;
-  numPmtEntries = 0;
+  Trigger();
 }
 
-void cPatFilter::Trigger(void)
+void cPatFilter::Trigger(int Sid)
 {
+  cMutexLock MutexLock(&mutex);
+  patVersion = -1;
+  pmtIndex = -1;
   numPmtEntries = 0;
+  if (Sid >= 0) {
+     sid = Sid;
+     DBGLOG("PAT filter trigger SID %d", Sid);
+     }
 }
 
-bool cPatFilter::PmtVersionChanged(int PmtPid, int Sid, int Version)
+bool cPatFilter::PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion)
 {
-  uint64_t v = Version;
-  v <<= 32;
-  uint64_t id = (PmtPid | (Sid << 16)) & 0x00000000FFFFFFFFLL;
+  int Id = MakePmtId(PmtPid, Sid);
   for (int i = 0; i < numPmtEntries; i++) {
-      if ((pmtVersion[i] & 0x00000000FFFFFFFFLL) == id) {
-         bool Changed = (pmtVersion[i] & 0x000000FF00000000LL) != v;
-         if (Changed)
-            pmtVersion[i] = id | v;
-         return Changed;
+      if (pmtId[i] == Id) {
+         if (pmtVersion[i] != Version) {
+            if (SetNewVersion)
+               pmtVersion[i] = Version;
+            else
+               DBGLOG("PMT %d  %2d %5d %2d -> %2d", Transponder(), i, PmtPid, pmtVersion[i], Version);
+            return true;
+            }
+         break;
          }
       }
-  if (numPmtEntries < MAXPMTENTRIES)
-     pmtVersion[numPmtEntries++] = id | v;
-  return true;
+  return false;
+}
+
+void cPatFilter::SwitchToNextPmtPid(void)
+{
+  if (pmtIndex >= 0) {
+     Del(GetPmtPid(pmtIndex), SI::TableIdPMT);
+     pmtIndex = (pmtIndex + 1) % numPmtEntries;
+     Add(GetPmtPid(pmtIndex), SI::TableIdPMT);
+     }
 }
 
 void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
 {
+  cMutexLock MutexLock(&mutex);
   if (Pid == 0x00) {
-     if (Tid == 0x00) {
-        if (pmtPid && time(NULL) - lastPmtScan > PMT_SCAN_TIMEOUT) {
-           Del(pmtPid, 0x02);
-           pmtPid = 0;
-           pmtIndex++;
-           lastPmtScan = time(NULL);
-           }
-        if (!pmtPid) {
-           SI::PAT pat(Data, false);
-           if (!pat.CheckCRCAndParse())
-              return;
+     if (Tid == SI::TableIdPAT) {
+        SI::PAT pat(Data, false);
+        if (!pat.CheckCRCAndParse())
+           return;
+        if (pat.getVersionNumber() != patVersion) {
+           DBGLOG("PAT %d %d -> %d", Transponder(), patVersion, pat.getVersionNumber());
+           if (pmtIndex >= 0) {
+              Del(GetPmtPid(pmtIndex), SI::TableIdPMT);
+              pmtIndex = -1;
+              }
+           numPmtEntries = 0;
            SI::PAT::Association assoc;
-           int Index = 0;
            for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); ) {
-               if (!assoc.isNITPid()) {
-                  if (Index++ >= pmtIndex && Channels.GetByServiceID(Source(), Transponder(), assoc.getServiceId())) {
-                     pmtPid = assoc.getPid();
-                     pmtSid = assoc.getServiceId();
-                     Add(pmtPid, 0x02);
-                     break;
+               if (!assoc.isNITPid() && numPmtEntries < MAXPMTENTRIES) {
+                  DBGLOG("    PMT pid %2d %5d  SID %5d", numPmtEntries, assoc.getPid(), assoc.getServiceId());
+                  pmtId[numPmtEntries] = MakePmtId(assoc.getPid(), assoc.getServiceId());
+                  pmtVersion[numPmtEntries] = -1;
+                  if (sid == assoc.getServiceId()) {
+                     pmtIndex = numPmtEntries;
+                     DBGLOG("sid = %d pmtIndex = %d", sid, pmtIndex);
                      }
+                  numPmtEntries++;
                   }
                }
-           if (!pmtPid)
+           if (numPmtEntries > 0 && pmtIndex < 0)
               pmtIndex = 0;
+           Add(GetPmtPid(pmtIndex), SI::TableIdPMT);
+           patVersion = pat.getVersionNumber();
+           timer.Set(PMT_SCAN_TIMEOUT);
            }
         }
      }
-  else if (Pid == pmtPid && Tid == SI::TableIdPMT && Source() && Transponder()) {
+  else if (Tid == SI::TableIdPMT && Source() && Transponder()) {
+     timer.Set(PMT_SCAN_TIMEOUT);
      SI::PMT pmt(Data, false);
      if (!pmt.CheckCRCAndParse())
         return;
-     if (pmt.getServiceId() != pmtSid)
-        return; // skip broken PMT records
-     if (!PmtVersionChanged(pmtPid, pmt.getTableIdExtension(), pmt.getVersionNumber())) {
-        lastPmtScan = 0; // this triggers the next scan
+     if (!PmtVersionChanged(Pid, pmt.getTableIdExtension(), pmt.getVersionNumber())) {
+        SwitchToNextPmtPid();
         return;
         }
-     if (!Channels.Lock(true, 10)) {
-        numPmtEntries = 0; // to make sure we try again
+     if (!Channels.Lock(true, 10))
         return;
-        }
+     PmtVersionChanged(Pid, pmt.getTableIdExtension(), pmt.getVersionNumber(), true);
+     SwitchToNextPmtPid();
      cChannel *Channel = Channels.GetByServiceID(Source(), Transponder(), pmt.getServiceId());
      if (Channel) {
         SI::CaDescriptor *d;
@@ -552,7 +572,12 @@
            }
         Channel->SetCaDescriptors(CaDescriptorHandler.AddCaDescriptors(CaDescriptors));
         }
-     lastPmtScan = 0; // this triggers the next scan
      Channels.Unlock();
      }
+  if (timer.TimedOut()) {
+     if (pmtIndex >= 0)
+        DBGLOG("PMT timeout %d", pmtIndex);
+     SwitchToNextPmtPid();
+     timer.Set(PMT_SCAN_TIMEOUT);
+     }
 }
diff -ruN vdr-2.0.5/pat.h vdr-2.0.6/pat.h
--- vdr-2.0.5/pat.h	2013-02-16 16:20:24.000000000 +0100
+++ vdr-2.0.6/pat.h	2014-02-18 15:12:24.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: pat.h 2.3 2013/02/16 15:20:24 kls Exp $
+ * $Id: pat.h 2.3.1.1 2014/02/18 14:12:24 kls Exp $
  */
 
 #ifndef __PAT_H
@@ -12,24 +12,30 @@
 
 #include <stdint.h>
 #include "filter.h"
+#include "thread.h"
 
 #define MAXPMTENTRIES 64
 
 class cPatFilter : public cFilter {
 private:
-  time_t lastPmtScan;
+  cMutex mutex;
+  cTimeMs timer;
+  int patVersion;
   int pmtIndex;
-  int pmtPid;
-  int pmtSid;
-  uint64_t pmtVersion[MAXPMTENTRIES];
+  int pmtId[MAXPMTENTRIES];
+  int pmtVersion[MAXPMTENTRIES];
   int numPmtEntries;
-  bool PmtVersionChanged(int PmtPid, int Sid, int Version);
+  int sid;
+  int GetPmtPid(int Index) { return pmtId[Index] & 0x0000FFFF; }
+  int MakePmtId(int PmtPid, int Sid) { return PmtPid | (Sid << 16); }
+  bool PmtVersionChanged(int PmtPid, int Sid, int Version, bool SetNewVersion = false);
+  void SwitchToNextPmtPid(void);
 protected:
   virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
 public:
   cPatFilter(void);
   virtual void SetStatus(bool On);
-  void Trigger(void);
+  void Trigger(int Sid = -1);
   };
 
 int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
diff -ruN vdr-2.0.5/recorder.c vdr-2.0.6/recorder.c
--- vdr-2.0.5/recorder.c	2013-10-12 14:10:05.000000000 +0200
+++ vdr-2.0.6/recorder.c	2014-02-21 10:21:30.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: recorder.c 2.17.1.1 2013/10/12 12:10:05 kls Exp $
+ * $Id: recorder.c 2.17.1.2 2014/02/21 09:21:30 kls Exp $
  */
 
 #include "recorder.h"
@@ -154,13 +154,13 @@
                              recordFile->Write(pmt, TS_SIZE);
                              fileSize += TS_SIZE;
                              }
+                       t.Set(MAXBROKENTIMEOUT);
                        }
                     if (recordFile->Write(b, Count) < 0) {
                        LOG_ERROR_STR(fileName->Name());
                        break;
                        }
                     fileSize += Count;
-                    t.Set(MAXBROKENTIMEOUT);
                     }
                  }
               ringBuffer->Del(Count);
diff -ruN vdr-2.0.5/recording.c vdr-2.0.6/recording.c
--- vdr-2.0.5/recording.c	2013-12-25 11:55:32.000000000 +0100
+++ vdr-2.0.6/recording.c	2014-03-16 12:03:18.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: recording.c 2.91.1.3 2013/12/25 10:55:32 kls Exp $
+ * $Id: recording.c 2.91.1.7 2014/03/16 11:03:18 kls Exp $
  */
 
 #include "recording.h"
@@ -958,14 +958,22 @@
 {
   char **sb = (RecordingsSortMode == rsmName) ? &sortBufferName : &sortBufferTime;
   if (!*sb) {
-     char *s = strdup(FileName() + strlen(VideoDirectory));
-     if (RecordingsSortMode != rsmName || Setup.AlwaysSortFoldersFirst)
-        s = StripEpisodeName(s, RecordingsSortMode != rsmName);
-     strreplace(s, '/', '0'); // some locales ignore '/' when sorting
-     int l = strxfrm(NULL, s, 0) + 1;
-     *sb = MALLOC(char, l);
-     strxfrm(*sb, s, l);
-     free(s);
+     if (RecordingsSortMode == rsmTime && !Setup.RecordingDirs) {
+        char buf[32];
+        struct tm tm_r;
+        strftime(buf, sizeof(buf), "%Y%m%d%H%I", localtime_r(&start, &tm_r));
+        *sb = strdup(buf);
+        }
+     else {
+        char *s = strdup(FileName() + strlen(VideoDirectory));
+        if (RecordingsSortMode != rsmName || Setup.AlwaysSortFoldersFirst)
+           s = StripEpisodeName(s, RecordingsSortMode != rsmName);
+        strreplace(s, '/', '0'); // some locales ignore '/' when sorting
+        int l = strxfrm(NULL, s, 0) + 1;
+        *sb = MALLOC(char, l);
+        strxfrm(*sb, s, l);
+        free(s);
+        }
      }
   return *sb;
 }
@@ -1300,6 +1308,7 @@
                     if (r->Name()) {
                        r->NumFrames(); // initializes the numFrames member
                        r->FileSizeMB(); // initializes the fileSizeMB member
+                       r->IsOnVideoDirectoryFileSystem(); // initializes the isOnVideoDirectoryFileSystem member
                        if (deleted)
                           r->deleted = time(NULL);
                        Lock();
diff -ruN vdr-2.0.5/remote.c vdr-2.0.6/remote.c
--- vdr-2.0.5/remote.c	2013-02-03 16:44:55.000000000 +0100
+++ vdr-2.0.6/remote.c	2014-02-15 13:44:48.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: remote.c 2.8 2013/02/03 15:44:55 kls Exp $
+ * $Id: remote.c 2.8.1.1 2014/02/15 12:44:48 kls Exp $
  */
 
 #include "remote.h"
@@ -297,7 +297,7 @@
 
 void cKbdRemote::PutKey(uint64_t Code, bool Repeat, bool Release)
 {
-  if (rawMode || !Put(Code, Repeat, Release)) {
+  if (rawMode || (!Put(Code, Repeat, Release) && !IsLearning())) {
      if (int func = MapCodeToFunc(Code))
         Put(KBDKEY(func), Repeat, Release);
      }
diff -ruN vdr-2.0.5/remux.c vdr-2.0.6/remux.c
--- vdr-2.0.5/remux.c	2013-03-03 11:37:58.000000000 +0100
+++ vdr-2.0.6/remux.c	2014-03-08 16:10:24.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: remux.c 2.75 2013/03/03 10:37:58 kls Exp $
+ * $Id: remux.c 2.75.1.5 2014/03/08 15:10:24 kls Exp $
  */
 
 #include "remux.h"
@@ -23,6 +23,10 @@
 #define dbgpatpmt(a...) if (DebugPatPmt) fprintf(stderr, a)
 #define dbgframes(a...) if (DebugFrames) fprintf(stderr, a)
 
+#define MAX_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION 6
+#define WRN_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION (MAX_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION / 2)
+#define WRN_TS_PACKETS_FOR_FRAME_DETECTOR (MIN_TS_PACKETS_FOR_FRAME_DETECTOR / 2)
+
 #define EMPTY_SCANNER (0xFFFFFFFF)
 
 ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader)
@@ -231,7 +235,7 @@
   data = NULL;
   length = 0;
   pid = -1;
-  index = 0;
+  Reset();
 }
 
 cTsPayload::cTsPayload(uchar *Data, int Length, int Pid)
@@ -239,12 +243,25 @@
   Setup(Data, Length, Pid);
 }
 
+uchar cTsPayload::SetEof(void)
+{
+  length = index; // triggers EOF
+  return 0x00;
+}
+
+void cTsPayload::Reset(void)
+{
+  index = 0;
+  numPacketsPid = 0;
+  numPacketsOther = 0;
+}
+
 void cTsPayload::Setup(uchar *Data, int Length, int Pid)
 {
   data = Data;
   length = Length;
   pid = Pid >= 0 ? Pid : TsPid(Data);
-  index = 0;
+  Reset();
 }
 
 uchar cTsPayload::GetByte(void)
@@ -255,20 +272,22 @@
             if (data[index] == TS_SYNC_BYTE && index + TS_SIZE <= length) { // to make sure we are at a TS header start and drop incomplete TS packets at the end
                uchar *p = data + index;
                if (TsPid(p) == pid) { // only handle TS packets for the initial PID
+                  if (++numPacketsPid > MAX_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION)
+                     return SetEof();
                   if (TsHasPayload(p)) {
-                     if (index > 0 && TsPayloadStart(p)) { // checking index to not skip the very first TS packet
-                        length = index; // triggers EOF
-                        return 0x00;
-                        }
+                     if (index > 0 && TsPayloadStart(p)) // checking index to not skip the very first TS packet
+                        return SetEof();
                      index += TsPayloadOffset(p);
                      break;
                      }
                   }
+               else if (TsPid(p) == PATPID)
+                  return SetEof(); // caller must see PAT packets in case of index regeneration
+               else
+                  numPacketsOther++;
                }
-            else {
-               length = index; // triggers EOF
-               return 0x00;
-               }
+            else
+               return SetEof();
            }
         }
      return data[index++];
@@ -302,6 +321,8 @@
 bool cTsPayload::Find(uint32_t Code)
 {
   int OldIndex = index;
+  int OldNumPacketsPid = numPacketsPid;
+  int OldNumPacketsOther = numPacketsOther;
   uint32_t Scanner = EMPTY_SCANNER;
   while (!Eof()) {
         Scanner = (Scanner << 8) | GetByte();
@@ -309,9 +330,19 @@
            return true;
         }
   index = OldIndex;
+  numPacketsPid = OldNumPacketsPid;
+  numPacketsOther = OldNumPacketsOther;
   return false;
 }
 
+void cTsPayload::Statistics(void) const
+{
+  if (numPacketsPid + numPacketsOther > WRN_TS_PACKETS_FOR_FRAME_DETECTOR)
+     dsyslog("WARNING: required (%d+%d) TS packets to determine frame type", numPacketsOther, numPacketsPid);
+  if (numPacketsPid > WRN_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION)
+     dsyslog("WARNING: required %d video TS packets to determine frame type", numPacketsPid);
+}
+
 // --- cPatPmtGenerator ------------------------------------------------------
 
 cPatPmtGenerator::cPatPmtGenerator(const cChannel *Channel)
@@ -1004,6 +1035,7 @@
   bool debug;
   bool newFrame;
   bool independentFrame;
+  int iFrameTemporalReferenceOffset;
 public:
   cFrameParser(void);
   virtual ~cFrameParser() {};
@@ -1017,6 +1049,7 @@
   void SetDebug(bool Debug) { debug = Debug; }
   bool NewFrame(void) { return newFrame; }
   bool IndependentFrame(void) { return independentFrame; }
+  int IFrameTemporalReferenceOffset(void) { return iFrameTemporalReferenceOffset; }
   };
 
 cFrameParser::cFrameParser(void)
@@ -1024,6 +1057,7 @@
   debug = true;
   newFrame = false;
   independentFrame = false;
+  iFrameTemporalReferenceOffset = 0;
 }
 
 // --- cAudioParser ----------------------------------------------------------
@@ -1056,6 +1090,7 @@
 private:
   uint32_t scanner;
   bool seenIndependentFrame;
+  int lastIFrameTemporalReference;
 public:
   cMpeg2Parser(void);
   virtual int Parse(const uchar *Data, int Length, int Pid);
@@ -1065,6 +1100,7 @@
 {
   scanner = EMPTY_SCANNER;
   seenIndependentFrame = false;
+  lastIFrameTemporalReference = -1; // invalid
 }
 
 int cMpeg2Parser::Parse(const uchar *Data, int Length, int Pid)
@@ -1089,10 +1125,25 @@
             scanner = OldScanner;
             return tsPayload.Used() - TS_SIZE;
             }
+         uchar b1 = tsPayload.GetByte();
+         uchar b2 = tsPayload.GetByte();
+         int TemporalReference = (b1 << 2 ) + ((b2 & 0xC0) >> 6);
+         uchar FrameType = (b2 >> 3) & 0x07;
+         if (tsPayload.Find(0x000001B5)) { // Extension start code
+            if (((tsPayload.GetByte() & 0xF0) >> 4) == 0x08) { // Picture coding extension
+               tsPayload.GetByte();
+               uchar PictureStructure = tsPayload.GetByte() & 0x03;
+               if (PictureStructure == 0x02) // bottom field
+                  break;
+               }
+            }
          newFrame = true;
-         tsPayload.GetByte();
-         uchar FrameType = (tsPayload.GetByte() >> 3) & 0x07;
          independentFrame = FrameType == 1; // I-Frame
+         if (independentFrame) {
+            if (lastIFrameTemporalReference >= 0)
+               iFrameTemporalReferenceOffset = TemporalReference - lastIFrameTemporalReference;
+            lastIFrameTemporalReference = TemporalReference;
+            }
          if (debug) {
             seenIndependentFrame |= independentFrame;
             if (seenIndependentFrame) {
@@ -1100,11 +1151,11 @@
                dbgframes("%c", FrameTypes[FrameType]);
                }
             }
+         tsPayload.Statistics();
          break;
          }
       if (tsPayload.AtPayloadStart() // stop at any new payload start to have the buffer refilled if necessary
-         || (tsPayload.Available() < MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE // stop if the available data is below the limit...
-            && (tsPayload.Available() <= 0 || tsPayload.AtTsStart()))) // ...but only if there is no more data at all, or if we are at a TS boundary
+         || tsPayload.Eof()) // or if we're out of data
          break;
       }
   return tsPayload.Used();
@@ -1203,7 +1254,7 @@
 uint32_t cH264Parser::GetGolombUe(void)
 {
   int z = -1;
-  for (int b = 0; !b; z++)
+  for (int b = 0; !b && z < 32; z++) // limiting z to no get stuck if GetBit() always returns 0
       b = GetBit();
   return (1 << z) - 1 + GetBits(z);
 }
@@ -1239,13 +1290,17 @@
            case nutAccessUnitDelimiter:  ParseAccessUnitDelimiter();
                                          gotAccessUnitDelimiter = true;
                                          break;
-           case nutSequenceParameterSet: ParseSequenceParameterSet();
-                                         gotSequenceParameterSet = true;
+           case nutSequenceParameterSet: if (gotAccessUnitDelimiter) {
+                                            ParseSequenceParameterSet();
+                                            gotSequenceParameterSet = true;
+                                            }
                                          break;
            case nutCodedSliceNonIdr:
            case nutCodedSliceIdr:        if (gotAccessUnitDelimiter && gotSequenceParameterSet) {
                                             ParseSliceHeader();
                                             gotAccessUnitDelimiter = false;
+                                            if (newFrame)
+                                               tsPayload.Statistics();
                                             return tsPayload.Used();
                                             }
                                          break;
@@ -1253,8 +1308,7 @@
            }
          }
       if (tsPayload.AtPayloadStart() // stop at any new payload start to have the buffer refilled if necessary
-         || (tsPayload.Available() < MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE // stop if the available data is below the limit...
-            && (tsPayload.Available() <= 0 || tsPayload.AtTsStart()))) // ...but only if there is no more data at all, or if we are at a TS boundary
+         || tsPayload.Eof()) // or if we're out of data
          break;
       }
   return tsPayload.Used();
@@ -1457,7 +1511,7 @@
                        for (int i = 0; i < numPtsValues; i++)
                            ptsValues[i] = ptsValues[i + 1] - ptsValues[i];
                        qsort(ptsValues, numPtsValues, sizeof(uint32_t), CmpUint32);
-                       uint32_t Delta = ptsValues[0] / framesPerPayloadUnit;
+                       uint32_t Delta = ptsValues[0] / (framesPerPayloadUnit +  parser->IFrameTemporalReferenceOffset());
                        // determine frame info:
                        if (isVideo) {
                           if (abs(Delta - 3600) <= 1)
@@ -1475,7 +1529,7 @@
                           }
                        else // audio
                           framesPerSecond = double(PTSTICKS) / Delta; // PTS of audio frames is always increasing
-                       dbgframes("\nDelta = %d  FPS = %5.2f  FPPU = %d NF = %d\n", Delta, framesPerSecond, framesPerPayloadUnit, numPtsValues + 1);
+                       dbgframes("\nDelta = %d  FPS = %5.2f  FPPU = %d NF = %d TRO = %d\n", Delta, framesPerSecond, framesPerPayloadUnit, numPtsValues + 1, parser->IFrameTemporalReferenceOffset());
                        synced = true;
                        parser->SetDebug(false);
                        }
diff -ruN vdr-2.0.5/remux.h vdr-2.0.6/remux.h
--- vdr-2.0.5/remux.h	2013-01-20 12:43:59.000000000 +0100
+++ vdr-2.0.6/remux.h	2014-01-28 13:36:26.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: remux.h 2.37 2013/01/20 11:43:59 kls Exp $
+ * $Id: remux.h 2.37.1.2 2014/01/28 12:36:26 kls Exp $
  */
 
 #ifndef __REMUX_H
@@ -217,8 +217,11 @@
   int length;
   int pid;
   int index; // points to the next byte to process
+  int numPacketsPid; // the number of TS packets with the given PID (for statistical purposes)
+  int numPacketsOther; // the number of TS packets with other PIDs (for statistical purposes)
+  uchar SetEof(void);
 protected:
-  void Reset(void) { index = 0; }
+  void Reset(void);
 public:
   cTsPayload(void);
   cTsPayload(uchar *Data, int Length, int Pid = -1);
@@ -246,6 +249,10 @@
        ///< is counted with its full size.
   bool Eof(void) const { return index >= length; }
        ///< Returns true if all available bytes of the TS payload have been processed.
+  void Statistics(void) const;
+       ///< May be called after a new frame has been detected, and will log a warning
+       ///< if the number of TS packets required to determine the frame type exceeded
+       ///< some safety limits.
   uchar GetByte(void);
        ///< Gets the next byte of the TS payload, skipping any intermediate TS header data.
   bool SkipBytes(int Bytes);
@@ -462,7 +469,7 @@
 
 // Frame detector:
 
-#define MIN_TS_PACKETS_FOR_FRAME_DETECTOR 5
+#define MIN_TS_PACKETS_FOR_FRAME_DETECTOR 100
 
 class cFrameParser;
 
diff -ruN vdr-2.0.5/sdt.c vdr-2.0.6/sdt.c
--- vdr-2.0.5/sdt.c	2010-05-16 16:23:21.000000000 +0200
+++ vdr-2.0.6/sdt.c	2014-03-11 10:30:59.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: sdt.c 2.5 2010/05/16 14:23:21 kls Exp $
+ * $Id: sdt.c 2.5.1.2 2014/03/11 09:30:59 kls Exp $
  */
 
 #include "sdt.h"
@@ -17,19 +17,30 @@
 
 cSdtFilter::cSdtFilter(cPatFilter *PatFilter)
 {
+  source = cSource::stNone;
   patFilter = PatFilter;
   Set(0x11, 0x42);  // SDT
 }
 
 void cSdtFilter::SetStatus(bool On)
 {
+  cMutexLock MutexLock(&mutex);
   cFilter::SetStatus(On);
   sectionSyncer.Reset();
+  if (!On)
+     source = cSource::stNone;
+}
+
+void cSdtFilter::Trigger(int Source)
+{
+  cMutexLock MutexLock(&mutex);
+  source = Source;
 }
 
 void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
 {
-  if (!(Source() && Transponder()))
+  cMutexLock MutexLock(&mutex);
+  if (!(source && Transponder()))
      return;
   SI::SDT sdt(Data, false);
   if (!sdt.CheckCRCAndParse())
@@ -40,9 +51,9 @@
      return;
   SI::SDT::Service SiSdtService;
   for (SI::Loop::Iterator it; sdt.serviceLoop.getNext(SiSdtService, it); ) {
-      cChannel *channel = Channels.GetByChannelID(tChannelID(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId()));
+      cChannel *channel = Channels.GetByChannelID(tChannelID(source, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId()));
       if (!channel)
-         channel = Channels.GetByChannelID(tChannelID(Source(), 0, Transponder(), SiSdtService.getServiceId()));
+         channel = Channels.GetByChannelID(tChannelID(source, 0, Transponder(), SiSdtService.getServiceId()));
 
       cLinkChannels *LinkChannels = NULL;
       SI::Descriptor *d;
@@ -64,7 +75,7 @@
                         sd->serviceName.getText(NameBuf, ShortNameBuf, sizeof(NameBuf), sizeof(ShortNameBuf));
                         char *pn = compactspace(NameBuf);
                         char *ps = compactspace(ShortNameBuf);
-                        if (!*ps && cSource::IsCable(Source())) {
+                        if (!*ps && cSource::IsCable(source)) {
                            // Some cable providers don't mark short channel names according to the
                            // standard, but rather go their own way and use "name>short name":
                            char *p = strchr(pn, '>'); // fix for UPC Wien
@@ -92,7 +103,7 @@
                            }
                         else if (*pn && Setup.UpdateChannels >= 4) {
                            channel = Channels.NewChannel(Channel(), pn, ps, pp, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
-                           patFilter->Trigger();
+                           patFilter->Trigger(SiSdtService.getServiceId());
                            }
                         }
                    default: ;
@@ -115,10 +126,10 @@
                  SI::NVODReferenceDescriptor *nrd = (SI::NVODReferenceDescriptor *)d;
                  SI::NVODReferenceDescriptor::Service Service;
                  for (SI::Loop::Iterator it; nrd->serviceLoop.getNext(Service, it); ) {
-                     cChannel *link = Channels.GetByChannelID(tChannelID(Source(), Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId()));
+                     cChannel *link = Channels.GetByChannelID(tChannelID(source, Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId()));
                      if (!link && Setup.UpdateChannels >= 4) {
                         link = Channels.NewChannel(Channel(), "NVOD", "", "", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId());
-                        patFilter->Trigger();
+                        patFilter->Trigger(Service.getServiceId());
                         }
                      if (link) {
                         if (!LinkChannels)
diff -ruN vdr-2.0.5/sdt.h vdr-2.0.6/sdt.h
--- vdr-2.0.5/sdt.h	2004-01-05 15:30:14.000000000 +0100
+++ vdr-2.0.6/sdt.h	2014-03-11 10:31:08.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: sdt.h 2.0 2004/01/05 14:30:14 kls Exp $
+ * $Id: sdt.h 2.0.1.1 2014/03/11 09:31:08 kls Exp $
  */
 
 #ifndef __SDT_H
@@ -15,13 +15,16 @@
 
 class cSdtFilter : public cFilter {
 private:
+  cMutex mutex;
   cSectionSyncer sectionSyncer;
+  int source;
   cPatFilter *patFilter;
 protected:
   virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
 public:
   cSdtFilter(cPatFilter *PatFilter);
   virtual void SetStatus(bool On);
+  void Trigger(int Source);
   };
 
 #endif //__SDT_H
diff -ruN vdr-2.0.5/skinlcars.c vdr-2.0.6/skinlcars.c
--- vdr-2.0.5/skinlcars.c	2013-11-16 14:28:19.000000000 +0100
+++ vdr-2.0.6/skinlcars.c	2014-03-10 13:12:19.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: skinlcars.c 2.21.1.3 2013/11/16 13:28:19 kls Exp $
+ * $Id: skinlcars.c 2.21.1.4 2014/03/10 12:12:19 kls Exp $
  */
 
 // "Star Trek: The Next Generation"(R) is a registered trademark of Paramount Pictures,
@@ -1298,7 +1298,7 @@
   if (initial || y != lastLiveIndicatorY || Transferring != lastLiveIndicatorTransferring) {
      if (lastLiveIndicatorY >= 0)
         osd->DrawRectangle(xs12, lastLiveIndicatorY, xs13 - 1, lastLiveIndicatorY + lineHeight - 1, Theme.Color(clrBackground));
-     if (y >= 0) {
+     if (y > 0) {
         tColor ColorBg = Theme.Color(clrChannelFrameBg);
         osd->DrawRectangle(xs12, y, xs12 + lineHeight / 2 - 1, y + lineHeight - 1, ColorBg);
         osd->DrawEllipse  (xs12 + lineHeight / 2, y, xs13 - 1, y + lineHeight - 1, ColorBg, 5);
diff -ruN vdr-2.0.5/skins.h vdr-2.0.6/skins.h
--- vdr-2.0.5/skins.h	2012-12-21 12:09:13.000000000 +0100
+++ vdr-2.0.6/skins.h	2014-02-18 15:06:50.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: skins.h 2.9 2012/12/21 11:09:13 kls Exp $
+ * $Id: skins.h 2.9.1.1 2014/02/18 14:06:50 kls Exp $
  */
 
 #ifndef __SKINS_H
@@ -264,7 +264,7 @@
   class cProgressBar : public cBitmap {
   protected:
     int total;
-    int Pos(int p) { return p * Width() / total; }
+    int Pos(int p) { return int(int64_t(p) * Width() / total); }
     void Mark(int x, bool Start, bool Current, tColor ColorMark, tColor ColorCurrent);
   public:
     cProgressBar(int Width, int Height, int Current, int Total, const cMarks *Marks, tColor ColorSeen, tColor ColorRest, tColor ColorSelected, tColor ColorMark, tColor ColorCurrent);
diff -ruN vdr-2.0.5/sourceparams.c vdr-2.0.6/sourceparams.c
--- vdr-2.0.5/sourceparams.c	2010-03-06 12:13:39.000000000 +0100
+++ vdr-2.0.6/sourceparams.c	2014-03-09 13:13:18.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: sourceparams.c 1.2 2010/03/06 11:13:39 kls Exp $
+ * $Id: sourceparams.c 1.2.1.1 2014/03/09 12:13:18 kls Exp $
  */
 
 #include "sourceparams.h"
@@ -21,8 +21,8 @@
         return;
         }
      SourceParams.Add(this);
-     if (!strchr("ACST", Source)) // no, it's not "ATSC" ;-)
-        Sources.Add(new cSource(Source, Description));
+     if (!Sources.ContainsSourceType(source))
+        Sources.Add(new cSource(source, Description));
      dsyslog("registered source parameters for '%c - %s'", source, Description);
      }
   else
diff -ruN vdr-2.0.5/sources.c vdr-2.0.6/sources.c
--- vdr-2.0.5/sources.c	2010-02-28 16:15:39.000000000 +0100
+++ vdr-2.0.6/sources.c	2014-03-09 13:13:25.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: sources.c 2.2 2010/02/28 15:15:39 kls Exp $
+ * $Id: sources.c 2.2.1.1 2014/03/09 12:13:25 kls Exp $
  */
 
 #include "sources.h"
@@ -112,3 +112,12 @@
       }
   return NULL;
 }
+
+bool cSources::ContainsSourceType(char SourceType)
+{
+  for (cSource *p = First(); p; p = Next(p)) {
+      if (cSource::ToChar(p->Code()) == SourceType)
+         return true;
+      }
+  return false;
+}
diff -ruN vdr-2.0.5/sources.conf vdr-2.0.6/sources.conf
--- vdr-2.0.5/sources.conf	2013-03-11 12:24:07.000000000 +0100
+++ vdr-2.0.6/sources.conf	2014-01-07 10:14:23.000000000 +0100
@@ -19,57 +19,59 @@
 
 # Europe
 
-S3E     Eutelsat 3A & Rascom 1R
-S4E     Eurobird 4A
-S4.8E   Astra 4A
-S7E     Eutelsat W3A
-S9E     Eurobird 9A
-S10E    Eutelsat W2A
-S13E    Hotbird 6/8/9
-S16E    Eutelsat W2M & Eurobird 16A
-S19.2E  Astra 1H/1KR/1L/1M/2C
-S21.6E  Eutelsat W6
-S23.5E  Astra 3A/3B
-S25.5E  Eurobird 2
+S3E     Eutelsat 3A/3D & Rascom 1R
+S4E     Eutelsat 4B
+S4.8E   Astra 4A & SES 5
+S7E     Eutelsat 7A
+S9E     Eutelsat 9A/Ka-Sat 9A
+S10E    Eutelsat 10A
+S13E    Eutelsat Hot Bird 13B/13C/13D
+S16E    Eutelsat 16A/16B
+S17E    Amos 5
+S19.2E  Astra 1KR/1L/1M/2C
+S21.6E  Eutelsat 21B
+S23.5E  Astra 3B
+S25.5E  Eutelsat 25B
 S26E    Badr 4/5/6
-S28.2E  Astra 2A/2B/2D
-S28.5E  Eurobird 1
+S28.2E  Astra 1N/2A/2F
+S28.5E  Eutelsat 28A
 S30.5E  Arabsat 5A
 S31.5E  Astra 1G
-S33E    Eurobird 3 & Intelsat New Dawn
-S36E    Eutelsat W4/W7
-S38E    Paksat 1
+S33E    Eutelsat 33A & Intelsat 28
+S36E    Eutelsat 36A/36B
+S38E    Paksat 1R
 S39E    Hellas Sat 2
-S40E    Express AM1
 S42E    Turksat 2A/3A
 S45E    Intelsat 12
+S46E    Azerspace-1
+S47.5E  Intelsat 10
 S49E    Yamal 202
+S52.5E  Yahsat 1A
 S53E    Express AM22
-S55E    Insat 3E
-S56E    Bonum 1
+S56E    DirecTV 1R
 S57E    NSS 12
 S60E    Intelsat 904
 S62E    Intelsat 902
 S64E    Intelsat 906
 S66E    Intelsat 17
 S68.5E  Intelsat 7/10
-S70.5E  Eutelsat W5
-S72E    Intelsat 709
+S70.5E  Eutelsat 70B
+S72E    Intelsat 22
 
 # Asia
 
 S74E    Insat 3C/4CR
 S75E    ABS 1A
-S76.5E  Apstar 2R
-S78.5E  Thaicom 5
-S80E    Express AM2/MD1
-S83E    Insat 2E/4A
-S85.2E  Intelsat 15
-S87.5E  Chinasat 5A
-S88E    ST 1/2
-S90E    Yamal 201
+S76.5E  Apstar 7
+S78.5E  Thaicom 5/6A
+S80E    Express AM2
+S83E    Insat 4A
+S85.2E  Intelsat 15 & Horizons 2
+S87.5E  ChinaSat 12
+S88E    ST 2
+S90E    Yamal 201/300K
 S91.5E  Measat 3/3A
-S92.2E  Chinasat 9
+S92.2E  ChinaSat 9
 S93.5E  Insat 3A/4B
 S95E    NSS 6
 S96.5E  Express AM33
@@ -77,21 +79,22 @@
 S103E   Express A2
 S105.5E Asiasat 3S
 S108.2E Telkom 1 & NSS 11 & SES 7
-S110E   N-Sat 110 & BSAT 2C/3A
-S110.5E Chinasat 10
+S110E   N-Sat 110 & BSAT 3A/3C
+S110.5E ChinaSat 10
 S113E   Palapa D & Koreasat 5
-S116E   Koreasat 6
+S115.5E ChinaSat 6B
+S116E   ABS 7 & Koreasat 6
 S118E   Telkom 2
+S119.5E Thaicom 4
 S122.2E Asiasat 4
-S124E   JCSAT 4A
-S125E   Chinasat 6A
-S128E   JCSAT RA
-S132E   Vinasat 1 & JCSAT5A
+S124E   JCSAT 4B
+S125E   ChinaSat 6A
+S128E   JCSAT 3A
+S132E   Vinasat 1/2 & JCSAT 5A
 S134E   Apstar 6
 S138E   Telstar 18
 S140E   Express AM3
 S144E   Superbird C2
-S146E   ABS 5
 S150E   JCSAT 1B
 S152E   Optus D2
 S154E   JCSAT 2A
@@ -99,73 +102,73 @@
 S160E   Optus D1
 S162E   Superbird B2
 S164E   Optus B3
-S166E   Intelsat 8
-S169E   Intelsat 5
-S172E   GE 23
-S180E   Intelsat 701
+S166E   Intelsat 19
+S169E   Intelsat 8
+S172E   Eutelsat 172A
+S180E   Intelsat 18
 S177W   NSS 9
 
 # Atlantic
 
 S1W     Thor 5/6 & Intelsat 10-02
 S4W     Amos 2/3
-S5W     Atlantic Bird 3
-S7W     Nilesat 101/102/201 & Atlantic Bird 4A
-S8W     Telecom 2D & Atlantic Bird 2
+S5W     Eutelsat 5 West A
+S7W     Nilesat 101/201 & Eutelsat 7 West A
+S8W     Eutelsat 8 West A/C
 S11W    Express AM44
-S12.5W  Atlantic Bird 1
+S12.5W  Eutelsat 12 West A
 S14W    Express A4
 S15W    Telstar 12
 S18W    Intelsat 901
-S20W    NSS 5
-S22W    NSS 7
+S20W    NSS 7
+S22W    SES 4
 S24.5W  Intelsat 905
 S27.5W  Intelsat 907
-S30W    Hispasat 1C/1D/1E
+S30W    Hispasat 1D/1E
 S31.5W  Intelsat 25
 S34.5W  Intelsat 903
 S37.5W  NSS 10 & Telstar 11N
-S40.5W  NSS 806
+S40.5W  SES 6
 S43W    Intelsat 11
 S45W    Intelsat 14
 S50W    Intelsat 1R
-S53W    Intelsat 707
+S53W    Intelsat 23
 S55.5W  Intelsat 805
-S58W    Intelsat 9/16
-S61W    Amazonas 1/2
+S58W    Intelsat 21
+S61W    Amazonas 2/3
 
 # America
 
-S61.5W  Echostar 12/15
+S61.5W  Echostar 16
 S63W    Telstar 14R
 S65W    Star One C1
+S67W    AMC 4
 S70W    Star One C2
 S72W    AMC 6
-S72.5W  DirecTV 1R & Nimiq 5
-S74W    Horizons 2
-S77W    Echostar 1/8
-S79W    AMC 2/5
+S72.7W  Nimiq 5
+S75W    Star One C3
+S77W    QuetzSat 1
 S82W    Nimiq 4
 S83W    AMC 9
 S84W    Brasilsat B4
 S85W    AMC 16
 S85.1W  XM 3
-S87W    AMC 3
+S87W    SES 2
 S89W    Galaxy 28
-S91W    Galaxy 17 & Nimiq 1
-S93W    Galaxy 25
+S91W    Galaxy 17 & Nimiq 6
+S93.1W  Galaxy 25
 S95W    Galaxy 3C
 S97W    Galaxy 19
-S99W    Galaxy 16
-S99.2W  Spaceway 2 & DirecTV 11
+S99.2W  Galaxy 16
 S101W   DirecTV 4S/8 & SES 1
 S103W   AMC 1
 S105W   AMC 15/18
-S107.3W Anik F1/F1R
+S107.3W Anik F1R/G1
 S110W   DirecTV 5 & Echostar 10/11
 S111.1W Anik F2
 S113W   SatMex 6
-S116.8W SatMex 5
+S114.9W SatMex 5
+S116.8W SatMex 8
 S118.8W Anik F3
 S119W   Echostar 14 & DirecTV 7S
 S121W   Echostar 9/Galaxy 23
@@ -174,7 +177,7 @@
 S127W   Galaxy 13/Horizons 1
 S129W   Ciel 2
 S131W   AMC 11
-S133W   Galaxy 13/15
+S133W   Galaxy 15
 S135W   AMC 10
 S137W   AMC 7
 S139W   AMC 8
diff -ruN vdr-2.0.5/sources.h vdr-2.0.6/sources.h
--- vdr-2.0.5/sources.h	2012-06-17 13:19:23.000000000 +0200
+++ vdr-2.0.6/sources.h	2014-03-09 13:13:34.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: sources.h 2.4 2012/06/17 11:19:23 kls Exp $
+ * $Id: sources.h 2.4.1.1 2014/03/09 12:13:34 kls Exp $
  */
 
 #ifndef __SOURCES_H
@@ -47,6 +47,7 @@
 class cSources : public cConfig<cSource> {
 public:
   cSource *Get(int Code);
+  bool ContainsSourceType(char SourceType);
   };
 
 extern cSources Sources;
diff -ruN vdr-2.0.5/vdr.c vdr-2.0.6/vdr.c
--- vdr-2.0.5/vdr.c	2013-12-25 12:40:37.000000000 +0100
+++ vdr-2.0.6/vdr.c	2014-01-26 13:45:00.000000000 +0100
@@ -22,7 +22,7 @@
  *
  * The project's page is at http://www.tvdr.de
  *
- * $Id: vdr.c 2.57.1.4 2013/12/25 11:40:37 kls Exp $
+ * $Id: vdr.c 2.57.1.5 2014/01/26 12:45:00 kls Exp $
  */
 
 #include <getopt.h>
@@ -909,7 +909,7 @@
               for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
                   if (Channel->Modification(CHANNELMOD_RETUNE)) {
                      cRecordControls::ChannelDataModified(Channel);
-                     if (Channel->Number() == cDevice::CurrentChannel()) {
+                     if (Channel->Number() == cDevice::CurrentChannel() && cDevice::PrimaryDevice()->HasDecoder()) {
                         if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring()) {
                            if (cDevice::ActualDevice()->ProvidesTransponder(Channel)) { // avoids retune on devices that don't really access the transponder
                               isyslog("retuning due to modification of channel %d", Channel->Number());
