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