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