update epg-description by left/right-actions
[enigma2-plugins.git] / merlinepg / src / plugin.py
1 #######################################################################
2 #
3 #    Merlin Programm Guide for Dreambox-Enigma2
4 #    Coded by Vali (c)2010
5 #    Support: www.dreambox-tools.info
6 #
7 #
8 #  This plugin is licensed under the Creative Commons 
9 #  Attribution-NonCommercial-ShareAlike 3.0 Unported License.
10 #  To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
11 #  or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
12 #
13 #  Alternatively, this plugin may be distributed and executed on hardware which
14 #  is licensed by Dream Multimedia GmbH.
15 #
16 #
17 #  This plugin is NOT free software. It is open source, you are allowed to
18 #  modify it (if you keep the license), but it may not be commercially 
19 #  distributed other than under the conditions noted above.
20 #
21 #
22 #######################################################################
23
24
25
26 from Plugins.Plugin import PluginDescriptor
27 from Screens.Screen import Screen
28 from Screens.EventView import EventViewSimple
29 from Screens.MessageBox import MessageBox
30 from Screens.TimerEntry import TimerEntry
31 from Screens.TimerEdit import TimerSanityConflict
32 from Components.ConfigList import ConfigListScreen
33 from Components.ActionMap import ActionMap
34 from Components.MenuList import MenuList
35 from Components.Label import Label
36 from Components.EpgList import EPGList, EPG_TYPE_SINGLE, Rect
37 from Components.config import config, ConfigSubsection, ConfigYesNo, ConfigInteger, getConfigListEntry
38 from Tools.Directories import resolveFilename, SCOPE_CURRENT_SKIN
39 from Tools.LoadPixmap import LoadPixmap
40 from enigma import eServiceReference, eServiceCenter, getDesktop, eTimer, gFont, eListboxPythonMultiContent, RT_HALIGN_LEFT, RT_WRAP
41 from RecordTimer import RecordTimerEntry, parseEvent, AFTEREVENT
42 from ServiceReference import ServiceReference
43 from ShowMe import ShowMe
44 from time import localtime
45
46
47
48 config.plugins.MerlinEPG = ConfigSubsection()
49 config.plugins.MerlinEPG.Columns = ConfigYesNo(default=True)
50 config.plugins.MerlinEPG.StartFirst = ConfigYesNo(default=False)
51 config.plugins.MerlinEPG.Primetime  = ConfigInteger(default=20, limits=(0, 23))
52 config.plugins.MerlinEPG.PTlow  = ConfigInteger(default=10, limits=(0, 59))
53 config.plugins.MerlinEPG.PThi  = ConfigInteger(default=20, limits=(0, 59))
54 config.plugins.MerlinEPG.AutoPT  = ConfigYesNo(default=False)
55 config.plugins.MerlinEPG.ZapOnOK  = ConfigYesNo(default=False)
56 config.plugins.MerlinEPG.PageUDonBouquets  = ConfigYesNo(default=True)
57
58
59
60 def Plugins(**kwargs):
61         list = [(PluginDescriptor(name="Merlin Programm Guide", description="Merlin Programm Guide", where = PluginDescriptor.WHERE_EVENTINFO, fnc=startMerlinPG))]
62         list.append(PluginDescriptor(name="Merlin Programm Guide", where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=startMerlinPG))
63         return list
64
65
66
67 def startMerlinPG(session, servicelist, **kwargs):
68         if config.plugins.MerlinEPG.Columns.value:
69                 session.open(Merlin_PGII, servicelist)
70         else:
71                 session.open(Merlin_PGd, servicelist)
72
73
74
75 class MerlinPGsetup(ConfigListScreen, Screen):
76         skin = """
77                 <screen position="center,center" size="600,300" title="Merlin Programm Guide">
78                         <widget name="config" position="10,10" size="580,280" scrollbarMode="showOnDemand" />
79                 </screen>"""
80
81         def __init__(self, session):
82                 Screen.__init__(self, session)
83                 clist = []
84                 clist.append(getConfigListEntry(_("Show EPG in columns:"), config.plugins.MerlinEPG.Columns))
85                 clist.append(getConfigListEntry(_("Start allways on channel 1:"), config.plugins.MerlinEPG.StartFirst))
86                 clist.append(getConfigListEntry(_("Primetime (h):"), config.plugins.MerlinEPG.Primetime))
87                 clist.append(getConfigListEntry(_("Primetime from (m):"), config.plugins.MerlinEPG.PTlow))
88                 clist.append(getConfigListEntry(_("Primetime to (m):"), config.plugins.MerlinEPG.PThi))
89                 clist.append(getConfigListEntry(_("Auto-Primetime:"), config.plugins.MerlinEPG.AutoPT))
90                 clist.append(getConfigListEntry(_("Zap with OK button (false=EventInfo):"), config.plugins.MerlinEPG.ZapOnOK))
91                 clist.append(getConfigListEntry(_("Page-up/down with bouquet+/- :"), config.plugins.MerlinEPG.PageUDonBouquets))
92                 ConfigListScreen.__init__(self, clist)
93                 self["actions"] = ActionMap(["OkCancelActions"], {"ok": self.set, "cancel": self.exit}, -2)
94
95         def set(self):
96                 if not config.plugins.MerlinEPG.PThi.value > config.plugins.MerlinEPG.PTlow.value:
97                         return
98                 for x in self["config"].list:
99                         x[1].save()
100                 self.close()
101
102         def exit(self):
103                 for x in self["config"].list:
104                         x[1].cancel()
105                 self.close()
106
107
108
109 class MerlinEPGList(EPGList):
110         def __init__(self, type=EPG_TYPE_SINGLE, selChangedCB=None, timer = None):
111                 EPGList.__init__(self, type, selChangedCB, timer)
112                 self.l.setFont(0, gFont("Regular", 18))
113                 self.PTpicture = LoadPixmap(cached=True, path="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/primetime.png")
114                 self.evCnt = 0
115
116         def recalcEntrySize(self):
117                 esize = self.l.getItemSize()
118                 width = esize.width()
119                 height = esize.height()
120                 self.weekday_rect = Rect(120, -10, 200, 20)
121                 self.datetime_rect = Rect(0, 0, 120, 20)
122                 self.descr_rect = Rect(0, 22, width, height-23)
123                 self.evCnt = 0
124
125         def buildSingleEntry(self, service, eventId, beginTime, duration, EventName):
126                 (clock_pic, rec) = self.getPixmapForEntry(service, eventId, beginTime, duration)
127                 r1=self.weekday_rect
128                 r2=self.datetime_rect
129                 r3=self.descr_rect
130                 t = localtime(beginTime)
131                 self.evCnt = self.evCnt + 1
132                 if (t[3]==config.plugins.MerlinEPG.Primetime.value) and (t[4]>=config.plugins.MerlinEPG.PTlow.value) and (t[4]<config.plugins.MerlinEPG.PThi.value):
133                         res = [
134                                 None,
135                                 (eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width(), r1.height(), 0, RT_HALIGN_LEFT, "  _________________"),
136                                 (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, 100, 1, 21, 21, self.PTpicture),
137                                 (eListboxPythonMultiContent.TYPE_TEXT, r2.left(), r2.top(), r2.width(), r1.height(), 0, RT_HALIGN_LEFT, (("%02d:%02d"%(t[3],t[4]))+" - "+self.days[t[6]]))
138                         ]
139                 else:
140                         res = [
141                                 None,
142                                 (eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width(), r1.height(), 0, RT_HALIGN_LEFT, "___________________"),
143                                 (eListboxPythonMultiContent.TYPE_TEXT, r2.left(), r2.top(), r2.width(), r1.height(), 0, RT_HALIGN_LEFT, (("%02d:%02d"%(t[3],t[4]))+" - "+self.days[t[6]]))
144                         ]
145                 if rec:
146                         res.extend((
147                                 (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left(), r3.top(), 21, 21, clock_pic),
148                                 (eListboxPythonMultiContent.TYPE_TEXT, r3.left() + 25, r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT|RT_WRAP, EventName)
149                         ))
150                 else:
151                         res.append((eListboxPythonMultiContent.TYPE_TEXT, r3.left(), r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT|RT_WRAP, EventName))
152                 return res
153
154         def getBgTime(self):
155                 tmp = self.l.getCurrentSelection()
156                 if tmp is None:
157                         return ( None )
158                 bt = localtime(tmp[2])
159                 return ( bt[3], bt[4] )
160
161         def foudPrimetime(self):
162                 for OneLine in range(0,self.evCnt):
163                         evBgTime, evBgMin = self.getBgTime()
164                         if evBgTime is not None:
165                                 if (evBgTime==config.plugins.MerlinEPG.Primetime.value) and (evBgMin>=config.plugins.MerlinEPG.PTlow.value) and (evBgMin<config.plugins.MerlinEPG.PThi.value):
166                                         break
167                                 self.moveDown()
168                         else:
169                                 break
170
171
172
173 class Merlin_PGII(Screen):
174         sz_w = getDesktop(0).size().width()
175         if sz_w == 1280:
176                 skin = """
177                 <screen flags="wfNoBorder" name="Merlin_PG" position="0,0" size="1280,720" title="Merlin Program Guide">
178                 <!-- DO NOT CHANGE THIS LINE !!!!!!!!!!!!!!! --><widget enableWrapAround="0" itemHeight="25" name="prg_list" position="-200,-200" size="50,125"/>
179                         <widget font="Regular;18" halign="center" valign="center" name="currCh1" position="60,40" size="231,24" transparent="1" zPosition="2"/>
180                         <widget font="Regular;18" halign="center" valign="center" name="currCh2" position="291,40" size="231,24" transparent="1" zPosition="2"/>
181                         <widget font="Regular;18" halign="center" valign="center" name="currCh3" position="522,40" size="231,24" transparent="1" zPosition="2"/>
182                         <widget font="Regular;18" halign="center" valign="center" name="currCh4" position="753,40" size="231,24" transparent="1" zPosition="2"/>
183                         <widget font="Regular;18" halign="center" valign="center" name="currCh5" position="984,40" size="231,24" transparent="1" zPosition="2"/>
184                         <widget backgroundColor="#10444649" name="Active1" position="60,80" size="225,560" transparent="0" zPosition="3"/>
185                         <widget backgroundColor="#10444649" name="Active2" position="291,80" size="225,560" transparent="0" zPosition="3"/>
186                         <widget backgroundColor="#10444649" name="Active3" position="522,80" size="225,560" transparent="0" zPosition="3"/>
187                         <widget backgroundColor="#10444649" name="Active4" position="753,80" size="225,560" transparent="0" zPosition="3"/>
188                         <widget backgroundColor="#10444649" name="Active5" position="984,80" size="225,560" transparent="0" zPosition="3"/>
189                         <widget itemHeight="70" name="epg_list1" position="60,80" scrollbarMode="showOnDemand" size="225,560" transparent="1" zPosition="4"/>
190                         <widget itemHeight="70" name="epg_list2" position="291,80" scrollbarMode="showOnDemand" size="225,560" transparent="1" zPosition="4"/>
191                         <widget itemHeight="70" name="epg_list3" position="522,80" scrollbarMode="showOnDemand" size="225,560" transparent="1" zPosition="4"/>
192                         <widget itemHeight="70" name="epg_list4" position="753,80" scrollbarMode="showOnDemand" size="225,560" transparent="1" zPosition="4"/>
193                         <widget itemHeight="70" name="epg_list5" position="984,80" scrollbarMode="showOnDemand" size="225,560" transparent="1" zPosition="4"/>
194                         <ePixmap pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/buttons.png" position="60,655" size="430,24"/>
195                         <widget backgroundColor="background" font="Regular;18" foregroundColor="#ffc000" position="500,655" render="Label" size="200,24" source="global.CurrentTime" transparent="1" valign="center" zPosition="3">     
196                                 <convert type="ClockToText">Format:%H:%M  %a %d. %b</convert>
197                         </widget>
198                 </screen>"""
199         elif sz_w == 1024:
200                 skin = """
201                 <screen flags="wfNoBorder" name="Merlin_PG" position="0,0" size="1024,576" title="Merlin Program Guide">
202                 <!-- DO NOT CHANGE THIS LINE !!!!!!!!!!!!!!! --><widget enableWrapAround="0" itemHeight="25" name="prg_list" position="-200,-200" size="50,100"/>
203                         <widget font="Regular;18" halign="center" valign="center" name="currCh1" position="50,40" size="231,24" transparent="1" zPosition="2"/>
204                         <widget font="Regular;18" halign="center" valign="center" name="currCh2" position="281,40" size="231,24" transparent="1" zPosition="2"/>
205                         <widget font="Regular;18" halign="center" valign="center" name="currCh3" position="512,40" size="231,24" transparent="1" zPosition="2"/>
206                         <widget font="Regular;18" halign="center" valign="center" name="currCh4" position="743,40" size="231,24" transparent="1" zPosition="2"/>
207                         <widget backgroundColor="#10444649" name="Active1" position="50,80" size="225,420" transparent="0" zPosition="3"/>
208                         <widget backgroundColor="#10444649" name="Active2" position="281,80" size="225,420" transparent="0" zPosition="3"/>
209                         <widget backgroundColor="#10444649" name="Active3" position="512,80" size="225,420" transparent="0" zPosition="3"/>
210                         <widget backgroundColor="#10444649" name="Active4" position="743,80" size="225,420" transparent="0" zPosition="3"/>
211                         <widget itemHeight="70" name="epg_list1" position="50,80" scrollbarMode="showOnDemand" size="225,420" transparent="1" zPosition="4"/>
212                         <widget itemHeight="70" name="epg_list2" position="281,80" scrollbarMode="showOnDemand" size="225,420" transparent="1" zPosition="4"/>
213                         <widget itemHeight="70" name="epg_list3" position="512,80" scrollbarMode="showOnDemand" size="225,420" transparent="1" zPosition="4"/>
214                         <widget itemHeight="70" name="epg_list4" position="743,80" scrollbarMode="showOnDemand" size="225,420" transparent="1" zPosition="4"/>
215                         <ePixmap pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/buttons.png" position="50,518" size="430,24"/>
216                         <widget backgroundColor="background" font="Regular;18" foregroundColor="#ffc000" position="490,518" render="Label" size="200,24" source="global.CurrentTime" transparent="1" valign="center" zPosition="3">     
217                                 <convert type="ClockToText">Format:%H:%M  %a %d. %b</convert>
218                         </widget>
219                         <!-- <widget font="Regular;18" name="fullEventInfo" position="300,200" size="300,200" transparent="0" zPosition="12"/> -->
220                 </screen>"""
221         else:
222                 skin = """
223                 <screen flags="wfNoBorder" name="Merlin_PG" position="0,0" size="720,576" title="Merlin Program Guide">
224                 <!-- DO NOT CHANGE THIS LINE !!!!!!!!!!!!!!! --><widget enableWrapAround="0" itemHeight="25" name="prg_list" position="-200,-200" size="50,100"/>
225                         <widget font="Regular;18" halign="center" valign="center" name="currCh1" position="50,35" size="155,36" transparent="1" zPosition="2"/>
226                         <widget font="Regular;18" halign="center" valign="center" name="currCh2" position="205,35" size="155,36" transparent="1" zPosition="2"/>
227                         <widget font="Regular;18" halign="center" valign="center" name="currCh3" position="360,35" size="155,36" transparent="1" zPosition="2"/>
228                         <widget font="Regular;18" halign="center" valign="center" name="currCh4" position="515,35" size="155,36" transparent="1" zPosition="2"/>
229                         <widget backgroundColor="#10444649" name="Active1" position="50,90" size="155,420" transparent="0" zPosition="3"/>
230                         <widget backgroundColor="#10444649" name="Active2" position="205,90" size="155,420" transparent="0" zPosition="3"/>
231                         <widget backgroundColor="#10444649" name="Active3" position="360,90" size="155,420" transparent="0" zPosition="3"/>
232                         <widget backgroundColor="#10444649" name="Active4" position="515,90" size="155,420" transparent="0" zPosition="3"/>
233                         <widget itemHeight="70" name="epg_list1" position="50,90" scrollbarMode="showOnDemand" size="155,420" transparent="1" zPosition="4"/>
234                         <widget itemHeight="70" name="epg_list2" position="205,90" scrollbarMode="showOnDemand" size="155,420" transparent="1" zPosition="4"/>
235                         <widget itemHeight="70" name="epg_list3" position="360,90" scrollbarMode="showOnDemand" size="155,420" transparent="1" zPosition="4"/>
236                         <widget itemHeight="70" name="epg_list4" position="515,90" scrollbarMode="showOnDemand" size="155,420" transparent="1" zPosition="4"/>
237                         <ePixmap pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/buttons.png" position="50,518" size="430,24"/>
238                         <widget backgroundColor="background" font="Regular;18" foregroundColor="#ffc000" position="490,518" render="Label" size="200,24" source="global.CurrentTime" transparent="1" valign="center" zPosition="3">     
239                                 <convert type="ClockToText">Format:%H:%M  %a %d. %b</convert>
240                         </widget>
241                 </screen>"""
242
243         def __init__(self, session, servicelist):
244                 Screen.__init__(self, session)
245                 self.session = session
246                 self.srvList = servicelist
247                 self.myServices = []
248                 self.myBqts = []
249                 self.list = []
250                 self.chCount = 0
251                 self.ActiveEPG = 1
252                 if getDesktop(0).size().width() == 1280:
253                         self.Fields = 6
254                         self["currCh5"] = Label(" ")
255                         self["Active5"] = Label(" ")
256                         self["epg_list5"] = MerlinEPGList(type = EPG_TYPE_SINGLE, selChangedCB = self.onSelectionChanged, timer = session.nav.RecordTimer)
257                 else:
258                         self.Fields = 5
259                 self.CheckForEPG = eTimer()
260                 self.CheckForEPG.callback.append(self.CheckItNow)
261                 self.AutoPrime = eTimer()
262                 self.AutoPrime.callback.append(self.go2Primetime)
263                 self["prg_list"] = MenuList(self.getChannels())
264                 self["fullEventInfo"] = Label(" ")
265                 self["currCh1"] = Label(" ")
266                 self["currCh2"] = Label(" ")
267                 self["currCh3"] = Label(" ")
268                 self["currCh4"] = Label(" ")
269                 self["Active1"] = Label(" ")
270                 self["Active2"] = Label(" ")
271                 self["Active3"] = Label(" ")
272                 self["Active4"] = Label(" ")
273                 self["epg_list1"] = MerlinEPGList(type = EPG_TYPE_SINGLE, selChangedCB = self.onSelectionChanged, timer = session.nav.RecordTimer)
274                 self["epg_list2"] = MerlinEPGList(type = EPG_TYPE_SINGLE, selChangedCB = self.onSelectionChanged, timer = session.nav.RecordTimer)
275                 self["epg_list3"] = MerlinEPGList(type = EPG_TYPE_SINGLE, selChangedCB = self.onSelectionChanged, timer = session.nav.RecordTimer)
276                 self["epg_list4"] = MerlinEPGList(type = EPG_TYPE_SINGLE, selChangedCB = self.onSelectionChanged, timer = session.nav.RecordTimer)
277                 self["actions"] = ActionMap(["OkCancelActions", "EPGSelectActions", "DirectionActions", "ColorActions", "MenuActions", "NumberActions", "HelpActions"], {
278                                                 "ok": self.UserOK, 
279                                                 "cancel": self.close,
280                                                 "nextBouquet": self.AllUp,
281                                                 "prevBouquet": self.AllDown,
282                                                 "nextService": self.NextPage,
283                                                 "prevService": self.PrevPage,
284                                                 "right": self.right,
285                                                 "rightRepeated": self.right,
286                                                 "left": self.left,
287                                                 "leftRepeated": self.left,
288                                                 "up": self.up,
289                                                 "upRepeated": self.up,
290                                                 "down": self.down,
291                                                 "downRepeated": self.down,
292                                                 "info": self.showEventInfo,
293                                                 "red": self.ZapTo,
294                                                 "green": self.timerAdd,
295                                                 "blue": self.ZapForRefresh,
296                                                 "yellow": self.go2Primetime,
297                                                 "menu": self.menuClicked,
298                                                 "displayHelp": self.myhelp,
299                                                 "0": self.go2now,
300                                                 "1": self.go2first,
301                                                 "7": self.findPrvBqt,
302                                                 "9": self.findNextBqt
303                                                 },-2)
304                 self.onLayoutFinish.append(self.onLayoutReady)
305
306         def getChannels(self):
307                 indx = 0
308                 serviceHandler = eServiceCenter.getInstance()
309                 services = serviceHandler.list(eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25) FROM BOUQUET "bouquets.tv" ORDER BY bouquet'))
310                 bouquets = services and services.getContent("SN", True)
311                 for bouquet in bouquets:
312                         services = serviceHandler.list(eServiceReference(bouquet[0]))
313                         channels = services and services.getContent("SN", True)
314                         for channel in channels:
315                                 if not channel[0].startswith("1:64:"):
316                                         indx = indx + 1
317                                         self.list.append(str(indx) + ". " + channel[1].replace('\xc2\x86', '').replace('\xc2\x87', ''))
318                                         self.myServices.append(channel)
319                                         self.myBqts.append(bouquet)
320                 self.chCount = indx - 1
321                 return self.list
322
323         def onLayoutReady(self):
324                 service = self.session.nav.getCurrentService()
325                 info = service and service.info()
326                 if (info is not None) and not(config.plugins.MerlinEPG.StartFirst.value):
327                         nameROH = info.getName().replace('\xc2\x86', '').replace('\xc2\x87', '')
328                         for idx in range(1, len(self.list)):
329                                 name = str(idx) + ". " + nameROH
330                                 if name == self.list[idx-1]:
331                                         break
332                         self["prg_list"].moveToIndex(idx-1)
333                 else:
334                         self["prg_list"].moveToIndex(0)
335                 self.updateInfos()
336
337         def updateInfos(self):
338                 if self.AutoPrime.isActive():
339                         self.AutoPrime.stop()
340                 self.displayActiveEPG()
341                 prgIndex = self["prg_list"].getSelectionIndex()
342                 CurrentPrg = self.myServices[prgIndex]
343                 self["currCh1"].setText(str(CurrentPrg[1]))
344                 l = self["epg_list1"]
345                 l.recalcEntrySize()
346                 myService = ServiceReference(CurrentPrg[0])
347                 l.fillSingleEPG(myService)
348                 prgIndex = prgIndex + 1
349                 if prgIndex < (self.chCount+1):
350                         self["epg_list2"].show()
351                         CurrentPrg = self.myServices[prgIndex]
352                         self["currCh2"].setText(str(CurrentPrg[1]))
353                         l = self["epg_list2"]
354                         l.recalcEntrySize()
355                         myService = ServiceReference(CurrentPrg[0])
356                         l.fillSingleEPG(myService)
357                 else:
358                         self["currCh2"].setText(str(" "))
359                         self["epg_list2"].hide()
360                 prgIndex = prgIndex + 1
361                 if prgIndex < (self.chCount+1):
362                         self["epg_list3"].show()
363                         CurrentPrg = self.myServices[prgIndex]
364                         self["currCh3"].setText(str(CurrentPrg[1]))
365                         l = self["epg_list3"]
366                         l.recalcEntrySize()
367                         myService = ServiceReference(CurrentPrg[0])
368                         l.fillSingleEPG(myService)
369                 else:
370                         self["currCh3"].setText(str(" "))
371                         self["epg_list3"].hide()
372                 prgIndex = prgIndex + 1
373                 if prgIndex < (self.chCount+1):
374                         self["epg_list4"].show()
375                         CurrentPrg = self.myServices[prgIndex]
376                         self["currCh4"].setText(str(CurrentPrg[1]))
377                         CurrentPrg = self.myServices[prgIndex]
378                         self["currCh4"].setText(str(CurrentPrg[1]))
379                         l = self["epg_list4"]
380                         l.recalcEntrySize()
381                         myService = ServiceReference(CurrentPrg[0])
382                         l.fillSingleEPG(myService)
383                 else:
384                         self["currCh4"].setText(str(" "))
385                         self["epg_list4"].hide()
386                 if self.Fields == 6:
387                         prgIndex = prgIndex + 1
388                         if prgIndex < (self.chCount+1):
389                                 self["epg_list5"].show()
390                                 CurrentPrg = self.myServices[prgIndex]
391                                 self["currCh5"].setText(str(CurrentPrg[1]))
392                                 l = self["epg_list5"]
393                                 l.recalcEntrySize()
394                                 myService = ServiceReference(CurrentPrg[0])
395                                 l.fillSingleEPG(myService)
396                         else:
397                                 self["currCh5"].setText(str(" "))
398                                 self["epg_list5"].hide()
399                 if config.plugins.MerlinEPG.AutoPT.value:
400                          self.AutoPrime.start(500)
401
402         def onSelectionChanged(self):           
403                 curEV = self["epg_list"+str(self.ActiveEPG)].getCurrent()
404                 event = curEV[0]
405                 ext = event and event.getExtendedDescription() or ""
406                 self["fullEventInfo"].setText(str(ext))
407
408         def NextPage(self):
409                 self["prg_list"].pageDown()
410                 self.ActiveEPG = 1
411                 self.updateInfos()
412
413         def PrevPage(self):
414                 self["prg_list"].pageUp()
415                 self.ActiveEPG = 1
416                 self.updateInfos()
417
418         def displayActiveEPG(self):
419                 for xA in range(1,self.Fields):
420                         if xA == self.ActiveEPG:
421                                 self["Active"+str(xA)].show()
422                         else:
423                                 self["Active"+str(xA)].hide()
424
425         def getActivePrg(self):
426                 return self["prg_list"].getSelectionIndex()+(self.ActiveEPG-1)
427
428         def ZapTo(self):
429                 if self.getActivePrg() > self.chCount:
430                         return
431                 CurrentPrg = self.myServices[self.getActivePrg()]
432                 CurrentBqt = self.myBqts[self.getActivePrg()]
433                 myService = ServiceReference(CurrentPrg[0])
434                 myB = ServiceReference(CurrentBqt[0])
435                 self.srvList.clearPath()
436                 if self.srvList.bouquet_root != myB.ref:
437                         self.srvList.enterPath(self.srvList.bouquet_root)
438                 self.srvList.enterPath(myB.ref)
439                 self.srvList.setCurrentSelection(myService.ref)
440                 self.srvList.zap()
441                 self.close()
442
443         def ZapForRefresh(self):
444                 if self.getActivePrg() > self.chCount:
445                         return
446                 CurrentPrg = self.myServices[self.getActivePrg()]
447                 myService = ServiceReference(CurrentPrg[0])
448                 self.session.nav.playService(myService.ref)
449                 self.CheckForEPG.start(4000, True)
450
451         def CheckItNow(self):
452                 self.CheckForEPG.stop()
453                 CurrentPrg = self.myServices[self.getActivePrg()]
454                 l = self["epg_list"+str(self.ActiveEPG)]
455                 l.recalcEntrySize()
456                 myService = ServiceReference(CurrentPrg[0])
457                 l.fillSingleEPG(myService)
458
459         def up(self):
460                 self["epg_list"+str(self.ActiveEPG)].moveUp()
461
462         def down(self):
463                 self["epg_list"+str(self.ActiveEPG)].moveDown()
464
465         def AllUp(self):
466                 if config.plugins.MerlinEPG.PageUDonBouquets.value:
467                         for xU in range(1,self.Fields):
468                                 self["epg_list"+str(xU)].instance.moveSelection(self["epg_list"+str(xU)].instance.pageUp)
469                 else:
470                         for xU in range(1,self.Fields):
471                                 self["epg_list"+str(xU)].moveUp()
472
473         def AllDown(self):
474                 if config.plugins.MerlinEPG.PageUDonBouquets.value:
475                         for xU in range(1,self.Fields):
476                                 self["epg_list"+str(xU)].instance.moveSelection(self["epg_list"+str(xU)].instance.pageDown)
477                 else:
478                         for xD in range(1,self.Fields):
479                                 self["epg_list"+str(xD)].moveDown()
480
481         def go2now(self):
482                 for xD in range(1,self.Fields):
483                         self["epg_list"+str(xD)].instance.moveSelection(self["epg_list"+str(xD)].instance.moveTop)
484
485         def go2first(self):
486                 self["prg_list"].moveToIndex(0)
487                 self.ActiveEPG = 1
488                 self.updateInfos()
489
490         def left(self):
491                 if self.ActiveEPG > 1:
492                         self.ActiveEPG = self.ActiveEPG - 1
493                         self.displayActiveEPG()
494                 else:
495                         self["prg_list"].pageUp()
496                         self.ActiveEPG = (self.Fields-1)
497                         self.updateInfos()
498                 self.onSelectionChanged()
499
500         def right(self):
501                 if self.ActiveEPG < (self.Fields-1):
502                         self.ActiveEPG = self.ActiveEPG + 1
503                         self.displayActiveEPG()
504                 else:
505                         self.NextPage()
506                 self.onSelectionChanged()
507
508         def showEventInfo(self):
509                 curEV = self["epg_list"+str(self.ActiveEPG)].getCurrent()
510                 event = curEV[0]
511                 service = curEV[1]
512                 if event is not None:
513                         self.session.open(EventViewSimple, event, service)
514
515         def timerAdd(self):
516                 cur = self["epg_list"+str(self.ActiveEPG)].getCurrent()
517                 event = cur[0]
518                 serviceref = cur[1]
519                 if event is None:
520                         return
521                 eventid = event.getEventId()
522                 refstr = serviceref.ref.toString()
523                 for timer in self.session.nav.RecordTimer.timer_list:
524                         if timer.eit == eventid and timer.service_ref.ref.toString() == refstr:
525                                 cb_func = lambda ret : not ret or self.removeTimer(timer)
526                                 self.session.openWithCallback(cb_func, MessageBox, _("Do you really want to delete %s?") % event.getEventName())
527                                 break
528                 else:
529                         newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, *parseEvent(event))
530                         self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry)
531
532         def removeTimer(self, timer):
533                 timer.afterEvent = AFTEREVENT.NONE
534                 self.session.nav.RecordTimer.removeEntry(timer)
535
536         def finishedAdd(self, answer):
537                 if answer[0]:
538                         entry = answer[1]
539                         simulTimerList = self.session.nav.RecordTimer.record(entry)
540                         if simulTimerList is not None:
541                                 for x in simulTimerList:
542                                         if x.setAutoincreaseEnd(entry):
543                                                 self.session.nav.RecordTimer.timeChanged(x)
544                                 simulTimerList = self.session.nav.RecordTimer.record(entry)
545                                 if simulTimerList is not None:
546                                         self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList)
547         
548         def finishSanityCorrection(self, answer):
549                 self.finishedAdd(answer)
550
551         def menuClicked(self):
552                 self.session.open(MerlinPGsetup)
553
554         def findNextBqt(self):
555                 CurrIdx = 0
556                 CurrBqt = self.myBqts[self.getActivePrg()]
557                 for CurrIdx in range(self.getActivePrg(),self.chCount):
558                         NewBqt = self.myBqts[CurrIdx]
559                         if NewBqt != CurrBqt:
560                                 break
561                 self["prg_list"].moveToIndex(CurrIdx)
562                 self.updateInfos()
563
564         def findPrvBqt(self):
565                 CurrIdx = 0
566                 CurrBqt = self.myBqts[self.getActivePrg()]
567                 for CurrIdx in range(self.getActivePrg(),-1,-1):
568                         NewBqt = self.myBqts[CurrIdx]
569                         if NewBqt != CurrBqt:
570                                 break
571                 self["prg_list"].moveToIndex(CurrIdx)
572                 self.updateInfos()
573
574         def go2Primetime(self):
575                 if self.AutoPrime.isActive():
576                         self.AutoPrime.stop()
577                 for xFL in range(1, self.Fields):
578                         self["epg_list"+str(xFL)].instance.moveSelection(self["epg_list"+str(xFL)].instance.moveTop)
579                         for i in range(0,(self.Fields*3)):
580                                 self["epg_list"+str(xFL)].foudPrimetime()
581
582         def myhelp(self):
583                 self.session.open(ShowMe, "/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/help.jpg")
584
585         def UserOK(self):
586                 if config.plugins.MerlinEPG.ZapOnOK.value:
587                         self.ZapTo()
588                 else:
589                         self.showEventInfo()
590
591
592
593 class Merlin_PGd(Screen):
594         try:
595                 sz_w = getDesktop(0).size().width()
596         except:
597                 sz_w = 720
598         if sz_w == 1280:
599                 skin = """
600                 <screen backgroundColor="#ffffffff" flags="wfNoBorder" name="Merlin_PG" position="0,0" size="1280,720" title="Merlin Program Guide">
601                         <widget backgroundColor="#ffffffff" position="0,0" render="Pig" size="520,292" source="session.VideoPicture" zPosition="-1"/>
602                         <eLabel backgroundColor="#00111112" position="0,292" size="520,450" zPosition="1"/>
603                         <eLabel backgroundColor="#00111112" position="520,0" size="760,720" zPosition="1"/>
604                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/epg.png" position="1136,105" size="85,77" zPosition="5"/>
605                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/channels.png" position="395,306" size="80,80" zPosition="5"/>
606                         <ePixmap alphatest="on" name="red" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/red.png" position="70,635" size="35,25" zPosition="2"/>
607                         <ePixmap alphatest="on" name="green" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/green.png" position="275,635" size="35,25" zPosition="2"/>
608                         <eLabel backgroundColor="#00111112" font="Regular;18" position="110,635" size="131,24" text="ZAP" transparent="1" zPosition="2"/>
609                         <eLabel backgroundColor="#00111112" font="Regular;18" position="315,635" size="191,24" text="TIMERS" transparent="1" zPosition="2"/>
610                         <widget itemHeight="25" name="prg_list" position="75,306" scrollbarMode="showNever" size="400,300" transparent="1" zPosition="4"/>
611                         <widget itemHeight="27" name="epg_list" position="570,105" scrollbarMode="showNever" size="651,540" transparent="1" zPosition="4"/>
612                         <widget backgroundColor="#00111112" font="Regular;22" foregroundColor="#fcc000" halign="center" name="currCh" position="555,55" size="651,24" transparent="1" valign="center" zPosition="2"/>
613                 </screen>"""
614         elif sz_w == 1024:
615                 skin = """
616                 <screen backgroundColor="#ffffffff" flags="wfNoBorder" name="Merlin_PG" position="0,0" size="1024,576" title="Merlin Program Guide">
617                         <widget backgroundColor="#ffffffff" position="0,0" render="Pig" size="384,216" source="session.VideoPicture" zPosition="-1"/>
618                         <eLabel backgroundColor="#00111112" position="0,216" size="384,366" zPosition="1"/>
619                         <eLabel backgroundColor="#00111112" position="384,0" size="720,576" zPosition="1"/>
620                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/epg.png" position="900,80" size="85,77" zPosition="5"/>
621                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/channels.png" position="292,228" size="80,80" zPosition="5"/>
622                         <ePixmap alphatest="on" name="red" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/red.png" position="40,520" size="35,25" zPosition="3"/>
623                         <ePixmap alphatest="on" name="green" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/green.png" position="185,520" size="35,25" zPosition="3"/>
624                         <eLabel backgroundColor="#00111112" font="Regular;18" position="80,520" size="92,24" text="ZAP" transparent="1" zPosition="2"/>
625                         <eLabel backgroundColor="#00111112" font="Regular;18" position="230,520" size="141,24" text="TIMERS" transparent="1" zPosition="2"/>
626                         <widget itemHeight="25" name="prg_list" position="40,228" scrollbarMode="showNever" size="332,275" transparent="1" zPosition="4"/>
627                         <widget itemHeight="28" name="epg_list" position="395,80" scrollbarMode="showNever" size="590,448" transparent="1" zPosition="4"/>
628                         <widget backgroundColor="#00111112" font="Regular;21" foregroundColor="#fcc000" halign="center" name="currCh" position="395,40" size="590,24" transparent="1" valign="center" zPosition="4"/>
629                 </screen>"""
630         else:
631                 skin = """
632                 <screen flags="wfNoBorder" name="Merlin_PG" position="0,0" size="720,576" title="Merlin Program Guide">
633                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/mpgbgSD-fs8.png" position="0,0" size="720,576" zPosition="1"/>
634                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/red.png" position="165,90" size="35,25" zPosition="2"/>
635                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/green.png" position="165,110" size="35,25" zPosition="2"/>
636                         <eLabel backgroundColor="#1f1f1f" font="Regular;15" foregroundColor="#f0f0f0" position="205,93" size="70,20" text="ZAP" transparent="1" zPosition="2"/>
637                         <eLabel backgroundColor="#1f1f1f" font="Regular;15" foregroundColor="#f0f0f0" position="205,113" size="70,20" text="TIMERS" transparent="1" zPosition="2"/>
638                         <widget name="prg_list" position="342,63" scrollbarMode="showOnDemand" size="327,150" zPosition="2" itemHeight="25"/>
639                         <widget name="epg_list" position="57,238" scrollbarMode="showOnDemand" size="612,270" zPosition="2" itemHeight="27"/>
640                         <widget font="Regular;22" foregroundColor="#ffc000" halign="center" name="currCh" position="57,133" size="252,66" transparent="1" valign="center" zPosition="2"/>
641                         <widget font="LCD;28" halign="left" position="60,95" render="Label" size="91,32" source="global.CurrentTime" transparent="1" zPosition="3">
642                                 <convert type="ClockToText">Default</convert>
643                         </widget>       
644                         <widget font="Regular;16" position="60,65" render="Label" size="276,26" source="global.CurrentTime" transparent="1" zPosition="3">
645                                 <convert type="ClockToText">Date</convert>
646                         </widget>
647                 </screen>"""
648
649         def __init__(self, session, servicelist):
650                 Screen.__init__(self, session)
651                 self.session = session
652                 self.myServices = []
653                 self.myBqts = []
654                 self.list = []
655                 self.srvList = servicelist
656                 self.CheckForEPG = eTimer()
657                 self.CheckForEPG.callback.append(self.CheckItNow)
658                 self["currCh"] = Label(_("Channel"))
659                 self["fullEventInfo"] = Label(" ")
660                 self["prg_list"] = MenuList(self.getChannels())
661                 self["epg_list"] = EPGList(type = EPG_TYPE_SINGLE, selChangedCB = self.onSelectionChanged, timer = session.nav.RecordTimer)
662                 self["actions"] = ActionMap(["OkCancelActions", "EPGSelectActions", "ColorActions", "DirectionActions", "MenuActions", "HelpActions"], {
663                                                                         "ok": self.ok, 
664                                                                         "cancel": self.close,
665                                                                         "nextBouquet": self.prgDown,
666                                                                         "prevBouquet": self.prgUp,
667                                                                         "nextService": self.prgPlus,
668                                                                         "prevService": self.prgMinus,
669                                                                         "red": self.ZapTo,
670                                                                         "green": self.timerAdd,
671                                                                         "blue": self.ZapForRefresh,
672                                                                         "yellow": self.go2now,
673                                                                         "info": self.ok,
674                                                                         "menu": self.menuClicked,
675                                                                         "displayHelp": self.myhelp,
676                                                                         "right": self.right,
677                                                                         "rightRepeated": self.right,
678                                                                         "left": self.left,
679                                                                         "leftRepeated": self.left,
680                                                                         "up": self.up,
681                                                                         "upRepeated": self.up,
682                                                                         "down": self.down,
683                                                                         "downRepeated": self.down,
684                                                                         },-2)
685                 self.onLayoutFinish.append(self.onLayoutReady)
686
687         def onLayoutReady(self):
688                 service = self.session.nav.getCurrentService()
689                 info = service and service.info()
690                 if (info is not None) and not(config.plugins.MerlinEPG.StartFirst.value):
691                         nameROH = info.getName().replace('\xc2\x86', '').replace('\xc2\x87', '')
692                         for idx in range(1, len(self.list)):
693                                 name = str(idx) + ". " + nameROH
694                                 if name == self.list[idx-1]:
695                                         break
696                         self["prg_list"].moveToIndex(idx-1)
697                 else:
698                         self["prg_list"].moveToIndex(0)
699                 self.updateInfos()
700
701         def onSelectionChanged(self):
702                 curEV = self["epg_list"].getCurrent()
703                 event = curEV[0]
704                 ext = event and event.getExtendedDescription() or ""
705                 self["fullEventInfo"].setText(str(ext))
706
707         def prgUp(self):
708                 self["prg_list"].down()
709                 self.updateInfos()
710         
711         def prgDown(self):
712                 self["prg_list"].up()
713                 self.updateInfos()
714
715         def prgPlus(self):
716                 self["prg_list"].pageDown()
717                 self.updateInfos()
718
719         def prgMinus(self):
720                 self["prg_list"].pageUp()
721                 self.updateInfos()
722
723         def getChannels(self):
724                 indx = 0
725                 serviceHandler = eServiceCenter.getInstance()
726                 services = serviceHandler.list(eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) || (type == 17) || (type == 195) || (type == 25) FROM BOUQUET "bouquets.tv" ORDER BY bouquet'))
727                 bouquets = services and services.getContent("SN", True)
728                 for bouquet in bouquets:
729                         services = serviceHandler.list(eServiceReference(bouquet[0]))
730                         channels = services and services.getContent("SN", True)
731                         for channel in channels:
732                                 if not channel[0].startswith("1:64:"):
733                                         indx = indx + 1
734                                         self.list.append(str(indx) + ". " + channel[1].replace('\xc2\x86', '').replace('\xc2\x87', ''))
735                                         self.myServices.append(channel)
736                                         self.myBqts.append(bouquet)
737                 return self.list
738
739         def updateInfos(self):
740                 l = self["epg_list"]
741                 l.recalcEntrySize()
742                 CurrentPrg = self.myServices[self["prg_list"].getSelectionIndex()]
743                 self["currCh"].setText(str(CurrentPrg[1]))
744                 myService = ServiceReference(CurrentPrg[0])
745                 l.fillSingleEPG(myService)
746
747         def ok(self):
748                 curEV = self["epg_list"].getCurrent()
749                 event = curEV[0]
750                 service = curEV[1]
751                 if event is not None:
752                         self.session.open(EventViewSimple, event, service)
753                         
754         def ZapTo(self):
755                 CurrentPrg = self.myServices[self["prg_list"].getSelectionIndex()]
756                 CurrentBqt = self.myBqts[self["prg_list"].getSelectionIndex()]
757                 myService = ServiceReference(CurrentPrg[0])
758                 myB = ServiceReference(CurrentBqt[0])
759                 self.srvList.clearPath()
760                 if self.srvList.bouquet_root != myB.ref:
761                         self.srvList.enterPath(self.srvList.bouquet_root)
762                 self.srvList.enterPath(myB.ref)
763                 self.srvList.setCurrentSelection(myService.ref)
764                 self.srvList.zap()
765                 self.close()
766
767         def ZapForRefresh(self):
768                 CurrentPrg = self.myServices[self["prg_list"].getSelectionIndex()]
769                 myService = ServiceReference(CurrentPrg[0])
770                 self.session.nav.playService(myService.ref)
771                 self.CheckForEPG.start(4000, True)
772
773         def CheckItNow(self):
774                 self.CheckForEPG.stop()
775                 self.updateInfos()
776
777         def timerAdd(self):
778                 cur = self["epg_list"].getCurrent()
779                 event = cur[0]
780                 serviceref = cur[1]
781                 if event is None:
782                         return
783                 eventid = event.getEventId()
784                 refstr = serviceref.ref.toString()
785                 for timer in self.session.nav.RecordTimer.timer_list:
786                         if timer.eit == eventid and timer.service_ref.ref.toString() == refstr:
787                                 cb_func = lambda ret : not ret or self.removeTimer(timer)
788                                 self.session.openWithCallback(cb_func, MessageBox, _("Do you really want to delete %s?") % event.getEventName())
789                                 break
790                 else:
791                         newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, *parseEvent(event))
792                         self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry)
793
794         def removeTimer(self, timer):
795                 timer.afterEvent = AFTEREVENT.NONE
796                 self.session.nav.RecordTimer.removeEntry(timer)
797
798         def finishedAdd(self, answer):
799                 if answer[0]:
800                         entry = answer[1]
801                         simulTimerList = self.session.nav.RecordTimer.record(entry)
802                         if simulTimerList is not None:
803                                 for x in simulTimerList:
804                                         if x.setAutoincreaseEnd(entry):
805                                                 self.session.nav.RecordTimer.timeChanged(x)
806                                 simulTimerList = self.session.nav.RecordTimer.record(entry)
807                                 if simulTimerList is not None:
808                                         self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList)
809
810         def finishSanityCorrection(self, answer):
811                 self.finishedAdd(answer)
812
813         def menuClicked(self):
814                 self.session.open(MerlinPGsetup)
815
816         def go2now(self):
817                 self["epg_list"].instance.moveSelection(self["epg_list"].instance.moveTop)
818
819         def myhelp(self):
820                 self.session.open(ShowMe, "/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/help.jpg")
821
822         def up(self):
823                 self["epg_list"].moveUp()
824
825         def down(self):
826                 self["epg_list"].moveDown()
827
828         def left(self):
829                 self["epg_list"].instance.moveSelection(self["epg_list"].instance.pageUp)
830
831         def right(self):
832                 self["epg_list"].instance.moveSelection(self["epg_list"].instance.pageDown)
833
834
835
836
837
838
839