more changes for service groups (replacement for zapping alternatives
[enigma2.git] / lib / service / servicedvb.cpp
index e6a2143..0a7a671 100644 (file)
@@ -39,6 +39,7 @@ class eStaticServiceDVBInformation: public iStaticServiceInformation
 public:
        RESULT getName(const eServiceReference &ref, std::string &name);
        int getLength(const eServiceReference &ref);
+       int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
 };
 
 DEFINE_REF(eStaticServiceDVBInformation);
@@ -90,13 +91,20 @@ int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
        return -1;
 }
 
-class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
+int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
 {
-       DECLARE_REF(eStaticServiceDVBBouquetInformation);
-public:
-       RESULT getName(const eServiceReference &ref, std::string &name);
-       int getLength(const eServiceReference &ref);
-};
+       ePtr<eDVBResourceManager> res_mgr;
+       if ( eDVBResourceManager::getInstance( res_mgr ) )
+               eDebug("isPlayble... no res manager!!");
+       else
+       {
+               eDVBChannelID chid, chid_ignore;
+               ((const eServiceReferenceDVB&)ref).getChannelID(chid);
+               ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
+               return res_mgr->canAllocateChannel(chid, chid_ignore);
+       }
+       return false;
+}
 
 DEFINE_REF(eStaticServiceDVBBouquetInformation);
 
@@ -133,11 +141,64 @@ RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref
                return -1;
 }
 
+int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
+{
+       if (ref.flags & eServiceReference::isGroup)
+       {
+               ePtr<iDVBChannelList> db;
+               ePtr<eDVBResourceManager> res;
+
+               if (eDVBResourceManager::getInstance(res))
+               {
+                       eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
+                       return 0;
+               }
+
+               if (res->getChannelList(db))
+               {
+                       eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
+                       return 0;
+               }
+
+               eBouquet *bouquet=0;
+               if (db->getBouquet(ref, bouquet))
+               {
+                       eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
+                       return 0;
+               }
+
+               int cur=0;
+               eDVBChannelID chid, chid_ignore;
+               ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
+               for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
+               {
+                       ((const eServiceReferenceDVB&)*it).getChannelID(chid);
+                       int tmp=res->canAllocateChannel(chid, chid_ignore);
+                       if (tmp > cur)
+                       {
+                               m_playable_service = *it;
+                               cur = tmp;
+                       }
+               }
+               if (cur)
+                       return cur;
+       }
+       m_playable_service = eServiceReference();
+       return 0;
+}
+
 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
 {
        return -1;
 }
 
+#include <lib/dvb/epgcache.h>
+
+RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
+{
+       return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
+}
+
 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
 {
        DECLARE_REF(eStaticServiceDVBPVRInformation);
@@ -148,7 +209,7 @@ public:
        RESULT getName(const eServiceReference &ref, std::string &name);
        int getLength(const eServiceReference &ref);
        RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
-
+       int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
        int getInfo(const eServiceReference &ref, int w);
        std::string getInfoString(const eServiceReference &ref,int w);
 };
@@ -382,7 +443,7 @@ RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sort
        
        if (!m_query)
                return -1;
-       
+
        while (!m_query->getNextResult(ref))
                list.push_back(ref);
 
@@ -406,7 +467,7 @@ RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sort
 //   unknown format string chars are returned as python None values !
 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
 {
-       PyObject *ret=0;
+       ePyObject ret;
        std::list<eServiceReference> tmplist;
        int retcount=1;
 
@@ -428,14 +489,14 @@ PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
                for (int cnt=0; cnt < services; ++cnt)
                {
                        eServiceReference &ref=*it++;
-                       PyObject *tuple = retcount > 1 ? PyTuple_New(retcount) : 0;
+                       ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
                        for (int i=0; i < retcount; ++i)
                        {
-                               PyObject *tmp=0;
+                               ePyObject tmp;
                                switch(format[i])
                                {
                                case 'R':  // service reference (swig)object
-                                       tmp = New_eServiceReference(ref);
+                                       tmp = NEW_eServiceReference(ref);
                                        break;
                                case 'C':  // service reference compare string
                                        tmp = PyString_FromString(ref.toCompareString().c_str());
@@ -478,7 +539,7 @@ PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
                                PyList_SET_ITEM(ret, cnt, tuple);
                }
        }
-       return ret ? ret : PyList_New(0);
+       return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
 }
 
 RESULT eDVBServiceList::getNext(eServiceReference &ref)
@@ -489,14 +550,9 @@ RESULT eDVBServiceList::getNext(eServiceReference &ref)
        return m_query->getNextResult((eServiceReferenceDVB&)ref);
 }
 
-int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
-{
-       return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
-}
-
 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
 {
-       if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
+       if (m_parent.flags & eServiceReference::canDescent) // bouquet
        {
                ePtr<iDVBChannelList> db;
                ePtr<eDVBResourceManager> resm;
@@ -590,7 +646,7 @@ RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableServ
 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
 {
        /* is a listable service? */
-       if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
+       if (ref.flags & eServiceReference::canDescent) // bouquet
        {
                if ( !ref.name.empty() )  // satellites or providers list
                        ptr = m_StaticServiceDVBInfo;
@@ -1216,6 +1272,7 @@ int eDVBServicePlay::getInfo(int w)
        case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
        case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
        case sProvider: if (!m_dvb_service) return -1; return -2;
+       case sServiceref: return resIsString;
        default:
                return -1;
        }
@@ -1228,6 +1285,8 @@ std::string eDVBServicePlay::getInfoString(int w)
        case sProvider:
                if (!m_dvb_service) return "";
                return m_dvb_service->m_provider_name;
+       case sServiceref:
+               return m_reference.toString();
        default:
                break;
        }
@@ -1388,7 +1447,7 @@ int eDVBServiceBase::getFrontendInfo(int w)
 
 PyObject *eDVBServiceBase::getFrontendData(bool original)
 {
-       PyObject *ret=0;
+       ePyObject ret;
 
        eUsePtr<iDVBChannel> channel;
        if(!m_service_handler.getChannel(channel))
@@ -1406,8 +1465,8 @@ PyObject *eDVBServiceBase::getFrontendData(bool original)
                                        eDVBFrontendParametersSatellite osat;
                                        if (!feparm->getDVBS(osat))
                                        {
-                                               void PutToDict(PyObject *, const char*, long);
-                                               void PutToDict(PyObject *, const char*, const char*);
+                                               void PutToDict(ePyObject &, const char*, long);
+                                               void PutToDict(ePyObject &, const char*, const char*);
                                                PutToDict(ret, "orbital_position", osat.orbital_position);
                                                const char *tmp = "UNKNOWN";
                                                switch(osat.polarisation)
@@ -1531,11 +1590,11 @@ RESULT eDVBServicePlay::activateTimeshift()
 
 PyObject *eDVBServicePlay::getCutList()
 {
-       PyObject *list = PyList_New(0);
+       ePyObject list = PyList_New(0);
        
        for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
        {
-               PyObject *tuple = PyTuple_New(2);
+               ePyObject tuple = PyTuple_New(2);
                PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
                PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
                PyList_Append(list, tuple);
@@ -1545,7 +1604,7 @@ PyObject *eDVBServicePlay::getCutList()
        return list;
 }
 
-void eDVBServicePlay::setCutList(PyObject *list)
+void eDVBServicePlay::setCutList(ePyObject list)
 {
        if (!PyList_Check(list))
                return;
@@ -1556,7 +1615,7 @@ void eDVBServicePlay::setCutList(PyObject *list)
        
        for (i=0; i<size; ++i)
        {
-               PyObject *tuple = PyList_GetItem(list, i);
+               ePyObject tuple = PyList_GET_ITEM(list, i);
                if (!PyTuple_Check(tuple))
                {
                        eDebug("non-tuple in cutlist");
@@ -1567,7 +1626,7 @@ void eDVBServicePlay::setCutList(PyObject *list)
                        eDebug("cutlist entries need to be a 2-tuple");
                        continue;
                }
-               PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
+               ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
                if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
                {
                        eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
@@ -1989,12 +2048,12 @@ void eDVBServicePlay::cutlistToCuesheet()
        m_cue->commitSpans();
 }
 
-RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *tuple)
+RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
 {
        if (m_subtitle_widget)
                disableSubtitles(parent);
 
-       PyObject *entry = 0;
+       ePyObject entry;
        int tuplesize = PyTuple_Size(tuple);
        int type = 0;
 
@@ -2013,7 +2072,7 @@ RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *tuple)
 
        if (type == 1)  // teletext subtitles
        {
-               int page, magazine;
+               int page, magazine, pid;
                if (tuplesize < 4)
                        goto error_out;
 
@@ -2023,7 +2082,11 @@ RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *tuple)
                        return -1;
                }
 
-               // PyTuple_GET_ITEM(tuple, 1);  //we dont need pid yet
+               entry = PyTuple_GET_ITEM(tuple, 1);
+               if (!PyInt_Check(entry))
+                       goto error_out;
+               pid = PyInt_AsLong(entry);
+
                entry = PyTuple_GET_ITEM(tuple, 2);
                if (!PyInt_Check(entry))
                        goto error_out;
@@ -2037,6 +2100,8 @@ RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *tuple)
                m_subtitle_widget = new eSubtitleWidget(parent);
                m_subtitle_widget->resize(parent->size()); /* full size */
                m_teletext_parser->setPageAndMagazine(page, magazine);
+               if (m_dvb_service)
+                       m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
        }
        else if (type == 0)
        {
@@ -2067,6 +2132,8 @@ RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *tuple)
                m_subtitle_widget = new eSubtitleWidget(parent);
                m_subtitle_widget->resize(parent->size()); /* full size */
                m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
+               if (m_dvb_service)
+                       m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
        }
        else
                goto error_out;
@@ -2089,12 +2156,43 @@ RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
        }
        if (m_teletext_parser)
        {
-               m_teletext_parser->setPageAndMagazine(0,0);
+               m_teletext_parser->setPageAndMagazine(-1, -1);
                m_subtitle_pages.clear();
        }
+       if (m_dvb_service)
+               m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
        return 0;
 }
 
+PyObject *eDVBServicePlay::getCachedSubtitle()
+{
+       if (m_dvb_service)
+       {
+               int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
+               if (tmp != -1)
+               {
+                       unsigned int data = (unsigned int)tmp;
+                       int pid = (data&0xFFFF0000)>>16;
+                       ePyObject tuple = PyTuple_New(4);
+                       eDVBServicePMTHandler::program program;
+                       eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
+                       if (!h.getProgramInfo(program))
+                       {
+                               if (program.textPid==pid) // teletext
+                                       PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
+                               else
+                                       PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
+                               PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
+                               PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
+                               PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
+                               return tuple;
+                       }
+               }
+       }
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
 PyObject *eDVBServicePlay::getSubtitleList()
 {
        if (!m_teletext_parser)
@@ -2103,7 +2201,7 @@ PyObject *eDVBServicePlay::getSubtitleList()
                return Py_None;
        }
        
-       PyObject *l = PyList_New(0);
+       ePyObject l = PyList_New(0);
        std::set<int> added_ttx_pages;
 
        std::set<eDVBServicePMTHandler::subtitleStream> &subs =
@@ -2127,7 +2225,7 @@ PyObject *eDVBServicePlay::getSubtitleList()
                                        int hash = magazine_number << 8 | page_number;
                                        if (added_ttx_pages.find(hash) == added_ttx_pages.end())
                                        {
-                                               PyObject *tuple = PyTuple_New(5);
+                                               ePyObject tuple = PyTuple_New(5);
                                                PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
                                                PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
                                                PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
@@ -2142,7 +2240,7 @@ PyObject *eDVBServicePlay::getSubtitleList()
                                case 0x10 ... 0x13:
                                case 0x20 ... 0x23: // dvb subtitles
                                {
-                                       PyObject *tuple = PyTuple_New(5);
+                                       ePyObject tuple = PyTuple_New(5);
                                        PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
                                        PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
                                        PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
@@ -2164,7 +2262,7 @@ PyObject *eDVBServicePlay::getSubtitleList()
                int hash = magazine_number << 8 | page_number;
                if (added_ttx_pages.find(hash) == added_ttx_pages.end())
                {
-                       PyObject *tuple = PyTuple_New(5);
+                       ePyObject tuple = PyTuple_New(5);
                        PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
                        PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
                        PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));