small code cleanup, fix memleaks
[enigma2.git] / lib / service / servicedvb.cpp
index c8e64b807040b3cc43430308a9e2bd4439df14b1..e498dd420933f8780feb42b1189300933eb8b5d3 100644 (file)
@@ -910,7 +910,7 @@ RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServ
        return 0;
 }
 
-eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): 
+eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
        m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
 {
        m_is_primary = 1;
@@ -1021,14 +1021,18 @@ void eDVBServicePlay::serviceEvent(int event)
                        updateTimeshiftPids();
                if (!m_timeshift_active)
                        updateDecoder();
-               if (m_first_program_info && m_is_pvr)
+               if (m_first_program_info & 1 && m_is_pvr)
                {
-                       m_first_program_info = 0;
+                       m_first_program_info &= ~1;
                        seekTo(0);
                }
-               m_event((iPlayableService*)this, evUpdatedInfo);
+               if (!m_timeshift_active)
+                       m_event((iPlayableService*)this, evUpdatedInfo);
                break;
        }
+       case eDVBServicePMTHandler::eventPreStart:
+               loadCuesheet();
+               break;
        case eDVBServicePMTHandler::eventEOF:
                m_event((iPlayableService*)this, evEOF);
                break;
@@ -1043,17 +1047,85 @@ void eDVBServicePlay::serviceEventTimeshift(int event)
        switch (event)
        {
        case eDVBServicePMTHandler::eventNewProgramInfo:
+               eDebug("eventNewProgramInfo TS");
                if (m_timeshift_active)
+               {
                        updateDecoder();
+                       if (m_first_program_info & 2)
+                       {
+                               if (m_slowmotion)
+                               {
+                                       eDebug("re-apply slowmotion after timeshift file change");
+                                       m_decoder->setSlowMotion(m_slowmotion);
+                               }
+                               if (m_fastforward)
+                               {
+                                       eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
+                                       if (m_skipmode)
+                                               m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
+                                       if (m_fastforward != 1)
+                                               m_decoder->setFastForward(m_fastforward);
+                                       else
+                                               m_decoder->setTrickmode();
+                               }
+                               else
+                                       seekTo(0);
+                               m_first_program_info &= ~2;
+                       }
+                       m_event((iPlayableService*)this, evUpdatedInfo);
+               }
                break;
        case eDVBServicePMTHandler::eventSOF:
-               m_event((iPlayableService*)this, evSOF);
+#if 0
+               if (!m_timeshift_file_next.empty())
+               {
+                       eDebug("timeshift SOF, switch to next file");
+                       m_decoder->pause();
+
+                       m_first_program_info |= 2;
+
+                       eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
+                       r.path = m_timeshift_file_next;
+
+                       /* free the timeshift service handler, we need the resources */
+                       m_service_handler_timeshift.free();
+                       resetTimeshift(1);
+
+                       if (m_skipmode < 0)
+                               m_cue->seekTo(0, -1000);
+                       m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
+
+                       m_event((iPlayableService*)this, evUser+1);
+               }
+               else
+#endif
+                       m_event((iPlayableService*)this, evSOF);
                break;
        case eDVBServicePMTHandler::eventEOF:
                if ((!m_is_paused) && (m_skipmode >= 0))
                {
-                       eDebug("timeshift EOF, so let's go live");
-                       switchToLive();
+                       if (m_timeshift_file_next.empty())
+                       {
+                               eDebug("timeshift EOF, so let's go live");
+                               switchToLive();
+                       }
+                       else
+                       {
+                               eDebug("timeshift EOF, switch to next file");
+
+                               m_first_program_info |= 2;
+
+                               eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
+                               r.path = m_timeshift_file_next;
+
+                               /* free the timeshift service handler, we need the resources */
+                               m_service_handler_timeshift.free();
+                               resetTimeshift(1);
+
+                               m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
+
+                               m_event((iPlayableService*)this, evUser+1);
+                       }
                }
                break;
        }
@@ -1095,7 +1167,6 @@ RESULT eDVBServicePlay::start()
                        m_event_handler.inject(event, 0);
                        m_event_handler.inject(empty, 1);
                }
-               loadCuesheet();
                m_event(this, evStart);
        }
        return 0;
@@ -1126,11 +1197,7 @@ RESULT eDVBServicePlay::stop()
                        
                        if (length)
                        {
-                               int perc = play_position * 100LL / length;
-                       
-                                       /* only store last play position when between 1% and 99% */
-                               if ((1 < perc) && (perc < 99))
-                                       m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
+                               m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
                        }
                        m_cuesheet_changed = 1;
                }
@@ -1385,7 +1452,14 @@ RESULT eDVBServicePlay::setTrickmode(int trick)
 
 RESULT eDVBServicePlay::isCurrentlySeekable()
 {
-       return m_is_pvr || m_timeshift_active ? 3 : 0; // fast forward/backward possible and seeking possible
+       int ret = 0;
+       if (m_decoder)
+       {
+               ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
+               if (m_decoder->getVideoProgressive() == -1)
+                       ret &= ~2;
+       }
+       return ret;
 }
 
 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
@@ -2080,12 +2154,13 @@ RESULT eDVBServicePlay::startTimeshift()
        return 0;
 }
 
-RESULT eDVBServicePlay::stopTimeshift()
+RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
 {
        if (!m_timeshift_enabled)
                return -1;
        
-       switchToLive();
+       if (swToLive)
+               switchToLive();
        
        m_timeshift_enabled = 0;
        
@@ -2234,40 +2309,32 @@ void eDVBServicePlay::updateTimeshiftPids()
        }
 }
 
+RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
+{
+       m_timeshift_file_next = f;
+       return 0;
+}
+
 void eDVBServicePlay::switchToLive()
 {
        if (!m_timeshift_active)
                return;
-       
+
        eDebug("SwitchToLive");
-       
-       m_cue = 0;
-       m_decoder = 0;
-       m_decode_demux = 0;
-       m_teletext_parser = 0;
-       m_rds_decoder = 0;
-       m_subtitle_parser = 0;
-       m_new_dvb_subtitle_page_connection = 0;
-       m_new_subtitle_page_connection = 0;
-       m_rds_decoder_event_connection = 0;
-       m_video_event_connection = 0;
+
+       resetTimeshift(0);
+
        m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
 
-               /* free the timeshift service handler, we need the resources */
+       /* free the timeshift service handler, we need the resources */
        m_service_handler_timeshift.free();
-       m_timeshift_active = 0;
-       m_timeshift_changed = 1;
-
-       m_event((iPlayableService*)this, evSeekableStatusChanged);
 
-       updateDecoder();
+       updateDecoder(true);
 }
 
-void eDVBServicePlay::switchToTimeshift()
+void eDVBServicePlay::resetTimeshift(int start)
 {
-       if (m_timeshift_active)
-               return;
-
+       m_cue = 0;
        m_decode_demux = 0;
        m_decoder = 0;
        m_teletext_parser = 0;
@@ -2277,27 +2344,40 @@ void eDVBServicePlay::switchToTimeshift()
        m_new_dvb_subtitle_page_connection = 0;
        m_rds_decoder_event_connection = 0;
        m_video_event_connection = 0;
-
-       m_timeshift_active = 1;
        m_timeshift_changed = 1;
+       m_timeshift_file_next.clear();
+
+       if (start)
+       {
+               m_cue = new eCueSheet();
+               m_timeshift_active = 1;
+       }
+       else
+               m_timeshift_active = 0;
+}
+
+void eDVBServicePlay::switchToTimeshift()
+{
+       if (m_timeshift_active)
+               return;
+
+       resetTimeshift(1);
 
        eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
        r.path = m_timeshift_file;
 
-       m_cue = new eCueSheet();
        m_cue->seekTo(0, -1000);
        m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
 
        eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
        pause();
-       updateDecoder(); /* mainly to switch off PCR, and to set pause */
-
-       m_event((iPlayableService*)this, evSeekableStatusChanged);
+       updateDecoder(true); /* mainly to switch off PCR, and to set pause */
 }
 
-void eDVBServicePlay::updateDecoder()
+void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
 {
        int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
+       bool mustPlay = false;
 
        eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
 
@@ -2348,8 +2428,6 @@ void eDVBServicePlay::updateDecoder()
        if (!m_decoder)
        {
                h.getDecodeDemux(m_decode_demux);
-               if (m_timeshift_changed)
-                       m_decoder = 0;
                if (m_decode_demux)
                {
                        m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
@@ -2378,17 +2456,17 @@ void eDVBServicePlay::updateDecoder()
                                        Py_DECREF(subs);
                                }
                        }
-                       m_decoder->play(); /* pids will be set later */
                }
                if (m_cue)
                        m_cue->setDecodingDemux(m_decode_demux, m_decoder);
-               m_decoder->play(); /* pids will be set later. */
+               mustPlay = true;
        }
 
        m_timeshift_changed = 0;
 
        if (m_decoder)
        {
+               bool wasSeekable = m_decoder->getVideoProgressive() != -1;
                if (m_dvb_service)
                {
                        achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
@@ -2447,7 +2525,11 @@ void eDVBServicePlay::updateDecoder()
                                m_decoder->setRadioPic(radio_pic);
                }
 
-               m_decoder->set();
+               if (mustPlay)
+                       m_decoder->play();
+               else
+                       m_decoder->set();
+
                m_decoder->setAudioChannel(achannel);
 
                /* don't worry about non-existing services, nor pvr services */
@@ -2459,8 +2541,13 @@ void eDVBServicePlay::updateDecoder()
                        m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
                        m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
                }
+               if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
+                       sendSeekableStateChanged = true;
        }
        m_have_video_pid = (vpid > 0 && vpid < 0x2000);
+
+       if (sendSeekableStateChanged)
+               m_event((iPlayableService*)this, evSeekableStatusChanged);
 }
 
 void eDVBServicePlay::loadCuesheet()
@@ -2561,7 +2648,7 @@ void eDVBServicePlay::cutlistToCuesheet()
        {
                if (i == m_cue_entries.end())
                {
-                       if (!have_any_span)
+                       if (!have_any_span && !in)
                                break;
                        out = length;
                } else {
@@ -2591,6 +2678,7 @@ void eDVBServicePlay::cutlistToCuesheet()
                {
                        have_any_span = 1;
                        m_cue->addSourceSpan(in, out);
+                       in = out = 0;
                }
                
                in = length;