Remove check legacy dvbapi version.
[vuplus_dvbapp] / lib / dvb / dvb.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 0a371f0..852c403
@@ -7,6 +7,7 @@
 #include <lib/dvb/specs.h>
 
 #include <lib/dvb/fbc.h>
+#include <lib/dvb/fcc.h>
 
 #include <errno.h>
 #include <sys/types.h>
@@ -14,6 +15,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <fstream>
 
 DEFINE_REF(eDVBRegisteredFrontend);
 DEFINE_REF(eDVBRegisteredDemux);
@@ -33,7 +35,7 @@ eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
                eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
                if (fbcmng)
                {
-                       fbcmng->unset(m_fe);
+                       fbcmng->unLink(m_fe);
                }
        }
 }
@@ -92,6 +94,8 @@ eDVBResourceManager::eDVBResourceManager()
                num_adapter++;
        }
 
+       setUsbTuner();
+
        int fd = open("/proc/stb/info/model", O_RDONLY);
        char tmp[255];
        int rd = fd >= 0 ? read(fd, tmp, 255) : 0;
@@ -125,6 +129,8 @@ eDVBResourceManager::eDVBResourceManager()
 
        eDVBCAService::registerChannelCallback(this);
 
+       m_fbc_mng = new eFBCTunerManager(this);
+
        CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
 }
 
@@ -148,11 +154,7 @@ eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
        {
                struct stat s;
                char filename[128];
-#if HAVE_DVB_API_VERSION < 3
-               sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
-#else
                sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
-#endif
                if (stat(filename, &s))
                        break;
                eDVBFrontend *fe;
@@ -179,11 +181,7 @@ eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
        {
                struct stat s;
                char filename[128];
-#if HAVE_DVB_API_VERSION < 3
-               sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
-#else
                sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
-#endif
                if (stat(filename, &s))
                        break;
                ePtr<eDVBDemux> demux;
@@ -243,11 +241,7 @@ int eDVBAdapterLinux::exist(int nr)
 {
        struct stat s;
        char filename[128];
-#if HAVE_DVB_API_VERSION < 3
-       sprintf(filename, "/dev/dvb/card%d", nr);
-#else
        sprintf(filename, "/dev/dvb/adapter%d", nr);
-#endif
        if (!stat(filename, &s))
                return 1;
        return 0;
@@ -322,6 +316,59 @@ void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
 
 }
 
+void eDVBResourceManager::setUsbTuner()
+{
+       std::ifstream in("/proc/bus/nim_sockets");
+       std::string line;
+
+       int res = -1;
+       int fe_idx = -1;
+       int usbtuner_idx[8] = {0};
+       int usbtuner_count = 0;
+
+       if (in.is_open())
+       {
+               while(!in.eof())
+               {
+                       getline(in, line);
+                       if ((res = sscanf(line.c_str(), "NIM Socket %d:", &fe_idx)) == 1)
+                               continue;
+
+                       if ((fe_idx != -1) && (line.find("\tName: ") == 0) && (line.find("VTUNER") != -1))
+                               usbtuner_idx[usbtuner_count++] = fe_idx;
+               }
+               in.close();
+       }
+
+       if (usbtuner_count)
+       {
+               for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_frontend.begin()); it != m_frontend.end(); ++it)
+               {
+                       int slotid = it->m_frontend->getSlotID();
+                       for (int i=0; i < usbtuner_count ; i++)
+                       {
+                               if (slotid == usbtuner_idx[i])
+                               {
+                                       it->m_frontend->setUSBTuner(true);
+                                       break;
+                               }
+                       }
+               }
+               for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_simulate_frontend.begin()); it != m_simulate_frontend.end(); ++it)
+               {
+                       int slotid = it->m_frontend->getSlotID();
+                       for (int i=0; i < usbtuner_count ; i++)
+                       {
+                               if (slotid == usbtuner_idx[i])
+                               {
+                                       it->m_frontend->setUSBTuner(true);
+                                       break;
+                               }
+                       }
+               }
+       }
+}
+
 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
 {
        if (!PyList_Check(list))
@@ -385,7 +432,7 @@ bool eDVBResourceManager::frontendIsCompatible(int index, const char *type)
                        }
                        else if (!strcmp(type, "DVB-C"))
                        {
-#if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
+#if defined SYS_DVBC_ANNEX_A
                                return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_A, false);
 #else
                                return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_AC, false);
@@ -417,7 +464,7 @@ void eDVBResourceManager::setFrontendType(int index, const char *type)
                        }
                        else if (!strcmp(type, "DVB-C"))
                        {
-#if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
+#if defined SYS_DVBC_ANNEX_A
                                whitelist.push_back(SYS_DVBC_ANNEX_A);
 #else
                                whitelist.push_back(SYS_DVBC_ANNEX_AC);
@@ -432,26 +479,34 @@ void eDVBResourceManager::setFrontendType(int index, const char *type)
 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
 {
        eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
-//     ePtr<eDVBRegisteredFrontend> best;
        eDVBRegisteredFrontend *best = NULL;
        int bestval = 0;
        int foundone = 0;
 
-       int check_fbc_linked = 0;
+       int check_fbc_leaf_linkable = 0;
+       int current_fbc_setid = -1;
        eDVBRegisteredFrontend *fbc_fe = NULL;
        eDVBRegisteredFrontend *best_fbc_fe = NULL;
-       eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
 
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
        {
                int c = 0;
                fbc_fe = NULL;
-               if (!check_fbc_linked && i->m_frontend->is_FBCTuner() && fbcmng && fbcmng->canLink(*i))
+               if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
                {
-                       check_fbc_linked = 1;
-                       c = fbcmng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
+                       int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
+                       if (fbc_setid != current_fbc_setid)
+                       {
+                               current_fbc_setid = fbc_setid;
+                               check_fbc_leaf_linkable = 0;
+                       }
 
-//                     eDebug("[eDVBResourceManager::allocateFrontend] fbcmng->isCompatibleWith slotid : %p (%d), fbc_fe : %p (%d), score : %d", (eDVBRegisteredFrontend *)*i,  i->m_frontend->getSlotID(), fbc_fe, fbc_fe?fbc_fe->m_frontend->getSlotID():-1, c);                     
+                       if (!check_fbc_leaf_linkable)
+                       {
+                               c = m_fbc_mng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
+                               check_fbc_leaf_linkable = 1;
+                               eDebug("[eDVBResourceManager::allocateFrontend] m_fbc_mng->isCompatibleWith slotid : %p (%d), fbc_fe : %p (%d), score : %d", (eDVBRegisteredFrontend *)*i,  i->m_frontend->getSlotID(), fbc_fe, fbc_fe?fbc_fe->m_frontend->getSlotID():-1, c);
+                       }
                }
                else
                {
@@ -463,18 +518,17 @@ RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, eP
 
                if (!i->m_inuse)
                {
-//                     eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
+                       eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
                        if (c > bestval)
                        {
                                bestval = c;
-//                             best = i;
                                best = *i;
                                best_fbc_fe = fbc_fe;
                        }
                }
                else
                {
-//                     eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
+                       eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
                }
 
                eDVBRegisteredFrontend *tmp = *i;
@@ -482,9 +536,9 @@ RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, eP
 
        if (best)
        {
-               if (fbcmng && best_fbc_fe)
+               if (best_fbc_fe)
                {
-                       fbcmng->addLink(best, best_fbc_fe, simulate);
+                       m_fbc_mng->addLink(best, best_fbc_fe, simulate);
                }
 
                fe = new eDVBAllocatedFrontend(best);
@@ -910,18 +964,29 @@ int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &fepar
        eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
        ePtr<eDVBRegisteredFrontend> best;
        int bestval = 0;
-       int check_fbc_link = 0;
-       eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance();
+       int check_fbc_leaf_linkable = 0;
+       int current_fbc_setid = -1;
 
        for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
        {
                if (!i->m_inuse)
                {
                        int c = 0;
-                       if(fbcmng && i->m_frontend->is_FBCTuner() && fbcmng->canLink(*i) && !check_fbc_link)
+                       if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
                        {
-                               check_fbc_link = 1;
-                               c = fbcmng->isCompatibleWith(feparm, *i, simulate);
+                               int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
+                               if (fbc_setid != current_fbc_setid)
+                               {
+                                       current_fbc_setid = fbc_setid;
+                                       check_fbc_leaf_linkable = 0;
+                               }
+
+                               if (!check_fbc_leaf_linkable)
+                               {
+                                       eDVBRegisteredFrontend *dummy;
+                                       c = m_fbc_mng->isCompatibleWith(feparm, *i, dummy, simulate);
+                                       check_fbc_leaf_linkable = 1;
+                               }
                        }
                        else
                        {
@@ -988,6 +1053,56 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
        int *decremented_cached_channel_fe_usecount=NULL,
                *decremented_fe_usecount=NULL;
 
+       /* check FCC channels */
+       std::vector<int*> fcc_decremented_fe_usecounts;
+       std::map<eDVBChannelID, int> fcc_chids;
+       int apply_to_ignore = 0;
+       if (!eFCCServiceManager::getFCCChannelID(fcc_chids))
+       {
+               for (std::map<eDVBChannelID, int>::iterator i(fcc_chids.begin()); i != fcc_chids.end(); ++i)
+               {
+                       //eDebug("[eDVBResourceManager::canAllocateChannel] FCC NS : %08x, TSID : %04x, ONID : %04x", i->first.dvbnamespace.get(), i->first.transport_stream_id.get(), i->first.original_network_id.get());
+                       if (ignore == i->first)
+                       {
+                               apply_to_ignore = i->second;
+                               continue;
+                       }
+                       for (std::list<active_channel>::iterator ii(active_channels.begin()); ii != active_channels.end(); ++ii)
+                       {
+                               eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
+                               if (ii->m_channel_id == i->first)
+                               {
+                                       eDVBChannel *channel = (eDVBChannel*) &(*ii->m_channel);
+
+                                       int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
+                                       check_usecount += i->second * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
+                                       //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
+                                       if (channel->getUseCount() == check_usecount)
+                                       {
+                                               ePtr<iDVBFrontend> fe;
+                                               if (!ii->m_channel->getFrontend(fe))
+                                               {
+                                                       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator iii(frontends.begin()); iii != frontends.end(); ++iii)
+                                                       {
+                                                               if ( &(*fe) == &(*iii->m_frontend) )
+                                                               {
+                                                                       //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : decrease fcc fe use_count! feid : %d (%d -> %d)", iii->m_frontend->getSlotID(), iii->m_inuse, iii->m_inuse-1);
+                                                                       --iii->m_inuse;
+                                                                       int *tmp_decremented_fe_usecount = &iii->m_inuse;
+                                                                       fcc_decremented_fe_usecounts.push_back(tmp_decremented_fe_usecount);
+                                                                       if (channel == &(*m_cached_channel))
+                                                                               decremented_cached_channel_fe_usecount = tmp_decremented_fe_usecount;
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       break;
+                               }
+                       }
+               }
+       }
+
        for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
        {
                eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
@@ -999,7 +1114,10 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
                        // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
                        // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
                        // or 2 when the cached channel is not equal to the compared channel
-                       if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2)  // channel only used once..
+                       int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
+                       check_usecount += (apply_to_ignore+1) * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
+                       //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
+                       if (channel->getUseCount() == check_usecount)  // channel only used once..(except fcc)
                        {
                                ePtr<iDVBFrontend> fe;
                                if (!i->m_channel->getFrontend(fe))
@@ -1008,6 +1126,7 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
                                        {
                                                if ( &(*fe) == &(*ii->m_frontend) )
                                                {
+                                                       //eDebug("[eDVBResourceManager::canAllocateChannel] ignore : decrease fcc fe use_count! feid : %d (%d -> %d)", ii->m_frontend->getSlotID(), ii->m_inuse, ii->m_inuse-1);
                                                        --ii->m_inuse;
                                                        decremented_fe_usecount = &ii->m_inuse;
                                                        if (channel == &(*m_cached_channel))
@@ -1070,6 +1189,14 @@ error:
                ++(*decremented_fe_usecount);
        if (decremented_cached_channel_fe_usecount)
                ++(*decremented_cached_channel_fe_usecount);
+       if (fcc_decremented_fe_usecounts.size())
+       {
+               for (std::vector<int*>::iterator i(fcc_decremented_fe_usecounts.begin()); i != fcc_decremented_fe_usecounts.end(); ++i)
+               {
+                       //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : increase fcc fe use_count!");
+                       ++(**i);
+               }
+       }
 
        return ret;
 }
@@ -1363,6 +1490,10 @@ void eDVBChannel::pvrEvent(int event)
                eDebug("SOF");
                m_event(this, evtSOF);
                break;
+       case eFilePushThread::evtUser+3: /* limit space */
+               eDebug("Too large file");
+               m_event(this, evtFailed+3);
+               break;
        }
 }
 
@@ -1948,7 +2079,8 @@ RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_f
                return -ENOENT;
        }
 
-       m_tstools.setSource(source, streaminfo_file);
+       m_source = source;
+       m_tstools.setSource(m_source, streaminfo_file);
 
                /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
                   THEN DO A REAL FIX HERE! */
@@ -1956,14 +2088,6 @@ RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_f
        if (m_pvr_fd_dst < 0)
        {
                /* (this codepath needs to be improved anyway.) */
-#if HAVE_DVB_API_VERSION < 3
-               m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
-               if (m_pvr_fd_dst < 0)
-               {
-                       eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
-                       return -ENODEV;
-               }
-#else
                ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
                if (demux)
                {
@@ -1979,18 +2103,17 @@ RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_f
                        eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
                        return -ENODEV;
                }
-#endif
        }
 
        m_pvr_thread = new eDVBChannelFilePush();
        m_pvr_thread->enablePVRCommit(1);
        /* If the source specifies a length, it's a file. If not, it's a stream */
-       m_pvr_thread->setStreamMode(source->isStream());
+       m_pvr_thread->setStreamMode(m_source->isStream());
        m_pvr_thread->setScatterGather(this);
 
        m_event(this, evtPreStart);
 
-       m_pvr_thread->start(source, m_pvr_fd_dst);
+       m_pvr_thread->start(m_source, m_pvr_fd_dst);
        CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
 
        m_state = state_ok;
@@ -2008,9 +2131,13 @@ void eDVBChannel::stopSource()
                m_pvr_thread = 0;
        }
        if (m_pvr_fd_dst >= 0)
+       {
                ::close(m_pvr_fd_dst);
-       ePtr<iTsSource> d;
-       m_tstools.setSource(d);
+               m_pvr_fd_dst = -1;
+       }
+
+       m_source = NULL;
+       m_tstools.setSource(m_source);
 }
 
 void eDVBChannel::stopFile()
@@ -2051,8 +2178,7 @@ RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, in
        } else
                now = pos; /* fixup supplied */
 
-       off_t off = 0; /* TODO: fixme */
-       r = m_tstools.fixupPTS(off, now);
+       r = m_tstools.fixupPTS(m_source ? m_source->offset() : 0, now);
        if (r)
        {
                eDebug("fixup PTS failed");