add new after record timer event behavior "auto".. and use it as default
[enigma2.git] / lib / dvb / dvb.cpp
index f163230e3b8bf12b479276f4cfd75259a12d2cf7..eac4554d1216bc0f5e35704b545a43134c010915 100644 (file)
@@ -4,6 +4,7 @@
 #include <lib/dvb/dvb.h>
 #include <lib/dvb/pmt.h>
 #include <lib/dvb/sec.h>
+#include <lib/dvb/specs.h>
 
 #include <errno.h>
 #include <sys/types.h>
@@ -61,7 +62,7 @@ ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
 }
 
 eDVBResourceManager::eDVBResourceManager()
-       :m_releaseCachedChannelTimer(eApp)
+       :m_releaseCachedChannelTimer(eTimer::create(eApp))
 {
        avail = 1;
        busy = 0;
@@ -86,7 +87,7 @@ eDVBResourceManager::eDVBResourceManager()
 
        eDVBCAService::registerChannelCallback(this);
 
-       CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
+       CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
 }
 
 void eDVBResourceManager::feStateChanged()
@@ -541,7 +542,7 @@ RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUse
                }
                m_cached_channel_state_changed_conn.disconnect();
                m_cached_channel=0;
-               m_releaseCachedChannelTimer.stop();
+               m_releaseCachedChannelTimer->stop();
        }
 
        eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
@@ -580,8 +581,7 @@ RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUse
                return err;
 
        RESULT res;
-       ePtr<eDVBChannel> ch;
-       ch = new eDVBChannel(this, fe);
+       ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
 
        res = ch->setChannel(channelid, feparm);
        if (res)
@@ -612,13 +612,13 @@ void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
                case iDVBChannel::state_ok:
                {
                        eDebug("stop release channel timer");
-                       m_releaseCachedChannelTimer.stop();
+                       m_releaseCachedChannelTimer->stop();
                        break;
                }
                case iDVBChannel::state_last_instance:
                {
                        eDebug("start release channel timer");
-                       m_releaseCachedChannelTimer.start(3000, true);
+                       m_releaseCachedChannelTimer->start(3000, true);
                        break;
                }
                default: // ignore all other events
@@ -640,17 +640,14 @@ RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, in
        {
                m_cached_channel_state_changed_conn.disconnect();
                m_cached_channel=0;
-               m_releaseCachedChannelTimer.stop();
+               m_releaseCachedChannelTimer->stop();
        }
 
        int err = allocateFrontendByIndex(fe, slot_index);
        if (err)
                return err;
 
-       eDVBChannel *ch;
-       ch = new eDVBChannel(this, fe);
-
-       channel = ch;
+       channel = new eDVBChannel(this, fe);
        return 0;
 }
 
@@ -659,17 +656,14 @@ RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
 {
        ePtr<eDVBAllocatedDemux> demux;
 
-       if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
+       if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
        {
                m_cached_channel_state_changed_conn.disconnect();
                m_cached_channel=0;
-               m_releaseCachedChannelTimer.stop();
+               m_releaseCachedChannelTimer->stop();
        }
 
-       eDVBChannel *ch;
-       ch = new eDVBChannel(this, 0);
-
-       channel = ch;
+       channel = new eDVBChannel(this, 0);
        return 0;
 }
 
@@ -720,12 +714,13 @@ RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &
        return 0;
 }
 
-int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
+int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
 {
+       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
        ePtr<eDVBRegisteredFrontend> best;
        int bestval = 0;
 
-       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
+       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
                if (!i->m_inuse)
                {
                        int c = i->m_frontend->isCompatibleWith(feparm);
@@ -762,10 +757,11 @@ int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBCha
        return 0;
 }
 
-int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
+int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, bool simulate)
 {
+       std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
        int ret=0;
-       if (m_cached_channel)
+       if (!simulate && m_cached_channel)
        {
                eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
                if(channelid==cache_chan->getChannelID())
@@ -774,7 +770,7 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
 
                /* first, check if a channel is already existing. */
 //     eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
-       for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
+       for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
        {
 //             eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
                if (i->m_channel_id == channelid)
@@ -787,8 +783,9 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
        int *decremented_cached_channel_fe_usecount=NULL,
                *decremented_fe_usecount=NULL;
 
-       for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
+       for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
        {
+               eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
 //             eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
                if (i->m_channel_id == ignore)
                {
@@ -802,7 +799,7 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
                                ePtr<iDVBFrontend> fe;
                                if (!i->m_channel->getFrontend(fe))
                                {
-                                       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
+                                       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
                                        {
                                                if ( &(*fe) == &(*ii->m_frontend) )
                                                {
@@ -829,7 +826,8 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
                                ePtr<iDVBFrontend> fe;
                                if (!channel->getFrontend(fe))
                                {
-                                       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
+                                       eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
+                                       for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
                                        {
                                                if ( &(*fe) == &(*ii->m_frontend) )
                                                {
@@ -859,7 +857,7 @@ int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, cons
                goto error;
        }
 
-       ret = canAllocateFrontend(feparm);
+       ret = canAllocateFrontend(feparm, simulate);
 
 error:
        if (decremented_fe_usecount)
@@ -985,7 +983,7 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s
 //     eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
 
        unsigned char *d = data;
-       while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
+       while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
        {
                int offset = d - data;
                int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
@@ -1502,6 +1500,61 @@ RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
        return -1;
 }
 
+void eDVBChannel::SDTready(int result)
+{
+       ePyObject args = PyTuple_New(2), ret;
+       bool ok=false;
+       if (!result)
+       {
+               for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
+               {
+                       ok = true;
+                       PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
+                       PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
+                       break;
+               }
+       }
+       if (!ok)
+       {
+               PyTuple_SET_ITEM(args, 0, Py_None);
+               PyTuple_SET_ITEM(args, 1, Py_None);
+               Py_INCREF(Py_None);
+               Py_INCREF(Py_None);
+       }
+       ret = PyObject_CallObject(m_tsid_onid_callback, args);
+       if (ret)
+               Py_DECREF(ret);
+       Py_DECREF(args);
+       Py_DECREF(m_tsid_onid_callback);
+       m_tsid_onid_callback = ePyObject();
+       m_tsid_onid_demux = 0;
+       m_SDT = 0;
+}
+
+RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
+{
+       if (PyCallable_Check(callback))
+       {
+               if (!getDemux(m_tsid_onid_demux, 0))
+               {
+                       m_SDT = new eTable<ServiceDescriptionSection>;
+                       CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
+                       if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
+                       {
+                               m_tsid_onid_demux = 0;
+                               m_SDT = 0;
+                       }
+                       else
+                       {
+                               Py_INCREF(callback);
+                               m_tsid_onid_callback = callback;
+                               return 0;
+                       }
+               }
+       }
+       return -1;
+}
+
 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
 {
        ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;