Some new functions and settings implemented
[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.MerlinPG = ConfigSubsection()
49 config.plugins.MerlinPG.Columns = ConfigYesNo(default=True)
50 config.plugins.MerlinPG.StartFirst = ConfigYesNo(default=False)
51 config.plugins.MerlinPG.Primetime  = ConfigInteger(default=20, limits=(0, 23))
52 config.plugins.MerlinPG.PTlow  = ConfigInteger(default=10, limits=(0, 59))
53 config.plugins.MerlinPG.PThi  = ConfigInteger(default=20, limits=(0, 59))
54 config.plugins.MerlinPG.AutoPT  = ConfigYesNo(default=False)
55 config.plugins.MerlinPG.ZapOnOK  = ConfigYesNo(default=False)
56 config.plugins.MerlinPG.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.MerlinPG.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.MerlinPG.Columns))
85                 clist.append(getConfigListEntry(_("Start allways on channel 1:"), config.plugins.MerlinPG.StartFirst))
86                 clist.append(getConfigListEntry(_("Primetime (h):"), config.plugins.MerlinPG.Primetime))
87                 clist.append(getConfigListEntry(_("Primetime from (m):"), config.plugins.MerlinPG.PTlow))
88                 clist.append(getConfigListEntry(_("Primetime to (m):"), config.plugins.MerlinPG.PThi))
89                 clist.append(getConfigListEntry(_("Auto-Primetime:"), config.plugins.MerlinPG.AutoPT))
90                 clist.append(getConfigListEntry(_("Zap with OK button (false=EventInfo):"), config.plugins.MerlinPG.ZapOnOK))
91                 clist.append(getConfigListEntry(_("Page-up/down with bouquet+/- :"), config.plugins.MerlinPG.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.MerlinPG.PThi.value > config.plugins.MerlinPG.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.MerlinPG.Primetime.value) and (t[4]>config.plugins.MerlinPG.PTlow.value) and (t[4]<config.plugins.MerlinPG.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.MerlinPG.Primetime.value) and (evBgMin>config.plugins.MerlinPG.PTlow.value) and (evBgMin<config.plugins.MerlinPG.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.MerlinPG.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.MerlinPG.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.MerlinPG.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.MerlinPG.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
499         def right(self):
500                 if self.ActiveEPG < (self.Fields-1):
501                         self.ActiveEPG = self.ActiveEPG + 1
502                         self.displayActiveEPG()
503                 else:
504                         self.NextPage()
505
506         def showEventInfo(self):
507                 curEV = self["epg_list"+str(self.ActiveEPG)].getCurrent()
508                 event = curEV[0]
509                 service = curEV[1]
510                 if event is not None:
511                         self.session.open(EventViewSimple, event, service)
512
513         def timerAdd(self):
514                 cur = self["epg_list"+str(self.ActiveEPG)].getCurrent()
515                 event = cur[0]
516                 serviceref = cur[1]
517                 if event is None:
518                         return
519                 eventid = event.getEventId()
520                 refstr = serviceref.ref.toString()
521                 for timer in self.session.nav.RecordTimer.timer_list:
522                         if timer.eit == eventid and timer.service_ref.ref.toString() == refstr:
523                                 cb_func = lambda ret : not ret or self.removeTimer(timer)
524                                 self.session.openWithCallback(cb_func, MessageBox, _("Do you really want to delete %s?") % event.getEventName())
525                                 break
526                 else:
527                         newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, *parseEvent(event))
528                         self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry)
529
530         def removeTimer(self, timer):
531                 timer.afterEvent = AFTEREVENT.NONE
532                 self.session.nav.RecordTimer.removeEntry(timer)
533
534         def finishedAdd(self, answer):
535                 if answer[0]:
536                         entry = answer[1]
537                         simulTimerList = self.session.nav.RecordTimer.record(entry)
538                         if simulTimerList is not None:
539                                 for x in simulTimerList:
540                                         if x.setAutoincreaseEnd(entry):
541                                                 self.session.nav.RecordTimer.timeChanged(x)
542                                 simulTimerList = self.session.nav.RecordTimer.record(entry)
543                                 if simulTimerList is not None:
544                                         self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList)
545         
546         def finishSanityCorrection(self, answer):
547                 self.finishedAdd(answer)
548
549         def menuClicked(self):
550                 self.session.open(MerlinPGsetup)
551
552         def findNextBqt(self):
553                 CurrIdx = 0
554                 CurrBqt = self.myBqts[self.getActivePrg()]
555                 for CurrIdx in range(self.getActivePrg(),self.chCount):
556                         NewBqt = self.myBqts[CurrIdx]
557                         if NewBqt != CurrBqt:
558                                 break
559                 self["prg_list"].moveToIndex(CurrIdx)
560                 self.updateInfos()
561
562         def findPrvBqt(self):
563                 CurrIdx = 0
564                 CurrBqt = self.myBqts[self.getActivePrg()]
565                 for CurrIdx in range(self.getActivePrg(),-1,-1):
566                         NewBqt = self.myBqts[CurrIdx]
567                         if NewBqt != CurrBqt:
568                                 break
569                 self["prg_list"].moveToIndex(CurrIdx)
570                 self.updateInfos()
571
572         def go2Primetime(self):
573                 if self.AutoPrime.isActive():
574                         self.AutoPrime.stop()
575                 for xFL in range(1, self.Fields):
576                         self["epg_list"+str(xFL)].instance.moveSelection(self["epg_list"+str(xFL)].instance.moveTop)
577                         for i in range(0,(self.Fields*3)):
578                                 self["epg_list"+str(xFL)].foudPrimetime()
579
580         def myhelp(self):
581                 self.session.open(ShowMe, "/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/help.jpg")
582
583         def UserOK(self):
584                 if config.plugins.MerlinPG.ZapOnOK.value:
585                         self.ZapTo()
586                 else:
587                         self.showEventInfo()
588
589
590
591 class Merlin_PGd(Screen):
592         try:
593                 sz_w = getDesktop(0).size().width()
594         except:
595                 sz_w = 720
596         if sz_w == 1280:
597                 skin = """
598                 <screen backgroundColor="#ffffffff" flags="wfNoBorder" name="Merlin_PG" position="0,0" size="1280,720" title="Merlin Program Guide">
599                         <widget backgroundColor="#ffffffff" position="0,0" render="Pig" size="520,292" source="session.VideoPicture" zPosition="-1"/>
600                         <eLabel backgroundColor="#00111112" position="0,292" size="520,450" zPosition="1"/>
601                         <eLabel backgroundColor="#00111112" position="520,0" size="760,720" zPosition="1"/>
602                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/epg.png" position="1136,105" size="85,77" zPosition="5"/>
603                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/channels.png" position="395,306" size="80,80" zPosition="5"/>
604                         <ePixmap alphatest="on" name="red" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/red.png" position="70,635" size="35,25" zPosition="2"/>
605                         <ePixmap alphatest="on" name="green" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/green.png" position="275,635" size="35,25" zPosition="2"/>
606                         <eLabel backgroundColor="#00111112" font="Regular;18" position="110,635" size="131,24" text="ZAP" transparent="1" zPosition="2"/>
607                         <eLabel backgroundColor="#00111112" font="Regular;18" position="315,635" size="191,24" text="TIMERS" transparent="1" zPosition="2"/>
608                         <widget itemHeight="25" name="prg_list" position="75,306" scrollbarMode="showNever" size="400,300" transparent="1" zPosition="4"/>
609                         <widget itemHeight="27" name="epg_list" position="570,105" scrollbarMode="showNever" size="651,540" transparent="1" zPosition="4"/>
610                         <widget backgroundColor="#00111112" font="Regular;22" foregroundColor="#fcc000" halign="center" name="currCh" position="555,55" size="651,24" transparent="1" valign="center" zPosition="2"/>
611                 </screen>"""
612         elif sz_w == 1024:
613                 skin = """
614                 <screen backgroundColor="#ffffffff" flags="wfNoBorder" name="Merlin_PG" position="0,0" size="1024,576" title="Merlin Program Guide">
615                         <widget backgroundColor="#ffffffff" position="0,0" render="Pig" size="384,216" source="session.VideoPicture" zPosition="-1"/>
616                         <eLabel backgroundColor="#00111112" position="0,216" size="384,366" zPosition="1"/>
617                         <eLabel backgroundColor="#00111112" position="384,0" size="720,576" zPosition="1"/>
618                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/epg.png" position="900,80" size="85,77" zPosition="5"/>
619                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/channels.png" position="292,228" size="80,80" zPosition="5"/>
620                         <ePixmap alphatest="on" name="red" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/red.png" position="40,520" size="35,25" zPosition="3"/>
621                         <ePixmap alphatest="on" name="green" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/green.png" position="185,520" size="35,25" zPosition="3"/>
622                         <eLabel backgroundColor="#00111112" font="Regular;18" position="80,520" size="92,24" text="ZAP" transparent="1" zPosition="2"/>
623                         <eLabel backgroundColor="#00111112" font="Regular;18" position="230,520" size="141,24" text="TIMERS" transparent="1" zPosition="2"/>
624                         <widget itemHeight="25" name="prg_list" position="40,228" scrollbarMode="showNever" size="332,275" transparent="1" zPosition="4"/>
625                         <widget itemHeight="28" name="epg_list" position="395,80" scrollbarMode="showNever" size="590,448" transparent="1" zPosition="4"/>
626                         <widget backgroundColor="#00111112" font="Regular;21" foregroundColor="#fcc000" halign="center" name="currCh" position="395,40" size="590,24" transparent="1" valign="center" zPosition="4"/>
627                 </screen>"""
628         else:
629                 skin = """
630                 <screen flags="wfNoBorder" name="Merlin_PG" position="0,0" size="720,576" title="Merlin Program Guide">
631                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/mpgbgSD-fs8.png" position="0,0" size="720,576" zPosition="1"/>
632                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/red.png" position="165,90" size="35,25" zPosition="2"/>
633                         <ePixmap alphatest="on" pixmap="/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/green.png" position="165,110" size="35,25" zPosition="2"/>
634                         <eLabel backgroundColor="#1f1f1f" font="Regular;15" foregroundColor="#f0f0f0" position="205,93" size="70,20" text="ZAP" transparent="1" zPosition="2"/>
635                         <eLabel backgroundColor="#1f1f1f" font="Regular;15" foregroundColor="#f0f0f0" position="205,113" size="70,20" text="TIMERS" transparent="1" zPosition="2"/>
636                         <widget name="prg_list" position="342,63" scrollbarMode="showOnDemand" size="327,150" zPosition="2" itemHeight="25"/>
637                         <widget name="epg_list" position="57,238" scrollbarMode="showOnDemand" size="612,270" zPosition="2" itemHeight="27"/>
638                         <widget font="Regular;22" foregroundColor="#ffc000" halign="center" name="currCh" position="57,133" size="252,66" transparent="1" valign="center" zPosition="2"/>
639                         <widget font="LCD;28" halign="left" position="60,95" render="Label" size="91,32" source="global.CurrentTime" transparent="1" zPosition="3">
640                                 <convert type="ClockToText">Default</convert>
641                         </widget>       
642                         <widget font="Regular;16" position="60,65" render="Label" size="276,26" source="global.CurrentTime" transparent="1" zPosition="3">
643                                 <convert type="ClockToText">Date</convert>
644                         </widget>
645                 </screen>"""
646
647         def __init__(self, session, servicelist):
648                 Screen.__init__(self, session)
649                 self.session = session
650                 self.myServices = []
651                 self.myBqts = []
652                 self.list = []
653                 self.srvList = servicelist
654                 self.CheckForEPG = eTimer()
655                 self.CheckForEPG.callback.append(self.CheckItNow)
656                 self["currCh"] = Label(_("Channel"))
657                 self["prg_list"] = MenuList(self.getChannels())
658                 self["epg_list"] = EPGList(type = EPG_TYPE_SINGLE, selChangedCB = self.onSelectionChanged, timer = session.nav.RecordTimer)
659                 self["actions"] = ActionMap(["OkCancelActions", "EPGSelectActions", "ColorActions", "MenuActions", "HelpActions"], {
660                                                                         "ok": self.ok, 
661                                                                         "cancel": self.close,
662                                                                         "nextBouquet": self.prgDown,
663                                                                         "prevBouquet": self.prgUp,
664                                                                         "nextService": self.prgPlus,
665                                                                         "prevService": self.prgMinus,
666                                                                         "red": self.ZapTo,
667                                                                         "green": self.timerAdd,
668                                                                         "blue": self.ZapForRefresh,
669                                                                         "yellow": self.go2now,
670                                                                         "info": self.ok,
671                                                                         "menu": self.menuClicked,
672                                                                         "displayHelp": self.myhelp
673                                                                         },-2)
674                 self.onLayoutFinish.append(self.onLayoutReady)
675
676         def onLayoutReady(self):
677                 service = self.session.nav.getCurrentService()
678                 info = service and service.info()
679                 if (info is not None) and not(config.plugins.MerlinPG.StartFirst.value):
680                         nameROH = info.getName().replace('\xc2\x86', '').replace('\xc2\x87', '')
681                         for idx in range(1, len(self.list)):
682                                 name = str(idx) + ". " + nameROH
683                                 if name == self.list[idx-1]:
684                                         break
685                         self["prg_list"].moveToIndex(idx-1)
686                 else:
687                         self["prg_list"].moveToIndex(0)
688                 self.updateInfos()
689
690         def onSelectionChanged(self):
691                 pass
692
693         def prgUp(self):
694                 self["prg_list"].down()
695                 self.updateInfos()
696         
697         def prgDown(self):
698                 self["prg_list"].up()
699                 self.updateInfos()
700
701         def prgPlus(self):
702                 self["prg_list"].pageDown()
703                 self.updateInfos()
704
705         def prgMinus(self):
706                 self["prg_list"].pageUp()
707                 self.updateInfos()
708
709         def getChannels(self):
710                 indx = 0
711                 serviceHandler = eServiceCenter.getInstance()
712                 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'))
713                 bouquets = services and services.getContent("SN", True)
714                 for bouquet in bouquets:
715                         services = serviceHandler.list(eServiceReference(bouquet[0]))
716                         channels = services and services.getContent("SN", True)
717                         for channel in channels:
718                                 if not channel[0].startswith("1:64:"):
719                                         indx = indx + 1
720                                         self.list.append(str(indx) + ". " + channel[1].replace('\xc2\x86', '').replace('\xc2\x87', ''))
721                                         self.myServices.append(channel)
722                                         self.myBqts.append(bouquet)
723                 return self.list
724
725         def updateInfos(self):
726                 l = self["epg_list"]
727                 l.recalcEntrySize()
728                 CurrentPrg = self.myServices[self["prg_list"].getSelectionIndex()]
729                 self["currCh"].setText(str(CurrentPrg[1]))
730                 myService = ServiceReference(CurrentPrg[0])
731                 l.fillSingleEPG(myService)
732
733         def ok(self):
734                 curEV = self["epg_list"].getCurrent()
735                 event = curEV[0]
736                 service = curEV[1]
737                 if event is not None:
738                         self.session.open(EventViewSimple, event, service)
739                         
740         def ZapTo(self):
741                 CurrentPrg = self.myServices[self["prg_list"].getSelectionIndex()]
742                 CurrentBqt = self.myBqts[self["prg_list"].getSelectionIndex()]
743                 myService = ServiceReference(CurrentPrg[0])
744                 myB = ServiceReference(CurrentBqt[0])
745                 self.srvList.clearPath()
746                 if self.srvList.bouquet_root != myB.ref:
747                         self.srvList.enterPath(self.srvList.bouquet_root)
748                 self.srvList.enterPath(myB.ref)
749                 self.srvList.setCurrentSelection(myService.ref)
750                 self.srvList.zap()
751                 self.close()
752
753         def ZapForRefresh(self):
754                 CurrentPrg = self.myServices[self["prg_list"].getSelectionIndex()]
755                 myService = ServiceReference(CurrentPrg[0])
756                 self.session.nav.playService(myService.ref)
757                 self.CheckForEPG.start(4000, True)
758
759         def CheckItNow(self):
760                 self.CheckForEPG.stop()
761                 self.updateInfos()
762
763         def timerAdd(self):
764                 cur = self["epg_list"].getCurrent()
765                 event = cur[0]
766                 serviceref = cur[1]
767                 if event is None:
768                         return
769                 eventid = event.getEventId()
770                 refstr = serviceref.ref.toString()
771                 for timer in self.session.nav.RecordTimer.timer_list:
772                         if timer.eit == eventid and timer.service_ref.ref.toString() == refstr:
773                                 cb_func = lambda ret : not ret or self.removeTimer(timer)
774                                 self.session.openWithCallback(cb_func, MessageBox, _("Do you really want to delete %s?") % event.getEventName())
775                                 break
776                 else:
777                         newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, *parseEvent(event))
778                         self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry)
779
780         def removeTimer(self, timer):
781                 timer.afterEvent = AFTEREVENT.NONE
782                 self.session.nav.RecordTimer.removeEntry(timer)
783
784         def finishedAdd(self, answer):
785                 if answer[0]:
786                         entry = answer[1]
787                         simulTimerList = self.session.nav.RecordTimer.record(entry)
788                         if simulTimerList is not None:
789                                 for x in simulTimerList:
790                                         if x.setAutoincreaseEnd(entry):
791                                                 self.session.nav.RecordTimer.timeChanged(x)
792                                 simulTimerList = self.session.nav.RecordTimer.record(entry)
793                                 if simulTimerList is not None:
794                                         self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList)
795
796         def finishSanityCorrection(self, answer):
797                 self.finishedAdd(answer)
798
799         def menuClicked(self):
800                 self.session.open(MerlinPGsetup)
801
802         def go2now(self):
803                 self["epg_list"].instance.moveSelection(self["epg_list"].instance.moveTop)
804
805         def myhelp(self):
806                 self.session.open(ShowMe, "/usr/lib/enigma2/python/Plugins/Extensions/MerlinEPG/help.jpg")
807
808
809
810
811
812
813