X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/f7ff87f985d26835958bb2404265f3029e35c72a..4cdb4528bbff583dc193f24508157e96a0d95c59:/lib/service/servicedvb.cpp diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index d1cc4ef8..c3bd1e69 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -11,10 +11,24 @@ #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); @@ -235,6 +249,9 @@ 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 +686,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 +742,7 @@ RESULT eDVBServicePlay::setFastForward(int ratio) { skipmode = 0; ffratio = 0; - } else if (ratio < 0) + } else // if (ratio < 0) { skipmode = ratio; ffratio = 1; @@ -708,7 +765,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 +775,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 +837,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 +862,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 +883,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 +914,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 +1152,26 @@ int eDVBServicePlay::getFrontendInfo(int w) return fe->readFrontendData(w); } +PyObject *eDVBServicePlay::getFrontendTransponderData() +{ + PyObject *ret=0; + + eUsePtr channel; + if(!m_service_handler.getChannel(channel)) + { + ePtr fe; + if(!channel->getFrontend(fe)) + ret = fe->readTransponderData(); + } + + if (!ret) + { + ret = Py_None; + Py_INCREF(ret); + } + return ret; +} + int eDVBServicePlay::getNumberOfSubservices() { ePtr evt; @@ -1085,7 +1209,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 +1244,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 +1269,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 +1507,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");