From: ghost Date: Thu, 5 Nov 2009 07:35:58 +0000 (+0100) Subject: Merge branch 'bug_236_recordpath' into experimental X-Git-Tag: 3.0.0~28^2~66^2~218 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/8c877cd5c0fa7f79f1191ce9c5cc112abfcd0a68?hp=1915c7f7dbbec39c4d5592d9a0bee5454e4c452c Merge branch 'bug_236_recordpath' into experimental --- diff --git a/data/setup.xml b/data/setup.xml index 22705f0b..9425afda 100644 --- a/data/setup.xml +++ b/data/setup.xml @@ -13,8 +13,8 @@ config.av.tvsystem config.av.wss config.av.defaultac3 - config.av.generalAC3delay - config.av.generalPCMdelay + config.av.generalAC3delay + config.av.generalPCMdelay config.av.downmix_ac3 config.av.vcrswitch diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index 90bf19e1..09350698 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -1048,9 +1048,9 @@ int eTSMPEGDecoder::setState() int eTSMPEGDecoder::m_pcm_delay=-1, eTSMPEGDecoder::m_ac3_delay=-1; -RESULT eTSMPEGDecoder::setPCMDelay(int delay) +RESULT eTSMPEGDecoder::setHwPCMDelay(int delay) { - if (m_decoder == 0 && delay != m_pcm_delay ) + if (delay != m_pcm_delay ) { FILE *fp = fopen("/proc/stb/audio/audio_delay_pcm", "w"); if (fp) @@ -1064,9 +1064,9 @@ RESULT eTSMPEGDecoder::setPCMDelay(int delay) return -1; } -RESULT eTSMPEGDecoder::setAC3Delay(int delay) +RESULT eTSMPEGDecoder::setHwAC3Delay(int delay) { - if ( m_decoder == 0 && delay != m_ac3_delay ) + if ( delay != m_ac3_delay ) { FILE *fp = fopen("/proc/stb/audio/audio_delay_bitstream", "w"); if (fp) @@ -1080,6 +1080,17 @@ RESULT eTSMPEGDecoder::setAC3Delay(int delay) return -1; } + +RESULT eTSMPEGDecoder::setPCMDelay(int delay) +{ + return m_decoder == 0 ? setHwPCMDelay(delay) : -1; +} + +RESULT eTSMPEGDecoder::setAC3Delay(int delay) +{ + return m_decoder == 0 ? setHwAC3Delay(delay) : -1; +} + eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder) : m_demux(demux), m_vpid(-1), m_vtype(-1), m_apid(-1), m_atype(-1), m_pcrpid(-1), m_textpid(-1), diff --git a/lib/dvb/decoder.h b/lib/dvb/decoder.h index b53638b5..3a0fbac1 100644 --- a/lib/dvb/decoder.h +++ b/lib/dvb/decoder.h @@ -193,6 +193,8 @@ public: int getVideoProgressive(); int getVideoFrameRate(); int getVideoAspect(); + static RESULT setHwPCMDelay(int delay); + static RESULT setHwAC3Delay(int delay); }; #endif diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 894287e8..a8dfb193 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -1462,12 +1462,7 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off continue; } - size_t iframe_len; - /* try to align to iframe */ - int direction = pts < 0 ? -1 : 1; - m_tstools.findFrame(offset, iframe_len, direction); - - eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx (skipped additional %d frames due to iframe re-align)", relative, pts, offset, direction); + eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset); current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */ } diff --git a/lib/dvb/pvrparse.cpp b/lib/dvb/pvrparse.cpp index 1393bf77..5cdecbd6 100644 --- a/lib/dvb/pvrparse.cpp +++ b/lib/dvb/pvrparse.cpp @@ -244,6 +244,7 @@ off_t eMPEGStreamInformation::getAccessPoint(pts_t ts, int marg) off_t last = 0; off_t last2 = 0; pts_t lastc = 0; + ts += 1; // Add rounding error margin for (std::map::const_iterator i(m_access_points.begin()); i != m_access_points.end(); ++i) { pts_t delta = getDelta(i->first); diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index a9eef406..2e5c5665 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -652,18 +652,23 @@ int eDVBTSTools::findFrame(off_t &_offset, size_t &len, int &direction, int fram int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int frame_types) { - int nr_frames = 0; + int nr_frames, direction; // eDebug("trying to move %d frames at %llx", distance, offset); frame_types = frametypeI; /* TODO: intelligent "allow IP frames when not crossing an I-Frame */ - int direction = distance > 0 ? 0 : -1; - distance = abs(distance); - off_t new_offset = offset; size_t new_len = len; int first = 1; + if (distance > 0) { + direction = 0; + nr_frames = 0; + } else { + direction = -1; + nr_frames = -1; + distance = -distance+1; + } while (distance > 0) { int dir = direction; @@ -677,12 +682,18 @@ int eDVBTSTools::findNextPicture(off_t &offset, size_t &len, int &distance, int // eDebug("we moved %d, %d to go frames (now at %llx)", dir, distance, new_offset); - if (distance >= 0 || first) + if (distance >= 0 || direction == 0) { first = 0; offset = new_offset; len = new_len; nr_frames += abs(dir); + } + else if (first) { + first = 0; + offset = new_offset; + len = new_len; + nr_frames += abs(dir) + distance; // never jump forward during rewind } } diff --git a/lib/python/Components/AVSwitch.py b/lib/python/Components/AVSwitch.py index bc2a66a4..2658f9ba 100644 --- a/lib/python/Components/AVSwitch.py +++ b/lib/python/Components/AVSwitch.py @@ -1,5 +1,5 @@ from config import config, ConfigSlider, ConfigSelection, ConfigYesNo, \ - ConfigEnableDisable, ConfigSubsection, ConfigBoolean, ConfigNumber, ConfigNothing, NoSave + ConfigEnableDisable, ConfigSubsection, ConfigBoolean, ConfigSelectionNumber, ConfigNothing, NoSave from enigma import eAVSwitch, getDesktop from SystemInfo import SystemInfo from os import path as os_path @@ -112,8 +112,8 @@ def InitAVSwitch(): config.av.tvsystem = ConfigSelection(choices = {"pal": _("PAL"), "ntsc": _("NTSC"), "multinorm": _("multinorm")}, default="pal") config.av.wss = ConfigEnableDisable(default = True) config.av.defaultac3 = ConfigYesNo(default = False) - config.av.generalAC3delay = ConfigNumber(default = 0) - config.av.generalPCMdelay = ConfigNumber(default = 0) + config.av.generalAC3delay = ConfigSelectionNumber(-1000, 1000, 25, default = 0) + config.av.generalPCMdelay = ConfigSelectionNumber(-1000, 1000, 25, default = 0) config.av.vcrswitch = ConfigEnableDisable(default = False) iAVSwitch = AVSwitch() diff --git a/lib/python/Components/NimManager.py b/lib/python/Components/NimManager.py index 5154e2b0..70cde47c 100644 --- a/lib/python/Components/NimManager.py +++ b/lib/python/Components/NimManager.py @@ -939,7 +939,7 @@ def InitNimManager(nimmgr): lnb_choices = { "universal_lnb": _("Universal LNB"), -# "unicable": _("Unicable"), + "unicable": _("Unicable"), "c_band": _("C-Band"), "user_defined": _("User defined")} diff --git a/lib/python/Components/config.py b/lib/python/Components/config.py index 450c302e..876e3a34 100755 --- a/lib/python/Components/config.py +++ b/lib/python/Components/config.py @@ -1017,6 +1017,42 @@ class ConfigPassword(ConfigText): ConfigText.onDeselect(self, session) self.hidden = True +# lets the user select between [min, min+stepwidth, min+(stepwidth*2)..., maxval] with maxval <= max depending +# on the stepwidth +# min, max, stepwidth, default are int values +# wraparound: pressing RIGHT key at max value brings you to min value and vice versa if set to True +class ConfigSelectionNumber(ConfigSelection): + def __init__(self, min, max, stepwidth, default = None, wraparound = False): + self.wraparound = wraparound + if default is None: + default = min + default = str(default) + choices = [] + step = min + while step <= max: + choices.append(str(step)) + step += stepwidth + + ConfigSelection.__init__(self, choices, default) + + def getValue(self): + return int(self.text) + + def setValue(self, val): + self.text = str(val) + + def handleKey(self, key): + if not self.wraparound: + if key == KEY_RIGHT: + if len(self.choices) == (self.choices.index(self.value) + 1): + return + if key == KEY_LEFT: + if self.choices.index(self.value) == 0: + return + ConfigSelection.handleKey(self, key) + + + class ConfigNumber(ConfigText): def __init__(self, default = 0): ConfigText.__init__(self, str(default), fixed_size = False) diff --git a/lib/python/Plugins/Extensions/CutListEditor/plugin.py b/lib/python/Plugins/Extensions/CutListEditor/plugin.py index 75663462..efe9f761 100644 --- a/lib/python/Plugins/Extensions/CutListEditor/plugin.py +++ b/lib/python/Plugins/Extensions/CutListEditor/plugin.py @@ -7,6 +7,7 @@ from Components.ActionMap import HelpableActionMap from Components.MultiContent import MultiContentEntryText from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase from Components.VideoWindow import VideoWindow +from Components.Label import Label from Screens.InfoBarGenerics import InfoBarSeek, InfoBarCueSheetSupport from Components.GUIComponent import GUIComponent from enigma import eListboxPythonMultiContent, eListbox, gFont, iPlayableService, RT_HALIGN_RIGHT @@ -119,12 +120,13 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He Name - + Position,Detailed - - - + + + + {"template": [ MultiContentEntryText(size=(125, 20), text = 1, backcolor = MultiContentTemplateColor(3)), @@ -161,6 +163,9 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He self["Timeline"] = ServicePositionGauge(self.session.nav) self["cutlist"] = List(self.getCutlist()) self["cutlist"].onSelectionChanged.append(self.selectionChanged) + self["SeekState"] = Label() + self.onPlayStateChanged.append(self.updateStateLabel) + self.updateStateLabel(self.seekstate) self["Video"] = VideoWindow(decoder = 0) @@ -184,13 +189,17 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He }) # to track new entries we save the last version of the cutlist - self.last_cuts = [ ] + self.last_cuts = self.getCutlist() self.cut_start = None + self.inhibit_seek = False self.onClose.append(self.__onClose) def __onClose(self): self.session.nav.playService(self.old_service) + def updateStateLabel(self, state): + self["SeekState"].setText(state[3].strip()) + def showTutorial(self): if not self.tutorial_seen: self.tutorial_seen = True @@ -238,44 +247,46 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He return r def selectionChanged(self): - where = self["cutlist"].getCurrent() - if where is None: - print "no selection" - return - pts = where[0][0] - seek = self.getSeek() - if seek is None: - print "no seek" - return - seek.seekTo(pts) + if not self.inhibit_seek: + where = self["cutlist"].getCurrent() + if where is None: + print "no selection" + return + pts = where[0][0] + seek = self.getSeek() + if seek is None: + print "no seek" + return + seek.seekTo(pts) def refillList(self): print "cue sheet changed, refilling" self.downloadCuesheet() - # get the first changed entry, and select it + # get the first changed entry, counted from the end, and select it new_list = self.getCutlist() self["cutlist"].list = new_list - for i in range(min(len(new_list), len(self.last_cuts))): - if new_list[i] != self.last_cuts[i]: - self["cutlist"].setIndex(i) + l1 = len(new_list) + l2 = len(self.last_cuts) + for i in range(min(l1, l2)): + if new_list[l1-i-1] != self.last_cuts[l2-i-1]: + self["cutlist"].setIndex(l1-i-1) break self.last_cuts = new_list def getStateForPosition(self, pos): - state = 0 # in - - # when first point is "in", the beginning is "out" - if len(self.cut_list) and self.cut_list[0][1] == 0: - state = 1 - + state = -1 for (where, what) in self.cut_list: - if where < pos: - if what == 0: # in - state = 0 - elif what == 1: # out + if what in [0, 1]: + if where < pos: + state = what + elif where == pos: state = 1 + elif state == -1: + state = 1 - what + if state == -1: + state = 0 return state def showMenu(self): @@ -329,11 +340,11 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He in_after = None for (where, what) in self.cut_list: - if what == 1 and where < self.context_position: # out + if what == 1 and where <= self.context_position: # out out_before = (where, what) elif what == 0 and where < self.context_position: # in, before out out_before = None - elif what == 0 and where > self.context_position and in_after is None: + elif what == 0 and where >= self.context_position and in_after is None: in_after = (where, what) if out_before is not None: @@ -341,12 +352,16 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He if in_after is not None: self.cut_list.remove(in_after) + self.inhibit_seek = True self.uploadCuesheet() + self.inhibit_seek = False elif result == CutListContextMenu.RET_MARK: self.__addMark() elif result == CutListContextMenu.RET_DELETEMARK: self.cut_list.remove(self.context_nearest_mark) + self.inhibit_seek = True self.uploadCuesheet() + self.inhibit_seek = False elif result == CutListContextMenu.RET_REMOVEBEFORE: # remove in/out marks before current position for (where, what) in self.cut_list[:]: @@ -354,7 +369,9 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He self.cut_list.remove((where, what)) # add 'in' point bisect.insort(self.cut_list, (self.context_position, 0)) + self.inhibit_seek = True self.uploadCuesheet() + self.inhibit_seek = False elif result == CutListContextMenu.RET_REMOVEAFTER: # remove in/out marks after current position for (where, what) in self.cut_list[:]: @@ -362,7 +379,9 @@ class CutListEditor(Screen, InfoBarBase, InfoBarSeek, InfoBarCueSheetSupport, He self.cut_list.remove((where, what)) # add 'out' point bisect.insort(self.cut_list, (self.context_position, 1)) + self.inhibit_seek = True self.uploadCuesheet() + self.inhibit_seek = False elif result == CutListContextMenu.RET_GRABFRAME: self.grabFrame() diff --git a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py index 0e3bdf02..596f2d5a 100644 --- a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py @@ -110,7 +110,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB # 'None' is magic to start at the list of mountpoints defaultDir = config.mediaplayer.defaultDir.getValue() - self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|mkv|mp4|m4a|dat|flac|mov)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") + self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|m2ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|mkv|mp4|m4a|dat|flac|mov)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") self["filelist"] = self.filelist self.playlist = MyPlayList() diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index ed41bb28..b98cd469 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -692,8 +692,6 @@ class InfoBarSeek: iPlayableService.evSOF: self.__evSOF, }) - self.minSpeedBackward = useSeekBackHack and 16 or 0 - class InfoBarSeekActionMap(HelpableActionMap): def __init__(self, screen, *args, **kwargs): HelpableActionMap.__init__(self, screen, *args, **kwargs) @@ -740,24 +738,19 @@ class InfoBarSeek: self.__seekableStatusChanged() def makeStateForward(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: +# 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) def makeStateBackward(self, n): - minspeed = config.seek.stepwise_minspeed.value - repeat = int(config.seek.stepwise_repeat.value) - if self.minSpeedBackward and n < self.minSpeedBackward: - r = (self.minSpeedBackward - 1)/ n + 1 - if minspeed != "Never" and n >= int(minspeed) and repeat > 1: - r = max(r, repeat) - return (0, -n * r, r, "<< %dx" % n) - elif minspeed != "Never" and n >= int(minspeed) and repeat > 1: - return (0, -n * repeat, repeat, "<< %dx" % n) - else: +# 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) def makeStateSlowMotion(self, n): @@ -877,7 +870,7 @@ class InfoBarSeek: if config.seek.on_pause.value == "play": self.unPauseService() elif config.seek.on_pause.value == "step": - self.doSeekRelative(0) + self.doSeekRelative(1) elif config.seek.on_pause.value == "last": self.setSeekState(self.lastseekstate) self.lastseekstate = self.SEEK_STATE_PLAY @@ -950,7 +943,7 @@ class InfoBarSeek: self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value))) self.doSeekRelative(-6) elif seekstate == self.SEEK_STATE_PAUSE: - self.doSeekRelative(-3) + self.doSeekRelative(-1) elif self.isStateForward(seekstate): speed = seekstate[1] if seekstate[2]: diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index e1bf23dd..62755ad5 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -2,20 +2,23 @@ /* note: this requires gstreamer 0.10.x and a big list of plugins. */ /* it's currently hardcoded to use a big-endian alsasink as sink. */ +#include #include +#include +#include +#include #include -#include -#include +#include +#include +#include #include #include -#include -#include -#include + +#include + #include #include #include -/* for subtitles */ -#include // eServiceFactoryMP3 @@ -42,6 +45,7 @@ eServiceFactoryMP3::eServiceFactoryMP3() extensions.push_back("mp4"); extensions.push_back("mov"); extensions.push_back("m4a"); + extensions.push_back("m2ts"); sc->addServiceFactory(eServiceFactoryMP3::id, this, extensions); } @@ -186,6 +190,8 @@ int eStaticServiceMP3Info::getLength(const eServiceReference &ref) } // eServiceMP3 +int eServiceMP3::ac3_delay, + eServiceMP3::pcm_delay; eServiceMP3::eServiceMP3(eServiceReference ref) :m_ref(ref), m_pump(eApp, 1) @@ -658,7 +664,6 @@ RESULT eServiceMP3::getName(std::string &name) return 0; } - int eServiceMP3::getInfo(int w) { const gchar *tag = 0; @@ -954,6 +959,12 @@ RESULT eServiceMP3::subtitle(ePtr &ptr) return 0; } +RESULT eServiceMP3::audioDelay(ePtr &ptr) +{ + ptr = this; + return 0; +} + int eServiceMP3::getNumberOfTracks() { return m_audioStreams.size(); @@ -1092,6 +1103,8 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) g_object_set (G_OBJECT (sink), "emit-signals", TRUE, NULL); gst_object_unref(sink); } + setAC3Delay(ac3_delay); + setPCMDelay(pcm_delay); } break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: { @@ -1578,6 +1591,75 @@ int eServiceMP3::setBufferSize(int size) return 0; } +int eServiceMP3::getAC3Delay() +{ + return ac3_delay; +} + +int eServiceMP3::getPCMDelay() +{ + return pcm_delay; +} + +void eServiceMP3::setAC3Delay(int delay) +{ + if (!m_gst_playbin || m_state != stRunning) + return; + else + { + GstElement *sink; + std::string config_delay; + int config_delay_int = delay; + if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0) + config_delay_int += atoi(config_delay.c_str()); + + g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL); + + if (!sink) + return; + else { + gchar *name = gst_element_get_name(sink); + + if (strstr(name, "dvbaudiosink")) + eTSMPEGDecoder::setHwAC3Delay(config_delay_int); + g_free(name); + gst_object_unref(sink); + } + } +} + +void eServiceMP3::setPCMDelay(int delay) +{ + if (!m_gst_playbin || m_state != stRunning) + return; + else + { + GstElement *sink; + std::string config_delay; + int config_delay_int = delay; + if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0) + config_delay_int += atoi(config_delay.c_str()); + + g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL); + + if (!sink) + return; + else { + gchar *name = gst_element_get_name(sink); + + if (strstr(name, "dvbaudiosink")) + eTSMPEGDecoder::setHwPCMDelay(config_delay_int); + else { + // this is realy untested..and not used yet + gint64 offset = config_delay_int; + offset *= 1000000; // milli to nano + g_object_set (G_OBJECT (m_gst_playbin), "ts-offset", offset, NULL); + } + g_free(name); + gst_object_unref(sink); + } + } +} #else #warning gstreamer not available, not building media player diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index 15ed0b07..985179f6 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -49,8 +49,9 @@ typedef enum { atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFL typedef enum { stPlainText, stSSA, stSRT } subtype_t; typedef enum { ctNone, ctMPEGTS, ctMPEGPS, ctMKV, ctAVI, ctMP4, ctVCD, ctCDA } containertype_t; -class eServiceMP3: public iPlayableService, public iPauseableService, - public iServiceInformation, public iSeekableService, public iAudioTrackSelection, public iAudioChannelSelection, public iSubtitleOutput, public iStreamedService, public Object +class eServiceMP3: public iPlayableService, public iPauseableService, + public iServiceInformation, public iSeekableService, public iAudioTrackSelection, public iAudioChannelSelection, + public iSubtitleOutput, public iStreamedService, public iAudioDelay, public Object { DECLARE_REF(eServiceMP3); public: @@ -70,13 +71,14 @@ public: RESULT audioTracks(ePtr &ptr); RESULT audioChannel(ePtr &ptr); RESULT subtitle(ePtr &ptr); + RESULT audioDelay(ePtr &ptr); // not implemented (yet) RESULT frontendInfo(ePtr &ptr) { ptr = 0; return -1; } RESULT subServices(ePtr &ptr) { ptr = 0; return -1; } RESULT timeshift(ePtr &ptr) { ptr = 0; return -1; } RESULT cueSheet(ePtr &ptr) { ptr = 0; return -1; } - RESULT audioDelay(ePtr &ptr) { ptr = 0; return -1; } + RESULT rdsDecoder(ePtr &ptr) { ptr = 0; return -1; } RESULT keys(ePtr &ptr) { ptr = 0; return -1; } RESULT stream(ePtr &ptr) { ptr = 0; return -1; } @@ -122,6 +124,12 @@ public: PyObject *getBufferCharge(); int setBufferSize(int size); + // iAudioDelay + int getAC3Delay(); + int getPCMDelay(); + void setAC3Delay(int); + void setPCMDelay(int); + struct audioStream { GstPad* pad; @@ -166,6 +174,8 @@ public: } }; private: + static int pcm_delay; + static int ac3_delay; int m_currentAudioStream; int m_currentSubtitleStream; int selectAudioStream(int i);