From: ghost Date: Mon, 29 Nov 2010 22:18:14 +0000 (+0100) Subject: Merge branch 'bug_624_change_handylike_char_input' into experimental X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=commitdiff_plain;h=f45bc033d3b701f2eee0a435d6b4f8d450455cda;hp=d8c5bdb00212706b1dc07a746a14e895f5df8811 Merge branch 'bug_624_change_handylike_char_input' into experimental --- diff --git a/configure.ac b/configure.ac index 48fea64..605431b 100644 --- a/configure.ac +++ b/configure.ac @@ -86,8 +86,8 @@ if test "$with_memcheck" = "yes"; then fi AC_ARG_WITH(po, - AS_HELP_STRING([--without-po],[disable updating of po files]), - [with_po="$withval"],[with_po="yes"]) + AS_HELP_STRING([--with-po],[enable updating of po files]), + [with_po="$withval"],[with_po="no"]) AM_CONDITIONAL(UPDATE_PO, test "$with_po" = "yes") CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS" diff --git a/data/setup.xml b/data/setup.xml index f5dea73..c5eb07f 100755 --- a/data/setup.xml +++ b/data/setup.xml @@ -47,27 +47,10 @@ config.seek.speeds_forward config.seek.speeds_backward config.seek.speeds_slowmotion - - config.seek.enter_forward - config.seek.enter_backward - - config.seek.stepwise_minspeed - config.seek.stepwise_repeat + + config.seek.enter_forward + config.seek.enter_backward config.seek.on_pause config.usage.pip_zero_button config.usage.alternatives_priority diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index 88cd3ee..8ed9f43 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -203,6 +203,9 @@ int eDVBAudio::startPid(int pid, int type) case aLPCM: bypass = 6; break; + case aDTSHD: + bypass = 0x10; + break; } eDebugNoNewLine("AUDIO_SET_BYPASS(%d) - ", bypass); diff --git a/lib/dvb/decoder.h b/lib/dvb/decoder.h index 3a0fbac..7610b65 100644 --- a/lib/dvb/decoder.h +++ b/lib/dvb/decoder.h @@ -13,7 +13,7 @@ private: ePtr m_demux; int m_fd, m_fd_demux, m_dev, m_is_freezed; public: - enum { aMPEG, aAC3, aDTS, aAAC, aAACHE, aLPCM }; + enum { aMPEG, aAC3, aDTS, aAAC, aAACHE, aLPCM, aDTSHD }; eDVBAudio(eDVBDemux *demux, int dev); enum { aMonoLeft, aStereo, aMonoRight }; void setChannel(int channel); diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h index f15cd04..e56a2c7 100644 --- a/lib/dvb/idvb.h +++ b/lib/dvb/idvb.h @@ -650,7 +650,7 @@ public: /** Set Displayed Video PID and type */ virtual RESULT setVideoPID(int vpid, int type)=0; - enum { af_MPEG, af_AC3, af_DTS, af_AAC }; + enum { af_MPEG, af_AC3, af_DTS, af_AAC, af_DTSHD }; /** Set Displayed Audio PID and type */ virtual RESULT setAudioPID(int apid, int type)=0; diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index 46fa12e..d673384 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -131,6 +131,8 @@ void eDVBServicePMTHandler::PATready(int) ePtr > ptr; if (!m_PAT.getCurrent(ptr)) { + int service_id_single = -1; + int pmtpid_single = -1; int pmtpid = -1; std::vector::const_iterator i; for (i = ptr->getSections().begin(); pmtpid == -1 && i != ptr->getSections().end(); ++i) @@ -138,8 +140,22 @@ void eDVBServicePMTHandler::PATready(int) const ProgramAssociationSection &pat = **i; ProgramAssociationConstIterator program; for (program = pat.getPrograms()->begin(); pmtpid == -1 && program != pat.getPrograms()->end(); ++program) + { if (eServiceID((*program)->getProgramNumber()) == m_reference.getServiceID()) pmtpid = (*program)->getProgramMapPid(); + if (pmtpid_single == -1 && pmtpid == -1) + { + pmtpid_single = (*program)->getProgramMapPid(); + service_id_single = (*program)->getProgramNumber(); + } + else + pmtpid_single = service_id_single = -1; + } + } + if (pmtpid_single != -1) // only one PAT entry .. so we use this one + { + m_reference.setServiceID(eServiceID(service_id_single)); + pmtpid = pmtpid_single; } if (pmtpid == -1) serviceEvent(eventNoPATEntry); @@ -149,7 +165,7 @@ void eDVBServicePMTHandler::PATready(int) serviceEvent(eventNoPAT); } -PyObject *eDVBServicePMTHandler::getCaIds() +PyObject *eDVBServicePMTHandler::getCaIds(bool pair) { ePyObject ret; @@ -157,20 +173,37 @@ PyObject *eDVBServicePMTHandler::getCaIds() if ( !getProgramInfo(prog) ) { - int cnt=prog.caids.size(); - if (cnt) + if (pair) { + int cnt=prog.caids.size(); + if (cnt) + { + ret=PyList_New(cnt); + std::list::iterator it(prog.caids.begin()); + while(cnt--) + { + ePyObject tuple = PyTuple_New(2); + PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(it->caid)); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((it++)->capid)); + PyList_SET_ITEM(ret, cnt, tuple); + } + } + } + else + { + std::set set(prog.caids.begin(), prog.caids.end()); + std::set::iterator it(set.begin()); + int cnt=set.size(); ret=PyList_New(cnt); - std::set::iterator it(prog.caids.begin()); while(cnt--) - PyList_SET_ITEM(ret, cnt, PyInt_FromLong(*it++)); + PyList_SET_ITEM(ret, cnt, PyInt_FromLong((it++)->caid)); } } return ret ? (PyObject*)ret : (PyObject*)PyList_New(0); } -int eDVBServicePMTHandler::getProgramInfo(struct program &program) +int eDVBServicePMTHandler::getProgramInfo(program &program) { ePtr > ptr; int cached_apid_ac3 = -1; @@ -213,8 +246,29 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i) { const ProgramMapSection &pmt = **i; + int is_hdmv = 0; + program.pcrPid = pmt.getPcrPid(); + for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); + desc != pmt.getDescriptors()->end(); ++desc) + { + if ((*desc)->getTag() == CA_DESCRIPTOR) + { + CaDescriptor *descr = (CaDescriptor*)(*desc); + program::capid_pair pair; + pair.caid = descr->getCaSystemId(); + pair.capid = descr->getCaPid(); + program.caids.push_back(pair); + } + else if ((*desc)->getTag() == REGISTRATION_DESCRIPTOR) + { + RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc); + if (d->getFormatIdentifier() == 0x48444d56) // HDMV + is_hdmv = 1; + } + } + ElementaryStreamInfoConstIterator es; for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es) { @@ -270,25 +324,34 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) audio.type = audioStream::atAACHE; forced_audio = 1; } - case 0x80: // user private ... but blueray LPCM - if (!isvideo && !isaudio) + case 0x80: // user private ... but bluray LPCM + case 0xA0: // bluray secondary LPCM + if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atLPCM; } - case 0x81: // user private ... but blueray AC3 - if (!isvideo && !isaudio) + case 0x81: // user private ... but bluray AC3 + case 0xA1: // bluray secondary AC3 + if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atAC3; } - case 0x82: // Blueray DTS (dvb user private...) - case 0xA2: // Blueray secondary DTS - if (!isvideo && !isaudio) + case 0x82: // bluray DTS (dvb user private...) + case 0xA2: // bluray secondary DTS + if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atDTS; } + case 0x86: // bluray DTS-HD (dvb user private...) + case 0xA6: // bluray secondary DTS-HD + if (!isvideo && !isaudio && is_hdmv) + { + isaudio = 1; + audio.type = audioStream::atDTSHD; + } case 0x06: // PES Private case 0xEA: // TS_PSI_ST_SMPTE_VC1 { @@ -460,7 +523,10 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) case CA_DESCRIPTOR: { CaDescriptor *descr = (CaDescriptor*)(*desc); - program.caids.insert(descr->getCaSystemId()); + program::capid_pair pair; + pair.caid = descr->getCaSystemId(); + pair.capid = descr->getCaPid(); + program.caids.push_back(pair); break; } default: @@ -477,9 +543,9 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) default: break; } - if (isteletext && (isaudio || isvideo)) + if (isteletext && (isaudio || isvideo)) { - eDebug("ambiguous streamtype for PID %04x detected.. forced as teletext!", (*es)->getPid()); + eDebug("ambiguous streamtype for PID %04x detected.. forced as teletext!", (*es)->getPid()); continue; // continue with next PID } else if (issubtitle && (isaudio || isvideo)) @@ -517,15 +583,6 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) else continue; } - for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); - desc != pmt.getDescriptors()->end(); ++desc) - { - if ((*desc)->getTag() == CA_DESCRIPTOR) - { - CaDescriptor *descr = (CaDescriptor*)(*desc); - program.caids.insert(descr->getCaSystemId()); - } - } } ret = 0; @@ -589,8 +646,12 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) program.textPid = cached_tpid; } CAID_LIST &caids = m_service->m_ca; - for (CAID_LIST::iterator it(caids.begin()); it != caids.end(); ++it) - program.caids.insert(*it); + for (CAID_LIST::iterator it(caids.begin()); it != caids.end(); ++it) { + program::capid_pair pair; + pair.caid = *it; + pair.capid = -1; // not known yet + program.caids.push_back(pair); + } if ( cnt ) ret = 0; } @@ -708,13 +769,12 @@ int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_dem { if (!ref.getServiceID().get() /* incorrect sid in meta file or recordings.epl*/ ) { - eWarning("no .meta file found, trying to find PMT pid"); eDVBTSTools tstools; + bool b = source || !tstools.openFile(ref.path.c_str(), 1); + eWarning("no .meta file found, trying to find PMT pid"); if (source) - tstools.setSource(source, streaminfo_file ? streaminfo_file : ref.path.c_str()); - else if (tstools.openFile(ref.path.c_str())) - eWarning("failed to open file"); - else + tstools.setSource(source, NULL); + if (b) { int service_id, pmt_pid; if (!tstools.findPMT(pmt_pid, service_id)) @@ -724,6 +784,8 @@ int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_dem m_pmt_pid = pmt_pid; } } + else + eWarning("no valid source to find PMT pid!"); } eDebug("alloc PVR"); /* allocate PVR */ diff --git a/lib/dvb/pmt.h b/lib/dvb/pmt.h index de0de05..aa5d34d 100644 --- a/lib/dvb/pmt.h +++ b/lib/dvb/pmt.h @@ -144,7 +144,7 @@ public: { int pid, rdsPid; // hack for some radio services which transmit radiotext on different pid (i.e. harmony fm, HIT RADIO FFH, ...) - enum { atMPEG, atAC3, atDTS, atAAC, atAACHE, atLPCM }; + enum { atMPEG, atAC3, atDTS, atAAC, atAACHE, atLPCM, atDTSHD }; int type; // mpeg2, ac3, dts, ... int component_tag; @@ -181,11 +181,17 @@ public: struct program { + struct capid_pair + { + uint16_t caid; + int capid; + bool operator< (const struct capid_pair &t) { return t.caid < caid; } + }; std::vector videoStreams; std::vector audioStreams; int defaultAudioStream; std::vector subtitleStreams; - std::set caids; + std::list caids; int pcrPid; int pmtPid; int textPid; @@ -193,10 +199,10 @@ public: PyObject *createPythonObject(); }; - int getProgramInfo(struct program &program); + int getProgramInfo(program &program); int getDataDemux(ePtr &demux); int getDecodeDemux(ePtr &demux); - PyObject *getCaIds(); + PyObject *getCaIds(bool pair=false); // caid / ecmpid pair int getPVRChannel(ePtr &pvr_channel); int getServiceReference(eServiceReferenceDVB &service) { service = m_reference; return 0; } diff --git a/lib/dvb/pvrparse.cpp b/lib/dvb/pvrparse.cpp index 5cdecbd..e19dd1e 100644 --- a/lib/dvb/pvrparse.cpp +++ b/lib/dvb/pvrparse.cpp @@ -123,7 +123,7 @@ void eMPEGStreamInformation::fixupDiscontinuties() pts_t current = i->second - currentDelta; pts_t diff = current - lastpts_t; - if (llabs(diff) > (90000*5)) // 5sec diff + if (llabs(diff) > (90000*10)) // 10sec diff { // eDebug("%llx < %llx, have discont. new timestamp is %llx (diff is %llx)!", current, lastpts_t, i->second, diff); currentDelta = i->second - lastpts_t; /* FIXME: should be the extrapolated new timestamp, based on the current rate */ diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index 1403059..3dff288 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -212,6 +212,8 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed) break; case 0x71: // AC3 / DTS break; + case 0x72: // DTS - HD + break; default: eDebug("skip unknwn stream_id_extension %02x\n", payload[9+offs]); continue; @@ -700,9 +702,23 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram else if (direction == +1) direction = 0; } - /* let's find the next frame after the given offset */ off_t start = offset; + /* backtrack to find the previous sequence start, in case of MPEG2 */ + if ((data & 0xFF) == 0x00) { + do { + --start; + if (m_streaminfo.getStructureEntry(start, data, 0)) + { + eDebug("get previous failed"); + return -1; + } + } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00) && ((data & 0xFF) != 0xB3)); /* sequence start or previous frame */ + if ((data & 0xFF) != 0xB3) + start = offset; /* Failed to find corresponding sequence start, so never mind */ + } + + /* let's find the next frame after the given offset */ do { if (m_streaminfo.getStructureEntry(offset, data, 1)) { @@ -718,8 +734,8 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00)); /* next frame */ /* align to TS pkt start */ -// start = start - (start % 188); -// offset = offset - (offset % 188); + start = start - (start % 188); + offset = offset - (offset % 188); len = offset - start; _offset = start; diff --git a/lib/dvb_ci/dvbci.cpp b/lib/dvb_ci/dvbci.cpp index 883fb5a..8a43e5b 100644 --- a/lib/dvb_ci/dvbci.cpp +++ b/lib/dvb_ci/dvbci.cpp @@ -297,8 +297,9 @@ void eDVBCIInterfaces::recheckPMTHandlers() if (!pmthandler->getProgramInfo(p)) { int cnt=0; - for (caidSet::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt) - caids.push_front(*x); + std::set set(p.caids.begin(), p.caids.end()); + for (std::set::reverse_iterator x(set.rbegin()); x != set.rend(); ++x, ++cnt) + caids.push_front(x->caid); if (service && cnt) service->m_ca = caids; } diff --git a/lib/gui/epositiongauge.cpp b/lib/gui/epositiongauge.cpp index ff98c08..e45d4a6 100644 --- a/lib/gui/epositiongauge.cpp +++ b/lib/gui/epositiongauge.cpp @@ -112,6 +112,7 @@ int ePositionGauge::event(int event, void *data, void *data2) // painter.fill(eRect(0, 10, s.width(), s.height()-20)); pts_t in = 0, out = 0; + int xm, xm_last = -1; std::multiset::iterator i(m_cue_entries.begin()); @@ -126,17 +127,22 @@ int ePositionGauge::event(int event, void *data, void *data2) continue; } else if (i->what == 1) /* out */ out = i++->where; - else if (i->what == 2) /* mark */ + else /* mark or last */ { - int xm = scale(i->where); - painter.setForegroundColor(gRGB(0xFF8080)); - painter.fill(eRect(xm - 2, 0, 4, s.height())); + xm = scale(i->where); + if (i->what == 2) { + painter.setForegroundColor(gRGB(0xFF8080)); + if (xm - 2 < xm_last) /* Make sure last is not overdrawn */ + painter.fill(eRect(xm_last, 0, 2 + xm - xm_last, s.height())); + else + painter.fill(eRect(xm - 2, 0, 4, s.height())); + } else if (i->what == 3) { + painter.setForegroundColor(gRGB(0x80FF80)); + painter.fill(eRect(xm - 1, 0, 3, s.height())); + xm_last = xm + 2; + } i++; continue; - } else /* other marker, like last position */ - { - ++i; - continue; } } diff --git a/lib/python/Components/FileList.py b/lib/python/Components/FileList.py index 1d71514..1b7e81f 100755 --- a/lib/python/Components/FileList.py +++ b/lib/python/Components/FileList.py @@ -28,7 +28,8 @@ EXTENSIONS = { "mpeg": "movie", "mkv": "movie", "mp4": "movie", - "mov": "movie" + "mov": "movie", + "m2ts": "movie", } def FileEntryComponent(name, absolute = None, isDir = False): diff --git a/lib/python/Components/UsageConfig.py b/lib/python/Components/UsageConfig.py index 8ea9aa6..a265a16 100644 --- a/lib/python/Components/UsageConfig.py +++ b/lib/python/Components/UsageConfig.py @@ -102,13 +102,11 @@ def InitUsageConfig(): config.seek.selfdefined_79 = ConfigNumber(default=300) config.seek.speeds_forward = ConfigSet(default=[2, 4, 8, 16, 32, 64, 128], choices=[2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128]) - config.seek.speeds_backward = ConfigSet(default=[8, 16, 32, 64, 128], choices=[1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128]) + config.seek.speeds_backward = ConfigSet(default=[2, 4, 8, 16, 32, 64, 128], choices=[1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128]) config.seek.speeds_slowmotion = ConfigSet(default=[2, 4, 8], choices=[2, 4, 6, 8, 12, 16, 25]) config.seek.enter_forward = ConfigSelection(default = "2", choices = ["2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"]) config.seek.enter_backward = ConfigSelection(default = "1", choices = ["1", "2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"]) - config.seek.stepwise_minspeed = ConfigSelection(default = "16", choices = ["Never", "2", "4", "6", "8", "12", "16", "24", "32", "48", "64", "96", "128"]) - config.seek.stepwise_repeat = ConfigSelection(default = "3", choices = ["2", "3", "4", "5", "6"]) config.seek.on_pause = ConfigSelection(default = "play", choices = [ ("play", _("Play")), diff --git a/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py b/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py index 7f755db..6dbcd49 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py +++ b/lib/python/Plugins/Extensions/DVDBurn/DVDProject.py @@ -2,6 +2,7 @@ from Tools.Directories import fileExists from Components.config import config, ConfigSubsection, ConfigInteger, ConfigText, ConfigSelection, getConfigListEntry, ConfigSequence, ConfigSubList import DVDTitle import xml.dom.minidom +from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_FONTS class ConfigColor(ConfigSequence): def __init__(self, default = [128,128,128]): @@ -125,6 +126,14 @@ class DVDProject: for key in self.filekeys: val = self.settings.dict()[key].getValue() if not fileExists(val): + if val[0] != "/": + if key.find("font") == 0: + val = resolveFilename(SCOPE_FONTS)+val + else: + val = resolveFilename(SCOPE_PLUGINS)+"Extensions/DVDBurn/"+val + if fileExists(val): + self.settings.dict()[key].setValue(val) + continue self.error += "\n%s '%s' not found" % (key, val) #except AttributeError: #print "loadProject AttributeError", self.error diff --git a/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVD.ddvdp.xml b/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVD.ddvdp.xml index 451e8a8..4645260 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVD.ddvdp.xml +++ b/lib/python/Plugins/Extensions/DVDBurn/DreamboxDVD.ddvdp.xml @@ -3,11 +3,11 @@ diff --git a/lib/python/Plugins/Extensions/DVDBurn/Text_menu_boat.ddvdm.xml b/lib/python/Plugins/Extensions/DVDBurn/Text_menu_boat.ddvdm.xml index 0de7f4b..bf6356a 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Text_menu_boat.ddvdm.xml +++ b/lib/python/Plugins/Extensions/DVDBurn/Text_menu_boat.ddvdm.xml @@ -3,17 +3,17 @@ = int(minspeed) and repeat > 1: -# return (0, n * repeat, repeat, ">> %dx" % n) -# else: - return (0, n, 0, ">> %dx" % n) + return (0, n, 0, ">> %dx" % n) def makeStateBackward(self, n): -# minspeed = config.seek.stepwise_minspeed.value -# repeat = int(config.seek.stepwise_repeat.value) -# if minspeed != "Never" and n >= int(minspeed) and repeat > 1: -# return (0, -n * repeat, repeat, "<< %dx" % n) -# else: - return (0, -n, 0, "<< %dx" % n) + return (0, -n, 0, "<< %dx" % n) def makeStateSlowMotion(self, n): return (0, 0, n, "/%d" % n) @@ -1970,20 +1960,21 @@ class InfoBarCueSheetSupport: return True def jumpPreviousMark(self): - # we add 2 seconds, so if the play position is <2s after + # we add 5 seconds, so if the play position is <5s after # the mark, the mark before will be used self.jumpPreviousNextMark(lambda x: -x-5*90000, start=True) def jumpNextMark(self): - if not self.jumpPreviousNextMark(lambda x: x): + if not self.jumpPreviousNextMark(lambda x: x-90000): self.doSeek(-1) def getNearestCutPoint(self, pts, cmp=abs, start=False): # can be optimized - beforecut = False + beforecut = True nearest = None + bestdiff = -1 + instate = True if start: - beforecut = True bestdiff = cmp(0 - pts) if bestdiff >= 0: nearest = [0, False] @@ -1992,14 +1983,19 @@ class InfoBarCueSheetSupport: beforecut = False if cp[1] == self.CUT_TYPE_IN: # Start is here, disregard previous marks diff = cmp(cp[0] - pts) - if diff >= 0: + if start and diff >= 0: nearest = cp bestdiff = diff else: nearest = None - if cp[1] in (self.CUT_TYPE_MARK, self.CUT_TYPE_LAST): + bestdiff = -1 + if cp[1] == self.CUT_TYPE_IN: + instate = True + elif cp[1] == self.CUT_TYPE_OUT: + instate = False + elif cp[1] in (self.CUT_TYPE_MARK, self.CUT_TYPE_LAST): diff = cmp(cp[0] - pts) - if diff >= 0 and (nearest is None or bestdiff > diff): + if instate and diff >= 0 and (nearest is None or bestdiff > diff): nearest = cp bestdiff = diff return nearest diff --git a/lib/service/Makefile.am b/lib/service/Makefile.am index edafd1a..9f956b6 100644 --- a/lib/service/Makefile.am +++ b/lib/service/Makefile.am @@ -16,7 +16,8 @@ libenigma_service_a_SOURCES = \ servicedvb.cpp \ servicedvbrecord.cpp \ servicefs.cpp \ - servicemp3.cpp + servicemp3.cpp \ + servicem2ts.cpp serviceincludedir = $(pkgincludedir)/lib/service serviceinclude_HEADERS = \ @@ -27,7 +28,8 @@ serviceinclude_HEADERS = \ servicedvb.h \ servicedvbrecord.h \ servicefs.h \ - servicemp3.h + servicemp3.h \ + servicem2ts.h if HAVE_LIBXINE libenigma_service_a_SOURCES += \ diff --git a/lib/service/iservice.h b/lib/service/iservice.h index 2ba7cb4..7f58249 100644 --- a/lib/service/iservice.h +++ b/lib/service/iservice.h @@ -289,6 +289,7 @@ public: sFileSize, sCAIDs, + sCAIDPIDs, sVideoType, /* MPEG2 MPEG4 */ sTags, /* space seperated list of tags */ diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index f1858c9..2889ad3 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -1591,7 +1591,7 @@ int eDVBServicePlay::getInfo(int w) { 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; @@ -1732,6 +1732,8 @@ PyObject *eDVBServicePlay::getInfoObject(int w) { case sCAIDs: return m_service_handler.getCaIds(); + case sCAIDPIDs: + return m_service_handler.getCaIds(true); case sTransponderData: return eStaticServiceDVBInformation().getInfoObject(m_reference, w); default: @@ -1799,6 +1801,8 @@ RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int 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 = "???"; diff --git a/lib/service/servicem2ts.cpp b/lib/service/servicem2ts.cpp new file mode 100644 index 0000000..e79907d --- /dev/null +++ b/lib/service/servicem2ts.cpp @@ -0,0 +1,380 @@ +#include +#include +#include +#include + +DEFINE_REF(eServiceFactoryM2TS) + +class eM2TSFile: public iTsSource +{ + DECLARE_REF(eM2TSFile); + eSingleLock m_lock; +public: + eM2TSFile(const char *filename, bool cached=false); + ~eM2TSFile(); + + // iTsSource + off_t lseek(off_t offset, int whence); + ssize_t read(off_t offset, void *buf, size_t count); + off_t length(); + int valid(); +private: + int m_sync_offset; + int m_fd; /* for uncached */ + FILE *m_file; /* for cached */ + off_t m_current_offset, m_length; + bool m_cached; + off_t lseek_internal(off_t offset, int whence); +}; + +class eStaticServiceM2TSInformation: public iStaticServiceInformation +{ + DECLARE_REF(eStaticServiceM2TSInformation); + eServiceReference m_ref; + eDVBMetaParser m_parser; +public: + eStaticServiceM2TSInformation(const eServiceReference &ref); + RESULT getName(const eServiceReference &ref, std::string &name); + int getLength(const eServiceReference &ref); + RESULT getEvent(const eServiceReference &ref, ePtr &SWIG_OUTPUT, time_t start_time); + int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; } + int getInfo(const eServiceReference &ref, int w); + std::string getInfoString(const eServiceReference &ref,int w); + PyObject *getInfoObject(const eServiceReference &r, int what); +}; + +DEFINE_REF(eStaticServiceM2TSInformation); + +eStaticServiceM2TSInformation::eStaticServiceM2TSInformation(const eServiceReference &ref) +{ + m_ref = ref; + m_parser.parseFile(ref.path); +} + +RESULT eStaticServiceM2TSInformation::getName(const eServiceReference &ref, std::string &name) +{ + ASSERT(ref == m_ref); + if (m_parser.m_name.size()) + name = m_parser.m_name; + else + { + name = ref.path; + size_t n = name.rfind('/'); + if (n != std::string::npos) + name = name.substr(n + 1); + } + return 0; +} + +int eStaticServiceM2TSInformation::getLength(const eServiceReference &ref) +{ + ASSERT(ref == m_ref); + + eDVBTSTools tstools; + + struct stat s; + stat(ref.path.c_str(), &s); + + eM2TSFile *file = new eM2TSFile(ref.path.c_str()); + ePtr source = file; + + if (!source->valid()) + return 0; + + tstools.setSource(source); + + /* check if cached data is still valid */ + if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length)) + return m_parser.m_length / 90000; + + /* open again, this time with stream info */ + tstools.setSource(source, ref.path.c_str()); + + /* otherwise, re-calc length and update meta file */ + pts_t len; + if (tstools.calcLen(len)) + return 0; + + m_parser.m_length = len; + m_parser.m_filesize = s.st_size; + m_parser.updateMeta(ref.path); + return m_parser.m_length / 90000; +} + +int eStaticServiceM2TSInformation::getInfo(const eServiceReference &ref, int w) +{ + switch (w) + { + case iServiceInformation::sDescription: + return iServiceInformation::resIsString; + case iServiceInformation::sServiceref: + return iServiceInformation::resIsString; + case iServiceInformation::sFileSize: + return m_parser.m_filesize; + case iServiceInformation::sTimeCreate: + if (m_parser.m_time_create) + return m_parser.m_time_create; + else + return iServiceInformation::resNA; + default: + return iServiceInformation::resNA; + } +} + +std::string eStaticServiceM2TSInformation::getInfoString(const eServiceReference &ref,int w) +{ + switch (w) + { + case iServiceInformation::sDescription: + return m_parser.m_description; + case iServiceInformation::sServiceref: + return m_parser.m_ref.toString(); + case iServiceInformation::sTags: + return m_parser.m_tags; + default: + return ""; + } +} + +PyObject *eStaticServiceM2TSInformation::getInfoObject(const eServiceReference &r, int what) +{ + switch (what) + { + case iServiceInformation::sFileSize: + return PyLong_FromLongLong(m_parser.m_filesize); + default: + Py_RETURN_NONE; + } +} + +RESULT eStaticServiceM2TSInformation::getEvent(const eServiceReference &ref, ePtr &evt, time_t start_time) +{ + if (!ref.path.empty()) + { + ePtr event = new eServiceEvent; + std::string filename = ref.path; + filename.erase(filename.length()-4, 2); + filename+="eit"; + if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get())) + { + evt = event; + return 0; + } + } + evt = 0; + return -1; +} + +DEFINE_REF(eM2TSFile); + +eM2TSFile::eM2TSFile(const char *filename, bool cached) + :m_lock(false), m_sync_offset(0), m_fd(-1), m_file(NULL), m_current_offset(0), m_length(0), m_cached(cached) +{ + if (!m_cached) + m_fd = ::open(filename, O_RDONLY | O_LARGEFILE); + else + m_file = ::fopen64(filename, "rb"); + if (valid()) + m_current_offset = m_length = lseek_internal(0, SEEK_END); +} + +eM2TSFile::~eM2TSFile() +{ + if (m_cached) + { + if (m_file) + { + ::fclose(m_file); + m_file = 0; + } + } + else + { + if (m_fd >= 0) + ::close(m_fd); + m_fd = -1; + } +} + +off_t eM2TSFile::lseek(off_t offset, int whence) +{ + eSingleLocker l(m_lock); + + offset = (offset % 188) + (offset * 192) / 188; + + if (offset != m_current_offset) + m_current_offset = lseek_internal(offset, whence); + + return m_current_offset; +} + +off_t eM2TSFile::lseek_internal(off_t offset, int whence) +{ + off_t ret; + + if (!m_cached) + ret = ::lseek(m_fd, offset, whence); + else + { + if (::fseeko(m_file, offset, whence) < 0) + perror("fseeko"); + ret = ::ftello(m_file); + } + return ret <= 0 ? ret : (ret % 192) + (ret*188) / 192; +} + +ssize_t eM2TSFile::read(off_t offset, void *b, size_t count) +{ + eSingleLocker l(m_lock); + unsigned char tmp[192*3]; + unsigned char *buf = (unsigned char*)b; + + size_t rd=0; + offset = (offset % 188) + (offset * 192) / 188; + +sync: + if ((offset+m_sync_offset) != m_current_offset) + { +// eDebug("seekTo %lld", offset+m_sync_offset); + m_current_offset = lseek_internal(offset+m_sync_offset, SEEK_SET); + if (m_current_offset < 0) + return m_current_offset; + } + + while (rd < count) { + size_t ret; + if (!m_cached) + ret = ::read(m_fd, tmp, 192); + else + ret = ::fread(tmp, 1, 192, m_file); + if (ret < 0 || ret < 192) + return rd ? rd : ret; + + if (tmp[4] != 0x47) + { + if (rd > 0) { + eDebug("short read at pos %lld async!!", m_current_offset); + return rd; + } + else { + int x=0; + if (!m_cached) + ret = ::read(m_fd, tmp+192, 384); + else + ret = ::fread(tmp+192, 1, 384, m_file); + +#if 0 + eDebugNoNewLine("m2ts out of sync at pos %lld, real %lld:", offset + m_sync_offset, m_current_offset); + for (; x < 192; ++x) + eDebugNoNewLine(" %02x", tmp[x]); + eDebug(""); + x=0; +#else + eDebug("m2ts out of sync at pos %lld, real %lld", offset + m_sync_offset, m_current_offset); +#endif + for (; x < 192; ++x) + { + if (tmp[x] == 0x47 && tmp[x+192] == 0x47) + { + int add_offs = (x - 4); + eDebug("sync found at pos %d, sync_offset is now %d, old was %d", x, add_offs + m_sync_offset, m_sync_offset); + m_sync_offset += add_offs; + goto sync; + } + } + } + } + + memcpy(buf+rd, tmp+4, 188); + + rd += 188; + m_current_offset += 188; + } + + m_sync_offset %= 188; + + return rd; +} + +int eM2TSFile::valid() +{ + if (!m_cached) + return m_fd != -1; + else + return !!m_file; +} + +off_t eM2TSFile::length() +{ + return m_length; +} + +eServiceFactoryM2TS::eServiceFactoryM2TS() +{ + ePtr sc; + eServiceCenter::getPrivInstance(sc); + if (sc) + { + std::list extensions; + extensions.push_back("m2ts"); + extensions.push_back("mts"); + sc->addServiceFactory(eServiceFactoryM2TS::id, this, extensions); + } +} + +eServiceFactoryM2TS::~eServiceFactoryM2TS() +{ + ePtr sc; + + eServiceCenter::getPrivInstance(sc); + if (sc) + sc->removeServiceFactory(eServiceFactoryM2TS::id); +} + +RESULT eServiceFactoryM2TS::play(const eServiceReference &ref, ePtr &ptr) +{ + ptr = new eServiceM2TS(ref); + return 0; +} + +RESULT eServiceFactoryM2TS::record(const eServiceReference &ref, ePtr &ptr) +{ + ptr=0; + return -1; +} + +RESULT eServiceFactoryM2TS::list(const eServiceReference &ref, ePtr &ptr) +{ + ptr=0; + return -1; +} + +RESULT eServiceFactoryM2TS::info(const eServiceReference &ref, ePtr &ptr) +{ + ptr=new eStaticServiceM2TSInformation(ref); + return 0; +} + +RESULT eServiceFactoryM2TS::offlineOperations(const eServiceReference &ref, ePtr &ptr) +{ + ptr = 0; + return -1; +} + +eServiceM2TS::eServiceM2TS(const eServiceReference &ref) + :eDVBServicePlay(ref, NULL) +{ +} + +ePtr eServiceM2TS::createTsSource(eServiceReferenceDVB &ref) +{ + ePtr source = new eM2TSFile(ref.path.c_str()); + return source; +} + +RESULT eServiceM2TS::isCurrentlySeekable() +{ + return 1; // for fast winding we need index files... so only skip forward/backward yet +} + +eAutoInitPtr init_eServiceFactoryM2TS(eAutoInitNumbers::service+1, "eServiceFactoryM2TS"); diff --git a/lib/service/servicem2ts.h b/lib/service/servicem2ts.h new file mode 100644 index 0000000..bfa4f7d --- /dev/null +++ b/lib/service/servicem2ts.h @@ -0,0 +1,33 @@ +#ifndef __servicem2ts_h +#define __servicem2ts_h + +#include + +class eServiceFactoryM2TS: public iServiceHandler +{ + DECLARE_REF(eServiceFactoryM2TS); +public: + eServiceFactoryM2TS(); + virtual ~eServiceFactoryM2TS(); + enum { id = 0x3 }; + + // iServiceHandler + RESULT play(const eServiceReference &, ePtr &ptr); + RESULT record(const eServiceReference &, ePtr &ptr); + RESULT list(const eServiceReference &, ePtr &ptr); + RESULT info(const eServiceReference &, ePtr &ptr); + RESULT offlineOperations(const eServiceReference &, ePtr &ptr); +}; + +class eServiceM2TS: public eDVBServicePlay +{ + friend class eServiceFactoryM2TS; +protected: + eServiceM2TS(const eServiceReference &ref); + ePtr createTsSource(eServiceReferenceDVB &ref); + + // iSeekableService + RESULT isCurrentlySeekable(); +}; + +#endif diff --git a/main/bsod.cpp b/main/bsod.cpp index f76283e..5b01c7c 100644 --- a/main/bsod.cpp +++ b/main/bsod.cpp @@ -183,6 +183,7 @@ void bsodFatal(const char *component) xml.open("image"); xml.stringFromFile("dreamboxmodel", "/proc/stb/info/model"); xml.stringFromFile("kernelcmdline", "/proc/cmdline"); + xml.stringFromFile("nimsockets", "/proc/bus/nim_sockets"); if (!getConfigBool("config.plugins.crashlogautosubmit.sendAnonCrashlog", true)) { xml.cDataFromFile("dreamboxca", "/proc/stb/info/ca"); xml.cDataFromFile("enigma2settings", eEnv::resolve("${sysconfdir}/enigma2/settings"), ".password=");