2 from Screens.Screen import Screen
3 from Components.ConfigList import ConfigListScreen
4 from Screens.ChannelSelection import SimpleChannelSelection
5 from Screens.MessageBox import MessageBox
6 from Screens.ChoiceBox import ChoiceBox
9 from Screens.Setup import SetupSummary
12 from Components.ActionMap import ActionMap
13 from Components.Button import Button
16 from Components.config import getConfigListEntry, ConfigEnableDisable, \
17 ConfigYesNo, ConfigText, ConfigClock, ConfigInteger, ConfigSelection
20 from RecordTimer import AFTEREVENT
22 # Needed to convert our timestamp back and forth
23 from time import localtime, mktime
25 # Show ServiceName instead of ServiceReference
26 from ServiceReference import ServiceReference
31 ("2", _("Wednesday")),
36 ("weekend", _("Weekend")),
37 ("weekday", _("Weekday"))
40 class AutoTimerEditor(Screen, ConfigListScreen):
43 skin = """<screen name="AutoTimerEdit" title="Edit AutoTimer" position="75,155" size="565,280">
44 <widget name="config" position="5,5" size="555,225" scrollbarMode="showOnDemand" />
45 <ePixmap position="0,235" zPosition="4" size="140,40" pixmap="skin_default/key-red.png" transparent="1" alphatest="on" />
46 <ePixmap position="140,235" zPosition="4" size="140,40" pixmap="skin_default/key-green.png" transparent="1" alphatest="on" />
47 <ePixmap position="280,235" zPosition="4" size="140,40" pixmap="skin_default/key-yellow.png" transparent="1" alphatest="on" />
48 <ePixmap position="420,235" zPosition="4" size="140,40" pixmap="skin_default/key-blue.png" transparent="1" alphatest="on" />
49 <widget name="key_red" position="0,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
50 <widget name="key_green" position="140,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
51 <widget name="key_yellow" position="280,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
52 <widget name="key_blue" position="420,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
55 def __init__(self, session, timer):
56 Screen.__init__(self, session)
62 self.setup_title = "AutoTimer Editor"
63 self.onChangedEntry = []
65 # See if we are filtering some strings
67 timer.getExcludedTitle(),
68 timer.getExcludedShort(),
69 timer.getExcludedDescription(),
70 timer.getExcludedDays()
73 timer.getIncludedTitle(),
74 timer.getIncludedShort(),
75 timer.getIncludedDescription(),
76 timer.getIncludedDays()
78 if len(self.excludes[0]) or len(self.excludes[1]) \
79 or len(self.excludes[2]) or len(self.excludes[3]) \
80 or len(self.includes[0]) or len(self.includes[1]) \
81 or len(self.includes[2]) or len(self.includes[3]):
84 self.filterSet = False
86 # See if services are restricted
87 self.services = timer.getServices()
88 if len(self.services):
89 self.serviceRestriction = True
91 self.serviceRestriction = False
93 self.createSetup(timer)
95 # We might need to change shown items, so add some notifiers
96 self.timespan.addNotifier(self.reloadList, initial_call = False)
97 self.offset.addNotifier(self.reloadList, initial_call = False)
98 self.duration.addNotifier(self.reloadList, initial_call = False)
99 self.afterevent.addNotifier(self.reloadList, initial_call = False)
100 self.afterevent_timespan.addNotifier(self.reloadList, initial_call = False)
101 self.counter.addNotifier(self.reloadList, initial_call = False)
105 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
108 self["key_red"] = Button(_("Cancel"))
109 self["key_green"] = Button(_("OK"))
110 self["key_yellow"] = Button()
111 self["key_blue"] = Button()
114 self.renameChannelButton()
115 self.renameFilterButton()
118 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
120 "cancel": self.cancel,
121 "save": self.maybeSave,
122 "yellow": self.editFilter,
123 "blue": self.editChannels
130 def renameFilterButton(self):
132 self["key_yellow"].setText(_("Edit Filters"))
134 self["key_yellow"].setText(_("Add Filters"))
136 def renameChannelButton(self):
137 if self.serviceRestriction:
138 self["key_blue"].setText(_("Edit Channels"))
140 self["key_blue"].setText(_("Add Channels"))
143 for x in self.onChangedEntry:
149 def getCurrentEntry(self):
150 return self["config"].getCurrent()[0]
152 def getCurrentValue(self):
153 return str(self["config"].getCurrent()[1].getText())
155 def createSummary(self):
158 def createSetup(self, timer):
160 self.name = ConfigText(default = timer.name, fixed_size = False)
163 self.match = ConfigText(default = timer.match, fixed_size = False)
166 self.justplay = ConfigSelection(choices = [("zap", _("zap")), ("record", _("record"))], default = {0: "record", 1: "zap"}[int(timer.justplay)])
169 now = [x for x in localtime()]
170 if timer.hasTimespan():
172 now[3] = timer.timespan[0][0]
173 now[4] = timer.timespan[0][1]
175 now[3] = timer.timespan[1][0]
176 now[4] = timer.timespan[1][1]
186 self.timespan = ConfigEnableDisable(default = default)
187 self.timespanbegin = ConfigClock(default = begin)
188 self.timespanend = ConfigClock(default = end)
190 # Services have their own Screen
193 if timer.hasOffset():
195 begin = timer.getOffsetBegin()
196 end = timer.getOffsetEnd()
201 self.offset = ConfigEnableDisable(default = default)
202 self.offsetbegin = ConfigInteger(default = begin, limits = (0, 180))
203 self.offsetend = ConfigInteger(default = end, limits = (0, 180))
206 if timer.hasAfterEvent():
207 afterevent = { None: "default", AFTEREVENT.NONE: "nothing", AFTEREVENT.DEEPSTANDBY: "deepstandby", AFTEREVENT.STANDBY: "standby"}[timer.afterevent[0][0]]
209 afterevent = "default"
210 self.afterevent = ConfigSelection(choices = [("default", _("standard")), ("nothing", _("do nothing")), ("standby", _("go to standby")), ("deepstandby", _("go to deep standby"))], default = afterevent)
212 # AfterEvent (Timespan)
213 if timer.hasAfterEvent() and timer.afterevent[0][1][0] is not None:
215 now[3] = timer.afterevent[0][1][0][0]
216 now[4] = timer.afterevent[0][1][0][1]
218 now[3] = timer.afterevent[0][1][1][0]
219 now[4] = timer.afterevent[0][1][1][1]
229 self.afterevent_timespan = ConfigEnableDisable(default = default)
230 self.afterevent_timespanbegin = ConfigClock(default = begin)
231 self.afterevent_timespanend = ConfigClock(default = end)
234 self.enabled = ConfigYesNo(default = timer.enabled)
237 if timer.hasDuration():
239 duration = timer.getDuration()
243 self.duration = ConfigEnableDisable(default = default)
244 self.durationlength = ConfigInteger(default = duration, limits = (0, 600))
247 if timer.hasCounter():
248 default = timer.matchCount
251 self.counter = ConfigInteger(default = default, limits = (0, 50))
252 self.counterLeft = ConfigInteger(default = timer.matchLeft, limits = (0, 50))
253 selection = [("", _("Never")), ("%m", _("Monthly")), ("%U", _("Weekly (Sunday)")), ("%W", _("Weekly (Monday)"))]
254 if timer.getCounterFormatString() not in ["", "%m", "%U", "%W"]:
255 selection.append((timer.getCounterFormatString(), _("Custom (%s)") % (timer.getCounterFormatString())))
256 self.counterFormatString = ConfigSelection(selection, default = timer.getCounterFormatString())
258 # Avoid Duplicate Description
259 self.avoidDuplicateDescription = ConfigEnableDisable(default = timer.getAvoidDuplicateDescription())
262 # First four entries are always shown
264 getConfigListEntry(_("Enabled"), self.enabled),
265 getConfigListEntry(_("Description"), self.name),
266 getConfigListEntry(_("Match Title"), self.match),
267 getConfigListEntry(_("Timer Type"), self.justplay),
268 getConfigListEntry(_("Only match during Timespan"), self.timespan)
271 # Only allow editing timespan when it's enabled
272 if self.timespan.value:
274 getConfigListEntry(_("Begin of Timespan"), self.timespanbegin),
275 getConfigListEntry(_("End of Timespan"), self.timespanend)
278 self.list.append(getConfigListEntry(_("Custom offset"), self.offset))
280 # Only allow editing offsets when it's enabled
281 if self.offset.value:
283 getConfigListEntry(_("Offset before recording (in m)"), self.offsetbegin),
284 getConfigListEntry(_("Offset after recording (in m)"), self.offsetend)
287 self.list.append(getConfigListEntry(_("Set maximum Duration"), self.duration))
289 # Only allow editing maxduration when it's enabled
290 if self.duration.value:
292 getConfigListEntry(_("Maximum Duration (in m)"), self.durationlength)
295 self.list.append(getConfigListEntry(_("After event"), self.afterevent))
297 # Only allow setting afterevent timespan when afterevent is active
298 if self.afterevent.value != "default":
299 self.list.append(getConfigListEntry(_("Execute after Event during Timespan"), self.afterevent_timespan))
301 # Only allow editing timespan when it's enabled
302 if self.afterevent_timespan.value:
304 getConfigListEntry(_("Begin of after Event Timespan"), self.afterevent_timespanbegin),
305 getConfigListEntry(_("End of after Event Timespan"), self.afterevent_timespanend)
308 self.list.append(getConfigListEntry(_("Record a maximum of x times"), self.counter))
310 # Only allow setting matchLeft when counting hits
311 if self.counter.value:
312 self.list.append(getConfigListEntry(_("Ammount of recordings left"), self.counterLeft))
313 self.list.append(getConfigListEntry(_("Reset Count"), self.counterFormatString))
315 self.list.append(getConfigListEntry(_("Require Description to be unique"), self.avoidDuplicateDescription))
317 def reloadList(self, value):
319 self["config"].setList(self.list)
321 def editFilter(self):
322 self.session.openWithCallback(
323 self.editFilterCallback,
324 AutoTimerFilterEditor,
330 def editFilterCallback(self, ret):
332 self.filterSet = ret[0]
333 self.excludes = ret[1]
334 self.includes = ret[2]
335 self.renameFilterButton()
337 def editChannels(self):
338 self.session.openWithCallback(
339 self.editChannelsCallback,
340 AutoTimerChannelEditor,
341 self.serviceRestriction,
345 def editChannelsCallback(self, ret):
347 self.serviceRestriction = ret[0]
348 self.services = ret[1]
349 self.renameChannelButton()
352 if self["config"].isChanged():
353 self.session.openWithCallback(
356 _("Really close without saving settings?")
361 def cancelConfirm(self, ret):
366 # Check if we have a trailing whitespace
367 if self.match.value[-1:] == " ":
368 self.session.openWithCallback(
371 _('You entered "%s" as Text to match.\nDo you want to remove trailing whitespaces?') % (self.match.value)
377 def saveCallback(self, ret):
380 self.match.value = self.match.value.rstrip()
382 # Don't to anything if MessageBox was canceled!
386 self.timer.match = self.match.value
389 self.timer.name = self.name.value or self.timer.match
392 self.timer.enabled = self.enabled.value
395 self.timer.justplay = self.justplay.value == "zap"
398 if self.timespan.value:
399 start = self.timespanbegin.value
400 end = self.timespanend.value
401 self.timer.timespan = (start, end)
403 self.timer.timespan = None
406 if self.serviceRestriction:
407 self.timer.services = self.services
409 self.timer.services = None
412 if self.offset.value:
413 self.timer.offset = (self.offsetbegin.value*60, self.offsetend.value*60)
415 self.timer.offset = None
418 if self.afterevent.value == "default":
419 self.timer.afterevent = []
421 afterevent = {"nothing": AFTEREVENT.NONE, "deepstandby": AFTEREVENT.DEEPSTANDBY, "standby": AFTEREVENT.STANDBY}[self.afterevent.value]
422 # AfterEvent Timespan
423 if self.afterevent_timespan.value:
424 start = self.afterevent_timespanbegin.value
425 end = self.afterevent_timespanend.value
426 self.timer.afterevent = [(afterevent, (start, end))]
428 self.timer.afterevent = [(afterevent, None)]
431 if self.duration.value:
432 self.timer.maxduration = self.durationlength.value*60
434 self.timer.maxduration = None
438 self.timer.exclude = self.excludes
439 self.timer.include = self.includes
441 self.timer.exclude = None
442 self.timer.include = None
445 if self.counter.value:
446 self.timer.matchCount = self.counter.value
447 if self.counterLeft.value <= self.counter.value:
448 self.timer.matchLeft = self.counterLeft.value
450 self.timer.matchLeft = self.counter.value
451 if self.counterFormatString.value:
452 self.timer.matchFormatString = self.counterFormatString.value
454 self.timer.matchFormatString = ''
456 self.timer.matchCount = 0
457 self.timer.matchLeft = 0
458 self.timer.matchFormatString = ''
460 self.timer.avoidDuplicateDescription = self.avoidDuplicateDescription.value
463 self.close(self.timer)
465 class AutoTimerFilterEditor(Screen, ConfigListScreen):
466 """Edit AutoTimer Filter"""
468 skin = """<screen name="AutoFilterEditor" title="Edit AutoTimer Filters" position="75,150" size="565,245">
469 <widget name="config" position="5,5" size="555,200" scrollbarMode="showOnDemand" />
470 <ePixmap position="5,205" zPosition="4" size="140,40" pixmap="skin_default/key-red.png" transparent="1" alphatest="on" />
471 <ePixmap position="145,205" zPosition="4" size="140,40" pixmap="skin_default/key-green.png" transparent="1" alphatest="on" />
472 <ePixmap position="285,205" zPosition="4" size="140,40" pixmap="skin_default/key-yellow.png" transparent="1" alphatest="on" />
473 <ePixmap position="425,205" zPosition="4" size="140,40" pixmap="skin_default/key-blue.png" transparent="1" alphatest="on" />
474 <widget name="key_red" position="5,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
475 <widget name="key_green" position="145,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
476 <widget name="key_yellow" position="285,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
477 <widget name="key_blue" position="425,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
480 def __init__(self, session, filterset, excludes, includes):
481 Screen.__init__(self, session)
484 self.setup_title = "AutoTimer Filters"
485 self.onChangedEntry = []
487 self.typeSelection = ConfigSelection(choices = [("title", _("in Title")), ("short", _("in Shortdescription")), ("desc", _("in Description")), ("day", _("on Weekday"))])
488 self.typeSelection.addNotifier(self.refresh, initial_call = False)
490 self.enabled = ConfigEnableDisable(default = filterset)
492 self.excludes = excludes
493 self.includes = includes
497 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
500 self["key_red"] = Button(_("Cancel"))
501 self["key_green"] = Button(_("Save"))
502 self["key_yellow"] = Button(_("delete"))
503 self["key_blue"] = Button(_("New"))
506 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
508 "cancel": self.cancel,
510 "yellow": self.remove,
519 for x in self.onChangedEntry:
525 def getCurrentEntry(self):
526 return self["config"].getCurrent()[0]
528 def getCurrentValue(self):
529 return str(self["config"].getCurrent()[1].getText())
531 def createSummary(self):
534 def saveCurrent(self):
535 del self.excludes[self.idx][:]
536 del self.includes[self.idx][:]
538 # Warning, accessing a ConfigListEntry directly might be considered evil!
541 for item in self["config"].getList():
543 # Skip empty entries (and those which are no filters)
544 if item[1].value == "" or idx < 2:
546 elif idx < self.lenExcludes:
547 self.excludes[self.idx].append(item[1].value.encode("UTF-8"))
549 self.includes[self.idx].append(item[1].value.encode("UTF-8"))
551 def refresh(self, value):
555 self["config"].setList(self.list)
557 def reloadList(self):
559 getConfigListEntry(_("Enable Filtering"), self.enabled),
560 getConfigListEntry(_("Filter"), self.typeSelection)
563 if self.typeSelection.value == "day":
566 # Weekdays are presented as ConfigSelection
568 getConfigListEntry(_("Exclude"), ConfigSelection(choices = weekdays, default = x))
569 for x in self.excludes[3]
571 self.lenExcludes = len(self.list)
573 getConfigListEntry(_("Include"), ConfigSelection(choices = weekdays, default = x))
574 for x in self.includes[3]
577 elif self.typeSelection.value == "title":
579 elif self.typeSelection.value == "short":
581 else: # self.typeSelection.value == "desc":
585 getConfigListEntry(_("Exclude"), ConfigText(default = x, fixed_size = False))
586 for x in self.excludes[self.idx]
588 self.lenExcludes = len(self.list)
590 getConfigListEntry(_("Include"), ConfigText(default = x, fixed_size = False))
591 for x in self.includes[self.idx]
595 idx = self["config"].getCurrentIndex()
597 if idx < self.lenExcludes:
598 self.lenExcludes -= 1
600 list = self["config"].getList()
601 list.remove(self["config"].getCurrent())
602 self["config"].setList(list)
605 self.session.openWithCallback(
608 _("Select type of Filter"),
615 def typeSelected(self, ret):
617 list = self["config"].getList()
620 pos = self.lenExcludes
621 self.lenExcludes += 1
627 if self.typeSelection.value == "day":
628 entry = getConfigListEntry(text, ConfigSelection(choices = weekdays))
630 entry = getConfigListEntry(text, ConfigText(fixed_size = False))
632 list.insert(pos, entry)
633 self["config"].setList(list)
636 if self["config"].isChanged():
637 self.session.openWithCallback(
640 _("Really close without saving settings?")
645 def cancelConfirm(self, ret):
658 class AutoTimerChannelEditor(Screen, ConfigListScreen):
659 """Edit allowed Channels of a AutoTimer"""
661 skin = """<screen name="AutoChannelEditor" title="Edit AutoTimer Channels" position="75,150" size="565,245">
662 <widget name="config" position="5,5" size="555,200" scrollbarMode="showOnDemand" />
663 <ePixmap position="5,205" zPosition="4" size="140,40" pixmap="skin_default/key-red.png" transparent="1" alphatest="on" />
664 <ePixmap position="145,205" zPosition="4" size="140,40" pixmap="skin_default/key-green.png" transparent="1" alphatest="on" />
665 <ePixmap position="285,205" zPosition="4" size="140,40" pixmap="skin_default/key-yellow.png" transparent="1" alphatest="on" />
666 <ePixmap position="425,205" zPosition="4" size="140,40" pixmap="skin_default/key-blue.png" transparent="1" alphatest="on" />
667 <widget name="key_red" position="5,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
668 <widget name="key_green" position="145,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
669 <widget name="key_yellow" position="285,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
670 <widget name="key_blue" position="425,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
673 def __init__(self, session, servicerestriction, servicelist):
674 Screen.__init__(self, session)
677 self.setup_title = "AutoTimer Channels"
678 self.onChangedEntry = []
681 getConfigListEntry(_("Enable Channel Restriction"), ConfigEnableDisable(default = servicerestriction))
685 getConfigListEntry(_("Record on"), ConfigSelection(choices = [(str(x), ServiceReference(str(x)).getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''))]))
689 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
692 self["key_red"] = Button(_("Cancel"))
693 self["key_green"] = Button(_("OK"))
694 self["key_yellow"] = Button(_("delete"))
695 self["key_blue"] = Button(_("New"))
698 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
700 "cancel": self.cancel,
702 "yellow": self.removeChannel,
703 "blue": self.newChannel
711 for x in self.onChangedEntry:
717 def getCurrentEntry(self):
718 return self["config"].getCurrent()[0]
720 def getCurrentValue(self):
721 return str(self["config"].getCurrent()[1].getText())
723 def createSummary(self):
726 def removeChannel(self):
727 if self["config"].getCurrentIndex() != 0:
728 list = self["config"].getList()
729 list.remove(self["config"].getCurrent())
730 self["config"].setList(list)
732 def newChannel(self):
733 self.session.openWithCallback(
734 self.finishedChannelSelection,
735 SimpleChannelSelection,
736 _("Select channel to record from")
739 def finishedChannelSelection(self, *args):
741 list = self["config"].getList()
742 sname = args[0].toString()
744 # strip all after last :
745 pos = sname.rfind(':')
747 sname = sname[:pos+1]
749 list.append(getConfigListEntry(_("Record on"), ConfigSelection(choices = [(sname, ServiceReference(args[0]).getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''))])))
750 self["config"].setList(list)
753 if self["config"].isChanged():
754 self.session.openWithCallback(
757 _("Really close without saving settings?")
762 def cancelConfirm(self, ret):
767 list = self["config"].getList()
768 restriction = list.pop(0)
770 # Warning, accessing a ConfigListEntry directly might be considered evil!
772 restriction[1].value,
774 x[1].value.encode("UTF-8")
779 def addAutotimerFromEvent(session, evt = None, service = None):
780 from AutoTimerComponent import AutoTimerComponent
782 name = evt and evt.getEventName() or "New AutoTimer"
783 match = evt and evt.getEventName() or ""
785 if service is not None:
786 service = str(service)
787 # strip all after last :
788 pos = service.rfind(':')
790 service = service[:pos+1]
792 servicelist.append(service)
794 begin = evt.getBeginTime()
795 end = begin + evt.getDuration()
796 timetuple = (begin-3600, end+3600) # timespan defaults to +- 1h
800 session.openWithCallback(
804 self.autotimer.getUniqueId(), # Id
808 timespan = timetuple,
809 services = servicelist
813 def addCallback(ret):
815 from plugin import autotimer
817 # Create instance if needed
818 if autotimer is None:
819 from AutoTimer import AutoTimer
820 autotimer = AutoTimer()
824 # Remove instance if not running in background
825 if not config.plugins.autotimer.autopoll.value: