Hello community,

here is the log from the commit of package vdr-plugin-satip for 
openSUSE:Factory checked in at 2015-03-11 09:57:47
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/vdr-plugin-satip (Old)
 and      /work/SRC/openSUSE:Factory/.vdr-plugin-satip.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "vdr-plugin-satip"

Changes:
--------
--- /work/SRC/openSUSE:Factory/vdr-plugin-satip/vdr-plugin-satip.changes        
2015-02-10 20:24:18.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.vdr-plugin-satip.new/vdr-plugin-satip.changes   
2015-03-11 09:57:48.000000000 +0100
@@ -1,0 +2,9 @@
+Fri Mar  6 08:44:40 UTC 2015 - [email protected]
+
+- update to version 2.2.0 (2015-02-19)
+  * Updated for vdr-2.2.0.
+  * Fixed memory deallocation errors.
+  * Cleaned up all scan-build warnings.
+  * Refactored the frontend handling.
+
+-------------------------------------------------------------------

Old:
----
  vdr-satip-1.0.2.tgz

New:
----
  vdr-satip-2.2.0.tgz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ vdr-plugin-satip.spec ++++++
--- /var/tmp/diff_new_pack.EMtgrO/_old  2015-03-11 09:57:48.000000000 +0100
+++ /var/tmp/diff_new_pack.EMtgrO/_new  2015-03-11 09:57:48.000000000 +0100
@@ -1,8 +1,8 @@
 #
 # spec file for package vdr-plugin-satip
 #
-# Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
-# Copyright (c) 2014 B1 Systems GmbH, Vohburg, Germany.
+# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2014,2015 B1 Systems GmbH, Vohburg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 
 Name:           vdr-plugin-satip
-Version:        1.0.2
+Version:        2.2.0
 Release:        0
 Summary:        SAT>IP Input Plugin for the Video Disc Recorder VDR
 License:        GPL-2.0

++++++ vdr-satip-1.0.2.tgz -> vdr-satip-2.2.0.tgz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/HISTORY new/satip-2.2.0/HISTORY
--- old/satip-1.0.2/HISTORY     2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/HISTORY     2015-02-19 03:20:00.000000000 +0100
@@ -108,3 +108,15 @@
 - Updated Spanish and Catalan translations (Thanks to
   Gabriel Bonich).
 - Updated German translations (Thanks to Frank Neumann).
+
+
+===================================
+VDR Plugin 'satip' Revision History
+===================================
+
+2015-02-19: Version 2.2.0
+
+- Updated for vdr-2.2.0.
+- Fixed memory deallocation errors.
+- Cleaned up all scan-build warnings.
+- Refactored the frontend handling.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/README new/satip-2.2.0/README
--- old/satip-1.0.2/README      2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/README      2015-02-19 03:20:00.000000000 +0100
@@ -26,10 +26,6 @@
 - Glibc >= 2.12 - the GNU C library (recvmmsg)
   http://www.gnu.org/software/libc/
 
-- VDR >= 2.1.4 for scrambled channels
-
-- VDR >= 2.1.7 for external CI
-
 Description:
 
 This plugin integrates SAT>IP network devices seamlessly into VDR.
@@ -136,8 +132,8 @@
   your setup doesn't have firewalled the UDP port 1900.
 
 - Stream decryption requires a separate CAM plugin that works without
-  direct access to any DVB card devices. The integrated CAM slot in
-  Octopus Net devices isn't supported.
+  direct access to any DVB card devices. Also the integrated CAM slots
+  in Octopus Net devices are supported.
 
 - Tracing can be set on/off dynamically via command-line switch or
   SVDRP command.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/device.c new/satip-2.2.0/device.c
--- old/satip-1.0.2/device.c    2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/device.c    2015-02-19 03:20:00.000000000 +0100
@@ -328,20 +328,19 @@
         return false;
         }
      cString address;
-     cSatipServer *server = 
cSatipDiscover::GetInstance()->GetServer(channelP->Source(), 
channelP->Transponder(), dtp.System());
+     cSatipServer *server = 
cSatipDiscover::GetInstance()->AssignServer(deviceIndexM, channelP->Source(), 
channelP->Transponder(), dtp.System());
      if (!server) {
         debug9("%s No suitable server found [device %u]", __PRETTY_FUNCTION__, 
deviceIndexM);
         return false;
         }
-     cSatipDiscover::GetInstance()->SetTransponder(server, 
channelP->Transponder());
-     if (pTunerM && pTunerM->SetSource(server, *params, deviceIndexM)) {
+     if (pTunerM && pTunerM->SetSource(server, channelP->Transponder(), 
*params, deviceIndexM)) {
         channelM = *channelP;
         deviceNameM = cString::sprintf("%s %d %s", *DeviceType(), 
deviceIndexM, *cSatipDiscover::GetInstance()->GetServerString(server));
         return true;
         }
      }
   else if (pTunerM) {
-     pTunerM->SetSource(NULL, NULL, deviceIndexM);
+     pTunerM->SetSource(NULL, 0, NULL, deviceIndexM);
      return true;
      }
   return false;
@@ -434,10 +433,7 @@
 
 int cSatipDevice::GetPmtPid(void)
 {
-  int pid = 0;
-#if defined(APIVERSNUM) && APIVERSNUM >= 20107
-  pid = channelM.Ca() ? ::GetPmtPid(channelM.Source(), channelM.Transponder(), 
channelM.Sid()) : 0;
-#endif
+  int pid = channelM.Ca() ? ::GetPmtPid(channelM.Source(), 
channelM.Transponder(), channelM.Sid()) : 0;
   debug11("%s pmtpid=%d source=%c transponder=%d sid=%d name=%s [device %u]", 
__PRETTY_FUNCTION__, pid, cSource::ToChar(channelM.Source()), 
channelM.Transponder(), channelM.Sid(), channelM.Name(), deviceIndexM);
   return pid;
 }
@@ -506,7 +502,6 @@
 {
   debug16("%s [device %u]", __PRETTY_FUNCTION__, deviceIndexM);
   if (tsBufferM) {
-#if defined(APIVERSNUM) && APIVERSNUM >= 20104
      if (cCamSlot *cs = CamSlot()) {
         if (cs->WantsTsData()) {
            int available;
@@ -518,7 +513,6 @@
            return true;
            }
         }
-#endif
      dataP = GetData();
      return true;
      }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/discover.c new/satip-2.2.0/discover.c
--- old/satip-1.0.2/discover.c  2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/discover.c  2015-02-19 03:20:00.000000000 +0100
@@ -233,7 +233,7 @@
 {
   debug1("%s (%s, %s, %s)", __PRETTY_FUNCTION__, addrP, modelP, descP);
   cMutexLock MutexLock(&mutexM);
-  if (SatipConfig.GetUseSingleModelServers()) {
+  if (SatipConfig.GetUseSingleModelServers() && modelP && !isempty(modelP)) {
      int n = 0;
      char *s, *p = strdup(modelP);
      char *r = strtok_r(p, ",", &s);
@@ -242,7 +242,7 @@
            cString desc = cString::sprintf("%s #%d", !isempty(descP) ? descP : 
"MyBrokenHardware", n++);
            cSatipServer *tmp = new cSatipServer(addrP, r, desc);
            if (!serversM.Update(tmp)) {
-              info("Adding server '%s|%s|%s'", tmp->Address(), tmp->Model(), 
tmp->Description());
+              info("Adding server '%s|%s|%s' CI: %s Quirks: %s", 
tmp->Address(), tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", 
tmp->HasQuirk() ? tmp->Quirks() : "none");
               serversM.Add(tmp);
               }
            else
@@ -254,7 +254,7 @@
   else {
      cSatipServer *tmp = new cSatipServer(addrP, modelP, descP);
      if (!serversM.Update(tmp)) {
-        info("Adding server '%s|%s|%s'", tmp->Address(), tmp->Model(), 
tmp->Description());
+        info("Adding server '%s|%s|%s' CI: %s Quirks: %s", tmp->Address(), 
tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() 
? tmp->Quirks() : "none");
         serversM.Add(tmp);
         }
      else
@@ -269,11 +269,18 @@
   return serversM.Count();
 }
 
-cSatipServer *cSatipDiscover::GetServer(int sourceP, int transponderP, int 
systemP)
+cSatipServer *cSatipDiscover::AssignServer(int deviceIdP, int sourceP, int 
transponderP, int systemP)
 {
-  debug16("%s (%d, %d, %d)", __PRETTY_FUNCTION__, sourceP, transponderP, 
systemP);
+  debug16("%s (%d, %d, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, sourceP, 
transponderP, systemP);
   cMutexLock MutexLock(&mutexM);
-  return serversM.Find(sourceP, transponderP, systemP);
+  return serversM.Assign(deviceIdP, sourceP, transponderP, systemP);
+}
+
+cSatipServer *cSatipDiscover::GetServer(int sourceP)
+{
+  debug16("%s (%d)", __PRETTY_FUNCTION__, sourceP);
+  cMutexLock MutexLock(&mutexM);
+  return serversM.Find(sourceP);
 }
 
 cSatipServer *cSatipDiscover::GetServer(cSatipServer *serverP)
@@ -304,18 +311,39 @@
   return serversM.List();
 }
 
-void cSatipDiscover::SetTransponder(cSatipServer *serverP, int transponderP)
+void cSatipDiscover::AttachServer(cSatipServer *serverP, int deviceIdP, int 
transponderP)
+{
+  debug16("%s (, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
+  cMutexLock MutexLock(&mutexM);
+  serversM.Attach(serverP, deviceIdP, transponderP);
+}
+
+void cSatipDiscover::DetachServer(cSatipServer *serverP, int deviceIdP, int 
transponderP)
+{
+  debug16("%s (, %d, %d)", __PRETTY_FUNCTION__, deviceIdP, transponderP);
+  cMutexLock MutexLock(&mutexM);
+  serversM.Detach(serverP, deviceIdP, transponderP);
+}
+
+bool cSatipDiscover::IsServerQuirk(cSatipServer *serverP, int quirkP)
 {
-  debug16("%s (, %d)", __PRETTY_FUNCTION__, transponderP);
+  debug16("%s (, %d)", __PRETTY_FUNCTION__, quirkP);
   cMutexLock MutexLock(&mutexM);
-  serversM.SetTransponder(serverP, transponderP);
+  return serversM.IsQuirk(serverP, quirkP);
 }
 
-void cSatipDiscover::UseServer(cSatipServer *serverP, bool onOffP)
+bool cSatipDiscover::HasServerCI(cSatipServer *serverP)
 {
-  debug16("%s (, %d)", __PRETTY_FUNCTION__, onOffP);
+  debug16("%s", __PRETTY_FUNCTION__);
+  cMutexLock MutexLock(&mutexM);
+  return serversM.HasCI(serverP);
+}
+
+cString cSatipDiscover::GetServerAddress(cSatipServer *serverP)
+{
+  debug16("%s", __PRETTY_FUNCTION__);
   cMutexLock MutexLock(&mutexM);
-  serversM.Use(serverP, onOffP);
+  return serversM.GetAddress(serverP);
 }
 
 int cSatipDiscover::NumProvidedSystems(void)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/discover.h new/satip-2.2.0/discover.h
--- old/satip-1.0.2/discover.h  2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/discover.h  2015-02-19 03:20:00.000000000 +0100
@@ -74,12 +74,16 @@
   virtual ~cSatipDiscover();
   void TriggerScan(void) { probeIntervalM.Set(0); }
   int GetServerCount(void);
-  cSatipServer *GetServer(int sourceP, int transponderP = 0, int systemP = -1);
+  cSatipServer *AssignServer(int deviceIdP, int sourceP, int transponderP, int 
systemP);
+  cSatipServer *GetServer(int sourceP);
   cSatipServer *GetServer(cSatipServer *serverP);
   cSatipServers *GetServers(void);
   cString GetServerString(cSatipServer *serverP);
-  void SetTransponder(cSatipServer *serverP, int transponderP);
-  void UseServer(cSatipServer *serverP, bool onOffP);
+  void AttachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
+  void DetachServer(cSatipServer *serverP, int deviceIdP, int transponderP);
+  bool IsServerQuirk(cSatipServer *serverP, int quirkP);
+  bool HasServerCI(cSatipServer *serverP);
+  cString GetServerAddress(cSatipServer *serverP);
   cString GetServerList(void);
   int NumProvidedSystems(void);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/msearch.c new/satip-2.2.0/msearch.c
--- old/satip-1.0.2/msearch.c   2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/msearch.c   2015-02-19 03:20:00.000000000 +0100
@@ -35,6 +35,7 @@
 
 cSatipMsearch::~cSatipMsearch()
 {
+  FREE_POINTER(bufferM);
 }
 
 void cSatipMsearch::Probe(void)
@@ -93,8 +94,6 @@
                  r = strtok_r(NULL, "\r\n", &s);
                  }
            }
-     if (errno != EAGAIN && errno != EWOULDBLOCK)
-        error("Error %d reading in %s", errno, *ToString());
      }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/param.c new/satip-2.2.0/param.c
--- old/satip-1.0.2/param.c     2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/param.c     2015-02-19 03:20:00.000000000 +0100
@@ -147,15 +147,9 @@
      cDvbTransponderParameters dtp(channelP->Parameters());
      int DataSlice = 0;
      int C2TuningFrequencyType = 0;
-#if defined(APIVERSNUM) && APIVERSNUM < 20106
-     int Pilot = PILOT_AUTO;
-     int T2SystemId = 0;
-     int SisoMiso = 0;
-#else
      int Pilot = dtp.Pilot();
      int T2SystemId = dtp.T2SystemId();
      int SisoMiso = dtp.SisoMiso();
-#endif
      float freq = channelP->Frequency();
      char type = cSource::ToChar(channelP->Source());
      cSource *source = Sources.Get(channelP->Source());
@@ -192,7 +186,7 @@
      ST("  T*") q += PrintUrlString(q, STBUFLEFT, dtp.System(),       
SatipSystemValuesTerrestrial);
      ST("  T*") q += PrintUrlString(q, STBUFLEFT, dtp.Transmission(), 
SatipTransmissionValues);
      if ((channelP->Rid() % 100) > 0)
-                q += snprintf(q,       STBUFLEFT, "&fe=%d",           
channelP->Rid() % 100);
+                snprintf(q,            STBUFLEFT, "&fe=%d",           
channelP->Rid() % 100);
 #undef ST
      return buffer;
      }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/po/ca_ES.po new/satip-2.2.0/po/ca_ES.po
--- old/satip-1.0.2/po/ca_ES.po 2015-01-18 14:50:03.000000000 +0100
+++ new/satip-2.2.0/po/ca_ES.po 2015-02-20 20:17:42.000000000 +0100
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: vdr-satip 1.0.2\n"
+"Project-Id-Version: vdr-satip 2.2.0\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-01-18 01:18+0200\n"
-"PO-Revision-Date: 2015-01-18 01:18+0200\n"
+"POT-Creation-Date: 2015-02-19 02:19+0200\n"
+"PO-Revision-Date: 2015-02-19 02:19+0200\n"
 "Last-Translator: Gabriel Bonich <[email protected]>\n"
 "Language-Team: Catalan <[email protected]>\n"
 "Language: ca\n"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/po/de_DE.po new/satip-2.2.0/po/de_DE.po
--- old/satip-1.0.2/po/de_DE.po 2015-01-18 14:50:03.000000000 +0100
+++ new/satip-2.2.0/po/de_DE.po 2015-02-20 20:17:42.000000000 +0100
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: vdr-satip 1.0.2\n"
+"Project-Id-Version: vdr-satip 2.2.0\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-01-18 01:18+0200\n"
-"PO-Revision-Date: 2015-01-18 01:18+0200\n"
+"POT-Creation-Date: 2015-02-19 02:19+0200\n"
+"PO-Revision-Date: 2015-02-19 02:19+0200\n"
 "Last-Translator: Frank Neumann <[email protected]>\n"
 "Language-Team: German <[email protected]>\n"
 "Language: de\n"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/po/es_ES.po new/satip-2.2.0/po/es_ES.po
--- old/satip-1.0.2/po/es_ES.po 2015-01-18 14:50:03.000000000 +0100
+++ new/satip-2.2.0/po/es_ES.po 2015-02-20 20:17:42.000000000 +0100
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: vdr-satip 1.0.2\n"
+"Project-Id-Version: vdr-satip 2.2.0\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-01-18 01:18+0200\n"
-"PO-Revision-Date: 2015-01-18 01:18+0200\n"
+"POT-Creation-Date: 2015-02-19 02:19+0200\n"
+"PO-Revision-Date: 2015-02-19 02:19+0200\n"
 "Last-Translator: Gabriel Bonich <[email protected]>\n"
 "Language-Team: Spanish <[email protected]>\n"
 "Language: es\n"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/po/fi_FI.po new/satip-2.2.0/po/fi_FI.po
--- old/satip-1.0.2/po/fi_FI.po 2015-01-18 14:50:03.000000000 +0100
+++ new/satip-2.2.0/po/fi_FI.po 2015-02-20 20:17:42.000000000 +0100
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: vdr-satip 1.0.2\n"
+"Project-Id-Version: vdr-satip 2.2.0\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2015-01-18 01:18+0200\n"
-"PO-Revision-Date: 2015-01-18 01:18+0200\n"
+"POT-Creation-Date: 2015-02-19 02:19+0200\n"
+"PO-Revision-Date: 2015-02-19 02:19+0200\n"
 "Last-Translator: Rolf Ahrenberg\n"
 "Language-Team: Finnish <[email protected]>\n"
 "Language: fi\n"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/rtcp.c new/satip-2.2.0/rtcp.c
--- old/satip-1.0.2/rtcp.c      2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/rtcp.c      2015-02-19 03:20:00.000000000 +0100
@@ -25,7 +25,7 @@
 cSatipRtcp::~cSatipRtcp()
 {
   debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
-  DELETE_POINTER(bufferM);
+  FREE_POINTER(bufferM);
 }
 
 int cSatipRtcp::GetFd(void)
@@ -89,8 +89,6 @@
            if (offset >= 0)
               tunerM.ProcessApplicationData(bufferM + offset, length);
            }
-     if (errno != EAGAIN && errno != EWOULDBLOCK)
-        error("Error %d reading in %s", errno, *ToString());
      }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/rtp.c new/satip-2.2.0/rtp.c
--- old/satip-1.0.2/rtp.c       2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/rtp.c       2015-02-19 03:20:00.000000000 +0100
@@ -29,7 +29,7 @@
 cSatipRtp::~cSatipRtp()
 {
   debug1("%s [device %d]", __PRETTY_FUNCTION__, tunerM.GetId());
-  DELETE_POINTER(bufferM);
+  FREE_POINTER(bufferM);
 }
 
 int cSatipRtp::GetFd(void)
@@ -136,9 +136,6 @@
            }
        } while (count >= eRtpPacketReadCount);
 
-     if (errno != EAGAIN && errno != EWOULDBLOCK)
-        error("Error %d reading in %s [device %d]", errno, *ToString(), 
tunerM.GetId());
-
      elapsed = processing.Elapsed();
      if (elapsed > 1)
         debug6("%s %d read(s) took %" PRIu64 " ms [device %d]", 
__PRETTY_FUNCTION__, count, elapsed, tunerM.GetId());
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/satip.c new/satip-2.2.0/satip.c
--- old/satip-1.0.2/satip.c     2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/satip.c     2015-02-19 03:20:00.000000000 +0100
@@ -19,15 +19,15 @@
 #warning "CURL version >= 7.36.0 is recommended"
 #endif
 
-#if defined(APIVERSNUM) && APIVERSNUM < 20000
-#error "VDR-2.0.0 API version or greater is required!"
+#if defined(APIVERSNUM) && APIVERSNUM < 20200
+#error "VDR-2.2.0 API version or greater is required!"
 #endif
 
 #ifndef GITVERSION
 #define GITVERSION ""
 #endif
 
-       const char VERSION[]     = "1.0.2" GITVERSION;
+       const char VERSION[]     = "2.2.0" GITVERSION;
 static const char DESCRIPTION[] = trNOOP("SAT>IP Devices");
 
 class cPluginSatip : public cPlugin {
@@ -84,7 +84,7 @@
   return "  -d <num>, --devices=<number>  set number of devices to be 
created\n"
          "  -t <mode>, --trace=<mode>     set the tracing mode\n"
          "  -s <ipaddr>|<model>|<desc>, 
--server=<ipaddr1>|<model1>|<desc1>;<ipaddr2>|<model2>|<desc2>\n"
-         "                                define hard-coded SAT>IP server(s)"
+         "                                define hard-coded SAT>IP server(s)\n"
          "  -S, --single                  set the single model server mode 
on\n"
          "  -n, --noquirks                disable all the server quirks\n";
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/server.c new/satip-2.2.0/server.c
--- old/satip-1.0.2/server.c    2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/server.c    2015-02-19 03:20:00.000000000 +0100
@@ -12,73 +12,140 @@
 #include "log.h"
 #include "server.h"
 
+// --- cSatipFrontend ---------------------------------------------------------
+
+cSatipFrontend::cSatipFrontend(const int indexP, const char *descriptionP)
+: indexM(indexP),
+  transponderM(0),
+  deviceIdM(-1),
+  descriptionM(descriptionP)
+{
+}
+
+cSatipFrontend::~cSatipFrontend()
+{
+}
+
+// --- cSatipFrontends --------------------------------------------------------
+
+bool cSatipFrontends::Matches(int deviceIdP, int transponderP)
+{
+  for (cSatipFrontend *f = First(); f; f = Next(f)) {
+      if (f->Attached() && (f->DeviceId() == deviceIdP) && (f->Transponder() 
== transponderP))
+         return true;
+      }
+  return false;
+}
+
+bool cSatipFrontends::Assign(int deviceIdP, int transponderP)
+{
+  cSatipFrontend *tmp = NULL;
+  // Prefer any unused one
+  for (cSatipFrontend *f = First(); f; f = Next(f)) {
+      if (!f->Attached() || (f->DeviceId() == deviceIdP)) {
+         tmp = f;
+         break;
+         }
+      }
+  if (tmp) {
+     tmp->SetTransponder(transponderP);
+     return true;
+     }
+  return false;
+}
+
+bool cSatipFrontends::Attach(int deviceIdP, int transponderP)
+{
+  for (cSatipFrontend *f = First(); f; f = Next(f)) {
+      if (f->Transponder() == transponderP) {
+         f->Attach(deviceIdP);
+         debug9("%s (%d, %d) %s/#%d", __PRETTY_FUNCTION__, deviceIdP, 
transponderP, *f->Description(), f->Index());
+         return true;
+         }
+      }
+  return false;
+}
+
+bool cSatipFrontends::Detach(int deviceIdP, int transponderP)
+{
+  for (cSatipFrontend *f = First(); f; f = Next(f)) {
+      if (f->Transponder() == transponderP) {
+         f->Detach(deviceIdP);
+         debug9("%s (%d, %d) %s/#%d", __PRETTY_FUNCTION__, deviceIdP, 
transponderP, *f->Description(), f->Index());
+         return true;
+         }
+      }
+  return false;
+}
+
 // --- cSatipServer -----------------------------------------------------------
 
 cSatipServer::cSatipServer(const char *addressP, const char *modelP, const 
char *descriptionP)
 : addressM((addressP && *addressP) ? addressP : "0.0.0.0"),
   modelM((modelP && *modelP) ? modelP : "DVBS-1"),
   descriptionM(!isempty(descriptionP) ? descriptionP : "MyBrokenHardware"),
-  modelTypeM(eSatipModelTypeNone),
+  quirksM(""),
   quirkM(eSatipQuirkNone),
-  useCountM(0),
-  transponderM(0),
+  hasCiM(false),
   createdM(time(NULL)),
   lastSeenM(0)
 {
-  memset(modelCountM, 0, sizeof(modelCountM));
   if (!SatipConfig.GetDisableServerQuirks()) {
-     debug3("%s quirks=%s", __PRETTY_FUNCTION__, *descriptionM);
      // These devices contain a session id bug:
      // Inverto Airscreen Server IDL 400 ?
      // Elgato EyeTV Netstream 4Sat ?
      if (strstr(*descriptionM, "GSSBOX") ||             // Grundig Sat Systems 
GSS.box DSI 400
          strstr(*descriptionM, "DIGIBIT") ||            // Telestar Digibit R1
          strstr(*descriptionM, "Triax SatIP Converter") // Triax TSS 400
-        )
+        ) {
         quirkM |= eSatipQuirkSessionId;
+        quirksM = cString::sprintf("%s%sSessionId", *quirksM, 
isempty(*quirksM) ? "" : ",");
+        }
      // These devices contain a play (add/delpids) parameter bug:
-     if (strstr(*descriptionM, "fritzdvbc"))            // Fritz!WLAN Repeater 
DVB-C
+     if (strstr(*descriptionM, "fritzdvbc")             // Fritz!WLAN Repeater 
DVB-C
+        ) {
         quirkM |= eSatipQuirkPlayPids;
+        quirksM = cString::sprintf("%s%sPlayPids", *quirksM, isempty(*quirksM) 
? "" : ",");
+        }
      // These devices contain a frontend locking bug:
-     if (strstr(*descriptionM, "fritzdvbc"))            // Fritz!WLAN Repeater 
DVB-C
+     if (strstr(*descriptionM, "fritzdvbc")             // Fritz!WLAN Repeater 
DVB-C
+        ) {
         quirkM |= eSatipQuirkForceLock;
-     if (quirkM != eSatipQuirkNone)
-        info("Malfunctioning '%s' server detected! Please, fix the firmware.", 
*descriptionM);
+        quirksM = cString::sprintf("%s%sForceLock", *quirksM, 
isempty(*quirksM) ? "" : ",");
+        }
+     debug3("%s description=%s quirks=%s", __PRETTY_FUNCTION__, *descriptionM, 
*quirksM);
      }
   // These devices support the X_PMT protocol extension
-  if (strstr(*descriptionM, "OctopusNet"))           // Digital Devices 
OctopusNet
-     quirkM |= eSatipQuirkUseXCI;
+  if (strstr(*descriptionM, "OctopusNet"))              // Digital Devices 
OctopusNet
+     hasCiM = true;
   char *s, *p = strdup(*modelM);
   char *r = strtok_r(p, ",", &s);
   while (r) {
-        if (strstr(r, "DVBS2-")) {
-           modelTypeM |= eSatipModelTypeDVBS2;
-           if (char *c = strstr(r, "-"))
-              modelCountM[eSatipModuleDVBS2] = atoi(++c);
+        char *c;
+        if (c = strstr(r, "DVBS2-")) {
+           int count = atoi(c + 6);
+           for (int i = 1; i <= count; ++i)
+               frontendsM[eSatipFrontendDVBS2].Add(new cSatipFrontend(i, 
"DVB-S2"));
            }
-        else if (strstr(r, "DVBT2-")) {
-           modelTypeM |= eSatipModelTypeDVBT2;
-           if (char *c = strstr(r, "-"))
-              modelCountM[eSatipModuleDVBT2] = atoi(++c);
-           modelTypeM |= eSatipModelTypeDVBT;
-           modelCountM[eSatipModuleDVBT] = modelCountM[eSatipModuleDVBT2];
+        else if (c = strstr(r, "DVBT-")) {
+           int count = atoi(c + 5);
+           for (int i = 1; i <= count; ++i)
+               frontendsM[eSatipFrontendDVBT].Add(new cSatipFrontend(i, 
"DVB-T"));
            }
-        else if (strstr(r, "DVBT-")) {
-           modelTypeM |= eSatipModelTypeDVBT;
-           if (char *c = strstr(r, "-"))
-              modelCountM[eSatipModuleDVBT] = atoi(++c);
+        else if (c = strstr(r, "DVBT2-")) {
+           int count = atoi(c + 6);
+           for (int i = 1; i <= count; ++i)
+               frontendsM[eSatipFrontendDVBT2].Add(new cSatipFrontend(i, 
"DVB-T2"));
            }
-        else if (strstr(r, "DVBC2-")) {
-           modelTypeM |= eSatipModelTypeDVBC2;
-           if (char *c = strstr(r, "-"))
-              modelCountM[eSatipModuleDVBC2] = atoi(++c);
-           modelTypeM |= eSatipModelTypeDVBC;
-           modelCountM[eSatipModuleDVBC] = modelCountM[eSatipModuleDVBC2];
+        else if (c = strstr(r, "DVBC-")) {
+           int count = atoi(c + 5);
+           for (int i = 1; i <= count; ++i)
+               frontendsM[eSatipFrontendDVBC].Add(new cSatipFrontend(i, 
"DVB-C"));
            }
-        else if (strstr(r, "DVBC-")) {
-           modelTypeM |= eSatipModelTypeDVBC;
-           if (char *c = strstr(r, "-"))
-              modelCountM[eSatipModuleDVBC] = atoi(++c);
+        else if (c = strstr(r, "DVBC2-")) {
+           int count = atoi(c + 6);
+           for (int i = 1; i <= count; ++i)
+               frontendsM[eSatipFrontendDVBC2].Add(new cSatipFrontend(i, 
"DVB-C2"));
            }
         r = strtok_r(NULL, ",", &s);
         }
@@ -101,12 +168,96 @@
   return result;
 }
 
-void cSatipServer::Use(bool onOffP)
+bool cSatipServer::Assign(int deviceIdP, int sourceP, int systemP, int 
transponderP)
+{
+  bool result = false;
+  if (cSource::IsType(sourceP, 'S'))
+     result = frontendsM[eSatipFrontendDVBS2].Assign(deviceIdP, transponderP);
+  else if (cSource::IsType(sourceP, 'T')) {
+     if (systemP)
+        result = frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, 
transponderP);
+     else
+        result = frontendsM[eSatipFrontendDVBT].Assign(deviceIdP, 
transponderP) || frontendsM[eSatipFrontendDVBT2].Assign(deviceIdP, 
transponderP);
+     }
+  else if (cSource::IsType(sourceP, 'C')) {
+     if (systemP)
+        result = frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, 
transponderP);
+     else
+        result = frontendsM[eSatipFrontendDVBC].Assign(deviceIdP, 
transponderP) || frontendsM[eSatipFrontendDVBC2].Assign(deviceIdP, 
transponderP);
+     }
+  return result;
+}
+
+bool cSatipServer::Matches(int sourceP)
+{
+  if (cSource::IsType(sourceP, 'S'))
+     return GetModulesDVBS2();
+  else if (cSource::IsType(sourceP, 'T'))
+     return GetModulesDVBT() || GetModulesDVBT2();
+  else if (cSource::IsType(sourceP, 'C'))
+     return GetModulesDVBC() || GetModulesDVBC2();
+  return false;
+}
+
+bool cSatipServer::Matches(int deviceIdP, int sourceP, int systemP, int 
transponderP)
+{
+  bool result = false;
+  if (cSource::IsType(sourceP, 'S'))
+     result = frontendsM[eSatipFrontendDVBS2].Matches(deviceIdP, transponderP);
+  else if (cSource::IsType(sourceP, 'T')) {
+     if (systemP)
+        result = frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, 
transponderP);
+     else
+        result = frontendsM[eSatipFrontendDVBT].Matches(deviceIdP, 
transponderP) || frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, 
transponderP);
+     }
+  else if (cSource::IsType(sourceP, 'C')) {
+     if (systemP)
+        result = frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, 
transponderP);
+     else
+        result = frontendsM[eSatipFrontendDVBC].Matches(deviceIdP, 
transponderP) || frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, 
transponderP);
+     }
+  return result;
+}
+
+void cSatipServer::Attach(int deviceIdP, int transponderP)
+{
+  for (int i = 0; i < eSatipFrontendCount; ++i) {
+      if (frontendsM[i].Attach(deviceIdP, transponderP))
+         return;
+      }
+}
+
+void cSatipServer::Detach(int deviceIdP, int transponderP)
+{
+  for (int i = 0; i < eSatipFrontendCount; ++i) {
+      if (frontendsM[i].Detach(deviceIdP, transponderP))
+         return;
+      }
+}
+
+int cSatipServer::GetModulesDVBS2(void)
 {
-  if (onOffP)
-     ++useCountM;
-  else
-     --useCountM;
+  return frontendsM[eSatipFrontendDVBS2].Count();
+}
+
+int cSatipServer::GetModulesDVBT(void)
+{
+  return frontendsM[eSatipFrontendDVBT].Count();
+}
+
+int cSatipServer::GetModulesDVBT2(void)
+{
+  return frontendsM[eSatipFrontendDVBT2].Count();
+}
+
+int cSatipServer::GetModulesDVBC(void)
+{
+  return frontendsM[eSatipFrontendDVBC].Count();
+}
+
+int cSatipServer::GetModulesDVBC2(void)
+{
+  return frontendsM[eSatipFrontendDVBC2].Count();
 }
 
 // --- cSatipServers ----------------------------------------------------------
@@ -114,70 +265,87 @@
 cSatipServer *cSatipServers::Find(cSatipServer *serverP)
 {
   for (cSatipServer *s = First(); s; s = Next(s)) {
-      if (s == serverP)
+      if (s->Compare(*serverP) == 0)
          return s;
       }
   return NULL;
 }
 
-cSatipServer *cSatipServers::Find(int sourceP, int transponderP, int systemP)
+cSatipServer *cSatipServers::Find(int sourceP)
+{
+  for (cSatipServer *s = First(); s; s = Next(s)) {
+      if (s->Matches(sourceP))
+         return s;
+      }
+  return NULL;
+}
+
+cSatipServer *cSatipServers::Assign(int deviceIdP, int sourceP, int 
transponderP, int systemP)
+{
+  for (cSatipServer *s = First(); s; s = Next(s)) {
+      if (s->Matches(deviceIdP, sourceP, systemP, transponderP))
+         return s;
+      }
+  for (cSatipServer *s = First(); s; s = Next(s)) {
+      if (s->Assign(deviceIdP, sourceP, systemP, transponderP))
+         return s;
+      }
+  return NULL;
+}
+
+cSatipServer *cSatipServers::Update(cSatipServer *serverP)
 {
-  cSatipServer *result = NULL;
-  int model = 0;
-  if (cSource::IsType(sourceP, 'S'))
-     model |= cSatipServer::eSatipModelTypeDVBS2;
-  else if (cSource::IsType(sourceP, 'T')) {
-     if (systemP < 0)
-        model |= cSatipServer::eSatipModelTypeDVBT2 | 
cSatipServer::eSatipModelTypeDVBT;
-     else
-        model |= systemP ? cSatipServer::eSatipModelTypeDVBT2 : 
cSatipServer::eSatipModelTypeDVBT;
-     }
-  else if (cSource::IsType(sourceP, 'C'))
-     model |= cSatipServer::eSatipModelTypeDVBC;
   for (cSatipServer *s = First(); s; s = Next(s)) {
-      if (s->Match(model) && s->Used() && (s->Transponder() == transponderP))
+      if (s->Compare(*serverP) == 0) {
+         s->Update();
          return s;
+         }
       }
+  return NULL;
+}
+
+void cSatipServers::Attach(cSatipServer *serverP, int deviceIdP, int 
transponderP)
+{
   for (cSatipServer *s = First(); s; s = Next(s)) {
-      if (s->Match(model)) {
-         result = s;
-         if (!s->Used()) {
-            break;
-            }
+      if (s == serverP) {
+         s->Attach(deviceIdP, transponderP);
+         break;
          }
       }
-  return result;
 }
 
-void cSatipServers::SetTransponder(cSatipServer *serverP, int transponderP)
+void cSatipServers::Detach(cSatipServer *serverP, int deviceIdP, int 
transponderP)
 {
   for (cSatipServer *s = First(); s; s = Next(s)) {
       if (s == serverP) {
-         s->SetTransponder(transponderP);
+         s->Detach(deviceIdP, transponderP);
          break;
          }
       }
 }
 
-cSatipServer *cSatipServers::Update(cSatipServer *serverP)
+bool cSatipServers::IsQuirk(cSatipServer *serverP, int quirkP)
 {
+  bool result = false;
   for (cSatipServer *s = First(); s; s = Next(s)) {
-      if (s->Compare(*serverP) == 0) {
-         s->Update();
-         return s;
+      if (s == serverP) {
+         result = s->Quirk(quirkP);
+         break;
          }
       }
-  return NULL;
+  return result;
 }
 
-void cSatipServers::Use(cSatipServer *serverP, bool onOffP)
+bool cSatipServers::HasCI(cSatipServer *serverP)
 {
+  bool result = false;
   for (cSatipServer *s = First(); s; s = Next(s)) {
       if (s == serverP) {
-         s->Use(onOffP);
+         result = s->HasCI();
          break;
          }
       }
+  return result;
 }
 
 void cSatipServers::Cleanup(uint64_t intervalMsP)
@@ -190,6 +358,18 @@
       }
 }
 
+cString cSatipServers::GetAddress(cSatipServer *serverP)
+{
+  cString address = "";
+  for (cSatipServer *s = First(); s; s = Next(s)) {
+      if (s == serverP) {
+         address = s->Address();
+         break;
+         }
+      }
+  return address;
+}
+
 cString cSatipServers::GetString(cSatipServer *serverP)
 {
   cString list = "";
@@ -215,13 +395,15 @@
   int count = 0;
   for (cSatipServer *s = First(); s; s = Next(s)) {
       // DVB-S2: qpsk, 8psk, 16apsk, 32apsk
-      count += s->Satellite() * 4;
-      // DVB-T2: qpsk, qam16, qam64, qam256
+      count += s->GetModulesDVBS2() * 4;
       // DVB-T: qpsk, qam16, qam64
-      count += s->Terrestrial2() ? s->Terrestrial2() * 4 : s->Terrestrial() * 
3;
-      // DVB-C2: qam16, qam32, qam64, qam128, qam256
+      count += s->GetModulesDVBT() * 3;
+      // DVB-T2: qpsk, qam16, qam64, qam256
+      count += s->GetModulesDVBT2() * 4;
       // DVB-C: qam64, qam128, qam256
-      count += s->Cable2() ? s->Cable2() * 5 : s->Cable() * 3;
+      count += s->GetModulesDVBC() * 3;
+      // DVB-C2: qam16, qam32, qam64, qam128, qam256
+      count += s->GetModulesDVBC2() * 5;
       }
   return count;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/server.h new/satip-2.2.0/server.h
--- old/satip-1.0.2/server.h    2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/server.h    2015-02-19 03:20:00.000000000 +0100
@@ -8,26 +8,59 @@
 #ifndef __SATIP_SERVER_H
 #define __SATIP_SERVER_H
 
+class cSatipServer;
+
+// --- cSatipFrontend ---------------------------------------------------------
+
+class cSatipFrontend : public cListObject {
+private:
+  int indexM;
+  int transponderM;
+  int deviceIdM;
+  cString descriptionM;
+
+public:
+  cSatipFrontend(const int indexP, const char *descriptionP);
+  virtual ~cSatipFrontend();
+  void Attach(int deviceIdP) { deviceIdM = deviceIdP; }
+  void Detach(int deviceIdP) { if (deviceIdP == deviceIdM) deviceIdM = -1; }
+  cString Description(void) { return descriptionM; }
+  bool Attached(void) { return (deviceIdM >= 0); }
+  int Index(void) { return indexM; }
+  int Transponder(void) { return transponderM; }
+  int DeviceId(void) { return deviceIdM; }
+  void SetTransponder(int transponderP) { transponderM = transponderP; }
+};
+
+// --- cSatipFrontends --------------------------------------------------------
+
+class cSatipFrontends : public cList<cSatipFrontend> {
+public:
+  bool Matches(int deviceIdP, int transponderP);
+  bool Assign(int deviceIdP, int transponderP);
+  bool Attach(int deviceIdP, int transponderP);
+  bool Detach(int deviceIdP, int transponderP);
+};
+
 // --- cSatipServer -----------------------------------------------------------
 
 class cSatipServer : public cListObject {
 private:
-  enum eSatipModule {
-    eSatipModuleDVBS2 = 0,
-    eSatipModuleDVBT,
-    eSatipModuleDVBT2,
-    eSatipModuleDVBC,
-    eSatipModuleDVBC2,
-    eSatipModuleCount
+  enum eSatipFrontend {
+    eSatipFrontendDVBS2 = 0,
+    eSatipFrontendDVBT,
+    eSatipFrontendDVBT2,
+    eSatipFrontendDVBC,
+    eSatipFrontendDVBC2,
+    eSatipFrontendCount
   };
   cString addressM;
   cString modelM;
   cString descriptionM;
-  int modelCountM[eSatipModuleCount];
-  int modelTypeM;
+  cString quirksM;
+  cSatipFrontends frontendsM[eSatipFrontendCount];
   int quirkM;
-  int useCountM;
-  int transponderM;
+  bool hasCiM;
   time_t createdM;
   cTimeMs lastSeenM;
 
@@ -37,39 +70,31 @@
     eSatipQuirkSessionId = 0x01,
     eSatipQuirkPlayPids  = 0x02,
     eSatipQuirkForceLock = 0x04,
-    eSatipQuirkUseXCI    = 0x08,
     eSatipQuirkMask      = 0x0F
   };
-  enum eSatipModelType {
-    eSatipModelTypeNone  = 0x00,
-    eSatipModelTypeDVBS2 = 0x01,
-    eSatipModelTypeDVBT  = 0x02,
-    eSatipModelTypeDVBT2 = 0x04,
-    eSatipModelTypeDVBC  = 0x08,
-    eSatipModelTypeDVBC2 = 0x10,
-    eSatipModelTypeMask  = 0xFF
-  };
   cSatipServer(const char *addressP, const char *modelP, const char 
*descriptionP);
   virtual ~cSatipServer();
   virtual int Compare(const cListObject &listObjectP) const;
-  void Use(bool onOffP);
-  void SetTransponder(const int transponderP) { transponderM = transponderP; }
-  int Transponder(void)     { return transponderM; }
-  bool Used(void)           { return !!useCountM; }
-  const char *Address()     { return *addressM; }
-  const char *Model(void)   { return *modelM; }
-  const char *Description() { return *descriptionM; }
-  bool Quirk(int quirkP)    { return ((quirkP & eSatipQuirkMask) & quirkM); }
-  int ModelType(void)       { return modelTypeM; }
-  bool Match(int modelP)    { return ((modelP & eSatipModelTypeMask) & 
modelTypeM); }
-  int Cable()               { return Match(eSatipModelTypeDVBC)  ? 
modelCountM[eSatipModuleDVBC]  : 0; }
-  int Cable2()              { return Match(eSatipModelTypeDVBC2) ? 
modelCountM[eSatipModuleDVBC2] : 0; }
-  int Satellite()           { return Match(eSatipModelTypeDVBS2) ? 
modelCountM[eSatipModuleDVBS2] : 0; }
-  int Terrestrial()         { return Match(eSatipModelTypeDVBT)  ? 
modelCountM[eSatipModuleDVBT]  : 0; }
-  int Terrestrial2()        { return Match(eSatipModelTypeDVBT2) ? 
modelCountM[eSatipModuleDVBT2] : 0; }
-  void Update(void)         { lastSeenM.Set(); }
-  uint64_t LastSeen(void)   { return lastSeenM.Elapsed(); }
-  time_t Created(void)      { return createdM; }
+  bool Assign(int deviceIdP, int sourceP, int systemP, int transponderP);
+  bool Matches(int sourceP);
+  bool Matches(int deviceIdP, int sourceP, int systemP, int transponderP);
+  void Attach(int deviceIdP, int transponderP);
+  void Detach(int deviceIdP, int transponderP);
+  int GetModulesDVBS2(void);
+  int GetModulesDVBT(void);
+  int GetModulesDVBT2(void);
+  int GetModulesDVBC(void);
+  int GetModulesDVBC2(void);
+  const char *Address(void)     { return *addressM; }
+  const char *Model(void)       { return *modelM; }
+  const char *Description(void) { return *descriptionM; }
+  const char *Quirks(void)      { return *quirksM; }
+  bool Quirk(int quirkP)        { return ((quirkP & eSatipQuirkMask) & 
quirkM); }
+  bool HasQuirk(void)           { return (quirkM != eSatipQuirkNone); }
+  bool HasCI(void)              { return hasCiM; }
+  void Update(void)             { lastSeenM.Set(); }
+  uint64_t LastSeen(void)       { return lastSeenM.Elapsed(); }
+  time_t Created(void)          { return createdM; }
 };
 
 // --- cSatipServers ----------------------------------------------------------
@@ -77,11 +102,15 @@
 class cSatipServers : public cList<cSatipServer> {
 public:
   cSatipServer *Find(cSatipServer *serverP);
-  cSatipServer *Find(int sourceP, int transponderP, int systemP);
-  void SetTransponder(cSatipServer *serverP, int transponderP);
+  cSatipServer *Find(int sourceP);
+  cSatipServer *Assign(int deviceIdP, int sourceP, int transponderP, int 
systemP);
   cSatipServer *Update(cSatipServer *serverP);
-  void Use(cSatipServer *serverP, bool onOffP);
+  void Attach(cSatipServer *serverP, int deviceIdP, int transponderP);
+  void Detach(cSatipServer *serverP, int deviceIdP, int transponderP);
+  bool IsQuirk(cSatipServer *serverP, int quirkP);
+  bool HasCI(cSatipServer *serverP);
   void Cleanup(uint64_t intervalMsP = 0);
+  cString GetAddress(cSatipServer *serverP);
   cString GetString(cSatipServer *serverP);
   cString List(void);
   int NumProvidedSystems(void);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/setup.c new/satip-2.2.0/setup.c
--- old/satip-1.0.2/setup.c     2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/setup.c     2015-02-19 03:20:00.000000000 +0100
@@ -104,7 +104,7 @@
   addressM(serverP ? serverP->Address() : "---"),
   modelM(serverP ? serverP->Model() : "---"),
   descriptionM(serverP ? serverP->Description() : "---"),
-  ciExtensionM(serverP && serverP->Quirk(cSatipServer::eSatipQuirkUseXCI) ? 
trVDR("yes") : trVDR("no")),
+  ciExtensionM(serverP && serverP->HasCI() ? trVDR("yes") : trVDR("no")),
   createdM(serverP ? serverP->Created() : 0)
 {
   SetMenuCategory(mcSetupPlugins);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/socket.c new/satip-2.2.0/socket.c
--- old/satip-1.0.2/socket.c    2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/socket.c    2015-02-19 03:20:00.000000000 +0100
@@ -129,19 +129,24 @@
     if (len > 0)
        return len;
     } while (len > 0);
-  ERROR_IF_RET(len < 0 && errno != EAGAIN, "recvmsg()", return -1);
+  ERROR_IF_RET(len < 0 && errno != EAGAIN && errno != EWOULDBLOCK, 
"recvmsg()", return -1);
   return 0;
 }
 
 int cSatipSocket::ReadMulti(unsigned char *bufferAddrP, unsigned int 
*elementRecvSizeP, unsigned int elementCountP, unsigned int elementBufferSizeP)
 {
   debug16("%s (, , %d, %d)", __PRETTY_FUNCTION__, elementCountP, 
elementBufferSizeP);
-#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2,12)
+  int count = -1;
   // Error out if socket not initialized
   if (socketDescM <= 0) {
      error("%s Invalid socket", __PRETTY_FUNCTION__);
      return -1;
      }
+  if (!bufferAddrP || !elementRecvSizeP || !elementCountP || 
!elementBufferSizeP) {
+     error("%s Invalid parameter(s)", __PRETTY_FUNCTION__);
+     return -1;
+     }
+#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2,12)
   // Initialize iov and msgh structures
   struct mmsghdr mmsgh[elementCountP];
   struct iovec iov[elementCountP];
@@ -154,14 +159,12 @@
       }
 
   // Read data from socket as a set
-  int count = -1;
-  if (socketDescM && bufferAddrP && elementRecvSizeP && (elementCountP > 0) && 
(elementBufferSizeP > 0))
-     count = (int)recvmmsg(socketDescM, mmsgh, elementCountP, MSG_DONTWAIT, 
NULL);
+  count = (int)recvmmsg(socketDescM, mmsgh, elementCountP, MSG_DONTWAIT, NULL);
   ERROR_IF_RET(count < 0 && errno != EAGAIN && errno != EWOULDBLOCK, 
"recvmmsg()", return -1);
   for (int i = 0; i < count; ++i)
       elementRecvSizeP[i] = mmsgh[i].msg_len;
 #else
-  int count = 0;
+  count = 0;
   while (count < (int)elementCountP) {
         int len = Read(bufferAddrP + count * elementBufferSizeP, 
elementBufferSizeP);
         if (len < 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/tuner.c new/satip-2.2.0/tuner.c
--- old/satip-1.0.2/tuner.c     2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/tuner.c     2015-02-19 03:20:00.000000000 +0100
@@ -25,8 +25,8 @@
   rtcpM(*this),
   streamAddrM(""),
   streamParamM(""),
-  currentServerM(NULL),
-  nextServerM(NULL),
+  currentServerM(NULL, deviceP.GetId(), 0),
+  nextServerM(NULL, deviceP.GetId(), 0),
   mutexM(),
   reConnectM(),
   keepAliveM(),
@@ -40,6 +40,7 @@
   hasLockM(false),
   signalStrengthM(-1),
   signalQualityM(-1),
+  frontendIdM(-1),
   streamIdM(-1),
   pmtPidM(-1),
   addPidsM(),
@@ -118,7 +119,7 @@
                // Read reception statistics via DESCRIBE and RTCP
                if (hasLockM || ReadReceptionStatus()) {
                   // Quirk for devices without valid reception data
-                  if (currentServerM && 
currentServerM->Quirk(cSatipServer::eSatipQuirkForceLock)) {
+                  if 
(currentServerM.IsQuirk(cSatipServer::eSatipQuirkForceLock)) {
                      hasLockM = true;
                      signalStrengthM = eDefaultSignalStrength;
                      signalQualityM = eDefaultSignalQuality;
@@ -196,15 +197,15 @@
      else if (rtspM.Options(*connectionUri)) {
         cString uri = cString::sprintf("%s?%s", *connectionUri, *streamParamM);
         // Flush any old content
-        rtpM.Flush();
-        rtcpM.Flush();
+        //rtpM.Flush();
+        //rtcpM.Flush();
         if (rtspM.Setup(*uri, rtpM.Port(), rtcpM.Port())) {
            keepAliveM.Set(timeoutM);
-           if (nextServerM) {
-              cSatipDiscover::GetInstance()->UseServer(nextServerM, true);
+           if (nextServerM.IsValid()) {
               currentServerM = nextServerM;
-              nextServerM = NULL;
+              nextServerM.Reset();
               }
+           currentServerM.Attach();
            return true;
            }
         }
@@ -234,9 +235,9 @@
   hasLockM = false;
   signalStrengthM = -1;
   signalQualityM = -1;
+  frontendIdM = -1;
 
-  if (currentServerM)
-     cSatipDiscover::GetInstance()->UseServer(currentServerM, false);
+  currentServerM.Detach();
   statusUpdateM.Set(0);
   timeoutM = eMinKeepAliveIntervalMs;
   pmtPidM = -1;
@@ -285,6 +286,9 @@
      if (c)  {
         int value;
 
+        // feID:
+        frontendIdM = atoi(c + 7);
+
         // level:
         // Numerical value between 0 and 255
         // An incoming L-band satellite signal of
@@ -330,7 +334,7 @@
   cMutexLock MutexLock(&mutexM);
   debug1("%s (%s, %d) [device %d]", __PRETTY_FUNCTION__, sessionP, timeoutP, 
deviceIdM);
   sessionM = sessionP;
-  if (nextServerM && nextServerM->Quirk(cSatipServer::eSatipQuirkSessionId) && 
!isempty(*sessionM) && startswith(*sessionM, "0"))
+  if (nextServerM.IsQuirk(cSatipServer::eSatipQuirkSessionId) && 
!isempty(*sessionM) && startswith(*sessionM, "0"))
      rtspM.SetSession(SkipZeroes(*sessionM));
   timeoutM = (timeoutP > eMinKeepAliveIntervalMs) ? timeoutP : 
eMinKeepAliveIntervalMs;
 }
@@ -341,15 +345,15 @@
   return deviceIdM;
 }
 
-bool cSatipTuner::SetSource(cSatipServer *serverP, const char *parameterP, 
const int indexP)
+bool cSatipTuner::SetSource(cSatipServer *serverP, const int transponderP, 
const char *parameterP, const int indexP)
 {
-  debug1("%s (%s, %d) [device %d]", __PRETTY_FUNCTION__, parameterP, indexP, 
deviceIdM);
+  debug1("%s (%d, %s, %d) [device %d]", __PRETTY_FUNCTION__, transponderP, 
parameterP, indexP, deviceIdM);
   cMutexLock MutexLock(&mutexM);
   if (serverP) {
-     nextServerM = cSatipDiscover::GetInstance()->GetServer(serverP);
-     if (nextServerM && !isempty(nextServerM->Address()) && 
!isempty(parameterP)) {
+     nextServerM.Set(serverP, transponderP);
+     if (!isempty(*nextServerM.GetAddress()) && !isempty(parameterP)) {
         // Update stream address and parameter
-        streamAddrM = rtspM.RtspUnescapeString(nextServerM->Address());
+        streamAddrM = rtspM.RtspUnescapeString(*nextServerM.GetAddress());
         streamParamM = rtspM.RtspUnescapeString(parameterP);
         // Reconnect
         RequestState(tsSet, smExternal);
@@ -390,8 +394,8 @@
   if (((forceP && pidsM.Size()) || (pidUpdateCacheM.TimedOut() && 
(addPidsM.Size() || delPidsM.Size()))) &&
       !isempty(*streamAddrM) && (streamIdM > 0)) {
      cString uri = cString::sprintf("rtsp://%s/stream=%d", *streamAddrM, 
streamIdM);
-     bool useci = (SatipConfig.GetCIExtension() && !!(currentServerM && 
currentServerM->Quirk(cSatipServer::eSatipQuirkUseXCI)));
-     bool usedummy = !!(currentServerM && 
currentServerM->Quirk(cSatipServer::eSatipQuirkPlayPids));
+     bool useci = (SatipConfig.GetCIExtension() && currentServerM.HasCI());
+     bool usedummy = currentServerM.IsQuirk(cSatipServer::eSatipQuirkPlayPids);
      if (forceP || usedummy) {
         if (pidsM.Size())
            uri = cString::sprintf("%s?pids=%s", *uri, *pidsM.ListPids());
@@ -558,6 +562,12 @@
   return "---";
 }
 
+int cSatipTuner::FrontendId(void)
+{
+  debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
+  return frontendIdM;
+}
+
 int cSatipTuner::SignalStrength(void)
 {
   debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
@@ -579,7 +589,7 @@
 cString cSatipTuner::GetSignalStatus(void)
 {
   debug16("%s [device %d]", __PRETTY_FUNCTION__, deviceIdM);
-  return cString::sprintf("lock=%d strength=%d quality=%d", HasLock(), 
SignalStrength(), SignalQuality());
+  return cString::sprintf("lock=%d strength=%d quality=%d frontend=%d", 
HasLock(), SignalStrength(), SignalQuality(), FrontendId());
 }
 
 cString cSatipTuner::GetInformation(void)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/satip-1.0.2/tuner.h new/satip-2.2.0/tuner.h
--- old/satip-1.0.2/tuner.h     2015-01-18 03:20:00.000000000 +0100
+++ new/satip-2.2.0/tuner.h     2015-02-19 03:20:00.000000000 +0100
@@ -8,11 +8,11 @@
 #ifndef __SATIP_TUNER_H
 #define __SATIP_TUNER_H
 
-#include <vdr/config.h> // APIVERSNUM
 #include <vdr/thread.h>
 #include <vdr/tools.h>
 
 #include "deviceif.h"
+#include "discover.h"
 #include "rtp.h"
 #include "rtcp.h"
 #include "rtsp.h"
@@ -27,33 +27,6 @@
   }
 
 public:
-#if defined(APIVERSNUM) && APIVERSNUM < 20107
-  int IndexOf(const int &pidP)
-  {
-    for (int i = 0; i < Size(); ++i) {
-        if (pidP == At(i))
-           return i;
-        }
-    return -1;
-  }
-  bool RemoveElement(const int &pidP)
-  {
-    int i = IndexOf(pidP);
-    if (i >= 0) {
-       Remove(i);
-       return true;
-       }
-    return false;
-  }
-  bool AppendUnique(int pidP)
-  {
-    if (IndexOf(pidP) < 0) {
-       Append(pidP);
-       return true;
-       }
-    return false;
-  }
-#endif
   void RemovePid(const int &pidP)
   {
     if (RemoveElement(pidP))
@@ -76,6 +49,29 @@
   }
 };
 
+class cSatipTunerServer
+{
+private:
+  cSatipServer *serverM;
+  int deviceIdM;
+  int transponderM;
+
+public:
+  cSatipTunerServer(cSatipServer *serverP, const int deviceIdP, const int 
transponderP) : serverM(serverP), deviceIdM(deviceIdP), 
transponderM(transponderP) {}
+  ~cSatipTunerServer() {}
+  cSatipTunerServer(const cSatipTunerServer &objP) { serverM = NULL; deviceIdM 
= -1; transponderM = 0; }
+  cSatipTunerServer& operator= (const cSatipTunerServer &objP) { serverM = 
objP.serverM; deviceIdM = objP.deviceIdM; transponderM = objP.transponderM; 
return *this; }
+  bool IsValid(void) { return !!serverM; }
+  bool IsQuirk(int quirkP) { return (serverM && 
cSatipDiscover::GetInstance()->IsServerQuirk(serverM, quirkP)); }
+  bool HasCI(void) { return (serverM && 
cSatipDiscover::GetInstance()->HasServerCI(serverM)); }
+  void Attach(void) { if (serverM) 
cSatipDiscover::GetInstance()->AttachServer(serverM, deviceIdM, transponderM); }
+  void Detach(void) { if (serverM) 
cSatipDiscover::GetInstance()->DetachServer(serverM, deviceIdM, transponderM); }
+  void Set(cSatipServer *serverP, const int transponderP) { serverM = serverP; 
transponderM = transponderP; }
+  void Reset(void) { serverM = NULL; transponderM = 0; }
+  cString GetAddress(void) { return serverM ? 
cSatipDiscover::GetInstance()->GetServerAddress(serverM) : ""; }
+  cString GetInfo(void) { return cString::sprintf("server=%s deviceid=%d 
transponder=%d", serverM ? "assigned" : "null", deviceIdM, transponderM); }
+};
+
 class cSatipTuner : public cThread, public cSatipTunerStatistics, public 
cSatipTunerIf
 {
 private:
@@ -100,8 +96,8 @@
   cSatipRtcp rtcpM;
   cString streamAddrM;
   cString streamParamM;
-  cSatipServer *currentServerM;
-  cSatipServer *nextServerM;
+  cSatipTunerServer currentServerM;
+  cSatipTunerServer nextServerM;
   cMutex mutexM;
   cTimeMs reConnectM;
   cTimeMs keepAliveM;
@@ -115,6 +111,7 @@
   bool hasLockM;
   int signalStrengthM;
   int signalQualityM;
+  int frontendIdM;
   int streamIdM;
   int pmtPidM;
   cSatipPid addPidsM;
@@ -139,10 +136,11 @@
   cSatipTuner(cSatipDeviceIf &deviceP, unsigned int packetLenP);
   virtual ~cSatipTuner();
   bool IsTuned(void) const { return (currentStateM >= tsTuned); }
-  bool SetSource(cSatipServer *serverP, const char *parameterP, const int 
indexP);
+  bool SetSource(cSatipServer *serverP, const int transponderP, const char 
*parameterP, const int indexP);
   bool SetPid(int pidP, int typeP, bool onP);
   bool Open(void);
   bool Close(void);
+  int FrontendId(void);
   int SignalStrength(void);
   int SignalQuality(void);
   bool HasLock(void);

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to