X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/f7ff87f985d26835958bb2404265f3029e35c72a..159a405b6c4eebe49e69b595310657ceda406c1c:/lib/service/servicedvb.cpp diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index d1cc4ef8..94c31b4f 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -10,11 +10,26 @@ #include #include +#include #include +#include #include #include #include +#include + +#include +#include + +#include + +#ifndef BYTE_ORDER +#error no byte order defined! +#endif + +#define TSPATH "/media/hdd" + class eStaticServiceDVBInformation: public iStaticServiceInformation { DECLARE_REF(eStaticServiceDVBInformation); @@ -171,6 +186,8 @@ int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w { 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; @@ -187,6 +204,8 @@ std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReferen { case iServiceInformation::sDescription: return m_parser.m_description; + case iServiceInformation::sServiceref: + return m_parser.m_ref.toString(); default: return ""; } @@ -219,11 +238,18 @@ RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate) 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::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; @@ -234,7 +260,25 @@ RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list -1 ) + { + __u8 buf[4096]; + int rd = ::read(fd, buf, 4096); + ::close(fd); + if ( rd > 12 /*EIT_LOOP_SIZE*/ ) + { + Event ev(buf); + ePtr event = new eServiceEvent; + ePtr 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; @@ -628,14 +716,13 @@ RESULT eDVBServicePlay::start() RESULT eDVBServicePlay::stop() { - eDebug("stop timeshift"); stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */ - - eDebug("free ts handler"); + m_service_handler_timeshift.free(); - eDebug("stop service handler"); m_service_handler.free(); - eDebug("ok"); + + if (m_is_pvr && m_cuesheet_changed) + saveCuesheet(); return 0; } @@ -685,7 +772,7 @@ RESULT eDVBServicePlay::setFastForward(int ratio) { skipmode = 0; ffratio = 0; - } else if (ratio < 0) + } else // if (ratio < 0) { skipmode = ratio; ffratio = 1; @@ -708,7 +795,7 @@ RESULT eDVBServicePlay::setFastForward(int ratio) RESULT eDVBServicePlay::seek(ePtr &ptr) { - if (m_is_pvr || m_timeshift_active) + if (m_is_pvr || m_timeshift_enabled) { ptr = this; return 0; @@ -718,15 +805,13 @@ RESULT eDVBServicePlay::seek(ePtr &ptr) return -1; } + /* TODO: when timeshift is enabled but not active, this doesn't work. */ RESULT eDVBServicePlay::getLength(pts_t &len) { ePtr pvr_channel; - if (m_service_handler.getPVRChannel(pvr_channel)) - { - eDebug("getPVRChannel failed!"); + if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel)) return -1; - } return pvr_channel->getLength(len); } @@ -782,12 +867,18 @@ RESULT eDVBServicePlay::seekRelative(int direction, pts_t to) 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; } @@ -801,7 +892,18 @@ RESULT eDVBServicePlay::getPlayPosition(pts_t &pos) if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel)) return -1; - return pvr_channel->getCurrentPosition(m_decode_demux, pos, 1); + int r = 0; + + /* if there is a decoder, use audio or video PTS */ + if (m_decoder) + { + r = m_decoder->getPTS(0, pos); + if (r) + return r; + } + + /* fixup */ + return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0); } RESULT eDVBServicePlay::setTrickmode(int trick) @@ -811,6 +913,11 @@ RESULT eDVBServicePlay::setTrickmode(int trick) return 0; } +RESULT eDVBServicePlay::isCurrentlySeekable() +{ + return m_is_pvr || m_timeshift_active; +} + RESULT eDVBServicePlay::frontendStatusInfo(ePtr &ptr) { ptr = this; @@ -837,7 +944,34 @@ RESULT eDVBServicePlay::subServices(ePtr &ptr) RESULT eDVBServicePlay::timeshift(ePtr &ptr) { + ptr = 0; if (m_timeshift_enabled || !m_is_pvr) + { + if (!m_timeshift_enabled) + { + /* we need enough diskspace */ + struct statfs fs; + if (statfs(TSPATH "/.", &fs) < 0) + { + eDebug("statfs failed!"); + return -2; + } + + if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL) + { + eDebug("not enough diskspace for timeshift! (less than 1GB)"); + return -3; + } + } + ptr = this; + return 0; + } + return -1; +} + +RESULT eDVBServicePlay::cueSheet(ePtr &ptr) +{ + if (m_is_pvr) { ptr = this; return 0; @@ -1048,6 +1182,52 @@ int eDVBServicePlay::getFrontendInfo(int w) return fe->readFrontendData(w); } +PyObject *eDVBServicePlay::getFrontendData(bool original) +{ + PyObject *ret=0; + + eUsePtr channel; + if(!m_service_handler.getChannel(channel)) + { + ePtr fe; + if(!channel->getFrontend(fe)) + { + ret = fe->readTransponderData(original); + if (ret) + { + ePtr 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 evt; @@ -1085,7 +1265,7 @@ RESULT eDVBServicePlay::startTimeshift() if (!m_record) return -3; - char templ[]="/media/hdd/timeshift.XXXXXX"; + char templ[]=TSPATH "/timeshift.XXXXXX"; m_timeshift_fd = mkstemp(templ); m_timeshift_file = templ; @@ -1120,6 +1300,7 @@ RESULT eDVBServicePlay::stopTimeshift() m_record = 0; close(m_timeshift_fd); + eDebug("remove timeshift file"); remove(m_timeshift_file.c_str()); return 0; @@ -1144,6 +1325,67 @@ RESULT eDVBServicePlay::activateTimeshift() return -2; } +PyObject *eDVBServicePlay::getCutList() +{ + PyObject *list = PyList_New(0); + + for (std::multiset::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i) + { + PyObject *tuple = PyTuple_New(2); + PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where)); + PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what)); + PyList_Append(list, tuple); + Py_DECREF(tuple); + } + + return list; +} + +void eDVBServicePlay::setCutList(PyObject *list) +{ + if (!PyList_Check(list)) + return; + int size = PyList_Size(list); + int i; + + m_cue_entries.clear(); + + for (i=0; igetMPEGDecoder(m_decoder); if (m_cue) - m_cue->setDecodingDemux(m_decode_demux); + m_cue->setDecodingDemux(m_decode_demux, m_decoder); } if (m_decoder) @@ -1321,6 +1564,127 @@ void eDVBServicePlay::updateDecoder() } } +void eDVBServicePlay::loadCuesheet() +{ + std::string filename = m_reference.path + ".cuts"; + + m_cue_entries.clear(); + + FILE *f = fopen(filename.c_str(), "rb"); + + if (f) + { + eDebug("loading cuts.."); + while (1) + { + unsigned long long where; + unsigned int what; + + if (!fread(&where, sizeof(where), 1, f)) + break; + if (!fread(&what, sizeof(what), 1, f)) + break; + +#if BYTE_ORDER == LITTLE_ENDIAN + where = bswap_64(where); +#endif + what = ntohl(what); + + if (what > 2) + break; + + m_cue_entries.insert(cueEntry(where, what)); + } + fclose(f); + eDebug("%d entries", m_cue_entries.size()); + } else + eDebug("cutfile not found!"); + + m_cuesheet_changed = 0; + cutlistToCuesheet(); + m_event((iPlayableService*)this, evCuesheetChanged); +} + +void eDVBServicePlay::saveCuesheet() +{ + std::string filename = m_reference.path + ".cuts"; + + FILE *f = fopen(filename.c_str(), "wb"); + + if (f) + { + unsigned long long where; + int what; + + for (std::multiset::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i) + { +#if BYTE_ORDER == BIG_ENDIAN + where = i->where; +#else + where = bswap_64(i->where); +#endif + what = htonl(i->what); + fwrite(&where, sizeof(where), 1, f); + fwrite(&what, sizeof(what), 1, f); + + } + fclose(f); + } + + 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::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 init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");