#include <lib/dvb/tstools.h>
#include <lib/python/python.h>
+ /* for subtitles */
+#include <lib/gui/esubtitle.h>
+
#include <sys/vfs.h>
#include <byteswap.h>
#include <dvbsi++/event_information_section.h>
+#define INTERNAL_TELETEXT
+
#ifndef BYTE_ORDER
#error no byte order defined!
#endif
m_cuesheet_changed = 0;
m_cutlist_enabled = 1;
+
+ m_subtitle_widget = 0;
+
+ CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
}
eDVBServicePlay::~eDVBServicePlay()
{
+ delete m_subtitle_widget;
}
void eDVBServicePlay::gotNewEvent()
return m_is_pvr || m_timeshift_active;
}
-RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
+RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
{
ptr = this;
return 0;
return 0;
}
+RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
+{
+ ptr = this;
+ return 0;
+}
+
RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
{
ptr = this;
return -1;
}
+RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
+{
+ ptr = this;
+ return 0;
+}
+
RESULT eDVBServicePlay::getName(std::string &name)
{
if (m_is_pvr)
}
}
return -1;
- case sIsCrypted: return program.isCrypted;
+ case sIsCrypted: return program.isCrypted();
case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
+ case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
case sPCRPID: return program.pcrPid;
case sPMTPID: return program.pmtPid;
info.m_description = "MPEG";
else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
info.m_description = "AC3";
+ else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
+ info.m_description = "AAC";
else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
info.m_description = "DTS";
else
{
if (program.audioStreams[i].type == eDVBAudio::aMPEG)
{
- m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
- m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
+ m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
+ m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
} else
{
- m_dvb_service->setCachePID(eDVBService::cAPID, -1);
- m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
+ m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
+ m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
}
}
return 0;
}
-int eDVBServicePlay::getFrontendInfo(int w)
+int eDVBServicePlay::getCurrentChannel()
+{
+ int curChannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
+ return curChannel == -1 ? STEREO : curChannel;
+}
+
+RESULT eDVBServicePlay::selectChannel(int i)
+{
+ if (i < iAudioChannelSelection::LEFT || i > iAudioChannelSelection::RIGHT)
+ i = -1; // Stereo
+ if (m_dvb_service->getCacheEntry(eDVBService::cACHANNEL) != i)
+ {
+ m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
+ if (m_decoder)
+ m_decoder->setAudioChannel(i);
+ }
+ return 0;
+}
+
+int eDVBServiceBase::getFrontendInfo(int w)
{
- if (m_is_pvr)
- return 0;
eUsePtr<iDVBChannel> channel;
if(m_service_handler.getChannel(channel))
return 0;
return fe->readFrontendData(w);
}
-PyObject *eDVBServicePlay::getFrontendData(bool original)
+PyObject *eDVBServiceBase::getFrontendData(bool original)
{
PyObject *ret=0;
void eDVBServicePlay::updateDecoder()
{
- int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
+ int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1;
eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
bool defaultac3=false;
i != program.videoStreams.end(); ++i)
{
if (vpid == -1)
+ {
vpid = i->pid;
+ vpidtype = i->type;
+ }
if (i != program.videoStreams.begin())
eDebugNoNewLine(", ");
eDebugNoNewLine("%04x", i->pid);
pcrpid = program.pcrPid;
eDebug(", and the text pid is %04x", program.textPid);
tpid = program.textPid;
+ achannel = program.audioChannel;
}
if (!m_decoder)
m_cue->setDecodingDemux(m_decode_demux, m_decoder);
#ifdef INTERNAL_TELETEXT
m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
+ m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
#endif
}
if (m_decoder)
{
- m_decoder->setVideoPID(vpid);
+ m_decoder->setVideoPID(vpid, vpidtype);
m_current_audio_stream = 0;
m_decoder->setAudioPID(apid, apidtype);
if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
if (!m_is_primary)
m_decoder->setTrickmode(1);
+
m_decoder->start();
+
+ m_decoder->setAudioChannel(achannel);
+
// how we can do this better?
// update cache pid when the user changed the audio track or video track
// TODO handling of difference audio types.. default audio types..
{
if (apidtype == eDVBAudio::aMPEG)
{
- m_dvb_service->setCachePID(eDVBService::cAPID, apid);
- m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
+ m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
+ m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
}
else
{
- m_dvb_service->setCachePID(eDVBService::cAPID, -1);
- m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
+ m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
+ m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
}
- m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
- m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
- m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
+ m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
+ m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
+ m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
+ m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
}
}
}
m_cue->commitSpans();
}
+RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
+{
+ if (m_subtitle_widget)
+ disableSubtitles(parent);
+
+ if (!m_teletext_parser)
+ return -1;
+
+ if (!PyInt_Check(entry))
+ return -1;
+
+ m_subtitle_widget = new eSubtitleWidget(parent);
+ m_subtitle_widget->resize(parent->size()); /* full size */
+
+ int page = PyInt_AsLong(entry);
+
+ m_teletext_parser->setPage(page);
+
+ return 0;
+}
+
+RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
+{
+ delete m_subtitle_widget;
+ m_subtitle_widget = 0;
+ return 0;
+}
+
+PyObject *eDVBServicePlay::getSubtitleList()
+{
+ if (!m_teletext_parser)
+ {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ PyObject *l = PyList_New(0);
+
+ for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
+ {
+ PyObject *tuple = PyTuple_New(2);
+ char desc[20];
+ sprintf(desc, "Page %x", *i);
+ PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
+ PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
+ PyList_Append(l, tuple);
+ }
+
+ return l;
+}
+
+void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
+{
+ if (m_subtitle_widget)
+ {
+ m_subtitle_pages.push_back(page);
+
+ checkSubtitleTiming();
+ }
+}
+
+void eDVBServicePlay::checkSubtitleTiming()
+{
+ while (1)
+ {
+ if (m_subtitle_pages.empty())
+ return;
+
+ eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
+
+ pts_t pos = 0;
+
+ if (m_decoder)
+ m_decoder->getPTS(0, pos);
+
+ int diff = p.m_pts - pos;
+ if (diff < 0)
+ {
+ eDebug("[late (%d ms)]", -diff / 90);
+ diff = 0;
+ }
+ if (diff > 900000)
+ {
+ eDebug("[invalid]");
+ diff = 0;
+ }
+
+ if (!diff)
+ {
+ m_subtitle_widget->setPage(p);
+ m_subtitle_pages.pop_front();
+ } else
+ {
+ m_subtitle_sync_timer.start(diff / 90, 1);
+ break;
+ }
+ }
+}
+
DEFINE_REF(eDVBServicePlay)
eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");