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, \
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"))
55 class ExtendedConfigText(ConfigText):
56 def __init__(self, default = "", fixed_size = True, visible_width = False):
57 ConfigText.__init__(self, default = default, fixed_size = fixed_size, visible_width = visible_width)
59 # Workaround some characters currently not "typeable" using NumericalTextInput
60 mapping = self.mapping
62 if "&" not in mapping[0]:
64 if ";" not in mapping[0]:
66 if "%" not in mapping[0]:
69 class SimpleBouquetSelection(SimpleChannelSelection):
70 def __init__(self, session, title):
71 SimpleChannelSelection.__init__(self, session, title)
72 self.skinName = "SimpleChannelSelection"
74 def channelSelected(self):
75 ref = self.getCurrentSelection()
76 if (ref.flags & 7) == 7:
79 # We return the currently active path here
80 # Asking the user if this is what he wants might be better though
81 self.close(self.servicePath[-1])
83 class AutoTimerChannelSelection(SimpleChannelSelection):
84 def __init__(self, session, autotimer):
85 SimpleChannelSelection.__init__(self, session, _("Channel Selection"))
86 self.skinName = "SimpleChannelSelection"
87 self.autotimer = autotimer
89 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
91 "showEPGList": self.channelSelected
95 def channelSelected(self):
96 ref = self.getCurrentSelection()
97 if (ref.flags & 7) == 7:
99 elif not (ref.flags & eServiceReference.isMarker):
101 AutoTimerEPGSelection,
105 class AutoTimerEPGSelection(EPGSelection):
106 def __init__(self, *args):
107 EPGSelection.__init__(self, *args)
108 self.skinName = "EPGSelection"
110 def infoKeyPressed(self):
114 cur = self["list"].getCurrent()
120 addAutotimerFromEvent(self.session, evt = evt, service = sref)
122 def onSelectionChanged(self):
125 class AutoTimerEditorBase:
126 """ Base Class for all Editors """
127 def __init__(self, timer, editingDefaults = False):
130 self.editingDefaults = editingDefaults
132 # See if we are filtering some strings
134 timer.getExcludedTitle(),
135 timer.getExcludedShort(),
136 timer.getExcludedDescription(),
137 timer.getExcludedDays()
140 timer.getIncludedTitle(),
141 timer.getIncludedShort(),
142 timer.getIncludedDescription(),
143 timer.getIncludedDays()
145 if excludes[0] or excludes[1] \
146 or excludes[2] or excludes[3] \
147 or includes[0] or includes[1] \
148 or includes[2] or includes[3]:
149 self.filterSet = True
151 self.filterSet = False
152 self.excludes = excludes
153 self.includes = includes
155 # See if services are restricted
156 self.services = timer.services
157 self.bouquets = timer.bouquets
158 if self.services or self.bouquets:
159 self.serviceRestriction = True
161 self.serviceRestriction = False
163 self.createSetup(timer)
165 def createSetup(self, timer):
167 self.name = NoSave(ExtendedConfigText(default = timer.name, fixed_size = False))
170 self.match = NoSave(ExtendedConfigText(default = timer.match, fixed_size = False))
173 default = timer.encoding
174 selection = ['UTF-8', 'ISO8859-15']
175 if default not in selection:
176 selection.append(default)
177 self.encoding = NoSave(ConfigSelection(choices = selection, default = default))
180 self.searchType = NoSave(ConfigSelection(choices = [("partial", _("partial match")), ("exact", _("exact match"))], default = timer.searchType))
181 self.searchCase = NoSave(ConfigSelection(choices = [("sensitive", _("case-sensitive search")), ("insensitive", _("case-insensitive search"))], default = timer.searchCase))
183 # Alternatives override
184 self.overrideAlternatives = NoSave(ConfigYesNo(default = timer.overrideAlternatives))
187 self.justplay = NoSave(ConfigSelection(choices = [("zap", _("zap")), ("record", _("record"))], default = {0: "record", 1: "zap"}[int(timer.justplay)]))
190 now = [x for x in localtime()]
191 if timer.hasTimespan():
193 now[3] = timer.timespan[0][0]
194 now[4] = timer.timespan[0][1]
196 now[3] = timer.timespan[1][0]
197 now[4] = timer.timespan[1][1]
207 self.timespan = NoSave(ConfigEnableDisable(default = default))
208 self.timespanbegin = NoSave(ConfigClock(default = begin))
209 self.timespanend = NoSave(ConfigClock(default = end))
211 # Services have their own Screen
214 if timer.hasOffset():
216 begin = timer.getOffsetBegin()
217 end = timer.getOffsetEnd()
222 self.offset = NoSave(ConfigEnableDisable(default = default))
223 self.offsetbegin = NoSave(ConfigNumber(default = begin))
224 self.offsetend = NoSave(ConfigNumber(default = end))
227 if timer.hasAfterEvent():
230 AFTEREVENT.NONE: "nothing",
231 AFTEREVENT.DEEPSTANDBY: "deepstandby",
232 AFTEREVENT.STANDBY: "standby",
233 AFTEREVENT.AUTO: "auto"
234 }[timer.afterevent[0][0]]
237 self.afterevent = NoSave(ConfigSelection(choices = [
238 ("default", _("standard")), ("nothing", _("do nothing")),
239 ("standby", _("go to standby")),
240 ("deepstandby", _("go to deep standby")),
241 ("auto", _("auto"))], default = default))
243 # AfterEvent (Timespan)
244 if timer.hasAfterEvent() and timer.afterevent[0][1][0] is not None:
246 now[3] = timer.afterevent[0][1][0][0]
247 now[4] = timer.afterevent[0][1][0][1]
249 now[3] = timer.afterevent[0][1][1][0]
250 now[4] = timer.afterevent[0][1][1][1]
260 self.afterevent_timespan = NoSave(ConfigEnableDisable(default = default))
261 self.afterevent_timespanbegin = NoSave(ConfigClock(default = begin))
262 self.afterevent_timespanend = NoSave(ConfigClock(default = end))
265 self.enabled = NoSave(ConfigYesNo(default = timer.enabled))
268 if timer.hasDuration():
270 duration = timer.getDuration()
274 self.duration = NoSave(ConfigEnableDisable(default = default))
275 self.durationlength = NoSave(ConfigNumber(default = duration))
278 if timer.hasCounter():
279 default = timer.matchCount
282 self.counter = NoSave(ConfigNumber(default = default))
283 self.counterLeft = NoSave(ConfigNumber(default = timer.matchLeft))
284 default = timer.getCounterFormatString()
285 selection = [("", _("Never")), ("%m", _("Monthly")), ("%U", _("Weekly (Sunday)")), ("%W", _("Weekly (Monday)"))]
286 if default not in ('', '%m', '%U', '%W'):
287 selection.append((default, _("Custom (%s)") % (default)))
288 self.counterFormatString = NoSave(ConfigSelection(selection, default = default))
290 # Avoid Duplicate Description
291 self.avoidDuplicateDescription = NoSave(ConfigSelection([
293 ("1", _("On same service")),
294 ("2", _("On any service")),
296 default = str(timer.getAvoidDuplicateDescription())
300 if timer.hasDestination():
305 self.useDestination = NoSave(ConfigYesNo(default = default))
307 default = timer.destination or Directories.resolveFilename(Directories.SCOPE_HDD)
308 choices = config.movielist.videodirs.value
310 if default not in choices:
311 choices.append(default)
312 self.destination = NoSave(ConfigSelection(default = default, choices = choices))
315 self.timerentry_tags = timer.tags
316 self.tags = NoSave(ConfigSelection(choices = [len(self.timerentry_tags) == 0 and _("None") or ' '.join(self.timerentry_tags)]))
318 def pathSelected(self, res):
320 # I'm pretty sure this will always fail
321 if config.movielist.videodirs.value != self.destination.choices:
322 self.destination.setChoices(config.movielist.videodirs.value, default = res)
323 self.destination.value = res
325 def chooseDestination(self):
326 from Screens.LocationBox import MovieLocationBox
328 self.session.openWithCallback(
331 _("Choose target folder"),
332 self.destination.value,
333 minFree = 100 # Same requirement as in Screens.TimerEntry
336 def tagEditFinished(self, ret):
338 self.timerentry_tags = ret
339 self.tags.setChoices([len(ret) == 0 and _("None") or ' '.join(ret)])
341 def chooseTags(self):
342 preferredTagEditor = getPreferredTagEditor()
343 if preferredTagEditor:
344 self.session.openWithCallback(
345 self.tagEditFinished,
350 class AutoTimerEditor(Screen, ConfigListScreen, AutoTimerEditorBase):
353 skin = """<screen name="AutoTimerEditor" title="Edit AutoTimer" position="center,center" size="565,350">
354 <ePixmap position="0,5" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
355 <ePixmap position="140,5" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
356 <ePixmap position="280,5" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
357 <ePixmap position="420,5" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
358 <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" />
359 <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" />
360 <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" />
361 <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" />
362 <widget name="config" position="5,50" size="555,225" scrollbarMode="showOnDemand" />
363 <ePixmap pixmap="skin_default/div-h.png" position="0,275" zPosition="1" size="565,2" />
364 <widget source="help" render="Label" position="5,280" size="555,63" font="Regular;21" />
367 def __init__(self, session, timer, editingDefaults = False):
368 Screen.__init__(self, session)
370 AutoTimerEditorBase.__init__(self, timer, editingDefaults)
373 self.setup_title = _("AutoTimer Editor")
374 self.onChangedEntry = []
376 # We might need to change shown items, so add some notifiers
377 self.timespan.addNotifier(self.reloadList, initial_call = False)
378 self.offset.addNotifier(self.reloadList, initial_call = False)
379 self.duration.addNotifier(self.reloadList, initial_call = False)
380 self.afterevent.addNotifier(self.reloadList, initial_call = False)
381 self.afterevent_timespan.addNotifier(self.reloadList, initial_call = False)
382 self.counter.addNotifier(self.reloadList, initial_call = False)
383 self.useDestination.addNotifier(self.reloadList, initial_call = False)
388 # XXX: no help for numericaltextinput since it is shown on top of our help
389 ConfigListScreen.__init__(self, self.list, on_change = self.changed)
390 self["config"].onSelectionChanged.append(self.updateHelp)
393 self["key_red"] = StaticText(_("Cancel"))
394 self["key_green"] = StaticText(_("OK"))
395 self["key_yellow"] = StaticText()
396 self["key_blue"] = StaticText()
398 self["help"] = StaticText()
401 self.renameServiceButton()
402 self.renameFilterButton()
405 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
407 "cancel": self.cancel,
408 "save": self.maybeSave,
410 "yellow": self.editFilter,
411 "blue": self.editServices
418 self.onLayoutFinish.append(self.setCustomTitle)
420 def setCustomTitle(self):
421 self.setTitle(_("Edit AutoTimer"))
423 def renameFilterButton(self):
425 self["key_yellow"].text = _("edit filters")
427 self["key_yellow"].text = _("add filters")
429 def renameServiceButton(self):
430 if self.serviceRestriction:
431 self["key_blue"].text = _("edit services")
433 self["key_blue"].text = _("add services")
435 def updateHelp(self):
436 cur = self["config"].getCurrent()
438 self["help"].text = self.helpDict[cur[1]]
441 for x in self.onChangedEntry:
447 def getCurrentEntry(self):
448 return self["config"].getCurrent()[0]
450 def getCurrentValue(self):
451 return str(self["config"].getCurrent()[1].getText())
453 def createSummary(self):
456 def initHelpTexts(self):
458 self.enabled: _("Set this NO to disable this AutoTimer."),
459 self.name: _("This is a name you can give the AutoTimer. It will be shown in the Overview and the Preview."),
460 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."),
461 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."),
462 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."),
463 self.searchCase: _("Select whether or not you want to enforce case correctness."),
464 self.justplay: _("Add zap timer instead of record timer?"),
465 self.overrideAlternatives: _("With this option enabled the channel to record on can be changed to a alternative service it is restricted to."),
466 self.timespan: _("Should this AutoTimer be restricted to a timespan?"),
467 self.timespanbegin: _("Lower bound of timespan. Nothing before this time will be matched. Offsets are not taken into account!"),
468 self.timespanend: _("Upper bound of timespan. Nothing after this time will be matched. Offsets are not taken into account!"),
469 self.offset: _("Change default recording offset?"),
470 self.offsetbegin: _("Time in minutes to prepend to recording."),
471 self.offsetend: _("Time in minutes to append to recording."),
472 self.duration: _("Should this AutoTimer only match up to a certain event duration?"),
473 self.durationlength: _("Maximum event duration to match. If an event is longer than this ammount of time (without offset) it won't be matched."),
474 self.afterevent: _("Power state to change to after recordings. Select \"standard\" to not change the default behavior of enigma2 or values changed by yourself."),
475 self.afterevent_timespan: _("Restrict \"after event\" to a certain timespan?"),
476 self.afterevent_timespanbegin: _("Lower bound of timespan."),
477 self.afterevent_timespanend: _("Upper bound of timespan."),
478 self.counter: _("With this option you can restrict the AutoTimer to a certain ammount of scheduled recordings. Set this to 0 to disable this functionality."),
479 self.counterLeft: _("Number of scheduled recordings left."),
480 self.counterFormatString: _("The counter can automatically be reset to the limit at certain intervals."),
481 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."),
482 self.useDestination: _("Should timers created by this AutoTimer be recorded to a custom location?"),
483 self.destination: _("Select the location to save the recording to."),
484 self.tags: _("Tags the Timer/Recording will have."),
488 # First three entries are only showed when not editing defaults
490 if not self.editingDefaults:
492 getConfigListEntry(_("Enabled"), self.enabled),
493 getConfigListEntry(_("Description"), self.name),
494 getConfigListEntry(_("Match title"), self.match),
498 getConfigListEntry(_("EPG encoding"), self.encoding),
499 getConfigListEntry(_("Search type"), self.searchType),
500 getConfigListEntry(_("Search strictness"), self.searchCase),
501 getConfigListEntry(_("Timer type"), self.justplay),
502 getConfigListEntry(_("Override found with alternative service"), self.overrideAlternatives),
503 getConfigListEntry(_("Only match during timespan"), self.timespan)
506 # Only allow editing timespan when it's enabled
507 if self.timespan.value:
509 getConfigListEntry(_("Begin of timespan"), self.timespanbegin),
510 getConfigListEntry(_("End of timespan"), self.timespanend)
513 list.append(getConfigListEntry(_("Custom offset"), self.offset))
515 # Only allow editing offsets when it's enabled
516 if self.offset.value:
518 getConfigListEntry(_("Offset before recording (in m)"), self.offsetbegin),
519 getConfigListEntry(_("Offset after recording (in m)"), self.offsetend)
522 list.append(getConfigListEntry(_("Set maximum duration"), self.duration))
524 # Only allow editing maxduration when it's enabled
525 if self.duration.value:
526 list.append(getConfigListEntry(_("Maximum duration (in m)"), self.durationlength))
528 list.append(getConfigListEntry(_("After event"), self.afterevent))
530 # Only allow setting afterevent timespan when afterevent is active
531 if self.afterevent.value != "default":
532 list.append(getConfigListEntry(_("Execute \"after event\" during timespan"), self.afterevent_timespan))
534 # Only allow editing timespan when it's enabled
535 if self.afterevent_timespan.value:
537 getConfigListEntry(_("Begin of \"after event\" timespan"), self.afterevent_timespanbegin),
538 getConfigListEntry(_("End of \"after event\" timespan"), self.afterevent_timespanend)
541 list.append(getConfigListEntry(_("Record a maximum of x times"), self.counter))
543 # Only allow setting matchLeft when counting hits
544 if self.counter.value:
545 if not self.editingDefaults:
546 list.append(getConfigListEntry(_("Ammount of recordings left"), self.counterLeft))
547 list.append(getConfigListEntry(_("Reset count"), self.counterFormatString))
549 list.append(getConfigListEntry(_("Require description to be unique"), self.avoidDuplicateDescription))
551 # We always add this option though its expert only in enigma2
552 list.append(getConfigListEntry(_("Use a custom location"), self.useDestination))
553 if self.useDestination.value:
554 list.append(getConfigListEntry(_("Custom location"), self.destination))
556 list.append(getConfigListEntry(_("Tags"), self.tags))
560 def reloadList(self, value):
562 self["config"].setList(self.list)
564 def editFilter(self):
565 self.session.openWithCallback(
566 self.editFilterCallback,
567 AutoTimerFilterEditor,
573 def editFilterCallback(self, ret):
575 self.filterSet = ret[0]
576 self.excludes = ret[1]
577 self.includes = ret[2]
578 self.renameFilterButton()
580 def editServices(self):
581 self.session.openWithCallback(
582 self.editServicesCallback,
583 AutoTimerServiceEditor,
584 self.serviceRestriction,
589 def editServicesCallback(self, ret):
591 self.serviceRestriction = ret[0]
592 self.services = ret[1][0]
593 self.bouquets = ret[1][1]
594 self.renameServiceButton()
597 cur = self["config"].getCurrent()
602 ConfigListScreen.keyLeft(self)
605 cur = self["config"].getCurrent()
610 ConfigListScreen.keyRight(self)
613 cur = self["config"].getCurrent()
615 if cur == self.destination:
616 self.chooseDestination()
617 elif cur == self.tags:
620 ConfigListScreen.keyOK(self)
623 if self["config"].isChanged():
624 self.session.openWithCallback(
627 _("Really close without saving settings?")
632 def cancelConfirm(self, ret):
637 if self.editingDefaults:
640 # Check if any match is set
641 if not self.match.value.strip():
644 _("The match attribute is mandatory."),
645 type = MessageBox.TYPE_ERROR,
648 # Check if we have a trailing whitespace
649 elif self.match.value[-1:] == " ":
650 self.session.openWithCallback(
653 _('You entered "%s" as Text to match.\nDo you want to remove trailing whitespaces?') % (self.match.value)
659 def saveCallback(self, ret):
662 self.match.value = self.match.value.rstrip()
664 # Don't to anything if MessageBox was canceled!
668 self.timer.match = self.match.value
671 self.timer.name = self.name.value.strip() or self.timer.match
674 self.timer.encoding = self.encoding.value
677 self.timer.searchType = self.searchType.value
678 self.timer.searchCase = self.searchCase.value
681 self.timer.overrideAlternatives = self.overrideAlternatives.value
684 self.timer.enabled = self.enabled.value
687 self.timer.justplay = self.justplay.value == "zap"
690 if self.timespan.value:
691 start = self.timespanbegin.value
692 end = self.timespanend.value
693 self.timer.timespan = (start, end)
695 self.timer.timespan = None
698 if self.serviceRestriction:
699 self.timer.services = self.services
700 self.timer.bouquets = self.bouquets
702 self.timer.services = None
703 self.timer.bouquets = None
706 if self.offset.value:
707 self.timer.offset = (self.offsetbegin.value*60, self.offsetend.value*60)
709 self.timer.offset = None
712 if self.afterevent.value == "default":
713 self.timer.afterevent = []
716 "nothing": AFTEREVENT.NONE,
717 "deepstandby": AFTEREVENT.DEEPSTANDBY,
718 "standby": AFTEREVENT.STANDBY,
719 "auto": AFTEREVENT.AUTO
720 }[self.afterevent.value]
721 # AfterEvent Timespan
722 if self.afterevent_timespan.value:
723 start = self.afterevent_timespanbegin.value
724 end = self.afterevent_timespanend.value
725 self.timer.afterevent = [(afterevent, (start, end))]
727 self.timer.afterevent = [(afterevent, None)]
730 if self.duration.value:
731 self.timer.maxduration = self.durationlength.value*60
733 self.timer.maxduration = None
737 self.timer.exclude = self.excludes
738 self.timer.include = self.includes
740 self.timer.exclude = None
741 self.timer.include = None
744 if self.counter.value:
745 self.timer.matchCount = self.counter.value
746 if self.counterLeft.value <= self.counter.value:
747 self.timer.matchLeft = self.counterLeft.value
749 self.timer.matchLeft = self.counter.value
750 if self.counterFormatString.value:
751 self.timer.matchFormatString = self.counterFormatString.value
753 self.timer.matchFormatString = ''
755 self.timer.matchCount = 0
756 self.timer.matchLeft = 0
757 self.timer.matchFormatString = ''
759 self.timer.avoidDuplicateDescription = int(self.avoidDuplicateDescription.value)
761 if self.useDestination.value:
762 self.timer.destination = self.destination.value
764 self.timer.destination = None
766 self.timer.tags = self.timerentry_tags
769 self.close(self.timer)
771 class AutoTimerFilterEditor(Screen, ConfigListScreen):
772 """Edit AutoTimer Filter"""
774 skin = """<screen name="AutoTimerFilterEditor" title="Edit AutoTimer Filters" position="center,center" size="565,280">
775 <ePixmap position="0,0" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
776 <ePixmap position="140,0" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
777 <ePixmap position="280,0" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
778 <ePixmap position="420,0" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
779 <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" />
780 <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" />
781 <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" />
782 <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" />
783 <widget name="config" position="5,45" size="555,225" scrollbarMode="showOnDemand" />
786 def __init__(self, session, filterset, excludes, includes):
787 Screen.__init__(self, session)
790 self.setup_title = _("AutoTimer Filters")
791 self.onChangedEntry = []
793 self.typeSelection = NoSave(ConfigSelection(choices = [
794 ("title", _("in Title")),
795 ("short", _("in Shortdescription")),
796 ("desc", _("in Description")),
797 ("day", _("on Weekday"))]
799 self.typeSelection.addNotifier(self.refresh, initial_call = False)
801 self.enabled = NoSave(ConfigEnableDisable(default = filterset))
803 self.excludes = excludes
804 self.includes = includes
808 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
811 self["key_red"] = StaticText(_("Cancel"))
812 self["key_green"] = StaticText(_("Save"))
813 self["key_yellow"] = StaticText(_("delete"))
814 self["key_blue"] = StaticText(_("New"))
817 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
819 "cancel": self.cancel,
821 "yellow": self.remove,
829 self.onLayoutFinish.append(self.setCustomTitle)
831 def setCustomTitle(self):
832 self.setTitle(_("Edit AutoTimer filters"))
836 for x in self.onChangedEntry:
842 def getCurrentEntry(self):
843 return self["config"].getCurrent()[0]
845 def getCurrentValue(self):
846 return str(self["config"].getCurrent()[1].getText())
848 def createSummary(self):
851 def saveCurrent(self):
852 del self.excludes[self.idx][:]
853 del self.includes[self.idx][:]
855 # Warning, accessing a ConfigListEntry directly might be considered evil!
858 for item in self["config"].getList()[:]:
860 # Skip empty entries (and those which are no filters)
861 if item[1].value == "" or idx < 2:
863 elif idx < self.lenExcludes:
864 self.excludes[self.idx].append(item[1].value.encode("UTF-8"))
866 self.includes[self.idx].append(item[1].value.encode("UTF-8"))
868 def refresh(self, *args, **kwargs):
872 self["config"].setList(self.list)
874 def reloadList(self):
876 getConfigListEntry(_("Enable Filtering"), self.enabled),
877 getConfigListEntry(_("Filter"), self.typeSelection)
880 if self.typeSelection.value == "day":
883 # Weekdays are presented as ConfigSelection
885 getConfigListEntry(_("Exclude"), NoSave(ConfigSelection(choices = weekdays, default = x)))
886 for x in self.excludes[3]
888 self.lenExcludes = len(self.list)
890 getConfigListEntry(_("Include"), NoSave(ConfigSelection(choices = weekdays, default = x)))
891 for x in self.includes[3]
894 elif self.typeSelection.value == "title":
896 elif self.typeSelection.value == "short":
898 else: # self.typeSelection.value == "desc":
902 getConfigListEntry(_("Exclude"), NoSave(ExtendedConfigText(default = x, fixed_size = False)))
903 for x in self.excludes[self.idx]
905 self.lenExcludes = len(self.list)
907 getConfigListEntry(_("Include"), NoSave(ExtendedConfigText(default = x, fixed_size = False)))
908 for x in self.includes[self.idx]
912 idx = self["config"].getCurrentIndex()
914 if idx < self.lenExcludes:
915 self.lenExcludes -= 1
917 list = self["config"].getList()
918 list.remove(self["config"].getCurrent())
919 self["config"].setList(list)
922 self.session.openWithCallback(
925 _("Select type of Filter"),
932 def typeSelected(self, ret):
934 list = self["config"].getList()
937 pos = self.lenExcludes
938 self.lenExcludes += 1
944 if self.typeSelection.value == "day":
945 entry = getConfigListEntry(text, NoSave(ConfigSelection(choices = weekdays)))
947 entry = getConfigListEntry(text, NoSave(ExtendedConfigText(fixed_size = False)))
949 list.insert(pos, entry)
950 self["config"].setList(list)
953 if self["config"].isChanged():
954 self.session.openWithCallback(
957 _("Really close without saving settings?")
962 def cancelConfirm(self, ret):
975 class AutoTimerServiceEditor(Screen, ConfigListScreen):
976 """Edit allowed Services of a AutoTimer"""
978 skin = """<screen name="AutoTimerServiceEditor" title="Edit AutoTimer Services" position="center,center" size="565,280">
979 <ePixmap position="0,0" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
980 <ePixmap position="140,0" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
981 <ePixmap position="280,0" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
982 <ePixmap position="420,0" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
983 <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" />
984 <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" />
985 <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" />
986 <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" />
987 <widget name="config" position="5,45" size="555,225" scrollbarMode="showOnDemand" />
990 def __init__(self, session, servicerestriction, servicelist, bouquetlist):
991 Screen.__init__(self, session)
994 self.setup_title = _("AutoTimer Services")
995 self.onChangedEntry = []
1002 self.enabled = NoSave(ConfigEnableDisable(default = servicerestriction))
1003 self.typeSelection = NoSave(ConfigSelection(choices = [
1004 ("channels", _("Channels")),
1005 ("bouquets", _("Bouquets"))]
1007 self.typeSelection.addNotifier(self.refresh, initial_call = False)
1011 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
1013 # Initialize Buttons
1014 self["key_red"] = StaticText(_("Cancel"))
1015 self["key_green"] = StaticText(_("OK"))
1016 self["key_yellow"] = StaticText(_("delete"))
1017 self["key_blue"] = StaticText(_("New"))
1020 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
1022 "cancel": self.cancel,
1024 "yellow": self.remove,
1032 self.onLayoutFinish.append(self.setCustomTitle)
1034 def setCustomTitle(self):
1035 self.setTitle(_("Edit AutoTimer services"))
1037 def saveCurrent(self):
1038 del self.services[self.idx][:]
1040 # Warning, accessing a ConfigListEntry directly might be considered evil!
1042 myl = self["config"].getList()[:]
1043 myl.pop(0) # Enabled
1046 self.services[self.idx].append(item[1].value)
1048 def refresh(self, *args, **kwargs):
1052 self["config"].setList(self.list)
1054 def reloadList(self):
1056 getConfigListEntry(_("Enable Service Restriction"), self.enabled),
1057 getConfigListEntry(_("Editing"), self.typeSelection)
1060 if self.typeSelection.value == "channels":
1062 else: # self.typeSelection.value == "bouquets":
1066 getConfigListEntry(_("Record on"), NoSave(ConfigSelection(choices = [(str(x), ServiceReference(str(x)).getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''))])))
1067 for x in self.services[self.idx]
1071 for x in self.onChangedEntry:
1077 def getCurrentEntry(self):
1078 return self["config"].getCurrent()[0]
1080 def getCurrentValue(self):
1081 return str(self["config"].getCurrent()[1].getText())
1083 def createSummary(self):
1087 if self["config"].getCurrentIndex() != 0:
1088 list = self["config"].getList()
1089 list.remove(self["config"].getCurrent())
1090 self["config"].setList(list)
1093 if self.typeSelection.value == "channels":
1094 self.session.openWithCallback(
1095 self.finishedServiceSelection,
1096 SimpleChannelSelection,
1097 _("Select channel to record on")
1099 else: # self.typeSelection.value == "bouquets":
1100 self.session.openWithCallback(
1101 self.finishedServiceSelection,
1102 SimpleBouquetSelection,
1103 _("Select bouquet to record on")
1106 def finishedServiceSelection(self, *args):
1108 list = self["config"].getList()
1109 sname = args[0].toString()
1111 if self.typeSelection.value == "channels" and not (args[0].flags & eServiceReference.isGroup):
1112 # strip all after last : when adding a (non alternative) channel
1113 pos = sname.rfind(':')
1115 if sname[pos-1] == ':':
1117 sname = sname[:pos+1]
1119 list.append(getConfigListEntry(_("Record on"), NoSave(ConfigSelection(choices = [(sname, ServiceReference(args[0]).getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''))]))))
1120 self["config"].setList(list)
1123 if self["config"].isChanged():
1124 self.session.openWithCallback(
1127 _("Really close without saving settings?")
1132 def cancelConfirm(self, ret):
1144 def addAutotimerFromSearchString(session, match):
1145 from AutoTimerComponent import preferredAutoTimerComponent
1146 from AutoTimerImporter import AutoTimerImporter
1147 from plugin import autotimer
1149 # Create instance if needed
1150 if autotimer is None:
1151 from AutoTimer import AutoTimer
1152 autotimer = AutoTimer()
1155 session.openWithCallback(
1158 preferredAutoTimerComponent(
1159 autotimer.getUniqueId(),
1164 match, # Proposed Match
1165 None, # Proposed Begin
1166 None, # Proposed End
1167 None, # Proposed Disabled
1168 None, # Proposed ServiceReference
1169 None, # Proposed afterEvent
1170 None, # Proposed justplay
1171 None, # Proposed dirname, can we get anything useful here?
1175 def addAutotimerFromEvent(session, evt = None, service = None):
1176 from AutoTimerComponent import preferredAutoTimerComponent
1177 from AutoTimerImporter import AutoTimerImporter
1178 from plugin import autotimer
1180 # Create instance if needed
1181 if autotimer is None:
1182 from AutoTimer import AutoTimer
1183 autotimer = AutoTimer()
1186 match = evt and evt.getEventName() or ""
1187 name = match or "New AutoTimer"
1189 if service is not None:
1190 service = str(service)
1191 myref = eServiceReference(service)
1192 if not (myref.flags & eServiceReference.isGroup):
1193 # strip all after last :
1194 pos = service.rfind(':')
1196 if service[pos-1] == ':':
1198 service = service[:pos+1]
1200 sref = ServiceReference(myref)
1202 # timespan defaults to +- 1h
1203 begin = evt.getBeginTime()-3600
1204 end = begin + evt.getDuration()+7200
1208 # XXX: we might want to make sure that we actually collected any data because the importer does not do so :-)
1210 session.openWithCallback(
1213 preferredAutoTimerComponent(
1214 autotimer.getUniqueId(),
1219 match, # Proposed Match
1220 begin, # Proposed Begin
1222 None, # Proposed Disabled
1223 sref, # Proposed ServiceReference
1224 None, # Proposed afterEvent
1225 None, # Proposed justplay
1226 None, # Proposed dirname, can we get anything useful here?
1230 def addAutotimerFromService(session, service = None):
1231 from AutoTimerComponent import preferredAutoTimerComponent
1232 from AutoTimerImporter import AutoTimerImporter
1233 from plugin import autotimer
1235 # Create instance if needed
1236 if autotimer is None:
1237 from AutoTimer import AutoTimer
1238 autotimer = AutoTimer()
1241 serviceHandler = eServiceCenter.getInstance()
1242 info = serviceHandler.info(service)
1244 match = info and info.getName(service) or ""
1245 name = match or "New AutoTimer"
1246 sref = info and info.getInfoString(service, iServiceInformation.sServiceref)
1248 # strip all after last :
1249 pos = sref.rfind(':')
1251 if sref[pos-1] == ':':
1255 sref = ServiceReference(sref)
1257 begin = info.getInfo(service, iServiceInformation.sTimeCreate)
1258 end = begin + info.getLength(service)
1262 from os.path import dirname
1263 path = dirname(service.getPath())
1267 tags = info.getInfoString(service, iServiceInformation.sTags)
1268 tags = tags and tags.split(' ') or []
1270 # XXX: we might want to make sure that we actually collected any data because the importer does not do so :-)
1272 session.openWithCallback(
1275 preferredAutoTimerComponent(
1276 autotimer.getUniqueId(),
1281 match, # Proposed Match
1282 begin, # Proposed Begin
1284 None, # Proposed Disabled
1285 sref, # Proposed ServiceReference
1286 None, # Proposed afterEvent
1287 None, # Proposed justplay
1288 path, # Proposed dirname
1289 tags # Proposed tags
1292 def importerCallback(ret):
1296 session.openWithCallback(
1302 # Remove instance if not running in background
1303 if not config.plugins.autotimer.autopoll.value:
1304 from plugin import autotimer
1307 def editorCallback(ret):
1309 from plugin import autotimer
1311 # Create instance if needed (should have been created by addAutotimerFrom* above though)
1312 if autotimer is None:
1313 from AutoTimer import AutoTimer
1314 autotimer = AutoTimer()
1320 autotimer.writeXml()
1322 # Remove instance if not running in background
1323 if not config.plugins.autotimer.autopoll.value: