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