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 53e9ed426153516466b627d147e2aeadd7fd17b7..50cdf01f3b00e3024dff1efa0f5385ff3150c2f2 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 21ad99d904b4dd226b8a05894fae7f147cf141bf..ab26f24e9149ed543eef197874d4b63020879b5f 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 787c5c4aa0d58fd0d5a6649cb884fc3691688402..78f7cc39140ad3e86e138a0c7697e6f0d1529c49 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 6adab3998e3f1b0ae5679bdbed130ffd10fb0651..47da4101102f1b18c63929a0557587f97789fc3c 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 8d728f0c0b53ae24e18b2a4175333b2ceb199ae5..6a5605c713a1050c9074d2b93c2a55b693c189fa 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 8a684ead9522e41b114d9b14127e2b82d2ee970a..82bca9fddc106088a0b5055755dcdd6390939625 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 3ec37c6474b13a6e069d592ac54b058f76d0f462..ed8149e488879e3d1393edd8ed7ba1816f6d6e43 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 5c49683335535660fc034d7a39576f2174245ada..bd340d8892f51a1c508fa58f44e465e012d0d2ad 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 e248c80ef19aafcfa511abef4285203dace70936..72b90388a4b75a342a25b037f00c49322a6a47a5 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 7f17fc84fbbe25643c6be951823b2436a22b0035..0a7a6715499501d1cfff01d3f8fa68624f5bb70c 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 e12e3e19cdaa1de80f781bb8e08b31d5b2263888..b3978a424763d5cb96e132b95fa1a8f80d1cf205 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