mediaplyer: use glib uri escape function for filenames
[enigma2.git] / lib / service / servicedvb.cpp
index 8017e3d6aa70b58927360c68ead0c3856b51a28c..558bf0c22cd0273428aa24577915a72b6182df3c 100644 (file)
@@ -97,50 +97,9 @@ int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const
 }
 
 extern void PutToDict(ePyObject &dict, const char*key, long value);  // defined in dvb/frontend.cpp
 }
 
 extern void PutToDict(ePyObject &dict, const char*key, long value);  // defined in dvb/frontend.cpp
-extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp
-extern void PutToDict(ePyObject &dict, const char*key, const char *value); // defined in dvb/frontend.cpp
-
-void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
-{
-       PutToDict(dict, "tuner_type", "DVB-S");
-       PutToDict(dict, "frequency", feparm.frequency);
-       PutToDict(dict, "symbol_rate", feparm.symbol_rate);
-       PutToDict(dict, "orbital_position", feparm.orbital_position);
-       PutToDict(dict, "inversion", feparm.inversion);
-       PutToDict(dict, "fec_inner", feparm.fec);
-       PutToDict(dict, "modulation", feparm.modulation);
-       PutToDict(dict, "polarization", feparm.polarisation);
-       if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
-       {
-               PutToDict(dict, "rolloff", feparm.rolloff);
-               PutToDict(dict, "pilot", feparm.pilot);
-       }
-       PutToDict(dict, "system", feparm.system);
-}
-
-void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
-{
-       PutToDict(dict, "tuner_type", "DVB-T");
-       PutToDict(dict, "frequency", feparm.frequency);
-       PutToDict(dict, "bandwidth", feparm.bandwidth);
-       PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
-       PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
-       PutToDict(dict, "constellation", feparm.modulation);
-       PutToDict(dict, "transmission_mode", feparm.transmission_mode);
-       PutToDict(dict, "guard_interval", feparm.guard_interval);
-       PutToDict(dict, "hierarchy_information", feparm.hierarchy);
-       PutToDict(dict, "inversion", feparm.inversion);
-}
-
-void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
-{
-       PutToDict(dict, "tuner_type", "DVB-C");
-       PutToDict(dict, "frequency", feparm.frequency);
-       PutToDict(dict, "symbol_rate", feparm.symbol_rate);
-       PutToDict(dict, "modulation", feparm.modulation);
-       PutToDict(dict, "inversion", feparm.inversion);
-       PutToDict(dict, "fec_inner", feparm.fec_inner);
-}
+extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
+extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
+extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
 
 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
 {
 
 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
 {
@@ -466,6 +425,7 @@ public:
        
        RESULT deleteFromDisk(int simulate);
        RESULT getListOfFilenames(std::list<std::string> &);
        
        RESULT deleteFromDisk(int simulate);
        RESULT getListOfFilenames(std::list<std::string> &);
+       RESULT reindex();
 };
 
 DEFINE_REF(eDVBPVRServiceOfflineOperations);
 };
 
 DEFINE_REF(eDVBPVRServiceOfflineOperations);
@@ -528,6 +488,42 @@ RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string
        return 0;
 }
 
        return 0;
 }
 
+RESULT eDVBPVRServiceOfflineOperations::reindex()
+{
+       const char *filename = m_ref.path.c_str();
+       eDebug("reindexing %s...", filename);
+
+       eMPEGStreamInformation info;
+       eMPEGStreamParserTS parser(info);
+       
+       info.startSave(filename);
+       
+       eRawFile f;
+       
+       int err = f.open(m_ref.path.c_str(), 0);
+       if (err < 0)
+               return -1;
+       
+       off_t length = f.length();
+       unsigned char buffer[188*256*4];
+       while (1)
+       {
+               off_t offset = f.lseek(0, SEEK_CUR);
+               eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
+               int r = f.read(buffer, sizeof(buffer));
+               if (!r)
+                       break;
+               if (r < 0)
+                       return r;
+               parser.parseData(offset, buffer, r);
+       }
+       
+       info.stopSave();
+       f.close();
+       
+       return 0;
+}
+
 DEFINE_REF(eServiceFactoryDVB)
 
 eServiceFactoryDVB::eServiceFactoryDVB()
 DEFINE_REF(eServiceFactoryDVB)
 
 eServiceFactoryDVB::eServiceFactoryDVB()
@@ -921,7 +917,7 @@ eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *serv
        m_is_pvr = !m_reference.path.empty();
        
        m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
        m_is_pvr = !m_reference.path.empty();
        
        m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
-       m_skipmode = 0;
+       m_skipmode = m_fastforward = m_slowmotion = 0;
        
        CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
        CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
        
        CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
        CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
@@ -1033,6 +1029,9 @@ void eDVBServicePlay::serviceEvent(int event)
                m_event((iPlayableService*)this, evUpdatedInfo);
                break;
        }
                m_event((iPlayableService*)this, evUpdatedInfo);
                break;
        }
+       case eDVBServicePMTHandler::eventPreStart:
+               loadCuesheet();
+               break;
        case eDVBServicePMTHandler::eventEOF:
                m_event((iPlayableService*)this, evEOF);
                break;
        case eDVBServicePMTHandler::eventEOF:
                m_event((iPlayableService*)this, evEOF);
                break;
@@ -1065,22 +1064,30 @@ void eDVBServicePlay::serviceEventTimeshift(int event)
 
 RESULT eDVBServicePlay::start()
 {
 
 RESULT eDVBServicePlay::start()
 {
-       int r;
+       eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
+
                /* 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. */
        if (m_is_pvr)
                /* 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. */
        if (m_is_pvr)
+       {
+               eDVBMetaParser meta;
+               if (!meta.parseFile(m_reference.path))
+               {
+                       service = meta.m_ref;
+                       service.path = m_reference.path;
+               }
                m_cue = new eCueSheet();
                m_cue = new eCueSheet();
+       }
        else
                m_event(this, evStart);
 
        m_first_program_info = 1;
        else
                m_event(this, evStart);
 
        m_first_program_info = 1;
-       eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
-       r = m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
+       m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
 
 
-               /* inject EIT if there is a stored one */
        if (m_is_pvr)
        {
        if (m_is_pvr)
        {
+               /* inject EIT if there is a stored one */
                std::string filename = service.path;
                filename.erase(filename.length()-2, 2);
                filename+="eit";
                std::string filename = service.path;
                filename.erase(filename.length()-2, 2);
                filename+="eit";
@@ -1091,11 +1098,6 @@ RESULT eDVBServicePlay::start()
                        m_event_handler.inject(event, 0);
                        m_event_handler.inject(empty, 1);
                }
                        m_event_handler.inject(event, 0);
                        m_event_handler.inject(empty, 1);
                }
-       }
-
-       if (m_is_pvr)
-       {
-               loadCuesheet();
                m_event(this, evStart);
        }
        return 0;
                m_event(this, evStart);
        }
        return 0;
@@ -1126,11 +1128,7 @@ RESULT eDVBServicePlay::stop()
                        
                        if (length)
                        {
                        
                        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;
                }
                        }
                        m_cuesheet_changed = 1;
                }
@@ -1185,7 +1183,10 @@ RESULT eDVBServicePlay::setSlowMotion(int ratio)
        eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
        setFastForward_internal(0);
        if (m_decoder)
        eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
        setFastForward_internal(0);
        if (m_decoder)
+       {
+               m_slowmotion = ratio;
                return m_decoder->setSlowMotion(ratio);
                return m_decoder->setSlowMotion(ratio);
+       }
        else
                return -1;
 }
        else
                return -1;
 }
@@ -1197,10 +1198,11 @@ RESULT eDVBServicePlay::setFastForward(int ratio)
        return setFastForward_internal(ratio);
 }
 
        return setFastForward_internal(ratio);
 }
 
-RESULT eDVBServicePlay::setFastForward_internal(int ratio)
+RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
 {
 {
-       int skipmode, ffratio;
-       
+       int skipmode, ffratio, ret = 0;
+       pts_t pos=0;
+
        if (ratio > 8)
        {
                skipmode = ratio;
        if (ratio > 8)
        {
                skipmode = ratio;
@@ -1225,19 +1227,28 @@ RESULT eDVBServicePlay::setFastForward_internal(int ratio)
                if (m_cue)
                        m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
        }
                if (m_cue)
                        m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
        }
-       
+
        m_skipmode = skipmode;
        m_skipmode = skipmode;
-       
+
+       if (final_seek)
+               eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
+
+       m_fastforward = ffratio;
+
        if (!m_decoder)
                return -1;
        if (!m_decoder)
                return -1;
-               
+
        if (ffratio == 0)
                ; /* return m_decoder->play(); is done in caller*/
        else if (ffratio != 1)
        if (ffratio == 0)
                ; /* return m_decoder->play(); is done in caller*/
        else if (ffratio != 1)
-               return m_decoder->setFastForward(ffratio);
+               ret = m_decoder->setFastForward(ffratio);
        else
        else
-               return m_decoder->setTrickmode();
-       return 0;
+               ret = m_decoder->setTrickmode();
+
+       if (pos)
+               eDebug("final seek after trickplay ret %d", seekTo(pos));
+
+       return ret;
 }
 
 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
 }
 
 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
@@ -1266,9 +1277,10 @@ RESULT eDVBServicePlay::getLength(pts_t &len)
 RESULT eDVBServicePlay::pause()
 {
        eDebug("eDVBServicePlay::pause");
 RESULT eDVBServicePlay::pause()
 {
        eDebug("eDVBServicePlay::pause");
-       setFastForward_internal(0);
+       setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
        if (m_decoder)
        {
        if (m_decoder)
        {
+               m_slowmotion = 0;
                m_is_paused = 1;
                return m_decoder->pause();
        } else
                m_is_paused = 1;
                return m_decoder->pause();
        } else
@@ -1278,9 +1290,10 @@ RESULT eDVBServicePlay::pause()
 RESULT eDVBServicePlay::unpause()
 {
        eDebug("eDVBServicePlay::unpause");
 RESULT eDVBServicePlay::unpause()
 {
        eDebug("eDVBServicePlay::unpause");
-       setFastForward_internal(0);
+       setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
        if (m_decoder)
        {
        if (m_decoder)
        {
+               m_slowmotion = 0;
                m_is_paused = 0;
                return m_decoder->play();
        } else
                m_is_paused = 0;
                return m_decoder->play();
        } else
@@ -1370,7 +1383,14 @@ RESULT eDVBServicePlay::setTrickmode(int trick)
 
 RESULT eDVBServicePlay::isCurrentlySeekable()
 {
 
 RESULT eDVBServicePlay::isCurrentlySeekable()
 {
-       return m_is_pvr || m_timeshift_active;
+       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)
 }
 
 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
@@ -1728,6 +1748,7 @@ int eDVBServicePlay::selectAudioStream(int i)
 {
        eDVBServicePMTHandler::program program;
        eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
 {
        eDVBServicePMTHandler::program program;
        eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
+       pts_t position = -1;
 
        if (h.getProgramInfo(program))
                return -1;
 
        if (h.getProgramInfo(program))
                return -1;
@@ -1750,6 +1771,9 @@ int eDVBServicePlay::selectAudioStream(int i)
                apidtype = program.audioStreams[stream].type;
        }
 
                apidtype = program.audioStreams[stream].type;
        }
 
+       if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
+               eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
+
        m_current_audio_pid = apid;
 
        if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
        m_current_audio_pid = apid;
 
        if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
@@ -1758,21 +1782,29 @@ int eDVBServicePlay::selectAudioStream(int i)
                return -4;
        }
 
                return -4;
        }
 
+       if (position != -1)
+               eDebug("seekTo ret %d", seekTo(position));
+
+       int rdsPid = apid;
+
                /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
        if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
                /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
        if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
-               if (!m_rds_decoder)
+       {
+               int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
+               if (different_pid)
+                       rdsPid = program.audioStreams[stream].rdsPid;
+               if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
                {
                {
+                       m_rds_decoder = 0;
                        ePtr<iDVBDemux> data_demux;
                        if (!h.getDataDemux(data_demux))
                        {
                        ePtr<iDVBDemux> data_demux;
                        if (!h.getDataDemux(data_demux))
                        {
-                               m_rds_decoder = new eDVBRdsDecoder(data_demux);
+                               m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
                                m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
                                m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
+                               m_rds_decoder->start(rdsPid);
                        }
                }
                        }
                }
-
-               /* if we decided that we need one, update the pid */
-       if (m_rds_decoder)
-               m_rds_decoder->start(apid);
+       }
 
                        /* store new pid as default only when:
                                a.) we have an entry in the service db for the current service,
 
                        /* store new pid as default only when:
                                a.) we have an entry in the service db for the current service,
@@ -2053,12 +2085,13 @@ RESULT eDVBServicePlay::startTimeshift()
        return 0;
 }
 
        return 0;
 }
 
-RESULT eDVBServicePlay::stopTimeshift()
+RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
 {
        if (!m_timeshift_enabled)
                return -1;
        
 {
        if (!m_timeshift_enabled)
                return -1;
        
-       switchToLive();
+       if (swToLive)
+               switchToLive();
        
        m_timeshift_enabled = 0;
        
        
        m_timeshift_enabled = 0;
        
@@ -2224,16 +2257,14 @@ void eDVBServicePlay::switchToLive()
        m_new_subtitle_page_connection = 0;
        m_rds_decoder_event_connection = 0;
        m_video_event_connection = 0;
        m_new_subtitle_page_connection = 0;
        m_rds_decoder_event_connection = 0;
        m_video_event_connection = 0;
-       m_is_paused = m_skipmode = 0; /* not supported in live mode */
+       m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
 
                /* free the timeshift service handler, we need the resources */
        m_service_handler_timeshift.free();
        m_timeshift_active = 0;
        m_timeshift_changed = 1;
 
 
                /* 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::switchToTimeshift()
@@ -2258,18 +2289,18 @@ void eDVBServicePlay::switchToTimeshift()
        r.path = m_timeshift_file;
 
        m_cue = new eCueSheet();
        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();
        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;
 {
        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;
 
 
        eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
 
@@ -2350,16 +2381,17 @@ void eDVBServicePlay::updateDecoder()
                                        Py_DECREF(subs);
                                }
                        }
                                        Py_DECREF(subs);
                                }
                        }
-                       m_decoder->play(); /* pids will be set later */
                }
                if (m_cue)
                        m_cue->setDecodingDemux(m_decode_demux, m_decoder);
                }
                if (m_cue)
                        m_cue->setDecodingDemux(m_decode_demux, m_decoder);
+               mustPlay = true;
        }
 
        m_timeshift_changed = 0;
 
        if (m_decoder)
        {
        }
 
        m_timeshift_changed = 0;
 
        if (m_decoder)
        {
+               bool wasSeekable = m_decoder->getVideoProgressive() != -1;
                if (m_dvb_service)
                {
                        achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
                if (m_dvb_service)
                {
                        achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
@@ -2392,17 +2424,8 @@ void eDVBServicePlay::updateDecoder()
                        }
                }
 
                        }
                }
 
-               std::string config_delay;
-               int config_delay_int = 0;
-               if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
-                       config_delay_int = atoi(config_delay.c_str());
-               m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
-
-               if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
-                       config_delay_int = atoi(config_delay.c_str());
-               else
-                       config_delay_int = 0;
-               m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
+               setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
+               setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
 
                m_decoder->setVideoPID(vpid, vpidtype);
                selectAudioStream();
 
                m_decoder->setVideoPID(vpid, vpidtype);
                selectAudioStream();
@@ -2427,7 +2450,11 @@ void eDVBServicePlay::updateDecoder()
                                m_decoder->setRadioPic(radio_pic);
                }
 
                                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 */
                m_decoder->setAudioChannel(achannel);
 
                /* don't worry about non-existing services, nor pvr services */
@@ -2439,8 +2466,13 @@ void eDVBServicePlay::updateDecoder()
                        m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
                        m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
                }
                        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);
        }
        m_have_video_pid = (vpid > 0 && vpid < 0x2000);
+
+       if (sendSeekableStateChanged)
+               m_event((iPlayableService*)this, evSeekableStatusChanged);
 }
 
 void eDVBServicePlay::loadCuesheet()
 }
 
 void eDVBServicePlay::loadCuesheet()
@@ -2541,7 +2573,7 @@ void eDVBServicePlay::cutlistToCuesheet()
        {
                if (i == m_cue_entries.end())
                {
        {
                if (i == m_cue_entries.end())
                {
-                       if (!have_any_span)
+                       if (!have_any_span && !in)
                                break;
                        out = length;
                } else {
                                break;
                        out = length;
                } else {
@@ -2571,6 +2603,7 @@ void eDVBServicePlay::cutlistToCuesheet()
                {
                        have_any_span = 1;
                        m_cue->addSourceSpan(in, out);
                {
                        have_any_span = 1;
                        m_cue->addSourceSpan(in, out);
+                       in = out = 0;
                }
                
                in = length;
                }
                
                in = length;
@@ -2926,16 +2959,28 @@ void eDVBServicePlay::setAC3Delay(int delay)
 {
        if (m_dvb_service)
                m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
 {
        if (m_dvb_service)
                m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
-       if (m_decoder)
-               m_decoder->setAC3Delay(delay);
+       if (m_decoder) {
+               std::string config_delay;
+               int config_delay_int = 0;
+               if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
+                       config_delay_int = atoi(config_delay.c_str());
+               m_decoder->setAC3Delay(delay + config_delay_int);
+       }
 }
 
 void eDVBServicePlay::setPCMDelay(int delay)
 {
        if (m_dvb_service)
                m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
 }
 
 void eDVBServicePlay::setPCMDelay(int delay)
 {
        if (m_dvb_service)
                m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
-       if (m_decoder)
-               m_decoder->setPCMDelay(delay);
+       if (m_decoder) {
+               std::string config_delay;
+               int config_delay_int = 0;
+               if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
+                       config_delay_int = atoi(config_delay.c_str());
+               else
+                       config_delay_int = 0;
+               m_decoder->setPCMDelay(delay + config_delay_int);
+       }
 }
 
 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
 }
 
 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)