RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
{
ASSERT(ref == m_ref);
- if (m_parser.m_name.size())
+ if (!ref.name.empty())
+ name = ref.name;
+ else if (!m_parser.m_name.empty())
name = m_parser.m_name;
else
{
int err = f.open(m_ref.path.c_str(), 0);
if (err < 0)
return -1;
-
+
+ off_t offset = 0;
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));
+ int r = f.read(offset, buffer, sizeof(buffer));
if (!r)
break;
if (r < 0)
return r;
+ offset += r;
parser.parseData(offset, buffer, r);
}
/* 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!");
+// eDebug("getService failed!");
return err;
}
}
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;
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:
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);
+ ePtr<iTsSource> source = createTsSource(r);
+ m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), 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);
+
+ ePtr<iTsSource> source = createTsSource(r);
+ m_service_handler_timeshift.tuneExt(r, 1, source, m_timeshift_file_next.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
+
+ m_event((iPlayableService*)this, evUser+1);
+ }
}
break;
}
m_event(this, evStart);
m_first_program_info = 1;
- m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
+ ePtr<iTsSource> source = createTsSource(service);
+ m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service);
if (m_is_pvr)
{
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;
}
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)
{
eDVBServicePMTHandler::program program;
- if (w == sCAIDs)
+ if (w == sCAIDs || w == sCAIDPIDs)
return resIsPyObject;
eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
{
case sCAIDs:
return m_service_handler.getCaIds();
+ case sCAIDPIDs:
+ return m_service_handler.getCaIds(true);
case sTransponderData:
return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
default:
info.m_description = "AAC-HE";
else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
info.m_description = "DTS";
+ else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
+ info.m_description = "DTS-HD";
else
info.m_description = "???";
return 0;
}
-RESULT eDVBServicePlay::stopTimeshift()
+RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
{
if (!m_timeshift_enabled)
return -1;
- switchToLive();
+ if (swToLive)
+ switchToLive();
m_timeshift_enabled = 0;
}
}
+RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
+{
+ m_timeshift_file_next = f;
+ return 0;
+}
+
void eDVBServicePlay::switchToLive()
{
if (!m_timeshift_active)
return;
-
+
eDebug("SwitchToLive");
-
+
+ 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 */
+ m_service_handler_timeshift.free();
+
+ updateDecoder(true);
+}
+
+void eDVBServicePlay::resetTimeshift(int start)
+{
m_cue = 0;
- m_decoder = 0;
m_decode_demux = 0;
+ m_decoder = 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_new_dvb_subtitle_page_connection = 0;
m_rds_decoder_event_connection = 0;
m_video_event_connection = 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 */
- m_service_handler_timeshift.free();
- m_timeshift_active = 0;
m_timeshift_changed = 1;
+ m_timeshift_file_next.clear();
- m_event((iPlayableService*)this, evSeekableStatusChanged);
+ if (start)
+ {
+ m_cue = new eCueSheet();
+ m_timeshift_active = 1;
+ }
+ else
+ m_timeshift_active = 0;
+}
- updateDecoder();
+ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
+{
+ eRawFile *f = new eRawFile();
+ f->open(ref.path.c_str());
+ return ePtr<iTsSource>(f);
}
void eDVBServicePlay::switchToTimeshift()
if (m_timeshift_active)
return;
- m_decode_demux = 0;
- m_decoder = 0;
- m_teletext_parser = 0;
- m_rds_decoder = 0;
- m_subtitle_parser = 0;
- m_new_subtitle_page_connection = 0;
- 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;
+ 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 */
+
+ ePtr<iTsSource> source = createTsSource(r);
+ m_service_handler_timeshift.tuneExt(r, 1, source, m_timeshift_file.c_str(), 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;
eDebug("getting program info failed.");
else
{
- eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
+ eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
if (!program.videoStreams.empty())
{
eDebugNoNewLine(" (");
}
eDebugNoNewLine(")");
}
- eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
+ eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
if (!program.audioStreams.empty())
{
eDebugNoNewLine(" (");
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)
{
+ bool wasSeekable = m_decoder->getVideoProgressive() != -1;
if (m_dvb_service)
{
achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
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()
m_cue_entries.insert(cueEntry(where, what));
}
fclose(f);
- eDebug("%d entries", m_cue_entries.size());
+ eDebug("%zd entries", m_cue_entries.size());
} else
eDebug("cutfile not found!");
{
if (i == m_cue_entries.end())
{
- if (!have_any_span)
+ if (!have_any_span && !in)
break;
out = length;
} else {
{
have_any_span = 1;
m_cue->addSourceSpan(in, out);
+ in = out = 0;
}
in = length;