#include <lib/dvb/db.h>
#include <lib/dvb/decoder.h>
+#include <lib/components/file_eraser.h>
#include <lib/service/servicedvbrecord.h>
+#include <lib/service/event.h>
#include <lib/dvb/metaparser.h>
#include <lib/dvb/tstools.h>
#include <lib/python/python.h>
#include <byteswap.h>
#include <netinet/in.h>
+#include <dvbsi++/event_information_section.h>
+
#ifndef BYTE_ORDER
#error no byte order defined!
#endif
{
case iServiceInformation::sDescription:
return iServiceInformation::resIsString;
+ case iServiceInformation::sServiceref:
+ return iServiceInformation::resIsString;
case iServiceInformation::sTimeCreate:
if (m_parser.m_time_create)
return m_parser.m_time_create;
{
case iServiceInformation::sDescription:
return m_parser.m_description;
+ case iServiceInformation::sServiceref:
+ return m_parser.m_ref.toString();
default:
return "";
}
if (getListOfFilenames(res))
return -1;
+ eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
+ if (!eraser)
+ eDebug("FATAL !! can't get background file eraser");
+
/* TODO: deferred removing.. */
for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
{
eDebug("Removing %s...", i->c_str());
- ::unlink(i->c_str());
+ if (eraser)
+ eraser->erase(i->c_str());
+ else
+ ::unlink(i->c_str());
}
return 0;
{
res.clear();
res.push_back(m_ref.path);
+
+// handling for old splitted recordings (enigma 1)
+ char buf[255];
+ int slice=1;
+ while(true)
+ {
+ snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
+ struct stat s;
+ if (stat(buf, &s) < 0)
+ break;
+ res.push_back(buf);
+ }
+
res.push_back(m_ref.path + ".meta");
res.push_back(m_ref.path + ".ap");
res.push_back(m_ref.path + ".cuts");
+ std::string tmp = m_ref.path;
+ tmp.erase(m_ref.path.length()-3);
+ res.push_back(tmp + ".eit");
return 0;
}
eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
m_reference(ref), m_dvb_service(service), m_is_paused(0)
{
- m_is_pvr = !ref.path.empty();
+ m_is_primary = 1;
+ m_is_pvr = !m_reference.path.empty();
m_timeshift_enabled = m_timeshift_active = 0;
m_skipmode = 0;
CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
m_cuesheet_changed = 0;
-
- if (m_is_pvr)
- loadCuesheet();
+ m_cutlist_enabled = 1;
}
eDVBServicePlay::~eDVBServicePlay()
if (m_timeshift_active)
updateDecoder();
break;
+ case eDVBServicePMTHandler::eventSOF:
+ m_event((iPlayableService*)this, evSOF);
+ break;
case eDVBServicePMTHandler::eventEOF:
switchToLive();
break;
/* 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. */
- m_cue = new eCueSheet();
+ if (m_is_pvr)
+ m_cue = new eCueSheet();
+
m_first_program_info = 1;
- r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr, m_cue);
+ eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
+ r = m_service_handler.tune(service, m_is_pvr, m_cue);
+
+ /* inject EIT if there is a stored one */
+ if (m_is_pvr)
+ {
+ std::string filename = service.path;
+ filename.erase(filename.length()-2, 2);
+ filename+="eit";
+ int fd = ::open( filename.c_str(), O_RDONLY );
+ if ( fd > -1 )
+ {
+ __u8 buf[4096];
+ int rd = ::read(fd, buf, 4096);
+ ::close(fd);
+ if ( rd > 12 /*EIT_LOOP_SIZE*/ )
+ {
+ Event ev(buf);
+ ePtr<eServiceEvent> event = new eServiceEvent;
+ ePtr<eServiceEvent> empty;
+ event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
+ m_event_handler.inject(event, 0);
+ m_event_handler.inject(empty, 1);
+ eDebug("injected");
+ }
+ }
+ }
+
+ if (m_is_pvr)
+ loadCuesheet();
+
m_event(this, evStart);
m_event((iPlayableService*)this, evSeekableStatusChanged);
return 0;
return 0;
}
+RESULT eDVBServicePlay::setTarget(int target)
+{
+ m_is_primary = !target;
+ return 0;
+}
+
RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
{
connection = new eConnection((iPlayableService*)this, m_event.connect(event));
if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
return -1;
+ int mode = 1;
+
+ /* HACK until we have skip-AP api */
+ if ((to > 0) && (to < 100))
+ mode = 2;
+
to *= direction;
if (!m_cue)
return 0;
- m_cue->seekTo(1, to);
+ m_cue->seekTo(mode, to);
return 0;
}
{
eDVBServicePMTHandler::program program;
+ if (w == sCAIDs)
+ return resIsPyObject;
+
if (m_service_handler.getProgramInfo(program))
return -1;
}
std::string eDVBServicePlay::getInfoString(int w)
-{
+{
switch (w)
{
case sProvider:
if (!m_dvb_service) return "";
return m_dvb_service->m_provider_name;
default:
- return "";
+ break;
}
+ return iServiceInformation::getInfoString(w);
+}
+
+PyObject *eDVBServicePlay::getInfoObject(int w)
+{
+ switch (w)
+ {
+ case sCAIDs:
+ if (m_dvb_service)
+ return m_service_handler.getCaIds();
+ default:
+ break;
+ }
+ return iServiceInformation::getInfoObject(w);
}
int eDVBServicePlay::getNumberOfTracks()
return fe->readFrontendData(w);
}
+PyObject *eDVBServicePlay::getFrontendData(bool original)
+{
+ PyObject *ret=0;
+
+ eUsePtr<iDVBChannel> channel;
+ if(!m_service_handler.getChannel(channel))
+ {
+ ePtr<iDVBFrontend> fe;
+ if(!channel->getFrontend(fe))
+ {
+ ret = fe->readTransponderData(original);
+ if (ret)
+ {
+ ePtr<iDVBFrontendParameters> feparm;
+ channel->getCurrentFrontendParameters(feparm);
+ if (feparm)
+ {
+ eDVBFrontendParametersSatellite osat;
+ if (!feparm->getDVBS(osat))
+ {
+ void PutToDict(PyObject *, const char*, long);
+ void PutToDict(PyObject *, const char*, const char*);
+ PutToDict(ret, "orbital_position", osat.orbital_position);
+ const char *tmp = "UNKNOWN";
+ switch(osat.polarisation)
+ {
+ case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
+ case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
+ case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
+ case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
+ default:break;
+ }
+ PutToDict(ret, "polarization", tmp);
+ }
+ }
+ }
+ }
+ }
+ if (!ret)
+ {
+ ret = Py_None;
+ Py_INCREF(ret);
+ }
+ return ret;
+}
+
int eDVBServicePlay::getNumberOfSubservices()
{
ePtr<eServiceEvent> evt;
}
m_cuesheet_changed = 1;
+ cutlistToCuesheet();
m_event((iPlayableService*)this, evCuesheetChanged);
}
+void eDVBServicePlay::setCutListEnable(int enable)
+{
+ m_cutlist_enabled = enable;
+ cutlistToCuesheet();
+}
+
void eDVBServicePlay::updateTimeshiftPids()
{
if (!m_record)
if (!m_timeshift_active)
return;
+ m_cue = 0;
m_decoder = 0;
m_decode_demux = 0;
/* free the timeshift service handler, we need the resources */
eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
r.path = m_timeshift_file;
+ m_cue = new eCueSheet();
m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
+ updateDecoder(); /* mainly to switch off PCR */
}
void eDVBServicePlay::updateDecoder()
{
h.getDecodeDemux(m_decode_demux);
if (m_decode_demux)
- m_decode_demux->getMPEGDecoder(m_decoder);
+ m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
if (m_cue)
m_cue->setDecodingDemux(m_decode_demux, m_decoder);
}
m_decoder->setVideoPID(vpid);
m_current_audio_stream = 0;
m_decoder->setAudioPID(apid, apidtype);
- if (!(m_is_pvr || m_timeshift_active))
+ if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
m_decoder->setSyncPCR(pcrpid);
else
m_decoder->setSyncPCR(-1);
m_decoder->setTextPID(tpid);
+ if (!m_is_primary)
+ m_decoder->setTrickmode(1);
m_decoder->start();
// how we can do this better?
// update cache pid when the user changed the audio track or video track
eDebug("cutfile not found!");
m_cuesheet_changed = 0;
+ cutlistToCuesheet();
m_event((iPlayableService*)this, evCuesheetChanged);
}
m_cuesheet_changed = 0;
}
+void eDVBServicePlay::cutlistToCuesheet()
+{
+ if (!m_cue)
+ {
+ eDebug("no cue sheet");
+ return;
+ }
+ m_cue->clear();
+
+ if (!m_cutlist_enabled)
+ {
+ m_cue->commitSpans();
+ eDebug("cutlists where disabled");
+ return;
+ }
+
+ pts_t in = 0, out = 0, length = 0;
+
+ getLength(length);
+
+ std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
+
+ while (1)
+ {
+ if (i == m_cue_entries.end())
+ out = length;
+ else {
+ if (i->what == 0) /* in */
+ {
+ in = i++->where;
+ continue;
+ } else if (i->what == 1) /* out */
+ out = i++->where;
+ else /* mark */
+ {
+ i++;
+ continue;
+ }
+ }
+
+ if (in != out)
+ m_cue->addSourceSpan(in, out);
+
+ in = length;
+
+ if (i == m_cue_entries.end())
+ break;
+ }
+ m_cue->commitSpans();
+}
+
DEFINE_REF(eDVBServicePlay)
eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");