X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/d58ca4cf34b7621aea4e2c1ff07bed6b2cd6b763..b455ca34e1ab4a716e1b2f0c7228fb235b577ce4:/lib/service/servicedvb.cpp diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 14c849db..497911c5 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -336,6 +336,7 @@ public: int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; } int getInfo(const eServiceReference &ref, int w); std::string getInfoString(const eServiceReference &ref,int w); + PyObject *getInfoObject(const eServiceReference &r, int what); }; DEFINE_REF(eStaticServiceDVBPVRInformation); @@ -400,6 +401,8 @@ int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w return iServiceInformation::resIsString; case iServiceInformation::sServiceref: return iServiceInformation::resIsString; + case iServiceInformation::sFileSize: + return m_parser.m_filesize; case iServiceInformation::sTimeCreate: if (m_parser.m_time_create) return m_parser.m_time_create; @@ -425,6 +428,17 @@ std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReferen } } +PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what) +{ + switch (what) + { + case iServiceInformation::sFileSize: + return PyLong_FromLongLong(m_parser.m_filesize); + default: + Py_RETURN_NONE; + } +} + RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr &evt, time_t start_time) { if (!ref.path.empty()) @@ -452,6 +466,7 @@ public: RESULT deleteFromDisk(int simulate); RESULT getListOfFilenames(std::list &); + RESULT reindex(); }; DEFINE_REF(eDVBPVRServiceOfflineOperations); @@ -514,6 +529,42 @@ RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list &service, const eServiceReference &ref) { - // TODO: handle the listing itself - // if (ref.... == -1) .. return "... bouquets ..."; - // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists - // TODO: cache - ePtr db; - ePtr res; - - int err; - if ((err = eDVBResourceManager::getInstance(res)) != 0) + if (!ref.path.empty()) // playback { - eDebug("no resource manager"); - return err; + eDVBMetaParser parser; + int ret=parser.parseFile(ref.path); + service = new eDVBService; + if (!ret) + eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data); } - if ((err = res->getChannelList(db)) != 0) + else { - eDebug("no channel list"); - return err; - } + // TODO: handle the listing itself + // if (ref.... == -1) .. return "... bouquets ..."; + // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists + // TODO: cache + ePtr db; + ePtr res; + + int err; + if ((err = eDVBResourceManager::getInstance(res)) != 0) + { + eDebug("no resource manager"); + return err; + } + if ((err = res->getChannelList(db)) != 0) + { + eDebug("no channel list"); + return err; + } /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */ - if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0) - { - eDebug("getService failed!"); - return err; + if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0) + { + eDebug("getService failed!"); + return err; + } } return 0; @@ -895,7 +957,7 @@ eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *serv m_is_primary = 1; m_is_pvr = !m_reference.path.empty(); - m_timeshift_enabled = m_timeshift_active = 0; + m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0; m_skipmode = 0; CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent); @@ -916,6 +978,29 @@ eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *serv eDVBServicePlay::~eDVBServicePlay() { + if (m_is_pvr) + { + eDVBMetaParser meta; + int ret=meta.parseFile(m_reference.path); + if (!ret) + { + char tmp[255]; + meta.m_service_data=""; + sprintf(tmp, "f:%x", m_dvb_service->m_flags); + meta.m_service_data += tmp; + // cached pids + for (int x=0; x < eDVBService::cacheMax; ++x) + { + int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x); + if (entry != -1) + { + sprintf(tmp, ",c:%02d%04x", x, entry); + meta.m_service_data += tmp; + } + } + meta.updateMeta(m_reference.path); + } + } delete m_subtitle_widget; } @@ -1028,7 +1113,7 @@ RESULT eDVBServicePlay::start() m_first_program_info = 1; eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference; - r = m_service_handler.tune(service, m_is_pvr, m_cue); + r = 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) @@ -1133,7 +1218,7 @@ RESULT eDVBServicePlay::pause(ePtr &ptr) RESULT eDVBServicePlay::setSlowMotion(int ratio) { - assert(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */ + ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */ eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio); setFastForward_internal(0); if (m_decoder) @@ -1145,7 +1230,7 @@ RESULT eDVBServicePlay::setSlowMotion(int ratio) RESULT eDVBServicePlay::setFastForward(int ratio) { eDebug("eDVBServicePlay::setFastForward(%d)", ratio); - assert(ratio); + ASSERT(ratio); return setFastForward_internal(ratio); } @@ -1189,6 +1274,7 @@ RESULT eDVBServicePlay::setFastForward_internal(int ratio) return m_decoder->setFastForward(ffratio); else return m_decoder->setTrickmode(); + return 0; } RESULT eDVBServicePlay::seek(ePtr &ptr) @@ -1425,7 +1511,7 @@ RESULT eDVBServicePlay::getName(std::string &name) ePtr i = new eStaticServiceDVBPVRInformation(m_reference); return i->getName(m_reference, name); } - if (m_dvb_service) + else if (m_dvb_service) { m_dvb_service->getName(m_reference, name); if (name.empty()) @@ -1480,7 +1566,7 @@ int eDVBServicePlay::getInfo(int w) int aspect = -1; if (m_decoder) aspect = m_decoder->getVideoAspect(); - if (no_program_info) + if (aspect == -1 && no_program_info) break; else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1) { @@ -1524,10 +1610,34 @@ int eDVBServicePlay::getInfo(int w) break; } case sIsCrypted: if (no_program_info) return -1; return program.isCrypted(); - case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid; + case sVideoPID: + if (m_dvb_service) + { + int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID); + if (vpid != -1) + return vpid; + } + if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid; case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type; - case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid; - case sPCRPID: if (no_program_info) return -1; return program.pcrPid; + case sAudioPID: + if (m_dvb_service) + { + int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID); + if (apid != -1) + return apid; + apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID); + if (apid != -1) + return apid; + } + if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid; + case sPCRPID: + if (m_dvb_service) + { + int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID); + if (pcrpid != -1) + return pcrpid; + } + if (no_program_info) return -1; return program.pcrPid; case sPMTPID: if (no_program_info) return -1; return program.pmtPid; case sTXTPID: if (no_program_info) return -1; return program.textPid; case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get(); @@ -1602,7 +1712,7 @@ RESULT eDVBServicePlay::selectTrack(unsigned int i) { int ret = selectAudioStream(i); - if (m_decoder->play()) + if (m_decoder->set()) return -5; return ret; @@ -1679,7 +1789,7 @@ int eDVBServicePlay::selectAudioStream(int i) m_current_audio_pid = apid; - if (m_decoder->setAudioPID(apid, apidtype)) + if (m_is_primary && m_decoder->setAudioPID(apid, apidtype)) { eDebug("set audio pid failed"); return -4; @@ -1708,7 +1818,7 @@ int eDVBServicePlay::selectAudioStream(int i) anything in the best case, or destroy the default setting in case the real default is not yet available.) */ - if (m_dvb_service && !m_is_pvr && ((i != -1) + if (m_dvb_service && ((i != -1) || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1)))) { if (apidtype == eDVBAudio::aMPEG) @@ -1716,11 +1826,16 @@ int eDVBServicePlay::selectAudioStream(int i) m_dvb_service->setCacheEntry(eDVBService::cAPID, apid); m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1); } - else + else if (apidtype == eDVBAudio::aAC3) { m_dvb_service->setCacheEntry(eDVBService::cAPID, -1); m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid); } + else + { + m_dvb_service->setCacheEntry(eDVBService::cAPID, -1); + m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1); + } } h.resetCachedProgram(); @@ -2146,10 +2261,12 @@ void eDVBServicePlay::switchToLive() 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 */ /* 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); @@ -2172,6 +2289,7 @@ void eDVBServicePlay::switchToTimeshift() m_video_event_connection = 0; m_timeshift_active = 1; + m_timeshift_changed = 1; eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference; r.path = m_timeshift_file; @@ -2239,25 +2357,45 @@ 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); if (m_decoder) m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection); - m_teletext_parser = new eDVBTeletextParser(m_decode_demux); - m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection); - m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux); - m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection); - } else - { - m_teletext_parser = 0; - m_subtitle_parser = 0; + if (m_is_primary) + { + m_teletext_parser = new eDVBTeletextParser(m_decode_demux); + m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection); + m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux); + m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection); + if (m_timeshift_changed) + { + ePyObject subs = getCachedSubtitle(); + if (subs != Py_None) + { + int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)), + pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)), + comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page + anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine + if (type == 0) // dvb + m_subtitle_parser->start(pid, comp_page, anc_page); + else if (type == 1) // ttx + m_teletext_parser->setPageAndMagazine(comp_page, anc_page); + } + 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. */ } + m_timeshift_changed = 0; + if (m_decoder) { if (m_dvb_service) @@ -2266,7 +2404,7 @@ void eDVBServicePlay::updateDecoder() ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY); pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY); } - else // subservice or recording + else // subservice { eServiceReferenceDVB ref; m_service_handler.getServiceReference(ref); @@ -2291,8 +2429,18 @@ void eDVBServicePlay::updateDecoder() } } } - m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay); - m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay); + + 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); m_decoder->setVideoPID(vpid, vpidtype); selectAudioStream(); @@ -2302,16 +2450,11 @@ void eDVBServicePlay::updateDecoder() else m_decoder->setSyncPCR(-1); - m_decoder->setTextPID(tpid); - - m_teletext_parser->start(program.textPid); - -/* if (!m_is_primary) - m_decoder->setTrickmode(); - else */ if (m_is_paused) - m_decoder->pause(); - else - m_decoder->play(); + if (m_is_primary) + { + m_decoder->setTextPID(tpid); + m_teletext_parser->start(program.textPid); + } if (vpid > 0 && vpid < 0x2000) ; @@ -2322,10 +2465,11 @@ void eDVBServicePlay::updateDecoder() m_decoder->setRadioPic(radio_pic); } + m_decoder->set(); m_decoder->setAudioChannel(achannel); /* don't worry about non-existing services, nor pvr services */ - if (m_dvb_service && !m_is_pvr) + if (m_dvb_service) { /* (audio pid will be set in selectAudioTrack */ m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid); @@ -2429,11 +2573,16 @@ void eDVBServicePlay::cutlistToCuesheet() std::multiset::iterator i(m_cue_entries.begin()); + int have_any_span = 0; + while (1) { if (i == m_cue_entries.end()) + { + if (!have_any_span) + break; out = length; - else { + } else { if (i->what == 0) /* in */ { in = i++->where; @@ -2457,7 +2606,10 @@ void eDVBServicePlay::cutlistToCuesheet() out = length; if (in < out) + { + have_any_span = 1; m_cue->addSourceSpan(in, out); + } in = length; @@ -2601,7 +2753,7 @@ PyObject *eDVBServicePlay::getCachedSubtitle() PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext else PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb - PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine return tuple; @@ -2736,18 +2888,22 @@ void eDVBServicePlay::checkSubtitleTiming() m_decoder->getPTS(0, pos); eDebug("%lld %lld", pos, show_time); - int diff = show_time - pos; + int diff = show_time - pos; + if (type == TELETEXT && !page.m_have_pts) + { + eDebug("ttx subtitle page without pts... immediate show"); + diff = 0; + } if (diff < 0) { eDebug("[late (%d ms)]", -diff / 90); diff = 0; } -// if (diff > 900000) -// { -// eDebug("[invalid]"); -// diff = 0; -// } - + if (abs(diff) > 1800000) + { + eDebug("[invalid]... immediate show!"); + diff = 0; + } if ((diff/90)<20) { if (type == TELETEXT)