diff --git a/NeoBoot/files/Harddisk.py b/NeoBoot/files/Harddisk.py
new file mode 100644
index 0000000..e0b4e91
--- /dev/null
+++ b/NeoBoot/files/Harddisk.py
@@ -0,0 +1,1048 @@
+# -*- coding: utf-8 -*-
+
+from Plugins.Extensions.NeoBoot.__init__ import _
+import os
+import time
+from Tools.Directories import fileExists, pathExists, fileCheck
+from Tools.CList import CList
+from Components.SystemInfo import SystemInfo
+from Components.Console import Console
+from Task import LoggingTask
+import Task
+from Screens.Screen import Screen
+from Components.ActionMap import ActionMap
+from Components.MenuList import MenuList
+from Components.Label import Label
+from Components.Pixmap import Pixmap
+from Screens.MessageBox import MessageBox
+
+def readFile(filename):
+ file = open(filename)
+ data = file.read().strip()
+ file.close()
+ return data
+
+
+def getProcMounts():
+ try:
+ mounts = open('/proc/mounts', 'r')
+ except IOError as ex:
+ print '[Harddisk] Failed to open /proc/mounts', ex
+ return []
+
+ result = [ line.strip().split(' ') for line in mounts ]
+ for item in result:
+ item[1] = item[1].replace('\\040', ' ')
+
+ return result
+
+
+def getNonNetworkMediaMounts():
+ return [ x[1] for x in getProcMounts() if x[1].startswith('/media/') and not x[0].startswith('//') ]
+
+
+def isFileSystemSupported(filesystem):
+ try:
+ for fs in open('/proc/filesystems', 'r'):
+ if fs.strip().endswith(filesystem):
+ return True
+
+ return False
+ except Exception as ex:
+ print '[Harddisk] Failed to read /proc/filesystems:', ex
+
+
+def findMountPoint(path):
+ path = os.path.abspath(path)
+ while not os.path.ismount(path):
+ path = os.path.dirname(path)
+
+ return path
+
+
+DEVTYPE_UDEV = 0
+DEVTYPE_DEVFS = 1
+
+class Harddisk():
+
+ def __init__(self, device, removable = False):
+ self.device = device
+ if os.access('/dev/.udev', 0):
+ self.type = DEVTYPE_UDEV
+ elif os.access('/dev/.devfsd', 0):
+ self.type = DEVTYPE_DEVFS
+ else:
+ print '[Harddisk] Unable to determine structure of /dev'
+ self.type = -1
+ self.card = False
+ self.max_idle_time = 0
+ self.idle_running = False
+ self.last_access = time.time()
+ self.last_stat = 0
+ self.timer = None
+ self.is_sleeping = False
+ self.dev_path = ''
+ self.disk_path = ''
+ self.mount_path = None
+ self.mount_device = None
+ self.phys_path = os.path.realpath(self.sysfsPath('device'))
+ self.removable = removable
+ self.internal = 'pci' in self.phys_path or 'ahci' in self.phys_path or 'sata' in self.phys_path
+ try:
+ data = open('/sys/block/%s/queue/rotational' % device, 'r').read().strip()
+ self.rotational = int(data)
+ except:
+ self.rotational = True
+
+ if self.type == DEVTYPE_UDEV:
+ self.dev_path = '/dev/' + self.device
+ self.disk_path = self.dev_path
+ self.card = 'sdhci' in self.phys_path
+ elif self.type == DEVTYPE_DEVFS:
+ tmp = readFile(self.sysfsPath('dev')).split(':')
+ s_major = int(tmp[0])
+ s_minor = int(tmp[1])
+ for disc in os.listdir('/dev/discs'):
+ dev_path = os.path.realpath('/dev/discs/' + disc)
+ disk_path = dev_path + '/disc'
+ try:
+ rdev = os.stat(disk_path).st_rdev
+ except OSError:
+ continue
+
+ if s_major == os.major(rdev) and s_minor == os.minor(rdev):
+ self.dev_path = dev_path
+ self.disk_path = disk_path
+ break
+
+ self.card = self.device[:2] == 'hd' and 'host0' not in self.dev_path
+ print '[Harddisk] new device', self.device, '->', self.dev_path, '->', self.disk_path
+ if not removable and not self.card:
+ self.startIdle()
+ return
+
+ def __lt__(self, ob):
+ return self.device < ob.device
+
+ def partitionPath(self, n):
+ if self.type == DEVTYPE_UDEV:
+ if self.dev_path.startswith('/dev/mmcblk0'):
+ return self.dev_path + 'p' + n
+ else:
+ return self.dev_path + n
+ elif self.type == DEVTYPE_DEVFS:
+ return self.dev_path + '/part' + n
+
+ def sysfsPath(self, filename):
+ return os.path.join('/sys/block/', self.device, filename)
+
+ def stop(self):
+ if self.timer:
+ self.timer.stop()
+ self.timer.callback.remove(self.runIdle)
+
+ def bus(self):
+ ret = _('External')
+ if self.type == DEVTYPE_UDEV:
+ type_name = ' (SD/MMC)'
+ elif self.type == DEVTYPE_DEVFS:
+ type_name = ' (CF)'
+ if self.card:
+ ret += type_name
+ else:
+ if self.internal:
+ ret = _('Internal')
+ if not self.rotational:
+ ret += ' (SSD)'
+ return ret
+
+ def diskSize(self):
+ cap = 0
+ try:
+ line = readFile(self.sysfsPath('size'))
+ cap = int(line)
+ return cap / 1000 * 512 / 1000
+ except:
+ dev = self.findMount()
+ if dev:
+ try:
+ stat = os.statvfs(dev)
+ cap = int(stat.f_blocks * stat.f_bsize)
+ return cap / 1000 / 1000
+ except:
+ pass
+
+ return cap
+
+ def capacity(self):
+ cap = self.diskSize()
+ if cap == 0:
+ return ''
+ if cap < 1000:
+ return _('%03d MB') % cap
+ return _('%d.%03d GB') % (cap / 1000, cap % 1000)
+
+ def model(self):
+ try:
+ if self.device[:2] == 'hd':
+ return readFile('/proc/ide/' + self.device + '/model')
+ if self.device[:2] == 'sd':
+ vendor = readFile(self.sysfsPath('device/vendor'))
+ model = readFile(self.sysfsPath('device/model'))
+ return vendor + '(' + model + ')'
+ if self.device.startswith('mmcblk0'):
+ return readFile(self.sysfsPath('device/name'))
+ raise Exception, '[Harddisk] no hdX or sdX or mmcX'
+ except Exception as e:
+ print '[Harddisk] Failed to get model:', e
+ return '-?-'
+
+ def free(self):
+ dev = self.findMount()
+ if dev:
+ try:
+ stat = os.statvfs(dev)
+ return stat.f_bfree / 1000 * (stat.f_bsize / 1024)
+ except:
+ pass
+
+ return -1
+
+ def numPartitions(self):
+ numPart = -1
+ if self.type == DEVTYPE_UDEV:
+ try:
+ devdir = os.listdir('/dev')
+ except OSError:
+ return -1
+
+ for filename in devdir:
+ if filename.startswith(self.device):
+ numPart += 1
+
+ elif self.type == DEVTYPE_DEVFS:
+ try:
+ idedir = os.listdir(self.dev_path)
+ except OSError:
+ return -1
+
+ for filename in idedir:
+ if filename.startswith('disc'):
+ numPart += 1
+ if filename.startswith('part'):
+ numPart += 1
+
+ return numPart
+
+ def mountDevice(self):
+ for parts in getProcMounts():
+ if os.path.realpath(parts[0]).startswith(self.dev_path):
+ self.mount_device = parts[0]
+ self.mount_path = parts[1]
+ return parts[1]
+
+ return None
+
+ def enumMountDevices(self):
+ for parts in getProcMounts():
+ if os.path.realpath(parts[0]).startswith(self.dev_path):
+ yield parts[1]
+
+ def findMount(self):
+ if self.mount_path is None:
+ return self.mountDevice()
+ else:
+ return self.mount_path
+
+ def unmount(self):
+ dev = self.mountDevice()
+ if dev is None:
+ return 0
+ else:
+ cmd = 'umount ' + dev
+ print '[Harddisk]', cmd
+ res = os.system(cmd)
+ return res >> 8
+
+ def createPartition(self):
+ cmd = 'printf "8,\n;0,0\n;0,0\n;0,0\ny\n" | sfdisk -f -uS ' + self.disk_path
+ res = os.system(cmd)
+ return res >> 8
+
+ def mkfs(self):
+ return 1
+
+ def mount(self):
+ if self.mount_device is None:
+ dev = self.partitionPath('1')
+ else:
+ dev = self.mount_device
+ try:
+ fstab = open('/etc/fstab')
+ lines = fstab.readlines()
+ fstab.close()
+ except IOError:
+ return -1
+
+ for line in lines:
+ parts = line.strip().split(' ')
+ fspath = os.path.realpath(parts[0])
+ if fspath == dev:
+ print '[Harddisk] mounting:', fspath
+ cmd = 'mount -t auto ' + fspath
+ res = os.system(cmd)
+ return res >> 8
+
+ res = -1
+ if self.type == DEVTYPE_UDEV:
+ res = os.system('hdparm -z ' + self.disk_path)
+ from time import sleep
+ sleep(3)
+ return res >> 8
+
+ def fsck(self):
+ return 1
+
+ def killPartitionTable(self):
+ zero = 512 * '\x00'
+ h = open(self.dev_path, 'wb')
+ for i in range(9):
+ h.write(zero)
+
+ h.close()
+
+ def killPartition(self, n):
+ zero = 512 * '\x00'
+ part = self.partitionPath(n)
+ h = open(part, 'wb')
+ for i in range(3):
+ h.write(zero)
+
+ h.close()
+
+ def createInitializeJob(self):
+ job = Task.Job(_('Initializing storage device...'))
+ size = self.diskSize()
+ print '[HD] size: %s MB' % size
+ task = UnmountTask(job, self)
+ task = Task.PythonTask(job, _('Removing partition table'))
+ task.work = self.killPartitionTable
+ task.weighting = 1
+ task = Task.LoggingTask(job, _('Rereading partition table'))
+ task.weighting = 1
+ task.setTool('hdparm')
+ task.args.append('-z')
+ task.args.append(self.disk_path)
+ task = Task.ConditionTask(job, _('Waiting for partition'), timeoutCount=20)
+ task.check = lambda : not os.path.exists(self.partitionPath('1'))
+ task.weighting = 1
+ if os.path.exists('/usr/sbin/parted'):
+ use_parted = True
+ elif size > 2097151:
+ addInstallTask(job, 'parted')
+ use_parted = True
+ else:
+ use_parted = False
+ task = Task.LoggingTask(job, _('Creating partition'))
+ task.weighting = 5
+ if use_parted:
+ task.setTool('parted')
+ if size < 1024:
+ alignment = 'min'
+ else:
+ alignment = 'opt'
+ if size > 2097151:
+ parttype = 'gpt'
+ else:
+ parttype = 'msdos'
+ task.args += ['-a',
+ alignment,
+ '-s',
+ self.disk_path,
+ 'mklabel',
+ parttype,
+ 'mkpart',
+ 'primary',
+ '0%',
+ '100%']
+ else:
+ task.setTool('sfdisk')
+ task.args.append('-f')
+ task.args.append('-uS')
+ task.args.append(self.disk_path)
+ if size > 128000:
+ print '[HD] Detected >128GB disk, using 4k alignment'
+ task.initial_input = '8,,L\n;0,0\n;0,0\n;0,0\ny\n'
+ else:
+ task.initial_input = ',,L\n;\n;\n;\ny\n'
+ task = Task.ConditionTask(job, _('Waiting for partition'))
+ task.check = lambda : os.path.exists(self.partitionPath('1'))
+ task.weighting = 1
+ task = MkfsTask(job, _('Creating filesystem'))
+ big_o_options = ['dir_index']
+
+###__blokada hash dla ext4 >>>
+# if isFileSystemSupported('ext4'):
+# task.setTool('mkfs.ext4')
+# if size > 20000:
+# try:
+# version = map(int, open('/proc/version', 'r').read().split(' ', 4)[2].split('.', 2)[:2])
+# if version[0] > 3 or version[0] > 2 and version[1] >= 2:
+# task.args += ['-C', '262144']
+# big_o_options.append('bigalloc')
+# except Exception as ex:
+# print 'Failed to detect Linux version:', ex
+# else:
+# task.setTool('mkfs.ext3')
+
+ task.setTool('mkfs.ext3')
+ if size > 250000:
+ task.args += ['-T',
+ 'largefile',
+ '-N',
+ '262144']
+ big_o_options.append('sparse_super')
+ elif size > 16384:
+ task.args += ['-T', 'largefile']
+ big_o_options.append('sparse_super')
+ elif size > 2048:
+ task.args += ['-T',
+ 'largefile',
+ '-N',
+ str(size * 32)]
+ task.args += ['-m0',
+ '-O',
+ ','.join(big_o_options),
+ self.partitionPath('1')]
+ task = MountTask(job, self)
+ task.weighting = 3
+ task = Task.ConditionTask(job, _('Waiting for mount'), timeoutCount=20)
+ task.check = self.mountDevice
+ task.weighting = 1
+ return job
+
+ def initialize(self):
+ return -5
+
+ def check(self):
+ return -5
+
+ def createCheckJob(self):
+ job = Task.Job(_('Checking filesystem...'))
+ if self.findMount():
+ UnmountTask(job, self)
+ dev = self.mount_device
+ else:
+ dev = self.partitionPath('1')
+ task = Task.LoggingTask(job, 'fsck')
+ task.setTool('fsck.ext3')
+ task.args.append('-f')
+ task.args.append('-p')
+ task.args.append(dev)
+ MountTask(job, self)
+ task = Task.ConditionTask(job, _('Waiting for mount'))
+ task.check = self.mountDevice
+ return job
+
+ def getDeviceDir(self):
+ return self.dev_path
+
+ def getDeviceName(self):
+ return self.disk_path
+
+ def readStats(self):
+ try:
+ l = open('/sys/block/%s/stat' % self.device).read()
+ except IOError:
+ return (-1, -1)
+
+ data = l.split(None, 5)
+ return (int(data[0]), int(data[4]))
+
+ def startIdle(self):
+ from enigma import eTimer
+ if self.bus() == _('External'):
+ Console().ePopen(('sdparm',
+ 'sdparm',
+ '--set=SCT=0',
+ self.disk_path))
+ else:
+ Console().ePopen(('hdparm',
+ 'hdparm',
+ '-S0',
+ self.disk_path))
+ self.timer = eTimer()
+ self.timer.callback.append(self.runIdle)
+ self.idle_running = True
+ self.setIdleTime(self.max_idle_time)
+
+ def runIdle(self):
+ if not self.max_idle_time:
+ return
+ t = time.time()
+ idle_time = t - self.last_access
+ stats = self.readStats()
+ l = sum(stats)
+ if l != self.last_stat and l >= 0:
+ self.last_stat = l
+ self.last_access = t
+ idle_time = 0
+ self.is_sleeping = False
+ if idle_time >= self.max_idle_time and not self.is_sleeping:
+ self.setSleep()
+ self.is_sleeping = True
+
+ def setSleep(self):
+ if self.bus() == _('External'):
+ Console().ePopen(('sdparm',
+ 'sdparm',
+ '--flexible',
+ '--readonly',
+ '--command=stop',
+ self.disk_path))
+ else:
+ Console().ePopen(('hdparm',
+ 'hdparm',
+ '-y',
+ self.disk_path))
+
+ def setIdleTime(self, idle):
+ self.max_idle_time = idle
+ if self.idle_running:
+ if not idle:
+ self.timer.stop()
+ else:
+ self.timer.start(idle * 100, False)
+
+ def isSleeping(self):
+ return self.is_sleeping
+
+
+class Partition():
+
+ def __init__(self, mountpoint, device = None, description = '', force_mounted = False):
+ self.mountpoint = mountpoint
+ self.description = description
+ self.force_mounted = mountpoint and force_mounted
+ self.is_hotplug = force_mounted
+ self.device = device
+
+ def __str__(self):
+ return 'Partition(mountpoint=%s,description=%s,device=%s)' % (self.mountpoint, self.description, self.device)
+
+ def stat(self):
+ if self.mountpoint:
+ return os.statvfs(self.mountpoint)
+ raise OSError, 'Device %s is not mounted' % self.device
+
+ def free(self):
+ try:
+ s = self.stat()
+ return s.f_bavail * s.f_bsize
+ except OSError:
+ return None
+
+ return None
+
+ def total(self):
+ try:
+ s = self.stat()
+ return s.f_blocks * s.f_bsize
+ except OSError:
+ return None
+
+ return None
+
+ def tabbedDescription(self):
+ if self.mountpoint.startswith('/media/net') or self.mountpoint.startswith('/media/autofs'):
+ return self.description
+ return self.description + '\t' + self.mountpoint
+
+ def mounted(self, mounts = None):
+ if self.force_mounted:
+ return True
+ else:
+ if self.mountpoint:
+ if mounts is None:
+ mounts = getProcMounts()
+ for parts in mounts:
+ if self.mountpoint.startswith(parts[1]):
+ return True
+
+ return False
+
+ def filesystem(self, mounts = None):
+ if self.mountpoint:
+ if mounts is None:
+ mounts = getProcMounts()
+ for fields in mounts:
+ if self.mountpoint.endswith('/') and not self.mountpoint == '/':
+ if fields[1] + '/' == self.mountpoint:
+ return fields[2]
+ elif fields[1] == self.mountpoint:
+ return fields[2]
+
+ return ''
+
+
+def addInstallTask(job, package):
+ task = Task.LoggingTask(job, 'update packages')
+ task.setTool('opkg')
+ task.args.append('update')
+ task = Task.LoggingTask(job, 'Install ' + package)
+ task.setTool('opkg')
+ task.args.append('install')
+ task.args.append(package)
+
+
+class HarddiskManager():
+
+ def __init__(self):
+ self.hdd = []
+ self.cd = ''
+ self.partitions = []
+ self.devices_scanned_on_init = []
+ self.on_partition_list_change = CList()
+ self.enumerateBlockDevices()
+ p = (('/media/hdd', _('Hard disk')),
+ ('/media/card', _('Card')),
+ ('/media/cf', _('Compact flash')),
+ ('/media/mmc1', _('MMC card')),
+ ('/media/net', _('Network mount')),
+ ('/media/net1', _('Network mount %s') % '1'),
+ ('/media/net2', _('Network mount %s') % '2'),
+ ('/media/net3', _('Network mount %s') % '3'),
+ ('/media/ram', _('Ram disk')),
+ ('/media/usb', _('USB stick')),
+ ('/media/usb1', _('USB1 stick')),
+ ('/media/usb2', _('USB2 stick')),
+ ('/', _('Internal flash')))
+ known = set([ os.path.normpath(a.mountpoint) for a in self.partitions if a.mountpoint ])
+ for m, d in p:
+ if m not in known and os.path.ismount(m):
+ self.partitions.append(Partition(mountpoint=m, description=d))
+
+ def getBlockDevInfo(self, blockdev):
+ HasMMC = fileExists('/proc/cmdline') and 'root=/dev/mmcblk' in open('/proc/cmdline', 'r').read()
+ devpath = '/sys/block/' + blockdev
+ error = False
+ removable = False
+ blacklisted = False
+ is_cdrom = False
+ partitions = []
+ try:
+ if os.path.exists(devpath + '/removable'):
+ removable = bool(int(readFile(devpath + '/removable')))
+ if os.path.exists(devpath + '/dev'):
+ dev = int(readFile(devpath + '/dev').split(':')[0])
+ else:
+ dev = None
+ blacklisted = dev in [1,
+ 7,
+ 31,
+ 253,
+ 254] + (['HasMMC'] and [179] or [])
+ if blockdev[0:2] == 'sr':
+ is_cdrom = True
+ if blockdev[0:2] == 'hd':
+ try:
+ media = readFile('/proc/ide/%s/media' % blockdev)
+ if 'cdrom' in media:
+ is_cdrom = True
+ except IOError:
+ error = True
+
+ if not is_cdrom and os.path.exists(devpath):
+ for partition in os.listdir(devpath):
+ if partition[0:len(blockdev)] != blockdev:
+ continue
+ partitions.append(partition)
+
+ else:
+ self.cd = blockdev
+ except IOError:
+ error = True
+
+ medium_found = True
+ try:
+ open('/dev/' + blockdev).close()
+ except IOError as err:
+ if err.errno == 159:
+ medium_found = False
+
+ return (error,
+ blacklisted,
+ removable,
+ is_cdrom,
+ partitions,
+ medium_found)
+
+ def enumerateBlockDevices(self):
+ print '[Harddisk] enumerating block devices...'
+ for blockdev in os.listdir('/sys/block'):
+ error, blacklisted, removable, is_cdrom, partitions, medium_found = self.addHotplugPartition(blockdev)
+ if not error and not blacklisted and medium_found:
+ for part in partitions:
+ self.addHotplugPartition(part)
+
+ self.devices_scanned_on_init.append((blockdev,
+ removable,
+ is_cdrom,
+ medium_found))
+
+ def getAutofsMountpoint(self, device):
+ r = self.getMountpoint(device)
+ if r is None:
+ return '/media/' + device
+ else:
+ return r
+
+ def getMountpoint(self, device):
+ dev = '/dev/%s' % device
+ for item in getProcMounts():
+ if item[0] == dev:
+ return item[1]
+
+ return None
+
+ def addHotplugPartition(self, device, physdev = None):
+ if not physdev:
+ dev, part = self.splitDeviceName(device)
+ try:
+ physdev = os.path.realpath('/sys/block/' + dev + '/device')[4:]
+ except OSError:
+ physdev = dev
+ print "couldn't determine blockdev physdev for device", device
+
+ error, blacklisted, removable, is_cdrom, partitions, medium_found = self.getBlockDevInfo(device)
+ if not blacklisted and medium_found:
+ description = self.getUserfriendlyDeviceName(device, physdev)
+ p = Partition(mountpoint=self.getMountpoint(device), description=description, force_mounted=True, device=device)
+ self.partitions.append(p)
+ if p.mountpoint:
+ self.on_partition_list_change('add', p)
+ l = len(device)
+ if l and (not device[l - 1].isdigit() or device == 'mmcblk0'):
+ self.hdd.append(Harddisk(device, removable))
+ self.hdd.sort()
+ SystemInfo['Harddisk'] = True
+ return (error,
+ blacklisted,
+ removable,
+ is_cdrom,
+ partitions,
+ medium_found)
+
+ def addHotplugAudiocd(self, device, physdev = None):
+ if not physdev:
+ dev, part = self.splitDeviceName(device)
+ try:
+ physdev = os.path.realpath('/sys/block/' + dev + '/device')[4:]
+ except OSError:
+ physdev = dev
+ print "couldn't determine blockdev physdev for device", device
+
+ error, blacklisted, removable, is_cdrom, partitions, medium_found = self.getBlockDevInfo(device)
+ if not blacklisted and medium_found:
+ description = self.getUserfriendlyDeviceName(device, physdev)
+ p = Partition(mountpoint='/media/audiocd', description=description, force_mounted=True, device=device)
+ self.partitions.append(p)
+ self.on_partition_list_change('add', p)
+ SystemInfo['Harddisk'] = False
+ return (error,
+ blacklisted,
+ removable,
+ is_cdrom,
+ partitions,
+ medium_found)
+
+ def removeHotplugPartition(self, device):
+ for x in self.partitions[:]:
+ if x.device == device:
+ self.partitions.remove(x)
+ if x.mountpoint:
+ self.on_partition_list_change('remove', x)
+
+ l = len(device)
+ if l and not device[l - 1].isdigit():
+ for hdd in self.hdd:
+ if hdd.device == device:
+ hdd.stop()
+ self.hdd.remove(hdd)
+ break
+
+ SystemInfo['Harddisk'] = len(self.hdd) > 0
+
+ def HDDCount(self):
+ return len(self.hdd)
+
+ def HDDList(self):
+ list = []
+ for hd in self.hdd:
+ hdd = hd.model() + ' - ' + hd.bus()
+ cap = hd.capacity()
+ if cap != '':
+ hdd += ' (' + cap + ')'
+ list.append((hdd, hd))
+
+ return list
+
+ def getCD(self):
+ return self.cd
+
+ def getMountedPartitions(self, onlyhotplug = False, mounts = None):
+ if mounts is None:
+ mounts = getProcMounts()
+ parts = [ x for x in self.partitions if (x.is_hotplug or not onlyhotplug) and x.mounted(mounts) ]
+ devs = set([ x.device for x in parts ])
+ for devname in devs.copy():
+ if not devname:
+ continue
+ dev, part = self.splitDeviceName(devname)
+ if part and dev in devs:
+ devs.remove(dev)
+
+ return [ x for x in parts if not x.device or x.device in devs ]
+
+ def splitDeviceName(self, devname):
+ dev = devname[:3]
+ part = devname[3:]
+ for p in part:
+ if not p.isdigit():
+ return (devname, 0)
+
+ return (dev, part and int(part) or 0)
+
+ def getUserfriendlyDeviceName(self, dev, phys):
+ dev, part = self.splitDeviceName(dev)
+ description = _('External Storage %s') % dev
+ try:
+ description = readFile('/sys' + phys + '/model')
+ except IOError as s:
+ print "couldn't read model: ", s
+
+ if part and part != 1:
+ description += _(' (Partition %d)') % part
+ return description
+
+ def addMountedPartition(self, device, desc):
+ for x in self.partitions:
+ if x.mountpoint == device:
+ return
+
+ self.partitions.append(Partition(mountpoint=device, description=desc))
+
+ def removeMountedPartition(self, mountpoint):
+ for x in self.partitions[:]:
+ if x.mountpoint == mountpoint:
+ self.partitions.remove(x)
+ self.on_partition_list_change('remove', x)
+
+ def setDVDSpeed(self, device, speed = 0):
+ ioctl_flag = int(21282)
+ if not device.startswith('/'):
+ device = '/dev/' + device
+ try:
+ from fcntl import ioctl
+ cd = open(device)
+ ioctl(cd.fileno(), ioctl_flag, speed)
+ cd.close()
+ except Exception as ex:
+ print '[Harddisk] Failed to set %s speed to %s' % (device, speed), ex
+
+
+class UnmountTask(Task.LoggingTask):
+
+ def __init__(self, job, hdd):
+ Task.LoggingTask.__init__(self, job, _('Unmount'))
+ self.hdd = hdd
+ self.mountpoints = []
+
+ def prepare(self):
+ try:
+ dev = self.hdd.disk_path.split('/')[-1]
+ open('/dev/nomount.%s' % dev, 'wb').close()
+ except Exception as e:
+ print 'ERROR: Failed to create /dev/nomount file:', e
+
+ self.setTool('umount')
+ self.args.append('-f')
+ for dev in self.hdd.enumMountDevices():
+ self.args.append(dev)
+ self.postconditions.append(Task.ReturncodePostcondition())
+ self.mountpoints.append(dev)
+
+ if not self.mountpoints:
+ print 'UnmountTask: No mountpoints found?'
+ self.cmd = 'true'
+ self.args = [self.cmd]
+
+ def afterRun(self):
+ for path in self.mountpoints:
+ try:
+ os.rmdir(path)
+ except Exception as ex:
+ print "Failed to remove path '%s':" % path, ex
+
+
+class MountTask(Task.LoggingTask):
+
+ def __init__(self, job, hdd):
+ Task.LoggingTask.__init__(self, job, _('Mount'))
+ self.hdd = hdd
+
+ def prepare(self):
+ try:
+ dev = self.hdd.disk_path.split('/')[-1]
+ os.unlink('/dev/nomount.%s' % dev)
+ except Exception as e:
+ print 'ERROR: Failed to remove /dev/nomount file:', e
+
+ if self.hdd.mount_device is None:
+ dev = self.hdd.partitionPath('1')
+ else:
+ dev = self.hdd.mount_device
+ fstab = open('/etc/fstab')
+ lines = fstab.readlines()
+ fstab.close()
+ for line in lines:
+ parts = line.strip().split(' ')
+ fspath = os.path.realpath(parts[0])
+ if os.path.realpath(fspath) == dev:
+ self.setCmdline('mount -t auto ' + fspath)
+ self.postconditions.append(Task.ReturncodePostcondition())
+ return
+
+ if self.hdd.type == DEVTYPE_UDEV:
+ self.setCmdline('sleep 2; hdparm -z ' + self.hdd.disk_path)
+ self.postconditions.append(Task.ReturncodePostcondition())
+ return
+
+
+class MkfsTask(Task.LoggingTask):
+
+ def prepare(self):
+ self.fsck_state = None
+ return
+
+ def processOutput(self, data):
+ print '[Mkfs]', data
+ if 'Writing inode tables:' in data:
+ self.fsck_state = 'inode'
+ elif 'Creating journal' in data:
+ self.fsck_state = 'journal'
+ self.setProgress(80)
+ elif 'Writing superblocks ' in data:
+ self.setProgress(95)
+ elif self.fsck_state == 'inode':
+ if '/' in data:
+ try:
+ d = data.strip(' \x08\r\n').split('/', 1)
+ if '\x08' in d[1]:
+ d[1] = d[1].split('\x08', 1)[0]
+ self.setProgress(80 * int(d[0]) / int(d[1]))
+ except Exception as e:
+ print '[Mkfs] E:', e
+
+ return
+ self.log.append(data)
+
+
+###########################__From HarddiskSetup_################################
+class HarddiskSetup(Screen):
+
+ def __init__(self, session, hdd, action, text, question):
+ Screen.__init__(self, session)
+ self.action = action
+ self.question = question
+ self.setTitle(_('Setup hard disk'))
+ self['model'] = Label(_('Model: ') + hdd.model())
+ self['capacity'] = Label(_('Capacity: ') + hdd.capacity())
+ self['bus'] = Label(_('Bus: ') + hdd.bus())
+ self['key_red'] = Label(_('Cancel'))
+ self['key_green'] = Label(text)
+ self['actions'] = ActionMap(['OkCancelActions'], {'ok': self.hddQuestion,
+ 'cancel': self.close})
+ self['shortcuts'] = ActionMap(['ShortcutActions'], {'red': self.close,
+ 'green': self.hddQuestion})
+
+ def hddQuestion(self):
+ message = self.question + '\n' + _('You can continue watching TV etc. while this is running.')
+ self.session.openWithCallback(self.hddConfirmed, MessageBox, message)
+
+ def hddConfirmed(self, confirmed):
+ if not confirmed:
+ return
+ from Components.Task import job_manager
+ try:
+ job = self.action()
+ job_manager.AddJob(job, onSuccess=job_manager.popupTaskView)
+ from Screens.TaskView import JobView
+ self.session.open(JobView, job, afterEventChangeable=False)
+ except Exception as ex:
+ self.session.open(MessageBox, str(ex), type=MessageBox.TYPE_ERROR, timeout=10)
+
+ self.close()
+
+
+class HarddiskSelection(Screen):
+ def __init__(self, session):
+ Screen.__init__(self, session)
+ self.setTitle(_('Select hard disk'))
+ self.skinName = 'HarddiskSelection'
+ if harddiskmanager.HDDCount() == 0:
+ tlist = []
+ tlist.append((_('no storage devices found'), 0))
+ self['hddlist'] = MenuList(tlist)
+ else:
+ self['hddlist'] = MenuList(harddiskmanager.HDDList())
+ self['key_red'] = Label(_('Cancel'))
+ self['key_green'] = Label(_('Select'))
+ self['actions'] = ActionMap(['OkCancelActions'], {'ok': self.okbuttonClick,
+ 'cancel': self.close})
+ self['shortcuts'] = ActionMap(['ShortcutActions'], {'red': self.close,
+ 'green': self.okbuttonClick})
+
+ def doIt(self, selection):
+ self.session.openWithCallback(self.close, HarddiskSetup, selection, action=selection.createInitializeJob, text=_('Initialize'), question=_('Do you really want to initialize the device?\nAll data on the disk will be lost!'))
+
+ def okbuttonClick(self):
+ selection = self['hddlist'].getCurrent()
+ if selection[1] != 0:
+ self.doIt(selection[1])
+
+
+class HarddiskFsckSelection(HarddiskSelection):
+
+ def doIt(self, selection):
+ self.session.openWithCallback(self.close, HarddiskSetup, selection, action=selection.createCheckJob, text=_('Check'), question=_('Do you really want to check the filesystem?\nThis could take lots of time!'))
+###########################__end HarddiskSetup_################################
+
+
+harddiskmanager = HarddiskManager()
+
+def isSleepStateDevice(device):
+ ret = os.popen('hdparm -C %s' % device).read()
+ if 'SG_IO' in ret or 'HDIO_DRIVE_CMD' in ret:
+ return None
+ elif 'drive state is: standby' in ret or 'drive state is: idle' in ret:
+ return True
+ elif 'drive state is: active/idle' in ret:
+ return False
+ else:
+ return None
+
+
+def internalHDDNotSleeping(external = False):
+ state = False
+ if harddiskmanager.HDDCount():
+ for hdd in harddiskmanager.HDDList():
+ if hdd[1].internal or external:
+ if hdd[1].idle_running and hdd[1].max_idle_time and not hdd[1].isSleeping():
+ state = True
+
+ return state
+
+
+harddiskmanager = HarddiskManager()
+SystemInfo['ext4'] = isFileSystemSupported('ext4') or isFileSystemSupported('ext3')
diff --git a/NeoBoot/files/Task.py b/NeoBoot/files/Task.py
new file mode 100644
index 0000000..18d2beb
--- /dev/null
+++ b/NeoBoot/files/Task.py
@@ -0,0 +1,524 @@
+# -*- coding: utf-8 -*-
+
+#from __future__ import print_function
+#from Plugins.Extensions.NeoBoot.__init__ import _
+from Tools.CList import CList
+
+class Job(object):
+ NOT_STARTED, IN_PROGRESS, FINISHED, FAILED = range(4)
+
+ def __init__(self, name):
+ self.tasks = []
+ self.resident_tasks = []
+ self.workspace = '/tmp'
+ self.current_task = 0
+ self.callback = None
+ self.name = name
+ self.finished = False
+ self.end = 100
+ self.__progress = 0
+ self.weightScale = 1
+ self.afterEvent = None
+ self.state_changed = CList()
+ self.status = self.NOT_STARTED
+ self.onSuccess = None
+ return
+
+ def fromDescription(self, description):
+ pass
+
+ def createDescription(self):
+ return None
+
+ def getProgress(self):
+ if self.current_task == len(self.tasks):
+ return self.end
+ t = self.tasks[self.current_task]
+ jobprogress = t.weighting * t.progress / float(t.end) + sum([ task.weighting for task in self.tasks[:self.current_task] ])
+ return int(jobprogress * self.weightScale)
+
+ progress = property(getProgress)
+
+ def getStatustext(self):
+ return {self.NOT_STARTED: _('Waiting'),
+ self.IN_PROGRESS: _('In progress'),
+ self.FINISHED: _('Finished'),
+ self.FAILED: _('Failed')}[self.status]
+
+ def task_progress_changed_CB(self):
+ self.state_changed()
+
+ def addTask(self, task):
+ task.job = self
+ task.task_progress_changed = self.task_progress_changed_CB
+ self.tasks.append(task)
+
+ def start(self, callback):
+ self.callback = callback
+ self.restart()
+
+ def restart(self):
+ self.status = self.IN_PROGRESS
+ self.state_changed()
+ self.runNext()
+ sumTaskWeightings = sum([ t.weighting for t in self.tasks ]) or 1
+ self.weightScale = self.end / float(sumTaskWeightings)
+
+ def runNext(self):
+ if self.current_task == len(self.tasks):
+ if len(self.resident_tasks) == 0:
+ self.status = self.FINISHED
+ self.state_changed()
+ self.callback(self, None, [])
+ self.callback = None
+ 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.state_changed()
+ return
+
+ def taskCallback(self, task, res, stay_resident = False):
+ cb_idx = self.tasks.index(task)
+ if stay_resident:
+ if cb_idx not in self.resident_tasks:
+ self.resident_tasks.append(self.current_task)
+ print 'task going resident:', task
+ else:
+ print 'task keeps staying resident:', task
+ return
+ if len(res):
+ print '>>> Error:', res
+ self.status = self.FAILED
+ self.state_changed()
+ self.callback(self, task, res)
+ if cb_idx != self.current_task:
+ if cb_idx in self.resident_tasks:
+ print 'resident task finished:', task
+ self.resident_tasks.remove(cb_idx)
+ if res == []:
+ self.state_changed()
+ self.current_task += 1
+ self.runNext()
+
+ def retry(self):
+ self.restart()
+
+ def abort(self):
+ if self.current_task < len(self.tasks):
+ self.tasks[self.current_task].abort()
+ for i in self.resident_tasks:
+ self.tasks[i].abort()
+
+ def cancel(self):
+ self.abort()
+
+ def __str__(self):
+ return 'Components.Task.Job name=%s #tasks=%s' % (self.name, len(self.tasks))
+
+
+class Task(object):
+
+ def __init__(self, job, name):
+ self.name = name
+ self.immediate_preconditions = []
+ self.global_preconditions = []
+ self.postconditions = []
+ self.returncode = None
+ self.initial_input = None
+ self.job = None
+ self.end = 100
+ self.weighting = 100
+ self.__progress = 0
+ self.cmd = None
+ self.cwd = '/tmp'
+ self.args = []
+ self.cmdline = None
+ self.task_progress_changed = None
+ self.output_line = ''
+ job.addTask(self)
+ self.container = None
+ return
+
+ def setCommandline(self, cmd, args):
+ self.cmd = cmd
+ self.args = args
+
+ def setTool(self, tool):
+ self.cmd = tool
+ self.args = [tool]
+ self.global_preconditions.append(ToolExistsPrecondition())
+ self.postconditions.append(ReturncodePostcondition())
+
+ def setCmdline(self, cmdline):
+ self.cmdline = cmdline
+
+ def checkPreconditions(self, immediate = False):
+ not_met = []
+ if immediate:
+ preconditions = self.immediate_preconditions
+ else:
+ preconditions = self.global_preconditions
+ for precondition in preconditions:
+ if not precondition.check(self):
+ not_met.append(precondition)
+
+ return not_met
+
+ def _run(self):
+ if self.cmd is None and self.cmdline is None:
+ self.finish()
+ return
+ else:
+ from enigma import eConsoleAppContainer
+ self.container = eConsoleAppContainer()
+ self.container.appClosed.append(self.processFinished)
+ self.container.stdoutAvail.append(self.processStdout)
+ self.container.stderrAvail.append(self.processStderr)
+ if self.cwd is not None:
+ self.container.setCWD(self.cwd)
+ if not self.cmd and self.cmdline:
+ print 'execute:', self.container.execute(self.cmdline), self.cmdline
+ else:
+ print 'execute:', self.container.execute(self.cmd, *self.args), ' '.join(self.args)
+ if self.initial_input:
+ self.writeInput(self.initial_input)
+ return
+ return
+
+ def run(self, callback):
+ failed_preconditions = self.checkPreconditions(True) + self.checkPreconditions(False)
+ if failed_preconditions:
+ print '[Task] preconditions failed'
+ callback(self, failed_preconditions)
+ return
+ self.callback = callback
+ try:
+ self.prepare()
+ self._run()
+ except Exception as ex:
+ print '[Task] exception:', ex
+ self.postconditions = [FailedPostcondition(ex)]
+ self.finish()
+
+ def prepare(self):
+ pass
+
+ def cleanup(self, failed):
+ pass
+
+ def processStdout(self, data):
+ self.processOutput(data)
+
+ def processStderr(self, data):
+ self.processOutput(data)
+
+ def processOutput(self, data):
+ self.output_line += data
+ while True:
+ i = self.output_line.find('\n')
+ if i == -1:
+ break
+ self.processOutputLine(self.output_line[:i + 1])
+ self.output_line = self.output_line[i + 1:]
+
+ def processOutputLine(self, line):
+ print '[Task %s]' % self.name, line[:-1]
+
+ def processFinished(self, returncode):
+ self.returncode = returncode
+ self.finish()
+
+ def abort(self):
+ if self.container:
+ self.container.kill()
+ self.finish(aborted=True)
+
+ def finish(self, aborted = False):
+ self.afterRun()
+ not_met = []
+ if aborted:
+ not_met.append(AbortedPostcondition())
+ else:
+ for postcondition in self.postconditions:
+ if not postcondition.check(self):
+ not_met.append(postcondition)
+
+ self.cleanup(not_met)
+ self.callback(self, not_met)
+
+ def afterRun(self):
+ pass
+
+ def writeInput(self, input):
+ self.container.write(input)
+
+ def getProgress(self):
+ return self.__progress
+
+ def setProgress(self, progress):
+ if progress > self.end:
+ progress = self.end
+ if progress < 0:
+ progress = 0
+ self.__progress = progress
+ if self.task_progress_changed:
+ self.task_progress_changed()
+
+ progress = property(getProgress, setProgress)
+
+ def __str__(self):
+ return 'Components.Task.Task name=%s' % self.name
+
+
+class LoggingTask(Task):
+
+ def __init__(self, job, name):
+ Task.__init__(self, job, name)
+ self.log = []
+
+ def processOutput(self, data):
+ print '[%s]' % self.name, data,
+ self.log.append(data)
+
+
+class PythonTask(Task):
+
+ def _run(self):
+ from twisted.internet import threads
+ from enigma import eTimer
+ self.aborted = False
+ self.pos = 0
+ threads.deferToThread(self.work).addBoth(self.onComplete)
+ self.timer = eTimer()
+ self.timer.callback.append(self.onTimer)
+ self.timer.start(5)
+
+ def work(self):
+ raise NotImplemented, 'work'
+
+ def abort(self):
+ self.aborted = True
+ if self.callback is None:
+ self.finish(aborted=True)
+ return
+
+ def onTimer(self):
+ self.setProgress(self.pos)
+
+ def onComplete(self, result):
+ self.postconditions.append(FailedPostcondition(result))
+ self.timer.stop()
+ del self.timer
+ self.finish()
+
+
+class ConditionTask(Task):
+
+ def __init__(self, job, name, timeoutCount = None):
+ Task.__init__(self, job, name)
+ self.timeoutCount = timeoutCount
+
+ def _run(self):
+ self.triggerCount = 0
+
+ def prepare(self):
+ from enigma import eTimer
+ self.timer = eTimer()
+ self.timer.callback.append(self.trigger)
+ self.timer.start(1000)
+
+ def cleanup(self, failed):
+ if hasattr(self, 'timer'):
+ self.timer.stop()
+ del self.timer
+
+ def check(self):
+ return True
+
+ def trigger(self):
+ self.triggerCount += 1
+ try:
+ if self.timeoutCount is not None and self.triggerCount > self.timeoutCount:
+ raise Exception, 'Timeout elapsed, sorry'
+ res = self.check()
+ except Exception as e:
+ self.postconditions.append(FailedPostcondition(e))
+ res = True
+
+ if res:
+ self.finish()
+ return
+
+
+class JobManager:
+
+ def __init__(self):
+ self.active_jobs = []
+ self.failed_jobs = []
+ self.job_classes = []
+ self.in_background = False
+ self.visible = False
+ self.active_job = None
+ return
+
+ def AddJob(self, job, onSuccess = None, onFail = None):
+ job.onSuccess = onSuccess
+ if onFail is None:
+ job.onFail = self.notifyFailed
+ else:
+ job.onFail = onFail
+ self.active_jobs.append(job)
+ self.kick()
+ return
+
+ def kick(self):
+ if self.active_job is None:
+ if self.active_jobs:
+ self.active_job = self.active_jobs.pop(0)
+ self.active_job.start(self.jobDone)
+ return
+
+ def notifyFailed(self, job, task, problems):
+ from Tools import Notifications
+ from Screens.MessageBox import MessageBox
+ if problems[0].RECOVERABLE:
+ Notifications.AddNotificationWithCallback(self.errorCB, MessageBox, _('Error: %s\nRetry?') % problems[0].getErrorMessage(task))
+ return True
+ else:
+ Notifications.AddNotification(MessageBox, job.name + '\n' + _('Error') + ': %s' % problems[0].getErrorMessage(task), type=MessageBox.TYPE_ERROR)
+ return False
+
+ def jobDone(self, job, task, problems):
+ print 'job', job, 'completed with', problems, 'in', task
+ if problems:
+ if not job.onFail(job, task, problems):
+ self.errorCB(False)
+ else:
+ self.active_job = None
+ if job.onSuccess:
+ job.onSuccess(job)
+ self.kick()
+ return
+
+ def popupTaskView(self, job):
+ if not self.visible:
+ from Tools import Notifications
+ from Screens.TaskView import JobView
+ self.visible = True
+ Notifications.AddNotification(JobView, job)
+
+ def errorCB(self, answer):
+ if answer:
+ print 'retrying job'
+ self.active_job.retry()
+ else:
+ print 'not retrying job.'
+ self.failed_jobs.append(self.active_job)
+ self.active_job = None
+ self.kick()
+ return
+
+ def getPendingJobs(self):
+ list = []
+ if self.active_job:
+ list.append(self.active_job)
+ list += self.active_jobs
+ return list
+
+
+class Condition:
+ RECOVERABLE = False
+
+ def getErrorMessage(self, task):
+ return _('An unknown error occurred!') + ' (%s @ task %s)' % (self.__class__.__name__, task.__class__.__name__)
+
+
+class WorkspaceExistsPrecondition(Condition):
+
+ def check(self, task):
+ return os.access(task.job.workspace, os.W_OK)
+
+
+class DiskspacePrecondition(Condition):
+
+ def __init__(self, diskspace_required):
+ self.diskspace_required = diskspace_required
+ self.diskspace_available = 0
+
+ def check(self, task):
+ import os
+ try:
+ s = os.statvfs(task.job.workspace)
+ self.diskspace_available = s.f_bsize * s.f_bavail
+ return self.diskspace_available >= self.diskspace_required
+ except OSError:
+ return False
+
+ def getErrorMessage(self, task):
+ return _('Not enough disk space. Please free up some disk space and try again. (%d MB required, %d MB available)') % (self.diskspace_required / 1024 / 1024, self.diskspace_available / 1024 / 1024)
+
+
+class ToolExistsPrecondition(Condition):
+
+ def check(self, task):
+ import os
+ if task.cmd[0] == '/':
+ self.realpath = task.cmd
+ print '[Task.py][ToolExistsPrecondition] WARNING: usage of absolute paths for tasks should be avoided!'
+ return os.access(self.realpath, os.X_OK)
+ self.realpath = task.cmd
+ path = os.environ.get('PATH', '').split(os.pathsep)
+ path.append(task.cwd + '/')
+ absolutes = filter(lambda file: os.access(file, os.X_OK), map(lambda directory, file = task.cmd: os.path.join(directory, file), path))
+ if absolutes:
+ self.realpath = absolutes[0]
+ return True
+ return False
+
+ def getErrorMessage(self, task):
+ return _('A required tool (%s) was not found.') % self.realpath
+
+
+class AbortedPostcondition(Condition):
+
+ def getErrorMessage(self, task):
+ return 'Cancelled upon user request'
+
+
+class ReturncodePostcondition(Condition):
+
+ def check(self, task):
+ return task.returncode == 0
+
+ def getErrorMessage(self, task):
+ if hasattr(task, 'log') and task.log:
+ log = ''.join(task.log).strip()
+ log = log.split('\n')[-3:]
+ log = '\n'.join(log)
+ return log
+ else:
+ return _('Error code') + ': %s' % task.returncode
+
+
+class FailedPostcondition(Condition):
+
+ def __init__(self, exception):
+ self.exception = exception
+
+ def getErrorMessage(self, task):
+ if isinstance(self.exception, int):
+ if hasattr(task, 'log'):
+ log = ''.join(task.log).strip()
+ log = log.split('\n')[-4:]
+ log = '\n'.join(log)
+ return log
+ else:
+ return _('Error code') + ' %s' % self.exception
+ return str(self.exception)
+
+ def check(self, task):
+ return self.exception is None or self.exception == 0
+
+
+job_manager = JobManager()
\ No newline at end of file
diff --git a/NeoBoot/files/devices.py b/NeoBoot/files/devices.py
index 6cfe450..fb0f4a5 100644
--- a/NeoBoot/files/devices.py
+++ b/NeoBoot/files/devices.py
@@ -1,6 +1,6 @@
-#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from __init__ import _
+
+from Plugins.Extensions.NeoBoot.__init__ import _
from enigma import getDesktop
from Plugins.Plugin import PluginDescriptor
from Screens.ChoiceBox import ChoiceBox
@@ -31,27 +31,46 @@ import os
from Screens.VirtualKeyBoard import VirtualKeyBoard
import gettext, os
from Plugins.Extensions.NeoBoot.files.stbbranding import getTunerModel
+LinkNeoBoot = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot'
-
-try:
- cat = gettext.translation('lang', '/usr/lib/enigma2/python/Plugins/Extensions/files/po', [config.osd.language.getText()])
- _ = cat.gettext
-except IOError:
- pass
-
+
class ManagerDevice(Screen):
screenwidth = getDesktop(0).size().width()
if screenwidth and screenwidth == 1920:
- skin = '\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\t{"template": [\n\t\t\t\t MultiContentEntryText(pos = (90, 5), size = (600, 30), font=0, text = 0),\n\t\t\t\t MultiContentEntryText(pos = (110, 60), size = (900, 100), font=1, flags = RT_VALIGN_TOP, text = 1),\n\t\t\t\t MultiContentEntryPixmapAlphaBlend(pos = (0, 0), size = (160, 160,), png = 2),\n\t\t\t\t],\n\t\t\t\t"fonts": [gFont("Regular", 33),gFont("Regular", 33)],\n\t\t\t\t"itemHeight": 140\n\t\t\t\t}\n\t\t\t\n\t\t\n\t\t\n\t'
+
+ skin = """
+
+
+
+
+
+
+
+
+ \n\n\t\t\t\t{"template": [\n\n\t\t\t\t MultiContentEntryText(pos = (90, 5), size = (600, 75), font=0, text = 0),\n\n\t\t\t\t MultiContentEntryText(pos = (110, 60), size = (900, 80), font=1, flags = RT_VALIGN_TOP, text = 1),\n\n\t\t\t\t MultiContentEntryPixmapAlphaBlend(pos = (0, 0), size = (150, 130,)),\n\n\t\t\t\t],\n\t\t\t\t"fonts": [gFont("Regular", 33),gFont("Regular", 33)],\n\n\t\t\t\t"itemHeight": 140\n\t\t\t\t}
+
+
+ """
else:
- skin = '\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t \n\t\t\n\t\t\t\n\t\t\t\t{"template": [\n\t\t\t\t MultiContentEntryText(pos = (90, 0), size = (600, 30), font=0, text = 0),\n\t\t\t\t MultiContentEntryText(pos = (110, 30), size = (600, 50), font=1, flags = RT_VALIGN_TOP, text = 1),\n\t\t\t\t MultiContentEntryPixmapAlphaBlend(pos = (0, 0), size = (80, 80), png = 2),\n\t\t\t\t],\n\t\t\t\t"fonts": [gFont("Regular", 24),gFont("Regular", 20)],\n\t\t\t\t"itemHeight": 85\n\t\t\t\t}\n\t\t\t\n\t\t\n\t\t\n\t'
+ skin = """
+
+
+
+
+
+
+ \n\t\t\t\t{"template": [\n\t\t\t\t MultiContentEntryText(pos = (90, 0), size = (600, 30), font=0, text = 0),\n\t\t\t\t MultiContentEntryText(pos = (110, 30), size = (600, 50), font=1, flags = RT_VALIGN_TOP, text = 1),\n\t\t\t\t MultiContentEntryPixmapAlphaBlend(pos = (0, 0), size = (80, 80)),\n\t\t\t\t],\n\t\t\t\t"fonts": [gFont("Regular", 24),gFont("Regular", 20)],\n\t\t\t\t"itemHeight": 85\n\t\t\t\t}\n\t\t\t
+
+
+ """
+
def __init__(self, session):
Screen.__init__(self, session)
Screen.setTitle(self, _('Mount Manager'))
- self['key_red'] = Label(_('Initialize'))
+ self['key_red'] = Label(_('Initialize ext3'))
self['key_green'] = Label(_('SetupMounts'))
- self['key_yellow'] = Label(_('Unmount'))
+ self['key_yellow'] = Label(_('Initialize ext4'))
self['key_blue'] = Label(_('Exit'))
self['lab1'] = Label()
self.onChangedEntry = []
@@ -59,15 +78,27 @@ class ManagerDevice(Screen):
self['list'] = List(self.list)
self['list'].onSelectionChanged.append(self.selectionChanged)
self['actions'] = ActionMap(['WizardActions', 'ColorActions', 'MenuActions'], {'back': self.close,
- 'red': self.Format,
+ 'red': self.Format_ext3,
'green': self.SetupMounts,
- 'yellow': self.Unmount,
- 'blue': self.Mount})
+ 'yellow': self.Format_ext4,
+ 'blue': self.ExitBack,
+ 'back': self.close})
self.activityTimer = eTimer()
self.activityTimer.timeout.get().append(self.updateList2)
self.updateList()
self.onShown.append(self.setWindowTitle)
+ def Format_ext3(self):
+ from Harddisk import HarddiskSelection
+ self.session.openWithCallback(self.updateList, HarddiskSelection)
+
+ def Format_ext4(self):
+ from Screens.HarddiskSetup import HarddiskSelection
+ self.session.openWithCallback(self.updateList, HarddiskSelection)
+
+ def ExitBack(self):
+ self.close()
+
def setWindowTitle(self):
self.setTitle(_('Mount Manager'))
@@ -123,20 +154,24 @@ class ManagerDevice(Screen):
device2 = re.sub('[0-9]', '', device)
devicetype = path.realpath('/sys/block/' + device2 + '/device')
d2 = device
- name = _('HARD DISK: ')
- mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_hdd.png'
+ name = _('HARD DISK: ')
+ mypixmap = '' + LinkNeoBoot + '/images/dev_hdd.png'
model = file('/sys/block/' + device2 + '/device/model').read()
model = str(model).replace('\n', '')
des = ''
if devicetype.find('usb') != -1:
name = _('USB: ')
- mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png'
+ mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png'
if devicetype.find('usb1') != -1:
name = _('USB1: ')
- mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png'
+ mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png'
if devicetype.find('usb2') != -1:
name = _('USB2: ')
- mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png'
+ mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png'
+ if devicetype.find('card') != -1:
+ name = _('CARD: ')
+ mypixmap = '' + LinkNeoBoot + '/images/dev_sd.png'
+
name = name + model
self.Console = Console()
self.Console.ePopen("sfdisk -l /dev/sd? | grep swap | awk '{print $(NF-9)}' >/tmp/devices.tmp")
@@ -198,13 +233,6 @@ class ManagerDevice(Screen):
os.system('cp /etc/fstab.org /etc/fstab')
self.session.openWithCallback(self.updateList, DevicesConf)
- def Format(self):
- from Screens.HarddiskSetup import HarddiskSelection
- self.session.openWithCallback(self.updateList, HarddiskSelection)
-
- def Mount(self):
- self.close()
-
def Unmount(self):
sel = self['list'].getCurrent()
if sel:
@@ -270,9 +298,19 @@ class ManagerDevice(Screen):
class DevicesConf(Screen, ConfigListScreen):
screenwidth = getDesktop(0).size().width()
if screenwidth and screenwidth == 1920:
- skin = '\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t'
+ skin = """
+
+
+
+
+ """
else:
- skin = '\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t'
+ skin = """
+
+
+
+
+ """
def __init__(self, session):
Screen.__init__(self, session)
@@ -326,19 +364,23 @@ class DevicesConf(Screen, ConfigListScreen):
devicetype = path.realpath('/sys/block/' + device2 + '/device')
d2 = device
name = _('HARD DISK: ')
- mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_hdd.png'
+ mypixmap = '' + LinkNeoBoot + '/images/dev_hdd.png'
model = file('/sys/block/' + device2 + '/device/model').read()
model = str(model).replace('\n', '')
des = ''
if devicetype.find('usb') != -1:
name = _('USB: ')
- mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png'
+ mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png'
if devicetype.find('usb1') != -1:
name = _('USB1: ')
- mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png'
+ mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png'
if devicetype.find('usb2') != -1:
name = _('USB2: ')
- mypixmap = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/dev_usb.png'
+ mypixmap = '' + LinkNeoBoot + '/images/dev_usb.png'
+ if devicetype.find('card') != -1:
+ name = _('CARD: ')
+ mypixmap = '' + LinkNeoBoot + '/images/dev_sd.png'
+
name = name + model
f = open('/proc/mounts', 'r')
for line in f.readlines():
@@ -369,7 +411,11 @@ class DevicesConf(Screen, ConfigListScreen):
('/media/usb', '/media/usb'),
('/media/usb1', '/media/usb1'),
('/media/usb2', '/media/usb2'),
- ('/media/usb3', '/media/usb3')]))
+ ('/media/usb3', '/media/usb3'),
+ ('/media/usb3', '/media/cf'),
+ ('/media/usb3', '/media/card'),
+ ('/media/cf', '/media/cf'),
+ ('/media/card', '/media/card')]))
if dtype == 'Linux':
dtype = 'ext2', 'ext3', 'ext4'
else:
@@ -434,73 +480,77 @@ class DevicesConf(Screen, ConfigListScreen):
out.close()
self.device_uuid2 = result.split('UUID=')[1].split(' ')[0].replace('"', '')
- if fileExists('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager2'):
- out1 = open('/etc/devicemanager.cfg', 'a')
- line1 = '"' + self.device_uuid2 + '"' + ':' + self.mountp + '\n'
- out1.write(line1)
- out1.close()
- elif fileExists('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager'):
- out2 = open('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager/devicemanager.cfg', 'a')
- line2 = '"' + self.device_uuid2 + '"' + ':' + self.mountp + '\n'
- out2.write(line2)
- out2.close()
-
- if fileExists('/etc/init.d/udev'):
- filename = '/etc/init.d/udev'
- if os.path.exists(filename):
+# if fileExists('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager2'):
+# out1 = open('/etc/devicemanager.cfg', 'a')
+# line1 = '"' + self.device_uuid2 + '"' + ':' + self.mountp + '\n'
+# out1.write(line1)
+# out1.close()
+# elif fileExists('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager'):
+# out2 = open('/usr/lib/enigma2/python/Plugins/SystemPlugins/DeviceManager/devicemanager.cfg', 'a')
+# line2 = '"' + self.device_uuid2 + '"' + ':' + self.mountp + '\n'
+# out2.write(line2)
+# out2.close()
+
- filename2 = filename + '.tmp'
- out = open(filename2, 'w')
- f = open(filename, 'r')
- for line in f.readlines():
- if line.find('mount -a /media/hdd; mount -a /media/usb') != -1:
- line = ''
- out.write(line)
-
- f.close()
- out.close()
- os.rename(filename2, filename)
+
- filename2 = filename + '.tmp'
- out = open(filename2, 'w')
- f = open(filename, 'r')
- for line in f.readlines():
- if line.find('exit 0') != -1:
- line = ''
- out.write(line)
-
- f.close()
- out.close()
- os.rename(filename2, filename)
- os.system('echo "mount -a /media/hdd; mount -a /media/usb" >> /etc/init.d/udev; chmod 0755 /etc/init.d/udev ')
-
- if fileExists('/etc/init.d/mdev'):
- filename = '/etc/init.d/mdev'
- if os.path.exists(filename):
-
- filename2 = filename + '.tmp'
- out = open(filename2, 'w')
- f = open(filename, 'r')
- for line in f.readlines():
- if line.find('mount -a /media/hdd; mount -a /media/usb') != -1:
- line = ''
- out.write(line)
-
- f.close()
- out.close()
- os.rename(filename2, filename)
-
- system('echo "" >> /etc/init.d/mdev; echo "mount -a /media/hdd; mount -a /media/usb" >> /etc/init.d/mdev; chmod 0755 /etc/init.d/mdev ')
-
-
+#SetDiskLabel - dziekuje autorowi
class SetDiskLabel(Screen):
- skin = '\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t\t\n\t'
+ screenwidth = getDesktop(0).size().width()
+ if screenwidth and screenwidth == 1920:
+ skin ="""
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """ % (_('!!!Do not set the label for /dev/mmcblk0p !!!'))
+ else:
+ skin = """
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
def __init__(self, session):
global liczymy
Screen.__init__(self, session)
- self.labList = ['hdd', 'usb']
+ self.labList = ['hdd', 'usb','card', 'cf']
self.list = []
self.sprDev()
self.devlist = []
@@ -653,6 +703,6 @@ class DeviceManagerSummary(Screen):
def SkinPath():
myskinpath = resolveFilename(SCOPE_CURRENT_SKIN, '')
- if myskinpath == '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/':
- myskinpath = '/usr/lib/enigma2/python/Plugins/Extensions/NeoBoot/images/'
+ if myskinpath == '' + LinkNeoBoot + '/images/':
+ myskinpath = '' + LinkNeoBoot + '/images/'
return myskinpath
diff --git a/NeoBoot/files/neoconsole.py b/NeoBoot/files/neoconsole.py
new file mode 100644
index 0000000..42007f1
--- /dev/null
+++ b/NeoBoot/files/neoconsole.py
@@ -0,0 +1,220 @@
+# -*- coding: utf-8 -*-
+
+from Plugins.Extensions.NeoBoot.__init__ import _
+from enigma import eConsoleAppContainer
+from Screens.Screen import Screen
+from Components.ActionMap import ActionMap
+from Components.ScrollLabel import ScrollLabel
+from Components.Sources.StaticText import StaticText
+from Screens.MessageBox import MessageBox
+from Components.Label import Label
+
+
+class Console(Screen):
+ skin = """
+
+ """
+
+# def __init__(self, session, title = 'Console', cmdlist = None, finishedCallback = None, closeOnSuccess = False):
+# Screen.__init__(self, session)
+
+ def __init__(self, session, title = _('Console'), cmdlist = None, finishedCallback = None, closeOnSuccess = False):
+ Screen.__init__(self, session)
+ self.finishedCallback = finishedCallback
+ self.closeOnSuccess = closeOnSuccess
+ self.errorOcurred = False
+ self['key_red'] = Label(_('Stop action'))
+ self['key_green'] = Label(_('Hide Console'))
+ self['text'] = ScrollLabel('')
+ self['summary_description'] = StaticText('')
+ self['actions'] = ActionMap(['WizardActions', 'DirectionActions', 'ColorActions'], {'ok': self.cancel,
+ 'back': self.cancel,
+ 'up': self.key_up,
+ 'down': self.key_down,
+ 'green': self.key_green,
+ 'red': self.key_red}, -1)
+ self.cmdlist = cmdlist
+ self.newtitle = title
+ self.screen_hide = False
+ self.cancel_msg = None
+ self.output_file = ''
+ self.onShown.append(self.updateTitle)
+ self.container = eConsoleAppContainer()
+ self.run = 0
+ self.container.appClosed.append(self.runFinished)
+ self.container.dataAvail.append(self.dataAvail)
+ self.onLayoutFinish.append(self.startRun)
+ return
+
+ def updateTitle(self):
+ self.setTitle(self.newtitle)
+
+ def doExec(self, cmd):
+ if isinstance(cmd, (list, tuple)):
+ return self.container.execute(cmd[0], *cmd)
+ else:
+ return self.container.execute(cmd)
+
+ def startRun(self):
+ self['text'].setText(_('Execution progress:') + '\n\n')
+ self['summary_description'].setText(_('Execution progress:'))
+ print '[Console] executing in run', self.run, ' the command:', self.cmdlist[self.run]
+ if self.doExec(self.cmdlist[self.run]):
+ self.runFinished(-1)
+
+ def runFinished(self, retval):
+ if retval:
+ self.errorOcurred = True
+ self.toggleScreenHide(True)
+ self.run += 1
+ if self.run != len(self.cmdlist):
+ if self.doExec(self.cmdlist[self.run]):
+ self.runFinished(-1)
+ else:
+# self['key_red'].setText(_('Close'))
+# self['key_green'].setText(_('Save'))
+ self.toggleScreenHide(True)
+ if self.cancel_msg:
+ self.cancel_msg.close()
+ from Tools.Directories import fileExists
+ if not fileExists('/etc/vtiversion.info'):
+ lastpage = self['text'].isAtLastPage()
+ self['text'].appendText('\n' + _('Execution finished!!'))
+ self['summary_description'].setText('\n' + _('Execution finished!!'))
+ if self.finishedCallback is not None:
+ self.finishedCallback()
+ if not self.errorOcurred and self.closeOnSuccess:
+ self.output_file = 'end'
+ self.cancel()
+ return
+
+ def key_up(self):
+ if self.screen_hide:
+ self.toggleScreenHide()
+ return
+ self['text'].pageUp()
+
+ def key_down(self):
+ if self.screen_hide:
+ self.toggleScreenHide()
+ return
+ self['text'].pageDown()
+
+ def key_green(self):
+ if self.screen_hide:
+ self.toggleScreenHide()
+ return
+ if self.output_file == 'end':
+ pass
+ elif self.output_file.startswith('/tmp/'):
+ self['text'].setText(self.readFile(self.output_file))
+ self['key_green'].setText(_(' '))
+ self.output_file = 'end'
+ elif self.run == len(self.cmdlist):
+ self.saveOutputText()
+ #self.toggleScreenHide()
+ else:
+ self.toggleScreenHide()
+
+ def key_red(self):
+ if self.screen_hide:
+ self.toggleScreenHide()
+ return
+ if self.run == len(self.cmdlist):
+ self.cancel()
+ else:
+ self.cancel_msg = self.session.openWithCallback(self.cancelCB, MessageBox, _('Cancel execution?'), type=MessageBox.TYPE_YESNO, default=False)
+
+ def cancelCB(self, ret = None):
+ self.cancel_msg = None
+ if ret:
+ self.cancel(True)
+ return
+
+ def saveOutputText(self):
+ from time import time, localtime
+ lt = localtime(time())
+ self.output_file = '/tmp/%02d%02d%02d_console.txt' % (lt[3], lt[4], lt[5])
+ self.session.openWithCallback(self.saveOutputTextCB, MessageBox, _("Save the commands and the output to a file?\n('%s')") % self.output_file, type=MessageBox.TYPE_YESNO, default=True)
+
+ def formatCmdList(self, source):
+ if isinstance(source, (list, tuple)):
+ for x in source:
+ for y in self.formatCmdList(x):
+ yield y
+
+ else:
+ yield source
+
+ def saveOutputTextCB(self, ret = None):
+ if ret:
+ from os import path
+ failtext = _("Path to save not exist: '/tmp/'")
+ if path.exists('/tmp/'):
+ text = 'commands ...\n\n'
+ try:
+ cmdlist = list(self.formatCmdList(self.cmdlist))
+ text += 'command line: %s\n\n' % cmdlist[0]
+ script = ''
+ for cmd in cmdlist[0].split():
+ if '.' in cmd:
+ if cmd[-3:] in ('.py', '.sh'):
+ script = cmd
+ break
+
+ if script and path.isfile(script):
+ text += 'script listing: %s\n\n%s\n\n' % (script, self.readFile(script))
+ if len(cmdlist) > 1:
+ text += 'next commands:\n\n' + '\n'.join(cmdlist[1:]) + '\n\n'
+ except:
+ text += 'error read commands!!!\n\n'
+
+ text += '-' * 50 + '\n\noutputs ...\n\n%s' % self['text'].getText()
+ try:
+ f = open(self.output_file, 'w')
+ f.write(text)
+ f.close()
+ self['key_green'].setText(_('Load'))
+ return
+ except:
+ failtext = _("File write error: '%s'") % self.output_file
+
+ self.output_file = 'end'
+ self['key_green'].setText(_(' '))
+ self.session.open(MessageBox, failtext, type=MessageBox.TYPE_ERROR)
+ else:
+ self.output_file = ''
+
+ def toggleScreenHide(self, setshow = False):
+ if self.screen_hide or setshow:
+ self.show()
+ else:
+ self.hide()
+ self.screen_hide = not (self.screen_hide or setshow)
+
+ def readFile(self, file):
+ try:
+ with open(file, 'r') as rdfile:
+ rd = rdfile.read()
+ rdfile.close()
+ except:
+ if file == self.output_file:
+ rd = self['text'].getText()
+ else:
+ rd = "File read error: '%s'\n" % file
+
+ return rd
+
+ def cancel(self, force = False):
+ if self.screen_hide:
+ self.toggleScreenHide()
+ return
+ if force or self.run == len(self.cmdlist):
+ self.close()
+ self.container.appClosed.remove(self.runFinished)
+ self.container.dataAvail.remove(self.dataAvail)
+ if self.run != len(self.cmdlist):
+ self.container.kill()
+
+ def dataAvail(self, str):
+ self['text'].appendText(str)
\ No newline at end of file
diff --git a/NeoBoot/files/stbbranding.py b/NeoBoot/files/stbbranding.py
index 7aa02b1..194bb12 100644
--- a/NeoBoot/files/stbbranding.py
+++ b/NeoBoot/files/stbbranding.py
@@ -332,7 +332,7 @@ def getVuModel():
f = open("/proc/stb/info/vumodel",'r')
procmodel = f.readline().strip()
f.close()
- model = procmodel.title().replace("olose", "olo SE").replace("olo2se", "olo2 SE").replace("2", "²")
+ model = procmodel.title().replace("olose", "olo SE").replace("olo2se", "olo2 SE").replace("2", "²")
return model
#zwraca nazwe stb z pliku hostname
@@ -694,5 +694,3 @@ def getMachineProcModel():
boxbrand = sys.modules[__name__]
-
-