# -*- coding: utf-8 -*- #based on spzZapHistory and ZapHistoryBrowser mod aka Uchkun #created by Vasiliks 11.2015 #added picon providers 05.01.2018 #r0.1_r6 PLI version from . import _ from Components.ActionMap import ActionMap from Components.config import config, ConfigEnableDisable, ConfigInteger, ConfigSelection, ConfigSubsection, getConfigListEntry from Components.ConfigList import ConfigListScreen from Components.Label import Label from Components.MenuList import MenuList from Components.MultiContent import MultiContentEntryProgress, MultiContentEntryText, MultiContentEntryPixmapAlphaBlend from enigma import BT_SCALE, getDesktop, eListboxPythonMultiContent, eServiceCenter, eServiceReference, eTimer, gFont, loadPNG, RT_HALIGN_LEFT, RT_HALIGN_CENTER, RT_HALIGN_RIGHT, RT_WRAP, RT_VALIGN_CENTER, iServiceInformation, iPlayableService, iPlayableServicePtr from Components.ParentalControl import parentalControl from Plugins.Plugin import PluginDescriptor from Screens.ChannelSelection import ChannelSelection from Screens.ParentalControlSetup import ProtectedScreen from Screens.Screen import Screen import Screens.InfoBar from time import localtime, time from Tools.Directories import fileExists, resolveFilename, SCOPE_SKIN_IMAGE, SCOPE_CURRENT_SKIN from Components.Converter.Converter import Converter from ServiceReference import resolveAlternate from Components.Element import cached screenWidth = getDesktop(0).size().width() color = [("0xffffff", _("белый")), ("0xc0c0c0", _("светлосерый")), ("0x8f8f8f", _("серый")), ("0x555555", _("тёмносерый")), ("0xffff55", _("жёлтый")), ("0xffcc33", _("золотой")), ("0xff80ff", _("розовый")), ("0xff8000", _("оранжевый")), ("0xff0000", _("красный")), ("0x800000", _("малиновый")), ("0x804000", _("коричневый")), ("0x80ff00", _("лайм")), ("0x00ff00", _("зелёный")), ("0x008000", _("тёмнозелёный")), ("0x00ffff", _("аква")), ("0x0099ff", _("голубой")), ("0x0000ff", _("синий")), ("0x000080", _("тёмносиний")), ("0x8080ff", _("сиреневый")), ("0x400080", _("фиолетовый"))] config.plugins.vZapHistory = ConfigSubsection() config.plugins.vZapHistory.enable = ConfigSelection(default='on', choices=[('off', _('выключено')), ('on', _('включено')), ('parental_lock', _('выключено в родительском контроле'))]) config.plugins.vZapHistory.maxEntries = ConfigInteger(default=20, limits=(2, 60)) config.plugins.vZapHistory.viewMode = ConfigSelection(default='picons_prov', choices=[('menu', _('стандартный')), ('picons', _('с пиконами')), ('picons_prov', _('с пиконами: провайдеров')), ('picons_prov_sat', _('с пиконами: провайдеров + спутников'))]) config.plugins.vZapHistory.alignment = ConfigSelection(default='left', choices=[('left', _('слева')), ('center', _('по центру')), ('right', _('справа'))]) config.plugins.vZapHistory.autoZap = ConfigEnableDisable(default=False) config.plugins.vZapHistory.namecolor = ConfigSelection(default="0xffffff", choices = color) config.plugins.vZapHistory.namecolor_sel = ConfigSelection(default="0xffffff", choices = color) config.plugins.vZapHistory.eventcolor = ConfigSelection(default="0xffffff", choices = color) config.plugins.vZapHistory.eventcolor_sel = ConfigSelection(default="0xffffff", choices = color) config.plugins.vZapHistory.duratcolor = ConfigSelection(default="0xffffff", choices = color) config.plugins.vZapHistory.duratcolor_sel = ConfigSelection(default="0xffffff", choices = color) config.plugins.vZapHistory.barcolor = ConfigSelection(default="0xffffff", choices = color) config.plugins.vZapHistory.barcolor_sel = ConfigSelection(default="0xffffff", choices = color) skin_sd = """ """ skin_hd = """ """ skin_fhd = """ """ skinConf_sd = """ """ skinConf_hd = """ """ skinConf_fhd = """ """ def addToHistory(instance, ref): if config.plugins.vZapHistory.enable.value == 'off': return else: if config.ParentalControl.servicepinactive.value and config.plugins.vZapHistory.enable.value == 'parental_lock': if parentalControl.getProtectionLevel(ref.toCompareString()) != -1: return if instance.servicePath is not None: tmp = instance.servicePath[:] tmp.append(ref) score = 0 remove = -1 for x in instance.history: if len(x) == 2: xref = x[1] else: xref = x[2] if xref == ref and remove == -1: remove = score score += 1 if remove > -1: del instance.history[remove] instance.history.append(tmp) hlen = len(instance.history) if hlen > config.plugins.vZapHistory.maxEntries.value: del instance.history[0] hlen -= 1 instance.history_pos = hlen - 1 ChannelSelection.addToHistory = addToHistory class vZapHistoryBrowserList(MenuList): def __init__(self, list, enableWrapAround = False): MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent) self.l.setFont(0, gFont('Regular', 24)) self.l.setFont(1, gFont('Regular', 18)) self.l.setFont(2, gFont('Regular', 15)) self.l.setFont(3, gFont('Regular', 15)) def vZapHistoryBrowserListEntry(self, serviceName, eventName, durationTime, bar, png, png_prov, png_prov_sat): # res = [serviceName] lasflags = RT_HALIGN_LEFT if config.plugins.vZapHistory.alignment.value == 'center': lasflags = RT_HALIGN_CENTER elif config.plugins.vZapHistory.alignment.value == 'right': lasflags = RT_HALIGN_RIGHT namecolor = int(config.plugins.vZapHistory.namecolor.value, 16) namecolor_sel = int(config.plugins.vZapHistory.namecolor_sel.value, 16) eventcolor = int(config.plugins.vZapHistory.eventcolor.value, 16) eventcolor_sel = int(config.plugins.vZapHistory.eventcolor_sel.value, 16) duratcolor = int(config.plugins.vZapHistory.duratcolor.value, 16) duratcolor_sel = int(config.plugins.vZapHistory.duratcolor_sel.value, 16) barcolor = int(config.plugins.vZapHistory.barcolor.value, 16) barcolor_sel = int(config.plugins.vZapHistory.barcolor_sel.value, 16) if screenWidth == 1920: if config.plugins.vZapHistory.viewMode.value == 'picons': self['list'].l.setItemHeight(70) png_pos=(5, 5) png_size=(100, 60) serviceName_pos=(110, 3) serviceName_size=(675, 25) serviceName_font=0 eventName_pos=(110, 28) eventName_size=(675, 40) eventName_font=1 durationTime_pos=(795, 16) durationTime_size=(180, 25) durationTime_font=2 bar_pos=(795, 45) bar_size=(180, 10) if config.plugins.vZapHistory.viewMode.value == 'picons_prov': self['list'].l.setItemHeight(70) png_pos=(5, 5) png_size=(100, 60) png_prov_pos=(110, 5) png_prov_size=(100, 60) serviceName_pos=(215, 3) serviceName_size=(570, 25) serviceName_font=0 eventName_pos=(215, 28) eventName_size=(570, 40) eventName_font=1 durationTime_pos=(795, 16) durationTime_size=(180, 25) durationTime_font=2 bar_pos=(795, 45) bar_size=(180, 10) elif config.plugins.vZapHistory.viewMode.value == 'menu': self['list'].l.setItemHeight(50) serviceName_pos=(5, 1) serviceName_size=(785, 24) serviceName_font=0 eventName_pos=(5, 25) eventName_size=(785, 25) eventName_font=1 durationTime_pos=(795, 5) durationTime_size=(180, 20) durationTime_font=2 bar_pos=(795, 30) bar_size=(180, 10) elif screenWidth == 1280: if config.plugins.vZapHistory.viewMode.value == 'picons': self['list'].l.setItemHeight(61) png_pos=(3, 3) png_size=(90, 54) serviceName_pos=(100, 2) serviceName_size=(971, 21) serviceName_font=1 eventName_pos=(100, 20) eventName_size=(971, 40) eventName_font=2 durationTime_pos=(1076, 10) durationTime_size=(181, 20) durationTime_font=3 bar_pos=(1076, 33) bar_size=(181, 6) elif config.plugins.vZapHistory.viewMode.value == 'picons_prov': self['list'].l.setItemHeight(61) png_prov_pos=(3, 3) png_prov_size=(90, 54) png_pos=(99, 3) png_size=(90, 54) serviceName_pos=(192, 2) serviceName_size=(879, 21) serviceName_font=1 eventName_pos=(192, 20) eventName_size=(879, 40) eventName_font=2 durationTime_pos=(1076, 10) durationTime_size=(181, 20) durationTime_font=3 bar_pos=(1076, 33) bar_size=(181, 6) elif config.plugins.vZapHistory.viewMode.value == 'picons_prov_sat': self['list'].l.setItemHeight(61) png_prov_sat_pos=(3, 3) png_prov_sat_size=(90, 54) png_prov_pos=(98, 3) png_prov_size=(90, 54) png_pos=(193, 3) png_size=(90, 54) serviceName_pos=(288, 2) serviceName_size=(783, 21) serviceName_font=1 eventName_pos=(288, 20) eventName_size=(783, 40) eventName_font=2 durationTime_pos=(1076, 10) durationTime_size=(181, 20) durationTime_font=3 bar_pos=(1076, 33) bar_size=(181, 6) elif config.plugins.vZapHistory.viewMode.value == 'menu': self['list'].l.setItemHeight(61) serviceName_pos=(5, 2) serviceName_size=(1066, 21) serviceName_font=1 eventName_pos=(5, 20) eventName_size=(1066, 40) eventName_font=2 durationTime_pos=(1076, 10) durationTime_size=(181, 20) durationTime_font=3 bar_pos=(1076, 33) bar_size=(181, 6) else: self['list'].l.setItemHeight(50) png_pos=(0, 0) png_size=(1, 1) serviceName_pos=(10, 2) serviceName_size=(360, 18) serviceName_font=1 eventName_pos=(10, 20) eventName_size=(360, 30) eventName_font=2 durationTime_pos=(380, 15) durationTime_size=(140, 25) durationTime_font=2 bar_pos=(380, 32) bar_size=(140, 8) if 'picons' in config.plugins.vZapHistory.viewMode.value: res.append(MultiContentEntryPixmapAlphaBlend(pos=png_pos, size=png_size, flags = BT_SCALE, png=png)) if 'picons_prov' in config.plugins.vZapHistory.viewMode.value: res.append(MultiContentEntryPixmapAlphaBlend(pos=png_prov_pos, size=png_prov_size, flags = BT_SCALE, png=png_prov)) res.append(MultiContentEntryText(pos=serviceName_pos, size=serviceName_size, font=serviceName_font, flags=lasflags, text=serviceName, color=namecolor, color_sel=namecolor_sel)) res.append(MultiContentEntryText(pos=eventName_pos, size=eventName_size, font=eventName_font, flags=lasflags | RT_VALIGN_CENTER | RT_WRAP, text=eventName, color=eventcolor, color_sel=eventcolor_sel)) res.append(MultiContentEntryText(pos=durationTime_pos, size=durationTime_size, font=durationTime_font, flags=lasflags, text=durationTime, color=duratcolor, color_sel=duratcolor_sel)) if 'picons_prov_sat' in config.plugins.vZapHistory.viewMode.value: res.append(MultiContentEntryPixmapAlphaBlend(pos=png_prov_sat_pos, size=png_prov_sat_size, flags = BT_SCALE, png=png_prov_sat)) res.append(MultiContentEntryText(pos=serviceName_pos, size=serviceName_size, font=serviceName_font, flags=lasflags, text=serviceName, color=namecolor, color_sel=namecolor_sel)) res.append(MultiContentEntryText(pos=eventName_pos, size=eventName_size, font=eventName_font, flags=lasflags | RT_VALIGN_CENTER | RT_WRAP, text=eventName, color=eventcolor, color_sel=eventcolor_sel)) res.append(MultiContentEntryText(pos=durationTime_pos, size=durationTime_size, font=durationTime_font, flags=lasflags, text=durationTime, color=duratcolor, color_sel=duratcolor_sel)) if bar != 0: res.append(MultiContentEntryProgress(pos=bar_pos, size=bar_size, percent=bar, borderWidth=1, foreColor=barcolor, foreColorSelected=barcolor_sel)) return res class vZapHistory(Screen, ProtectedScreen): def __init__(self, session, servicelist): Screen.__init__(self, session) ProtectedScreen.__init__(self) if screenWidth and screenWidth == 1280: self.skin = skin_hd elif screenWidth and screenWidth == 1920: self.skin = skin_fhd else: self.skin = skin_sd self.session = session self.servicelist = servicelist or Screens.InfoBar.InfoBar.instance.servicelist self.serviceHandler = eServiceCenter.getInstance() self.allowChanges = True self.zapDown = False self.time = 3 self['list'] = vZapHistoryBrowserList([]) self['key_green'] = Label(_('Переключить')) self['key_red'] = Label(_('Очистить')) self['key_yellow'] = Label(_('Удалить')) self['key_blue'] = Label(_('Настройки')) self.setTitle(_("История переключения каналов")) self['actions'] = ActionMap(['OkCancelActions', 'ColorActions', 'DirectionActions'], {'cancel': self.cancel, 'left': self.keyLeft, 'right': self.keyRight, 'up': self.keyUp, 'down': self.keyDown, 'ok': self.zapAndClose, 'blue': self.config, 'green': self.zap, 'yellow': self.delete, 'red': self.clear}, -1) self.onLayoutFinish.append(self.buildList) self.timerAutoZap = eTimer() self.timerAutoZap.callback.append(self.zap) def cancel(self): self.timerAutoZap.stop() self.close() def findPicon(self, serviceName): try: if '::' in serviceName: serviceName = serviceName.split('::')[0] + ':' except: pass serviceName = serviceName.toString() serviceName = '_'.join(serviceName.split(':', 10)[:10]) searchPaths = ['/media/hdd/picon/', '/media/usb/picon/', '/usr/share/enigma2/picon/', '/media/sda1/picon/', '/media/sdb1/picon/'] for path in searchPaths: pngname = path + serviceName + '.png' if fileExists(pngname): return pngname pngname = path + 'picon_default.png' if fileExists(pngname): return pngname pngname = resolveFilename(SCOPE_CURRENT_SKIN, 'picon_default.png') if fileExists(pngname): return pngname else: return resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/picon_default.png') def findPiconprov(self, service): name = self.getProviderName(service) serviceName = name.upper() searchPaths = ['/media/hdd/piconProv/', '/media/usb/piconProv/', '/usr/share/enigma2/piconProv/', '/media/sda1/piconProv/', '/media/sdb1/piconProv/'] for path in searchPaths: pngname = path + serviceName + '.png' if fileExists(pngname): return pngname pngname = path + 'picon_default.png' if fileExists(pngname): return pngname pngname = resolveFilename(SCOPE_CURRENT_SKIN, 'picon_default.png') if fileExists(pngname): return pngname else: return resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/picon_default.png') def findPiconprovsat(self, service): name = self.getProviderName(service) serviceName = name.upper() searchPaths = ['/media/hdd/piconProv/', '/media/usb/piconProv/', '/usr/share/enigma2/piconProv/', '/media/sda1/piconProv/', '/media/sdb1/piconProv/'] for path in searchPaths: pngname = path + serviceName + '.png' if fileExists(pngname): return pngname pngname = path + 'picon_default.png' if fileExists(pngname): return pngname pngname = resolveFilename(SCOPE_CURRENT_SKIN, 'picon_default.png') if fileExists(pngname): return pngname else: return resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/picon_default.png') def findPiconprovsat(self, service): name = self.getProviderName(service) serviceName = name.upper() searchPaths = ['/media/hdd/piconProv/', '/media/usb/piconProv/', '/usr/share/enigma2/piconProv/', '/media/sda1/piconProv/', '/media/sdb1/piconProv/'] for path in searchPaths: pngname = path + serviceName + '.png' if fileExists(pngname): return pngname pngname = path + 'picon_default.png' if fileExists(pngname): return pngname pngname = resolveFilename(SCOPE_CURRENT_SKIN, 'picon_default.png') if fileExists(pngname): return pngname else: return resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/picon_default.png') def getProviderName(self, ref): if isinstance(ref, eServiceReference): from Screens.ChannelSelection import service_types_radio, service_types_tv typestr = ref.getData(0) in (2,10) and service_types_radio or service_types_tv pos = typestr.rfind(':') rootstr = '%s (channelID == %08x%04x%04x) && %s FROM PROVIDERS ORDER BY name' %(typestr[:pos+1],ref.getUnsignedData(4),ref.getUnsignedData(2),ref.getUnsignedData(3),typestr[pos+1:]) provider_root = eServiceReference(rootstr) serviceHandler = eServiceCenter.getInstance() providerlist = serviceHandler.list(provider_root) if not providerlist is None: while True: provider = providerlist.getNext() if not provider.valid(): break if provider.flags & eServiceReference.isDirectory: servicelist = serviceHandler.list(provider) if not servicelist is None: while True: service = servicelist.getNext() if not service.valid(): break if service == ref: info = serviceHandler.info(provider) return info and info.getName(provider) or "Unknown" return "" def buildList(self): prov = "" list = [] for x in self.servicelist.history: if len(x) == 2: ref = x[1] else: ref = x[2] png = loadPNG(self.findPicon(ref)) png_prov = loadPNG(self.findPiconprov(ref)) png_prov_sat = loadPNG(self.findPiconprovsat(ref)) info = self.serviceHandler.info(ref) if info: name = info.getName(ref).replace('\xc2\x86', '').replace('\xc2\x87', '') event = info.getEvent(ref) if event is not None: eventName = event.getEventName() if eventName is None: eventName = '' else: eventName = eventName.replace('(18+)', '').replace('18+', '').replace('(16+)', '').replace('16+', '').replace('(12+)', '').replace('12+', '').replace('(7+)', '').replace('7+', '').replace('(6+)', '').replace('6+', '').replace('(0+)', '').replace('0+', '') try: begin = event.getBeginTime() if begin is not None: end = begin + event.getDuration() remaining = (end - int(time())) / 60 prefix = '' if remaining > 0: prefix = "+" local_begin = localtime(begin) local_end = localtime(end) bar = 0 perc = '' i = (100 * (int(time()) - begin)) / event.getDuration() if i < 101: bar = i durationTime = _("%02d:%02d - %02d:%02d ( %s%04d мин. )") % (local_begin[3],local_begin[4],local_end[3],local_end[4],prefix, remaining) except: durationTime = '' else: eventName = '' durationTime = '' descriptionName = '' bar = 0 else: name = 'N/A' eventName = '' durationTime = '' descriptionName = '' bar = 0 list.append(vZapHistoryBrowserListEntry(self, name, eventName, durationTime, bar, png, png_prov, png_prov_sat)) list.reverse() self['list'].setList(list) def keyRight(self): self.zapDown = False self.timerAutoZap.stop() self['list'].pageDown() if config.plugins.vZapHistory.autoZap.value: self.timerAutoZap.startLongTimer(self.time) def keyLeft(self): self.zapDown = False self.timerAutoZap.stop() self['list'].pageUp() if config.plugins.vZapHistory.autoZap.value: self.timerAutoZap.stop() self.timerAutoZap.startLongTimer(self.time) def keyUp(self): self.zapDown = False self.timerAutoZap.stop() pos = self['list'].getSelectionIndex() lon = len(self['list'].list) if pos == 0 and lon > 1: self['list'].moveToIndex(lon - 1) else: self['list'].up() if pos == 1: return if config.plugins.vZapHistory.autoZap.value: self.timerAutoZap.startLongTimer(self.time) def keyDown(self): self.zapDown = True self.timerAutoZap.stop() pos = self['list'].getSelectionIndex() lon = len(self['list'].list) if pos == lon - 1 and lon > 1: self['list'].moveToIndex(0) else: self['list'].down() if config.plugins.vZapHistory.autoZap.value: self.timerAutoZap.startLongTimer(self.time) def zapAndClose(self): self.zapDown = False self.zap() self.close() def zap(self): self.timerAutoZap.stop() length = len(self.servicelist.history) if length > 0: self.servicelist.history_pos = length - self['list'].getSelectionIndex() - 1 self.servicelist.setHistoryPath() idx = length - self['list'].getSelectionIndex() - 1 value_idx = self.servicelist.history[idx] del self.servicelist.history[idx] self.servicelist.history.append(value_idx) self.time = 2 if self.zapDown: self.time = 5 self.keyDown() self.buildList() def clear(self): self.timerAutoZap.stop() if self.allowChanges: for i in range(0, len(self.servicelist.history)): del self.servicelist.history[0] self.buildList() self.servicelist.history_pos = 0 def delete(self): self.timerAutoZap.stop() if self.allowChanges: length = len(self.servicelist.history) if length > 0: idx = length - self['list'].getSelectionIndex() - 1 del self.servicelist.history[idx] self.buildList() currRef = self.session.nav.getCurrentlyPlayingServiceReference() idx = 0 for x in self.servicelist.history: if len(x) == 2: ref = x[1] else: ref = x[2] if ref == currRef: self.servicelist.history_pos = idx break else: idx += 1 def config(self): self.timerAutoZap.stop() self.session.openWithCallback(self.buildList, vZapHistoryConf) def isProtected(self): return config.ParentalControl.servicepinactive.value and config.ParentalControl.configured.value def pinEntered(self, result): if result is None: self.allowChanges = False elif not result: self.allowChanges = False else: self.allowChanges = True class vZapHistoryConf(ConfigListScreen, Screen): def __init__(self, session): Screen.__init__(self, session) self.session = session if screenWidth == 1920: self.skin = skinConf_fhd elif screenWidth == 1280: self.skin = skinConf_hd else: self.skin = skinConf_sd self['key_red'] = Label(_('Cancel')) self['key_green'] = Label( _('Save')) self.setTitle(_('Настройки')) ConfigListScreen.__init__(self, [getConfigListEntry(_('Разрешить историю переключений:'), config.plugins.vZapHistory.enable), getConfigListEntry(_('Режим показа:'), config.plugins.vZapHistory.viewMode), getConfigListEntry(_('Выравнивание списка:'), config.plugins.vZapHistory.alignment), getConfigListEntry(_('Максимум записей в истории:'), config.plugins.vZapHistory.maxEntries), getConfigListEntry(_('Автопереключение при перемещении в списке:'), config.plugins.vZapHistory.autoZap), getConfigListEntry(_('Цвет названия канала:'), config.plugins.vZapHistory.namecolor), getConfigListEntry(_('Цвет названия передачи:'), config.plugins.vZapHistory.eventcolor), getConfigListEntry(_('Цвет времени передачи:'), config.plugins.vZapHistory.duratcolor), getConfigListEntry(_('Цвет прогресс-бара:'), config.plugins.vZapHistory.barcolor), getConfigListEntry(_('Цвет названия канала под курсором:'), config.plugins.vZapHistory.namecolor_sel), getConfigListEntry(_('Цвет названия передачи под курсором:'), config.plugins.vZapHistory.eventcolor_sel), getConfigListEntry(_('Цвет времени передачи под курсором:'), config.plugins.vZapHistory.duratcolor_sel), getConfigListEntry(_('Цвет прогресс-бара под курсором:'), config.plugins.vZapHistory.barcolor_sel)]) self['actions'] = ActionMap(['OkCancelActions', 'ColorActions'], {'ok': self.save, 'green': self.save, 'cancel': self.exit, 'red': self.exit}, -2) def save(self): for x in self['config'].list: x[1].save() self.close() def exit(self): for x in self['config'].list: x[1].cancel() self.close() def main(session, servicelist = None, **kwargs): session.open(vZapHistory, servicelist) def Plugins(**kwargs): return PluginDescriptor(name=_('История переключения каналов'), description=_("Show the 'Channel Switching History' on the screen"), where=PluginDescriptor.WHERE_PLUGINMENU, icon = 'vzh.png', fnc=main)