From c0d4e140b6ab536c08074800248c366fa7cb79b0 Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 30 Oct 2008 15:09:21 +0100 Subject: add plugin list icon for dvdburn --- lib/python/Plugins/Extensions/DVDBurn/dvdburn.png | Bin 0 -> 3869 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 lib/python/Plugins/Extensions/DVDBurn/dvdburn.png (limited to 'lib/python') diff --git a/lib/python/Plugins/Extensions/DVDBurn/dvdburn.png b/lib/python/Plugins/Extensions/DVDBurn/dvdburn.png new file mode 100755 index 00000000..7e7adead Binary files /dev/null and b/lib/python/Plugins/Extensions/DVDBurn/dvdburn.png differ -- cgit v1.2.3 From d36def84f92bb9206c792356954e62c533297af4 Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 30 Oct 2008 18:24:06 +0100 Subject: fix execute string for tasks --- lib/python/Components/Task.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Components/Task.py b/lib/python/Components/Task.py index 7ea64f1a..c152e9a2 100644 --- a/lib/python/Components/Task.py +++ b/lib/python/Components/Task.py @@ -136,7 +136,6 @@ class Task(object): def setTool(self, tool): self.cmd = tool - self.args = [tool] self.global_preconditions.append(ToolExistsPrecondition()) self.postconditions.append(ReturncodePostcondition()) @@ -172,7 +171,7 @@ class Task(object): if self.cwd is not None: self.container.setCWD(self.cwd) - execstr = self.cmd + " ".join(self.args) + #execstr = " ".join([self.cmd]+self.args) print "execute:", self.container.execute(execstr), execstr if self.initial_input: self.writeInput(self.initial_input) -- cgit v1.2.3 From 8d4316d824f584eb3900fef898de59c9aca8d771 Mon Sep 17 00:00:00 2001 From: ghost Date: Thu, 30 Oct 2008 18:54:24 +0100 Subject: add possibility to disable user input in Messageboxes --- lib/python/Screens/MessageBox.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Screens/MessageBox.py b/lib/python/Screens/MessageBox.py index 8477fe04..8a5989c7 100644 --- a/lib/python/Screens/MessageBox.py +++ b/lib/python/Screens/MessageBox.py @@ -12,7 +12,7 @@ class MessageBox(Screen): TYPE_WARNING = 2 TYPE_ERROR = 3 - def __init__(self, session, text, type = TYPE_YESNO, timeout = -1, close_on_any_key = False, default = True): + def __init__(self, session, text, type = TYPE_YESNO, timeout = -1, close_on_any_key = False, default = True, enable_input = True): self.type = type Screen.__init__(self, session) @@ -47,20 +47,21 @@ class MessageBox(Screen): self["selectedChoice"].setText(self.list[0][0]) self["list"] = MenuList(self.list) - self["actions"] = ActionMap(["MsgBoxActions", "DirectionActions"], - { - "cancel": self.cancel, - "ok": self.ok, - "alwaysOK": self.alwaysOK, - "up": self.up, - "down": self.down, - "left": self.left, - "right": self.right, - "upRepeated": self.up, - "downRepeated": self.down, - "leftRepeated": self.left, - "rightRepeated": self.right - }, -1) + if enable_input: + self["actions"] = ActionMap(["MsgBoxActions", "DirectionActions"], + { + "cancel": self.cancel, + "ok": self.ok, + "alwaysOK": self.alwaysOK, + "up": self.up, + "down": self.down, + "left": self.left, + "right": self.right, + "upRepeated": self.up, + "downRepeated": self.down, + "leftRepeated": self.left, + "rightRepeated": self.right + }, -1) def initTimeout(self, timeout): self.timeout = timeout -- cgit v1.2.3 From f69b4f8dbed8ff96260b951cf8cecd76fa85423b Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Fri, 31 Oct 2008 11:18:40 +0100 Subject: uncomment necessary line --- lib/python/Components/Task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/python') diff --git a/lib/python/Components/Task.py b/lib/python/Components/Task.py index c152e9a2..47acc87e 100644 --- a/lib/python/Components/Task.py +++ b/lib/python/Components/Task.py @@ -171,7 +171,7 @@ class Task(object): if self.cwd is not None: self.container.setCWD(self.cwd) - #execstr = " ".join([self.cmd]+self.args) + execstr = " ".join([self.cmd]+self.args) print "execute:", self.container.execute(execstr), execstr if self.initial_input: self.writeInput(self.initial_input) -- cgit v1.2.3 From 19ce1123c780a9475e2f158712da6e73fa543e9c Mon Sep 17 00:00:00 2001 From: ghost Date: Fri, 31 Oct 2008 13:07:01 +0100 Subject: add possibility to call eConsoleAppContainer execute with unlimited count of arguments when its called with single argument, then /bin/sh is started else not --- lib/base/console.cpp | 36 +++++++++++++++++++++++++++++++----- lib/python/Components/Task.py | 4 ++-- 2 files changed, 33 insertions(+), 7 deletions(-) (limited to 'lib/python') diff --git a/lib/base/console.cpp b/lib/base/console.cpp index a12cb5e2..25318cc9 100644 --- a/lib/base/console.cpp +++ b/lib/base/console.cpp @@ -476,11 +476,37 @@ eConsolePy_running(eConsolePy* self) static PyObject * eConsolePy_execute(eConsolePy* self, PyObject *argt) { - const char *str; - if (PyArg_ParseTuple(argt, "s", &str)) - return PyInt_FromLong(self->cont->execute(str)); - PyErr_SetString(PyExc_TypeError, - "argument is not a string"); + Py_ssize_t argc = PyTuple_Size(argt); + if (argc > 1) + { + const char *argv[argc + 1]; + int argpos=0; + while(argpos < argc) + { + PyObject *arg = PyTuple_GET_ITEM(argt, argpos); + if (!PyString_Check(arg)) + { + char err[255]; + if (argpos) + snprintf(err, 255, "arg %d is not a string", argpos); + else + snprintf(err, 255, "cmd is not a string!"); + PyErr_SetString(PyExc_TypeError, err); + return NULL; + } + argv[argpos++] = PyString_AsString(arg); + } + argv[argpos] = 0; + return PyInt_FromLong(self->cont->execute(argv[0], argv)); + } + else + { + const char *str; + if (PyArg_ParseTuple(argt, "s", &str)) + return PyInt_FromLong(self->cont->execute(str)); + PyErr_SetString(PyExc_TypeError, + "cmd is not a string!"); + } return NULL; } diff --git a/lib/python/Components/Task.py b/lib/python/Components/Task.py index 47acc87e..ab85c667 100644 --- a/lib/python/Components/Task.py +++ b/lib/python/Components/Task.py @@ -136,6 +136,7 @@ class Task(object): def setTool(self, tool): self.cmd = tool + self.args = [tool] self.global_preconditions.append(ToolExistsPrecondition()) self.postconditions.append(ReturncodePostcondition()) @@ -171,8 +172,7 @@ class Task(object): if self.cwd is not None: self.container.setCWD(self.cwd) - execstr = " ".join([self.cmd]+self.args) - print "execute:", self.container.execute(execstr), execstr + print "execute:", self.container.execute(self.cmd, *self.args), self.cmd, *self.args if self.initial_input: self.writeInput(self.initial_input) -- cgit v1.2.3 From de868496fdbc0dc65d961d7404bfd7af827e045f Mon Sep 17 00:00:00 2001 From: ghost Date: Fri, 31 Oct 2008 14:04:12 +0100 Subject: fix syntax error --- lib/python/Components/Task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/python') diff --git a/lib/python/Components/Task.py b/lib/python/Components/Task.py index ab85c667..f249f711 100644 --- a/lib/python/Components/Task.py +++ b/lib/python/Components/Task.py @@ -172,7 +172,7 @@ class Task(object): if self.cwd is not None: self.container.setCWD(self.cwd) - print "execute:", self.container.execute(self.cmd, *self.args), self.cmd, *self.args + print "execute:", self.container.execute(self.cmd, *self.args), self.cmd, self.args if self.initial_input: self.writeInput(self.initial_input) -- cgit v1.2.3 From 95f74bb07093569c7996b331efa189a1d115eefe Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Fri, 31 Oct 2008 14:11:59 +0100 Subject: actually burn and not just simulate burning to dvd-MINUS-r(w) media --- lib/python/Plugins/Extensions/DVDBurn/Process.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Plugins/Extensions/DVDBurn/Process.py b/lib/python/Plugins/Extensions/DVDBurn/Process.py index b8a3788e..1cc11e2d 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Process.py +++ b/lib/python/Plugins/Extensions/DVDBurn/Process.py @@ -701,7 +701,7 @@ class DVDJob(Job): if output == "dvd": self.name = _("Burn DVD") tool = "/bin/growisofs" - burnargs = [ "-Z", "/dev/" + harddiskmanager.getCD(), "-dvd-compat", "-use-the-force-luke=dummy" ] + burnargs = [ "-Z", "/dev/" + harddiskmanager.getCD(), "-dvd-compat" ] elif output == "iso": self.name = _("Create DVD-ISO") tool = "/usr/bin/mkisofs" @@ -739,7 +739,7 @@ class DVDdataJob(Job): tool = "/bin/growisofs" if output == "dvd": self.name = _("Burn DVD") - burnargs = [ "-Z", "/dev/" + harddiskmanager.getCD(), "-dvd-compat", "-use-the-force-luke=dummy" ] + burnargs = [ "-Z", "/dev/" + harddiskmanager.getCD(), "-dvd-compat" ] elif output == "iso": tool = "/usr/bin/mkisofs" self.name = _("Create DVD-ISO") @@ -762,11 +762,11 @@ class DVDisoJob(Job): self.menupreview = False if imagepath.endswith(".iso"): PreviewTask(self, imagepath) - burnargs = [ "-Z", "/dev/" + harddiskmanager.getCD() + '='+imagepath, "-dvd-compat", "-use-the-force-luke=dummy" ] + burnargs = [ "-Z", "/dev/" + harddiskmanager.getCD() + '='+imagepath, "-dvd-compat" ] else: PreviewTask(self, imagepath + "/VIDEO_TS/") volName = self.project.settings.name.getValue() - burnargs = [ "-Z", "/dev/" + harddiskmanager.getCD(), "-dvd-compat", "-use-the-force-luke=dummy" ] + burnargs = [ "-Z", "/dev/" + harddiskmanager.getCD(), "-dvd-compat" ] burnargs += [ "-dvd-video", "-publisher", "Dreambox", "-V", volName, imagepath ] tool = "/bin/growisofs" BurnTask(self, burnargs, tool) -- cgit v1.2.3 From 9f767ea6bfa7f37de7553b3c7f15adb678c63d71 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Fri, 31 Oct 2008 15:08:48 +0100 Subject: add additional clear text error messages for burntask --- lib/python/Plugins/Extensions/DVDBurn/Process.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib/python') diff --git a/lib/python/Plugins/Extensions/DVDBurn/Process.py b/lib/python/Plugins/Extensions/DVDBurn/Process.py index 1cc11e2d..7a03b7eb 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Process.py +++ b/lib/python/Plugins/Extensions/DVDBurn/Process.py @@ -251,11 +251,13 @@ class BurnTaskPostcondition(Condition): task.ERROR_WRITE_FAILED: _("Write failed!"), task.ERROR_DVDROM: _("No (supported) DVDROM found!"), task.ERROR_ISOFS: _("Medium is not empty!"), + task.ERROR_FILETOOLARGE: _("TS file is too large for ISO9660 level 1!"), + task.ERROR_ISOTOOLARGE: _("ISO file is too large for this filesystem!"), task.ERROR_UNKNOWN: _("An unknown error occured!") }[task.error] class BurnTask(Task): - ERROR_NOTWRITEABLE, ERROR_LOAD, ERROR_SIZE, ERROR_WRITE_FAILED, ERROR_DVDROM, ERROR_ISOFS, ERROR_UNKNOWN = range(7) + ERROR_NOTWRITEABLE, ERROR_LOAD, ERROR_SIZE, ERROR_WRITE_FAILED, ERROR_DVDROM, ERROR_ISOFS, ERROR_FILETOOLARGE, ERROR_ISOTOOLARGE, ERROR_UNKNOWN = range(9) def __init__(self, job, extra_args=[], tool="/bin/growisofs"): Task.__init__(self, job, job.name) self.weighting = 500 @@ -303,6 +305,10 @@ class BurnTask(Task): else: self.error = self.ERROR_UNKNOWN print "BurnTask: unknown error %s" % line + elif line.find("-allow-limited-size was not specified. There is no way do represent this file size. Aborting.") != -1: + self.error = self.ERROR_FILETOOLARGE + elif line.startswith("genisoimage: File too large."): + self.error = self.ERROR_ISOTOOLARGE class RemoveDVDFolder(Task): def __init__(self, job): -- cgit v1.2.3 From 28c7b76bc72da019f3c3bf3aca88c3636062a618 Mon Sep 17 00:00:00 2001 From: ghost Date: Fri, 31 Oct 2008 16:43:41 +0100 Subject: needed update for avahi stuff --- lib/python/Components/Network.py | 102 +++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 37 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Components/Network.py b/lib/python/Components/Network.py index 9b0898e0..5c9e06b7 100644 --- a/lib/python/Components/Network.py +++ b/lib/python/Components/Network.py @@ -14,10 +14,11 @@ class Network: self.Console = Console() self.getInterfaces() - def getInterfaces(self): + def getInterfaces(self, callback = None): devicesPattern = re_compile('[a-z]+[0-9]+') self.configuredInterfaces = [] fp = file('/proc/net/dev', 'r') + system("cat /proc/net/dev") result = fp.readlines() fp.close() for line in result: @@ -25,19 +26,10 @@ class Network: device = devicesPattern.search(line).group() if device == 'wifi0': continue - self.getDataForInterface(device) - # Show only UP Interfaces in E2 - #if self.getAdapterAttribute(device, 'up') is False: - # del self.ifaces[device] + self.getDataForInterface(device, callback) except AttributeError: pass - #print "self.ifaces:", self.ifaces - #self.writeNetworkConfig() - #print ord(' ') - #for line in result: - # print ord(line[0]) - # helper function def regExpMatch(self, pattern, string): if string is None: @@ -55,12 +47,37 @@ class Network: ip.append(int(x)) return ip - def getDataForInterface(self, iface): - cmd = "ifconfig " + iface - self.Console.ePopen(cmd, self.ifconfigFinished, iface) - - def ifconfigFinished(self, result, retval, iface): + def IPaddrFinished(self, result, retval, extra_args): + (iface, callback ) = extra_args data = { 'up': False, 'dhcp': False, 'preup' : False, 'postdown' : False } + globalIPpattern = re_compile("scope global") + ipRegexp = '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' + ipLinePattern = re_compile('inet ' + ipRegexp +'/') + ipPattern = re_compile(ipRegexp) + + for line in result.splitlines(): + split = line.strip().split(' ',2) + if (split[1] == iface): + if re_search(globalIPpattern, split[2]): + ip = self.regExpMatch(ipPattern, self.regExpMatch(ipLinePattern, split[2])) + if ip is not None: + data['ip'] = self.convertIP(ip) + if not data.has_key('ip'): + data['dhcp'] = True + data['ip'] = [0, 0, 0, 0] + data['netmask'] = [0, 0, 0, 0] + data['gateway'] = [0, 0, 0, 0] + + cmd = "ifconfig " + iface + self.Console.ePopen(cmd, self.ifconfigFinished, [iface, data, callback]) + + def getDataForInterface(self, iface,callback): + #get ip out of ip addr, as avahi sometimes overrides it in ifconfig. + cmd = "ip -o addr" + self.Console.ePopen(cmd, self.IPaddrFinished, [iface,callback]) + + def ifconfigFinished(self, result, retval, extra_args ): + (iface, data, callback ) = extra_args ipRegexp = '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' ipLinePattern = re_compile('inet addr:' + ipRegexp) netmaskLinePattern = re_compile('Mask:' + ipRegexp) @@ -68,15 +85,15 @@ class Network: ipPattern = re_compile(ipRegexp) upPattern = re_compile('UP ') macPattern = re_compile('[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[0-9]{2}\:[0-9]{2}') - + for line in result.splitlines(): - ip = self.regExpMatch(ipPattern, self.regExpMatch(ipLinePattern, line)) + #ip = self.regExpMatch(ipPattern, self.regExpMatch(ipLinePattern, line)) netmask = self.regExpMatch(ipPattern, self.regExpMatch(netmaskLinePattern, line)) bcast = self.regExpMatch(ipPattern, self.regExpMatch(bcastLinePattern, line)) up = self.regExpMatch(upPattern, line) mac = self.regExpMatch(macPattern, line) - if ip is not None: - data['ip'] = self.convertIP(ip) + #if ip is not None: + # data['ip'] = self.convertIP(ip) if netmask is not None: data['netmask'] = self.convertIP(netmask) if bcast is not None: @@ -87,27 +104,34 @@ class Network: self.configuredInterfaces.append(iface) if mac is not None: data['mac'] = mac - if not data.has_key('ip'): - data['dhcp'] = True - data['ip'] = [0, 0, 0, 0] - data['netmask'] = [0, 0, 0, 0] - data['gateway'] = [0, 0, 0, 0] - + cmd = "route -n | grep " + iface - self.Console.ePopen(cmd,self.routeFinished,[iface,data,ipPattern]) + self.Console.ePopen(cmd,self.routeFinished,[iface,data,callback]) def routeFinished(self, result, retval, extra_args): - (iface, data, ipPattern) = extra_args - + (iface, data, callback) = extra_args + ipRegexp = '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' + ipPattern = re_compile(ipRegexp) + ipLinePattern = re_compile(ipRegexp) + for line in result.splitlines(): print line[0:7] if line[0:7] == "0.0.0.0": gateway = self.regExpMatch(ipPattern, line[16:31]) if gateway is not None: data['gateway'] = self.convertIP(gateway) + + for line in result.splitlines(): #get real netmask in case avahi has overridden ifconfig netmask + split = line.strip().split(' ') + if re_search(ipPattern, split[0]): + foundip = self.convertIP(split[0]) + if (foundip[0] == data['ip'][0] and foundip[1] == data['ip'][1]): + if re_search(ipPattern, split[4]): + mask = self.regExpMatch(ipPattern, self.regExpMatch(ipLinePattern, split[4])) + if mask is not None: + data['netmask'] = self.convertIP(mask) self.ifaces[iface] = data - if len(self.Console.appContainers) == 0: - self.loadNetworkConfig() + self.loadNetworkConfig(iface,callback) def writeNetworkConfig(self): self.configuredInterfaces = [] @@ -144,8 +168,7 @@ class Network: fp.write("nameserver %d.%d.%d.%d\n" % tuple(nameserver)) fp.close() - def loadNetworkConfig(self): - self.loadNameserverConfig() + def loadNetworkConfig(self,iface,callback = None): interfaces = [] # parse the interfaces-file try: @@ -166,7 +189,7 @@ class Network: ifaces[currif]["dhcp"] = True else: ifaces[currif]["dhcp"] = False - if (currif != ""): + if (currif == iface): #read information only for available interfaces if (split[0] == "address"): ifaces[currif]["address"] = map(int, split[1].split('.')) if self.ifaces[currif].has_key("ip"): @@ -181,7 +204,7 @@ class Network: ifaces[currif]["gateway"] = map(int, split[1].split('.')) if self.ifaces[currif].has_key("gateway"): if self.ifaces[currif]["gateway"] != ifaces[currif]["gateway"] and ifaces[currif]["dhcp"] == False: - self.ifaces[currif]["gateway"] = map(int, split[1].split('.')) + self.ifaces[currif]["gateway"] = map(int, split[1].split('.')) if (split[0] == "pre-up"): if self.ifaces[currif].has_key("preup"): self.ifaces[currif]["preup"] = i @@ -189,11 +212,16 @@ class Network: if self.ifaces[currif].has_key("postdown"): self.ifaces[currif]["postdown"] = i - print "read interfaces:", ifaces for ifacename, iface in ifaces.items(): if self.ifaces.has_key(ifacename): self.ifaces[ifacename]["dhcp"] = iface["dhcp"] - print "self.ifaces after loading:", self.ifaces + if len(self.Console.appContainers) == 0: + # load ns only once + self.loadNameserverConfig() + print "read configured interfac:", ifaces + print "self.ifaces after loading:", self.ifaces + if callback is not None: + callback(True) def loadNameserverConfig(self): ipRegexp = "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" -- cgit v1.2.3 From 340ec4b3727cb61e1038ca97b006471b5568e8a3 Mon Sep 17 00:00:00 2001 From: ghost Date: Fri, 31 Oct 2008 17:16:10 +0100 Subject: remove debug output --- lib/python/Components/Network.py | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/python') diff --git a/lib/python/Components/Network.py b/lib/python/Components/Network.py index 5c9e06b7..cf21c6d0 100644 --- a/lib/python/Components/Network.py +++ b/lib/python/Components/Network.py @@ -18,7 +18,6 @@ class Network: devicesPattern = re_compile('[a-z]+[0-9]+') self.configuredInterfaces = [] fp = file('/proc/net/dev', 'r') - system("cat /proc/net/dev") result = fp.readlines() fp.close() for line in result: -- cgit v1.2.3 From 7d90a93493f1dc9ab9d3a5694aa96501a9b25b89 Mon Sep 17 00:00:00 2001 From: ghost Date: Fri, 31 Oct 2008 19:36:58 +0100 Subject: add missing import --- lib/python/Components/Network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/python') diff --git a/lib/python/Components/Network.py b/lib/python/Components/Network.py index cf21c6d0..bed9d95f 100644 --- a/lib/python/Components/Network.py +++ b/lib/python/Components/Network.py @@ -1,5 +1,5 @@ from os import system, popen, path as os_path, listdir -from re import compile as re_compile +from re import compile as re_compile, search as re_search from socket import * from enigma import eConsoleAppContainer from Components.Console import Console -- cgit v1.2.3 From 70084c02aa33ef20e61d0b6257a679ab76a42660 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Sat, 1 Nov 2008 00:34:47 +0100 Subject: add icon to be installed. remove deprecated directories --- .../Plugins/Extensions/DVDBurn/data/Makefile.am | 6 ------ .../Plugins/Extensions/DVDBurn/data/dreamdvd_boat.jpg | Bin 187417 -> 0 bytes .../Plugins/Extensions/DVDBurn/data/dreamvmgm.mpg | Bin 575488 -> 0 bytes .../Plugins/Extensions/DVDBurn/data/silence.mp2 | Bin 8340 -> 0 bytes .../DVDBurn/template/DreamboxDVDtemplate.ddvdp.xml | 18 ------------------ .../Plugins/Extensions/DVDBurn/template/Makefile.am | 7 ------- 6 files changed, 31 deletions(-) delete mode 100644 lib/python/Plugins/Extensions/DVDBurn/data/Makefile.am delete mode 100755 lib/python/Plugins/Extensions/DVDBurn/data/dreamdvd_boat.jpg delete mode 100644 lib/python/Plugins/Extensions/DVDBurn/data/dreamvmgm.mpg delete mode 100644 lib/python/Plugins/Extensions/DVDBurn/data/silence.mp2 delete mode 100644 lib/python/Plugins/Extensions/DVDBurn/template/DreamboxDVDtemplate.ddvdp.xml delete mode 100644 lib/python/Plugins/Extensions/DVDBurn/template/Makefile.am (limited to 'lib/python') diff --git a/lib/python/Plugins/Extensions/DVDBurn/data/Makefile.am b/lib/python/Plugins/Extensions/DVDBurn/data/Makefile.am deleted file mode 100644 index e5992b9c..00000000 --- a/lib/python/Plugins/Extensions/DVDBurn/data/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -AUTOMAKE_OPTIONS = gnu - -installdir = $(DATADIR)/enigma2 - -install_DATA = \ - dreamdvd_boat.jpg dreamvmgm.mpg silence.mp2 diff --git a/lib/python/Plugins/Extensions/DVDBurn/data/dreamdvd_boat.jpg b/lib/python/Plugins/Extensions/DVDBurn/data/dreamdvd_boat.jpg deleted file mode 100755 index a5256e28..00000000 Binary files a/lib/python/Plugins/Extensions/DVDBurn/data/dreamdvd_boat.jpg and /dev/null differ diff --git a/lib/python/Plugins/Extensions/DVDBurn/data/dreamvmgm.mpg b/lib/python/Plugins/Extensions/DVDBurn/data/dreamvmgm.mpg deleted file mode 100644 index 4797986f..00000000 Binary files a/lib/python/Plugins/Extensions/DVDBurn/data/dreamvmgm.mpg and /dev/null differ diff --git a/lib/python/Plugins/Extensions/DVDBurn/data/silence.mp2 b/lib/python/Plugins/Extensions/DVDBurn/data/silence.mp2 deleted file mode 100644 index e8a817f8..00000000 Binary files a/lib/python/Plugins/Extensions/DVDBurn/data/silence.mp2 and /dev/null differ diff --git a/lib/python/Plugins/Extensions/DVDBurn/template/DreamboxDVDtemplate.ddvdp.xml b/lib/python/Plugins/Extensions/DVDBurn/template/DreamboxDVDtemplate.ddvdp.xml deleted file mode 100644 index b839ad8a..00000000 --- a/lib/python/Plugins/Extensions/DVDBurn/template/DreamboxDVDtemplate.ddvdp.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - diff --git a/lib/python/Plugins/Extensions/DVDBurn/template/Makefile.am b/lib/python/Plugins/Extensions/DVDBurn/template/Makefile.am deleted file mode 100644 index f0d9e8a0..00000000 --- a/lib/python/Plugins/Extensions/DVDBurn/template/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -AUTOMAKE_OPTIONS = gnu - -installdir = /etc/enigma2/playlist - -install_DATA = \ - DreamboxDVDtemplate.ddvdp.xml - -- cgit v1.2.3 From bd9c23676ae20d70488f7a539574b2ec75886940 Mon Sep 17 00:00:00 2001 From: ghost Date: Sun, 2 Nov 2008 11:14:33 +0100 Subject: add .mp2 as supported filetype --- lib/python/Components/FileList.py | 1 + lib/python/Plugins/Extensions/MediaPlayer/plugin.py | 6 +++--- lib/service/servicemp3.cpp | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Components/FileList.py b/lib/python/Components/FileList.py index 7801c556..e028ec3a 100644 --- a/lib/python/Components/FileList.py +++ b/lib/python/Components/FileList.py @@ -10,6 +10,7 @@ from enigma import RT_HALIGN_LEFT, eListboxPythonMultiContent, \ from Tools.LoadPixmap import LoadPixmap EXTENSIONS = { + "mp2": "music", "mp3": "music", "wav": "music", "ogg": "music", diff --git a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py index a144f2cd..841ad614 100644 --- a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py @@ -66,7 +66,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB self.addPlaylistParser(PlaylistIOInternal, "e2pls") # 'None' is magic to start at the list of mountpoints - self.filelist = FileList(None, matchingPattern = "(?i)^.*\.(mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|mkv|mp4|dat|flac)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") + self.filelist = FileList(None, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|mkv|mp4|dat|flac)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") self["filelist"] = self.filelist self.playlist = MyPlayList() @@ -727,7 +727,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB ext = text[-4:].lower() # FIXME: the information if the service contains video (and we should hide our window) should com from the service instead - if ext not in [".mp3", ".wav", ".ogg", "flac"] and not self.isAudioCD: + if ext not in [".mp2", ".mp3", ".wav", ".ogg", "flac"] and not self.isAudioCD: self.hide() else: needsInfoUpdate = True @@ -754,7 +754,7 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB currref = self.playlist.getServiceRefList()[idx] text = currref.getPath() ext = text[-4:].lower() - if ext not in [".mp3", ".wav", ".ogg", "flac"] and not self.isAudioCD: + if ext not in [".mp2", ".mp3", ".wav", ".ogg", "flac"] and not self.isAudioCD: self.hide() else: needsInfoUpdate = True diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index 5c982aa1..c76e346e 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -27,6 +27,7 @@ eServiceFactoryMP3::eServiceFactoryMP3() if (sc) { std::list extensions; + extensions.push_back("mp2"); extensions.push_back("mp3"); extensions.push_back("ogg"); extensions.push_back("mpg"); -- cgit v1.2.3 From c2e910d7e435dc9aefcc34e5c2eda5f7732606d8 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Mon, 3 Nov 2008 09:01:50 +0100 Subject: user correct playlist parser from dict --- lib/python/Plugins/Extensions/MediaPlayer/plugin.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py index 841ad614..ed1a8874 100644 --- a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py @@ -592,12 +592,13 @@ class MediaPlayer(Screen, InfoBarBase, InfoBarSeek, InfoBarAudioSelection, InfoB def PlaylistSelected(self,path): if path is not None: self.clear_playlist() - self.playlistIOInternal = PlaylistIOInternal() - list = self.playlistIOInternal.open(path[1]) - if list: + extension = path[0].rsplit('.',1)[-1] + if self.playlistparsers.has_key(extension): + playlist = self.playlistparsers[extension]() + list = playlist.open(path[1]) for x in list: self.playlist.addFile(x.ref) - self.playlist.updateList() + self.playlist.updateList() def delete_saved_playlist(self): listpath = [] -- cgit v1.2.3 From 6d9bdc5e7ee8990b74da7e18f0b641b39250a827 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Mon, 3 Nov 2008 13:47:04 +0100 Subject: fix streaming playback (webradio) --- lib/python/Components/Playlist.py | 2 ++ lib/service/servicemp3.cpp | 35 +++++++++++++++++++---------------- 2 files changed, 21 insertions(+), 16 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Components/Playlist.py b/lib/python/Components/Playlist.py index 22799692..744ee3af 100644 --- a/lib/python/Components/Playlist.py +++ b/lib/python/Components/Playlist.py @@ -70,6 +70,8 @@ class PlaylistIOM3U(PlaylistIO): # TODO: use e2 facilities to create a service ref from file if entry[0] == "/": self.addService(ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + entry)) + elif entry.startswith("http"): + self.addService(ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + entry.replace(':',"%3a"))) else: self.addService(ServiceReference("4097:0:0:0:0:0:0:0:0:0:" + os.path.dirname(filename) + "/" + entry)) file.close() diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index c76e346e..19b7735b 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -227,11 +227,29 @@ eServiceMP3::eServiceMP3(const char *filename): m_filename(filename), m_pump(eAp if (!m_gst_pipeline) m_error_message = "failed to create GStreamer pipeline!\n"; - if ( sourceinfo.containertype == ctCDA ) + if ( sourceinfo.is_streaming ) + { + eDebug("play webradio!"); + source = gst_element_factory_make ("neonhttpsrc", "http-source"); + if (source) + { + g_object_set (G_OBJECT (source), "location", filename, NULL); + g_object_set (G_OBJECT (source), "automatic-redirect", TRUE, NULL); + } + else + m_error_message = "GStreamer plugin neonhttpsrc not available!\n"; + } + else if ( sourceinfo.containertype == ctCDA ) { source = gst_element_factory_make ("cdiocddasrc", "cda-source"); if (source) + { g_object_set (G_OBJECT (source), "device", "/dev/cdroms/cdrom0", NULL); + int track = atoi(filename+18); + eDebug("play audio CD track #%i",track); + if (track > 0) + g_object_set (G_OBJECT (source), "track", track, NULL); + } else sourceinfo.containertype = ctNone; } @@ -243,21 +261,6 @@ eServiceMP3::eServiceMP3(const char *filename): m_filename(filename), m_pump(eAp else m_error_message = "GStreamer can't open filesrc " + (std::string)filename + "!\n"; } - else if ( sourceinfo.is_streaming ) - { - source = gst_element_factory_make ("neonhttpsrc", "http-source"); - if (source) - g_object_set (G_OBJECT (source), "automatic-redirect", TRUE, NULL); - else - m_error_message = "GStreamer plugin neonhttpsrc not available!\n"; - } - else - { - int track = atoi(filename+18); - eDebug("play audio CD track #%i",track); - if (track > 0) - g_object_set (G_OBJECT (source), "track", track, NULL); - } if ( sourceinfo.is_video ) { /* filesrc -> mpegdemux -> | queue_audio -> dvbaudiosink -- cgit v1.2.3 From ae6c45c7c6ae6c03fd535e40ddb5ce63ffa8e1f8 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Mon, 3 Nov 2008 20:48:01 +0100 Subject: save backup network configuration files and not only gui stuff from enigma2 and change the default backup location to harddisk (on behalf of sat-man) --- lib/python/Plugins/SystemPlugins/ConfigurationBackup/plugin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Plugins/SystemPlugins/ConfigurationBackup/plugin.py b/lib/python/Plugins/SystemPlugins/ConfigurationBackup/plugin.py index 9ff8c05d..7a918da6 100644 --- a/lib/python/Plugins/SystemPlugins/ConfigurationBackup/plugin.py +++ b/lib/python/Plugins/SystemPlugins/ConfigurationBackup/plugin.py @@ -104,8 +104,8 @@ class BackupSetup(Screen): self.list = [ ] self["config"] = ConfigList(self.list) self.backup = ConfigSubsection() - self.backup.type = ConfigSelection(choices = [("settings", _("only /etc/enigma2 directory")), ("var", _("/var directory")), ("skin", _("/usr/share/enigma2 directory"))], default="settings") - self.backup.location = ConfigSelection(choices = [("usb", _("USB Stick")), ("cf", _("CF Drive")), ("hdd", _("Harddisk"))]) + self.backup.type = ConfigSelection(choices = [("settings", _("enigma2 and network")), ("var", _("/var directory")), ("skin", _("/usr/share/enigma2 directory"))], default="settings") + self.backup.location = ConfigSelection(choices = [("hdd", _("Harddisk")), ("usb", _("USB Stick")), ("cf", _("CF Drive"))]) self.list.append(getConfigListEntry(_("Backup Mode"), self.backup.type)) self.list.append(getConfigListEntry(_("Backup Location"), self.backup.location)) @@ -132,7 +132,7 @@ class BackupSetup(Screen): self.path = BackupPath[self.backup.location.value] if self.backup.type.value == "settings": print "Backup Mode: Settings" - self.session.open(Console, title = "Backup running", cmdlist = ["tar -czvf " + self.path + "/" + str(dt) + "_settings_backup.tar.gz /etc/enigma2/"]) + self.session.open(Console, title = "Backup running", cmdlist = ["tar -czvf " + self.path + "/" + str(dt) + "_settings_backup.tar.gz /etc/enigma2/ /etc/network/interfaces /etc/wpa_supplicant.conf"]) elif self.backup.type.value == "var": print "Backup Mode: var" self.session.open(Console, title = "Backup running", cmdlist = [ "tar -czvf " + self.path + "/" + str(dt) + "_var_backup.tar.gz /var/"]) -- cgit v1.2.3 From 229de887b7ee74c1ed0eae8a7bbabd6a758756eb Mon Sep 17 00:00:00 2001 From: ghost Date: Tue, 4 Nov 2008 11:30:56 +0100 Subject: more failsave code, remove imho unneeded invalidate calls --- lib/python/Screens/TimerEdit.py | 47 ++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 27 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Screens/TimerEdit.py b/lib/python/Screens/TimerEdit.py index 67c49cc5..800bab33 100644 --- a/lib/python/Screens/TimerEdit.py +++ b/lib/python/Screens/TimerEdit.py @@ -117,41 +117,40 @@ class TimerEditList(Screen): self.session.nav.RecordTimer.timeChanged(t) self.refill() self.updateState() - + + def removeAction(self, descr): + actions = self["actions"].actions + if descr in actions: + del actions[descr] + def updateState(self): cur = self["timerlist"].getCurrent() if cur: if self.key_red_choice != self.DELETE: self["actions"].actions.update({"red":self.removeTimerQuestion}) self["key_red"].setText(_("Delete")) - self["key_red"].instance.invalidate() self.key_red_choice = self.DELETE if cur.disabled and (self.key_yellow_choice != self.ENABLE): self["actions"].actions.update({"yellow":self.toggleDisabledState}) self["key_yellow"].setText(_("Enable")) - self["key_yellow"].instance.invalidate() self.key_yellow_choice = self.ENABLE elif cur.isRunning() and not cur.repeated and (self.key_yellow_choice != self.EMPTY): - del self["actions"].actions["yellow"] + self.removeAction("yellow") self["key_yellow"].setText(" ") - self["key_yellow"].instance.invalidate() self.key_yellow_choice = self.EMPTY elif ((not cur.isRunning())or cur.repeated ) and (not cur.disabled) and (self.key_yellow_choice != self.DISABLE): self["actions"].actions.update({"yellow":self.toggleDisabledState}) self["key_yellow"].setText(_("Disable")) - self["key_yellow"].instance.invalidate() self.key_yellow_choice = self.DISABLE else: if self.key_red_choice != self.EMPTY: - del self["actions"].actions["red"] + self.removeAction("red") self["key_red"].setText(" ") - self["key_red"].instance.invalidate() self.key_red_choice = self.EMPTY if self.key_yellow_choice != self.EMPTY: - del self["actions"].actions["yellow"] + self.removeAction("yellow") self["key_yellow"].setText(" ") - self["key_yellow"].instance.invalidate() self.key_yellow_choice = self.EMPTY showCleanup = True @@ -164,15 +163,12 @@ class TimerEditList(Screen): if showCleanup and (self.key_blue_choice != self.CLEANUP): self["actions"].actions.update({"blue":self.cleanupQuestion}) self["key_blue"].setText(_("Cleanup")) - self["key_blue"].instance.invalidate() self.key_blue_choice = self.CLEANUP elif (not showCleanup) and (self.key_blue_choice != self.EMPTY): - del self["actions"].actions["blue"] + self.removeAction("blue") self["key_blue"].setText(" ") - self["key_blue"].instance.invalidate() self.key_blue_choice = self.EMPTY - def fillTimerList(self): del self.list[:] @@ -399,23 +395,25 @@ class TimerSanityConflict(Screen): def down(self): self["list"].instance.moveSelection(self["list"].instance.moveDown) self["timer2"].moveToIndex(self["list"].getSelectedIndex()) - + + def removeAction(self, descr): + actions = self["actions"].actions + if descr in actions: + del actions[descr] + def updateState(self): if self.timer[0] is not None: if self.timer[0].disabled and self.key_green_choice != self.ENABLE: self["actions"].actions.update({"green":self.toggleTimer1}) self["key_green"].setText(_("Enable")) - self["key_green"].instance.invalidate() self.key_green_choice = self.ENABLE elif self.timer[0].isRunning() and not timer[0].repeated and self.key_green_choice != self.EMPTY: - del self["actions"].actions["green"] + self.removeAction("green") self["key_green"].setText(" ") - self["key_green"].instance.invalidate() self.key_green_choice = self.EMPTY elif (not self.timer[0].isRunning() or self.timer[0].repeated ) and self.key_green_choice != self.DISABLE: self["actions"].actions.update({"green":self.toggleTimer1}) self["key_green"].setText(_("Disable")) - self["key_green"].instance.invalidate() self.key_green_choice = self.DISABLE if len(self.timer) > 1: x = self["list"].getSelectedIndex() @@ -423,25 +421,20 @@ class TimerSanityConflict(Screen): if self.timer[x].disabled and self.key_blue_choice != self.ENABLE: self["actions"].actions.update({"blue":self.toggleTimer2}) self["key_blue"].setText(_("Enable")) - self["key_blue"].instance.invalidate() self.key_blue_choice = self.ENABLE elif self.timer[x].isRunning() and not timer[x].repeated and self.key_blue_choice != self.EMPTY: - del self["actions"].actions["blue"] + self.removeAction("blue") self["key_blue"].setText(" ") - self["key_blue"].instance.invalidate() self.key_blue_choice = self.EMPTY elif (not self.timer[x].isRunning() or self.timer[x].repeated ) and self.key_blue_choice != self.DISABLE: self["actions"].actions.update({"blue":self.toggleTimer2}) self["key_blue"].setText(_("Disable")) - self["key_blue"].instance.invalidate() self.key_blue_choice = self.DISABLE else: #FIXME.... this doesnt hide the buttons self.... just the text - del self["actions"].actions["yellow"] + self.removeAction("yellow") self["key_yellow"].setText(" ") - self["key_yellow"].instance.invalidate() self.key_yellow_choice = self.EMPTY - del self["actions"].actions["blue"] + self.removeAction("blue") self["key_blue"].setText(" ") - self["key_blue"].instance.invalidate() self.key_blue_choice = self.EMPTY -- cgit v1.2.3 From 61e2eca2450a20da4ecd5cc138058e221df9837f Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Tue, 4 Nov 2008 15:27:06 +0100 Subject: implement blanking of dvd minus rw media --- lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py b/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py index 0c375129..d4e6a375 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py +++ b/lib/python/Plugins/Extensions/DVDBurn/DVDToolbox.py @@ -150,7 +150,7 @@ class DVDformatJob(Job): DVDformatTask(self) def retry(self): - self.tasks[0].args += [ "-force" ] + self.tasks[0].args += self.tasks[0].retryargs Job.retry(self) class DVDformatTaskPostcondition(Condition): @@ -174,6 +174,7 @@ class DVDformatTask(Task): self.setTool("/bin/dvd+rw-format") self.args += [ "/dev/" + harddiskmanager.getCD() ] self.end = 1100 + self.retryargs = [ ] def prepare(self): self.error = None @@ -181,7 +182,10 @@ class DVDformatTask(Task): def processOutputLine(self, line): if line.startswith("- media is already formatted"): self.error = self.ERROR_ALREADYFORMATTED - self.force = True + self.retryargs = [ "-force" ] + if line.startswith("- media is not blank"): + self.error = self.ERROR_ALREADYFORMATTED + self.retryargs = [ "-blank" ] if line.startswith(":-( mounted media doesn't appear to be"): self.error = self.ERROR_NOTWRITEABLE -- cgit v1.2.3 From 73e179bb7dfd67800dce39a383a269b2d871d180 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Tue, 4 Nov 2008 23:03:42 +0100 Subject: don't crash when exitting dvd image selection without selection --- lib/python/Plugins/Extensions/DVDBurn/TitleList.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py index 600411ce..19380af4 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py @@ -207,10 +207,11 @@ class TitleList(Screen, HelpableScreen): self.session.openWithCallback(self.JobViewCB, JobView, job) def burnISO(self, path, scope): - job = Process.DVDisoJob(self.project, path) - job_manager.AddJob(job) - job_manager.in_background = False - self.session.openWithCallback(self.JobViewCB, JobView, job) + if path: + job = Process.DVDisoJob(self.project, path) + job_manager.AddJob(job) + job_manager.in_background = False + self.session.openWithCallback(self.JobViewCB, JobView, job) def JobViewCB(self, in_background): job_manager.in_background = in_background -- cgit v1.2.3 From a1404d58d60d5dc369e89cb98f239a83d447a986 Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Wed, 5 Nov 2008 09:00:27 +0100 Subject: don't crash when background jobs fail and user presses red key --- lib/python/Components/Task.py | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/python') diff --git a/lib/python/Components/Task.py b/lib/python/Components/Task.py index f249f711..b276438f 100644 --- a/lib/python/Components/Task.py +++ b/lib/python/Components/Task.py @@ -265,6 +265,7 @@ class JobManager: from Tools import Notifications if self.in_background: from Screens.TaskView import JobView + self.in_background = False Notifications.AddNotification(JobView, self.active_job) if problems: from Screens.MessageBox import MessageBox -- cgit v1.2.3 From 938a550b0874cd87f475a638551d7046f729d1bc Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Wed, 5 Nov 2008 12:52:46 +0100 Subject: nastily pretend the dvd minus rw bruning error never happened --- lib/python/Plugins/Extensions/DVDBurn/Process.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Plugins/Extensions/DVDBurn/Process.py b/lib/python/Plugins/Extensions/DVDBurn/Process.py index 7a03b7eb..9cca8f70 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Process.py +++ b/lib/python/Plugins/Extensions/DVDBurn/Process.py @@ -241,7 +241,11 @@ class WaitForResidentTasks(Task): class BurnTaskPostcondition(Condition): RECOVERABLE = True def check(self, task): - return task.error is None + if task.returncode == 0: + return True + elif task.error is None or task.error is task.ERROR_MINUSRWBUG: + return True + return False def getErrorMessage(self, task): return { @@ -257,7 +261,7 @@ class BurnTaskPostcondition(Condition): }[task.error] class BurnTask(Task): - ERROR_NOTWRITEABLE, ERROR_LOAD, ERROR_SIZE, ERROR_WRITE_FAILED, ERROR_DVDROM, ERROR_ISOFS, ERROR_FILETOOLARGE, ERROR_ISOTOOLARGE, ERROR_UNKNOWN = range(9) + ERROR_NOTWRITEABLE, ERROR_LOAD, ERROR_SIZE, ERROR_WRITE_FAILED, ERROR_DVDROM, ERROR_ISOFS, ERROR_FILETOOLARGE, ERROR_ISOTOOLARGE, ERROR_MINUSRWBUG, ERROR_UNKNOWN = range(10) def __init__(self, job, extra_args=[], tool="/bin/growisofs"): Task.__init__(self, job, job.name) self.weighting = 500 @@ -284,12 +288,17 @@ class BurnTask(Task): self.error = self.ERROR_NOTWRITEABLE if line.find("ASC=24h") != -1: self.error = self.ERROR_LOAD + if line.find("SK=5h/ASC=A8h/ACQ=04h") != -1: + self.error = self.ERROR_MINUSRWBUG else: self.error = self.ERROR_UNKNOWN print "BurnTask: unknown error %s" % line elif line.startswith(":-("): if line.find("No space left on device") != -1: self.error = self.ERROR_SIZE + elif self.error == self.ERROR_MINUSRWBUG: + print "*sigh* this is a known bug. we're simply gonna assume everything is fine." + self.postconditions = [] elif line.find("write failed") != -1: self.error = self.ERROR_WRITE_FAILED elif line.find("unable to open64(") != -1 and line.find(",O_RDONLY): No such file or directory") != -1: @@ -309,6 +318,11 @@ class BurnTask(Task): self.error = self.ERROR_FILETOOLARGE elif line.startswith("genisoimage: File too large."): self.error = self.ERROR_ISOTOOLARGE + + def setTool(self, tool): + self.cmd = tool + self.args = [tool] + self.global_preconditions.append(ToolExistsPrecondition()) class RemoveDVDFolder(Task): def __init__(self, job): -- cgit v1.2.3 From 8ab0666af66fdb08f955daa70b255a5841ea73fb Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Wed, 5 Nov 2008 14:32:25 +0100 Subject: try to add dvdburn icon once again --- lib/python/Plugins/Extensions/DVDBurn/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/python') diff --git a/lib/python/Plugins/Extensions/DVDBurn/Makefile.am b/lib/python/Plugins/Extensions/DVDBurn/Makefile.am index d5c558d1..cb65f56a 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Makefile.am +++ b/lib/python/Plugins/Extensions/DVDBurn/Makefile.am @@ -5,5 +5,5 @@ install_PYTHON = \ plugin.py \ DVDProject.py DVDTitle.py TitleCutter.py TitleList.py Process.py ProjectSettings.py DVDToolbox.py -install_DATA = *.xml *.jpg *.mpg *.mp2 +install_DATA = *.xml *.jpg *.mpg *.mp2 *.png -- cgit v1.2.3 From be092c47edfd4babfd3b4c5ea511710e6458343f Mon Sep 17 00:00:00 2001 From: Fraxinas Date: Wed, 5 Nov 2008 17:25:52 +0100 Subject: allow setting progress for current task from within resident task, implement rudimentary progress for mplextask in dvdburn (requires dvdauthor patch) --- lib/python/Components/Task.py | 12 ++++--- lib/python/Plugins/Extensions/DVDBurn/Process.py | 45 ++++++++++++++---------- 2 files changed, 33 insertions(+), 24 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Components/Task.py b/lib/python/Components/Task.py index b276438f..9a768425 100644 --- a/lib/python/Components/Task.py +++ b/lib/python/Components/Task.py @@ -45,6 +45,7 @@ class Job(object): def addTask(self, task): task.job = self + task.task_progress_changed = self.task_progress_changed_CB self.tasks.append(task) def start(self, callback): @@ -70,7 +71,7 @@ class Job(object): else: print "still waiting for %d resident task(s) %s to finish" % (len(self.resident_tasks), str(self.resident_tasks)) else: - self.tasks[self.current_task].run(self.taskCallback, self.task_progress_changed_CB) + self.tasks[self.current_task].run(self.taskCallback) self.state_changed() def taskCallback(self, task, res, stay_resident = False): @@ -151,7 +152,7 @@ class Task(object): not_met.append(precondition) return not_met - def run(self, callback, task_progress_changed): + def run(self, callback): failed_preconditions = self.checkPreconditions(True) + self.checkPreconditions(False) if len(failed_preconditions): callback(self, failed_preconditions) @@ -159,7 +160,6 @@ class Task(object): self.prepare() self.callback = callback - self.task_progress_changed = task_progress_changed from enigma import eConsoleAppContainer self.container = eConsoleAppContainer() self.container.appClosed.append(self.processFinished) @@ -235,7 +235,8 @@ class Task(object): if progress < 0: progress = 0 self.__progress = progress - self.task_progress_changed() + if self.task_progress_changed: + self.task_progress_changed() progress = property(getProgress, setProgress) @@ -372,7 +373,8 @@ class ToolExistsPrecondition(Condition): return _("A required tool (%s) was not found.") % (self.realpath) class AbortedPostcondition(Condition): - pass + def getErrorMessage(self, task): + return "Cancelled upon user request" class ReturncodePostcondition(Condition): def check(self, task): diff --git a/lib/python/Plugins/Extensions/DVDBurn/Process.py b/lib/python/Plugins/Extensions/DVDBurn/Process.py index 9cca8f70..49054596 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Process.py +++ b/lib/python/Plugins/Extensions/DVDBurn/Process.py @@ -10,8 +10,8 @@ class png2yuvTask(Task): self.dumpFile = outputfile self.weighting = 15 - def run(self, callback, task_progress_changed): - Task.run(self, callback, task_progress_changed) + def run(self, callback): + Task.run(self, callback) self.container.stdoutAvail.remove(self.processStdout) self.container.dumpToFile(self.dumpFile) @@ -26,8 +26,8 @@ class mpeg2encTask(Task): self.inputFile = inputfile self.weighting = 25 - def run(self, callback, task_progress_changed): - Task.run(self, callback, task_progress_changed) + def run(self, callback): + Task.run(self, callback) self.container.readFromFile(self.inputFile) def processOutputLine(self, line): @@ -42,8 +42,8 @@ class spumuxTask(Task): self.dumpFile = outputfile self.weighting = 15 - def run(self, callback, task_progress_changed): - Task.run(self, callback, task_progress_changed) + def run(self, callback): + Task.run(self, callback) self.container.stdoutAvail.remove(self.processStdout) self.container.dumpToFile(self.dumpFile) self.container.readFromFile(self.inputFile) @@ -212,7 +212,7 @@ class RemoveESFiles(Task): class DVDAuthorTask(Task): def __init__(self, job): Task.__init__(self, job, "Authoring DVD") - self.weighting = 300 + self.weighting = 20 self.setTool("/usr/bin/dvdauthor") self.CWD = self.job.workspace self.args += ["-x", self.job.workspace+"/dvdauthor.xml"] @@ -222,6 +222,14 @@ class DVDAuthorTask(Task): print "[DVDAuthorTask] ", line[:-1] if not self.menupreview and line.startswith("STAT: Processing"): self.callback(self, [], stay_resident=True) + elif line.startswith("STAT: VOBU"): + try: + progress = int(line.split("MB")[0].split(" ")[-1]) + if progress: + self.job.mplextask.progress = progress + print "[DVDAuthorTask] update mplextask progress:", self.job.mplextask.progress, "of", self.job.mplextask.end + except: + print "couldn't set mux progress" class DVDAuthorFinalTask(Task): def __init__(self, job): @@ -233,7 +241,7 @@ class WaitForResidentTasks(Task): def __init__(self, job): Task.__init__(self, job, "waiting for dvdauthor to finalize") - def run(self, callback, task_progress_changed): + def run(self, callback): print "waiting for %d resident task(s) %s to finish..." % (len(self.job.resident_tasks),str(self.job.resident_tasks)) if self.job.resident_tasks == 0: callback(self, []) @@ -334,23 +342,24 @@ class RemoveDVDFolder(Task): class CheckDiskspaceTask(Task): def __init__(self, job): Task.__init__(self, job, "Checking free space") - totalsize = 50*1024*1024 # require an extra safety 50 MB + totalsize = 0 # require an extra safety 50 MB maxsize = 0 for title in job.project.titles: titlesize = title.estimatedDiskspace if titlesize > maxsize: maxsize = titlesize totalsize += titlesize diskSpaceNeeded = totalsize + maxsize + job.estimateddvdsize = totalsize / 1024 / 1024 + totalsize += 50*1024*1024 # require an extra safety 50 MB self.global_preconditions.append(DiskspacePrecondition(diskSpaceNeeded)) self.weighting = 5 - def run(self, callback, task_progress_changed): + def run(self, callback): failed_preconditions = self.checkPreconditions(True) + self.checkPreconditions(False) if len(failed_preconditions): callback(self, failed_preconditions) return self.callback = callback - self.task_progress_changed = task_progress_changed Task.processFinished(self, 0) class PreviewTask(Task): @@ -361,9 +370,8 @@ class PreviewTask(Task): self.path = path self.weighting = 10 - def run(self, callback, task_progress_changed): + def run(self, callback): self.callback = callback - self.task_progress_changed = task_progress_changed if self.job.menupreview: self.previewProject() else: @@ -439,9 +447,8 @@ class ImagePrepareTask(Task): self.job = job self.Menus = job.Menus - def run(self, callback, task_progress_changed): + def run(self, callback): self.callback = callback - self.task_progress_changed = task_progress_changed # we are doing it this weird way so that the TaskView Screen actually pops up before the spinner comes from enigma import eTimer self.delayTimer = eTimer() @@ -451,7 +458,7 @@ class ImagePrepareTask(Task): def conduct(self): try: from ImageFont import truetype - from Image import open as Image_open + from Image import open as Image_open s = self.job.project.settings self.Menus.im_bg_orig = Image_open(s.menubg.getValue()) if self.Menus.im_bg_orig.size != (self.Menus.imgwidth, self.Menus.imgheight): @@ -475,9 +482,8 @@ class MenuImageTask(Task): self.menubgpngfilename = menubgpngfilename self.highlightpngfilename = highlightpngfilename - def run(self, callback, task_progress_changed): + def run(self, callback): self.callback = callback - self.task_progress_changed = task_progress_changed try: import ImageDraw, Image, os s = self.job.project.settings @@ -712,7 +718,8 @@ class DVDJob(Job): title_filename = self.workspace + "/dvd_title_%d.mpg" % (self.i+1) LinkTS(self, title.inputfile, link_name) demux = DemuxTask(self, link_name) - MplexTask(self, outputfile=title_filename, demux_task=demux) + self.mplextask = MplexTask(self, outputfile=title_filename, demux_task=demux) + self.mplextask.end = self.estimateddvdsize RemoveESFiles(self, demux) WaitForResidentTasks(self) PreviewTask(self, self.workspace + "/dvd/VIDEO_TS/") -- cgit v1.2.3 From 67a09e962e20c1a2becd8b8699b542779941b6e7 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Mon, 17 Nov 2008 17:19:39 +0100 Subject: performance fix: don't redraw if in/out list is the same --- lib/python/Components/Renderer/PositionGauge.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/python') diff --git a/lib/python/Components/Renderer/PositionGauge.py b/lib/python/Components/Renderer/PositionGauge.py index 5fa8c356..3f93d82e 100644 --- a/lib/python/Components/Renderer/PositionGauge.py +++ b/lib/python/Components/Renderer/PositionGauge.py @@ -50,9 +50,10 @@ class PositionGauge(Renderer): return self.__cutlist def setCutlist(self, cutlist): - self.__cutlist = cutlist - if self.instance is not None: - self.instance.setInOutList(cutlist) + if self.__cutlist != cutlist: + self.__cutlist = cutlist + if self.instance is not None: + self.instance.setInOutList(cutlist) cutlist = property(getCutlist, setCutlist) -- cgit v1.2.3 From 3aedbe22cf74b72ad0c3e2bc1869e914701e6574 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Tue, 18 Nov 2008 00:39:59 +0100 Subject: experimental dm8000 recording fix, doesn't belong here --- lib/python/Components/Renderer/FrontpanelLed.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib/python') diff --git a/lib/python/Components/Renderer/FrontpanelLed.py b/lib/python/Components/Renderer/FrontpanelLed.py index 7bb584e5..cd329b56 100644 --- a/lib/python/Components/Renderer/FrontpanelLed.py +++ b/lib/python/Components/Renderer/FrontpanelLed.py @@ -6,15 +6,24 @@ class FrontpanelLed(Element): Element.__init__(self) def changed(self, *args, **kwargs): - if self.source.value: + if self.source.value or 1: pattern = 0x55555555 + pattern_4bit = 0x84fc8c04 speed = 20 else: pattern = 0 + pattern_4bit = 0xffffffff speed = 1 try: open("/proc/stb/fp/led0_pattern", "w").write("%08x" % pattern) + except IOError: + pass + try: + open("/proc/stb/fp/led_pattern", "w").write("%08x" % pattern_4bit) + except IOError: + pass + try: open("/proc/stb/fp/led_pattern_speed", "w").write("%d" % speed) except IOError: pass -- cgit v1.2.3 From 4f7990ff2a55874b9eb65e3c9cd47dacb9f76deb Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Tue, 18 Nov 2008 00:40:19 +0100 Subject: rework decoder states --- lib/dvb/decoder.cpp | 208 ++++++++++++++++------------------ lib/dvb/decoder.h | 42 +++++-- lib/dvb/idvb.h | 33 ++---- lib/python/Screens/InfoBarGenerics.py | 17 ++- lib/service/iservice.h | 2 + lib/service/servicedvb.cpp | 40 ++++--- lib/service/servicedvb.h | 1 + 7 files changed, 177 insertions(+), 166 deletions(-) (limited to 'lib/python') diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index 6ad39225..66b923a6 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -39,7 +39,7 @@ DEFINE_REF(eDVBAudio); eDVBAudio::eDVBAudio(eDVBDemux *demux, int dev) - :m_demux(demux), m_dev(dev), m_is_freezed(0) + :m_demux(demux), m_dev(dev) { char filename[128]; #if HAVE_DVB_API_VERSION < 3 @@ -194,7 +194,7 @@ int eDVBAudio::startPid(int pid, int type) */ } - eDebugNoNewLine("AUDIO_SET_BYPASS - "); + eDebugNoNewLine("AUDIO_SET_BYPASS(%d) - ", bypass); if (::ioctl(m_fd, AUDIO_SET_BYPASS_MODE, bypass) < 0) eDebug("failed (%m)"); else @@ -240,28 +240,20 @@ void eDVBAudio::flush() void eDVBAudio::freeze() { - if (!m_is_freezed) - { - eDebugNoNewLine("AUDIO_PAUSE - "); - if (::ioctl(m_fd, AUDIO_PAUSE) < 0) - eDebug("failed (%m)"); - else - eDebug("ok"); - m_is_freezed=1; - } + eDebugNoNewLine("AUDIO_PAUSE - "); + if (::ioctl(m_fd, AUDIO_PAUSE) < 0) + eDebug("failed (%m)"); + else + eDebug("ok"); } void eDVBAudio::unfreeze() { - if (m_is_freezed) - { - eDebugNoNewLine("AUDIO_CONTINUE - "); - if (::ioctl(m_fd, AUDIO_CONTINUE) < 0) - eDebug("failed (%m)"); - else - eDebug("ok"); - m_is_freezed=0; - } + eDebugNoNewLine("AUDIO_CONTINUE - "); + if (::ioctl(m_fd, AUDIO_CONTINUE) < 0) + eDebug("failed (%m)"); + else + eDebug("ok"); } void eDVBAudio::setChannel(int channel) @@ -299,7 +291,7 @@ eDVBAudio::~eDVBAudio() DEFINE_REF(eDVBVideo); eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev) - :m_demux(demux), m_dev(dev), m_is_slow_motion(0), m_is_fast_forward(0), m_is_freezed(0) + :m_demux(demux), m_dev(dev) { char filename[128]; #if HAVE_DVB_API_VERSION < 3 @@ -461,34 +453,25 @@ void eDVBVideo::flush() void eDVBVideo::freeze() { - if (!m_is_freezed) - { - eDebugNoNewLine("VIDEO_FREEZE - "); - if (::ioctl(m_fd, VIDEO_FREEZE) < 0) - eDebug("failed (%m)"); - else - eDebug("ok"); - m_is_freezed=1; - } + eDebugNoNewLine("VIDEO_FREEZE - "); + if (::ioctl(m_fd, VIDEO_FREEZE) < 0) + eDebug("failed (%m)"); + else + eDebug("ok"); } void eDVBVideo::unfreeze() { - if (m_is_freezed) - { - eDebugNoNewLine("VIDEO_CONTINUE - "); - if (::ioctl(m_fd, VIDEO_CONTINUE) < 0) - eDebug("failed (%m)"); - else - eDebug("ok"); - m_is_freezed=0; - } + eDebugNoNewLine("VIDEO_CONTINUE - "); + if (::ioctl(m_fd, VIDEO_CONTINUE) < 0) + eDebug("failed (%m)"); + else + eDebug("ok"); } int eDVBVideo::setSlowMotion(int repeat) { - eDebugNoNewLine("VIDEO_SLOWMOTION - "); - m_is_slow_motion = repeat; + eDebugNoNewLine("VIDEO_SLOWMOTION(%d) - ", repeat); int ret = ::ioctl(m_fd, VIDEO_SLOWMOTION, repeat); if (ret < 0) eDebug("failed(%m)"); @@ -499,8 +482,7 @@ int eDVBVideo::setSlowMotion(int repeat) int eDVBVideo::setFastForward(int skip) { - eDebugNoNewLine("VIDEO_FAST_FORWARD - "); - m_is_fast_forward = skip; + eDebugNoNewLine("VIDEO_FAST_FORWARD(%d) - ", skip); int ret = ::ioctl(m_fd, VIDEO_FAST_FORWARD, skip); if (ret < 0) eDebug("failed(%m)"); @@ -527,11 +509,6 @@ int eDVBVideo::getPTS(pts_t &now) eDVBVideo::~eDVBVideo() { - if (m_is_slow_motion) - setSlowMotion(0); - if (m_is_fast_forward) - setFastForward(0); - unfreeze(); if (m_fd >= 0) ::close(m_fd); if (m_fd_demux >= 0) @@ -750,14 +727,14 @@ int eTSMPEGDecoder::setState() { int res = 0; - int noaudio = m_is_sm || m_is_ff || m_is_trickmode; + int noaudio = (m_state != statePlay) && (m_state != statePause); int nott = noaudio; /* actually same conditions */ if ((noaudio && m_audio) || (!m_audio && !noaudio)) - m_changed |= changeAudio; + m_changed |= changeAudio | changeState; if ((nott && m_text) || (!m_text && !nott)) - m_changed |= changeText; + m_changed |= changeText | changeState; bool changed = !!m_changed; #if HAVE_DVB_API_VERSION < 3 @@ -900,6 +877,39 @@ int eTSMPEGDecoder::setState() m_changed &= ~changeText; } #endif + + if (m_changed & changeState) + { + /* play, slowmotion, fast-forward */ + int state_table[6][4] = + { + /* [stateStop] = */ {0, 0, 0}, + /* [statePause] = */ {0, 0, 0}, + /* [statePlay] = */ {1, 0, 0}, + /* [stateDecoderFastForward] = */ {1, 0, m_ff_sm_ratio}, + /* [stateHighspeedFastForward] = */ {1, 0, 1}, + /* [stateSlowMotion] = */ {1, m_ff_sm_ratio, 0} + }; + int *s = state_table[m_state]; + if (m_video) + { + m_video->setSlowMotion(s[1]); + m_video->setFastForward(s[2]); + if (s[0]) + m_video->unfreeze(); + else + m_video->freeze(); + } + if (m_audio) + { + if (s[0]) + m_audio->unfreeze(); + else + m_audio->freeze(); + } + m_changed &= ~changeState; + } + if (changed && !m_video && m_audio && m_radio_pic.length()) showSinglePic(m_radio_pic.c_str()); @@ -946,7 +956,7 @@ eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder) { demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event_conn); CONNECT(m_showSinglePicTimer->timeout, eTSMPEGDecoder::finishShowSinglePic); - m_is_ff = m_is_sm = m_is_trickmode = 0; + m_state = stateStop; } eTSMPEGDecoder::~eTSMPEGDecoder() @@ -1028,82 +1038,61 @@ RESULT eTSMPEGDecoder::setSyncMaster(int who) return -1; } -RESULT eTSMPEGDecoder::start() -{ - RESULT r; - r = setState(); - if (r) - return r; - return unfreeze(); -} - - /* preroll is start in freezed mode. */ -RESULT eTSMPEGDecoder::preroll() +RESULT eTSMPEGDecoder::set() { return setState(); } -RESULT eTSMPEGDecoder::freeze(int cont) -{ - if (m_video) - m_video->freeze(); - - if (m_audio) - m_audio->freeze(); - - return 0; -} - -RESULT eTSMPEGDecoder::unfreeze() -{ - if (m_video) - m_video->unfreeze(); - - if (m_audio) - m_audio->unfreeze(); - - return 0; -} - -RESULT eTSMPEGDecoder::setSinglePictureMode(int when) +RESULT eTSMPEGDecoder::play() { - return -1; + if (m_state == statePlay) + return 0; + m_state = statePlay; + m_changed |= changeState; + return setState(); } -RESULT eTSMPEGDecoder::setPictureSkipMode(int what) +RESULT eTSMPEGDecoder::pause() { - return -1; + if (m_state == statePause) + return 0; + m_state = statePause; + m_changed |= changeState; + return setState(); } RESULT eTSMPEGDecoder::setFastForward(int frames_to_skip) { - m_is_ff = frames_to_skip != 0; + if ((m_state == stateDecoderFastForward) && (m_ff_sm_ratio == frames_to_skip)) + return 0; - setState(); - unfreeze(); // audio might be restarted and still in preroll (freezed) state. + m_state = stateDecoderFastForward; + m_ff_sm_ratio = frames_to_skip; + m_changed |= changeState; + return setState(); - if (m_video) - return m_video->setFastForward(frames_to_skip); - else - return -1; +// return m_video->setFastForward(frames_to_skip); } RESULT eTSMPEGDecoder::setSlowMotion(int repeat) { - m_is_sm = repeat != 0; + if ((m_state == stateSlowMotion) && (m_ff_sm_ratio == repeat)) + return 0; - setState(); - unfreeze(); // audio might be restarted and still in preroll (freezed) state. - - if (m_video) - return m_video->setSlowMotion(repeat); - else - return -1; + m_state = stateSlowMotion; + m_ff_sm_ratio = repeat; + m_changed |= changeState; + return setState(); } -RESULT eTSMPEGDecoder::setZoom(int what) +RESULT eTSMPEGDecoder::setTrickmode() { - return -1; + if (m_state == stateTrickmode) + return 0; + + m_state = stateTrickmode; + m_changed |= changeState; + return setState(); } RESULT eTSMPEGDecoder::flush() @@ -1127,13 +1116,6 @@ void eTSMPEGDecoder::demux_event(int event) } } -RESULT eTSMPEGDecoder::setTrickmode(int what) -{ - m_is_trickmode = what; - setState(); - return 0; -} - RESULT eTSMPEGDecoder::getPTS(int what, pts_t &pts) { if (what == 0) /* auto */ diff --git a/lib/dvb/decoder.h b/lib/dvb/decoder.h index 05e07ef9..04501fe6 100644 --- a/lib/dvb/decoder.h +++ b/lib/dvb/decoder.h @@ -119,10 +119,12 @@ private: changeVideo = 1, changeAudio = 2, changePCR = 4, - changeText = 8 + changeText = 8, + changeState = 16, }; int m_changed, m_decoder; - int m_is_ff, m_is_sm, m_is_trickmode; + int m_state; + int m_ff_sm_ratio; int setState(); ePtr m_demux_event_conn; ePtr m_video_event_conn; @@ -148,17 +150,33 @@ public: RESULT setSyncPCR(int pcrpid); RESULT setTextPID(int textpid); RESULT setSyncMaster(int who); - RESULT start(); - RESULT preroll(); - RESULT freeze(int cont); - RESULT unfreeze(); - RESULT setSinglePictureMode(int when); - RESULT setPictureSkipMode(int what); - RESULT setFastForward(int frames_to_skip); - RESULT setSlowMotion(int repeat); - RESULT setZoom(int what); + + /* + The following states exist: + + - stop: data source closed, no playback + - pause: data source active, decoder paused + - play: data source active, decoder consuming + - decoder fast forward: data source linear, decoder drops frames + - trickmode, highspeed reverse: data source fast forwards / reverses, decoder just displays frames as fast as it can + - slow motion: decoder displays frames multiple times + */ + enum { + stateStop, + statePause, + statePlay, + stateDecoderFastForward, + stateTrickmode, + stateSlowMotion + }; + RESULT set(); /* just apply settings, keep state */ + RESULT play(); /* -> play */ + RESULT pause(); /* -> pause */ + RESULT setFastForward(int frames_to_skip); /* -> decoder fast forward */ + RESULT setSlowMotion(int repeat); /* -> slow motion **/ + RESULT setTrickmode(); /* -> highspeed fast forward */ + RESULT flush(); - RESULT setTrickmode(int what); RESULT showSinglePic(const char *filename); RESULT setRadioPic(const std::string &filename); /* what 0=auto, 1=video, 2=audio. */ diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h index cda05894..bd1c7035 100644 --- a/lib/dvb/idvb.h +++ b/lib/dvb/idvb.h @@ -662,37 +662,24 @@ public: /** Set Sync mode to either audio or video master */ virtual RESULT setSyncMaster(int who)=0; - /** Apply settings with starting video */ - virtual RESULT start()=0; - /** Apply settings but don't start yet */ - virtual RESULT preroll()=0; + /** Apply settings but don't change state */ + virtual RESULT set()=0; + /* all those apply settings, then transition to the given state */ - /** Freeze frame. Either continue decoding (without display) or halt. */ - virtual RESULT freeze(int cont)=0; - /** Continue after freeze. */ - virtual RESULT unfreeze()=0; + /** play */ + virtual RESULT play()=0; + /** Freeze frame. */ + virtual RESULT pause()=0; /** fast forward by skipping frames. 0 is disabled, 2 is twice-the-speed, ... */ virtual RESULT setFastForward(int skip=0)=0; - // stop on .. Picture - enum { spm_I, spm_Ref, spm_Any }; - /** Stop on specific decoded picture. For I-Frame display. */ - virtual RESULT setSinglePictureMode(int when)=0; - - enum { pkm_B, pkm_PB }; - /** Fast forward by skipping either B or P/B pictures */ - virtual RESULT setPictureSkipMode(int what)=0; - /** Slow Motion by repeating pictures */ virtual RESULT setSlowMotion(int repeat)=0; - - enum { zoom_Normal, zoom_PanScan, zoom_Letterbox, zoom_Fullscreen }; - /** Set Zoom. mode *must* be fitting. */ - virtual RESULT setZoom(int what)=0; - - virtual RESULT setTrickmode(int what) = 0; + /** Display any complete data as fast as possible */ + virtual RESULT setTrickmode()=0; + virtual RESULT getPTS(int what, pts_t &pts) = 0; virtual RESULT showSinglePic(const char *filename) = 0; diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index cdaa2c1e..409018de 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -779,12 +779,21 @@ class InfoBarSeek: print "not pauseable." state = self.SEEK_STATE_PLAY - oldstate = self.seekstate self.seekstate = state - for i in range(3): - if oldstate[i] != self.seekstate[i]: - (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i]) + if pauseable is not None: + if self.seekstate[0]: + print "resolved to PAUSE" + pauseable.pause() + elif self.seekstate[1]: + print "resolved to FAST FORWARD" + pauseable.setFastForward(self.seekstate[1]) + elif self.seekstate[2]: + print "resolved to SLOW MOTION" + pauseable.setSlowMotion(self.seekstate[2]) + else: + print "resolved to PLAY" + pauseable.unpause() for c in self.onPlayStateChanged: c(self.seekstate) diff --git a/lib/service/iservice.h b/lib/service/iservice.h index 02fc4508..e27752a2 100644 --- a/lib/service/iservice.h +++ b/lib/service/iservice.h @@ -392,6 +392,8 @@ class iPauseableService: public iObject ~iPausableService(); #endif public: + + /* this will set the *state* directly. So just call a SINGLE function of those at a time. */ virtual RESULT pause()=0; virtual RESULT unpause()=0; diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 7e6c0337..af3ab206 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -1281,7 +1281,9 @@ RESULT eDVBServicePlay::pause(ePtr &ptr) RESULT eDVBServicePlay::setSlowMotion(int ratio) { + assert(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */ eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio); + setFastForward_internal(0); if (m_decoder) return m_decoder->setSlowMotion(ratio); else @@ -1291,6 +1293,12 @@ RESULT eDVBServicePlay::setSlowMotion(int ratio) RESULT eDVBServicePlay::setFastForward(int ratio) { eDebug("eDVBServicePlay::setFastForward(%d)", ratio); + assert(ratio); + return setFastForward_internal(ratio); +} + +RESULT eDVBServicePlay::setFastForward_internal(int ratio) +{ int skipmode, ffratio; if (ratio > 8) @@ -1323,7 +1331,12 @@ RESULT eDVBServicePlay::setFastForward(int ratio) if (!m_decoder) return -1; - return m_decoder->setFastForward(ffratio); + if (ffratio == 0) + return 0; + else if (ffratio != 1) + return m_decoder->setFastForward(ffratio); + else + return m_decoder->setTrickmode(); } RESULT eDVBServicePlay::seek(ePtr &ptr) @@ -1352,10 +1365,10 @@ RESULT eDVBServicePlay::getLength(pts_t &len) RESULT eDVBServicePlay::pause() { eDebug("eDVBServicePlay::pause"); - if (!m_is_paused && m_decoder) + setFastForward_internal(0); + if (m_decoder) { - m_is_paused = 1; - return m_decoder->freeze(0); + return m_decoder->pause(); } else return -1; } @@ -1363,10 +1376,10 @@ RESULT eDVBServicePlay::pause() RESULT eDVBServicePlay::unpause() { eDebug("eDVBServicePlay::unpause"); - if (m_is_paused && m_decoder) + setFastForward_internal(0); + if (m_decoder) { - m_is_paused = 0; - return m_decoder->unfreeze(); + return m_decoder->play(); } else return -1; } @@ -1448,9 +1461,8 @@ RESULT eDVBServicePlay::getPlayPosition(pts_t &pos) RESULT eDVBServicePlay::setTrickmode(int trick) { - if (m_decoder) - m_decoder->setTrickmode(trick); - return 0; + /* currently unimplemented */ + return -1; } RESULT eDVBServicePlay::isCurrentlySeekable() @@ -1761,7 +1773,7 @@ RESULT eDVBServicePlay::selectTrack(unsigned int i) { int ret = selectAudioStream(i); - if (m_decoder->start()) + if (m_decoder->play()) return -5; return ret; @@ -2486,12 +2498,12 @@ void eDVBServicePlay::updateDecoder() m_teletext_parser->start(program.textPid); if (!m_is_primary) - m_decoder->setTrickmode(1); + m_decoder->setTrickmode(); if (m_is_paused) - m_decoder->preroll(); + m_decoder->pause(); else - m_decoder->start(); + m_decoder->play(); if (vpid > 0 && vpid < 0x2000) ; diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h index d19b92d6..c19e1ed5 100644 --- a/lib/service/servicedvb.h +++ b/lib/service/servicedvb.h @@ -218,6 +218,7 @@ private: int m_current_audio_stream; int selectAudioStream(int n = -1); + RESULT setFastForward_internal(int ratio); /* timeshift */ ePtr m_record; -- cgit v1.2.3 From dce87891f204f8e1f7151c4a3ba00b9dd048e795 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Fri, 13 Feb 2009 03:41:57 +0100 Subject: - While recording, collect startcodes and save them into ".sc"-files - this allows finding iframes for fast forward/reverse more easily - when in fast forward, strictly just output good (=complete iframes) data (this might break dm7025, we will fix this later) - draw smaller, fixed-size bar in position gauge --- lib/dvb/decoder.cpp | 4 +- lib/dvb/demux.cpp | 28 ++- lib/dvb/demux.h | 2 +- lib/dvb/dvb.cpp | 56 +++-- lib/dvb/idemux.h | 2 +- lib/dvb/pvrparse.cpp | 302 ++++++++++++++++++++------ lib/dvb/pvrparse.h | 26 ++- lib/dvb/tstools.cpp | 70 +++++- lib/dvb/tstools.h | 2 + lib/gui/epositiongauge.cpp | 2 +- lib/python/Components/Converter/StringList.py | 6 + lib/python/Components/Renderer/Listbox.py | 4 + lib/service/servicedvb.cpp | 18 +- lib/service/servicedvbrecord.cpp | 10 +- 14 files changed, 416 insertions(+), 116 deletions(-) (limited to 'lib/python') diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index 6f0ead65..a4cffb77 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -1071,7 +1071,9 @@ RESULT eTSMPEGDecoder::setAC3Delay(int delay) } eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemux *demux, int decoder) - :m_demux(demux), m_changed(0), m_decoder(decoder), m_video_clip_fd(-1), m_showSinglePicTimer(eTimer::create(eApp)) + : m_demux(demux), + m_vpid(-1), m_vtype(-1), m_apid(-1), m_atype(-1), m_pcrpid(-1), m_textpid(-1), + m_changed(0), m_decoder(decoder), m_video_clip_fd(-1), m_showSinglePicTimer(eTimer::create(eApp)) { demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event_conn); CONNECT(m_showSinglePicTimer->timeout, eTSMPEGDecoder::finishShowSinglePic); diff --git a/lib/dvb/demux.cpp b/lib/dvb/demux.cpp index 810b10a5..918ecec6 100644 --- a/lib/dvb/demux.cpp +++ b/lib/dvb/demux.cpp @@ -402,9 +402,10 @@ class eDVBRecordFileThread: public eFilePushThread { public: eDVBRecordFileThread(); - void setTimingPID(int pid); + void setTimingPID(int pid, int type); - void saveTimingInformation(const std::string &filename); + void startSaveMetaInformation(const std::string &filename); + void stopSaveMetaInformation(); int getLastPTS(pts_t &pts); protected: int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining); @@ -422,14 +423,19 @@ eDVBRecordFileThread::eDVBRecordFileThread() m_current_offset = 0; } -void eDVBRecordFileThread::setTimingPID(int pid) +void eDVBRecordFileThread::setTimingPID(int pid, int type) { - m_ts_parser.setPid(pid); + m_ts_parser.setPid(pid, type); } -void eDVBRecordFileThread::saveTimingInformation(const std::string &filename) +void eDVBRecordFileThread::startSaveMetaInformation(const std::string &filename) { - m_stream_info.save(filename.c_str()); + m_stream_info.startSave(filename.c_str()); +} + +void eDVBRecordFileThread::stopSaveMetaInformation() +{ + m_stream_info.stopSave(); } int eDVBRecordFileThread::getLastPTS(pts_t &pts) @@ -520,6 +526,9 @@ RESULT eDVBTSRecorder::start() ::ioctl(m_source_fd, DMX_START); #endif + + if (m_target_filename != "") + m_thread->startSaveMetaInformation(m_target_filename); m_thread->start(m_source_fd, m_target_fd); m_running = 1; @@ -553,11 +562,11 @@ RESULT eDVBTSRecorder::removePID(int pid) return 0; } -RESULT eDVBTSRecorder::setTimingPID(int pid) +RESULT eDVBTSRecorder::setTimingPID(int pid, int type) { if (m_running) return -1; - m_thread->setTimingPID(pid); + m_thread->setTimingPID(pid, type); return 0; } @@ -590,8 +599,7 @@ RESULT eDVBTSRecorder::stop() close(m_source_fd); m_source_fd = -1; - if (m_target_filename != "") - m_thread->saveTimingInformation(m_target_filename + ".ap"); + m_thread->stopSaveMetaInformation(); return 0; } diff --git a/lib/dvb/demux.h b/lib/dvb/demux.h index 14501b98..7a697d49 100644 --- a/lib/dvb/demux.h +++ b/lib/dvb/demux.h @@ -94,7 +94,7 @@ public: RESULT addPID(int pid); RESULT removePID(int pid); - RESULT setTimingPID(int pid); + RESULT setTimingPID(int pid, int type); RESULT setTargetFD(int fd); RESULT setTargetFilename(const char *filename); diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index c320fc78..4bbed519 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -974,7 +974,7 @@ int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, s } #endif -#if 1 /* This codepath is required on Broadcom-based Dreamboxes (DM800, DM8000) and strips away non-I-frames. */ +#if 0 if (!m_iframe_search) return len; @@ -1272,6 +1272,21 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m); current_offset += align(m_skipmode_m, blocksize); + + if (m_skipmode_m) + { + eDebug("we are at %llx, and we try to find the iframe here:", current_offset); + size_t iframe_len; + off_t iframe_start = current_offset; + + if (m_tstools.findIFrame(iframe_start, iframe_len, (m_skipmode_m < 0) ? -1 : +1)) + eDebug("failed"); + else + { + current_offset = align(iframe_start, blocksize); + max = align(iframe_len, blocksize); + } + } while (!m_cue->m_seek_requests.empty()) { @@ -1348,6 +1363,10 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off eDebug("get offset for pts=%lld failed!", pts); continue; } + + size_t iframe_len; + /* try to align to iframe */ + m_tstools.findIFrame(offset, iframe_len, pts < 0 ? -1 : 1); 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 */ @@ -1417,30 +1436,23 @@ void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off } } - if (m_source_span.empty()) { - if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0)) - { - eDebug("reached SOF"); - m_skipmode_m = 0; - m_pvr_thread->sendEvent(eFilePushThread::evtUser); - } + if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0)) + { + eDebug("reached SOF"); + m_skipmode_m = 0; + m_pvr_thread->sendEvent(eFilePushThread::evtUser); + } + + if (m_source_span.empty()) + { start = current_offset; size = max; - } else { - off_t tmp2, tmp = align(m_source_span.rbegin()->second, blocksize); - pts_t len; - getLength(len); - m_tstools.getOffset(tmp2, len, 1); - if (current_offset == tmp || current_offset == tmp2) { - start = tmp2; - size = max; - } else { - start = tmp - align(512*1024, blocksize); - size = align(512*1024, blocksize); - } + eDebug("NO CUESHEET. (%08llx, %d)", start, size); + } else + { + start = current_offset; + size = 0; } - - eDebug("END OF CUESHEET. (%08llx, %d)", start, size); return; } diff --git a/lib/dvb/idemux.h b/lib/dvb/idemux.h index 9432afb6..e92b1e75 100644 --- a/lib/dvb/idemux.h +++ b/lib/dvb/idemux.h @@ -30,7 +30,7 @@ public: virtual RESULT addPID(int pid) = 0; virtual RESULT removePID(int pid) = 0; - virtual RESULT setTimingPID(int pid) = 0; + virtual RESULT setTimingPID(int pid, int type) = 0; virtual RESULT setTargetFD(int fd) = 0; /* for saving additional meta data. */ diff --git a/lib/dvb/pvrparse.cpp b/lib/dvb/pvrparse.cpp index 71cbd602..1393bf77 100644 --- a/lib/dvb/pvrparse.cpp +++ b/lib/dvb/pvrparse.cpp @@ -6,9 +6,36 @@ #error no byte order defined! #endif -int eMPEGStreamInformation::save(const char *filename) +eMPEGStreamInformation::eMPEGStreamInformation() + : m_structure_cache_valid(0), m_structure_read(0), m_structure_write(0) { - FILE *f = fopen(filename, "wb"); +} + +eMPEGStreamInformation::~eMPEGStreamInformation() +{ + if (m_structure_read) + fclose(m_structure_read); + if (m_structure_write) + fclose(m_structure_write); +} + +int eMPEGStreamInformation::startSave(const char *filename) +{ + m_filename = filename; + m_structure_write = fopen((m_filename + ".sc").c_str(), "wb"); + return 0; +} + +int eMPEGStreamInformation::stopSave(void) +{ + if (m_structure_write) + { + fclose(m_structure_write); + m_structure_write = 0; + } + if (m_filename == "") + return -1; + FILE *f = fopen((m_filename + ".ap").c_str(), "wb"); if (!f) return -1; @@ -31,7 +58,11 @@ int eMPEGStreamInformation::save(const char *filename) int eMPEGStreamInformation::load(const char *filename) { - FILE *f = fopen(filename, "rb"); + m_filename = filename; + if (m_structure_read) + fclose(m_structure_read); + m_structure_read = fopen((std::string(m_filename) + ".sc").c_str(), "rb"); + FILE *f = fopen((std::string(m_filename) + ".ap").c_str(), "rb"); if (!f) return -1; m_access_points.clear(); @@ -284,6 +315,117 @@ int eMPEGStreamInformation::getNextAccessPoint(pts_t &ts, const pts_t &start, in return 0; } +void eMPEGStreamInformation::writeStructureEntry(off_t offset, structure_data data) +{ + unsigned long long d[2]; +#if BYTE_ORDER == BIG_ENDIAN + d[0] = offset; + d[1] = data; +#else + d[0] = bswap_64(offset); + d[1] = bswap_64(data); +#endif + if (m_structure_write) + fwrite(d, sizeof(d), 1, m_structure_write); +} + +int eMPEGStreamInformation::getStructureEntry(off_t &offset, unsigned long long &data, int get_next) +{ + if (!m_structure_read) + { + eDebug("getStructureEntry failed because of no m_structure_read"); + return -1; + } + + const int struture_cache_entries = sizeof(m_structure_cache) / 16; + if ((!m_structure_cache_valid) || ((off_t)m_structure_cache[0] > offset) || ((off_t)m_structure_cache[(struture_cache_entries - (get_next ? 2 : 1)) * 2] <= offset)) + { + fseek(m_structure_read, 0, SEEK_END); + int l = ftell(m_structure_read); + unsigned long long d[2]; + const int entry_size = sizeof d; + + /* do a binary search */ + int count = l / entry_size; + int i = 0; + + while (count) + { + int step = count >> 1; + + fseek(m_structure_read, (i + step) * entry_size, SEEK_SET); + if (!fread(d, 1, entry_size, m_structure_read)) + { + eDebug("read error at entry %d", i); + return -1; + } + +#if BYTE_ORDER != BIG_ENDIAN + d[0] = bswap_64(d[0]); + d[1] = bswap_64(d[1]); +#endif +// eDebug("%d: %08llx > %llx", i, d[0], d[1]); + + if (d[0] < (unsigned long long)offset) + { + i += step + 1; + count -= step + 1; + } else + count = step; + } + + eDebug("found %d", i); + + /* put that in the middle */ + i -= struture_cache_entries / 2; + if (i < 0) + i = 0; + eDebug("cache starts at %d", i); + fseek(m_structure_read, i * entry_size, SEEK_SET); + int num = fread(m_structure_cache, entry_size, struture_cache_entries, m_structure_read); + eDebug("%d entries", num); + for (i = 0; i < struture_cache_entries; ++i) + { + if (i < num) + { +#if BYTE_ORDER != BIG_ENDIAN + m_structure_cache[i * 2] = bswap_64(m_structure_cache[i * 2]); + m_structure_cache[i * 2 + 1] = bswap_64(m_structure_cache[i * 2 + 1]); +#endif + } else + { + m_structure_cache[i * 2] = 0x7fffffffffffffffULL; /* fill with harmless content */ + m_structure_cache[i * 2 + 1] = 0; + } + } + m_structure_cache_valid = 1; + } + + int i = 0; + while ((off_t)m_structure_cache[i * 2] <= offset) + { + ++i; + if (i == struture_cache_entries) + { + eDebug("structure data consistency fail!, we are looking for %llx, but last entry is %llx", offset, m_structure_cache[i*2-2]); + return -1; + } + } + if (!i) + { + eDebug("structure data (first entry) consistency fail!"); + return -1; + } + + if (!get_next) + --i; + +// eDebug("[%d] looked for %llx, found %llx=%llx", sizeof offset, offset, m_structure_cache[i * 2], m_structure_cache[i * 2 + 1]); + offset = m_structure_cache[i * 2]; + data = m_structure_cache[i * 2 + 1]; + return 0; +} + eMPEGStreamParserTS::eMPEGStreamParserTS(eMPEGStreamInformation &streaminfo): m_streaminfo(streaminfo), m_pktptr(0), m_pid(-1), m_need_next_packet(0), m_skip(0), m_last_pts_valid(0) { } @@ -293,16 +435,15 @@ int eMPEGStreamParserTS::processPacket(const unsigned char *pkt, off_t offset) if (!wantPacket(pkt)) eWarning("something's wrong."); - const unsigned char *end = pkt + 188; + const unsigned char *end = pkt + 188, *begin = pkt; - if (!(pkt[3] & 0x10)) - { - eWarning("[TSPARSE] PUSI set but no payload."); - return 0; - } + int pusi = !!(pkt[1] & 0x40); - if (pkt[3] & 0x20) // adaption field present? - pkt += pkt[4] + 4 + 1; /* skip adaption field and header */ + if (!(pkt[3] & 0x10)) /* no payload? */ + return 0; + + if (pkt[3] & 0x20) // adaptation field present? + pkt += pkt[4] + 4 + 1; /* skip adaptation field and header */ else pkt += 4; /* skip header */ @@ -311,78 +452,96 @@ int eMPEGStreamParserTS::processPacket(const unsigned char *pkt, off_t offset) eWarning("[TSPARSE] dropping huge adaption field"); return 0; } - - // ok, we now have the start of the payload, aligned with the PES packet start. - if (pkt[0] || pkt[1] || (pkt[2] != 1)) - { - eWarning("broken startcode"); - return 0; - } - - + pts_t pts = 0; int ptsvalid = 0; - if (pkt[7] & 0x80) // PTS present? + if (pusi) { - pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29; - pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22; - pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14; - pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7; - pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1; - ptsvalid = 1; - - m_last_pts = pts; - m_last_pts_valid = 1; - -#if 0 - int sec = pts / 90000; - int frm = pts % 90000; - int min = sec / 60; - sec %= 60; - int hr = min / 60; - min %= 60; - int d = hr / 24; - hr %= 24; + // ok, we now have the start of the payload, aligned with the PES packet start. + if (pkt[0] || pkt[1] || (pkt[2] != 1)) + { + eWarning("broken startcode"); + return 0; + } + + if (pkt[7] & 0x80) // PTS present? + { + pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29; + pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22; + pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14; + pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7; + pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1; + ptsvalid = 1; + + m_last_pts = pts; + m_last_pts_valid = 1; + + #if 0 + int sec = pts / 90000; + int frm = pts % 90000; + int min = sec / 60; + sec %= 60; + int hr = min / 60; + min %= 60; + int d = hr / 24; + hr %= 24; + + eDebug("pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm); + #endif + } - eDebug("pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm); -#endif + /* advance to payload */ + pkt += pkt[8] + 9; } - - /* advance to payload */ - pkt += pkt[8] + 9; - /* sometimes, there are zeros before the startcode. */ while (pkt < (end-4)) - if (pkt[0] || pkt[1] || pkt[2]) - break; - else - pkt++; - - /* if startcode found */ -// eDebug("%02x %02x %02x %02x", pkt[0], pkt[1], pkt[2], pkt[3]); - if (!(pkt[0] || pkt[1] || (pkt[2] != 1))) { - if (pkt[3] == 0xb3) /* sequence header */ + int pkt_offset = pkt - begin; + if (!(pkt[0] || pkt[1] || (pkt[2] != 1))) { - if (ptsvalid) +// eDebug("SC %02x %02x %02x %02x, %02x", pkt[0], pkt[1], pkt[2], pkt[3], pkt[4]); + int sc = pkt[3]; + + if (m_streamtype == 0) /* mpeg2 */ { - m_streaminfo.m_access_points[offset] = pts; -// eDebug("Sequence header at %llx, pts %llx", offset, pts); - } else - /*eDebug("Sequence header but no valid PTS value.")*/; - } + if ((sc == 0x00) || (sc == 0xb3) || (sc == 0xb8)) /* picture, sequence, group start code */ + { + unsigned long long data = sc | (pkt[4] << 8) | (pkt[5] << 16) | (pkt[6] << 24); + m_streaminfo.writeStructureEntry(offset + pkt_offset, data & 0xFFFFFFFFULL); + } + if (pkt[3] == 0xb3) /* sequence header */ + { + if (ptsvalid) + { + m_streaminfo.m_access_points[offset] = pts; + // eDebug("Sequence header at %llx, pts %llx", offset, pts); + } else + /*eDebug("Sequence header but no valid PTS value.")*/; + } + } - if (pkt[3] == 0x09 && /* MPEG4 AVC unit access delimiter */ - (pkt[4] >> 5) == 0) /* and I-frame */ - { - if (ptsvalid) + if (m_streamtype == 1) /* H.264 */ { - m_streaminfo.m_access_points[offset] = pts; -// eDebug("MPEG4 AVC UAD at %llx, pts %llx", offset, pts); - } else - /*eDebug("MPEG4 AVC UAD but no valid PTS value.")*/; + if (sc == 0x09) + { + /* store image type */ + unsigned long long data = sc | (pkt[4] << 8); + m_streaminfo.writeStructureEntry(offset + pkt_offset, data); + } + if (pkt[3] == 0x09 && /* MPEG4 AVC NAL unit access delimiter */ + (pkt[4] >> 5) == 0) /* and I-frame */ + { + if (ptsvalid) + { + m_streaminfo.m_access_points[offset] = pts; + // eDebug("MPEG4 AVC UAD at %llx, pts %llx", offset, pts); + } else + /*eDebug("MPEG4 AVC UAD but no valid PTS value.")*/; + } + } } + ++pkt; } return 0; } @@ -405,7 +564,7 @@ inline int eMPEGStreamParserTS::wantPacket(const unsigned char *hdr) const if (hdr[1] & 0x40) /* pusi set: yes. */ return 1; - return 0; + return m_streamtype == 0; /* we need all packets for MPEG2, but only PUSI packets for H.264 */ } void eMPEGStreamParserTS::parseData(off_t offset, const void *data, unsigned int len) @@ -520,10 +679,11 @@ void eMPEGStreamParserTS::parseData(off_t offset, const void *data, unsigned int } } -void eMPEGStreamParserTS::setPid(int _pid) +void eMPEGStreamParserTS::setPid(int _pid, int type) { m_pktptr = 0; m_pid = _pid; + m_streamtype = type; } int eMPEGStreamParserTS::getLastPTS(pts_t &last_pts) diff --git a/lib/dvb/pvrparse.h b/lib/dvb/pvrparse.h index 20d33470..28c0314a 100644 --- a/lib/dvb/pvrparse.h +++ b/lib/dvb/pvrparse.h @@ -12,6 +12,8 @@ class eMPEGStreamInformation { public: + eMPEGStreamInformation(); + ~eMPEGStreamInformation(); /* we order by off_t here, since the timestamp may */ /* wrap around. */ /* we only record sequence start's pts values here. */ @@ -23,7 +25,8 @@ public: /* these are non-fixed up pts value (like m_access_points), just used to accelerate stuff. */ std::multimap m_pts_to_offset; - int save(const char *filename); + int startSave(const char *filename); + int stopSave(void); int load(const char *filename); /* recalculates timestampDeltas */ @@ -46,6 +49,23 @@ public: int getNextAccessPoint(pts_t &ts, const pts_t &start, int direction); bool empty(); + + typedef unsigned long long structure_data; + /* this is usually: + sc | (other_information << 8) + but is really specific to the used video encoder. + */ + void writeStructureEntry(off_t offset, structure_data data); + + /* get a structure entry at given offset (or previous one, if no exact match was found). + optionall, return next element. Offset will be returned. this allows you to easily + get previous and next structure elements. */ + int getStructureEntry(off_t &offset, unsigned long long &data, int get_next); + + std::string m_filename; + int m_structure_cache_valid; + unsigned long long m_structure_cache[1024]; + FILE *m_structure_read, *m_structure_write; }; /* Now we define the parser's state: */ @@ -54,7 +74,7 @@ class eMPEGStreamParserTS public: eMPEGStreamParserTS(eMPEGStreamInformation &streaminfo); void parseData(off_t offset, const void *data, unsigned int len); - void setPid(int pid); + void setPid(int pid, int streamtype); int getLastPTS(pts_t &last_pts); private: eMPEGStreamInformation &m_streaminfo; @@ -62,7 +82,7 @@ private: int m_pktptr; int processPacket(const unsigned char *pkt, off_t offset); inline int wantPacket(const unsigned char *hdr) const; - int m_pid; + int m_pid, m_streamtype; int m_need_next_packet; int m_skip; int m_last_pts_valid; diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index bd7ebce2..7ac86f08 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -32,7 +32,10 @@ int eDVBTSTools::openFile(const char *filename, int nostreaminfo) closeFile(); if (!nostreaminfo) - m_streaminfo.load((std::string(filename) + ".ap").c_str()); + { + eDebug("loading streaminfo for %s", filename); + m_streaminfo.load(filename); + } if (!m_streaminfo.empty()) m_use_streaminfo = 1; @@ -562,3 +565,68 @@ int eDVBTSTools::findPMT(int &pmt_pid, int &service_id) return -1; } + +int eDVBTSTools::findIFrame(off_t &_offset, size_t &len, int direction) +{ + off_t offset = _offset; +// eDebug("trying to find iFrame at %llx", offset); + + if (!m_use_streaminfo) + { + eDebug("can't get next iframe without streaminfo"); + return -1; + } + + /* let's find the iframe before the given offset */ + unsigned long long data; + while (1) + { + if (m_streaminfo.getStructureEntry(offset, data, (direction == 0) ? 1 : 0)) + { + eDebug("getting structure info for origin offset failed."); + return -1; + } + if (offset == 0x7fffffffffffffffLL) /* eof */ + { + eDebug("reached eof"); + return -1; + } + /* data is usually the start code in the lower 8 bit, and the next byte <<8. we extract the picture type from there */ + /* we know that we aren't recording startcode 0x09 for mpeg2, so this is safe */ + int is_start = (data & 0xE0FF) == 0x0009; /* H.264 NAL unit access delimiter with I-frame*/ + is_start |= (data & 0x3800FF) == 0x080000; /* MPEG2 picture start code with I-frame */ +// eDebug("%08llx@%llx -> %d", data, offset, is_start); + if (is_start) + break; + + if (direction == -1) + --offset; /* move to previous entry */ + else if (direction == +1) + direction = 0; + } + /* let's find the next frame after the given offset */ + off_t start = offset; + + do { + if (m_streaminfo.getStructureEntry(offset, data, 1)) + { + eDebug("get next failed"); + return -1; + } + if (offset == 0x7fffffffffffffffLL) /* eof */ + { + eDebug("reached eof (while looking for end of iframe)"); + return -1; + } +// eDebug("%08llx@%llx", data, offset); + } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00)); /* next frame */ + + /* align to TS pkt start */ + start = start - (start % 188); + offset = offset - (offset % 188); + + len = offset - start; + _offset = start; +// eDebug("result: offset=%llx, len: %ld", offset, (int)len); + return 0; +} diff --git a/lib/dvb/tstools.h b/lib/dvb/tstools.h index 4bc04729..a8e0751e 100644 --- a/lib/dvb/tstools.h +++ b/lib/dvb/tstools.h @@ -55,6 +55,8 @@ public: int takeSample(off_t off, pts_t &p); int findPMT(int &pmt_pid, int &service_id); + + int findIFrame(off_t &offset, size_t &len, int direction); private: int m_pid; int m_maxrange; diff --git a/lib/gui/epositiongauge.cpp b/lib/gui/epositiongauge.cpp index b3ee5111..ff98c080 100644 --- a/lib/gui/epositiongauge.cpp +++ b/lib/gui/epositiongauge.cpp @@ -144,7 +144,7 @@ int ePositionGauge::event(int event, void *data, void *data2) { painter.setForegroundColor(gRGB(m_foreground_color)); int xi = scale(in), xo = scale(out); - painter.fill(eRect(xi, 10, xo-xi, s.height()-14)); + painter.fill(eRect(xi, (s.height()-4) / 2, xo-xi, 4)); } in = m_length; diff --git a/lib/python/Components/Converter/StringList.py b/lib/python/Components/Converter/StringList.py index c9488db0..08794b34 100644 --- a/lib/python/Components/Converter/StringList.py +++ b/lib/python/Components/Converter/StringList.py @@ -19,8 +19,11 @@ class StringList(Converter): def selectionChanged(self, index): self.source.selectionChanged(index) # update all non-master targets + print "changed selection in listbox!" for x in self.downstream_elements: + print "downstream element", x if x is not self.master: + print "is not master, so update to index", index x.index = index @cached @@ -43,3 +46,6 @@ class StringList(Converter): self.master.index = index index = property(getIndex, setIndex) + + def entry_changed(self, index): + self.downstream_elements.entry_changed(index) \ No newline at end of file diff --git a/lib/python/Components/Renderer/Listbox.py b/lib/python/Components/Renderer/Listbox.py index 8e510b4c..7a895330 100644 --- a/lib/python/Components/Renderer/Listbox.py +++ b/lib/python/Components/Renderer/Listbox.py @@ -78,3 +78,7 @@ class Listbox(Renderer, object): def changed(self, what): self.content = self.source.content + + def entry_changed(self, index): + if self.instance is not None: + self.instance.entryChanged(index) diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 33cd865e..e3d960d4 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -370,13 +370,17 @@ int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref) struct stat s; stat(ref.path.c_str(), &s); - if (tstools.openFile(ref.path.c_str())) + if (tstools.openFile(ref.path.c_str(), 1)) return 0; /* 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 */ + if (tstools.openFile(ref.path.c_str())) + return 0; + /* otherwise, re-calc length and update meta file */ pts_t len; if (tstools.calcLen(len)) @@ -502,6 +506,7 @@ RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list= 0)) + { + eDebug("timeshift EOF, so let's go live"); switchToLive(); + } break; } } @@ -1173,9 +1181,9 @@ RESULT eDVBServicePlay::setFastForward_internal(int ratio) if (!m_decoder) return -1; - + if (ffratio == 0) - return 0; + return m_decoder->play(); else if (ffratio != 1) return m_decoder->setFastForward(ffratio); else @@ -1211,6 +1219,7 @@ RESULT eDVBServicePlay::pause() setFastForward_internal(0); if (m_decoder) { + m_is_paused = 1; return m_decoder->pause(); } else return -1; @@ -1222,6 +1231,7 @@ RESULT eDVBServicePlay::unpause() setFastForward_internal(0); if (m_decoder) { + m_is_paused = 0; return m_decoder->play(); } else return -1; @@ -2136,6 +2146,8 @@ void eDVBServicePlay::switchToLive() if (!m_timeshift_active) return; + eDebug("SwitchToLive"); + m_cue = 0; m_decoder = 0; m_decode_demux = 0; diff --git a/lib/service/servicedvbrecord.cpp b/lib/service/servicedvbrecord.cpp index c2767e8d..5b7b5d8c 100644 --- a/lib/service/servicedvbrecord.cpp +++ b/lib/service/servicedvbrecord.cpp @@ -270,7 +270,7 @@ int eDVBServiceRecord::doRecord() if (program.pmtPid != -1) pids_to_record.insert(program.pmtPid); // PMT - int timing_pid = -1; + int timing_pid = -1, timing_pid_type = -1; eDebugNoNewLine("RECORD: have %d video stream(s)", program.videoStreams.size()); if (!program.videoStreams.empty()) @@ -283,7 +283,10 @@ int eDVBServiceRecord::doRecord() pids_to_record.insert(i->pid); if (timing_pid == -1) + { timing_pid = i->pid; + timing_pid_type = i->type; + } if (i != program.videoStreams.begin()) eDebugNoNewLine(", "); @@ -302,7 +305,10 @@ int eDVBServiceRecord::doRecord() pids_to_record.insert(i->pid); if (timing_pid == -1) + { timing_pid = i->pid; + timing_pid_type = -1; + } if (i != program.audioStreams.begin()) eDebugNoNewLine(", "); @@ -358,7 +364,7 @@ int eDVBServiceRecord::doRecord() } if (timing_pid != -1) - m_record->setTimingPID(timing_pid); + m_record->setTimingPID(timing_pid, timing_pid_type); m_pids_active = pids_to_record; -- cgit v1.2.3