Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
from __future__ import print_function
#
# Tuner Error Plugin by gutemine
#
tunererror_version="1.4-r4"
#
from Components.ActionMap import ActionMap
from Components.Label import Label
from Components.config import config, ConfigSubsection, ConfigIP, ConfigText, ConfigBoolean, ConfigSelection, getConfigListEntry
from Components.ConfigList import ConfigListScreen
from Plugins.Plugin import PluginDescriptor
from Components.Pixmap import Pixmap
from Screens.Screen import Screen
from Screens.MessageBox import MessageBox
from Screens.ChannelSelection import ChannelSelectionRadio as ChannelSelectionRadio
from Components.SystemInfo import SystemInfo
from enigma import getDesktop, eTimer, eDVBServicePMTHandler, iServiceInformation, eEPGCache, eSize, eListboxPythonMultiContent
from enigma import eLabel, eServiceReference, RT_VALIGN_CENTER, RT_HALIGN_LEFT, RT_HALIGN_RIGHT, eListbox
from os import path as os_path, listdir as os_listdir
import socket
import gm
from socket import gethostname, getfqdn, gethostbyaddr, getaddrinfo
from skin import componentSizes
from time import time, localtime
import subprocess

numVideoDecoders = SystemInfo.get("NumVideoDecoders", 1)                        
#numVideoDecoders= 1 # Test-Value to simulate One/Two on 920   

sz_w = getDesktop(0).size().width() 

tunererror_plugindir="/usr/lib/enigma2/python/Plugins/SystemPlugins/TunerError"
tunererror_str=_("Tuner status")+" "+_("Error")
tunererror_description_str=_("User defined")+" "+_("Tuner status")+" "+_("Error")+" "+_("Message")
yes_no_descriptions = {False: _("no"), True: _("yes")}

config.plugins.tunererror = ConfigSubsection()
timeouts =[]                             
timeouts.append(("0",_("none")))
timeouts.append(("2",_("2")))
timeouts.append(("5",_("5")))
timeouts.append(("10",_("10")))
config.plugins.tunererror.timeout = ConfigSelection(default = "5", choices=timeouts)
opt =[]                             
opt.append(("none",_("none")))
opt.append(("default",_("Default")))
opt.append(("message",_("Message")))
opt2 =[]                             
opt2.append(("none",_("none")))
opt2.append(("default",_("Default")))
opt2.append(("message",_("Message")))
opt2.append(("zap",_("zapped")))
nopt =[]                             
nopt.append(("none",_("none")))
nopt.append(("default",_("Default")))
nopt.append(("message",_("Message")))
nopt.append(("remote",_("Streaming")))
nodef =[]                             
nodef.append(("none",_("none")))
nodef.append(("message",_("Message")))
config.plugins.tunererror.eventNoResources = ConfigSelection(default = "default", choices=nopt)
hidden =[]                             
config.plugins.tunererror.complete = ConfigBoolean(default=True, descriptions=yes_no_descriptions)
config.plugins.tunererror.virtualzap = ConfigBoolean(default=False, descriptions=yes_no_descriptions)
config.plugins.tunererror.radio = ConfigBoolean(default=False, descriptions=yes_no_descriptions)
server_opt =[]                             
server_opt.append(("ip",_("IP Address") ))
server_opt.append(("name",_("Server IP").replace("IP",_("Name")) ))
config.plugins.tunererror.server = ConfigSelection(default = "ip", choices=server_opt)
config.plugins.tunererror.ip = ConfigIP(default = [192,168,0,220])
hostname=gethostname()
fullname=getfqdn(hostname)
config.plugins.tunererror.hostname = ConfigText(default = fullname, visible_width = 50, fixed_size = False)
config.plugins.tunererror.password = ConfigText(default = "dreambox", visible_width = 50, fixed_size = False)
config.plugins.tunererror.eventTuneFailed = ConfigSelection(default = "default", choices=opt2)
config.plugins.tunererror.eventNoPAT = ConfigSelection(default = "default", choices=opt)
config.plugins.tunererror.eventNoPATEntry = ConfigSelection(default = "default", choices=opt)
config.plugins.tunererror.eventNoPMT = ConfigSelection(default = "default", choices=opt)
config.plugins.tunererror.eventNewProgramInfo = ConfigSelection(default = "none", choices=nodef)
config.plugins.tunererror.eventTuned = ConfigSelection(default = "none", choices=nodef)
config.plugins.tunererror.eventSOF = ConfigSelection(default = "none", choices=nodef)
config.plugins.tunererror.eventEOF = ConfigSelection(default = "none", choices=nodef)
config.plugins.tunererror.eventMisconfiguration = ConfigSelection(default = "default", choices=nopt)

YELLOWC =  '\033[33m'                                                           
ENDC = '\033[m'                                                                 
                                                                                
def cprint(text):                                                               
        print(YELLOWC+"[TunerError] "+text+ENDC)                                            

def ping_doOne(server='example.com', wait_sec=1, count=1):
    cprint(">>>> ping_doOne(%s)" % server)
    cmd = "ping -c {} -W {} {}".format(count, wait_sec, server).split(' ')
    try:
        output = subprocess.check_output(cmd).decode().strip()
        lines = output.split("\n")
        loss = lines[-2].split(',')[2].split()[0]
        timing = lines[-1].split()[3].split('/')
        return {
            'type': 'rtt',
            'min': timing[0],
            'avg': timing[1],
            'max': timing[2],
            'loss': loss,
        }
    except Exception as e:
        #print (e)
        return None

gPiPinstalled=False
if os_path.exists("/usr/lib/enigma2/python/Plugins/SystemPlugins/gPiP") and numVideoDecoders < 2 and not gm.universal():
    gPiPinstalled=True
    from Plugins.SystemPlugins.gPiP.plugin import gPiP, gPiPgetCmd, gPiPgetContainer, gPiPgetRunning
    global gpip_container
    gpip_container=gPiPgetContainer()                                        

    gPiPdeadStream_ori=gPiP.deadStream

    def TunerError_gPiPdeadStream(self=None):
        cprint(">>>>>> TunerError.gPiPdeadStream")
        # housekeeping in case the stream failed, simply start once more ...    
        if gPiPdeadStream_ori():
            cprint("re-run died stream ...")                                 
            gpip_cmd=gPiPgetCmd()
            cprint(gpip_cmd)                                                 
            global gpip_container
            gpip_container.execute(gpip_cmd)                              
        tryRemoteStreaming=False
        if config.plugins.tunererror.eventNoResources.value=="remote":
            tryRemoteStreaming=True
        if config.plugins.tunererror.eventMisconfiguration.value=="remote":
            tryRemoteStreaming=True
        if tryRemoteStreaming:
            cprint("check gPiP once more ...")
            gPiP.remoteStreamingTimer = eTimer()        
            gPiP.remoteStreamingTimer_conn = gPiP.remoteStreamingTimer.timeout.connect(gPiP.remoteStreaming)
            gPiP.remoteStreamingTimer.start(1000, True)
        # always return False, because handler is now HERE !!!
        return False

    def TunerError_gPiPremoteStreaming(self=None):    
        if gPiPdeadStream_ori(): # when last check fails, we try remotely ...
            cprint("re-run stream DIED AGAIN ...")
            gpip_cmd=gPiPgetCmd() 
            cprint(gpip_cmd)                                                 
            sref=gPiPgetRunning()
            if sref is None:
                return
            ref = sref.toString()
            if ref.startswith("1:256") or ref.find("//") is not -1: 
                cprint("FAILED for %s" % ref)
                # already (remote) streaming, we are dead
                return
            cprint("TRYING REMOTE STREAMING for %s" % ref)
            if config.plugins.tunererror.server.value=="ip":
                host = "%d.%d.%d.%d" % tuple(config.plugins.tunererror.ip.value)
            else:
                host = config.plugins.tunererror.hostname.value
            password = str(config.plugins.tunererror.password.value)
            port = "8001"
            username = "root"
            if len(password) == 0:
                http = "http://%s:%s/" % (host,port)       
            else:
                http = "http://%s:%s@%s:%s/" % (username,password,host,port)       
            sp=[]
            sp=ref.split(":")
            # change stream service reference for retry ...
            if len(sp) > 9:                                                        
                # change stream service reference for retry ...
                nref="%s:256:%s:%s:%s:%s:%s:%s:%s:%s:" % (sp[0].upper(),sp[2].upper(),sp[3].upper(),sp[4].upper(),sp[5].upper(),sp[6].upper(),sp[7].upper(),sp[8].upper(),sp[9].upper())
                new=http+nref
                cprint("start remote http streaming %s ..." % new)
                xx, yy, ww, hh = gPiP.dialog.getPiP_Position()
                analyzeduration=""
                if gm.arch()=="arm64":
                    analyzeduration="-analyzeduration %s" % config.plugins.gpip.analyze.value
                gpip_cmd="/usr/bin/ffmpeg -re %s -i \"%s\" -movflags +faststart -vf \"scale=w=%s:h=%s\" -pix_fmt rgba -xoffset %s -yoffset %s -f fbdev /dev/fb0" % (analyzeduration,new,ww,hh,xx,yy) 
                cprint(gpip_cmd)
                global gpip_container
                gpip_container.execute(gpip_cmd)                              

    gPiP.deadStream=TunerError_gPiPdeadStream
    gPiP.remoteStreaming=TunerError_gPiPremoteStreaming

QuadPiPinstalled=False
if os_path.exists("/usr/lib/enigma2/python/Plugins/Extensions/QuadPip") and numVideoDecoders < 2:
    QuadPiPinstalled=True
    from Plugins.Extensions.QuadPip.qpip import QuadPipScreen

    def TunerError_QuadPip_deadStreams(self=None):
        cprint(">>>>>> TunerError.QuadPip_deadStreams")
        if SystemInfo.get("NumVideoDecoders", 1) > 1:
            start=3
        else:
            start=2
        if config.plugins.quadpip.zapping.value:
            start=1
        for idx in range(start,5):
            if len(self.qpip_cmd[idx]) > 0:
                dead=True
                check=self.qpip_cmd[idx].replace('\"','').replace(" ","")
                cprint("checking QuadPip #%d" % idx)
                for dirname in os_listdir('/proc'):
                    cmd="/proc/"+dirname+"/cmdline"
                    if os_path.exists(cmd):
                        f=open(cmd,"rb")
                        cmdline=f.readline()
                        f.close()
                        if cmdline.startswith("/usr/bin/ffmpeg"):
                            ncmdline=cmdline.replace("\0","")
                            if check==ncmdline:
                                dead=False
                if dead:
                    cprint("Re-starting QuadPip #%d: %s" % (idx,self.qpip_cmd[idx]))
                    self.qpip_containers[idx].execute(self.qpip_cmd[idx])
        tryRemoteStreaming=False
        if config.plugins.tunererror.eventNoResources.value=="remote":
            tryRemoteStreaming=True
        if config.plugins.tunererror.eventMisconfiguration.value=="remote":
            tryRemoteStreaming=True
        if tryRemoteStreaming:
            cprint("check Quad PiP once more ...")
            self.remoteQuadPipTimer = eTimer()        
            self.remoteQuadPipTimer_conn = self.remoteQuadPipTimer.timeout.connect(self.remoteQuadPip)
            self.remoteQuadPipTimer.start(1000, True)

    def TunerError_QuadPip_remoteQuadPip(self=None):
        cprint(">>>>>> TunerError_QuadPip_remoteQuadPip")
        # when last check fails, we try remotely ...
        if SystemInfo.get("NumVideoDecoders", 1) > 1:
            start=3
        else:
            start=2
        if config.plugins.quadpip.zapping.value:
            start=1
        for idx in range(start,5):
            if len(self.qpip_cmd[idx]) > 0:
                dead=True
                check=self.qpip_cmd[idx].replace('\"','').replace(" ","")
                cprint("checking QuadPip #%d" % idx)
                for dirname in os_listdir('/proc'):
                    cmd="/proc/"+dirname+"/cmdline"
                    if os_path.exists(cmd):
                        f=open(cmd,"rb")
                        cmdline=f.readline()
                        f.close()
                        if cmdline.startswith("/usr/bin/ffmpeg"):
                            ncmdline=cmdline.replace("\0","")
                            if check==ncmdline:
                                dead=False
                if dead:
                    cprint("Re-run QuadPip #%d: %s DIED AGAIN" % (idx,self.qpip_cmd[idx]))
                    cmd=self.qpip_cmd[idx]
                    if cmd.find("1:256") is not -1 or cmd.find("http://localhost:8001/") is -1: 
                	cprint("FAILED for %s"  % cmd)
                        # already (remote) streaming, we are dead
                        continue
                    cprint("TRYING REMOTE STREAMING ...")
                    if config.plugins.tunererror.server.value=="ip":
                         host = "%d.%d.%d.%d" % tuple(config.plugins.tunererror.ip.value)
                    else:
                         host = config.plugins.tunererror.hostname.value
                    password = str(config.plugins.tunererror.password.value)
                    port = "8001"
                    username = "root"
                    if len(password) == 0:
                        http = "http://%s:%s/" % (host,port)       
                    else:
                        http = "http://%s:%s@%s:%s/" % (username,password,host,port)       
                    cprint(http)
                    sp=[]
		    sp=cmd.split("http://localhost:8001/")
                    ref=sp[1]
                    sp=ref.split(":")
                    # change stream service reference for retry ...
                    if len(sp) > 9:                                                        
                        # change stream service reference for retry ...
                        nref="%s:256:%s:%s:%s:%s:%s:%s:%s:%s:" % (sp[0].upper(),sp[2].upper(),sp[3].upper(),sp[4].upper(),sp[5].upper(),sp[6].upper(),sp[7].upper(),sp[8].upper(),sp[9].upper())
                        new=http+nref
                        cprint("start remote http streaming %s ..." % new)
			sp=cmd.split("-movflags +faststart")
                        analyzeduration=""
                        if gm.arch()=="arm64":
                            analyzeduration="-analyzeduration %s" % config.plugins.quadpip.analyze.value
                        self.qpip_cmd[idx]="/usr/bin/ffmpeg -loglevel quiet -re %s -i \"%s\" -movflags +faststart " % (analyzeduration,new)
                        self.qpip_cmd[idx]+=sp[1]
                        cprint(self.qpip_cmd[idx])
                        self.qpip_containers[idx].execute(self.qpip_cmd[idx])                              

    def TunerError_QuadPip_playAudioVideo(self, idx):                                    
        cprint(">>>>>> TunerError_QuadPip_playAudioVido #%d" % idx)                      
        self.curPlayAudioVideo = idx                
        channel = self.qpipChannelList.getCurrentChannel()
	chName=channel.getChannelName(str(idx),False)
        sref = channel.getChannelSref(str(idx))                       
        cprint("sref: %s stream: %s" % (sref,self.qpip_cmd[idx]))
        # check if not a remote channel and if tuner error was needed ... 
	if sref.find("//") is -1 and self.qpip_cmd[idx].find("http://localhost:8001/") is -1:
	    cprint("needs remote help ...")
   	    sp=[]
	    sp=self.qpip_cmd[idx].split(":8001/")
	    if len(sp) > 1:
	        streamref=sp[1]
	        cprint("streamref: %s" % streamref)
 	        sp=streamref.split("\" -movflags +faststart")
		streamref=sp[0]
	        cprint("streamref: %s" % streamref)
    	        sp=self.qpip_cmd[idx].split("http://")
 	        if len(sp) > 1:
		    url=sp[1]
   	            cprint("url: %s" % url)
		    sp=url.split("\" -movflags +faststart")
		    url=sp[0]
		    sp=url.split("@")
 	            if len(sp) > 1:
		        url=sp[1].replace(":","%3a")
   	                cprint("url: %s" % url)
	                sref=streamref+"http%3a//"+url
   	                cprint("REMOTE: %s sref: %s" % (chName,sref))
        if sref is not None and config.plugins.quadpip.zapping.value:
            self.session.nav.playService(eServiceReference(sref))               
            # should not do any harm ...                             
            self.deadStreams()   

    QuadPipScreen.deadStreams=TunerError_QuadPip_deadStreams
    QuadPipScreen.playAudioVideo=TunerError_QuadPip_playAudioVideo
    QuadPipScreen.remoteQuadPip=TunerError_QuadPip_remoteQuadPip

# csel.bouquet_mark_edit values from ChannelSelection.py                                            
OFF = 0                                
EDIT_BOUQUET = 1      
EDIT_ALTERNATIVES = 2   

def TunerError_onCreate(self):                                                     
	cprint(">>>>>>>> onCreate")
        self.setRadioMode()                                             
        self.restoreRoot()                                              
        lastservice=eServiceReference(config.radio.lastservice.value)   
        if lastservice.valid():                                         
        	self.servicelist.setCurrent(lastservice)                
		sref=lastservice.toString()
	        if config.plugins.tunererror.radio.value and sref.find("http") is -1:
		    cprint(">>> onStatrt Radio remote %s" % sref)
	            if not sref.startswith("1:256"): # prevent recursive calls ...
	                if config.plugins.tunererror.server.value=="ip":
	                    host = "%d.%d.%d.%d" % tuple(config.plugins.tunererror.ip.value)
	                else:
	                    host = config.plugins.tunererror.hostname.value
	                password = str(config.plugins.tunererror.password.value)
	                port = "8001"
	                username = "root"
	                if len(password) == 0:
	                    http = "http://%s:%s/" % (host,port)       
	                else:
	                    http = "http://%s:%s@%s:%s/" % (username,password,host,port)       
	                    http=http.replace(":","%3a")
	                sp=[]
	                sp=sref.split(":")
	                # change stream service reference for retry ...
	                if len(sp) > 9:                                                        
	                    # change stream service reference for retry ...
	                    nref="%s:256:%s:%s:%s:%s:%s:%s:%s:%s:" % (sp[0].upper(),sp[2].upper(),sp[3].upper(),sp[4].upper(),sp[5].upper(),sp[6].upper(),sp[7].upper(),sp[8].upper(),sp[9].upper())
	                    a="%3a"
	                    href="%s%s256%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % (sp[0].upper(),a,a,sp[2].upper(),a,sp[3].upper(),a,sp[4].upper(),a,sp[5].upper(),a,sp[6].upper(),a,sp[7].upper(),a,sp[8].upper(),a,sp[9].upper())
	                    teservice=nref+http+href
	                    cprint("PLAYS RADIO REMOTE %s" % teservice)
	                    lastservice = eServiceReference(teservice)    
	        else:
		    cprint(">>> onCreate Radio normal %s" % sref)
        	self.session.nav.playService(lastservice)               
        else:                                                           
                self.session.nav.stopService()                          
        self.info.show()                                               

def TunerError_channelSelected(self): # just return selected service
	cprint(">>>>>>>> channelSelectedRadio")
	ref = self.getCurrentSelection()
	newref=ref
	sref=""
	if ref is not None:
        	sref = ref.toString()
	if self.movemode:
		self.toggleMoveMarked()
	elif (ref.flags & 7) == 7:
		self.enterPath(ref)
	elif self.bouquet_mark_edit != OFF:
		if not (self.bouquet_mark_edit == EDIT_ALTERNATIVES and ref.flags & eServiceReference.isGroup):
			self.doMark()
	elif not (ref.flags & eServiceReference.isMarker): # no marker
		cur_root = self.getRoot()
		if not cur_root or not (cur_root.flags & eServiceReference.isGroup):
			playingref = self.session.nav.getCurrentlyPlayingServiceReference()
			playingsref=""
			if playingref is not None:
				playingsref=playingref.toString()
			cprint("playing %s new ref %s" % (playingsref,sref))
			if playingref is None or playingref != ref:
			        if config.plugins.tunererror.radio.value and sref.find("http") is -1:
				    cprint(">>> playService Radio remote %s" % sref)
			            if not sref.startswith("1:256"): # prevent recursive calls ...
			                if config.plugins.tunererror.server.value=="ip":
			                    host = "%d.%d.%d.%d" % tuple(config.plugins.tunererror.ip.value)
			                else:
			                    host = config.plugins.tunererror.hostname.value
			                password = str(config.plugins.tunererror.password.value)
			                port = "8001"
			                username = "root"
			                if len(password) == 0:
			                    http = "http://%s:%s/" % (host,port)       
			                else:
			                    http = "http://%s:%s@%s:%s/" % (username,password,host,port)       
			                    http=http.replace(":","%3a")
			                sp=[]
			                sp=sref.split(":")
			                # change stream service reference for retry ...
			                if len(sp) > 9:                                                        
			                    # change stream service reference for retry ...
			                    nref="%s:256:%s:%s:%s:%s:%s:%s:%s:%s:" % (sp[0].upper(),sp[2].upper(),sp[3].upper(),sp[4].upper(),sp[5].upper(),sp[6].upper(),sp[7].upper(),sp[8].upper(),sp[9].upper())
			                    a="%3a"
			                    href="%s%s256%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % (sp[0].upper(),a,a,sp[2].upper(),a,sp[3].upper(),a,sp[4].upper(),a,sp[5].upper(),a,sp[6].upper(),a,sp[7].upper(),a,sp[8].upper(),a,sp[9].upper())
			                    teservice=nref+http+href
			                    cprint("PLAYS RADIO REMOTE %s" % teservice)
			                    newref = eServiceReference(teservice)    
				            self.session.nav.playService(newref)
			        else:
				    cprint(">>> playService Radio normal %s" % sref)
				    self.session.nav.playService(ref)
				config.radio.lastservice.value = ref.toString()
				config.radio.lastservice.save()
			self.saveRoot()
# rename on startup
ChannelSelectionRadio.channelSelected=TunerError_channelSelected
ChannelSelectionRadio.onCreate=TunerError_onCreate

def TunerError_playService(self, service):                                         
    if service is None:
        return
    ref = service.toString()
    if config.plugins.tunererror.virtualzap.value and ref.find("http") is -1:
	cprint(">>> playService remote %s" % ref)
        ref = service.toString()
        if not ref.startswith("1:256"): # prevent recursive calls ...
            if config.plugins.tunererror.server.value=="ip":
                host = "%d.%d.%d.%d" % tuple(config.plugins.tunererror.ip.value)
            else:
                host = config.plugins.tunererror.hostname.value
            password = str(config.plugins.tunererror.password.value)
            port = "8001"
            username = "root"
            if len(password) == 0:
                http = "http://%s:%s/" % (host,port)       
            else:
                http = "http://%s:%s@%s:%s/" % (username,password,host,port)       
                http=http.replace(":","%3a")
            sp=[]
            sp=ref.split(":")
            # change stream service reference for retry ...
            if len(sp) > 9:                                                        
                # change stream service reference for retry ...
                nref="%s:256:%s:%s:%s:%s:%s:%s:%s:%s:" % (sp[0].upper(),sp[2].upper(),sp[3].upper(),sp[4].upper(),sp[5].upper(),sp[6].upper(),sp[7].upper(),sp[8].upper(),sp[9].upper())
                a="%3a"
                href="%s%s256%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % (sp[0].upper(),a,a,sp[2].upper(),a,sp[3].upper(),a,sp[4].upper(),a,sp[5].upper(),a,sp[6].upper(),a,sp[7].upper(),a,sp[8].upper(),a,sp[9].upper())
                teservice=nref+http+href
                cprint("PLAYS REMOTE %s" % teservice)
                service = eServiceReference(teservice)    
        else:
	    cprint(">>> playService normal %s" % service.toString())
    Virtual_Zap_playService_ori(self,service)

if os_path.exists("/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap"):
    from Plugins.Extensions.VirtualZap.plugin import VirtualZap
    Virtual_Zap_playService_ori=VirtualZap.playService
    # rename on startup
    VirtualZap.playService=TunerError_playService

def TunerError_streamRemote(self,sref=None):
    if sref is None:
        sref = self.session.nav.getCurrentServiceReference()
    ref = sref.toString()
    cprint("FAILED %s" % ref)
    if not ref.startswith("1:256"): # prevent recursive calls ...
        if config.plugins.tunererror.server.value=="ip":
            host = "%d.%d.%d.%d" % tuple(config.plugins.tunererror.ip.value)
        else:
            host = config.plugins.tunererror.hostname.value
        password = str(config.plugins.tunererror.password.value)
        port = "8001"
        username = "root"
        if len(password) == 0:
            http = "http://%s:%s/" % (host,port)       
        else:
            http = "http://%s:%s@%s:%s/" % (username,password,host,port)       
        http=http.replace(":","%3a")
        sp=[]
        sp=ref.split(":")
        # change stream service reference for retry ...
        if len(sp) > 9:                                                        
            # change stream service reference for retry ...
            nref="%s:256:%s:%s:%s:%s:%s:%s:%s:%s:" % (sp[0].upper(),sp[2].upper(),sp[3].upper(),sp[4].upper(),sp[5].upper(),sp[6].upper(),sp[7].upper(),sp[8].upper(),sp[9].upper())
            a="%3a"
            href="%s%s256%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % (sp[0].upper(),a,a,sp[2].upper(),a,sp[3].upper(),a,sp[4].upper(),a,sp[5].upper(),a,sp[6].upper(),a,sp[7].upper(),a,sp[8].upper(),a,sp[9].upper())
            teservice=nref+http+href
            cprint("PLAYS REMOTE %s" % teservice)
            teref = eServiceReference(teservice)    
            self.session.nav.playService(teref)
            return True
    return False

def TunerError__tuneFailed(self):
    cprint(">>>> __tuneFailed")
    service = self.session.nav.getCurrentService()
    info = service and service.info()
    error = info and info.getInfo(iServiceInformation.sDVBState)
    refreshAdapter = RecordAdapter(self.session)
    
    msg=False
    cprint(">>>> ERROR: %d" % error)
    if error == eDVBServicePMTHandler.eventNoResources:
        if config.plugins.tunererror.eventNoResources.value=="none":
            error=None
        elif config.plugins.tunererror.eventNoResources.value=="message":
            msg=True
        elif config.plugins.tunererror.eventNoResources.value=="remote":
            remote=self.streamRemote()
            if remote:
                error=None
        else: # default handler
            pass

    elif error == eDVBServicePMTHandler.eventTuneFailed:
        if config.plugins.tunererror.eventTuneFailed.value=="none":
            error=None
        elif config.plugins.tunererror.eventTuneFailed.value=="message":
            msg=True
        elif config.plugins.tunererror.eventTuneFailed.value=="zap":
            cprint("handled as ZAP")
            # Play fake service
            sref = self.session.nav.getCurrentServiceReference()
            ref = sref.toString()
            cprint("PLAYS %s" % ref)
            x=ref.split(":")
            fref=sref
            if int(x[0]) == 1:
                fake=x[6]
                faked=fake[:3]+"AAA"
                cprint("FAKING: %s %s" % (fake, faked))
                fake_service=ref.replace(":"+x[6]+":",":"+faked+":")
                cprint("FAKES SERVICE %s" % fake_service)
                fref=eServiceReference(fake_service)   
                #self.session.nav.stopService() # try to disable failed foreground service
                #refreshAdapter.play(fref) # play fake service in background
                #self.session.nav.playService(sref) # try real service again

            error=None
        else: # default handler
            pass
    elif error == eDVBServicePMTHandler.eventNoPAT:
        if config.plugins.tunererror.eventNoPAT.value=="none":
            error=None
        elif config.plugins.tunererror.eventNoPAT.value=="message":
            msg=True
        else: # default handler
            pass
    elif error == eDVBServicePMTHandler.eventNoPATEntry:
        if config.plugins.tunererror.eventNoPATEntry.value=="none":
            error=None
        elif config.plugins.tunererror.eventNoPATEntry.value=="message":
            msg=True
        else: # default handler
            pass
    elif error == eDVBServicePMTHandler.eventNoPMT:
        if config.plugins.tunererror.eventNoPMT.value=="none":
            error=None
        elif config.plugins.tunererror.eventNoPMT.value=="message":
            msg=True
        else: # default handler
            pass
    elif error == eDVBServicePMTHandler.eventNewProgramInfo:
        if config.plugins.tunererror.eventNewProgramInfo.value=="none":
            error=None
        elif config.plugins.tunererror.eventNewProgramInfo.value=="message":
            msg=True
        else: # default handler
            pass
    elif error == eDVBServicePMTHandler.eventTuned:
        if config.plugins.tunererror.eventTuned.value=="none":
            error=None
        elif config.plugins.tunererror.eventTuned.value=="message":
            msg=True
        else: # default handler
            pass
    elif error == eDVBServicePMTHandler.eventSOF:
        if config.plugins.tunererror.eventSOF.value=="none":
            error=None
        elif config.plugins.tunererror.eventSOF.value=="message":
            msg=True
        else: # default handler
            pass
    elif error == eDVBServicePMTHandler.eventEOF:
        if config.plugins.tunererror.eventEOF.value=="none":
            error=None
        elif config.plugins.tunererror.eventEOF.value=="message":
            msg=True
        else: # default handler
            pass
    elif error == eDVBServicePMTHandler.eventMisconfiguration:
        if config.plugins.tunererror.eventMisconfiguration.value=="none":
            error=None
        elif config.plugins.tunererror.eventMisconfiguration.value=="message":
            msg=True
        elif config.plugins.tunererror.eventMisconfiguration.value=="remote":
            remote=self.streamRemote()
            if remote:
                error=None
        else: # default handler
            pass
    else:
        cprint("unknown error %s" % error)
    
    if error == self.last_error:
        cprint("error already reported %s" % error)
        error = None
    else:
        self.last_error = error

    error = {
        eDVBServicePMTHandler.eventNoResources: _("No free tuner!"),
        eDVBServicePMTHandler.eventTuneFailed: _("Tune failed!"),
        eDVBServicePMTHandler.eventNoPAT: _("No data on transponder!\n(Timeout reading PAT)"),
        eDVBServicePMTHandler.eventNoPATEntry: _("Service not found!\n(SID not found in PAT)"),
        eDVBServicePMTHandler.eventNoPMT: _("Service invalid!\n(Timeout reading PMT)"),
        eDVBServicePMTHandler.eventNewProgramInfo: _("new Program Info!"),
        eDVBServicePMTHandler.eventTuned: _("Tuner status"),
        eDVBServicePMTHandler.eventSOF: _("Start of File!\n(SOF)"),
        eDVBServicePMTHandler.eventEOF: _("End of File!\n(EOF)"),
        eDVBServicePMTHandler.eventMisconfiguration: _("Service unavailable!\nCheck tuner configuration!"),
    }.get(error) #this returns None when the key not exist in the dict

    if msg and error is not None:
        tunererror_timeout=int(config.plugins.tunererror.timeout.value)
        message=error 
        try:
            self.session.open(MessageBox, message, MessageBox.TYPE_ERROR,timeout=tunererror_timeout)
        except:
            cprint("ERROR: %s" % message)
        # surpress standard error handling ...
        error=False
    
    if error:
        self.setPlaybackState(self.STATE_TUNING, error)
    else:
        self.setPlaybackState()

# rename on startup
from Screens.InfoBarGenerics import InfoBarServiceErrorPopupSupport
InfoBarServiceErrorPopupSupport._InfoBarServiceErrorPopupSupport__tuneFailed=TunerError__tuneFailed
from Screens.InfoBar import InfoBar
InfoBar.streamRemote=TunerError_streamRemote

def TunerError_buildOptionEntry(self, service, **args):
    cprint(">>>> ServiceList.buildOptionEntry")
    width = self.l.getItemSize().width()
    width -= self._componentSizes.get(self.KEY_END_MARGIN, 5)
    height = self.l.getItemSize().height()
    selected = args["selected"]
    res = [ None ]
    showListNumbers = config.usage.configselection_showlistnumbers.value
    showPicons = self.mode == self.MODE_FAVOURITES and config.usage.configselection_showpicons.value
    showServiceName = self.mode == self.MODE_NORMAL or (self.mode == self.MODE_FAVOURITES and config.usage.configselection_showservicename.value)
    showProgressbar = config.usage.show_event_progress_in_servicelist.value
    progressbarPosition = config.usage.configselection_progressbarposition.value
    try:
        servicenameWidth = config.usage.configselection_servicenamecolwidth.value
    except:
        servicenameWidth = 0
    columnStyle = config.usage.configselection_columnstyle.value
    additionalposition = config.usage.configselection_additionaltimedisplayposition.value
    bigPicons = self.mode == self.MODE_FAVOURITES and config.usage.configselection_bigpicons.value
    secondlineinfo = config.usage.configselection_secondlineinfo.value
    # get service information
    service_info = self.service_center.info(service)
    isMarker = service.flags & eServiceReference.isMarker
    isPlayable = not(service.flags & eServiceReference.isDirectory or isMarker)
    recording = self._checkHasRecording(service, isPlayable)
    
    marked = 0
    if self.l.isCurrentMarked() and selected:
        marked = 2
    elif self.l.isMarked(service):
        if selected:
            marked = 2
        else:
            marked = 1
    if marked == 1: #  marked
        additionalInfoColor = serviceDescriptionColor = forgroundColor = self.markedForeground
        backgroundColor = self.markedBackground
        forgroundColorSel = backgroundColorSel = additionalInfoColorSelected = serviceDescriptionColorSelected = None
    elif marked == 2: # marked and selected
        additionalInfoColorSelected = serviceDescriptionColorSelected = forgroundColorSel = self.markedForegroundSelected
        backgroundColorSel = self.markedBackgroundSelected
        forgroundColor = additionalInfoColor = serviceDescriptionColor = backgroundColor = None
    else:
        if recording:
            forgroundColor = additionalInfoColor = serviceDescriptionColor = self.recordingColor
            forgroundColorSel = additionalInfoColorSelected = serviceDescriptionColorSelected = self.recordingColorSelected
            backgroundColor = backgroundColorSel = None
        else:
            forgroundColor = forgroundColorSel = backgroundColor = backgroundColorSel = None
            serviceDescriptionColor = self.serviceDescriptionColor
            serviceDescriptionColorSelected = self.serviceDescriptionColorSelected
            additionalInfoColor = self.additionalInfoColor
            additionalInfoColorSelected = self.additionalInfoColorSelected
    
    if (marked == 0 and isPlayable and service_info and not service_info.isPlayable(service, self.is_playable_ignore)):
        #
        # keep greyed channel list if not disabled via setting
        #
        if not config.plugins.tunererror.complete.value:
            forgroundColor = forgroundColorSel = additionalInfoColor = additionalInfoColorSelected = serviceDescriptionColor = serviceDescriptionColorSelected = self.serviceNotAvail
        else:
            cprint("channel NOT greyed out")
    
    # set windowstyle
    if marked > 0:
        res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0, width , height, 1, RT_HALIGN_RIGHT, "", forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel))

    info = self.service_center.info(service)
    serviceName = info and info.getName(service) or "<n/a>"
    event = info and info.getEvent(service)
    index = self.getCurrentIndex()
    xoffset = self._componentSizes.get(self.KEY_BEGIN_MARGIN, 5)
    pixmap = self._buildOptionEntryServicePixmap(service)
    drawProgressbar = isPlayable and showProgressbar
    progressBarWidth = self._progressBarWidth(withOffset=True)
    textOffset = self._componentSizes.get(self.KEY_TEXT_OFFSET, 10)
    
    if pixmap is not None:
        pixmap_size = self.picMarker.size()
        pix_width = pixmap_size.width()
        pix_height = pixmap_size.height()
        ypos = (height - pix_height) / 2
        res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, xoffset, ypos, pix_width, pix_height, pixmap))
        xoffset += pix_width + self._componentSizes.get(self.KEY_PICON_OFFSET, 8)
    
    if self.mode != self.MODE_NORMAL:
        # servicenumber
        if not (service.flags & eServiceReference.isMarker) and showListNumbers:
            markers_before = self.l.getNumMarkersBeforeCurrent()
            text = "%d" % (self.numberoffset + index + 1 - markers_before)
            nameWidth = self._componentSizes.get(self.KEY_SERVICE_NUMBER_WIDTH, 50)
            res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, nameWidth , height, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, text, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel))
            xoffset += nameWidth + textOffset
    
    # picons
    if isPlayable and showPicons:
        picon = self._buildOptionEntryServicePicon(service)
        if bigPicons:
            pix_width = self._componentSizes.get(self.KEY_PICON_WIDTH_BIG, 108)
        else:
            pix_width = self._componentSizes.get(self.KEY_PICON_WIDTH, 58)
        if picon:
            res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, xoffset, 0, pix_width, height, picon))
        xoffset += pix_width
        xoffset += self._componentSizes.get(self.KEY_PICON_OFFSET, 8)

    # progressbar between servicenumber and servicename
    if drawProgressbar and progressbarPosition == "0":
        res.append(self._buildOptionEntryProgressBar(event, xoffset, width, height))
        xoffset += progressBarWidth
    addtimedisplay, addtimedisplayWidth = self._buildOptionEntryAddTimeDisplay(event, isPlayable, columnStyle)
    
    if columnStyle:
        rwidth = 0
        # servicename
        if (isPlayable and showServiceName) or not isPlayable:
            if isPlayable:
                rwidth = servicenameWidth # space for servicename
            else:
                rwidth = width - xoffset # space for servicename
            res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel))
            xoffset += rwidth + textOffset
            # progressbar between servicename and service description
            if drawProgressbar and progressbarPosition == "1":
                res.append(self._buildOptionEntryProgressBar(event, xoffset, width, height))
                xoffset += progressBarWidth
        if event and isPlayable:
            rwidth = width - xoffset
            if drawProgressbar and progressbarPosition == "2":
                rwidth -= self._progressBarWidth(withOffset=True, withProgressBarSize=False)
                rwidth -= self._progressBarWidth(withOffset=True, withProgressBarSize=True)
            if addtimedisplay != "" :
                if additionalposition == "0":
                    # add time text before service description
                    res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, addtimedisplayWidth, height, 0, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, addtimedisplay, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel))
                    addoffset = addtimedisplayWidth + textOffset
                    xoffset += addoffset
                    rwidth -= addoffset
                elif additionalposition == "1":
                    rwidth -= addtimedisplayWidth + textOffset
            # service description
            if secondlineinfo != "0" and self.mode == self.MODE_FAVOURITES:
                res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth, self.serviceInfoHeight, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, event.getEventName(), serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel))
                if secondlineinfo == "1": # shortdescription
                    text = event.getShortDescription()
                else:
                    event_next = eEPGCache.getInstance().lookupEventTime(service, -1, 1)
                    if event_next:
                        beginTime = localtime(event_next.getBeginTime())
                        endTime = localtime(event_next.getBeginTime()+event_next.getDuration())
                        text = "%02d:%02d - %02d:%02d %s" % (beginTime[3],beginTime[4],endTime[3],endTime[4], event_next.getEventName())
                    else:
                        text = "%s: n/a" % _("upcoming event")
                res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, self.serviceInfoHeight, rwidth, height - self.serviceInfoHeight, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, text, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel))
            else:
                res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth, height, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, event.getEventName(), serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel))
            # progressbar after service description
            xoffset += rwidth
            if drawProgressbar and progressbarPosition == "2":
                xoffset += self._progressBarWidth(withOffset=True, withProgressBarSize=False)
                res.append(self._buildOptionEntryProgressBar(event, xoffset, width, height))
                xoffset += progressBarWidth
            # add time text at last position
            if addtimedisplay != "" and additionalposition == "1":
                xoffset += textOffset
                res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, addtimedisplayWidth , height, 0, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, addtimedisplay, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel))
    else:
        if event and isPlayable:
            maxLength = width - xoffset
            if drawProgressbar and progressbarPosition == "2":
                # progressbar after service description
                maxLength -= progressBarWidth
            length = self._calcTextWidth(serviceName, font=self.serviceNameFont, size=eSize(maxLength,0)) + textOffset
            res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, length , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel))
            xoffset += length
            if addtimedisplay != "":
                if additionalposition == "1":
                    # add time text after service description
                    text = "(%s %s)" % (event.getEventName(), addtimedisplay)
                else:
                    # add time text before service description
                    text = "(%s %s)" % (addtimedisplay, event.getEventName())
            else:
                text = "(%s)" % (event.getEventName())
            length = width - xoffset
            if drawProgressbar and progressbarPosition == "2":
                # progressbar after service description
                length -= progressBarWidth
            # service description
            res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, length , height, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, text, serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel))
            if drawProgressbar and progressbarPosition == "2":
                xoffset += length + textOffset / 2
                res.append(self._buildOptionEntryProgressBar(event, xoffset, width, height))
        else:
            res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, width - xoffset , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel))
    return res

# rename on startup
if config.plugins.tunererror.complete.value:
    from Components.ServiceList import ServiceList
    ServiceList.buildOptionEntry=TunerError_buildOptionEntry

class TunerError(Screen, ConfigListScreen):
    if sz_w == 2560:
        skin = """
        <screen name="TunerError" position="center,240" size="1840,920" title="Tuner Error" >
        <widget name="logo" position="20,10" size="200,80" />
        <widget backgroundColor="#9f1313" font="Regular;32" halign="center" name="buttonred" position="240,10" foregroundColor="white" shadowColor="black" shadowOffset="-4,-4" size="380,80" valign="center" />
        <widget backgroundColor="#1f771f" font="Regular;32" halign="center" name="buttongreen" position="640,10" foregroundColor="white" shadowColor="black" shadowOffset="-4,-4" size="380,80" valign="center" />
        <widget backgroundColor="#a08500" font="Regular;32" halign="center" name="buttonyellow" position="1040,10" foregroundColor="white" shadowColor="black" shadowOffset="-4,-4" size="380,80" valign="center" />
        <widget backgroundColor="#18188b" font="Regular;32" halign="center" name="buttonblue" position="1440,10" foregroundColor="white" shadowColor="black" shadowOffset="-4,-4" size="380,80" valign="center" />
        <eLabel backgroundColor="grey" position="20,100" size="1800,2" />
        <widget name="config" position="20,120" size="1800,780" enableWrapAround="1" scrollbarMode="showOnDemand" />
        </screen>"""
    elif sz_w == 1920:
        skin = """
        <screen name="TunerError" position="center,170" size="1200,720" title="Tuner Error" >
        <widget name="logo" position="20,10" size="150,60" />
        <widget backgroundColor="#9f1313" font="Regular;24" halign="center" name="buttonred" position="190,10" foregroundColor="white" shadowColor="black" shadowOffset="-2,-2" size="240,60" valign="center" />
        <widget backgroundColor="#1f771f" font="Regular;24" halign="center" name="buttongreen" position="440,10" foregroundColor="white" shadowColor="black" shadowOffset="-2,-2" size="240,60" valign="center" />
        <widget backgroundColor="#a08500" font="Regular;24" halign="center" name="buttonyellow" position="690,10" foregroundColor="white" shadowColor="black" shadowOffset="-2,-2" size="240,60" valign="center" />
        <widget backgroundColor="#18188b" font="Regular;24" halign="center" name="buttonblue" position="940,10" foregroundColor="white" shadowColor="black" shadowOffset="-2,-2" size="240,60" valign="center" />
        <eLabel backgroundColor="grey" position="20,80" size="1160,1" />
        <widget enableWrapAround="1" name="config" position="20,90" scrollbarMode="showOnDemand" size="1160,600" />
        </screen>"""
    else:
        skin = """
        <screen name="TunerError" position="center,120" size="920,460" title="Tuner Error" >
        <widget name="logo" position="10,5" size="100,40" />
        <widget backgroundColor="#9f1313" font="Regular;16" halign="center" name="buttonred" position="120,5" foregroundColor="white" shadowColor="black" shadowOffset="-2,-2" size="190,40" valign="center" />
        <widget backgroundColor="#1f771f" font="Regular;16" halign="center" name="buttongreen" position="320,5" foregroundColor="white" shadowColor="black" shadowOffset="-2,-2" size="190,40" valign="center" />
        <widget backgroundColor="#a08500" font="Regular;16" halign="center" name="buttonyellow" position="520,5" foregroundColor="white" shadowColor="black" shadowOffset="-2,-2" size="190,40" valign="center" />
        <widget backgroundColor="#18188b" font="Regular;16" halign="center" name="buttonblue" position="720,5" foregroundColor="white" shadowColor="black" shadowOffset="-2,-2" size="190,40" valign="center" />
        <eLabel backgroundColor="grey" position="10,50" size="900,1" />
        <widget name="config" position="10,60" size="900,390" enableWrapAround="1" scrollbarMode="showOnDemand" />
        </screen>"""

    def __init__(self, session, args = 0):
        Screen.__init__(self, session)

        self.onShown.append(self.setWindowTitle)

        self.onChangedEntry = []  
        self.list = []
       	ConfigListScreen.__init__(self, self.list, session = self.session, on_change = self.changedEntry)
       	self.createSetup()

        self["logo"] = Pixmap()
        self["buttonred"] = Label(_("Exit"))
        self["buttongreen"] = Label(_("Save"))
        self["buttonyellow"] = Label(_("Default"))
        self["buttonblue"] = Label(_("About"))

        self["setupActions"] = ActionMap(["SetupActions", "ColorActions", "ChannelSelectEPGActions"],
            {
               "green": self.save,
                "red": self.cancel,
                "yellow": self.reset,
                "blue": self.about,
                "save": self.save,
                "cancel": self.cancel,
                "ok": self.save,
                "showEPGList": self.about,
            })

    def createSetup(self):
        self.list = []
        self.list.append(getConfigListEntry(_("Infobar timeout").replace("Infobar",_("Tuner status"))+" "+_("Message"), config.plugins.tunererror.timeout))
        self.list.append(getConfigListEntry(_("No free tuner!").replace("!","")+" (+"+_("Streaming")+" "+_("Setup")+")", config.plugins.tunererror.eventNoResources))
        self.list.append(getConfigListEntry(_("Tune failed!").replace("!",""), config.plugins.tunererror.eventTuneFailed))
        error=_("No data on transponder!\n(Timeout reading PAT)").split("!\n")
        self.list.append(getConfigListEntry(error[0], config.plugins.tunererror.eventNoPAT))
        error=_("Service not found!\n(SID not found in PAT)").split("!\n")
        self.list.append(getConfigListEntry(error[0], config.plugins.tunererror.eventNoPATEntry))
        error=_("Service invalid!\n(Timeout reading PMT)").split("!\n")
        self.list.append(getConfigListEntry(error[0], config.plugins.tunererror.eventNoPMT))
        self.list.append(getConfigListEntry(_("new Program Info!").replace("!",""),config.plugins.tunererror.eventNewProgramInfo)) 
        self.list.append(getConfigListEntry(_("Tuner status"), config.plugins.tunererror.eventTuned))
        self.list.append(getConfigListEntry(_("Start of File!\n(SOF)").replace("!\n"," "), config.plugins.tunererror.eventSOF))
        self.list.append(getConfigListEntry(_("End of File!\n(EOF)").replace("!\n"," "), config.plugins.tunererror.eventEOF))
        error=_("Service unavailable!\nCheck tuner configuration!").split("!\n")
        self.list.append(getConfigListEntry(error[0]+" (+"+_("Streaming")+" "+_("Setup")+")", config.plugins.tunererror.eventMisconfiguration))
        if config.plugins.tunererror.eventNoResources.value=="remote" or config.plugins.tunererror.eventMisconfiguration.value=="remote":
            self.list.append(getConfigListEntry(_("Streaming")+" "+_("Server IP").replace("IP",""), config.plugins.tunererror.server))
            if config.plugins.tunererror.server.value=="ip":
                self.list.append(getConfigListEntry(_("IP Address"), config.plugins.tunererror.ip))
            else:
                self.list.append(getConfigListEntry(_("Server IP").replace("IP",_("Name")), config.plugins.tunererror.hostname))
            self.list.append(getConfigListEntry(_("Password"), config.plugins.tunererror.password))
            self.list.append(getConfigListEntry(_("Complete")+" "+_("Channel Selection"), config.plugins.tunererror.complete))
            self.list.append(getConfigListEntry(_("Streaming")+" "+_("Radio"), config.plugins.tunererror.radio))
	    if os_path.exists("/usr/lib/enigma2/python/Plugins/Extensions/VirtualZap"):
        	self.list.append(getConfigListEntry(_("Streaming")+" "+_("Virtual Zap"), config.plugins.tunererror.virtualzap))
        self["config"].list = self.list
        self["config"].l.setList(self.list)

    def setWindowTitle(self):
        if os_path.exists("%s/tunererror.svg" % tunererror_plugindir):
            self["logo"].instance.setPixmapFromFile("%s/tunererror.svg" % tunererror_plugindir)
        self.setTitle(tunererror_str+" V%s " % tunererror_version)

    def changedEntry(self):         
        choice = self["config"].getCurrent()
        current=choice[1]
        password=config.plugins.tunererror.password
        hostname=config.plugins.tunererror.hostname
        if choice != None:
            if current != password and current != hostname:
                self.createSetup()

    def save(self):
        if config.plugins.tunererror.eventNoResources.value != "remote" and config.plugins.tunererror.eventMisconfiguration.value != "remote":
            #no server check if no remote-option is enabled
            self.save_afterCkeck()
            return
        
        if config.plugins.tunererror.server.value=="ip":
            #check network with IP
            ip = "%d.%d.%d.%d" % tuple(config.plugins.tunererror.ip.value)
	    cprint(ip)
	    if len(ip) == 0:
                self.session.open(MessageBox,"Please enter a streaming server IP!", MessageBox.TYPE_ERROR)
                return
	    else:
		fullname=ip
        else:
            #check network with servername
            hostname = config.plugins.tunererror.hostname.value.lstrip().rstrip().replace(" ","")
            if len(hostname) == 0:
                self.session.open(MessageBox,"Please enter a streaming server hostname!", MessageBox.TYPE_ERROR)
                return
            else:
                fullname = hostname

        connected_message = _("Active")
	save_text=_("Save")
        if not ping_doOne(fullname,1):
        	connected_message = _("Inactive")
        self.session.open(MessageBox,"%s %s Streaming Server '%s'!" % (save_text,connected_message,fullname), MessageBox.TYPE_INFO)
        config.plugins.tunererror.hostname.value=fullname
        print("last fullname before save", fullname)
        self.save_afterCkeck()
    
    def saveCallback(self, retVal):
        if retVal:
            self.save_afterCkeck()
    
    def save_afterCkeck(self):
        # keep greyed channel list if not remote streaming is enabled
        if config.plugins.tunererror.eventNoResources.value != "remote":
            config.plugins.tunererror.complete.value = False
        
        for x in self["config"].list:
            x[1].save()
        self.close(True)

    def cancel(self):
        for x in self["config"].list:
           x[1].cancel()
        self.close(False)

    def reset(self):
        for x in self["config"].list:
            if len(x) > 1:
              x[1].value=x[1].default
        self.createSetup()

    def about(self):
        gpipText=""
        if gPiPinstalled:
            gpipText="("+_("Include")+" gPIP) "
        message=tunererror_str+" "+gpipText+_("Plugin")+(" V%s " % tunererror_version) + " (c) gutemine" 
        self.session.open(MessageBox, message, MessageBox.TYPE_INFO)

def Plugins(**kwargs):
    return [PluginDescriptor(name=tunererror_str, description=tunererror_description_str, where = PluginDescriptor.WHERE_PLUGINMENU, icon="tunererror.svg", fnc=main), PluginDescriptor(name=tunererror_str, description=tunererror_description_str, where = PluginDescriptor.WHERE_MENU, fnc=mainconf)]

def main(session,**kwargs):
     session.open(TunerError)  

def mainconf(menuid):
    if menuid == "services_recordings":
        return [(tunererror_str, main, "tunererror", None)]
    else:
        return [ ]

#
# borrowed from EPGRefresh ...
#
class RecordAdapter:
    backgroundCapable = True
    def __init__(self, session):
        self.backgroundRefreshAvailable = True
        self.__service = None
        self.navcore = session.nav
    
    def prepare(self):
        if not self.backgroundRefreshAvailable:
            return False
        return True
    
    def play(self, service):
        cprint(">>>> RecordAdapter.play]")
        if not self.backgroundRefreshAvailable: return False
        self.stopStreaming()
        self.__service = self.navcore.recordService(service)
        if self.__service is not None:
            self.__service.prepareStreaming()
            self.__service.start()
            return True
        return False
    
    def stopStreaming(self):
        if self.__service is not None:
            self.navcore.stopRecordService(self.__service)
            self.__service = None
    
    def stop(self):
        cprint(">>>> RecordAdapter.stop")
        self.stopStreaming()