replaced xml.dom.minidom with xml.etree.cElementTree --> way faster and better perfor...
[enigma2-plugins.git] / partnerbox / src / plugin.py
1 #
2 #  Partnerbox E2
3 #
4 #  $Id$
5 #
6 #  Coded by Dr.Best (c) 2009
7 #  Support: www.dreambox-tools.info
8 #
9 #  This program is free software; you can redistribute it and/or
10 #  modify it under the terms of the GNU General Public License
11 #  as published by the Free Software Foundation; either version 2
12 #  of the License, or (at your option) any later version.
13 #
14 #  This program is distributed in the hope that it will be useful,
15 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 #  GNU General Public License for more details.
18 #
19
20 from Plugins.Plugin import PluginDescriptor
21 from Screens.Screen import Screen
22 from Screens.MessageBox import MessageBox
23 from Screens.ChoiceBox import ChoiceBox
24 from Components.config import config
25 from Components.ScrollLabel import ScrollLabel
26 from Components.ActionMap import ActionMap, NumberActionMap
27 from Components.MenuList import MenuList
28 from Components.Label import Label
29 from Components.Button import Button
30 from Components.EpgList import Rect
31 from Components.MultiContent import MultiContentEntryText
32 from enigma import eServiceReference
33 from enigma import eListboxPythonMultiContent, eListbox, gFont, \
34         RT_HALIGN_LEFT, RT_HALIGN_RIGHT, RT_VALIGN_CENTER
35 from Tools.LoadPixmap import LoadPixmap
36 from Tools.Directories import resolveFilename, SCOPE_SKIN_IMAGE
37 from Tools.FuzzyDate import FuzzyTime
38 from timer import TimerEntry
39 from enigma import eTimer
40 from time import localtime
41 import time
42 import xml.etree.cElementTree
43 import urllib
44 import SocketServer
45 import servicewebts
46 ENIGMA_WEBSERVICE_ID = 0x1012
47 from Screens.InfoBarGenerics import InfoBarAudioSelection
48 from RemoteTimerEntry import RemoteTimerEntry, RemoteTimerInit
49 from PartnerboxEPGSelection import Partnerbox_EPGSelectionInit
50
51 from PartnerboxFunctions import PlaylistEntry, FillE1TimerList, E2Timer, FillE2TimerList, SetPartnerboxTimerlist, sendPartnerBoxWebCommand, isInTimerList
52
53 from PartnerboxEPGList import Partnerbox_EPGListInit
54 from PartnerboxSetup import PartnerboxSetup, PartnerboxEntriesListConfigScreen, PartnerboxEntryList, PartnerboxEntryConfigScreen, initPartnerboxEntryConfig, initConfig
55 import time
56
57 from Services import Services, E2EPGListAllData, E2ServiceList
58 from Screens.ChannelSelection import service_types_tv
59
60 from Components.ConfigList import ConfigList, ConfigListScreen
61 from Components.config import ConfigSubsection, ConfigSubList, ConfigIP, ConfigInteger, ConfigSelection, ConfigText, ConfigYesNo, getConfigListEntry, configfile
62
63
64 config.plugins.Partnerbox = ConfigSubsection()
65 config.plugins.Partnerbox.showremotetvinextensionsmenu= ConfigYesNo(default = True)
66 config.plugins.Partnerbox.showcurrentstreaminextensionsmenu= ConfigYesNo(default = True)
67 config.plugins.Partnerbox.showremotetimerinextensionsmenu= ConfigYesNo(default = True)
68 config.plugins.Partnerbox.enablepartnerboxintimerevent = ConfigYesNo(default = False)
69 config.plugins.Partnerbox.enablepartnerboxepglist = ConfigYesNo(default = False)
70 config.plugins.Partnerbox.entriescount =  ConfigInteger(0)
71 config.plugins.Partnerbox.Entries = ConfigSubList()
72 initConfig()
73
74
75 def partnerboxpluginStart(session, what):
76         count = config.plugins.Partnerbox.entriescount.value
77         if count == 1:
78                 partnerboxplugin(session, what, config.plugins.Partnerbox.Entries[0])
79         else:
80                 session.openWithCallback(partnerboxplugin, PartnerboxEntriesListConfigScreen, what)
81
82 def partnerboxplugin(session, what, partnerboxentry = None):
83         if partnerboxentry is None:
84                 return
85         if what == 0: # Current RemoteTV
86                 session.open(CurrentRemoteTV, partnerboxentry)
87         elif what == 1: # RemoteTV
88                 session.open(RemoteTimerBouquetList, [], partnerboxentry, 1)
89         elif what == 2: # RemoteTimer
90                 session.open(RemoteTimer, partnerboxentry)
91
92 def autostart_RemoteTimerInit(reason, **kwargs):
93         if "session" in kwargs:
94                 session = kwargs["session"]
95                 try: RemoteTimerInit()
96                 except: pass
97
98 def autostart_Partnerbox_EPGList(reason, **kwargs):
99         if "session" in kwargs:
100                 session = kwargs["session"]
101                 try: 
102                         Partnerbox_EPGListInit()
103                         Partnerbox_EPGSelectionInit()
104                 except: pass
105
106 def PartnerboxSetupFinished(session, result):
107         if result:
108                 session.open(MessageBox,_("You have to restart Enigma2 to activate your new preferences!"), MessageBox.TYPE_INFO)
109
110 def setup(session,**kwargs):
111         session.openWithCallback(PartnerboxSetupFinished, PartnerboxSetup)
112
113
114 def currentremotetv(session,**kwargs):
115         partnerboxpluginStart(session, 0)
116
117 def remotetvplayer(session,**kwargs):
118         partnerboxpluginStart(session, 1)
119
120 def main(session,**kwargs):
121         partnerboxpluginStart(session, 2)
122
123 def Plugins(**kwargs):
124         list = [PluginDescriptor(name="Partnerbox: RemoteTimer", description=_("Manage timer for other dreamboxes in network"), 
125                 where = [PluginDescriptor.WHERE_EVENTINFO ], fnc=main)]
126         if config.plugins.Partnerbox.enablepartnerboxintimerevent.value:
127                 list.append(PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, fnc = autostart_RemoteTimerInit))
128         if config.plugins.Partnerbox.enablepartnerboxepglist.value:
129                 list.append(PluginDescriptor(where = PluginDescriptor.WHERE_SESSIONSTART, fnc = autostart_Partnerbox_EPGList))
130         list.append(PluginDescriptor(name="Setup Partnerbox", description=_("setup for partnerbox"), where = [PluginDescriptor.WHERE_PLUGINMENU], fnc=setup))
131         if config.plugins.Partnerbox.showremotetimerinextensionsmenu.value:
132                 list.append(PluginDescriptor(name="Partnerbox: RemoteTimer", description=_("Manage timer for other dreamboxes in network"), 
133                 where = [PluginDescriptor.WHERE_EXTENSIONSMENU], fnc=main))
134         if config.plugins.Partnerbox.showremotetvinextensionsmenu.value:
135                 list.append(PluginDescriptor(name="Partnerbox: RemoteTV Player", description=_("Stream TV from your Partnerbox"), where = [PluginDescriptor.WHERE_EXTENSIONSMENU], fnc=remotetvplayer))
136         if config.plugins.Partnerbox.showcurrentstreaminextensionsmenu.value:
137                 list.append(PluginDescriptor(name="Stream current Service from Partnerbox", description=_("Stream current service from partnerbox"), where = [PluginDescriptor.WHERE_EXTENSIONSMENU], fnc=currentremotetv))
138         
139         return list
140                         
141 def FillLocationList(xmlstring):
142         Locations = []
143         try: root = xml.etree.cElementTree.fromstring(xmlstring)
144         except: Locations 
145         for location in root.findall("e2location"):
146                 Locations.append(location.text.encode("utf-8", 'ignore'))
147         for location in root.findall("e2simplexmlitem"):  # vorerst Kompatibilitaet zum alten Webinterface-Api aufrecht erhalten (e2simplexmlitem)
148                 Locations.append(location.text.encode("utf-8", 'ignore'))
149         return Locations
150                 
151         
152 class CurrentRemoteTV(Screen):
153         skin = """
154                 <screen name="CurrentRemoteTV" position="210,160" size="300,240" title="Remote Player">
155                 <widget name="text" position="10,10" zPosition="1" size="290,225" font="Regular;20" halign="center" valign="center" />
156         </screen>"""
157         def __init__(self, session, partnerboxentry):
158                 self.session = session
159                 Screen.__init__(self, session)
160                 self.CurrentService = self.session.nav.getCurrentlyPlayingServiceReference()
161                 self.PartnerboxEntry = partnerboxentry
162                 self.password = partnerboxentry.password.value
163                 self.username = "root"
164                 self.ip = "%d.%d.%d.%d" % tuple(partnerboxentry.ip.value)
165                 port = partnerboxentry.port.value
166                 self.http = "http://%s:%d" % (self.ip,port)
167                 self.enigma_type = int(partnerboxentry.enigma.value)
168                 self.useinternal = int(partnerboxentry.useinternal.value)
169                 if self.enigma_type == 1:
170                         self.url = self.http + "/video.m3u"
171                 else:
172                         self.url = self.http + "/web/getcurrent"
173                         
174                 tt = "Starting Remote Player (IP = %s)" % (self.ip)
175                 self["text"] = Label(tt)
176                 self.onLayoutFinish.append(self.startRun)
177         
178         def startRun(self):
179                 sendPartnerBoxWebCommand(self.url, None,10, self.username, self.password).addCallback(self.Callback).addErrback(self.Error)
180
181         def Callback(self, xmlstring):
182                 url = ""
183                 servicereference = ""
184                 if self.enigma_type == 0:
185                         root = xml.etree.cElementTree.fromstring(xmlstring)
186                         for service in root.findall("e2service"):
187                                 servicereference = str(service.findtext("e2servicereference", '').encode("utf-8", 'ignore'))
188                         if len(servicereference) > 0:
189                                 url = "http://" + self.ip + ":8001/" + servicereference
190                         else:
191                                 self.close()
192                 else:
193                         url = xmlstring
194                 if len(url) > 0:
195                         self.session.nav.stopService()
196                         sref = eServiceReference(ENIGMA_WEBSERVICE_ID, 0, url)
197                         self.session.nav.playService(sref)
198                         self.session.openWithCallback(self.RemotePlayerFinished, RemotePlayer,"" ,"", 0, 0, self.PartnerboxEntry, servicereference)
199                 else:
200                         self.close()
201                 
202         def RemotePlayerFinished(self):
203                 self.session.nav.playService(self.CurrentService)
204                 self.close()
205                 
206         def Error(self, error = None):
207                 self.close()
208
209 class RemoteTimer(Screen):
210         global CurrentParnerBoxName
211         skin = """
212                 <screen name="RemoteTimer" position="90,95" size="560,430" title="RemoteTimer Timerlist">
213                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on"/>
214                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on"/>
215                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on"/>
216                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on"/>
217                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1"/>
218                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1"/>
219                         <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1"/>
220                         <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1"/>
221                         <widget name="text" position="0,60" zPosition="1" size="560,350" font="Regular;20" halign="center" valign="center" />
222                         <widget name="timerlist" position="0,60" zPosition="2" size="560,350" scrollbarMode="showOnDemand"/>
223                 </screen>"""
224         
225         timerlist = []
226         def __init__(self, session, partnerboxentry):
227                 self.session = session
228                 Screen.__init__(self, session)
229                 self["timerlist"] = E2TimerMenu([])
230                 self["key_red"] = Label(_("Delete"))
231                 self["key_green"] = Label() # Dummy, kommt eventuell noch was
232                 self["key_yellow"] = Label(_("EPG Selection")) 
233                 self["key_blue"] = Label(_("Clean up"))
234                 self["text"] = Label(_("Getting Partnerbox Information..."))
235                 self.onLayoutFinish.append(self.startRun)
236                 self.E2TimerList = []
237                 self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EPGSelectActions"],
238                 {
239                         "ok": self.getLocations,
240                         "back": self.close,
241                         "yellow": self.EPGList,
242                         "blue": self.cleanupTimer,
243                         "red": self.deleteTimer,
244                 }, -1)
245
246                 self.PartnerboxEntry = partnerboxentry
247                 self.password = partnerboxentry.password.value
248                 self.username = "root"
249                 self.ip = "%d.%d.%d.%d" % tuple(partnerboxentry.ip.value)
250                 self.port = partnerboxentry.port.value
251                 self.http = "http://%s:%d" % (self.ip,self.port)
252                 self.enigma_type = int(partnerboxentry.enigma.value)
253                 self.useinternal = int(partnerboxentry.useinternal.value)
254                 self.oldstart = 0
255                 self.oldend = 0
256                 self.oldtype = 0
257                 self.Locations = []
258                 
259         def getLocations(self):
260                 if self.enigma_type == 0:
261                         sCommand = self.http + "/web/getlocations"
262                         sendPartnerBoxWebCommand(sCommand, None,3, self.username, self.password).addCallback(self.getLocationsCallback).addErrback(self.deleteTimerError)
263                 else:
264                         self.addTimer()
265         
266         def getLocationsCallback(self, xmlstring):
267                 self.Locations = []
268                 self.Locations = FillLocationList(xmlstring)
269                 self.addTimer()
270
271         def addTimer(self):
272                 cur = self["timerlist"].getCurrent()
273                 if cur is None:
274                                 return
275                 if cur[0].repeated == 0:
276                         self.oldstart = cur[0].timebegin
277                         self.oldend = cur[0].timeend
278                         self.oldtype = cur[0].type
279                         self.session.openWithCallback(self.RemoteTimerEntryFinished, RemoteTimerEntry,cur[0], self.Locations)
280                 else:
281                         text = "Repeated Timer are not supported!"
282                         self.session.open(MessageBox,text,  MessageBox.TYPE_INFO)
283         
284         def RemoteTimerEntryFinished(self, answer):
285                 if answer[0]:
286                         entry = answer[1]
287                         self["timerlist"].instance.hide()
288                         if self.enigma_type == 0:
289                                 ref_old = "&channelOld=" + urllib.quote(entry.servicereference.decode('utf8').encode('latin-1','ignore')) + "&beginOld=" + ("%s"%(self.oldstart)) + "&endOld=" + ("%s"%(self.oldend))  + "&deleteOldOnSave=1"
290                                 ref = urllib.quote(entry.servicereference.decode('utf8').encode('latin-1','ignore')) + "&begin=" + ("%s"%(entry.timebegin)) + "&end=" + ("%s"%(entry.timeend))  + "&name=" + urllib.quote(entry.name) + "&description=" + urllib.quote(entry.description) + "&dirname=" + urllib.quote(entry.dirname) + "&eit=0&justplay=" + ("%s"%(entry.justplay)) + "&afterevent=" + ("%s"%(entry.afterevent))
291                                 sCommand = self.http + "/web/timerchange?sRef=" + ref + ref_old
292                                 sendPartnerBoxWebCommand(sCommand, None,10, self.username, self.password).addCallback(self.deleteTimerCallback).addErrback(self.downloadError)
293                         else:
294                                 if entry.justplay & PlaylistEntry.SwitchTimerEntry:
295                                         action = "zap"
296                                 elif entry.justplay & PlaylistEntry.recNgrab:
297                                         action = "ngrab"
298                                 else:
299                                         action = ""
300                                 tstart = time.localtime(entry.timebegin)
301                                 tend = time.localtime(entry.timeend)
302                                 ref_time_start = "&sday=" + ("%s"%(tstart.tm_mday)) + "&smonth=" + ("%s"%(tstart.tm_mon)) + "&syear=" + ("%s"%(tstart.tm_year)) + "&shour=" + ("%s"%(tstart.tm_hour)) + "&smin=" + ("%s"%(tstart.tm_min))
303                                 ref_time_end = "&eday=" + ("%s"%(tend.tm_mday)) + "&emonth=" + ("%s"%(tend.tm_mon)) + "&eyear=" + ("%s"%(tend.tm_year)) + "&ehour=" + ("%s"%(tend.tm_hour)) + "&emin=" + ("%s"%(tend.tm_min))
304                                 ref_old = "&old_type=" + ("%s"%(self.oldtype)) + "&old_stime=" + ("%s"%(self.oldstart)) + "&force=yes"
305                                 ref = urllib.quote(entry.servicereference.decode('utf8').encode('latin-1','ignore')) + "&descr=" + urllib.quote(entry.description) + "&channel=" + urllib.quote(entry.servicename) + "&after_event=" + ("%s"%(entry.afterevent)) + "&action=" + ("%s"%(action))
306                                 sCommand = self.http + "/changeTimerEvent?ref=" + ref + ref_old + ref_time_start + ref_time_end
307                                 sendPartnerBoxWebCommand(sCommand, None,10, self.username, self.password).addCallback(self.deleteTimerCallback).addErrback(self.downloadError)
308         
309         def startRun(self):
310                 self["timerlist"].instance.hide()
311                 self.action()
312                 
313         def cleanupTimer(self):
314                 self["timerlist"].instance.hide()
315                 self["text"].setText(_("Cleaning up finished timer entries..."))
316                 if self.enigma_type == 0:
317                         sCommand = self.http + "/web/timercleanup?cleanup=1"
318                 else:
319                         sCommand = self.http + "/cleanupTimerList"
320                 sendPartnerBoxWebCommand(sCommand, None,3, self.username, self.password).addCallback(self.cleanupTimerlistCallback).addErrback(self.cleanupTimerlistCallback)
321                         
322         def cleanupTimerlistCallback(self, answer):
323                 self.action()
324         
325         def deleteTimer(self):
326                 try:
327                         sel = self["timerlist"].l.getCurrentSelection()[0]
328                         if sel is None:
329                                 return
330                         if self.enigma_type == 0:
331                                 name = sel.name
332                         else:
333                                 name = sel.description
334                         self.session.openWithCallback(self.deleteTimerConfirmed, MessageBox, _("Do you really want to delete the timer \n%s ?") % name)
335                 except: return
336
337         def deleteTimerConfirmed(self, val):
338                 if val:
339                         sel = self["timerlist"].l.getCurrentSelection()[0]
340                         if sel is None:
341                                 return
342                         if self.enigma_type == 0:
343                                 sCommand = self.http + "/web/timerdelete?sRef=" + sel.servicereference + "&begin=" + ("%s"%(sel.timebegin)) + "&end=" +("%s"%(sel.timeend))
344                         else:
345                                 sCommand = self.http + "/deleteTimerEvent?ref=" + sel.servicereference + "&start=" + ("%s"%(sel.timebegin)) + "&type=" +("%s"%(sel.type)) + "&force=yes"
346                         sendPartnerBoxWebCommand(sCommand, None,3, self.username, self.password).addCallback(self.deleteTimerCallback).addErrback(self.deleteTimerError)
347         
348         def deleteTimerCallback(self, callback = None):
349                 self.action()
350                 
351         def deleteTimerError(self, error = None):
352                 if error is not None:
353                         self["timerlist"].instance.hide()
354                         self["text"].setText(str(error.getErrorMessage()))
355         
356         def downloadCallback(self, callback = None):
357                 self.readXML(callback)
358                 self["timerlist"].instance.show()
359
360         def downloadError(self, error = None):
361                 if error is not None:
362                         self["text"].setText(str(error.getErrorMessage()))
363
364         def action(self):
365                 if self.enigma_type == 0:
366                         url = self.http + "/web/timerlist"
367                 else:
368                         url = self.http + "/xml/timers"
369                 sendPartnerBoxWebCommand(url, None,10, self.username, self.password).addCallback(self.downloadCallback).addErrback(self.downloadError)
370
371         def readXML(self, xmlstring):
372                 self.E2TimerList = []
373                 if self.enigma_type == 0:
374                         self.E2TimerList = FillE2TimerList(xmlstring)
375                         self["timerlist"].buildList(self.E2TimerList)
376                 else:
377                         self.E2TimerList = FillE1TimerList(xmlstring)
378                         self["timerlist"].buildE1List(self.E2TimerList)
379
380         def EPGList(self):
381                 self.session.openWithCallback(self.CallbackEPGList, RemoteTimerBouquetList, self.E2TimerList, self.PartnerboxEntry, 0)
382                 
383         def CallbackEPGList(self):
384                 self.startRun()
385
386 class RemoteTimerBouquetList(Screen):
387         skin = """
388                 <screen name="RemoteTimerBouquetList" position="210,160" size="300,240" title="Choose bouquet">
389                 <widget name="text" position="10,10" zPosition="1" size="290,225" font="Regular;20" halign="center" valign="center" />
390                 <widget name="bouquetlist" position="10,10" zPosition="2" size="290,225" scrollbarMode="showOnDemand" />
391         </screen>"""
392         
393         def __init__(self, session, E2Timerlist, partnerboxentry, playeronly):
394                 self.session = session
395                 Screen.__init__(self, session)
396                 self["bouquetlist"] = E2BouquetList([])
397                 self["text"] = Label(_("Getting Partnerbox Bouquet Information..."))
398                 self.onLayoutFinish.append(self.startRun)
399                 self.E2TimerList = E2Timerlist
400                 self["actions"] = ActionMap(["WizardActions", "DirectionActions"],
401                 {
402                         "ok": self.action,
403                         "back": self.close,
404                 }, -1)
405                 self.PartnerboxEntry = partnerboxentry
406                 self.password = partnerboxentry.password.value
407                 self.username = "root"
408                 ip = "%d.%d.%d.%d" % tuple(partnerboxentry.ip.value)
409                 port = partnerboxentry.port.value
410                 self.http = "http://%s:%d" % (ip,port)
411                 self.enigma_type = int(partnerboxentry.enigma.value)
412                 self.useinternal = int(partnerboxentry.useinternal.value)
413                 self.playeronly = playeronly
414                 if self.enigma_type == 0:
415                         self.url = self.http + "/web/getservices"
416                 else:
417                         self.url = self.http + "/xml/services?mode=0&submode=4"
418                 self.E1XMLString = ""
419                 
420                 
421         def action(self):
422                 try:
423                         sel = self["bouquetlist"].l.getCurrentSelection()[0]
424                         if sel is None:
425                                 return
426                         self.session.openWithCallback(self.CallbackEPGList, RemoteTimerChannelList, self.E2TimerList, sel.servicereference, sel.servicename, self.PartnerboxEntry, self.E1XMLString, self.playeronly)
427                 except: return
428                 
429         def CallbackEPGList(self):
430                 pass
431         
432         def startRun(self):
433                 if self.useinternal == 1 :
434                         BouquetList = []
435                         a = Services(self.session)
436                         ref = eServiceReference( service_types_tv + ' FROM BOUQUET "bouquets.tv" ORDER BY bouquet')
437                         BouquetList = a.buildList(ref, False)
438                         self["bouquetlist"].buildList(BouquetList)
439                 else:
440                         self["bouquetlist"].instance.hide()
441                         self.getBouquetList()
442         
443         def getBouquetList(self):
444                 sendPartnerBoxWebCommand(self.url, None,10, self.username, self.password).addCallback(self.downloadCallback).addErrback(self.downloadError)
445                 
446         def downloadCallback(self, callback = None):
447                 if self.enigma_type == 0:
448                         self.readXML(callback)
449                 else:
450                         self.readXMLE1(callback)
451                 self["bouquetlist"].instance.show()
452
453         def downloadError(self, error = None):
454                 if error is not None:
455                         self["text"].setText(str(error.getErrorMessage()))
456
457         def readXMLE1(self,xmlstring):
458                 self.E1XMLString = xmlstring
459                 BouquetList = []
460                 root = xml.etree.cElementTree.fromstring(xmlstring)
461                 for bouquets in root.findall("bouquet"):
462                         BouquetList.append(E2ServiceList(
463                         servicereference = str(bouquets.findtext("reference", '').encode("utf-8", 'ignore')),
464                         servicename = str(bouquets.findtext("name", 'n/a').encode("utf-8", 'ignore'))))
465                 self["bouquetlist"].buildList(BouquetList)
466
467         def readXML(self, xmlstring):
468                 BouquetList = []
469                 root = xml.etree.cElementTree.fromstring(xmlstring)
470                 for servives in root.findall("e2service"):
471                         BouquetList.append(E2ServiceList(
472                         servicereference = str(servives.findtext("e2servicereference", '').encode("utf-8", 'ignore')),
473                         servicename = str(servives.findtext("e2servicename", 'n/a').encode("utf-8", 'ignore'))))
474                 self["bouquetlist"].buildList(BouquetList)
475
476 class RemoteTimerChannelList(Screen):
477         EMPTY = 0
478         ADD_TIMER = 1
479         REMOVE_TIMER = 2
480         REMOTE_TIMER_MODE = 0
481         REMOTE_TV_MODE = 1
482         skin = """
483                 <screen name="RemoteTimerChannelList" position="90,95" size="560,430" title ="Bouquet List">
484                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
485                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
486                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
487                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
488                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
489                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
490                         <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
491                         <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
492                         <widget name="text" position="0,40" zPosition="1" size="560,375" font="Regular;20" halign="center" valign="center" />
493                         <widget name="channellist" position="0,40" zPosition="2" size="560,375" scrollbarMode="showOnDemand" />
494                 </screen>"""
495         
496         def __init__(self, session, E2Timerlist, ServiceReference, ServiceName, partnerboxentry, E1XMLString,  playeronly):
497                 self.session = session
498                 Screen.__init__(self, session)
499                 self["channellist"] = E2ChannelList([], selChangedCB = self.onSelectionChanged)
500                 self.playeronly = playeronly
501                 self["key_red"] = Label(_("Zap"))
502                 self["key_green"] = Label()
503                 if self.playeronly == 0:
504                                 self["key_yellow"] = Label(_("EPG Selection"))
505                 else:
506                         self["key_yellow"] = Label()
507                 self["key_blue"] = Label(_("Info"))
508                 
509                 self["text"] = Label(_("Getting Channel Information..."))
510                 self.onLayoutFinish.append(self.startRun)
511                 self.E2TimerList = E2Timerlist
512                 self.E2ChannelList = []
513                 self.servicereference = ServiceReference
514                 self.E1XMLString = E1XMLString
515                 self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions"],
516                 {
517                         "ok": self.PlayRemoteStream,
518                         "back": self.close,
519                         "yellow": self.EPGSelection,
520                         "blue": self.EPGEvent,
521                         "red": self.Zap,
522                 }, -1)
523
524
525                 self.PartnerboxEntry = partnerboxentry
526                 self.password = partnerboxentry.password.value
527                 self.username = "root"
528                 self.ip = "%d.%d.%d.%d" % tuple(partnerboxentry.ip.value)
529                 self.port = partnerboxentry.port.value
530                 self.http = "http://%s:%d" % (self.ip,self.port)
531                 self.enigma_type = int(partnerboxentry.enigma.value)
532                 self.useinternal = int(partnerboxentry.useinternal.value)
533                 self.key_green_choice = self.ADD_TIMER
534                 self.zapTimer = eTimer()
535                 self.zapTimer.timeout.get().append(self.zapTimerTimeout)
536                 self.onClose.append(self.__onClose)
537                 self.ChannelListCurrentIndex = 0
538                 self.mode = self.REMOTE_TIMER_MODE
539                 self.CurrentService = self.session.nav.getCurrentlyPlayingServiceReference()
540                 
541         def __onClose(self):
542                 if self.zapTimer.isActive():
543                         self.zapTimer.stop()
544                         
545         def startRun(self):
546                 if self.useinternal == 1 :
547                         ChannelList = []
548                         a = Services(self.session)
549                         Channelref = eServiceReference(self.servicereference)
550                         ChannelList = a.buildList(Channelref, True)
551                         self["channellist"].buildList(ChannelList)
552                         self["channellist"].instance.show()
553                         if self.ChannelListCurrentIndex !=0:
554                                 sel = self["channellist"].moveSelectionTo(self.ChannelListCurrentIndex)
555                                 self.ChannelListCurrentIndex = 0
556                 else:
557                         self["channellist"].instance.hide()
558                         self.getChannelList()
559         
560         def PlayRemoteStream(self):
561                 if self.playeronly == 1:
562                         if self.mode == self.REMOTE_TIMER_MODE:
563                                 self.mode = self.REMOTE_TV_MODE
564                                 self.Zap()
565                         else:
566                                 self.session.nav.playService(self.CurrentService)
567                                 self.mode = self.REMOTE_TIMER_MODE
568                                 self["channellist"].instance.show()
569                 else:
570                         self.EPGSelection()
571                         
572         def Zap(self):
573                 sel = self["channellist"].l.getCurrentSelection()[0]
574                 if sel is None:
575                         return
576                 self["channellist"].instance.hide()
577                 self.ChannelListCurrentIndex = self["channellist"].getCurrentIndex()
578                 self["text"].setText("Zapping to " + sel.servicename)
579         
580                 if self.useinternal == 1 and self.mode == self.REMOTE_TIMER_MODE:
581                         self.session.nav.playService(eServiceReference(sel.servicereference))
582                         self.ZapCallback(None)
583                 else:
584                         if self.enigma_type == 0:
585                                 url = self.http + "/web/zap?sRef=" + urllib.quote(sel.servicereference.decode('utf8').encode('latin-1','ignore'))
586                         else:
587                                 url = self.http + "/cgi-bin/zapTo?path=" + urllib.quote(sel.servicereference.decode('utf8').encode('latin-1','ignore'))
588                         sendPartnerBoxWebCommand(url, None,10, self.username, self.password).addCallback(self.ZapCallback).addErrback(self.DoNotCareError)
589         
590         def DoNotCareError(self, dnce = None):
591                 # Jesses, E1 sendet 204 nach umschalten, kommt hier also immer rein...
592                 self.ZapCallback(dnce)
593         
594         def ZapCallback(self, callback = None):
595                 if self.mode == self.REMOTE_TIMER_MODE:
596                         self["text"].setText("Give Enigma time to fill epg cache...")
597                         self.zapTimer.start(10000) # 10 Sekunden
598                 else:
599                         self.zapTimer.start(3000) # 3 Sekunden REMOTE_TV
600                 
601         def zapTimerTimeout(self):
602                 if self.zapTimer.isActive():
603                         self.zapTimer.stop()
604                 if self.mode == self.REMOTE_TIMER_MODE:
605                         self.startRun()
606                 else:
607                         self.GetStreamInfosCallback()
608         
609         def GetStreamInfosCallback(self):
610                 if self.enigma_type == 0:
611                         url = "http://" + self.ip + ":8001/" + self["channellist"].l.getCurrentSelection()[0].servicereference 
612                         self.StreamTV(url)
613                 else:
614                         url = self.http + "/video.m3u"
615                         sendPartnerBoxWebCommand(url, None,10, self.username, self.password).addCallback(self.StreamTV).addErrback(self.ChannelListDownloadError)
616         
617         def StreamTV(self, connectstring):
618                         self.session.nav.stopService()
619                         sref = eServiceReference(ENIGMA_WEBSERVICE_ID, 0, connectstring)
620                         self.session.nav.playService(sref)
621                         self.session.openWithCallback(self.PlayRemoteStream, RemotePlayer, self["channellist"].l.getCurrentSelection()[0].servicename,self["channellist"].l.getCurrentSelection()[0].eventtitle, self["channellist"].l.getCurrentSelection()[0].eventstart, self["channellist"].l.getCurrentSelection()[0].eventduration, self.PartnerboxEntry, self["channellist"].l.getCurrentSelection()[0].servicereference)
622         
623         def EPGEvent(self):
624                 sel = self["channellist"].l.getCurrentSelection()[0]
625                 if sel is None:
626                         return
627                 self.session.openWithCallback(self.CallbackEPGEvent, RemoteTimerEventView, self.E2TimerList, sel, self.PartnerboxEntry)
628
629         def CallbackEPGEvent(self):
630                 pass
631                 
632         def onSelectionChanged(self):
633                 cur = self["channellist"].getCurrent()
634                 if cur is None:
635                         self["key_green"].setText("")
636                         self.key_green_choice = self.EMPTY
637                         self["key_yellow"].setText("")
638                         self["key_blue"].setText("")
639                         return
640                 eventid = cur[0].eventid
641                 if eventid ==0:
642                         self["key_green"].setText("")
643                         self.key_green_choice = self.EMPTY
644                         self["key_yellow"].setText("")
645                         self["key_blue"].setText("")
646                         return
647                 if self.playeronly == 0:
648                         self["key_yellow"].setText(_("EPG Selection"))
649                 self["key_blue"].setText(_("Info"))
650                 serviceref = cur[0].servicereference
651                 
652 #               isRecordEvent = False
653 #               for timer in self.E2TimerList:
654 #                       if timer.eventId == eventid and timer.servicereference == serviceref:
655 #                               isRecordEvent = True
656 #                               break
657 #               if isRecordEvent and self.key_green_choice != self.REMOVE_TIMER:
658 #                       self["key_green"].setText(_("Remove timer"))
659 #                       self.key_green_choice = self.REMOVE_TIMER
660 #               elif not isRecordEvent and self.key_green_choice != self.ADD_TIMER:
661 #                       self["key_green"].setText(_("Add timer"))
662 #                       self.key_green_choice = self.ADD_TIMER
663                 
664         def ChannelListDownloadCallback(self, callback = None):
665                 self.readXMLServiceList(callback)
666                 if self.ChannelListCurrentIndex !=0:
667                         sel = self["channellist"].moveSelectionTo(self.ChannelListCurrentIndex)
668                         self.ChannelListCurrentIndex = 0
669                 self["channellist"].instance.show()
670
671         def ChannelListDownloadError(self, error = None):
672                 if error is not None:
673                         self["text"].setText(str(error.getErrorMessage()))
674                         self.mode = REMOTE_TIMER_MODE
675                         
676         def getChannelList(self):
677                 if self.enigma_type == 0:
678                         ref = urllib.quote(self.servicereference.decode('utf8').encode('latin-1','ignore'))
679                         url = self.http + "/web/epgnow?bRef=" + ref
680                         sendPartnerBoxWebCommand(url, None,10, self.username, self.password).addCallback(self.ChannelListDownloadCallback).addErrback(self.ChannelListDownloadError)
681                 else:
682                         self.readXMLServiceListE1()
683                         if self.ChannelListCurrentIndex !=0:
684                                 sel = self["channellist"].moveSelectionTo(self.ChannelListCurrentIndex)
685                                 self.ChannelListCurrentIndex = 0
686                         self["channellist"].instance.show()
687
688         def readXMLServiceListE1(self):
689                 self.E2ChannelList = []
690                 root = xml.etree.cElementTree.fromstring(self.E1XMLString)
691                 for bouquets in root.findall("bouquet"):
692                         tempref = str(bouquets.findtext("reference", '').encode("utf-8", 'ignore'))
693                         print "----------->tempref = %s, service = %s"%(tempref, self.servicereference)
694                         if tempref == self.servicereference:
695                                 for services in bouquets.findall("service"):
696                                         servicereference = str(services.findtext("reference", '').encode("utf-8", 'ignore'))
697                                         servicename = str(services.findtext("name", 'n/a').encode("utf-8", 'ignore'))
698                                         http_ = "%s:%d" % (self.ip,self.port)
699                                         url = "http://" + self.username + ":" + self.password + "@" + http_ + "/xml/serviceepg?ref=" + servicereference + "&entries=1"
700                                         f = urllib.urlopen(url)
701                                         sxml = f.read()
702                                         eventstart, eventduration, eventtitle, eventdescriptionextended, eventdescription, eventid = self.XMLReadEPGDataE1(sxml)
703                                         self.E2ChannelList.append(E2EPGListAllData(servicereference = servicereference, servicename = servicename, eventstart = eventstart, eventduration = eventduration, eventtitle = eventtitle, eventid = eventid , eventdescription= eventdescription, eventdescriptionextended = eventdescriptionextended))
704                 self["channellist"].buildList(self.E2ChannelList)
705                 
706         def XMLReadEPGDataE1(self,xmlstring):
707                 eventstart = 0
708                 eventduration = 0
709                 eventtitle = ""
710                 eventdescriptionextended = ""
711                 eventdescription = ""
712                 eventid = 0
713                 xmlstring = xmlstring.replace("""<?xml-stylesheet type="text/xsl" href="/xml/serviceepg.xsl"?>""","")
714                 root = xml.etree.cElementTree.fromstring(xmlstring)
715                 for events in root.findall("event"):
716                         try:eventtitle = str(events.findtext("description", '').encode("utf-8", 'ignore'))
717                         except:eventtitle = ""
718                         try:eventdescriptionextended = str(events.findtext("details", '').encode("utf-8", 'ignore'))
719                         except:eventdescriptionextended = ""
720                         try:eventdescription = str(events.findtext("genre", '').encode("utf-8", 'ignore'))
721                         except:eventdescription = ""
722                         try:eventstart = int(events.findtext("start", 0))
723                         except:eventstart = 0
724                         try:eventduration = int(events.findtext("duration", 0))
725                         except:eventduration = 0
726                 if eventstart != 0:
727                         eventid = 1
728
729                 return eventstart, eventduration, eventtitle, eventdescriptionextended, eventdescription,eventid
730
731         def readXMLServiceList(self, xmlstring):
732                 self.E2ChannelList = []
733                 root = xml.etree.cElementTree.fromstring(xmlstring)
734                 for events in root.findall("e2event"):
735                         servicereference = str(events.findtext("e2eventservicereference", '').encode("utf-8", 'ignore'))
736                         servicename = str(events.findtext("e2eventservicename", 'n/a').encode("utf-8", 'ignore'))
737                         try:eventstart = int(events.findtext("e2eventstart", 0))
738                         except:eventstart = 0
739                         try:eventduration = int(events.findtext("e2eventduration", 0))
740                         except:eventduration  = 0
741                         try:eventtitle = str(events.findtext("e2eventtitle", '').encode("utf-8", 'ignore'))
742                         except:eventtitle = ""
743                         try:eventid = int(events.findtext("e2eventid", 0))
744                         except:eventid = 0
745                         try:eventdescription = str(events.findtext("e2eventdescription", '').encode("utf-8", 'ignore'))
746                         except:eventdescription = ""
747                         try:eventdescriptionextended = str(events.findtext("e2eventdescriptionextended", '').encode("utf-8", 'ignore'))
748                         except:eventdescriptionextended = ""
749                         self.E2ChannelList.append(E2EPGListAllData(
750                                         servicereference = servicereference, servicename = servicename, eventstart = eventstart,
751                                         eventduration = eventduration, eventtitle = eventtitle, eventid = eventid, eventdescription= eventdescription, 
752                                         eventdescriptionextended = eventdescriptionextended))
753                 self["channellist"].buildList(self.E2ChannelList)
754
755         def EPGSelection(self):
756                 if self.playeronly == 0:
757                         try:
758                                 sel = self["channellist"].l.getCurrentSelection()[0]
759                                 if sel is None:
760                                         return
761                                 if sel.eventid != 0:
762                                         self.session.openWithCallback(self.CallbackEPGSelection, RemoteTimerEPGList, self.E2TimerList, sel.servicereference, sel.servicename, self.PartnerboxEntry)
763                         except: return
764                 
765         def CallbackEPGSelection(self):
766                 pass
767
768 class RemotePlayer(Screen, InfoBarAudioSelection):
769         
770         
771         HDSkn = False
772         try:
773                 sz_w = getDesktop(0).size().width()
774                 if sz_w == 1280:
775                         HDSkn = True
776                 else:
777                         HDSkn = False
778         except:
779                 HDSkn = False
780         if HDSkn:
781                 skin="""
782                 <screen name="RemotePlayer" flags="wfNoBorder" position="283,102" size="720,576" title="Partnerbox - RemotePlayer" backgroundColor="#FFFFFFFF">
783                         <ePixmap position="41,388" zPosition="-1" size="630,130" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/ExPlayer.png" alphatest="off" transparent="1"/>
784                         <widget name="ServiceName" zPosition="1" position="50,404" size="610,59" valign="center" halign="center" font="Regular;21" foregroundColor="#F0F0F0" backgroundColor="#302C2C39" />
785                         <widget name="DateTime" zPosition="1" position="52,473" size="500,30" halign="left" font="Regular;16" foregroundColor="#F0F0F0" backgroundColor="#302C2C39" transparent="1" />
786                         <widget name="IP" zPosition="2" position="361,473" size="300,30" halign="right" font="Regular;16" foregroundColor="#F0F0F0" backgroundColor="#302C2C39" transparent="1" />
787                 </screen>"""
788         else:
789                 skin="""
790                 <screen name="RemotePlayer" flags="wfNoBorder" position="3,30" size="720,576" title="Partnerbox - RemotePlayer" backgroundColor="#FFFFFFFF">
791                         <ePixmap position="41,388" zPosition="-1" size="630,130" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/ExPlayer.png" alphatest="off" transparent="1"/>
792                         <widget name="ServiceName" zPosition="1" position="50,404" size="610,59" valign="center" halign="center" font="Regular;21" foregroundColor="#F0F0F0" backgroundColor="#302C2C39" />
793                         <widget name="DateTime" zPosition="1" position="52,473" size="500,30" halign="left" font="Regular;16" foregroundColor="#F0F0F0" backgroundColor="#302C2C39" transparent="1" />
794                         <widget name="IP" zPosition="2" position="361,473" size="300,30" halign="right" font="Regular;16" foregroundColor="#F0F0F0" backgroundColor="#302C2C39" transparent="1" />
795                 </screen>"""
796         
797         def __init__(self, session, ServiceName, EventTitle, eventstart, eventduration, partnerboxentry, servicereference):
798                 self.session = session
799                 Screen.__init__(self, session)
800                 InfoBarAudioSelection.__init__(self)
801                 self.enigma_type = int(partnerboxentry.enigma.value)
802                 self.useinternal = int(partnerboxentry.useinternal.value)
803                 endtime = int(eventstart + eventduration)
804                 tt = ((" %s ... %s (+%d " + _("mins") + ")") % (FuzzyTime(eventstart)[1], FuzzyTime(endtime)[1], (endtime - time.time()) / 60)) 
805                 self["ServiceName"] = Label(EventTitle)
806                 self.ip = "%d.%d.%d.%d" % tuple(partnerboxentry.ip.value)
807                 port = partnerboxentry.port.value
808                 self.http = self.http = "http://%s:%d" % (self.ip,port)
809                 self["IP"] = Label(self.ip)
810                 if eventstart != 0:
811                         self["DateTime"] = Label(ServiceName + ": " + tt)
812                 else:
813                         self["DateTime"] = Label()
814                 self.isVisible = True
815                 self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions"],
816                 {
817                         "ok": self.Infobar,
818                         "back": self.close,
819                 }, -1)
820                 self.password = partnerboxentry.password.value
821                 self.username = "root"
822                 self.servicereference = servicereference
823                 self.onLayoutFinish.append(self.startRun)
824                 self.onClose.append(self.__onClose)
825                 
826                 self.Timer = eTimer()
827                 self.Timer.timeout.get().append(self.TimerTimeout)
828                 
829         def TimerTimeout(self):
830                 if self.Timer.isActive():
831                         self.Timer.stop()
832                 self.Infobar()
833         
834         def startRun(self):
835                 idx = config.usage.infobar_timeout.index
836                 if idx:
837                         self.Timer.start(idx * 1000)
838                 else:
839                         self.Timer.start(6 * 1000)
840                 if self.enigma_type == 0:
841                         url = self.http + "/web/epgservicenow?sRef=" + self.servicereference
842                 else:
843                         url = self.http + "/xml/serviceepg?ref=" + self.servicereference + "&entries=1"
844                 sendPartnerBoxWebCommand(url, None,10, self.username, self.password).addCallback(self.CurrentEPGCallback).addErrback(self.CurrentEPGCallbackError)
845
846         def CurrentEPGCallback(self, xmlstring):
847                 xmlstring = xmlstring.replace("""<?xml-stylesheet type="text/xsl" href="/xml/serviceepg.xsl"?>""","")
848                 root = xml.etree.cElementTree.fromstring(xmlstring)
849                 e2eventtitle = ""
850                 e2eventservicename = ""
851                 e2eventstart = 0
852                 e2eventduration = 0
853                 if self.enigma_type == 0:
854                         for events in root.findall("e2event"):
855                                 try:e2eventservicename = str(events.findtext("e2eventservicename", 'n/a').encode("utf-8", 'ignore'))
856                                 except:e2eventservicename = "n/a"
857                                 try:e2eventstart = int(events.findtext("e2eventstart", 0))
858                                 except:e2eventstart = 0
859                                 try:e2eventduration = int(events.findtext("e2eventduration", 0))
860                                 except:e2eventduration  = 0
861                                 try:e2eventtitle = str(events.findtext("e2eventtitle", '').encode("utf-8", 'ignore'))
862                                 except:e2eventtitle = ""
863                 else:
864                         for services in root.findall("service"):
865                                 try:e2eventservicename = str(services.findtext("name", 'n/a').encode("utf-8", 'ignore'))
866                                 except:e2eventservicename = "n/a"
867                         for events in root.findall("event"):
868                                 try:e2eventstart = int(events.findtext("start", 0))
869                                 except:e2eventstart = 0
870                                 try:e2eventduration = int(events.findtext("duration", 0))
871                                 except:e2eventduration  = 0
872                                 try:e2eventtitle = str(events.findtext("description", '').encode("utf-8", 'ignore'))
873                                 except:e2eventtitle = ""
874                 endtime = int(e2eventstart + e2eventduration)
875                 if endtime != 0:
876                         tt = ((": %s ... %s (+%d " + _("mins") + ")") % (FuzzyTime(e2eventstart)[1], FuzzyTime(endtime)[1], (endtime - time.time()) / 60))
877                 else:
878                         tt = ""
879                 self["ServiceName"].setText(e2eventtitle)
880                 self["DateTime"].setText(e2eventservicename + tt)
881
882         def CurrentEPGCallbackError(self, error = None):
883                 print "[RemotePlayer] Error: ",error.getErrorMessage()
884                 
885 #       def readXMSubChanelList(self, xmlstring):
886 #               BouquetList = []
887 #               counter = 0
888 #               dom = xml.dom.minidom.parseString(xmlstring)
889 #               for node in dom.firstChild.childNodes:
890 #                       servicereference = ""
891 #                       servicename = ""
892 #                       if node.nodeName == "e2service":
893 #                               for node2 in node.childNodes:
894 #                                       if node2.nodeName == "e2servicereference": servicereference = str(node2.firstChild.data.strip().encode("utf-8"))
895 #                                       if node2.nodeName == "e2servicename":
896 #                                               try:servicename = str(node2.firstChild.data.strip().encode("utf-8"))
897 #                                               except:servicename = "n/a"
898 #                                               if counter != 0: # erster Eintrag ist der aktuelle Sedner, nicht aufnehmen
899 #                                                       BouquetList.append(E2ServiceList(servicereference = servicereference, servicename = servicename))
900 #                                               counter += 1
901         
902         def Infobar(self):
903                 if self.isVisible:
904                         if self.Timer.isActive():
905                                 self.Timer.stop()
906                         self.hide()
907                         self.isVisible = False
908                 else:
909                         self.startRun()
910                         self.show()
911                         self.isVisible = True
912                         
913         def __onClose(self):
914                 if self.Timer.isActive():
915                         self.Timer.stop()
916                 
917 class RemoteTimerEPGList(Screen):
918         EMPTY = 0
919         ADD_TIMER = 1
920         REMOVE_TIMER = 2
921         skin = """
922                 <screen name="RemoteTimerEPGList" position="90,95" size="560,430" title ="EPG Selection">
923                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
924                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
925                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
926                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
927                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
928                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
929                         <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
930                         <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
931                         <widget name="text" position="0,40" zPosition="1" size="560,375" font="Regular;20" halign="center" valign="center" />
932                         <widget name="epglist" position="0,40" zPosition="2" size="560,375" scrollbarMode="showOnDemand" />
933                 </screen>"""
934         
935         def __init__(self, session, E2Timerlist, ServiceReference, ServiceName, partnerboxentry):
936                 self.session = session
937                 Screen.__init__(self, session)
938                 self.E2TimerList = E2Timerlist
939                 self["epglist"] = E2EPGList([],selChangedCB = self.onSelectionChanged)
940                 self["key_red"] = Label()# Dummy, kommt eventuell noch was
941                 self["key_green"] = Label(_("Add timer"))
942                 self.key_green_choice = self.ADD_TIMER
943                 self["key_yellow"] = Label() # Dummy, kommt eventuell noch was
944                 self["key_blue"] = Label(_("Info"))
945                 self["text"] = Label(_("Getting EPG Information..."))
946                 self.onLayoutFinish.append(self.startRun)
947                 self.servicereference = ServiceReference
948                 self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions"],
949                 {
950                         "back": self.close,
951                         "green": self.GreenPressed,
952                         "blue": self.EPGEvent,
953                 }, -1)
954                 
955                 self.PartnerboxEntry = partnerboxentry
956                 self.password = partnerboxentry.password.value
957                 self.username = "root"
958                 self.ip = "%d.%d.%d.%d" % tuple(partnerboxentry.ip.value)
959                 port = partnerboxentry.port.value
960                 self.http = "http://%s:%d" % (self.ip,port)
961                 self.enigma_type = int(partnerboxentry.enigma.value)
962                 self.useinternal = int(partnerboxentry.useinternal.value)
963                 
964                 if self.enigma_type == 0:
965                         self.url = self.http + "/web/epgservice?sRef=" + urllib.quote(self.servicereference.decode('utf8').encode('latin-1','ignore'))
966                 else:
967                         self.url = self.http + "/xml/serviceepg?ref=" + urllib.quote(self.servicereference.decode('utf8').encode('latin-1','ignore'))
968                 self.ListCurrentIndex = 0
969                 self.Locations = []
970                 
971         def EPGEvent(self):
972                 
973                 sel = self["epglist"].l.getCurrentSelection()[0]
974                 if sel is None:
975                         return
976                 self.session.openWithCallback(self.CallbackEPGEvent, RemoteTimerEventView, self.E2TimerList, sel, self.PartnerboxEntry)
977                 
978         def CallbackEPGEvent(self):
979                 pass
980                 
981         def onSelectionChanged(self):
982                 cur = self["epglist"].getCurrent()
983                 if cur is None:
984                         self["key_green"].setText("")
985                         self.key_green_choice = self.EMPTY
986                         self["key_blue"].setText("")
987                         return
988                 serviceref = cur[0].servicereference
989                 eventid = cur[0].eventid
990                 if eventid ==0:
991                         self["key_green"].setText("")
992                         self.key_green_choice = self.EMPTY
993                         self["key_blue"].setText("")
994                         return
995                 self["key_blue"].setText(_("Info"))
996                 
997                 timerentry = isInTimerList(cur[0].eventstart,cur[0].eventduration, cur[0].servicereference, cur[0].eventid, self.E2TimerList)
998                 if timerentry is None:
999                         if self.key_green_choice != self.ADD_TIMER:
1000                                 self["key_green"].setText(_("Add timer"))
1001                                 self.key_green_choice = self.ADD_TIMER
1002                 else:
1003                         if self.key_green_choice != self.REMOVE_TIMER:
1004                                 self["key_green"].setText(_("Remove timer"))
1005                                 self.key_green_choice = self.REMOVE_TIMER
1006         
1007         def startRun(self):
1008                 if self.useinternal == 1:
1009                         EPGList = []
1010                         a = Services(self.session)
1011                         EPGList = a.buildEPGList(self.servicereference)
1012                         self["epglist"].buildList(EPGList, self.E2TimerList)
1013                         if self.ListCurrentIndex != 0:
1014                                 sel = self["epglist"].moveSelectionTo(self.ListCurrentIndex)
1015                                 self.ListCurrentIndex = 0
1016                 else:
1017                         self["epglist"].instance.hide()
1018                         self.getEPGList()
1019         
1020         def getEPGList(self):
1021                         sendPartnerBoxWebCommand(self.url, None,10, self.username, self.password).addCallback(self.EPGListDownloadCallback).addErrback(self.EPGListDownloadError)
1022                 
1023         def EPGListDownloadCallback(self, callback = None):
1024                 if self.enigma_type == 0:
1025                         self.readXMLEPGList(callback)
1026                 else:
1027                         self.readXMLEPGListE1(callback)
1028                 self["epglist"].instance.show()
1029         
1030         def EPGListDownloadError(self, error = None):
1031                 if error is not None:
1032                         self["text"].setText(str(error.getErrorMessage()))
1033         
1034         def readXMLEPGListE1(self, xmlstring):
1035                 E1ListEPG = []
1036                 xmlstring = xmlstring.replace("""<?xml-stylesheet type="text/xsl" href="/xml/serviceepg.xsl"?>""","")
1037                 root = xml.etree.cElementTree.fromstring(xmlstring)
1038                 for services in root.findall("service"):
1039                         servicereference = str(services.findtext("reference", 'n/a').encode("utf-8", 'ignore'))
1040                         try:servicename = str(services.findtext("name", 'n/a').encode("utf-8", 'ignore'))
1041                         except:servicename = "n/a"
1042                 for events in root.findall("event"):
1043                         try:eventstart = int(events.findtext("start", 0))
1044                         except:eventstart = 0
1045                         try:eventduration = int(events.findtext("duration", 0))
1046                         except:eventduration  = 0
1047                         try:eventtitle = str(events.findtext("description", '').encode("utf-8", 'ignore'))
1048                         except:eventtitle = ""
1049                         try:eventdescription = str(events.findtext("genre", '').encode("utf-8", 'ignore'))
1050                         except:eventdescription = ""
1051                         try:eventdescriptionextended = str(events.findtext("details", '').encode("utf-8", 'ignore'))
1052                         except:eventdescriptionextended = ""
1053                         E1ListEPG.append(E2EPGListAllData(servicereference = servicereference, servicename = servicename, eventid = 1, eventstart = eventstart, eventduration = eventduration, eventtitle = eventtitle, eventdescription = eventdescription, eventdescriptionextended = eventdescriptionextended  ))
1054                 self["epglist"].buildList(E1ListEPG, self.E2TimerList)
1055                 if self.ListCurrentIndex != 0:
1056                         sel = self["epglist"].moveSelectionTo(self.ListCurrentIndex)
1057                         self.ListCurrentIndex = 0
1058         
1059         def readXMLEPGList(self, xmlstring):
1060                 E2ListEPG = []
1061                 root = xml.etree.cElementTree.fromstring(xmlstring)
1062                 for events in root.findall("e2event"):
1063                         servicereference = str(events.findtext("e2eventservicereference", '').encode("utf-8", 'ignore'))
1064                         servicename = str(events.findtext("e2eventservicename", 'n/a').encode("utf-8", 'ignore'))
1065                         try:eventstart = int(events.findtext("e2eventstart", 0))
1066                         except:eventstart = 0
1067                         try:eventduration = int(events.findtext("e2eventduration", 0))
1068                         except:eventduration  = 0
1069                         try:eventtitle = str(events.findtext("e2eventtitle", '').encode("utf-8", 'ignore'))
1070                         except:eventtitle = ""
1071                         try:eventid = int(events.findtext("e2eventid", 0))
1072                         except:eventid = 0
1073                         try:eventdescription = str(events.findtext("e2eventdescription", '').encode("utf-8", 'ignore'))
1074                         except:eventdescription = ""
1075                         try:eventdescriptionextended = str(events.findtext("e2eventdescriptionextended", '').encode("utf-8", 'ignore'))
1076                         except:eventdescriptionextended = ""
1077                         E2ListEPG.append(E2EPGListAllData(servicereference = servicereference, servicename = servicename, eventid = eventid, eventstart = eventstart, eventduration = eventduration, eventtitle = eventtitle, eventdescription = eventdescription, eventdescriptionextended = eventdescriptionextended  ))
1078                 self["epglist"].buildList(E2ListEPG, self.E2TimerList)
1079                 if self.ListCurrentIndex != 0:
1080                         sel = self["epglist"].moveSelectionTo(self.ListCurrentIndex)
1081                         self.ListCurrentIndex = 0
1082                 
1083         def GreenPressed(self):
1084                 if self.key_green_choice == self.ADD_TIMER:
1085                         if self.enigma_type == 0:
1086                                 self.getLocations()
1087                         else:
1088                                 self.addTimerEvent()
1089                 elif self.key_green_choice == self.REMOVE_TIMER:
1090                         self.deleteTimer()
1091         
1092         def LocationsError(self, error = None):
1093                 if error is not None:
1094                         self["epglist"].instance.hide()
1095                         self["text"].setText(str(error.getErrorMessage()))
1096         
1097         def getLocations(self):
1098                 sCommand = self.http + "/web/getlocations"
1099                 sendPartnerBoxWebCommand(sCommand, None,3, self.username, self.password).addCallback(self.getLocationsCallback).addErrback(self.LocationsError)
1100         
1101         def getLocationsCallback(self, xmlstring):
1102                 self.Locations = []
1103                 self.Locations = FillLocationList(xmlstring)
1104                 self.addTimerEvent()
1105                         
1106         def addTimerEvent(self):
1107                 cur = self["epglist"].getCurrent()
1108                 if cur is None:
1109                         return
1110                 if self.enigma_type == 0:
1111                         description = cur[0].eventdescription
1112                         type = 0
1113                         dirname = "/hdd/movie/"
1114                 else:
1115                         dirname = ""
1116                         type = PlaylistEntry.RecTimerEntry|PlaylistEntry.recDVR
1117                         description = cur[0].eventtitle
1118                 timerentry = E2Timer(servicereference = cur[0].servicereference, servicename = cur[0].servicename, name = cur[0].eventtitle, disabled = 0, timebegin = cur[0].eventstart, timeend = cur[0].eventstart + cur[0].eventduration, duration = cur[0].eventduration, startprepare = 0, state = 0 , repeated = 0, justplay= 0, eventId = 0, afterevent = 0, dirname = dirname, description = description, type = type )
1119                 self.session.openWithCallback(self.RemoteTimerEntryFinished, RemoteTimerEntry,timerentry, self.Locations)
1120
1121         def RemoteTimerEntryFinished(self, answer):
1122                 if answer[0]:
1123                         self.ListCurrentIndex = self["epglist"].getCurrentIndex()
1124                         entry = answer[1]
1125                         self["epglist"].instance.hide()
1126                         if self.enigma_type == 0:
1127                                 ref = urllib.quote(entry.servicereference.decode('utf8').encode('latin-1','ignore')) + "&begin=" + ("%s"%(entry.timebegin)) + "&end=" + ("%s"%(entry.timeend))  + "&name=" + urllib.quote(entry.name) + "&description=" + urllib.quote(entry.description) + "&dirname=" + urllib.quote(entry.dirname) + "&eit=0&justplay=" + ("%s"%(entry.justplay)) + "&afterevent=" + ("%s"%(entry.afterevent))
1128                                 sCommand = self.http + "/web/timeradd?sRef=" + ref
1129                                 sendPartnerBoxWebCommand(sCommand, None,10, self.username, self.password).addCallback(self.deleteTimerCallback).addErrback(self.EPGListDownloadError)
1130                         else:
1131                                 if entry.justplay & PlaylistEntry.SwitchTimerEntry:
1132                                         action = "zap"
1133                                 elif entry.justplay & PlaylistEntry.recNgrab:
1134                                         action = "ngrab"
1135                                 else:
1136                                         action = ""
1137                                 ref = urllib.quote(entry.servicereference.decode('utf8').encode('latin-1','ignore')) + "&start=" + ("%s"%(entry.timebegin)) + "&duration=" + ("%s"%(entry.timeend - entry.timebegin))  + "&descr=" + urllib.quote(entry.description) + "&channel=" + urllib.quote(entry.servicename) + "&after_event=" + ("%s"%(entry.afterevent)) + "&action=" + ("%s"%(action))
1138                                 sCommand = self.http + "/addTimerEvent?ref=" + ref
1139                                 sendPartnerBoxWebCommand(sCommand, None,10, self.username, self.password).addCallback(self.deleteTimerCallback).addErrback(self.EPGListDownloadError)
1140         
1141         def deleteTimer(self):
1142                 cur = self["epglist"].getCurrent()
1143                 if cur is None:
1144                         return
1145                 timerentry = isInTimerList(cur[0].eventstart,cur[0].eventduration, cur[0].servicereference, cur[0].eventid, self.E2TimerList)
1146                 if timerentry is None:
1147                         return
1148                 else:
1149                         self.session.openWithCallback(self.deleteTimerConfirmed, MessageBox, _("Do you really want to delete the timer \n%s ?") % timerentry.name)
1150
1151         def deleteTimerConfirmed(self, val):
1152                 if val:
1153                         cur = self["epglist"].getCurrent()
1154                         if cur is None:
1155                                 return
1156                         self.ListCurrentIndex = self["epglist"].getCurrentIndex()
1157                         timerentry = isInTimerList(cur[0].eventstart,cur[0].eventduration, cur[0].servicereference, cur[0].eventid, self.E2TimerList)
1158                         if timerentry is None:
1159                                 return
1160                         else:
1161                                 self["epglist"].instance.hide()
1162                                 if self.enigma_type == 0:
1163                                         sCommand = self.http + "/web/timerdelete?sRef=" + timerentry.servicereference + "&begin=" + ("%s"%(timerentry.timebegin)) + "&end=" +("%s"%(timerentry.timeend))
1164                                 else:
1165                                         sCommand = self.http + "/deleteTimerEvent?ref=" + timerentry.servicereference + "&start=" + ("%s"%(timerentry.timebegin)) + "&type=" +("%s"%(timerentry.type)) + "&force=yes"
1166                                 sendPartnerBoxWebCommand(sCommand, None,3, self.username, self.password).addCallback(self.deleteTimerCallback).addErrback(self.EPGListDownloadError)
1167         
1168         def deleteTimerCallback(self, callback = None):
1169                 if self.enigma_type == 0:
1170                         url = self.http + "/web/timerlist"
1171                 else:
1172                         if callback.find("Timer event deleted successfully.") != -1:
1173                                 msg = "Timer event deleted successfully."
1174                         else:
1175                                 msg = callback
1176                         self.session.open(MessageBox,msg,  MessageBox.TYPE_INFO, timeout = 3)
1177                         url = self.http + "/xml/timers"
1178                 sendPartnerBoxWebCommand(url, None,10, self.username, self.password).addCallback(self.readXML).addErrback(self.EPGListDownloadError)
1179
1180         def readXML(self, xmlstring = None):
1181                 if xmlstring is not None:
1182                         self["text"].setText("Getting timerlist data...")
1183                         self.E2TimerList = []
1184                         if self.enigma_type == 0:
1185                                 self.E2TimerList = FillE2TimerList(xmlstring)
1186                         else:
1187                                 self.E2TimerList = FillE1TimerList(xmlstring)
1188                         self["text"].setText("Getting EPG data...")
1189                         if self.useinternal == 1:
1190                                 EPGList = []
1191                                 a = Services(self.session)
1192                                 EPGList = a.buildEPGList(self.servicereference)
1193                                 self["epglist"].buildList(EPGList, self.E2TimerList)
1194                                 self["epglist"].instance.show()
1195                                 if self.ListCurrentIndex != 0:
1196                                         sel = self["epglist"].moveSelectionTo(self.ListCurrentIndex)
1197                                         self.ListCurrentIndex = 0
1198                         else:
1199                                 self.getEPGList()
1200                         
1201 class E2TimerMenu(MenuList):
1202         def __init__(self, list, enableWrapAround = True):
1203                 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
1204                 self.l.setFont(0, gFont("Regular", 20))
1205                 self.l.setFont(1, gFont("Regular", 18))
1206         def postWidgetCreate(self, instance):
1207                 MenuList.postWidgetCreate(self, instance)
1208                 instance.setItemHeight(70)
1209
1210         def buildList(self,listnew):
1211                 self.list=[]
1212                 width = self.l.getItemSize().width()
1213                 for timer in listnew:
1214                         res = [ timer ]
1215                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0, width, 30, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, timer.servicename))
1216                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 30, width, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, timer.name))
1217
1218                         repeatedtext = ""
1219                         days = [ _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun") ]
1220                         if timer.repeated:
1221                                 flags = timer.repeated
1222                                 count = 0
1223                                 for x in range(0, 7):
1224                                                 if (flags & 1 == 1):
1225                                                         if (count != 0):
1226                                                                 repeatedtext += ", "
1227                                                         repeatedtext += days[x]
1228                                                         count += 1
1229                                                 flags = flags >> 1
1230                                 if timer.justplay:
1231                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-150, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + ((" %s "+ _("(ZAP)")) % (FuzzyTime(timer.timebegin)[1]))))
1232                                 else:
1233                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-150, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + ((" %s ... %s (%d " + _("mins") + ")") % (FuzzyTime(timer.timebegin)[1], FuzzyTime(timer.timeend)[1], (timer.timeend - timer.timebegin) / 60))))
1234                         else:
1235                                 if timer.justplay:
1236                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-150, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + (("%s, %s " + _("(ZAP)")) % (FuzzyTime(timer.timebegin)))))
1237                                 else:
1238                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-150, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + (("%s, %s ... %s (%d " + _("mins") + ")") % (FuzzyTime(timer.timebegin) + FuzzyTime(timer.timeend)[1:] + ((timer.timeend - timer.timebegin) / 60,)))))
1239                         
1240                         if timer.state == TimerEntry.StateWaiting:
1241                                 state = _("waiting")
1242                         elif timer.state == TimerEntry.StatePrepared:
1243                                 state = _("about to start")
1244                         elif timer.state == TimerEntry.StateRunning:
1245                                 if timer.justplay:
1246                                         state = _("zapped")
1247                                 else:
1248                                         state = _("recording...")
1249                         elif timer.state == TimerEntry.StateEnded:
1250                                 state = _("done!")
1251                         else:
1252                                 state = _("<unknown>")
1253
1254                         if timer.disabled:
1255                                 state = _("disabled")
1256
1257                         res.append((eListboxPythonMultiContent.TYPE_TEXT, width-150, 50, 150, 20, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, state))
1258
1259                         if timer.disabled:
1260                                 png = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/redx.png"))
1261                                 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 490, 5, 40, 40, png))
1262
1263                         self.list.append(res)
1264                 self.l.setList(self.list)
1265                 self.moveToIndex(0)
1266                 
1267         def buildE1List(self,listnew):
1268                 self.list=[]
1269                 width = self.l.getItemSize().width()
1270                 for timer in listnew:
1271                         res = [ timer ]
1272                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0, width, 30, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, timer.servicename))
1273                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 30, width, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, timer.description))
1274
1275                         repeatedtext = ""
1276                         days = [ _("Sun"), _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat") ]
1277                         if timer.type & PlaylistEntry.isRepeating :
1278                                 mask = PlaylistEntry.Su
1279                                 count = 0
1280                                 for x in range(0, 7):
1281                                         if timer.type & mask:
1282                                                 if (count != 0):
1283                                                         repeatedtext += ", "
1284                                                 repeatedtext += days[x]
1285                                                 count += 1
1286                                         mask *= 2
1287                                 if timer.type & PlaylistEntry.SwitchTimerEntry:
1288                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-170, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + ((" %s "+ _("(ZAP)")) % (FuzzyTime(timer.timebegin)[1]))))
1289                                 elif timer.type & PlaylistEntry.RecTimerEntry:
1290                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-170, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + ((" %s ... %s (%d " + _("mins") + ")") % (FuzzyTime(timer.timebegin)[1], FuzzyTime(timer.timeend)[1], (timer.timeend - timer.timebegin) / 60))))
1291                         else:
1292                                 if timer.type & PlaylistEntry.SwitchTimerEntry:
1293                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-170, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + (("%s, %s ... %s (%d " + _("mins") + ") ") % (FuzzyTime(timer.timebegin) + FuzzyTime(timer.timeend)[1:] + ((timer.timeend - timer.timebegin) / 60,))) + _("(ZAP)")))
1294                                 elif timer.type & PlaylistEntry.RecTimerEntry:
1295                                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-170, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, repeatedtext + (("%s, %s ... %s (%d " + _("mins") + ")") % (FuzzyTime(timer.timebegin) + FuzzyTime(timer.timeend)[1:] + ((timer.timeend - timer.timebegin) / 60,)))))
1296                         
1297                         if timer.type & PlaylistEntry.stateWaiting:
1298                                 state = _("waiting")
1299                         elif timer.type & PlaylistEntry.stateRunning:
1300                                 if timer.type & PlaylistEntry.SwitchTimerEntry:
1301                                         state = _("zapped")
1302                                 elif timer.type & PlaylistEntry.RecTimerEntry:
1303                                         state = _("recording...")
1304                         elif timer.type & PlaylistEntry.stateFinished:
1305                                 state = _("done!")
1306                         elif timer.type & PlaylistEntry.stateError:
1307                                 if timer.type & PlaylistEntry.errorNoSpaceLeft:
1308                                         state = _("Error: No space left")
1309                                 elif timer.type & PlaylistEntry.errorUserAborted:
1310                                         state = _("Error: User aborted")
1311                                 elif timer.type & PlaylistEntry.errorZapFailed:
1312                                         state = _("Error: Zap failed")
1313                                 elif timer.type & PlaylistEntry.errorOutdated:
1314                                         state = _("Error: Outdated")
1315                                 else:
1316                                         state = "Error: " + _("<unknown>")
1317                         else:
1318                                 state = _("<unknown>")
1319                         res.append((eListboxPythonMultiContent.TYPE_TEXT, width-170, 50, 170, 20, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, state))
1320                         self.list.append(res)
1321                 self.l.setList(self.list)
1322                 self.moveToIndex(0)
1323                 
1324 class E2BouquetList(MenuList):
1325         def __init__(self, list, enableWrapAround = True):
1326                 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
1327                 self.l.setFont(0, gFont("Regular", 20))
1328                 self.l.setFont(1, gFont("Regular", 18))
1329         def postWidgetCreate(self, instance):
1330                 MenuList.postWidgetCreate(self, instance)
1331                 instance.setItemHeight(30)
1332
1333         def buildList(self,listnew):
1334                 self.list=[]
1335                 width = self.l.getItemSize().width()
1336                 for bouquets in listnew:
1337                         res = [ bouquets ]
1338                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0, width, 30, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, bouquets.servicename))
1339                         self.list.append(res)
1340                 self.l.setList(self.list)
1341                 self.moveToIndex(0)
1342
1343 class E2ChannelList(MenuList):
1344         def __init__(self, list, selChangedCB=None, enableWrapAround = True):
1345                 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
1346                 self.onSelChanged = [ ]
1347                 if selChangedCB is not None:
1348                         self.onSelChanged.append(selChangedCB)
1349                 self.l.setFont(0, gFont("Regular", 20))
1350                 self.l.setFont(1, gFont("Regular", 18))
1351         def postWidgetCreate(self, instance):
1352                 MenuList.postWidgetCreate(self, instance)
1353                 instance.setItemHeight(70)
1354                 instance.selectionChanged.get().append(self.selectionChanged)
1355         
1356         def preWidgetRemove(self, instance):
1357                 instance.selectionChanged.get().remove(self.selectionChanged)
1358                 
1359         def selectionChanged(self):
1360                 for x in self.onSelChanged:
1361                         if x is not None:
1362                                 x()
1363                                 
1364         def getCurrentIndex(self):
1365                 return self.instance.getCurrentIndex()
1366                 
1367         def moveSelectionTo(self,index):
1368                 self.moveToIndex(index)
1369         
1370         def buildList(self,listnew):
1371                 self.list=[]
1372                 width = self.l.getItemSize().width()
1373                 for epgdata in listnew:
1374                         res = [ epgdata ]
1375                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0, width, 30, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, epgdata.servicename))
1376                         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 30, width, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, epgdata.eventtitle))
1377                         if epgdata.eventstart != 0:
1378                                 endtime = int(epgdata.eventstart + epgdata.eventduration)
1379                                 res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 50, width-150, 20, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, (("%s ... %s (%d " + _("mins") + ")") % (FuzzyTime(epgdata.eventstart)[1], FuzzyTime(endtime)[1], (endtime - epgdata.eventstart) / 60))))
1380                         self.list.append(res)
1381                 self.l.setList(self.list)
1382                 self.moveToIndex(0)
1383
1384 class E2EPGList(MenuList):
1385         def __init__(self, list, selChangedCB=None, enableWrapAround = True):
1386                 MenuList.__init__(self, list, enableWrapAround, eListboxPythonMultiContent)
1387                 self.onSelChanged = [ ]
1388                 if selChangedCB is not None:
1389                         self.onSelChanged.append(selChangedCB)
1390                 self.l.setFont(0, gFont("Regular", 22))
1391                 self.l.setFont(1, gFont("Regular", 16))
1392                 self.days = [ _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun") ]
1393                 self.timer_list = []
1394                 self.clock_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock.png'))
1395                 self.clock_add_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_add.png'))
1396                 self.clock_pre_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_pre.png'))
1397                 self.clock_post_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_post.png'))
1398                 self.clock_prepost_pixmap = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/epgclock_prepost.png'))
1399                 
1400         def postWidgetCreate(self, instance):
1401                 MenuList.postWidgetCreate(self, instance)
1402                 instance.setItemHeight(30)
1403                 instance.selectionChanged.get().append(self.selectionChanged)
1404         
1405         def preWidgetRemove(self, instance):
1406                 instance.selectionChanged.get().remove(self.selectionChanged)
1407         
1408         def getCurrentIndex(self):
1409                 return self.instance.getCurrentIndex()
1410                 
1411         def moveSelectionTo(self,index):
1412                 self.moveToIndex(index)
1413                 
1414         def selectionChanged(self):
1415                 for x in self.onSelChanged:
1416                         if x is not None:
1417                                 x()
1418         
1419         def buildList(self,listnew, timerlist):
1420                 self.list=[]
1421                 self.timer_list = timerlist
1422                 for epgdata in listnew:
1423                         res = [ epgdata ]
1424                         rec=epgdata.eventstart and (self.isInTimer(epgdata.eventstart, epgdata.eventduration, epgdata.servicereference))
1425                         esize = self.l.getItemSize()
1426                         width = esize.width()
1427                         height = esize.height()
1428                         r1 = Rect(0, 0, width/20*2-10, height)
1429                         r2 = Rect(width/20*2, 0, width/20*5-15, height)
1430                         r3 = Rect(width/20*7, 0, width/20*13, height)
1431                         t = localtime(epgdata.eventstart)
1432                         res.append((eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width(), r1.height(), 0, RT_HALIGN_RIGHT, self.days[t[6]]))
1433                         res.append((eListboxPythonMultiContent.TYPE_TEXT, r2.left(), r2.top(), r2.width(), r1.height(), 0, RT_HALIGN_RIGHT, "%02d.%02d, %02d:%02d"%(t[2],t[1],t[3],t[4])))
1434                         if rec:
1435                                 clock_pic = self.getClockPixmap(epgdata.servicereference, epgdata.eventstart, epgdata.eventduration, epgdata.eventid)
1436                                 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left(), r3.top(), 21, 21, clock_pic))
1437                                 res.append((eListboxPythonMultiContent.TYPE_TEXT, r3.left() + 25, r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, epgdata.eventtitle))
1438                         else:
1439                                 res.append((eListboxPythonMultiContent.TYPE_TEXT, r3.left(), r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, epgdata.eventtitle))
1440                         
1441                         self.list.append(res)
1442                 self.l.setList(self.list)
1443                 self.moveToIndex(0)
1444                 
1445         def isInTimer(self, begin, duration, service):
1446                 time_match = 0
1447                 chktime = None
1448                 chktimecmp = None
1449                 chktimecmp_end = None
1450                 end = begin + duration
1451                 for x in self.timer_list:
1452                         if x.servicereference.upper() == service.upper():
1453                                 if x.repeated != 0:
1454                                         if chktime is None:
1455                                                 chktime = localtime(begin)
1456                                                 chktimecmp = chktime.tm_wday * 1440 + chktime.tm_hour * 60 + chktime.tm_min
1457                                                 chktimecmp_end = chktimecmp + (duration / 60)
1458                                         time = localtime(x.timebegin)
1459                                         for y in range(7):
1460                                                 if x.repeated & (2 ** y):
1461                                                         timecmp = y * 1440 + time.tm_hour * 60 + time.tm_min
1462                                                         if timecmp <= chktimecmp < (timecmp + ((x.timeend - x.timebegin) / 60)):
1463                                                                 time_match = ((timecmp + ((x.timeend - x.timebegin) / 60)) - chktimecmp) * 60
1464                                                         elif chktimecmp <= timecmp < chktimecmp_end:
1465                                                                 time_match = (chktimecmp_end - timecmp) * 60
1466                                 else: 
1467                                         if begin <= x.timebegin <= end:
1468                                                 diff = end - x.timebegin
1469                                                 if time_match < diff:
1470                                                         time_match = diff
1471                                         elif x.timebegin <= begin <= x.timeend:
1472                                                 diff = x.timeend - begin
1473                                                 if time_match < diff:
1474                                                         time_match = diff
1475                                 if time_match:
1476                                         break
1477                 return time_match
1478         
1479         def getClockPixmap(self, refstr, beginTime, duration, eventId):
1480
1481                 pre_clock = 1
1482                 post_clock = 2
1483                 clock_type = 0
1484                 endTime = beginTime + duration
1485                 for x in self.timer_list:
1486                         if x.servicereference.upper() == refstr.upper():
1487                                 if x.eventId == eventId:
1488                                         return self.clock_pixmap
1489                                 beg = x.timebegin
1490                                 end = x.timeend
1491                                 if beginTime > beg and beginTime < end and endTime > end:
1492                                         clock_type |= pre_clock
1493                                 elif beginTime < beg and endTime > beg and endTime < end:
1494                                         clock_type |= post_clock
1495                 if clock_type == 0:
1496                         return self.clock_add_pixmap
1497                 elif clock_type == pre_clock:
1498                         return self.clock_pre_pixmap
1499                 elif clock_type == post_clock:
1500                         return self.clock_post_pixmap
1501                 else:
1502                         return self.clock_prepost_pixmap
1503
1504 class RemoteTimerEventView(Screen):
1505         EMPTY = 0
1506         ADD_TIMER = 1
1507         REMOVE_TIMER = 2
1508         skin = """
1509                 <screen name="RemoteTimerEventView" position="90,95" size="560,430" title="Eventview">
1510                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1511                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1512                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
1513                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
1514                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
1515                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
1516                         <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
1517                         <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
1518                         <widget name="epg_description" position="10,50" size="540,330" font="Regular;22" />
1519                         <widget name="datetime" position="10,395" size="130,25" font="Regular;22" />
1520                         <widget name="duration" position="140,395" size="100,25" font="Regular;22" />
1521                         <widget name="channel" position="240,395" size="305,25" font="Regular;22" halign="right" />
1522                 </screen>"""
1523         
1524         def __init__(self, session, E2Timerlist, epgdata , partnerboxentry):
1525                 self.session = session
1526                 Screen.__init__(self, session)
1527                 self["epg_description"] = ScrollLabel()
1528                 self["datetime"] = Label()
1529                 self["channel"] = Label()
1530                 self["duration"] = Label()
1531                 self["key_red"] = Label() # Dummy, kommt eventuell noch was
1532                 self["key_green"] = Label() # Dummy, kommt eventuell noch was
1533                 self["key_yellow"] = Label() # Dummy, kommt eventuell noch was
1534                 self["key_blue"] = Label() # Dummy, kommt eventuell noch was
1535                 self.key_green_choice = self.ADD_TIMER
1536                 self.onLayoutFinish.append(self.startRun)
1537                 self.E2TimerList = E2Timerlist
1538                 self.epgdata = epgdata
1539                 
1540                 self["actions"] = ActionMap(["WizardActions", "DirectionActions", "ColorActions", "EventViewActions"],
1541                 {
1542                         "back": self.close,
1543                         "pageUp": self.pageUp,
1544                         "pageDown": self.pageDown,
1545                 }, -1)
1546
1547                 self.PartnerboxEntry = partnerboxentry
1548                 self.password = partnerboxentry.password.value
1549                 self.username = "root"
1550                 self.ip = "%d.%d.%d.%d" % tuple(partnerboxentry.ip.value)
1551                 port = partnerboxentry.port.value
1552                 self.http = "http://%s:%d" % (self.ip,port)
1553                 self.enigma_type = int(partnerboxentry.enigma.value)
1554                 self.useinternal = int(partnerboxentry.useinternal.value)
1555
1556         def startRun(self):
1557                 name = self.epgdata.servicename
1558                 if name != "n/a":
1559                         self["channel"].setText(name)
1560                 else:
1561                         self["channel"].setText(_("unknown service"))
1562                 text = self.epgdata.eventtitle
1563                 short = self.epgdata.eventdescription
1564                 ext = self.epgdata.eventdescriptionextended
1565                 if len(short) > 0 and short != text:
1566                         text = text + '\n\n' + short
1567                 if len(ext) > 0:
1568                         if len(text) > 0:
1569                                 text = text + '\n\n'
1570                         text = text + ext
1571                 self.setTitle(self.epgdata.eventtitle)
1572                 self["epg_description"].setText(text)
1573                 endtime = int(self.epgdata.eventstart + self.epgdata.eventduration)
1574                 t = localtime(self.epgdata.eventstart)
1575                 datetime = ("%02d.%02d, %02d:%02d"%(t[2],t[1],t[3],t[4]))
1576                 duration = (" (%d " + _("mins")+")") % ((self.epgdata.eventduration ) / 60)
1577                 self["datetime"].setText(datetime)
1578                 self["duration"].setText(duration)
1579                 self["key_red"].setText("")     
1580
1581         def pageUp(self):
1582                 self["epg_description"].pageUp()
1583
1584         def pageDown(self):
1585                 self["epg_description"].pageDown()