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