store a .eit file for each recoring this holds raw eit event informations
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Sat, 25 Feb 2006 01:35:04 +0000 (01:35 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Sat, 25 Feb 2006 01:35:04 +0000 (01:35 +0000)
including audio track informations, event description, event title......
for information about the file format look in EN300468 (www.etsi.org)
make info button useable when playbacking a movie

RecordTimer.py
lib/dvb/eit.cpp
lib/dvb/eit.h
lib/python/Screens/EventView.py
lib/python/Screens/InfoBar.py
lib/python/Screens/InfoBarGenerics.py
lib/service/iservice.h
lib/service/servicedvb.cpp
lib/service/servicedvbrecord.cpp
lib/service/servicedvbrecord.h

index 9bb1da7..cf4160c 100644 (file)
@@ -86,7 +86,10 @@ class RecordTimerEntry(timer.TimerEntry):
                        self.log(1, "'record service' failed")
                        return False
                else:
-                       prep_res = self.record_service.prepare(self.Filename + ".ts")
+                       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
index 9f3169f..fa776b9 100644 (file)
@@ -32,6 +32,15 @@ void eDVBServiceEITHandler::EITready(int error)
        m_eit_changed();
 }
 
+void eDVBServiceEITHandler::inject(ePtr<eServiceEvent> &event, int nownext)
+{
+       if (nownext)
+               m_event_next = event;
+       else
+               m_event_now = event;
+       m_eit_changed();
+}
+
 eDVBServiceEITHandler::eDVBServiceEITHandler()
 {
        CONNECT(m_EIT.tableReady, eDVBServiceEITHandler::EITready);
index bc52e14..2c065ab 100644 (file)
@@ -17,7 +17,8 @@ class eDVBServiceEITHandler: public Object
        ePtr<eServiceEvent> m_event_now, m_event_next;
 public:
        eDVBServiceEITHandler();
-       
+
+       void inject(ePtr<eServiceEvent> &event, int nownext);
        void start(iDVBDemux *demux, int sid);
        void startOther(iDVBDemux *demux, int sid);
        
index ba4ea57..01695df 100644 (file)
@@ -12,13 +12,17 @@ class EventViewBase:
        def __init__(self, Event, Ref, callback=None):
                self.cbFunc = callback
                self.currentService=Ref
+               self.isRecording = len(Ref.ref.getPath())
                self.event = Event
                self["epg_description"] = ScrollLabel()
                self["datetime"] = Label()
                self["channel"] = Label()
                self["duration"] = Label()
                self["key_red"] = Button("")
-               self["key_green"] = Button(_("Add timer"))
+               if self.isRecording:
+                       self["key_green"] = Button("")
+               else:
+                       self["key_green"] = Button(_("Add timer"))
                self["key_yellow"] = Button("")
                self["key_blue"] = Button("")
                self["actions"] = ActionMap(["OkCancelActions", "EventViewActions"],
@@ -46,8 +50,9 @@ class EventViewBase:
                        self.cbFunc(self.setEvent, self.setService, +1)
 
        def timerAdd(self):
-               newEntry = RecordTimerEntry(self.currentService, *parseEvent(self.event))
-               self.session.openWithCallback(self.timerEditFinished, TimerEntry, newEntry)
+               if not self.isRecording:
+                       newEntry = RecordTimerEntry(self.currentService, *parseEvent(self.event))
+                       self.session.openWithCallback(self.timerEditFinished, TimerEntry, newEntry)
 
        def timerEditFinished(self, answer):
                if (answer[0]):
@@ -57,11 +62,14 @@ class EventViewBase:
 
        def setService(self, service):
                self.currentService=service
-               name = self.currentService.getServiceName()
-               if name is not None:
-                       self["channel"].setText(name)
+               if self.isRecording:
+                       self["channel"].setText(_("Recording"))
                else:
-                       self["channel"].setText(_("unknown service"))
+                       name = self.currentService.getServiceName()
+                       if name is not None:
+                               self["channel"].setText(name)
+                       else:
+                               self["channel"].setText(_("unknown service"))
 
        def setEvent(self, event):
                self.event = event
index 66996c6..cfc3529 100644 (file)
@@ -16,7 +16,7 @@ from Screens.InfoBarGenerics import InfoBarShowHide, \
        InfoBarEPG, InfoBarEvent, InfoBarServiceName, InfoBarSeek, InfoBarInstantRecord, \
        InfoBarAudioSelection, InfoBarAdditionalInfo, InfoBarNotifications, InfoBarDish, \
        InfoBarSubserviceSelection, InfoBarTuner, InfoBarShowMovies, InfoBarTimeshift,  \
-       InfoBarServiceNotifications, InfoBarPVRState, InfoBarCueSheetSupport
+       InfoBarServiceNotifications, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarSimpleEventView
 
 from Screens.HelpMenu import HelpableScreen, HelpMenu
 
@@ -66,7 +66,7 @@ class InfoBar(Screen, InfoBarShowHide, InfoBarPowerKey,
 class MoviePlayer(Screen, InfoBarShowHide, InfoBarPowerKey, \
                InfoBarMenu, \
                InfoBarServiceName, InfoBarSeek, InfoBarShowMovies, InfoBarAudioSelection, HelpableScreen, InfoBarNotifications,
-               InfoBarServiceNotifications, InfoBarPVRState, InfoBarCueSheetSupport):
+               InfoBarServiceNotifications, InfoBarPVRState, InfoBarCueSheetSupport, InfoBarSimpleEventView):
                
        def __init__(self, session, service):
                Screen.__init__(self, session)
@@ -78,7 +78,7 @@ class MoviePlayer(Screen, InfoBarShowHide, InfoBarPowerKey, \
                
                for x in HelpableScreen, InfoBarShowHide, InfoBarPowerKey, InfoBarMenu, \
                                InfoBarServiceName, InfoBarSeek, InfoBarShowMovies, \
-                               InfoBarAudioSelection, InfoBarNotifications, \
+                               InfoBarAudioSelection, InfoBarNotifications, InfoBarSimpleEventView, \
                                InfoBarServiceNotifications, InfoBarPVRState, InfoBarCueSheetSupport:
                        x.__init__(self)
 
index 308dcf1..195f6d0 100644 (file)
@@ -18,7 +18,7 @@ from EpgSelection import EPGSelection
 from Screens.MessageBox import MessageBox
 from Screens.Dish import Dish
 from Screens.Standby import Standby
-from Screens.EventView import EventViewEPGSelect
+from Screens.EventView import EventViewEPGSelect, EventViewSimple
 from Screens.MinuteInput import MinuteInput
 from Components.Harddisk import harddiskmanager
 
@@ -326,6 +326,35 @@ class InfoBarMenu:
                assert menu.tagName == "menu", "root element in menu must be 'menu'!"
                self.session.open(MainMenu, menu, menu.childNodes)
 
+class InfoBarSimpleEventView:
+       """ Opens the Eventview for now/next """
+       def __init__(self):
+               self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
+                       {
+                               "showEventInfo": (self.openEventView, _("show event details")),
+                       })
+
+       def openEventView(self):
+               self.epglist = [ ]
+               service = self.session.nav.getCurrentService()
+               ref = self.session.nav.getCurrentlyPlayingServiceReference()
+               info = service.info()
+               ptr=info.getEvent(0)
+               if ptr:
+                       self.epglist.append(ptr)
+               ptr=info.getEvent(1)
+               if ptr:
+                       self.epglist.append(ptr)
+               if len(self.epglist) > 0:
+                       self.session.open(EventViewSimple, self.epglist[0], ServiceReference(ref), self.eventViewCallback)
+
+       def eventViewCallback(self, setEvent, setService, val): #used for now/next displaying
+               if len(self.epglist) > 1:
+                       tmp = self.epglist[0]
+                       self.epglist[0]=self.epglist[1]
+                       self.epglist[1]=tmp
+                       setEvent(self.epglist[0])
+
 class InfoBarEPG:
        """ EPG - Opens an EPG list when the showEPGList action fires """
        def __init__(self):
@@ -959,17 +988,19 @@ class InfoBarInstantRecord:
                event = None
                try:
                        service = self.session.nav.getCurrentService()
-                       info = service.info()
-                       ev = info.getEvent(0)
-                       event = ev
+                       epg = eEPGCache.getInstance()
+                       event = epg.lookupEventTime(serviceref, -1, 0)
+                       if event is None:
+                               info = service.info()
+                               ev = info.getEvent(0)
+                               event = ev
                except:
                        pass
-               
+
                if event is not None:
                        data = parseEvent(event)
                        begin = time.time()
                        end = begin + 3600 * 10
-                       
                        data = (begin, end, data[2], data[3], data[4])
                else:
                        data = (time.time(), time.time() + 3600 * 10, "instant record", "", None)
index bc0fc97..436d355 100644 (file)
@@ -444,7 +444,7 @@ class iRecordableService: public iObject
        ~iRecordableService();
 #endif
 public:
-       virtual RESULT prepare(const char *filename)=0;
+       virtual RESULT prepare(const char *filename, time_t begTime=-1, time_t endTime=-1, int eit_event_id=-1)=0;
        virtual RESULT start()=0;
        virtual RESULT stop()=0;
 };
index 3d55101..f9bb877 100644 (file)
@@ -11,6 +11,7 @@
 #include <lib/dvb/decoder.h>
 
 #include <lib/service/servicedvbrecord.h>
+#include <lib/service/event.h>
 #include <lib/dvb/metaparser.h>
 #include <lib/dvb/tstools.h>
 #include <lib/python/python.h>
@@ -20,6 +21,8 @@
 #include <byteswap.h>
 #include <netinet/in.h>
 
+#include <dvbsi++/event_information_section.h>
+
 #ifndef BYTE_ORDER
 #error no byte order defined!
 #endif
@@ -248,6 +251,7 @@ RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string
        res.push_back(m_ref.path + ".meta");
        res.push_back(m_ref.path + ".ap");
        res.push_back(m_ref.path + ".cuts");
+       res.push_back(m_ref.path + ".eit");
        return 0;
 }
 
@@ -645,7 +649,31 @@ RESULT eDVBServicePlay::start()
                   to start recording from the data demux. */
        m_cue = new eCueSheet();
        m_first_program_info = 1;
-       r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr, m_cue);
+       eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
+       r = m_service_handler.tune(service, m_is_pvr, m_cue);
+       if (m_is_pvr)
+       {
+               std::string filename = service.path;
+               filename.erase(filename.length()-2, 2);
+               filename+="eit";
+               int fd = ::open( filename.c_str(), O_RDONLY );
+               if ( fd > -1 )
+               {
+                       __u8 buf[4096];
+                       int rd = ::read(fd, buf, 4096);
+                       ::close(fd);
+                       if ( rd > 12 /*EIT_LOOP_SIZE*/ )
+                       {
+                               Event ev(buf);
+                               ePtr<eServiceEvent> event = new eServiceEvent;
+                               ePtr<eServiceEvent> empty;
+                               event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
+                               m_event_handler.inject(event, 0);
+                               m_event_handler.inject(empty, 1);
+                               eDebug("injected");
+                       }
+               }
+       }
        m_event(this, evStart);
        m_event((iPlayableService*)this, evSeekableStatusChanged);
        return 0;
index bded7cc..a035935 100644 (file)
@@ -1,5 +1,6 @@
 #include <lib/service/servicedvbrecord.h>
 #include <lib/base/eerror.h>
+#include <lib/dvb/epgcache.h>
 
 #include <fcntl.h>
 
@@ -37,11 +38,54 @@ void eDVBServiceRecord::serviceEvent(int event)
        }
 }
 
-RESULT eDVBServiceRecord::prepare(const char *filename)
+RESULT eDVBServiceRecord::prepare(const char *filename, time_t begTime, time_t endTime, int eit_event_id)
 {
        m_filename = filename;
        if (m_state == stateIdle)
-               return doPrepare();
+       {
+               int ret = doPrepare();
+               if (!ret)
+               {
+                       eEPGCache::getInstance()->Lock();
+                       const eit_event_struct *event = 0;
+                       if ( eit_event_id != -1 )
+                       {
+                               eDebug("query epg event id %d", eit_event_id);
+                               eEPGCache::getInstance()->lookupEventId(m_ref, eit_event_id, event);
+                       }
+                       if ( !event && (begTime != -1 && endTime != -1) )
+                       {
+                               time_t queryTime = begTime + ((endTime-begTime)/2);
+                               tm beg, end, query;
+                               localtime_r(&begTime, &beg);
+                               localtime_r(&endTime, &end);
+                               localtime_r(&queryTime, &query);
+                               eDebug("query stime %d:%d:%d, etime %d:%d:%d, qtime %d:%d:%d",
+                                       beg.tm_hour, beg.tm_min, beg.tm_sec,
+                                       end.tm_hour, end.tm_min, end.tm_sec,
+                                       query.tm_hour, query.tm_min, query.tm_sec);
+                               eEPGCache::getInstance()->lookupEventTime(m_ref, queryTime, event);
+                       }
+                       if ( event )
+                       {
+                               eDebug("found event.. store to disc");
+                               std::string fname = filename;
+                               fname.erase(fname.length()-2, 2);
+                               fname+="eit";
+                               int fd = open(fname.c_str(), O_CREAT|O_WRONLY, 0777);
+                               if (fd>-1)
+                               {
+                                       int evLen=HILO(event->descriptors_loop_length)+12/*EIT_LOOP_SIZE*/;
+                                       int wr = ::write( fd, (unsigned char*)event, evLen );
+                                       if ( wr != evLen )
+                                               eDebug("eit write error (%m)");
+                                       ::close(fd);
+                               }
+                       }
+                       eEPGCache::getInstance()->Unlock();
+               }
+               return ret;
+       }
        else
                return -1;
 }
index 7f08c55..25ca3e5 100644 (file)
@@ -14,7 +14,7 @@ class eDVBServiceRecord: public iRecordableService, public Object
 {
 DECLARE_REF(eDVBServiceRecord);
 public:
-       RESULT prepare(const char *filename);
+       RESULT prepare(const char *filename, time_t begTime, time_t endTime, int eit_event_id);
        RESULT start();
        RESULT stop();
 private: