1 # -*- coding: UTF-8 -*-
2 # for localized messages
6 from Screens.Screen import Screen
7 from Components.ConfigList import ConfigListScreen
8 from Screens.ChannelSelection import SimpleChannelSelection
9 from Screens.EpgSelection import EPGSelection
10 from Screens.MessageBox import MessageBox
11 from Screens.ChoiceBox import ChoiceBox
14 from Screens.Setup import SetupSummary
17 from Components.ActionMap import ActionMap
18 from Components.Sources.StaticText import StaticText
21 from Components.config import getConfigListEntry, ConfigEnableDisable, \
22 ConfigYesNo, ConfigText, ConfigClock, ConfigNumber, ConfigSelection, \
23 ConfigDateTime, config, NoSave
26 from RecordTimer import AFTEREVENT
28 # Needed to convert our timestamp back and forth
29 from time import localtime, mktime
31 # Show ServiceName instead of ServiceReference
32 from ServiceReference import ServiceReference
34 # addAutotimerFromService, AutoTimerChannelSelection
35 from enigma import eServiceCenter, eServiceReference, iServiceInformation
37 # Default Record Directory
38 from Tools import Directories
41 from Screens.MovieSelection import getPreferredTagEditor
46 ("2", _("Wednesday")),
51 ("weekend", _("Weekend")),
52 ("weekday", _("Weekday"))
56 from Plugins.SystemPlugins.vps import Vps
57 except ImportError, ie:
62 class ExtendedConfigText(ConfigText):
63 def __init__(self, default = "", fixed_size = True, visible_width = False):
64 ConfigText.__init__(self, default = default, fixed_size = fixed_size, visible_width = visible_width)
66 # Workaround some characters currently not "typeable" using NumericalTextInput
67 mapping = self.mapping
69 if "&" not in mapping[0]:
71 if ";" not in mapping[0]:
73 if "%" not in mapping[0]:
76 class SimpleBouquetSelection(SimpleChannelSelection):
77 def __init__(self, session, title):
78 SimpleChannelSelection.__init__(self, session, title)
79 self.skinName = "SimpleChannelSelection"
81 def channelSelected(self):
82 ref = self.getCurrentSelection()
83 if (ref.flags & 7) == 7:
86 # We return the currently active path here
87 # Asking the user if this is what he wants might be better though
88 self.close(self.servicePath[-1])
90 class AutoTimerChannelSelection(SimpleChannelSelection):
91 def __init__(self, session, autotimer):
92 SimpleChannelSelection.__init__(self, session, _("Channel Selection"))
93 self.skinName = "SimpleChannelSelection"
94 self.autotimer = autotimer
96 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
98 "showEPGList": self.channelSelected
102 def channelSelected(self):
103 ref = self.getCurrentSelection()
104 if (ref.flags & 7) == 7:
106 elif not (ref.flags & eServiceReference.isMarker):
108 AutoTimerEPGSelection,
112 class AutoTimerEPGSelection(EPGSelection):
113 def __init__(self, *args):
114 EPGSelection.__init__(self, *args)
115 self.skinName = "EPGSelection"
117 def infoKeyPressed(self):
121 cur = self["list"].getCurrent()
127 addAutotimerFromEvent(self.session, evt = evt, service = sref)
129 def onSelectionChanged(self):
132 class AutoTimerEditorBase:
133 """ Base Class for all Editors """
134 def __init__(self, timer, editingDefaults = False):
137 self.editingDefaults = editingDefaults
139 # See if we are filtering some strings
141 timer.getExcludedTitle(),
142 timer.getExcludedShort(),
143 timer.getExcludedDescription(),
144 timer.getExcludedDays()
147 timer.getIncludedTitle(),
148 timer.getIncludedShort(),
149 timer.getIncludedDescription(),
150 timer.getIncludedDays()
152 if excludes[0] or excludes[1] \
153 or excludes[2] or excludes[3] \
154 or includes[0] or includes[1] \
155 or includes[2] or includes[3]:
156 self.filterSet = True
158 self.filterSet = False
159 self.excludes = excludes
160 self.includes = includes
162 # See if services are restricted
163 self.services = timer.services
164 self.bouquets = timer.bouquets
165 if self.services or self.bouquets:
166 self.serviceRestriction = True
168 self.serviceRestriction = False
170 self.createSetup(timer)
172 def createSetup(self, timer):
174 self.name = NoSave(ExtendedConfigText(default = timer.name, fixed_size = False))
177 self.match = NoSave(ExtendedConfigText(default = timer.match, fixed_size = False))
180 default = timer.encoding
181 selection = ['UTF-8', 'ISO8859-15']
182 if default not in selection:
183 selection.append(default)
184 self.encoding = NoSave(ConfigSelection(choices = selection, default = default))
187 self.searchType = NoSave(ConfigSelection(choices = [("partial", _("partial match")), ("exact", _("exact match"))], default = timer.searchType))
188 self.searchCase = NoSave(ConfigSelection(choices = [("sensitive", _("case-sensitive search")), ("insensitive", _("case-insensitive search"))], default = timer.searchCase))
190 # Alternatives override
191 self.overrideAlternatives = NoSave(ConfigYesNo(default = timer.overrideAlternatives))
194 self.justplay = NoSave(ConfigSelection(choices = [("zap", _("zap")), ("record", _("record"))], default = {0: "record", 1: "zap"}[int(timer.justplay)]))
197 now = [x for x in localtime()]
198 if timer.hasTimespan():
200 now[3] = timer.timespan[0][0]
201 now[4] = timer.timespan[0][1]
203 now[3] = timer.timespan[1][0]
204 now[4] = timer.timespan[1][1]
214 self.timespan = NoSave(ConfigEnableDisable(default = default))
215 self.timespanbegin = NoSave(ConfigClock(default = begin))
216 self.timespanend = NoSave(ConfigClock(default = end))
219 if timer.hasTimeframe():
221 begin = timer.getTimeframeBegin()
222 end = timer.getTimeframeEnd()
225 now = [x for x in localtime()]
229 end = begin + 604800 # today + 7d
230 self.timeframe = NoSave(ConfigEnableDisable(default = default))
231 self.timeframebegin = NoSave(ConfigDateTime(begin, _("%d.%B %Y"), increment = 86400))
232 self.timeframeend = NoSave(ConfigDateTime(end, _("%d.%B %Y"), increment = 86400))
234 # Services have their own Screen
237 if timer.hasOffset():
239 begin = timer.getOffsetBegin()
240 end = timer.getOffsetEnd()
245 self.offset = NoSave(ConfigEnableDisable(default = default))
246 self.offsetbegin = NoSave(ConfigNumber(default = begin))
247 self.offsetend = NoSave(ConfigNumber(default = end))
250 if timer.hasAfterEvent():
253 AFTEREVENT.NONE: "nothing",
254 AFTEREVENT.DEEPSTANDBY: "deepstandby",
255 AFTEREVENT.STANDBY: "standby",
256 AFTEREVENT.AUTO: "auto"
257 }[timer.afterevent[0][0]]
260 self.afterevent = NoSave(ConfigSelection(choices = [
261 ("default", _("standard")), ("nothing", _("do nothing")),
262 ("standby", _("go to standby")),
263 ("deepstandby", _("go to deep standby")),
264 ("auto", _("auto"))], default = default))
266 # AfterEvent (Timespan)
267 if timer.hasAfterEvent() and timer.afterevent[0][1][0] is not None:
269 now[3] = timer.afterevent[0][1][0][0]
270 now[4] = timer.afterevent[0][1][0][1]
272 now[3] = timer.afterevent[0][1][1][0]
273 now[4] = timer.afterevent[0][1][1][1]
283 self.afterevent_timespan = NoSave(ConfigEnableDisable(default = default))
284 self.afterevent_timespanbegin = NoSave(ConfigClock(default = begin))
285 self.afterevent_timespanend = NoSave(ConfigClock(default = end))
288 self.enabled = NoSave(ConfigYesNo(default = timer.enabled))
291 if timer.hasDuration():
293 duration = timer.getDuration()
297 self.duration = NoSave(ConfigEnableDisable(default = default))
298 self.durationlength = NoSave(ConfigNumber(default = duration))
301 if timer.hasCounter():
302 default = timer.matchCount
305 self.counter = NoSave(ConfigNumber(default = default))
306 self.counterLeft = NoSave(ConfigNumber(default = timer.matchLeft))
307 default = timer.getCounterFormatString()
308 selection = [("", _("Never")), ("%m", _("Monthly")), ("%U", _("Weekly (Sunday)")), ("%W", _("Weekly (Monday)"))]
309 if default not in ('', '%m', '%U', '%W'):
310 selection.append((default, _("Custom (%s)") % (default)))
311 self.counterFormatString = NoSave(ConfigSelection(selection, default = default))
313 # Avoid Duplicate Description
314 self.avoidDuplicateDescription = NoSave(ConfigSelection([
316 ("1", _("On same service")),
317 ("2", _("On any service")),
318 ("3", _("Any service/recording")),
320 default = str(timer.getAvoidDuplicateDescription())
324 if timer.hasDestination():
329 self.useDestination = NoSave(ConfigYesNo(default = default))
331 default = timer.destination or Directories.resolveFilename(Directories.SCOPE_HDD)
332 choices = config.movielist.videodirs.value
334 if default not in choices:
335 choices.append(default)
336 self.destination = NoSave(ConfigSelection(default = default, choices = choices))
339 self.timerentry_tags = timer.tags
340 self.tags = NoSave(ConfigSelection(choices = [len(self.timerentry_tags) == 0 and _("None") or ' '.join(self.timerentry_tags)]))
343 self.vps_enabled = NoSave(ConfigYesNo(default = timer.vps_enabled))
344 self.vps_overwrite = NoSave(ConfigYesNo(default = timer.vps_overwrite))
346 def pathSelected(self, res):
348 # I'm pretty sure this will always fail
349 if config.movielist.videodirs.value != self.destination.choices:
350 self.destination.setChoices(config.movielist.videodirs.value, default = res)
351 self.destination.value = res
353 def chooseDestination(self):
354 from Screens.LocationBox import MovieLocationBox
356 self.session.openWithCallback(
359 _("Choose target folder"),
360 self.destination.value,
361 minFree = 100 # Same requirement as in Screens.TimerEntry
364 def tagEditFinished(self, ret):
366 self.timerentry_tags = ret
367 self.tags.setChoices([len(ret) == 0 and _("None") or ' '.join(ret)])
369 def chooseTags(self):
370 preferredTagEditor = getPreferredTagEditor()
371 if preferredTagEditor:
372 self.session.openWithCallback(
373 self.tagEditFinished,
378 class AutoTimerEditor(Screen, ConfigListScreen, AutoTimerEditorBase):
381 skin = """<screen name="AutoTimerEditor" title="Edit AutoTimer" position="center,center" size="565,350">
382 <ePixmap position="0,5" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
383 <ePixmap position="140,5" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
384 <ePixmap position="280,5" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
385 <ePixmap position="420,5" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
386 <widget source="key_red" render="Label" position="0,5" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
387 <widget source="key_green" render="Label" position="140,5" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
388 <widget source="key_yellow" render="Label" position="280,5" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
389 <widget source="key_blue" render="Label" position="420,5" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
390 <widget name="config" position="5,50" size="555,225" scrollbarMode="showOnDemand" />
391 <ePixmap pixmap="skin_default/div-h.png" position="0,275" zPosition="1" size="565,2" />
392 <widget source="help" render="Label" position="5,280" size="555,63" font="Regular;21" />
395 def __init__(self, session, timer, editingDefaults = False):
396 Screen.__init__(self, session)
398 AutoTimerEditorBase.__init__(self, timer, editingDefaults)
401 self.setup_title = _("AutoTimer Editor")
402 self.onChangedEntry = []
404 # We might need to change shown items, so add some notifiers
405 self.timespan.addNotifier(self.reloadList, initial_call = False)
406 self.timeframe.addNotifier(self.reloadList, initial_call = False)
407 self.offset.addNotifier(self.reloadList, initial_call = False)
408 self.duration.addNotifier(self.reloadList, initial_call = False)
409 self.afterevent.addNotifier(self.reloadList, initial_call = False)
410 self.afterevent_timespan.addNotifier(self.reloadList, initial_call = False)
411 self.counter.addNotifier(self.reloadList, initial_call = False)
412 self.useDestination.addNotifier(self.reloadList, initial_call = False)
417 # XXX: no help for numericaltextinput since it is shown on top of our help
418 ConfigListScreen.__init__(self, self.list, on_change = self.changed)
419 self["config"].onSelectionChanged.append(self.updateHelp)
422 self["key_red"] = StaticText(_("Cancel"))
423 self["key_green"] = StaticText(_("OK"))
424 self["key_yellow"] = StaticText()
425 self["key_blue"] = StaticText()
427 self["help"] = StaticText()
430 self.renameServiceButton()
431 self.renameFilterButton()
434 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
436 "cancel": self.cancel,
437 "save": self.maybeSave,
439 "yellow": self.editFilter,
440 "blue": self.editServices
447 self.onLayoutFinish.append(self.setCustomTitle)
449 def setCustomTitle(self):
450 self.setTitle(_("Edit AutoTimer"))
452 def renameFilterButton(self):
454 self["key_yellow"].text = _("edit filters")
456 self["key_yellow"].text = _("add filters")
458 def renameServiceButton(self):
459 if self.serviceRestriction:
460 self["key_blue"].text = _("edit services")
462 self["key_blue"].text = _("add services")
464 def updateHelp(self):
465 cur = self["config"].getCurrent()
467 self["help"].text = self.helpDict.get(cur[1], "")
470 for x in self.onChangedEntry:
476 def getCurrentEntry(self):
477 return self["config"].getCurrent()[0]
479 def getCurrentValue(self):
480 return str(self["config"].getCurrent()[1].getText())
482 def createSummary(self):
485 def initHelpTexts(self):
487 self.enabled: _("Set this NO to disable this AutoTimer."),
488 self.name: _("This is a name you can give the AutoTimer. It will be shown in the Overview and the Preview."),
489 self.match: _("This is what will be looked for in event titles. Note that looking for e.g. german umlauts can be tricky as you have to know the encoding the channel uses."),
490 self.encoding: _("Encoding the channel uses for it's EPG data. You only need to change this if you're searching for special characters like the german umlauts."),
491 self.searchType: _("Select \"exact match\" to enforce \"Match title\" to match exactly or \"partial match\" if you only want to search for a part of the event title."),
492 self.searchCase: _("Select whether or not you want to enforce case correctness."),
493 self.justplay: _("Add zap timer instead of record timer?"),
494 self.overrideAlternatives: _("With this option enabled the channel to record on can be changed to a alternative service it is restricted to."),
495 self.timespan: _("Should this AutoTimer be restricted to a timespan?"),
496 self.timespanbegin: _("Lower bound of timespan. Nothing before this time will be matched. Offsets are not taken into account!"),
497 self.timespanend: _("Upper bound of timespan. Nothing after this time will be matched. Offsets are not taken into account!"),
498 self.timeframe: _("By enabling this events will not be matched if they don't occur on certain dates."),
499 self.timeframebegin: _("First day to match events. No event that begins before this date will be matched."),
500 self.timeframeend: _("Last day to match events. Events have to begin before this date to be matched."),
501 self.offset: _("Change default recording offset?"),
502 self.offsetbegin: _("Time in minutes to prepend to recording."),
503 self.offsetend: _("Time in minutes to append to recording."),
504 self.duration: _("Should this AutoTimer only match up to a certain event duration?"),
505 self.durationlength: _("Maximum event duration to match. If an event is longer than this amount of time (without offset) it won't be matched."),
506 self.afterevent: _("Power state to change to after recordings. Select \"standard\" to not change the default behavior of enigma2 or values changed by yourself."),
507 self.afterevent_timespan: _("Restrict \"after event\" to a certain timespan?"),
508 self.afterevent_timespanbegin: _("Lower bound of timespan."),
509 self.afterevent_timespanend: _("Upper bound of timespan."),
510 self.counter: _("With this option you can restrict the AutoTimer to a certain amount of scheduled recordings. Set this to 0 to disable this functionality."),
511 self.counterLeft: _("Number of scheduled recordings left."),
512 self.counterFormatString: _("The counter can automatically be reset to the limit at certain intervals."),
513 self.avoidDuplicateDescription: _("When this option is enabled the AutoTimer won't match events where another timer with the same description already exists in the timer list."),
514 self.useDestination: _("Should timers created by this AutoTimer be recorded to a custom location?"),
515 self.destination: _("Select the location to save the recording to."),
516 self.tags: _("Tags the Timer/Recording will have."),
520 # First three entries are only showed when not editing defaults
522 if not self.editingDefaults:
524 getConfigListEntry(_("Enabled"), self.enabled),
525 getConfigListEntry(_("Description"), self.name),
526 getConfigListEntry(_("Match title"), self.match),
530 getConfigListEntry(_("EPG encoding"), self.encoding),
531 getConfigListEntry(_("Search type"), self.searchType),
532 getConfigListEntry(_("Search strictness"), self.searchCase),
533 getConfigListEntry(_("Timer type"), self.justplay),
534 getConfigListEntry(_("Override found with alternative service"), self.overrideAlternatives),
535 getConfigListEntry(_("Only match during timespan"), self.timespan)
538 # Only allow editing timespan when it's enabled
539 if self.timespan.value:
541 getConfigListEntry(_("Begin of timespan"), self.timespanbegin),
542 getConfigListEntry(_("End of timespan"), self.timespanend)
545 list.append(getConfigListEntry(_("Restrict to events on certain dates"), self.timeframe))
547 # Only allow editing timeframe when it's enabled
548 if self.timeframe.value:
550 getConfigListEntry(_("Not before"), self.timeframebegin),
551 getConfigListEntry(_("Not after"), self.timeframeend)
554 list.append(getConfigListEntry(_("Custom offset"), self.offset))
556 # Only allow editing offsets when it's enabled
557 if self.offset.value:
559 getConfigListEntry(_("Offset before recording (in m)"), self.offsetbegin),
560 getConfigListEntry(_("Offset after recording (in m)"), self.offsetend)
563 list.append(getConfigListEntry(_("Set maximum duration"), self.duration))
565 # Only allow editing maxduration when it's enabled
566 if self.duration.value:
567 list.append(getConfigListEntry(_("Maximum duration (in m)"), self.durationlength))
569 list.append(getConfigListEntry(_("After event"), self.afterevent))
571 # Only allow setting afterevent timespan when afterevent is active
572 if self.afterevent.value != "default":
573 list.append(getConfigListEntry(_("Execute \"after event\" during timespan"), self.afterevent_timespan))
575 # Only allow editing timespan when it's enabled
576 if self.afterevent_timespan.value:
578 getConfigListEntry(_("Begin of \"after event\" timespan"), self.afterevent_timespanbegin),
579 getConfigListEntry(_("End of \"after event\" timespan"), self.afterevent_timespanend)
582 list.append(getConfigListEntry(_("Record a maximum of x times"), self.counter))
584 # Only allow setting matchLeft when counting hits
585 if self.counter.value:
586 if not self.editingDefaults:
587 list.append(getConfigListEntry(_("Amount of recordings left"), self.counterLeft))
588 list.append(getConfigListEntry(_("Reset count"), self.counterFormatString))
590 list.append(getConfigListEntry(_("Require description to be unique"), self.avoidDuplicateDescription))
592 # We always add this option though its expert only in enigma2
593 list.append(getConfigListEntry(_("Use a custom location"), self.useDestination))
594 if self.useDestination.value:
595 list.append(getConfigListEntry(_("Custom location"), self.destination))
597 list.append(getConfigListEntry(_("Tags"), self.tags))
600 list.append(getConfigListEntry(_("Activate VPS"), self.vps_enabled))
601 if self.vps_enabled.value:
602 list.append(getConfigListEntry(_("Control recording completely by service"), self.vps_overwrite))
606 def reloadList(self, value):
608 self["config"].setList(self.list)
610 def editFilter(self):
611 self.session.openWithCallback(
612 self.editFilterCallback,
613 AutoTimerFilterEditor,
619 def editFilterCallback(self, ret):
621 self.filterSet = ret[0]
622 self.excludes = ret[1]
623 self.includes = ret[2]
624 self.renameFilterButton()
626 def editServices(self):
627 self.session.openWithCallback(
628 self.editServicesCallback,
629 AutoTimerServiceEditor,
630 self.serviceRestriction,
635 def editServicesCallback(self, ret):
637 self.serviceRestriction = ret[0]
638 self.services = ret[1][0]
639 self.bouquets = ret[1][1]
640 self.renameServiceButton()
643 cur = self["config"].getCurrent()
648 ConfigListScreen.keyLeft(self)
651 cur = self["config"].getCurrent()
656 ConfigListScreen.keyRight(self)
659 cur = self["config"].getCurrent()
661 if cur == self.destination:
662 self.chooseDestination()
663 elif cur == self.tags:
666 ConfigListScreen.keyOK(self)
669 if self["config"].isChanged():
670 self.session.openWithCallback(
673 _("Really close without saving settings?")
678 def cancelConfirm(self, ret):
683 if self.editingDefaults:
686 # Check if any match is set
687 if not self.match.value.strip():
690 _("The match attribute is mandatory."),
691 type = MessageBox.TYPE_ERROR,
694 # Check if we have a trailing whitespace
695 elif self.match.value[-1:] == " ":
696 self.session.openWithCallback(
699 _('You entered "%s" as Text to match.\nDo you want to remove trailing whitespaces?') % (self.match.value)
705 def saveCallback(self, ret):
708 self.match.value = self.match.value.rstrip()
710 # Don't to anything if MessageBox was canceled!
714 self.timer.match = self.match.value
717 self.timer.name = self.name.value.strip() or self.timer.match
720 self.timer.encoding = self.encoding.value
723 self.timer.searchType = self.searchType.value
724 self.timer.searchCase = self.searchCase.value
727 self.timer.overrideAlternatives = self.overrideAlternatives.value
730 self.timer.enabled = self.enabled.value
733 self.timer.justplay = self.justplay.value == "zap"
736 if self.timespan.value:
737 start = self.timespanbegin.value
738 end = self.timespanend.value
739 self.timer.timespan = (start, end)
741 self.timer.timespan = None
744 if self.timeframe.value:
745 start = self.timeframebegin.value
746 end = self.timeframeend.value
747 self.timer.timeframe = (start, end)
749 self.timer.timeframe = None
752 if self.serviceRestriction:
753 self.timer.services = self.services
754 self.timer.bouquets = self.bouquets
756 self.timer.services = None
757 self.timer.bouquets = None
760 if self.offset.value:
761 self.timer.offset = (self.offsetbegin.value*60, self.offsetend.value*60)
763 self.timer.offset = None
766 if self.afterevent.value == "default":
767 self.timer.afterevent = []
770 "nothing": AFTEREVENT.NONE,
771 "deepstandby": AFTEREVENT.DEEPSTANDBY,
772 "standby": AFTEREVENT.STANDBY,
773 "auto": AFTEREVENT.AUTO
774 }[self.afterevent.value]
775 # AfterEvent Timespan
776 if self.afterevent_timespan.value:
777 start = self.afterevent_timespanbegin.value
778 end = self.afterevent_timespanend.value
779 self.timer.afterevent = [(afterevent, (start, end))]
781 self.timer.afterevent = [(afterevent, None)]
784 if self.duration.value:
785 self.timer.maxduration = self.durationlength.value*60
787 self.timer.maxduration = None
791 self.timer.exclude = self.excludes
792 self.timer.include = self.includes
794 self.timer.exclude = None
795 self.timer.include = None
798 if self.counter.value:
799 self.timer.matchCount = self.counter.value
800 if self.counterLeft.value <= self.counter.value:
801 self.timer.matchLeft = self.counterLeft.value
803 self.timer.matchLeft = self.counter.value
804 if self.counterFormatString.value:
805 self.timer.matchFormatString = self.counterFormatString.value
807 self.timer.matchFormatString = ''
809 self.timer.matchCount = 0
810 self.timer.matchLeft = 0
811 self.timer.matchFormatString = ''
813 self.timer.avoidDuplicateDescription = int(self.avoidDuplicateDescription.value)
815 if self.useDestination.value:
816 self.timer.destination = self.destination.value
818 self.timer.destination = None
820 self.timer.tags = self.timerentry_tags
822 self.timer.vps_enabled = self.vps_enabled.value
823 self.timer.vps_overwrite = self.vps_overwrite.value
826 self.close(self.timer)
828 class AutoTimerFilterEditor(Screen, ConfigListScreen):
829 """Edit AutoTimer Filter"""
831 skin = """<screen name="AutoTimerFilterEditor" title="Edit AutoTimer Filters" position="center,center" size="565,280">
832 <ePixmap position="0,0" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
833 <ePixmap position="140,0" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
834 <ePixmap position="280,0" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
835 <ePixmap position="420,0" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
836 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
837 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
838 <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
839 <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
840 <widget name="config" position="5,45" size="555,225" scrollbarMode="showOnDemand" />
843 def __init__(self, session, filterset, excludes, includes):
844 Screen.__init__(self, session)
847 self.setup_title = _("AutoTimer Filters")
848 self.onChangedEntry = []
850 self.typeSelection = NoSave(ConfigSelection(choices = [
851 ("title", _("in Title")),
852 ("short", _("in Shortdescription")),
853 ("desc", _("in Description")),
854 ("day", _("on Weekday"))]
856 self.typeSelection.addNotifier(self.refresh, initial_call = False)
858 self.enabled = NoSave(ConfigEnableDisable(default = filterset))
860 self.excludes = excludes
861 self.includes = includes
865 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
868 self["key_red"] = StaticText(_("Cancel"))
869 self["key_green"] = StaticText(_("Save"))
870 self["key_yellow"] = StaticText(_("delete"))
871 self["key_blue"] = StaticText(_("New"))
874 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
876 "cancel": self.cancel,
878 "yellow": self.remove,
886 self.onLayoutFinish.append(self.setCustomTitle)
888 def setCustomTitle(self):
889 self.setTitle(_("Edit AutoTimer filters"))
893 for x in self.onChangedEntry:
899 def getCurrentEntry(self):
900 return self["config"].getCurrent()[0]
902 def getCurrentValue(self):
903 return str(self["config"].getCurrent()[1].getText())
905 def createSummary(self):
908 def saveCurrent(self):
909 del self.excludes[self.idx][:]
910 del self.includes[self.idx][:]
912 # Warning, accessing a ConfigListEntry directly might be considered evil!
915 for item in self["config"].getList()[:]:
917 # Skip empty entries (and those which are no filters)
918 if item[1].value == "" or idx < 2:
920 elif idx < self.lenExcludes:
921 self.excludes[self.idx].append(item[1].value.encode("UTF-8"))
923 self.includes[self.idx].append(item[1].value.encode("UTF-8"))
925 def refresh(self, *args, **kwargs):
929 self["config"].setList(self.list)
931 def reloadList(self):
933 getConfigListEntry(_("Enable Filtering"), self.enabled),
934 getConfigListEntry(_("Filter"), self.typeSelection)
937 if self.typeSelection.value == "day":
940 # Weekdays are presented as ConfigSelection
942 getConfigListEntry(_("Exclude"), NoSave(ConfigSelection(choices = weekdays, default = x)))
943 for x in self.excludes[3]
945 self.lenExcludes = len(self.list)
947 getConfigListEntry(_("Include"), NoSave(ConfigSelection(choices = weekdays, default = x)))
948 for x in self.includes[3]
951 elif self.typeSelection.value == "title":
953 elif self.typeSelection.value == "short":
955 else: # self.typeSelection.value == "desc":
959 getConfigListEntry(_("Exclude"), NoSave(ExtendedConfigText(default = x, fixed_size = False)))
960 for x in self.excludes[self.idx]
962 self.lenExcludes = len(self.list)
964 getConfigListEntry(_("Include"), NoSave(ExtendedConfigText(default = x, fixed_size = False)))
965 for x in self.includes[self.idx]
969 idx = self["config"].getCurrentIndex()
971 if idx < self.lenExcludes:
972 self.lenExcludes -= 1
974 list = self["config"].getList()
975 list.remove(self["config"].getCurrent())
976 self["config"].setList(list)
979 self.session.openWithCallback(
982 _("Select type of Filter"),
989 def typeSelected(self, ret):
991 list = self["config"].getList()
994 pos = self.lenExcludes
995 self.lenExcludes += 1
1001 if self.typeSelection.value == "day":
1002 entry = getConfigListEntry(text, NoSave(ConfigSelection(choices = weekdays)))
1004 entry = getConfigListEntry(text, NoSave(ExtendedConfigText(fixed_size = False)))
1006 list.insert(pos, entry)
1007 self["config"].setList(list)
1010 if self["config"].isChanged():
1011 self.session.openWithCallback(
1014 _("Really close without saving settings?")
1019 def cancelConfirm(self, ret):
1032 class AutoTimerServiceEditor(Screen, ConfigListScreen):
1033 """Edit allowed Services of a AutoTimer"""
1035 skin = """<screen name="AutoTimerServiceEditor" title="Edit AutoTimer Services" position="center,center" size="565,280">
1036 <ePixmap position="0,0" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
1037 <ePixmap position="140,0" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
1038 <ePixmap position="280,0" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
1039 <ePixmap position="420,0" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
1040 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1041 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1042 <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1043 <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
1044 <widget name="config" position="5,45" size="555,225" scrollbarMode="showOnDemand" />
1047 def __init__(self, session, servicerestriction, servicelist, bouquetlist):
1048 Screen.__init__(self, session)
1051 self.setup_title = _("AutoTimer Services")
1052 self.onChangedEntry = []
1059 self.enabled = NoSave(ConfigEnableDisable(default = servicerestriction))
1060 self.typeSelection = NoSave(ConfigSelection(choices = [
1061 ("channels", _("Channels")),
1062 ("bouquets", _("Bouquets"))]
1064 self.typeSelection.addNotifier(self.refresh, initial_call = False)
1068 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
1070 # Initialize Buttons
1071 self["key_red"] = StaticText(_("Cancel"))
1072 self["key_green"] = StaticText(_("OK"))
1073 self["key_yellow"] = StaticText(_("delete"))
1074 self["key_blue"] = StaticText(_("New"))
1077 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
1079 "cancel": self.cancel,
1081 "yellow": self.remove,
1089 self.onLayoutFinish.append(self.setCustomTitle)
1091 def setCustomTitle(self):
1092 self.setTitle(_("Edit AutoTimer services"))
1094 def saveCurrent(self):
1095 del self.services[self.idx][:]
1097 # Warning, accessing a ConfigListEntry directly might be considered evil!
1099 myl = self["config"].getList()[:]
1100 myl.pop(0) # Enabled
1103 self.services[self.idx].append(item[1].value)
1105 def refresh(self, *args, **kwargs):
1109 self["config"].setList(self.list)
1111 def reloadList(self):
1113 getConfigListEntry(_("Enable Service Restriction"), self.enabled),
1114 getConfigListEntry(_("Editing"), self.typeSelection)
1117 if self.typeSelection.value == "channels":
1119 else: # self.typeSelection.value == "bouquets":
1123 getConfigListEntry(_("Record on"), NoSave(ConfigSelection(choices = [(str(x), ServiceReference(str(x)).getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''))])))
1124 for x in self.services[self.idx]
1128 for x in self.onChangedEntry:
1134 def getCurrentEntry(self):
1135 return self["config"].getCurrent()[0]
1137 def getCurrentValue(self):
1138 return str(self["config"].getCurrent()[1].getText())
1140 def createSummary(self):
1144 if self["config"].getCurrentIndex() != 0:
1145 list = self["config"].getList()
1146 list.remove(self["config"].getCurrent())
1147 self["config"].setList(list)
1150 if self.typeSelection.value == "channels":
1151 self.session.openWithCallback(
1152 self.finishedServiceSelection,
1153 SimpleChannelSelection,
1154 _("Select channel to record on")
1156 else: # self.typeSelection.value == "bouquets":
1157 self.session.openWithCallback(
1158 self.finishedServiceSelection,
1159 SimpleBouquetSelection,
1160 _("Select bouquet to record on")
1163 def finishedServiceSelection(self, *args):
1165 list = self["config"].getList()
1166 sname = args[0].toString()
1168 if self.typeSelection.value == "channels" and not (args[0].flags & eServiceReference.isGroup):
1169 # strip all after last : when adding a (non alternative) channel
1170 pos = sname.rfind(':')
1172 if sname[pos-1] == ':':
1174 sname = sname[:pos+1]
1176 list.append(getConfigListEntry(_("Record on"), NoSave(ConfigSelection(choices = [(sname, ServiceReference(args[0]).getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''))]))))
1177 self["config"].setList(list)
1180 if self["config"].isChanged():
1181 self.session.openWithCallback(
1184 _("Really close without saving settings?")
1189 def cancelConfirm(self, ret):
1201 def addAutotimerFromSearchString(session, match):
1202 from AutoTimerComponent import preferredAutoTimerComponent
1203 from AutoTimerImporter import AutoTimerImporter
1204 from plugin import autotimer
1206 # Create instance if needed
1207 if autotimer is None:
1208 from AutoTimer import AutoTimer
1209 autotimer = AutoTimer()
1212 newTimer = autotimer.defaultTimer.clone()
1213 newTimer.id = autotimer.getUniqueId()
1214 newTimer.name = match
1216 newTimer.enabled = True
1218 session.openWithCallback(
1222 match, # Proposed Match
1223 None, # Proposed Begin
1224 None, # Proposed End
1225 None, # Proposed Disabled
1226 None, # Proposed ServiceReference
1227 None, # Proposed afterEvent
1228 None, # Proposed justplay
1229 None, # Proposed dirname, can we get anything useful here?
1233 def addAutotimerFromEvent(session, evt = None, service = None):
1234 from AutoTimerComponent import preferredAutoTimerComponent
1235 from AutoTimerImporter import AutoTimerImporter
1236 from plugin import autotimer
1238 # Create instance if needed
1239 if autotimer is None:
1240 from AutoTimer import AutoTimer
1241 autotimer = AutoTimer()
1244 match = evt and evt.getEventName() or ""
1245 name = match or "New AutoTimer"
1247 if service is not None:
1248 service = str(service)
1249 myref = eServiceReference(service)
1250 if not (myref.flags & eServiceReference.isGroup):
1251 # strip all after last :
1252 pos = service.rfind(':')
1254 if service[pos-1] == ':':
1256 service = service[:pos+1]
1258 sref = ServiceReference(myref)
1260 # timespan defaults to +- 1h
1261 begin = evt.getBeginTime()-3600
1262 end = begin + evt.getDuration()+7200
1266 # XXX: we might want to make sure that we actually collected any data because the importer does not do so :-)
1268 newTimer = autotimer.defaultTimer.clone()
1269 newTimer.id = autotimer.getUniqueId()
1270 newTimer.name = name
1272 newTimer.enabled = True
1274 session.openWithCallback(
1278 match, # Proposed Match
1279 begin, # Proposed Begin
1281 None, # Proposed Disabled
1282 sref, # Proposed ServiceReference
1283 None, # Proposed afterEvent
1284 None, # Proposed justplay
1285 None, # Proposed dirname, can we get anything useful here?
1289 def addAutotimerFromService(session, service = None):
1290 from AutoTimerComponent import preferredAutoTimerComponent
1291 from AutoTimerImporter import AutoTimerImporter
1292 from plugin import autotimer
1294 # Create instance if needed
1295 if autotimer is None:
1296 from AutoTimer import AutoTimer
1297 autotimer = AutoTimer()
1300 serviceHandler = eServiceCenter.getInstance()
1301 info = serviceHandler.info(service)
1303 match = info and info.getName(service) or ""
1304 name = match or "New AutoTimer"
1305 sref = info and info.getInfoString(service, iServiceInformation.sServiceref)
1307 # strip all after last :
1308 pos = sref.rfind(':')
1310 if sref[pos-1] == ':':
1314 sref = ServiceReference(sref)
1316 begin = info.getInfo(service, iServiceInformation.sTimeCreate)
1317 end = begin + info.getLength(service)
1321 from os.path import dirname
1322 path = dirname(service.getPath())
1326 tags = info.getInfoString(service, iServiceInformation.sTags)
1327 tags = tags and tags.split(' ') or []
1329 # XXX: we might want to make sure that we actually collected any data because the importer does not do so :-)
1331 session.openWithCallback(
1334 preferredAutoTimerComponent(
1335 autotimer.getUniqueId(),
1340 match, # Proposed Match
1341 begin, # Proposed Begin
1343 None, # Proposed Disabled
1344 sref, # Proposed ServiceReference
1345 None, # Proposed afterEvent
1346 None, # Proposed justplay
1347 path, # Proposed dirname
1348 tags # Proposed tags
1351 def importerCallback(ret):
1355 session.openWithCallback(
1361 # Remove instance if not running in background
1362 if not config.plugins.autotimer.autopoll.value:
1363 from plugin import autotimer
1366 def editorCallback(ret):
1368 from plugin import autotimer
1370 # Create instance if needed (should have been created by addAutotimerFrom* above though)
1371 if autotimer is None:
1372 from AutoTimer import AutoTimer
1373 autotimer = AutoTimer()
1379 autotimer.writeXml()
1381 # Remove instance if not running in background
1382 if not config.plugins.autotimer.autopoll.value: