From 59509b4e918123e1faeaae46b5ae8c6506f36dfc Mon Sep 17 00:00:00 2001
From: Karl Dietz <dekarl@users.sourceforge.net>
Date: Tue, 22 May 2012 23:30:38 +0200
Subject: [PATCH 7/7] Handle EIT events of the active transport without looking at original_network_id or transport_id

Refs #10217
---
 mythtv/libs/libmythtv/eithelper.cpp  |  112 ++++++++++++++++++++++++++++++----
 mythtv/libs/libmythtv/eithelper.h    |    6 ++
 mythtv/libs/libmythtv/eitscanner.cpp |    3 +
 mythtv/libs/libmythtv/tv_rec.cpp     |   10 +++
 mythtv/libs/libmythtv/tv_rec.h       |    1 +
 5 files changed, 120 insertions(+), 12 deletions(-)

diff --git a/mythtv/libs/libmythtv/eithelper.cpp b/mythtv/libs/libmythtv/eithelper.cpp
index df145fc..dd82960 100644
--- a/mythtv/libs/libmythtv/eithelper.cpp
+++ b/mythtv/libs/libmythtv/eithelper.cpp
@@ -25,10 +25,12 @@ using namespace std;
 const uint EITHelper::kChunkSize = 20;
 EITCache *EITHelper::eitcache = new EITCache();
 
-static uint get_chan_id_from_db(uint sourceid,
-                                uint atscmajor, uint atscminor);
-static uint get_chan_id_from_db(uint sourceid,  uint serviceid,
-                                uint networkid, uint transportid);
+static uint get_chan_id_from_db_atsc(uint sourceid,
+                                     uint atscmajor, uint atscminor);
+static uint get_chan_id_from_db_dvb(uint sourceid,  uint serviceid,
+                                    uint networkid, uint transportid);
+static uint get_chan_id_from_db_dtv(uint sourceid,
+                                    uint programnumber, uint tunedchanid);
 static void init_fixup(QMap<uint64_t,uint> &fix);
 static int calc_eit_utc_offset(void);
 
@@ -37,7 +39,7 @@ static int calc_eit_utc_offset(void);
 EITHelper::EITHelper() :
     eitfixup(new EITFixUp()),
     gps_offset(-1 * GPS_LEAP_SECONDS),          utc_offset(0),
-    sourceid(0)
+    sourceid(0), channelid(0)
 {
     init_fixup(fixup);
 
@@ -146,6 +148,12 @@ void EITHelper::SetSourceID(uint _sourceid)
     sourceid = _sourceid;
 }
 
+void EITHelper::SetChannelID(uint _channelid)
+{
+    QMutexLocker locker(&eitList_lock);
+    channelid = _channelid;
+}
+
 void EITHelper::AddEIT(uint atsc_major, uint atsc_minor,
                        const EventInformationTable *eit)
 {
@@ -318,8 +326,18 @@ void EITHelper::AddEIT(const DVBEventInformationTable *eit)
                   (uint64_t)eit->ServiceID());
     fix |= EITFixUp::kFixGenericDVB;
 
-    uint chanid = GetChanID(eit->ServiceID(), eit->OriginalNetworkID(),
-                            eit->TSID());
+    uint chanid = 0;
+    if ((eit->TableID() == TableID::PF_EIT) ||
+        ((eit->TableID() >= TableID::SC_EITbeg) && (eit->TableID() <= TableID::SC_EITend)))
+    {
+        // EITa(ctive)
+        chanid = GetChanID(eit->ServiceID());
+    }
+    else
+    {
+        // EITo(ther)
+        chanid = GetChanID(eit->ServiceID(), eit->OriginalNetworkID(), eit->TSID());
+    }
     if (!chanid)
         return;
 
@@ -684,7 +702,7 @@ uint EITHelper::GetChanID(uint atsc_major, uint atsc_minor)
     if (it != srv_to_chanid.end())
         return max(*it, 0);
 
-    uint chanid = get_chan_id_from_db(sourceid, atsc_major, atsc_minor);
+    uint chanid = get_chan_id_from_db_atsc(sourceid, atsc_major, atsc_minor);
     if (chanid)
         srv_to_chanid[key] = chanid;
 
@@ -703,14 +721,32 @@ uint EITHelper::GetChanID(uint serviceid, uint networkid, uint tsid)
     if (it != srv_to_chanid.end())
         return max(*it, 0);
 
-    uint chanid = get_chan_id_from_db(sourceid, serviceid, networkid, tsid);
+    uint chanid = get_chan_id_from_db_dvb(sourceid, serviceid, networkid, tsid);
     if (chanid)
         srv_to_chanid[key] = chanid;
 
     return chanid;
 }
 
-static uint get_chan_id_from_db(uint sourceid,
+uint EITHelper::GetChanID(uint program_number)
+{
+    uint64_t key;
+    key  = ((uint64_t) sourceid);
+    key |= ((uint64_t) program_number) << 16;
+    key |= ((uint64_t) channelid)      << 32;
+
+    ServiceToChanID::const_iterator it = srv_to_chanid.find(key);
+    if (it != srv_to_chanid.end())
+        return max(*it, 0);
+
+    uint chanid = get_chan_id_from_db_dtv(sourceid, program_number, channelid);
+    if (chanid)
+        srv_to_chanid[key] = chanid;
+
+    return chanid;
+}
+
+static uint get_chan_id_from_db_atsc(uint sourceid,
                                 uint atsc_major, uint atsc_minor)
 {
     MSqlQuery query(MSqlQuery::InitCon());
@@ -736,7 +772,7 @@ static uint get_chan_id_from_db(uint sourceid,
 }
 
 // Figure out the chanid for this channel
-static uint get_chan_id_from_db(uint sourceid, uint serviceid,
+static uint get_chan_id_from_db_dvb(uint sourceid, uint serviceid,
                                 uint networkid, uint transportid)
 {
     uint chanid = 0;
@@ -769,7 +805,8 @@ static uint get_chan_id_from_db(uint sourceid, uint serviceid,
             return useOnAirGuide ? chanid : 0;
     }
 
-    if (query.size() > 1) {
+    if (query.size() > 1)
+    {
         LOG(VB_EIT, LOG_INFO,
             LOC + QString("found %1 channels for networdid %2, "
                           "transportid %3, serviceid %4 but none "
@@ -781,6 +818,57 @@ static uint get_chan_id_from_db(uint sourceid, uint serviceid,
     return useOnAirGuide ? chanid : 0;
 }
 
+/* Figure out the chanid for this channel from the sourceid,
+ * program_number/service_id and the chanid of the channel we are tuned to
+ *
+ * TODO for SPTS (e.g. HLS / IPTV) it would be useful to match without an entry
+ * in dtv_multiplex
+ */
+static uint get_chan_id_from_db_dtv(uint sourceid, uint serviceid,
+                                uint tunedchanid)
+{
+    uint chanid = 0;
+    bool useOnAirGuide = false;
+    MSqlQuery query(MSqlQuery::InitCon());
+
+    // DVB Link to chanid
+    QString qstr =
+        "SELECT c1.chanid, c1.useonairguide, c1.sourceid "
+        "FROM channel c1, dtv_multiplex m, channel c2 "
+        "WHERE c1.serviceid        = :SERVICEID   AND "
+        "      c1.mplexid  = m.mplexid AND "
+        "      m.mplexid = c2.mplexid AND "
+        "      c2.chanid = :CHANID";
+
+    query.prepare(qstr);
+    query.bindValue(":SERVICEID",   serviceid);
+    query.bindValue(":CHANID", tunedchanid);
+
+    if (!query.exec() || !query.isActive())
+        MythDB::DBError("Looking up chanID", query);
+
+    while (query.next())
+    {
+        // Check to see if we are interested in this channel
+        chanid        = query.value(0).toUInt();
+        useOnAirGuide = query.value(1).toBool();
+        if (sourceid == query.value(2).toUInt())
+            return useOnAirGuide ? chanid : 0;
+    }
+
+    if (query.size() > 1)
+    {
+        LOG(VB_EIT, LOG_INFO,
+            LOC + QString("found %1 channels for multiplex of chanid %2, "
+                          "serviceid %3 but none "
+                          "for current sourceid %4.")
+                .arg(query.size()).arg(tunedchanid)
+                .arg(serviceid).arg(sourceid));
+    }
+
+    return useOnAirGuide ? chanid : 0;
+}
+
 static void init_fixup(QMap<uint64_t,uint> &fix)
 {
     ///////////////////////////////////////////////////////////////////////////
diff --git a/mythtv/libs/libmythtv/eithelper.h b/mythtv/libs/libmythtv/eithelper.h
index 6fca7d5..e83244a 100644
--- a/mythtv/libs/libmythtv/eithelper.h
+++ b/mythtv/libs/libmythtv/eithelper.h
@@ -66,6 +66,7 @@ class EITHelper
 
     uint GetGPSOffset(void) const { return (uint) (0 - gps_offset); }
 
+    void SetChannelID(uint _channelid);
     void SetGPSOffset(uint _gps_offset) { gps_offset = 0 - _gps_offset; }
     void SetFixup(uint atsc_major, uint atsc_minor, uint eitfixup);
     void SetLanguagePreferences(const QStringList &langPref);
@@ -90,8 +91,12 @@ class EITHelper
     void WriteEITCache(void);
 
   private:
+    // only ATSC
     uint GetChanID(uint atsc_major, uint atsc_minor);
+    // only DVB
     uint GetChanID(uint serviceid, uint networkid, uint transportid);
+    // any DTV
+    uint GetChanID(uint program_number);
 
     void CompleteEvent(uint atsc_major, uint atsc_minor,
                        const ATSCEvent &event,
@@ -107,6 +112,7 @@ class EITHelper
     int                     gps_offset;
     int                     utc_offset;
     uint                    sourceid;
+    uint                    channelid;
     QMap<uint64_t,uint>     fixup;
     ATSCSRCToEvents         incomplete_events;
     ATSCSRCToETTs           unmatched_etts;
diff --git a/mythtv/libs/libmythtv/eitscanner.cpp b/mythtv/libs/libmythtv/eitscanner.cpp
index 2e42bd5..8acf7e9 100644
--- a/mythtv/libs/libmythtv/eitscanner.cpp
+++ b/mythtv/libs/libmythtv/eitscanner.cpp
@@ -134,6 +134,8 @@ void EITScanner::run(void)
             {
                 eitHelper->WriteEITCache();
                 rec->SetChannel(*activeScanNextChan, TVRec::kFlagEITScan);
+                eitHelper->SetChannelID(ChannelUtil::GetChanID(rec->GetSourceID(),
+                                                            *activeScanNextChan));
                 LOG(VB_EIT, LOG_INFO,
                     LOC_ID + QString("Now looking for EIT data on "
                                      "multiplex of channel %1")
@@ -204,6 +206,7 @@ void EITScanner::StartPassiveScan(ChannelBase *_channel,
     eitHelper->SetSourceID(sourceid);
     eitSource->SetEITHelper(eitHelper);
     eitSource->SetEITRate(1.0f);
+    eitHelper->SetChannelID(_channel->GetChanID());
 
     LOG(VB_EIT, LOG_INFO, LOC_ID + "Started passive scan.");
 }
diff --git a/mythtv/libs/libmythtv/tv_rec.cpp b/mythtv/libs/libmythtv/tv_rec.cpp
index a5d4986..fc9e96c 100644
--- a/mythtv/libs/libmythtv/tv_rec.cpp
+++ b/mythtv/libs/libmythtv/tv_rec.cpp
@@ -2934,6 +2934,16 @@ QString TVRec::GetInput(void) const
     return QString::null;
 }
 
+/** \fn TVRec::GetSourceID(void) const
+ *  \brief Returns current source id.
+ */
+uint TVRec::GetSourceID(void) const
+{
+    if (channel)
+        return channel->GetCurrentSourceID();
+    return 0;
+}
+
 /** \fn TVRec::SetInput(QString, uint)
  *  \brief Changes to the specified input.
  *
diff --git a/mythtv/libs/libmythtv/tv_rec.h b/mythtv/libs/libmythtv/tv_rec.h
index ce54bff..6c2aaf8 100644
--- a/mythtv/libs/libmythtv/tv_rec.h
+++ b/mythtv/libs/libmythtv/tv_rec.h
@@ -192,6 +192,7 @@ class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable
 
     vector<InputInfo> GetFreeInputs(const vector<uint> &excluded_cards) const;
     QString     GetInput(void) const;
+    uint        GetSourceID(void) const;
     QString     SetInput(QString input, uint requestType = kFlagDetect);
 
     /// Changes to a channel in the 'dir' channel change direction.
-- 
1.7.4.1

