}
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)
{
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);
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;
}
}
+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<eServiceEvent> &evt, time_t start_time)
{
if (!ref.path.empty())
RESULT deleteFromDisk(int simulate);
RESULT getListOfFilenames(std::list<std::string> &);
+ RESULT reindex();
};
DEFINE_REF(eDVBPVRServiceOfflineOperations);
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()
RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &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<iDVBChannelList> db;
- ePtr<eDVBResourceManager> 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<iDVBChannelList> db;
+ ePtr<eDVBResourceManager> 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;
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);
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;
}
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)
return m_decoder->setFastForward(ffratio);
else
return m_decoder->setTrickmode();
+ return 0;
}
RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
ePtr<iStaticServiceInformation> 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())
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)
{
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();
{
int ret = selectAudioStream(i);
- if (m_decoder->play())
+ if (m_decoder->set())
return -5;
return ret;
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;
}
+ 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 (!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))
{
- 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->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,
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)
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();
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);
m_video_event_connection = 0;
m_timeshift_active = 1;
+ m_timeshift_changed = 1;
eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
r.path = m_timeshift_file;
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)
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);
else
m_decoder->setSyncPCR(-1);
- m_decoder->setTextPID(tpid);
-
- m_teletext_parser->start(program.textPid);
+ if (m_is_primary)
+ {
+ m_decoder->setTextPID(tpid);
+ m_teletext_parser->start(program.textPid);
+ }
if (vpid > 0 && vpid < 0x2000)
;
m_decoder->setRadioPic(radio_pic);
}
-/* if (!m_is_primary)
- m_decoder->setTrickmode();
- else */ if (m_is_paused)
- m_decoder->pause();
- else
- m_decoder->play();
-
+ 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);
std::multiset<cueEntry>::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;
out = length;
if (in < out)
+ {
+ have_any_span = 1;
m_cue->addSourceSpan(in, out);
+ }
in = length;
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;
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)