use cue sheets for seeking/skipping
[enigma2.git] / lib / service / servicedvb.cpp
index 8be89a6d284f0fa79cd23658daa15c53824e5958..d1cc4ef83bedc2f7a695b0ea303e8ffe80f7a351 100644 (file)
@@ -13,6 +13,7 @@
 #include <lib/service/servicedvbrecord.h>
 #include <lib/dvb/metaparser.h>
 #include <lib/dvb/tstools.h>
+#include <lib/python/python.h>
 
 class eStaticServiceDVBInformation: public iStaticServiceInformation
 {
@@ -305,7 +306,32 @@ RESULT eDVBServiceList::startQuery()
        return 0;
 }
 
-RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list)
+RESULT eDVBServiceList::getContent(PyObject *list, bool sorted)
+{
+       eServiceReferenceDVB ref;
+
+       if (!m_query || !list || !PyList_Check(list))
+               return -1;
+
+       std::list<eServiceReferenceDVB> tmplist;
+
+       while (!m_query->getNextResult(ref))
+               tmplist.push_back(ref);
+
+       if (sorted)
+               tmplist.sort(iListableServiceCompare(this));
+
+       for (std::list<eServiceReferenceDVB>::iterator it(tmplist.begin());
+               it != tmplist.end(); ++it)
+       {
+               PyObject *refobj = New_eServiceReference(*it);
+               PyList_Append(list, refobj);
+               Py_DECREF(refobj);
+       }
+       return 0;
+}
+
+RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
 {
        eServiceReferenceDVB ref;
        
@@ -314,6 +340,10 @@ RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list)
        
        while (!m_query->getNextResult(ref))
                list.push_back(ref);
+
+       if (sorted)
+               list.sort(iListableServiceCompare(this));
+
        return 0;
 }
 
@@ -379,6 +409,13 @@ RESULT eDVBServiceList::flushChanges()
        return m_bouquet->flushChanges();
 }
 
+RESULT eDVBServiceList::setListName(const std::string &name)
+{
+       if (!m_bouquet)
+               return -1;
+       return m_bouquet->setListName(name);
+}
+
 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
 {
        ePtr<eDVBService> service;
@@ -489,6 +526,7 @@ eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *serv
 {
        m_is_pvr = !ref.path.empty();
        m_timeshift_enabled = m_timeshift_active = 0;
+       m_skipmode = 0;
        
        CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
        CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
@@ -553,10 +591,11 @@ void eDVBServicePlay::serviceEvent(int event)
                break;
        }
        case eDVBServicePMTHandler::eventEOF:
-       {
-               m_event((iPlayableService*)this, evEnd);
+               m_event((iPlayableService*)this, evEOF);
+               break;
+       case eDVBServicePMTHandler::eventSOF:
+               m_event((iPlayableService*)this, evSOF);
                break;
-       }
        }
 }
 
@@ -580,13 +619,24 @@ RESULT eDVBServicePlay::start()
                /* in pvr mode, we only want to use one demux. in tv mode, we're using 
                   two (one for decoding, one for data source), as we must be prepared
                   to start recording from the data demux. */
-       r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr);
+       m_cue = new eCueSheet();
+       r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr, m_cue);
        m_event(this, evStart);
+       m_event((iPlayableService*)this, evSeekableStatusChanged);
        return 0;
 }
 
 RESULT eDVBServicePlay::stop()
 {
+       eDebug("stop timeshift");
+       stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
+       
+       eDebug("free ts handler");
+       m_service_handler_timeshift.free();
+       eDebug("stop service handler");
+       m_service_handler.free();
+       eDebug("ok");
+       
        return 0;
 }
 
@@ -598,6 +648,9 @@ RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &ev
 
 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
 {
+               /* note: we check for timeshift to be enabled,
+                  not neccessary active. if you pause when timeshift
+                  is not active, you should activate it when unpausing */
        if ((!m_is_pvr) && (!m_timeshift_enabled))
        {
                ptr = 0;
@@ -618,10 +671,39 @@ RESULT eDVBServicePlay::setSlowMotion(int ratio)
 
 RESULT eDVBServicePlay::setFastForward(int ratio)
 {
-       if (m_decoder)
-               return m_decoder->setFastForward(ratio);
-       else
+       int skipmode, ffratio;
+       
+       if (ratio > 8)
+       {
+               skipmode = ratio;
+               ffratio = 1;
+       } else if (ratio > 0)
+       {
+               skipmode = 0;
+               ffratio = ratio;
+       } else if (!ratio)
+       {
+               skipmode = 0;
+               ffratio = 0;
+       } else if (ratio < 0)
+       {
+               skipmode = ratio;
+               ffratio = 1;
+       }
+
+       if (m_skipmode != skipmode)
+       {
+               eDebug("setting cue skipmode to %d", skipmode);
+               if (m_cue)
+                       m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
+       }
+       
+       m_skipmode = skipmode;
+       
+       if (!m_decoder)
                return -1;
+
+       return m_decoder->setFastForward(ffratio);
 }
     
 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
@@ -681,7 +763,11 @@ RESULT eDVBServicePlay::seekTo(pts_t to)
        if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
                return -1;
        
-       return pvr_channel->seekTo(m_decode_demux, 0, to);
+       if (!m_cue)
+               return -1;
+       
+       m_cue->seekTo(0, to);
+       return 0;
 }
 
 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
@@ -698,7 +784,11 @@ RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
        
        to *= direction;
        
-       return pvr_channel->seekTo(m_decode_demux, 1, to);
+       if (!m_cue)
+               return 0;
+       
+       m_cue->seekTo(1, to);
+       return 0;
 }
 
 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
@@ -1003,7 +1093,7 @@ RESULT eDVBServicePlay::startTimeshift()
        
        if (m_timeshift_fd < 0)
        {
-               delete m_record;
+               m_record = 0;
                return -4;
        }
                
@@ -1027,12 +1117,11 @@ RESULT eDVBServicePlay::stopTimeshift()
        m_timeshift_enabled = 0;
        
        m_record->stop();
-       delete m_record;
+       m_record = 0;
        
        close(m_timeshift_fd);
        remove(m_timeshift_file.c_str());
        
-       eDebug("timeshift disabled");
        return 0;
 }
 
@@ -1105,7 +1194,6 @@ void eDVBServicePlay::updateTimeshiftPids()
 
 void eDVBServicePlay::switchToLive()
 {
-       eDebug("SwitchToLive");
        if (!m_timeshift_active)
                return;
        
@@ -1122,7 +1210,6 @@ void eDVBServicePlay::switchToLive()
 
 void eDVBServicePlay::switchToTimeshift()
 {
-       eDebug("SwitchToTimeshift");
        if (m_timeshift_active)
                return;
        
@@ -1136,8 +1223,7 @@ void eDVBServicePlay::switchToTimeshift()
        eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
        r.path = m_timeshift_file;
        
-       eDebug("ok, re-tuning to %s", r.toString().c_str());
-       m_service_handler_timeshift.tune(r, 1); /* use the decoder demux for everything */
+       m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
 }
 
 void eDVBServicePlay::updateDecoder()
@@ -1196,6 +1282,8 @@ void eDVBServicePlay::updateDecoder()
                h.getDecodeDemux(m_decode_demux);
                if (m_decode_demux)
                        m_decode_demux->getMPEGDecoder(m_decoder);
+               if (m_cue)
+                       m_cue->setDecodingDemux(m_decode_demux);
        }
 
        if (m_decoder)