60541fdd8fa4f852ffca15e18219f17c9833fde7
[openblackhole/openblackhole-enigma2.git] / lib / python / Screens / EpgSelection.py
1 from Screen import Screen
2 import ChannelSelection
3 from Components.config import config, ConfigClock
4 from Components.Button import Button
5 from Components.Pixmap import Pixmap
6 from Components.Label import Label
7 from Components.EpgList import EPGList, EPG_TYPE_SINGLE, EPG_TYPE_SIMILAR, EPG_TYPE_MULTI
8 from Components.ActionMap import ActionMap
9 from Components.TimerSanityCheck import TimerSanityCheck
10 from Components.UsageConfig import preferredTimerPath
11 from Components.Sources.ServiceEvent import ServiceEvent
12 from Components.Sources.Event import Event
13 from Screens.ChoiceBox import ChoiceBox
14 from Screens.TimerEdit import TimerSanityConflict, TimerEditList
15 from Screens.EventView import EventViewSimple
16 from Screens.MessageBox import MessageBox
17 from TimeDateInput import TimeDateInput
18 from enigma import eServiceReference
19 from RecordTimer import RecordTimerEntry, parseEvent, AFTEREVENT
20 from TimerEntry import TimerEntry
21 from ServiceReference import ServiceReference
22 from time import localtime, time
23 from Components.PluginComponent import plugins
24 from Plugins.Plugin import PluginDescriptor
25 from Tools.BoundFunction import boundFunction
26
27 mepg_config_initialized = False
28
29 class EPGSelection(Screen):
30         EMPTY = 0
31         ADD_TIMER = 1
32         REMOVE_TIMER = 2
33
34         ZAP = 1
35
36         def __init__(self, session, service, zapFunc=None, eventid=None, bouquetChangeCB=None, serviceChangeCB=None):
37                 Screen.__init__(self, session)
38                 self.bouquetChangeCB = bouquetChangeCB
39                 self.serviceChangeCB = serviceChangeCB
40                 self.ask_time = -1 #now
41                 self["key_red"] = Button("")
42                 self.closeRecursive = False
43                 self.saved_title = None
44                 self["Service"] = ServiceEvent()
45                 self["Event"] = Event()
46                 self.session = session
47                 if isinstance(service, str) and eventid != None:
48                         self.type = EPG_TYPE_SIMILAR
49                         self["key_yellow"] = Button()
50                         self["key_blue"] = Button()
51                         self["key_red"] = Button()
52                         self.currentService=service
53                         self.eventid = eventid
54                         self.zapFunc = None
55                 elif isinstance(service, eServiceReference) or isinstance(service, str):
56                         self.type = EPG_TYPE_SINGLE
57                         self["key_yellow"] = Button()
58                         self["key_blue"] = Button(_("Select Channel"))
59                         self.currentService=ServiceReference(service)
60                         self.zapFunc = zapFunc
61                         self.sort_type = 0
62                         self.setSortDescription()
63                 else:
64                         self.skinName = "EPGSelectionMulti"
65                         self.type = EPG_TYPE_MULTI
66                         self["key_yellow"] = Button(pgettext("button label, 'previous screen'", "Prev"))
67                         self["key_blue"] = Button(pgettext("button label, 'next screen'", "Next"))
68                         self["now_button"] = Pixmap()
69                         self["next_button"] = Pixmap()
70                         self["more_button"] = Pixmap()
71                         self["now_button_sel"] = Pixmap()
72                         self["next_button_sel"] = Pixmap()
73                         self["more_button_sel"] = Pixmap()
74                         self["now_text"] = Label()
75                         self["next_text"] = Label()
76                         self["more_text"] = Label()
77                         self["date"] = Label()
78                         self.services = service
79                         self.zapFunc = zapFunc
80                 self["key_green"] = Button(_("Add timer"))
81                 self.key_green_choice = self.ADD_TIMER
82                 self.key_red_choice = self.EMPTY
83                 self["list"] = EPGList(type = self.type, selChangedCB = self.onSelectionChanged, timer = session.nav.RecordTimer)
84
85                 self["actions"] = ActionMap(["EPGSelectActions", "OkCancelActions"],
86                         {
87                                 "cancel": self.closeScreen,
88                                 "ok": self.eventSelected,
89                                 "timerAdd": self.timerAdd,
90                                 "yellow": self.yellowButtonPressed,
91                                 "blue": self.blueButtonPressed,
92                                 "info": self.infoKeyPressed,
93                                 "red": self.zapTo,
94                                 "menu": self.furtherOptions,
95                                 "nextBouquet": self.nextBouquet, # just used in multi epg yet
96                                 "prevBouquet": self.prevBouquet, # just used in multi epg yet
97                                 "nextService": self.nextService, # just used in single epg yet
98                                 "prevService": self.prevService, # just used in single epg yet
99                                 "preview": self.eventPreview,
100                         })
101                 self["actions"].csel = self
102                 self.onLayoutFinish.append(self.onCreate)
103
104         def nextBouquet(self):
105                 if self.bouquetChangeCB:
106                         self.bouquetChangeCB(1, self)
107
108         def prevBouquet(self):
109                 if self.bouquetChangeCB:
110                         self.bouquetChangeCB(-1, self)
111
112         def nextService(self):
113                 if self.serviceChangeCB:
114                         self.serviceChangeCB(1, self)
115
116         def prevService(self):
117                 if self.serviceChangeCB:
118                         self.serviceChangeCB(-1, self)
119
120         def enterDateTime(self):
121                 if self.type == EPG_TYPE_MULTI:
122                         global mepg_config_initialized
123                         if not mepg_config_initialized:
124                                 config.misc.prev_mepg_time=ConfigClock(default = time())
125                                 mepg_config_initialized = True
126                         self.session.openWithCallback(self.onDateTimeInputClosed, TimeDateInput, config.misc.prev_mepg_time )
127
128         def furtherOptions(self):
129                 menu = []
130                 text = _("Select action")
131                 event = self["list"].getCurrent()[0]
132                 if event:
133                         menu = [(p.name, boundFunction(self.runPlugin, p)) for p in plugins.getPlugins(where = PluginDescriptor.WHERE_EVENTINFO) \
134                                 if 'selectedevent' in p.__call__.func_code.co_varnames]
135                         if menu:
136                                 text += _(": %s") % event.getEventName()
137                 if self.type == EPG_TYPE_MULTI:
138                         menu.append((_("Goto specific date/time"),self.enterDateTime))
139                 menu.append((_("Timer Overview"), self.openTimerOverview))
140                 if len(menu) == 1:
141                         menu and menu[0][1]()
142                 elif len(menu) > 1:
143                         def boxAction(choice):
144                                 if choice:
145                                         choice[1]()
146                         self.session.openWithCallback(boxAction, ChoiceBox, title=text, list=menu)
147
148         def runPlugin(self, plugin):
149                 event = self["list"].getCurrent()
150                 plugin(session=self.session, selectedevent=event)
151
152         def openTimerOverview(self):
153                 self.session.open(TimerEditList)
154
155         def onDateTimeInputClosed(self, ret):
156                 if len(ret) > 1:
157                         if ret[0]:
158                                 self.ask_time=ret[1]
159                                 self["list"].fillMultiEPG(self.services, ret[1])
160
161         def closeScreen(self):
162                 if self.zapFunc:
163                         self.zapFunc(None, zapback = True)
164                 self.close(self.closeRecursive)
165
166         def infoKeyPressed(self):
167                 cur = self["list"].getCurrent()
168                 event = cur[0]
169                 service = cur[1]
170                 if event is not None:
171                         if self.type != EPG_TYPE_SIMILAR:
172                                 self.session.open(EventViewSimple, event, service, self.eventViewCallback, self.openSimilarList)
173                         else:
174                                 self.session.open(EventViewSimple, event, service, self.eventViewCallback)
175
176         def openSimilarList(self, eventid, refstr):
177                 self.session.open(EPGSelection, refstr, None, eventid)
178
179         def setServices(self, services):
180                 self.services = services
181                 self.onCreate()
182
183         def setService(self, service):
184                 self.currentService = service
185                 self.onCreate()
186
187         #just used in multipeg
188         def onCreate(self):
189                 l = self["list"]
190                 l.recalcEntrySize()
191                 if self.type == EPG_TYPE_MULTI:
192                         l.fillMultiEPG(self.services, self.ask_time)
193                         l.moveToService(self.session.nav.getCurrentlyPlayingServiceOrGroup())
194                 elif self.type == EPG_TYPE_SINGLE:
195                         service = self.currentService
196                         self["Service"].newService(service.ref)
197                         if self.saved_title is None:
198                                 self.saved_title = self.instance.getTitle()
199                         title = self.saved_title + ' - ' + service.getServiceName()
200                         self.instance.setTitle(title)
201                         l.fillSingleEPG(service)
202                 else:
203                         l.fillSimilarList(self.currentService, self.eventid)
204
205         def eventViewCallback(self, setEvent, setService, val):
206                 l = self["list"]
207                 old = l.getCurrent()
208                 if val == -1:
209                         self.moveUp()
210                 elif val == +1:
211                         self.moveDown()
212                 cur = l.getCurrent()
213                 if self.type == EPG_TYPE_MULTI and cur[0] is None and cur[1].ref != old[1].ref:
214                         self.eventViewCallback(setEvent, setService, val)
215                 else:
216                         setService(cur[1])
217                         setEvent(cur[0])
218
219         def zapTo(self):
220                 if self.key_red_choice == self.ZAP and self.zapFunc:
221                         self.closeRecursive = True
222                         from Components.ServiceEventTracker import InfoBarCount
223                         if InfoBarCount > 1:
224                                 self.eventPreview()
225                         else:
226                                 self.zapSelectedService()
227                                 self.close(self.closeRecursive)
228
229         def zapSelectedService(self, prev=False):
230                 lst = self["list"]
231                 count = lst.getCurrentChangeCount()
232                 if count == 0:
233                         ref = lst.getCurrent()[1]
234                         if ref is not None:
235                                 self.zapFunc(ref.ref, preview = prev)
236
237         def eventPreview(self):
238                 if self.zapFunc:
239                         # if enabled, then closed whole EPG with EXIT:
240                         # self.closeRecursive = True
241                         self.zapSelectedService(True)
242
243         def eventSelected(self):
244                 if self.skinName == "EPGSelectionMulti":
245                         cur = self["list"].getCurrent()
246                         event = cur[0]
247                         ref = cur[1] and cur[1].ref.toString()
248                         if ref and event:
249                                 self.session.open(EPGSelection, ref)
250                 else:
251                         self.infoKeyPressed()
252
253         def yellowButtonPressed(self):
254                 if self.type == EPG_TYPE_MULTI:
255                         self["list"].updateMultiEPG(-1)
256                 elif self.type == EPG_TYPE_SINGLE:
257                         if self.sort_type == 0:
258                                 self.sort_type = 1
259                         else:
260                                 self.sort_type = 0
261                         self["list"].sortSingleEPG(self.sort_type)
262                         self.setSortDescription()
263
264         def setSortDescription(self):
265                 if self.sort_type == 1:
266                         # TRANSLATORS: This must fit into the header button in the EPG-List
267                         self["key_yellow"].setText(_("Sort time"))
268                 else:
269                         # TRANSLATORS: This must fit into the header button in the EPG-List
270                         self["key_yellow"].setText(_("Sort A-Z"))
271
272         def blueButtonPressed(self):
273                 if self.type == EPG_TYPE_MULTI:
274                         self["list"].updateMultiEPG(1)
275                 if self.type == EPG_TYPE_SINGLE:
276                         self.session.openWithCallback(self.channelSelectionCallback, ChannelSelection.SimpleChannelSelection, _("Select channel"), currentBouquet=True)
277
278         def channelSelectionCallback(self, *args):
279                 args and self.setService(ServiceReference(args[0]))
280
281         def removeTimer(self, timer):
282                 timer.afterEvent = AFTEREVENT.NONE
283                 self.session.nav.RecordTimer.removeEntry(timer)
284                 self["key_green"].setText(_("Add timer"))
285                 self.key_green_choice = self.ADD_TIMER
286
287         def disableTimer(self, timer, repeat=False, record=False):
288                 if repeat:
289                         if record:
290                                 title_text = _("Repeating event currently recording.\nWhat do you want to do?")
291                                 menu = [(_("Stop current event but not coming events"), "stoponlycurrent"),(_("Stop current event and disable coming events"), "stopall")]
292                                 if not timer.disabled:
293                                         menu.append((_("Don't stop current event but disable coming events"), "stoponlycoming"))
294                         else:
295                                 title_text = _("Attention, this is repeated timer!\nWhat do you want to do?")
296                                 menu = [(_("Disable current event but not coming events"), "nextonlystop"),(_("Disable timer"), "simplestop")]
297                         self.session.openWithCallback(boundFunction(self.runningEventCallback, timer), ChoiceBox, title=title_text, list=menu)
298                 else:
299                         timer.disable()
300                         self.session.nav.RecordTimer.timeChanged(timer)
301                         self["key_green"].setText(_("Add timer"))
302                         self.key_green_choice = self.ADD_TIMER
303
304         def runningEventCallback(self, t, result):
305                 if result is not None:
306                         findNextRunningEvent = True
307                         findEventNext = False 
308                         if result[1] == "nextonlystop":
309                                 findEventNext = True
310                                 t.disable()
311                                 self.session.nav.RecordTimer.timeChanged(t)
312                                 t.processRepeated(findNextEvent=True)
313                                 t.enable()
314                         if result[1] in ("stoponlycurrent", "stopall"):
315                                 findNextRunningEvent = False
316                                 t.enable()
317                                 t.processRepeated(findRunningEvent=False)
318                                 self.session.nav.RecordTimer.doActivate(t)
319                         if result[1] in ("stoponlycoming", "stopall", "simplestop"):
320                                 findNextRunningEvent = True
321                                 t.disable()
322                         self.session.nav.RecordTimer.timeChanged(t)
323                         t.findRunningEvent = findNextRunningEvent
324                         t.findNextEvent = findEventNext
325                         if result[1] in ("stoponlycurrent", "stopall", "simplestop", "nextonlystop"):
326                                 self["key_green"].setText(_("Add timer"))
327                                 self.key_green_choice = self.ADD_TIMER
328
329         def timerAdd(self):
330                 cur = self["list"].getCurrent()
331                 event = cur[0]
332                 if event is None:
333                         return
334                 serviceref = cur[1]
335                 isRecordEvent = isRepeat = firstNextRepeatEvent = False
336                 eventid = event.getEventId()
337                 begin = event.getBeginTime()
338                 end = begin + event.getDuration()
339                 refstr = ':'.join(serviceref.ref.toString().split(':')[:11])
340                 for timer in self.session.nav.RecordTimer.timer_list:
341                         needed_ref = ':'.join(timer.service_ref.ref.toString().split(':')[:11]) == refstr
342                         if needed_ref and timer.eit == eventid and (begin < timer.begin <= end or timer.begin <= begin <= timer.end):
343                                 isRecordEvent = True
344                                 break
345                         elif needed_ref and timer.repeated and self.session.nav.RecordTimer.isInRepeatTimer(timer, event):
346                                 isRecordEvent = True
347                                 break
348                 if isRecordEvent:
349                         isRepeat = timer.repeated
350                         title_text = isRepeat and _("Attention, this is repeated timer!\n") or ""
351                         firstNextRepeatEvent = isRepeat and (begin < timer.begin <= end or timer.begin <= begin <= timer.end) and not timer.justplay 
352                         menu = [(_("Delete timer"), "delete"),(_("Edit timer"), "edit")]
353                         buttons = ["red", "green"]
354                         if not timer.isRunning():
355                                 if firstNextRepeatEvent and timer.isFindRunningEvent() and not timer.isFindNextEvent():
356                                         menu.append((_("Options disable timer"), "disablerepeat"))
357                                 else:
358                                         menu.append((_("Disable timer"), "disable"))
359                                 buttons.append("yellow")
360                         elif firstNextRepeatEvent:
361                                 menu.append((_("Options disable timer"), "disablerepeatrunning"))
362                                 buttons.append("yellow")
363                         menu.append((_("Timer Overview"), "timereditlist"))
364                         def timerAction(choice):
365                                 if choice is not None:
366                                         if choice[1] == "delete":
367                                                 self.removeTimer(timer)
368                                         elif choice[1] == "edit":
369                                                 self.session.open(TimerEntry, timer)
370                                         elif choice[1] == "disable":
371                                                 self.disableTimer(timer)
372                                         elif choice[1] == "timereditlist":
373                                                 self.session.open(TimerEditList)
374                                         elif choice[1] == "disablerepeatrunning":
375                                                 self.disableTimer(timer, repeat=True, record=True)
376                                         elif choice[1] == "disablerepeat":
377                                                 self.disableTimer(timer, repeat=True)
378                         self.session.openWithCallback(timerAction, ChoiceBox, title=title_text + _("Select action for timer '%s'.") % timer.name, list=menu, keys=buttons)
379                 else:
380                         newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, dirname = preferredTimerPath(), *parseEvent(event))
381                         self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry)
382
383         def finishedAdd(self, answer):
384                 print "finished add"
385                 if answer[0]:
386                         entry = answer[1]
387                         simulTimerList = self.session.nav.RecordTimer.record(entry)
388                         if simulTimerList is not None:
389                                 for x in simulTimerList:
390                                         if x.setAutoincreaseEnd(entry):
391                                                 self.session.nav.RecordTimer.timeChanged(x)
392                                 simulTimerList = self.session.nav.RecordTimer.record(entry)
393                                 if simulTimerList is not None:
394                                         if not entry.repeated and not config.recording.margin_before.value and not config.recording.margin_after.value and len(simulTimerList) > 1:
395                                                 change_time = False
396                                                 conflict_begin = simulTimerList[1].begin
397                                                 conflict_end = simulTimerList[1].end
398                                                 if conflict_begin == entry.end:
399                                                         entry.end -= 30
400                                                         change_time = True
401                                                 elif entry.begin == conflict_end:
402                                                         entry.begin += 30
403                                                         change_time = True
404                                                 if change_time:
405                                                         simulTimerList = self.session.nav.RecordTimer.record(entry)
406                                         if simulTimerList is not None:
407                                                 self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList)
408                                                 return
409                         cur = self["list"].getCurrent()
410                         event = cur and cur[0]
411                         if event:
412                                 begin = event.getBeginTime()
413                                 end = begin + event.getDuration()
414                                 if begin < entry.begin <= end or entry.begin <= begin <= entry.end:
415                                         self["key_green"].setText(_("Change timer"))
416                                         self.key_green_choice = self.REMOVE_TIMER
417                 else:
418                         self["key_green"].setText(_("Add timer"))
419                         self.key_green_choice = self.ADD_TIMER
420                         print "Timeredit aborted"
421
422         def finishSanityCorrection(self, answer):
423                 self.finishedAdd(answer)
424
425         def moveUp(self):
426                 self["list"].moveUp()
427
428         def moveDown(self):
429                 self["list"].moveDown()
430
431         def applyButtonState(self, state):
432                 if state == 0:
433                         self["now_button"].hide()
434                         self["now_button_sel"].hide()
435                         self["next_button"].hide()
436                         self["next_button_sel"].hide()
437                         self["more_button"].hide()
438                         self["more_button_sel"].hide()
439                         self["now_text"].hide()
440                         self["next_text"].hide()
441                         self["more_text"].hide()
442                         self["key_red"].setText("")
443                 else:
444                         if state == 1:
445                                 self["now_button_sel"].show()
446                                 self["now_button"].hide()
447                         else:
448                                 self["now_button"].show()
449                                 self["now_button_sel"].hide()
450
451                         if state == 2:
452                                 self["next_button_sel"].show()
453                                 self["next_button"].hide()
454                         else:
455                                 self["next_button"].show()
456                                 self["next_button_sel"].hide()
457
458                         if state == 3:
459                                 self["more_button_sel"].show()
460                                 self["more_button"].hide()
461                         else:
462                                 self["more_button"].show()
463                                 self["more_button_sel"].hide()
464
465         def onSelectionChanged(self):
466                 cur = self["list"].getCurrent()
467                 if cur is None:
468                         if self.key_green_choice != self.EMPTY:
469                                 self["key_green"].setText("")
470                                 self.key_green_choice = self.EMPTY
471                         if self.key_red_choice != self.EMPTY:
472                                 self["key_red"].setText("")
473                                 self.key_red_choice = self.EMPTY
474                         return
475                 event = cur[0]
476                 self["Event"].newEvent(event)
477                 if self.type == EPG_TYPE_MULTI:
478                         count = self["list"].getCurrentChangeCount()
479                         if self.ask_time != -1:
480                                 self.applyButtonState(0)
481                         elif count > 1:
482                                 self.applyButtonState(3)
483                         elif count > 0:
484                                 self.applyButtonState(2)
485                         else:
486                                 self.applyButtonState(1)
487                         days = [ _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun") ]
488                         datestr = ""
489                         if event is not None:
490                                 now = time()
491                                 beg = event.getBeginTime()
492                                 nowTime = localtime(now)
493                                 begTime = localtime(beg)
494                                 if nowTime[2] != begTime[2]:
495                                         datestr = '%s %d.%d.'%(days[begTime[6]], begTime[2], begTime[1])
496                                 else:
497                                         datestr = '%s %d.%d.'%(_("Today"), begTime[2], begTime[1])
498                         self["date"].setText(datestr)
499                         if cur[1] is None:
500                                 self["Service"].newService(None)
501                         else:
502                                 self["Service"].newService(cur[1].ref)
503
504                 if cur[1] is None or cur[1].getServiceName() == "":
505                         if self.key_green_choice != self.EMPTY:
506                                 self["key_green"].setText("")
507                                 self.key_green_choice = self.EMPTY
508                         if self.key_red_choice != self.EMPTY:
509                                 self["key_red"].setText("")
510                                 self.key_red_choice = self.EMPTY
511                         return
512                 elif self.key_red_choice != self.ZAP and self.zapFunc is not None:
513                                 self["key_red"].setText(_("Zap"))
514                                 self.key_red_choice = self.ZAP
515
516                 if event is None:
517                         if self.key_green_choice != self.EMPTY:
518                                 self["key_green"].setText("")
519                                 self.key_green_choice = self.EMPTY
520                         return
521
522                 serviceref = cur[1]
523                 eventid = event.getEventId()
524                 begin = event.getBeginTime()
525                 end = begin + event.getDuration()
526                 refstr = ':'.join(serviceref.ref.toString().split(':')[:11])
527                 isRecordEvent = False
528                 for timer in self.session.nav.RecordTimer.timer_list:
529                         needed_ref = ':'.join(timer.service_ref.ref.toString().split(':')[:11]) == refstr
530                         if needed_ref and (timer.eit == eventid and (begin < timer.begin <= end or timer.begin <= begin <= timer.end) or timer.repeated and self.session.nav.RecordTimer.isInRepeatTimer(timer, event)):
531                                 isRecordEvent = True
532                                 break
533                 if isRecordEvent and self.key_green_choice != self.REMOVE_TIMER:
534                         self["key_green"].setText(_("Change timer"))
535                         self.key_green_choice = self.REMOVE_TIMER
536                 elif not isRecordEvent and self.key_green_choice != self.ADD_TIMER:
537                         self["key_green"].setText(_("Add timer"))
538                         self.key_green_choice = self.ADD_TIMER