Add service name to title of single EPG
[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 not self.saved_title:
202                                 self.saved_title = self.instance.getTitle()
203                         self.setTitle(self.saved_title + ' - ' + service.getServiceName())
204                         l.fillSingleEPG(service)
205                 else:
206                         l.fillSimilarList(self.currentService, self.eventid)
207
208         def eventViewCallback(self, setEvent, setService, val):
209                 l = self["list"]
210                 old = l.getCurrent()
211                 if val == -1:
212                         self.moveUp()
213                 elif val == +1:
214                         self.moveDown()
215                 cur = l.getCurrent()
216                 if self.type == EPG_TYPE_MULTI and cur[0] is None and cur[1].ref != old[1].ref:
217                         self.eventViewCallback(setEvent, setService, val)
218                 else:
219                         setService(cur[1])
220                         setEvent(cur[0])
221
222         def zapTo(self):
223                 if self.key_red_choice == self.ZAP and self.zapFunc:
224                         self.closeRecursive = True
225                         from Components.ServiceEventTracker import InfoBarCount
226                         if InfoBarCount > 1:
227                                 self.eventPreview()
228                         else:
229                                 self.zapSelectedService()
230                                 self.close(self.closeRecursive)
231
232         def zapSelectedService(self, prev=False):
233                 lst = self["list"]
234                 count = lst.getCurrentChangeCount()
235                 if count == 0:
236                         ref = lst.getCurrent()[1]
237                         if ref is not None:
238                                 self.zapFunc(ref.ref, preview = prev)
239
240         def eventPreview(self):
241                 if self.zapFunc:
242                         # if enabled, then closed whole EPG with EXIT:
243                         # self.closeRecursive = True
244                         self.zapSelectedService(True)
245
246         def eventSelected(self):
247                 if self.skinName == "EPGSelectionMulti":
248                         cur = self["list"].getCurrent()
249                         event = cur[0]
250                         ref = cur[1] and cur[1].ref.toString()
251                         if ref and event:
252                                 self.session.open(EPGSelection, ref)
253                 else:
254                         self.infoKeyPressed()
255
256         def yellowButtonPressed(self):
257                 if self.type == EPG_TYPE_MULTI:
258                         self["list"].updateMultiEPG(-1)
259                 elif self.type == EPG_TYPE_SINGLE:
260                         if self.sort_type == 0:
261                                 self.sort_type = 1
262                         else:
263                                 self.sort_type = 0
264                         self["list"].sortSingleEPG(self.sort_type)
265                         self.setSortDescription()
266
267         def setSortDescription(self):
268                 if self.sort_type == 1:
269                         # TRANSLATORS: This must fit into the header button in the EPG-List
270                         self["key_yellow"].setText(_("Sort time"))
271                 else:
272                         # TRANSLATORS: This must fit into the header button in the EPG-List
273                         self["key_yellow"].setText(_("Sort A-Z"))
274
275         def blueButtonPressed(self):
276                 if self.type == EPG_TYPE_MULTI:
277                         self["list"].updateMultiEPG(1)
278                 if self.type == EPG_TYPE_SINGLE:
279                         self.session.openWithCallback(self.channelSelectionCallback, ChannelSelection.SimpleChannelSelection, _("Select channel"), currentBouquet=True)
280
281         def channelSelectionCallback(self, *args):
282                 args and self.setService(ServiceReference(args[0]))
283
284         def removeTimer(self, timer):
285                 timer.afterEvent = AFTEREVENT.NONE
286                 self.session.nav.RecordTimer.removeEntry(timer)
287                 self["key_green"].setText(_("Add timer"))
288                 self.key_green_choice = self.ADD_TIMER
289
290         def disableTimer(self, timer, state, repeat=False, record=False):
291                 if repeat:
292                         if record:
293                                 title_text = _("Repeating event currently recording.\nWhat do you want to do?")
294                                 menu = [(_("Stop current event but not coming events"), "stoponlycurrent"),(_("Stop current event and disable coming events"), "stopall")]
295                                 if not timer.disabled:
296                                         menu.append((_("Don't stop current event but disable coming events"), "stoponlycoming"))
297                         else:
298                                 title_text = _("Attention, this is repeated timer!\nWhat do you want to do?")
299                                 menu = [(_("Disable current event but not coming events"), "nextonlystop"),(_("Disable timer"), "simplestop")]
300                         self.session.openWithCallback(boundFunction(self.runningEventCallback, timer, state), ChoiceBox, title=title_text, list=menu)
301                 elif timer.state == state:
302                         timer.disable()
303                         self.session.nav.RecordTimer.timeChanged(timer)
304                         self["key_green"].setText(_("Add timer"))
305                         self.key_green_choice = self.ADD_TIMER
306
307         def runningEventCallback(self, t, state, result):
308                 if result is not None and t.state == state:
309                         findNextRunningEvent = True
310                         findEventNext = False
311                         if result[1] == "nextonlystop":
312                                 findEventNext = True
313                                 t.disable()
314                                 self.session.nav.RecordTimer.timeChanged(t)
315                                 t.processRepeated(findNextEvent=True)
316                                 t.enable()
317                         if result[1] in ("stoponlycurrent", "stopall"):
318                                 findNextRunningEvent = False
319                                 t.enable()
320                                 t.processRepeated(findRunningEvent=False)
321                                 self.session.nav.RecordTimer.doActivate(t)
322                         if result[1] in ("stoponlycoming", "stopall", "simplestop"):
323                                 findNextRunningEvent = True
324                                 t.disable()
325                         self.session.nav.RecordTimer.timeChanged(t)
326                         t.findRunningEvent = findNextRunningEvent
327                         t.findNextEvent = findEventNext
328                         if result[1] in ("stoponlycurrent", "stopall", "simplestop", "nextonlystop"):
329                                 self["key_green"].setText(_("Add timer"))
330                                 self.key_green_choice = self.ADD_TIMER
331
332         def timerAdd(self):
333                 cur = self["list"].getCurrent()
334                 event = cur[0]
335                 if event is None:
336                         return
337                 serviceref = cur[1]
338                 isRecordEvent = isRepeat = firstNextRepeatEvent = isRunning = False
339                 eventid = event.getEventId()
340                 begin = event.getBeginTime()
341                 end = begin + event.getDuration()
342                 refstr = ':'.join(serviceref.ref.toString().split(':')[:11])
343                 for timer in self.session.nav.RecordTimer.timer_list:
344                         needed_ref = ':'.join(timer.service_ref.ref.toString().split(':')[:11]) == refstr
345                         if needed_ref and timer.eit == eventid and (begin < timer.begin <= end or timer.begin <= begin <= timer.end):
346                                 isRecordEvent = True
347                                 break
348                         elif needed_ref and timer.repeated and self.session.nav.RecordTimer.isInRepeatTimer(timer, event):
349                                 isRecordEvent = True
350                                 break
351                 if isRecordEvent:
352                         isRepeat = timer.repeated
353                         prev_state = timer.state
354                         isRunning = prev_state in (1, 2)
355                         title_text = isRepeat and _("Attention, this is repeated timer!\n") or ""
356                         firstNextRepeatEvent = isRepeat and (begin < timer.begin <= end or timer.begin <= begin <= timer.end) and not timer.justplay
357                         menu = [(_("Delete timer"), "delete"),(_("Edit timer"), "edit")]
358                         buttons = ["red", "green"]
359                         if not isRunning:
360                                 if firstNextRepeatEvent and timer.isFindRunningEvent() and not timer.isFindNextEvent():
361                                         menu.append((_("Options disable timer"), "disablerepeat"))
362                                 else:
363                                         menu.append((_("Disable timer"), "disable"))
364                                 buttons.append("yellow")
365                         elif prev_state == 2 and firstNextRepeatEvent:
366                                 menu.append((_("Options disable timer"), "disablerepeatrunning"))
367                                 buttons.append("yellow")
368                         menu.append((_("Timer Overview"), "timereditlist"))
369                         def timerAction(choice):
370                                 if choice is not None:
371                                         if choice[1] == "delete":
372                                                 self.removeTimer(timer)
373                                         elif choice[1] == "edit":
374                                                 self.session.openWithCallback(self.finishedEdit, TimerEntry, timer)
375                                         elif choice[1] == "disable":
376                                                 self.disableTimer(timer, prev_state)
377                                         elif choice[1] == "timereditlist":
378                                                 self.session.open(TimerEditList)
379                                         elif choice[1] == "disablerepeatrunning":
380                                                 self.disableTimer(timer, prev_state, repeat=True, record=True)
381                                         elif choice[1] == "disablerepeat":
382                                                 self.disableTimer(timer, prev_state, repeat=True)
383                         self.session.openWithCallback(timerAction, ChoiceBox, title=title_text + _("Select action for timer '%s'.") % timer.name, list=menu, keys=buttons)
384                 else:
385                         newEntry = RecordTimerEntry(serviceref, checkOldTimers = True, dirname = preferredTimerPath(), *parseEvent(event))
386                         self.session.openWithCallback(self.finishedAdd, TimerEntry, newEntry)
387
388         def finishedEdit(self, answer=None):
389                 if answer[0]:
390                         entry = answer[1]
391                         simulTimerList = self.session.nav.RecordTimer.record(entry)
392                         if simulTimerList is not None:
393                                 for x in simulTimerList:
394                                         if x.setAutoincreaseEnd(entry):
395                                                 self.session.nav.RecordTimer.timeChanged(x)
396                                 simulTimerList = self.session.nav.RecordTimer.record(entry)
397                                 if simulTimerList is not None:
398                                         self.session.openWithCallback(self.finishedEdit, TimerSanityConflict, simulTimerList)
399                                         return
400                                 else:
401                                         self.session.nav.RecordTimer.timeChanged(entry)
402                 self.onSelectionChanged()
403
404         def finishedAdd(self, answer):
405                 print "finished add"
406                 if answer[0]:
407                         entry = answer[1]
408                         simulTimerList = self.session.nav.RecordTimer.record(entry)
409                         if simulTimerList is not None:
410                                 for x in simulTimerList:
411                                         if x.setAutoincreaseEnd(entry):
412                                                 self.session.nav.RecordTimer.timeChanged(x)
413                                 simulTimerList = self.session.nav.RecordTimer.record(entry)
414                                 if simulTimerList is not None:
415                                         if not entry.repeated and not config.recording.margin_before.value and not config.recording.margin_after.value and len(simulTimerList) > 1:
416                                                 change_time = False
417                                                 conflict_begin = simulTimerList[1].begin
418                                                 conflict_end = simulTimerList[1].end
419                                                 if conflict_begin == entry.end:
420                                                         entry.end -= 30
421                                                         change_time = True
422                                                 elif entry.begin == conflict_end:
423                                                         entry.begin += 30
424                                                         change_time = True
425                                                 if change_time:
426                                                         simulTimerList = self.session.nav.RecordTimer.record(entry)
427                                         if simulTimerList is not None:
428                                                 self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList)
429                                                 return
430                         cur = self["list"].getCurrent()
431                         event = cur and cur[0]
432                         if event:
433                                 begin = event.getBeginTime()
434                                 end = begin + event.getDuration()
435                                 if begin < entry.begin <= end or entry.begin <= begin <= entry.end:
436                                         self["key_green"].setText(_("Change timer"))
437                                         self.key_green_choice = self.REMOVE_TIMER
438                 else:
439                         self["key_green"].setText(_("Add timer"))
440                         self.key_green_choice = self.ADD_TIMER
441                         print "Timeredit aborted"
442
443         def finishSanityCorrection(self, answer):
444                 self.finishedAdd(answer)
445
446         def moveUp(self):
447                 self["list"].moveUp()
448
449         def moveDown(self):
450                 self["list"].moveDown()
451
452         def applyButtonState(self, state):
453                 if state == 0:
454                         self["now_button"].hide()
455                         self["now_button_sel"].hide()
456                         self["next_button"].hide()
457                         self["next_button_sel"].hide()
458                         self["more_button"].hide()
459                         self["more_button_sel"].hide()
460                         self["now_text"].hide()
461                         self["next_text"].hide()
462                         self["more_text"].hide()
463                         self["key_red"].setText("")
464                 else:
465                         if state == 1:
466                                 self["now_button_sel"].show()
467                                 self["now_button"].hide()
468                         else:
469                                 self["now_button"].show()
470                                 self["now_button_sel"].hide()
471
472                         if state == 2:
473                                 self["next_button_sel"].show()
474                                 self["next_button"].hide()
475                         else:
476                                 self["next_button"].show()
477                                 self["next_button_sel"].hide()
478
479                         if state == 3:
480                                 self["more_button_sel"].show()
481                                 self["more_button"].hide()
482                         else:
483                                 self["more_button"].show()
484                                 self["more_button_sel"].hide()
485
486         def onSelectionChanged(self):
487                 cur = self["list"].getCurrent()
488                 if cur is None:
489                         if self.key_green_choice != self.EMPTY:
490                                 self["key_green"].setText("")
491                                 self.key_green_choice = self.EMPTY
492                         if self.key_red_choice != self.EMPTY:
493                                 self["key_red"].setText("")
494                                 self.key_red_choice = self.EMPTY
495                         return
496                 event = cur[0]
497                 self["Event"].newEvent(event)
498                 if self.type == EPG_TYPE_MULTI:
499                         count = self["list"].getCurrentChangeCount()
500                         if self.ask_time != -1:
501                                 self.applyButtonState(0)
502                         elif count > 1:
503                                 self.applyButtonState(3)
504                         elif count > 0:
505                                 self.applyButtonState(2)
506                         else:
507                                 self.applyButtonState(1)
508                         days = [ _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun") ]
509                         datestr = ""
510                         if event is not None:
511                                 now = time()
512                                 beg = event.getBeginTime()
513                                 nowTime = localtime(now)
514                                 begTime = localtime(beg)
515                                 if nowTime[2] != begTime[2]:
516                                         datestr = '%s %d.%d.'%(days[begTime[6]], begTime[2], begTime[1])
517                                 else:
518                                         datestr = '%s %d.%d.'%(_("Today"), begTime[2], begTime[1])
519                         self["date"].setText(datestr)
520                         if cur[1] is None:
521                                 self["Service"].newService(None)
522                         else:
523                                 self["Service"].newService(cur[1].ref)
524
525                 if cur[1] is None or cur[1].getServiceName() == "":
526                         if self.key_green_choice != self.EMPTY:
527                                 self["key_green"].setText("")
528                                 self.key_green_choice = self.EMPTY
529                         if self.key_red_choice != self.EMPTY:
530                                 self["key_red"].setText("")
531                                 self.key_red_choice = self.EMPTY
532                         return
533                 elif self.key_red_choice != self.ZAP and self.zapFunc is not None:
534                                 self["key_red"].setText(_("Zap"))
535                                 self.key_red_choice = self.ZAP
536
537                 if event is None:
538                         if self.key_green_choice != self.EMPTY:
539                                 self["key_green"].setText("")
540                                 self.key_green_choice = self.EMPTY
541                         return
542
543                 serviceref = cur[1]
544                 eventid = event.getEventId()
545                 begin = event.getBeginTime()
546                 end = begin + event.getDuration()
547                 refstr = ':'.join(serviceref.ref.toString().split(':')[:11])
548                 isRecordEvent = False
549                 for timer in self.session.nav.RecordTimer.timer_list:
550                         needed_ref = ':'.join(timer.service_ref.ref.toString().split(':')[:11]) == refstr
551                         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)):
552                                 isRecordEvent = True
553                                 break
554                 if isRecordEvent and self.key_green_choice != self.REMOVE_TIMER:
555                         self["key_green"].setText(_("Change timer"))
556                         self.key_green_choice = self.REMOVE_TIMER
557                 elif not isRecordEvent and self.key_green_choice != self.ADD_TIMER:
558                         self["key_green"].setText(_("Add timer"))
559                         self.key_green_choice = self.ADD_TIMER