more changes for service groups (replacement for zapping alternatives
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Thu, 30 Nov 2006 20:03:35 +0000 (20:03 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Thu, 30 Nov 2006 20:03:35 +0000 (20:03 +0000)
plugin).. now its basicaly working..
TODO: change zapping alternatives editor for new style

Navigation.py
RecordTimer.py
ServiceReference.py
lib/dvb/epgcache.cpp
lib/python/Screens/ChannelSelection.py
lib/python/Screens/EventView.py
lib/python/Screens/InfoBarGenerics.py
lib/python/Screens/PictureInPicture.py
lib/python/Tools/XMLTools.py
lib/service/servicedvb.cpp
lib/service/servicedvb.h

index 53e9ed4..50cdf01 100644 (file)
@@ -43,15 +43,24 @@ class Navigation:
                        x(rec_service, event)
 
        def playService(self, ref, checkParentalControl = True):
                        x(rec_service, event)
 
        def playService(self, ref, checkParentalControl = True):
+               oldref = self.currentlyPlayingServiceReference
                print "playing", ref and ref.toString()
                self.currentlyPlayingServiceReference = None
                self.currentlyPlayingService = None
                if ref is None:
                        self.stopService()
                        return 0
                print "playing", ref and ref.toString()
                self.currentlyPlayingServiceReference = None
                self.currentlyPlayingService = None
                if ref is None:
                        self.stopService()
                        return 0
-               
                if not checkParentalControl or parentalControl.isServicePlayable(ref.toCompareString(), boundFunction(self.playService, checkParentalControl = False)):
                if not checkParentalControl or parentalControl.isServicePlayable(ref.toCompareString(), boundFunction(self.playService, checkParentalControl = False)):
-                       if self.pnav and not self.pnav.playService(ref):
+                       if ref.flags & eServiceReference.isGroup:
+                               if not oldref:
+                                       oldref = eServiceReference()
+                               playref = getBestPlayableServiceReference(ref, oldref)
+                               if not playref or (checkParentalControl and not parentalControl.isServicePlayable(playref.toCompareString(), boundFunction(self.playService, checkParentalControl = False))):
+                                       self.stopService()
+                                       return 0
+                       else:
+                               playref = ref
+                       if self.pnav and not self.pnav.playService(playref):
                                self.currentlyPlayingServiceReference = ref
                                return 0
                else:
                                self.currentlyPlayingServiceReference = ref
                                return 0
                else:
@@ -62,16 +71,17 @@ class Navigation:
                return self.currentlyPlayingServiceReference
        
        def recordService(self, ref):
                return self.currentlyPlayingServiceReference
        
        def recordService(self, ref):
+               service = None
                print "recording service: %s" % (str(ref))
                if isinstance(ref, ServiceReference.ServiceReference):
                        ref = ref.ref
                print "recording service: %s" % (str(ref))
                if isinstance(ref, ServiceReference.ServiceReference):
                        ref = ref.ref
-               service = self.pnav and self.pnav.recordService(ref)
-               
-               if service is None:
-                       print "record returned non-zero"
-                       return None
-               else:
-                       return service
+               if ref:
+                       if ref.flags & eServiceReference.isGroup:
+                               ref = getBestPlayableServiceReference(ref, eServiceReference())
+                       service = ref and self.pnav and self.pnav.recordService(ref)
+                       if service is None:
+                               print "record returned non-zero"
+               return service
 
        def stopRecordService(self, service):
                ret = self.pnav and self.pnav.stopRecordService(service)
 
        def stopRecordService(self, service):
                ret = self.pnav and self.pnav.stopRecordService(service)
index 21ad99d..ab26f24 100644 (file)
@@ -7,7 +7,7 @@ from Components.config import config, ConfigYesNo
 import timer
 import xml.dom.minidom
 
 import timer
 import xml.dom.minidom
 
-from enigma import quitMainloop, eEPGCache
+from enigma import quitMainloop, eEPGCache, getBestPlayableServiceReference, eServiceReference
 
 from Screens.MessageBox import MessageBox
 import NavigationInstance
 
 from Screens.MessageBox import MessageBox
 import NavigationInstance
@@ -106,37 +106,47 @@ class RecordTimerEntry(timer.TimerEntry):
                        return True
                else:
                        self.calculateFilename()
                        return True
                else:
                        self.calculateFilename()
-                       self.record_service = NavigationInstance.instance.recordService(self.service_ref)
-                       if self.record_service == None:
+                       rec_ref = self.service_ref and self.service_ref.ref
+                       if rec_ref and rec_ref.flags & eServiceReference.isGroup:
+                               rec_ref = getBestPlayableServiceReference(rec_ref, eServiceReference())
+                               if not rec_ref:
+                                       self.log(1, "'get best playable service for group... record' failed")
+                                       return False
+                               
+                       self.record_service = rec_ref and NavigationInstance.instance.recordService(rec_ref)
+                       if not self.record_service:
                                self.log(1, "'record service' failed")
                                return False
                                self.log(1, "'record service' failed")
                                return False
-                       else:
-                               event_id = self.eit
-                               if event_id is None:
-                                       event_id = -1
-                               prep_res = self.record_service.prepare(self.Filename + ".ts", self.begin, self.end, event_id )
-                               if prep_res:
-                                       self.log(2, "'prepare' failed: error %d" % prep_res)
-                                       self.record_service = None
-                                       return False
-
-                               if self.repeated:
-                                       epgcache = eEPGCache.getInstance()
-                                       queryTime=self.begin+(self.end-self.begin)/2
-                                       evt = epgcache.lookupEventTime(self.service_ref.ref, queryTime)
-                                       if evt:
-                                               self.description = evt.getShortDescription()
-                               self.log(3, "prepare ok, writing meta information to %s" % self.Filename)
-                               try:
-                                       f = open(self.Filename + ".ts.meta", "w")
-                                       f.write(str(self.service_ref) + "\n")
-                                       f.write(self.name + "\n")
-                                       f.write(self.description + "\n")
-                                       f.write(str(self.begin) + "\n")
-                                       f.close()
-                               except IOError:
-                                       self.log(4, "failed to write meta information")
-                               return True
+                               
+                       event_id = self.eit
+                       if event_id is None:
+                               event_id = -1
+                               
+                       if self.record_service.prepare(self.Filename + ".ts", self.begin, self.end, event_id):
+                               self.log(2, "'prepare' failed: error %d" % prep_res)
+                               self.record_service = None
+                               return False
+                               
+                       if self.repeated:
+                               epgcache = eEPGCache.getInstance()
+                               queryTime=self.begin+(self.end-self.begin)/2
+                               evt = epgcache.lookupEventTime(rec_ref, queryTime)
+                               if evt:
+                                       self.description = evt.getShortDescription()
+                               
+                       self.log(3, "prepare ok, writing meta information to %s" % self.Filename)
+                       try:
+                               f = open(self.Filename + ".ts.meta", "w")
+                               f.write(str(rec_ref) + "\n")
+                               f.write(self.name + "\n")
+                               f.write(self.description + "\n")
+                               f.write(str(self.begin) + "\n")
+                               f.close()
+                       except IOError:
+                               self.log(4, "failed to write meta information")
+                               self.record_service = None
+                               return False
+                       return True
 
        def do_backoff(self):
                if self.backoff == 0:
 
        def do_backoff(self):
                if self.backoff == 0:
@@ -340,7 +350,7 @@ class RecordTimer(timer.Timer):
                        list.append('<timer')
                        list.append(' begin="' + str(int(timer.begin)) + '"')
                        list.append(' end="' + str(int(timer.end)) + '"')
                        list.append('<timer')
                        list.append(' begin="' + str(int(timer.begin)) + '"')
                        list.append(' end="' + str(int(timer.end)) + '"')
-                       list.append(' serviceref="' + str(timer.service_ref) + '"')
+                       list.append(' serviceref="' + stringToXML(str(timer.service_ref)) + '"')
                        list.append(' repeated="' + str(int(timer.repeated)) + '"')
                        list.append(' name="' + str(stringToXML(timer.name)) + '"')
                        list.append(' description="' + str(stringToXML(timer.description)) + '"')
                        list.append(' repeated="' + str(int(timer.repeated)) + '"')
                        list.append(' name="' + str(stringToXML(timer.name)) + '"')
                        list.append(' description="' + str(stringToXML(timer.description)) + '"')
index 787c5c4..78f7cc3 100644 (file)
@@ -18,17 +18,5 @@ class ServiceReference(eServiceReference):
                info = self.info()
                return info and info.getName(self.ref) or ""
 
                info = self.info()
                return info and info.getName(self.ref) or ""
 
-       def play(self):
-               return self.serviceHandler.info(self.ref)
-       
-       def record(self):
-               return self.serviceHandler.record(self.ref)
-       
-       def list(self):
-               return self.serviceHandler.list(self.ref)
-       
        def info(self):
                return self.serviceHandler.info(self.ref)
        def info(self):
                return self.serviceHandler.info(self.ref)
-
-       def offlineOperations(self):
-               return self.serviceHandler.offlineOperations(self.ref)
index 6adab39..47da410 100644 (file)
@@ -21,6 +21,30 @@ descriptorMap eventData::descriptors;
 __u8 eventData::data[4108];
 extern const uint32_t crc32_table[256];
 
 __u8 eventData::data[4108];
 extern const uint32_t crc32_table[256];
 
+const eServiceReference &handleGroup(const eServiceReference &ref)
+{
+       if (ref.flags & eServiceReference::isGroup)
+       {
+               ePtr<eDVBResourceManager> res;
+               if (!eDVBResourceManager::getInstance(res))
+               {
+                       ePtr<iDVBChannelList> db;
+                       if (!res->getChannelList(db))
+                       {
+                               eBouquet *bouquet=0;
+                               if (!db->getBouquet(ref, bouquet))
+                               {
+                                       std::list<eServiceReference>::iterator it(bouquet->m_services.begin());
+                                       if (it != bouquet->m_services.end())
+                                               return *it;
+                               }
+                       }
+               }
+       }
+       return ref;
+}
+
+
 eventData::eventData(const eit_event_struct* e, int size, int type)
        :ByteSize(size&0xFF), type(type&0xFF)
 {
 eventData::eventData(const eit_event_struct* e, int size, int type)
        :ByteSize(size&0xFF), type(type&0xFF)
 {
@@ -1317,7 +1341,7 @@ RESULT eEPGCache::lookupEventTime(const eServiceReference &service, time_t t, co
 // if t == -1 we search the current event...
 {
        singleLock s(cache_lock);
 // if t == -1 we search the current event...
 {
        singleLock s(cache_lock);
-       uniqueEPGKey key(service);
+       uniqueEPGKey key(handleGroup(service));
 
        // check if EPG for this service is ready...
        eventCache::iterator It = eventDB.find( key );
 
        // check if EPG for this service is ready...
        eventCache::iterator It = eventDB.find( key );
@@ -1393,7 +1417,7 @@ RESULT eEPGCache::lookupEventTime(const eServiceReference &service, time_t t, eP
 RESULT eEPGCache::lookupEventId(const eServiceReference &service, int event_id, const eventData *&result )
 {
        singleLock s(cache_lock);
 RESULT eEPGCache::lookupEventId(const eServiceReference &service, int event_id, const eventData *&result )
 {
        singleLock s(cache_lock);
-       uniqueEPGKey key( service );
+       uniqueEPGKey key(handleGroup(service));
 
        eventCache::iterator It = eventDB.find( key );
        if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached?
 
        eventCache::iterator It = eventDB.find( key );
        if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached?
@@ -1450,7 +1474,7 @@ RESULT eEPGCache::lookupEventId(const eServiceReference &service, int event_id,
 
 RESULT eEPGCache::startTimeQuery(const eServiceReference &service, time_t begin, int minutes)
 {
 
 RESULT eEPGCache::startTimeQuery(const eServiceReference &service, time_t begin, int minutes)
 {
-       eventCache::iterator It = eventDB.find( service );
+       eventCache::iterator It = eventDB.find(handleGroup(service));
        if ( It != eventDB.end() && It->second.second.size() )
        {
                m_timemap_end = minutes != -1 ? It->second.second.upper_bound(begin+minutes*60) : It->second.second.end();
        if ( It != eventDB.end() && It->second.second.size() )
        {
                m_timemap_end = minutes != -1 ? It->second.second.upper_bound(begin+minutes*60) : It->second.second.end();
@@ -1474,7 +1498,7 @@ RESULT eEPGCache::startTimeQuery(const eServiceReference &service, time_t begin,
                }
                else
                        m_timemap_cursor = It->second.second.begin();
                }
                else
                        m_timemap_cursor = It->second.second.begin();
-               const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)service;
+               const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)handleGroup(service);
                currentQueryTsidOnid = (ref.getTransportStreamID().get()<<16) | ref.getOriginalNetworkID().get();
                return 0;
        }
                currentQueryTsidOnid = (ref.getTransportStreamID().get()<<16) | ref.getOriginalNetworkID().get();
                return 0;
        }
@@ -1732,7 +1756,7 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc)
                                                break;
                                }
                        }
                                                break;
                                }
                        }
-                       eServiceReference ref(PyString_AS_STRING(service));
+                       eServiceReference ref(handleGroup(eServiceReference(PyString_AS_STRING(service))));
                        if (ref.type != eServiceReference::idDVB)
                        {
                                eDebug("service reference for epg query is not valid");
                        if (ref.type != eServiceReference::idDVB)
                        {
                                eDebug("service reference for epg query is not valid");
@@ -2110,7 +2134,7 @@ PyObject *eEPGCache::search(ePyObject arg)
        if (descridx > -1)
        {
                int maxcount=maxmatches;
        if (descridx > -1)
        {
                int maxcount=maxmatches;
-               eServiceReferenceDVB ref(refstr?refstr:"");
+               eServiceReferenceDVB ref(refstr?(const eServiceReferenceDVB&)handleGroup(eServiceReference(refstr)):eServiceReferenceDVB(""));
                // ref is only valid in SIMILAR_BROADCASTING_SEARCH
                // in this case we start searching with the base service
                bool first = ref.valid() ? true : false;
                // ref is only valid in SIMILAR_BROADCASTING_SEARCH
                // in this case we start searching with the base service
                bool first = ref.valid() ? true : false;
index 8d728f0..6a5605c 100644 (file)
@@ -1043,7 +1043,7 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                if ref is None or ref != nref:
                        self.session.nav.playService(nref)
                        self.saveRoot()
                if ref is None or ref != nref:
                        self.session.nav.playService(nref)
                        self.saveRoot()
-                       self.saveChannel()
+                       self.saveChannel(nref)
                        config.servicelist.lastmode.save()
                        self.addToHistory(nref)
 
                        config.servicelist.lastmode.save()
                        self.addToHistory(nref)
 
@@ -1086,7 +1086,7 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                        self.setRoot(root)
                self.session.nav.playService(ref)
                self.setCurrentSelection(ref)
                        self.setRoot(root)
                self.session.nav.playService(ref)
                self.setCurrentSelection(ref)
-               self.saveChannel()
+               self.saveChannel(ref)
 
        def saveRoot(self):
                path = ''
 
        def saveRoot(self):
                path = ''
@@ -1123,8 +1123,7 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                                return True
                return False
 
                                return True
                return False
 
-       def saveChannel(self):
-               ref = self.session.nav.getCurrentlyPlayingServiceReference()
+       def saveChannel(self, ref):
                if ref is not None:
                        refstr = ref.toString()
                else:
                if ref is not None:
                        refstr = ref.toString()
                else:
index 8a684ea..82bca9f 100644 (file)
@@ -3,7 +3,7 @@ from Components.ActionMap import ActionMap
 from Components.Button import Button
 from Components.Label import Label
 from Components.ScrollLabel import ScrollLabel
 from Components.Button import Button
 from Components.Label import Label
 from Components.ScrollLabel import ScrollLabel
-from enigma import eServiceEventPtr, eEPGCache, eTimer
+from enigma import eServiceEventPtr, eEPGCache, eTimer, eServiceReference
 from ServiceReference import ServiceReference
 from RecordTimer import RecordTimerEntry, parseEvent
 from TimerEntry import TimerEntry
 from ServiceReference import ServiceReference
 from RecordTimer import RecordTimerEntry, parseEvent
 from TimerEntry import TimerEntry
@@ -14,7 +14,7 @@ class EventViewBase:
                self.similarEPGCB = similarEPGCB
                self.cbFunc = callback
                self.currentService=Ref
                self.similarEPGCB = similarEPGCB
                self.cbFunc = callback
                self.currentService=Ref
-               self.isRecording = len(Ref.ref.getPath())
+               self.isRecording = (not Ref.ref.flags & eServiceReference.isGroup) and len(Ref.ref.getPath())
                self.event = Event
                self["epg_description"] = ScrollLabel()
                self["datetime"] = Label()
                self.event = Event
                self["epg_description"] = ScrollLabel()
                self["datetime"] = Label()
index 3ec37c6..ed8149e 100644 (file)
@@ -425,7 +425,7 @@ class InfoBarEPG:
                                service = servicelist.getNext()
                                if not service.valid(): #check if end of list
                                        break
                                service = servicelist.getNext()
                                if not service.valid(): #check if end of list
                                        break
-                               if service.flags: #ignore non playable services
+                               if service.flags & (eServiceReference.isDirectory | eServiceReference.isMarker): #ignore non playable services
                                        continue
                                services.append(ServiceReference(service))
                return services
                                        continue
                                services.append(ServiceReference(service))
                return services
index 5c49683..bd340d8 100644 (file)
@@ -1,5 +1,5 @@
 from Screens.Screen import Screen
 from Screens.Screen import Screen
-from enigma import ePoint, eSize, eServiceCenter
+from enigma import ePoint, eSize, eServiceCenter, getBestPlayableServiceReference, eServiceReference
 from Components.VideoWindow import VideoWindow
 from Components.config import config, ConfigPosition
 
 from Components.VideoWindow import VideoWindow
 from Components.config import config, ConfigPosition
 
@@ -46,14 +46,19 @@ class PictureInPicture(Screen):
                return (self.instance.size().width(), self.instance.size().height())
                
        def playService(self, service):
                return (self.instance.size().width(), self.instance.size().height())
                
        def playService(self, service):
-               self.pipservice = eServiceCenter.getInstance().play(service)
-               if self.pipservice and not self.pipservice.setTarget(1):
-                       self.pipservice.start()
-                       self.currentService = service
-                       return True
+               if service and (service.flags & eServiceReference.isGroup):
+                       ref = getBestPlayableServiceReference(service, eServiceReference())
                else:
                else:
-                       self.pipservice = None
-                       return False
+                       ref = service
+               if ref:
+                       self.pipservice = eServiceCenter.getInstance().play(ref)
+                       if self.pipservice and not self.pipservice.setTarget(1):
+                               self.pipservice.start()
+                               self.currentService = service
+                               return True
+                       else:
+                               self.pipservice = None
+               return False
                
        def getCurrentService(self):
                return self.currentService
                
        def getCurrentService(self):
                return self.currentService
index e248c80..72b9038 100644 (file)
@@ -24,4 +24,4 @@ def mergeText(nodelist):
        return rc
 
 def stringToXML(text):
        return rc
 
 def stringToXML(text):
-               return text.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace("'", '&apos;').replace('"', '&quot;')
+       return text.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace("'", '&apos;').replace('"', '&quot;')
index 7f17fc8..0a7a671 100644 (file)
@@ -192,6 +192,13 @@ int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
        return -1;
 }
 
        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);
 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
 {
        DECLARE_REF(eStaticServiceDVBPVRInformation);
index e12e3e1..b3978a4 100644 (file)
@@ -277,6 +277,7 @@ public:
        RESULT getName(const eServiceReference &ref, std::string &name);
        int getLength(const eServiceReference &ref);
        int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
        RESULT getName(const eServiceReference &ref, std::string &name);
        int getLength(const eServiceReference &ref);
        int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
+       RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time);
 };
 
 #endif
 };
 
 #endif