AutoTimerEditor.py: fix typo
[enigma2-plugins.git] / autotimer / src / AutoTimerEditor.py
1 # -*- coding: UTF-8 -*-
2 # for localized messages
3 from . import _
4
5 # GUI (Screens)
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
12
13 # GUI (Summary)
14 from Screens.Setup import SetupSummary
15
16 # GUI (Components)
17 from Components.ActionMap import ActionMap
18 from Components.Sources.StaticText import StaticText
19
20 # Configuration
21 from Components.config import getConfigListEntry, ConfigEnableDisable, \
22         ConfigYesNo, ConfigText, ConfigClock, ConfigNumber, ConfigSelection, \
23         ConfigDateTime, config, NoSave
24
25 # Timer
26 from RecordTimer import AFTEREVENT
27
28 # Needed to convert our timestamp back and forth
29 from time import localtime, mktime
30
31 # Show ServiceName instead of ServiceReference
32 from ServiceReference import ServiceReference
33
34 # addAutotimerFromService, AutoTimerChannelSelection
35 from enigma import eServiceCenter, eServiceReference, iServiceInformation
36
37 # Default Record Directory
38 from Tools import Directories
39
40 # Tags
41 from Screens.MovieSelection import getPreferredTagEditor
42
43 weekdays = [
44         ("0", _("Monday")),
45         ("1", _("Tuesday")),
46         ("2", _("Wednesday")),
47         ("3", _("Thursday")),
48         ("4", _("Friday")),
49         ("5", _("Saturday")),
50         ("6", _("Sunday")),
51         ("weekend", _("Weekend")),
52         ("weekday", _("Weekday"))
53 ]
54
55 try:
56         from Plugins.SystemPlugins.vps import Vps
57 except ImportError, ie:
58         hasVps = False
59 else:
60         hasVps = True
61
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)
65
66                 # Workaround some characters currently not "typeable" using NumericalTextInput
67                 mapping = self.mapping
68                 if mapping:
69                         if "&" not in mapping[0]:
70                                 mapping[0] += "&"
71                         if ";" not in mapping[0]:
72                                 mapping[0] += ";"
73                         if "%" not in mapping[0]:
74                                 mapping[0] += "%"
75
76 class SimpleBouquetSelection(SimpleChannelSelection):
77         def __init__(self, session, title):
78                 SimpleChannelSelection.__init__(self, session, title)
79                 self.skinName = "SimpleChannelSelection"
80
81         def channelSelected(self):
82                 ref = self.getCurrentSelection()
83                 if (ref.flags & 7) == 7:
84                         self.close(ref)
85                 else:
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])
89
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
95
96                 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
97                         {
98                                 "showEPGList": self.channelSelected
99                         }
100                 )
101
102         def channelSelected(self):
103                 ref = self.getCurrentSelection()
104                 if (ref.flags & 7) == 7:
105                         self.enterPath(ref)
106                 elif not (ref.flags & eServiceReference.isMarker):
107                         self.session.open(
108                                 AutoTimerEPGSelection,
109                                 ref
110                         )
111
112 class AutoTimerEPGSelection(EPGSelection):
113         def __init__(self, *args):
114                 EPGSelection.__init__(self, *args)
115                 self.skinName = "EPGSelection"
116
117         def infoKeyPressed(self):
118                 self.timerAdd()
119
120         def timerAdd(self):
121                 cur = self["list"].getCurrent()
122                 evt = cur[0]
123                 sref = cur[1]
124                 if not evt:
125                         return
126
127                 addAutotimerFromEvent(self.session, evt = evt, service = sref)
128
129         def onSelectionChanged(self):
130                 pass
131
132 class AutoTimerEditorBase:
133         """ Base Class for all Editors """
134         def __init__(self, timer, editingDefaults = False):
135                 # Keep Timer
136                 self.timer = timer
137                 self.editingDefaults = editingDefaults
138
139                 # See if we are filtering some strings
140                 excludes = (
141                         timer.getExcludedTitle(),
142                         timer.getExcludedShort(),
143                         timer.getExcludedDescription(),
144                         timer.getExcludedDays()
145                 )
146                 includes = (
147                         timer.getIncludedTitle(),
148                         timer.getIncludedShort(),
149                         timer.getIncludedDescription(),
150                         timer.getIncludedDays()
151                 )
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
157                 else:
158                         self.filterSet = False
159                 self.excludes = excludes
160                 self.includes = includes
161
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
167                 else:
168                         self.serviceRestriction = False
169
170                 self.createSetup(timer)
171
172         def createSetup(self, timer):
173                 # Name
174                 self.name = NoSave(ExtendedConfigText(default = timer.name, fixed_size = False))
175
176                 # Match
177                 self.match = NoSave(ExtendedConfigText(default = timer.match, fixed_size = False))
178
179                 # Encoding
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))
185
186                 # ...
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))
189
190                 # Alternatives override
191                 self.overrideAlternatives = NoSave(ConfigYesNo(default = timer.overrideAlternatives))
192
193                 # Justplay
194                 self.justplay = NoSave(ConfigSelection(choices = [("zap", _("zap")), ("record", _("record"))], default = {0: "record", 1: "zap"}[int(timer.justplay)]))
195
196                 # Timespan
197                 now = [x for x in localtime()]
198                 if timer.hasTimespan():
199                         default = True
200                         now[3] = timer.timespan[0][0]
201                         now[4] = timer.timespan[0][1]
202                         begin = mktime(now)
203                         now[3] = timer.timespan[1][0]
204                         now[4] = timer.timespan[1][1]
205                         end = mktime(now)
206                 else:
207                         default = False
208                         now[3] = 20
209                         now[4] = 15
210                         begin = mktime(now)
211                         now[3] = 23
212                         now[4] = 15
213                         end = mktime(now)
214                 self.timespan = NoSave(ConfigEnableDisable(default = default))
215                 self.timespanbegin = NoSave(ConfigClock(default = begin))
216                 self.timespanend = NoSave(ConfigClock(default = end))
217
218                 # Timeframe
219                 if timer.hasTimeframe():
220                         default = True
221                         begin = timer.getTimeframeBegin()
222                         end = timer.getTimeframeEnd()
223                 else:
224                         default = False
225                         now = [x for x in localtime()]
226                         now[3] = 0
227                         now[4] = 0
228                         begin = mktime(now)
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))
233
234                 # Services have their own Screen
235
236                 # Offset
237                 if timer.hasOffset():
238                         default = True
239                         begin = timer.getOffsetBegin()
240                         end = timer.getOffsetEnd()
241                 else:
242                         default = False
243                         begin = 5
244                         end = 5
245                 self.offset = NoSave(ConfigEnableDisable(default = default))
246                 self.offsetbegin = NoSave(ConfigNumber(default = begin))
247                 self.offsetend = NoSave(ConfigNumber(default = end))
248
249                 # AfterEvent
250                 if timer.hasAfterEvent():
251                         default = {
252                                 None: "default",
253                                 AFTEREVENT.NONE: "nothing",
254                                 AFTEREVENT.DEEPSTANDBY: "deepstandby",
255                                 AFTEREVENT.STANDBY: "standby",
256                                 AFTEREVENT.AUTO: "auto"
257                         }[timer.afterevent[0][0]]
258                 else:
259                         default = "default"
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))
265
266                 # AfterEvent (Timespan)
267                 if timer.hasAfterEvent() and timer.afterevent[0][1][0] is not None:
268                         default = True
269                         now[3] = timer.afterevent[0][1][0][0]
270                         now[4] = timer.afterevent[0][1][0][1]
271                         begin = mktime(now)
272                         now[3] = timer.afterevent[0][1][1][0]
273                         now[4] = timer.afterevent[0][1][1][1]
274                         end = mktime(now)
275                 else:
276                         default = False
277                         now[3] = 23
278                         now[4] = 15
279                         begin = mktime(now)
280                         now[3] = 7
281                         now[4] = 0
282                         end = mktime(now)
283                 self.afterevent_timespan = NoSave(ConfigEnableDisable(default = default))
284                 self.afterevent_timespanbegin = NoSave(ConfigClock(default = begin))
285                 self.afterevent_timespanend = NoSave(ConfigClock(default = end))
286
287                 # Enabled
288                 self.enabled = NoSave(ConfigYesNo(default = timer.enabled))
289
290                 # Maxduration
291                 if timer.hasDuration():
292                         default = True
293                         duration = timer.getDuration()
294                 else:
295                         default = False
296                         duration =70
297                 self.duration = NoSave(ConfigEnableDisable(default = default))
298                 self.durationlength = NoSave(ConfigNumber(default = duration))
299
300                 # Counter
301                 if timer.hasCounter():
302                         default = timer.matchCount
303                 else:
304                         default = 0
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))
312
313                 # Avoid Duplicate Description
314                 self.avoidDuplicateDescription = NoSave(ConfigSelection([
315                                 ("0", _("No")),
316                                 ("1", _("On same service")),
317                                 ("2", _("On any service")),
318                                 ("3", _("Any service/recording")),
319                         ],
320                         default = str(timer.getAvoidDuplicateDescription())
321                 ))
322
323                 # Custom Location
324                 if timer.hasDestination():
325                         default = True
326                 else:
327                         default = False
328
329                 self.useDestination = NoSave(ConfigYesNo(default = default))
330
331                 default = timer.destination or Directories.resolveFilename(Directories.SCOPE_HDD)
332                 choices = config.movielist.videodirs.value
333
334                 if default not in choices:
335                         choices.append(default)
336                 self.destination = NoSave(ConfigSelection(default = default, choices = choices))
337
338                 # Tags
339                 self.timerentry_tags = timer.tags
340                 self.tags = NoSave(ConfigSelection(choices = [len(self.timerentry_tags) == 0 and _("None") or ' '.join(self.timerentry_tags)]))
341
342                 # Vps
343                 self.vps_enabled = NoSave(ConfigYesNo(default = timer.vps_enabled))
344                 self.vps_overwrite = NoSave(ConfigYesNo(default = timer.vps_overwrite))
345
346         def pathSelected(self, res):
347                 if res is not None:
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
352
353         def chooseDestination(self):
354                 from Screens.LocationBox import MovieLocationBox
355
356                 self.session.openWithCallback(
357                         self.pathSelected,
358                         MovieLocationBox,
359                         _("Choose target folder"),
360                         self.destination.value,
361                         minFree = 100 # Same requirement as in Screens.TimerEntry
362                 )
363
364         def tagEditFinished(self, ret):
365                 if ret is not None:
366                         self.timerentry_tags = ret
367                         self.tags.setChoices([len(ret) == 0 and _("None") or ' '.join(ret)])
368
369         def chooseTags(self):
370                 preferredTagEditor = getPreferredTagEditor()
371                 if preferredTagEditor:
372                         self.session.openWithCallback(
373                                 self.tagEditFinished,
374                                 preferredTagEditor,
375                                 self.timerentry_tags
376                         )
377
378 class AutoTimerEditor(Screen, ConfigListScreen, AutoTimerEditorBase):
379         """Edit AutoTimer"""
380
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" />
393         </screen>"""
394
395         def __init__(self, session, timer, editingDefaults = False):
396                 Screen.__init__(self, session)
397
398                 AutoTimerEditorBase.__init__(self, timer, editingDefaults)
399
400                 # Summary
401                 self.setup_title = _("AutoTimer Editor")
402                 self.onChangedEntry = []
403
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)
413
414                 self.refresh()
415                 self.initHelpTexts()
416
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)
420
421                 # Initialize Buttons
422                 self["key_red"] = StaticText(_("Cancel"))
423                 self["key_green"] = StaticText(_("OK"))
424                 self["key_yellow"] = StaticText()
425                 self["key_blue"] = StaticText()
426
427                 self["help"] = StaticText()
428
429                 # Set Button texts
430                 self.renameServiceButton()
431                 self.renameFilterButton()
432
433                 # Define Actions
434                 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
435                         {
436                                 "cancel": self.cancel,
437                                 "save": self.maybeSave,
438                                 "ok": self.ok,
439                                 "yellow": self.editFilter,
440                                 "blue": self.editServices
441                         }, -2
442                 )
443
444                 # Trigger change
445                 self.changed()
446
447                 self.onLayoutFinish.append(self.setCustomTitle)
448
449         def setCustomTitle(self):
450                 self.setTitle(_("Edit AutoTimer"))
451
452         def renameFilterButton(self):
453                 if self.filterSet:
454                         self["key_yellow"].text = _("edit filters")
455                 else:
456                         self["key_yellow"].text = _("add filters")
457
458         def renameServiceButton(self):
459                 if self.serviceRestriction:
460                         self["key_blue"].text = _("edit services")
461                 else:
462                         self["key_blue"].text = _("add services")
463
464         def updateHelp(self):
465                 cur = self["config"].getCurrent()
466                 if cur:
467                         self["help"].text = self.helpDict[cur[1]]
468
469         def changed(self):
470                 for x in self.onChangedEntry:
471                         try:
472                                 x()
473                         except Exception:
474                                 pass
475
476         def getCurrentEntry(self):
477                 return self["config"].getCurrent()[0]
478
479         def getCurrentValue(self):
480                 return str(self["config"].getCurrent()[1].getText())
481
482         def createSummary(self):
483                 return SetupSummary
484
485         def initHelpTexts(self):
486                 self.helpDict = {
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."),
517                 }
518
519         def refresh(self):
520                 # First three entries are only showed when not editing defaults
521                 list = []
522                 if not self.editingDefaults:
523                         list.extend((
524                                 getConfigListEntry(_("Enabled"), self.enabled),
525                                 getConfigListEntry(_("Description"), self.name),
526                                 getConfigListEntry(_("Match title"), self.match),
527                         ))
528
529                 list.extend((
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)
536                 ))
537
538                 # Only allow editing timespan when it's enabled
539                 if self.timespan.value:
540                         list.extend((
541                                 getConfigListEntry(_("Begin of timespan"), self.timespanbegin),
542                                 getConfigListEntry(_("End of timespan"), self.timespanend)
543                         ))
544
545                 list.append(getConfigListEntry(_("Restrict to events on certain dates"), self.timeframe))
546
547                 # Only allow editing timeframe when it's enabled
548                 if self.timeframe.value:
549                         list.extend((
550                                 getConfigListEntry(_("Not before"), self.timeframebegin),
551                                 getConfigListEntry(_("Not after"), self.timeframeend)
552                         ))
553
554                 list.append(getConfigListEntry(_("Custom offset"), self.offset))
555
556                 # Only allow editing offsets when it's enabled
557                 if self.offset.value:
558                         list.extend((
559                                 getConfigListEntry(_("Offset before recording (in m)"), self.offsetbegin),
560                                 getConfigListEntry(_("Offset after recording (in m)"), self.offsetend)
561                         ))
562
563                 list.append(getConfigListEntry(_("Set maximum duration"), self.duration))
564
565                 # Only allow editing maxduration when it's enabled
566                 if self.duration.value:
567                         list.append(getConfigListEntry(_("Maximum duration (in m)"), self.durationlength))
568
569                 list.append(getConfigListEntry(_("After event"), self.afterevent))
570
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))
574
575                         # Only allow editing timespan when it's enabled
576                         if self.afterevent_timespan.value:
577                                 list.extend((
578                                         getConfigListEntry(_("Begin of \"after event\" timespan"), self.afterevent_timespanbegin),
579                                         getConfigListEntry(_("End of \"after event\" timespan"), self.afterevent_timespanend)
580                                 ))
581
582                 list.append(getConfigListEntry(_("Record a maximum of x times"), self.counter))
583
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))
589
590                 list.append(getConfigListEntry(_("Require description to be unique"), self.avoidDuplicateDescription))
591
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))
596
597                 list.append(getConfigListEntry(_("Tags"), self.tags))
598
599                 if hasVps:
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))
603
604                 self.list = list
605
606         def reloadList(self, value):
607                 self.refresh()
608                 self["config"].setList(self.list)
609
610         def editFilter(self):
611                 self.session.openWithCallback(
612                         self.editFilterCallback,
613                         AutoTimerFilterEditor,
614                         self.filterSet,
615                         self.excludes,
616                         self.includes
617                 )
618
619         def editFilterCallback(self, ret):
620                 if ret:
621                         self.filterSet = ret[0]
622                         self.excludes = ret[1]
623                         self.includes = ret[2]
624                         self.renameFilterButton()
625
626         def editServices(self):
627                 self.session.openWithCallback(
628                         self.editServicesCallback,
629                         AutoTimerServiceEditor,
630                         self.serviceRestriction,
631                         self.services,
632                         self.bouquets
633                 )
634
635         def editServicesCallback(self, ret):
636                 if ret:
637                         self.serviceRestriction = ret[0]
638                         self.services = ret[1][0]
639                         self.bouquets = ret[1][1]
640                         self.renameServiceButton()
641
642         def keyLeft(self):
643                 cur = self["config"].getCurrent()
644                 cur = cur and cur[1]
645                 if cur == self.tags:
646                         self.chooseTags()
647                 else:
648                         ConfigListScreen.keyLeft(self)
649
650         def keyRight(self):
651                 cur = self["config"].getCurrent()
652                 cur = cur and cur[1]
653                 if cur == self.tags:
654                         self.chooseTags()
655                 else:
656                         ConfigListScreen.keyRight(self)
657
658         def ok(self):
659                 cur = self["config"].getCurrent()
660                 cur = cur and cur[1]
661                 if cur == self.destination:
662                         self.chooseDestination()
663                 elif cur == self.tags:
664                         self.chooseTags()
665                 else:
666                         ConfigListScreen.keyOK(self)
667
668         def cancel(self):
669                 if self["config"].isChanged():
670                         self.session.openWithCallback(
671                                 self.cancelConfirm,
672                                 MessageBox,
673                                 _("Really close without saving settings?")
674                         )
675                 else:
676                         self.close(None)
677
678         def cancelConfirm(self, ret):
679                 if ret:
680                         self.close(None)
681
682         def maybeSave(self):
683                 if self.editingDefaults:
684                         self.save()
685                         return
686                 # Check if any match is set
687                 if not self.match.value.strip():
688                         self.session.open(
689                                         MessageBox,
690                                         _("The match attribute is mandatory."),
691                                         type = MessageBox.TYPE_ERROR,
692                                         timeout = 5
693                         )
694                 # Check if we have a trailing whitespace
695                 elif self.match.value[-1:] == " ":
696                         self.session.openWithCallback(
697                                 self.saveCallback,
698                                 MessageBox,
699                                 _('You entered "%s" as Text to match.\nDo you want to remove trailing whitespaces?') % (self.match.value)
700                         )
701                 # Just save else
702                 else:
703                         self.save()
704
705         def saveCallback(self, ret):
706                 if ret is not None:
707                         if ret:
708                                 self.match.value = self.match.value.rstrip()
709                         self.save()
710                 # Don't to anything if MessageBox was canceled!
711
712         def save(self):
713                 # Match
714                 self.timer.match = self.match.value
715
716                 # Name
717                 self.timer.name = self.name.value.strip() or self.timer.match
718
719                 # Encoding
720                 self.timer.encoding = self.encoding.value
721
722                 # ...
723                 self.timer.searchType = self.searchType.value
724                 self.timer.searchCase = self.searchCase.value
725
726                 # Alternatives
727                 self.timer.overrideAlternatives = self.overrideAlternatives.value
728
729                 # Enabled
730                 self.timer.enabled = self.enabled.value
731
732                 # Justplay
733                 self.timer.justplay = self.justplay.value == "zap"
734
735                 # Timespan
736                 if self.timespan.value:
737                         start = self.timespanbegin.value
738                         end = self.timespanend.value
739                         self.timer.timespan = (start, end)
740                 else:
741                         self.timer.timespan = None
742
743                 # Timeframe
744                 if self.timeframe.value:
745                         start = self.timeframebegin.value
746                         end = self.timeframeend.value
747                         self.timer.timeframe = (start, end)
748                 else:
749                         self.timer.timeframe = None
750
751                 # Services
752                 if self.serviceRestriction:
753                         self.timer.services = self.services
754                         self.timer.bouquets = self.bouquets
755                 else:
756                         self.timer.services = None
757                         self.timer.bouquets = None
758
759                 # Offset
760                 if self.offset.value:
761                         self.timer.offset = (self.offsetbegin.value*60, self.offsetend.value*60)
762                 else:
763                         self.timer.offset = None
764
765                 # AfterEvent
766                 if self.afterevent.value == "default":
767                         self.timer.afterevent = []
768                 else:
769                         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))]
780                         else:
781                                 self.timer.afterevent = [(afterevent, None)]
782
783                 # Maxduration
784                 if self.duration.value:
785                         self.timer.maxduration = self.durationlength.value*60
786                 else:
787                         self.timer.maxduration = None
788
789                 # Ex-&Includes
790                 if self.filterSet:
791                         self.timer.exclude = self.excludes
792                         self.timer.include = self.includes
793                 else:
794                         self.timer.exclude = None
795                         self.timer.include = None
796
797                 # Counter
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
802                         else:
803                                 self.timer.matchLeft = self.counter.value
804                         if self.counterFormatString.value:
805                                 self.timer.matchFormatString = self.counterFormatString.value
806                         else:
807                                 self.timer.matchFormatString = ''
808                 else:
809                         self.timer.matchCount = 0
810                         self.timer.matchLeft = 0
811                         self.timer.matchFormatString = ''
812
813                 self.timer.avoidDuplicateDescription = int(self.avoidDuplicateDescription.value)
814
815                 if self.useDestination.value:
816                         self.timer.destination = self.destination.value
817                 else:
818                         self.timer.destination = None
819
820                 self.timer.tags = self.timerentry_tags
821
822                 self.timer.vps_enabled = self.vps_enabled.value
823                 self.timer.vps_overwrite = self.vps_overwrite.value
824
825                 # Close
826                 self.close(self.timer)
827
828 class AutoTimerFilterEditor(Screen, ConfigListScreen):
829         """Edit AutoTimer Filter"""
830
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" />
841         </screen>"""
842
843         def __init__(self, session, filterset, excludes, includes):
844                 Screen.__init__(self, session)
845
846                 # Summary
847                 self.setup_title = _("AutoTimer Filters")
848                 self.onChangedEntry = []
849
850                 self.typeSelection = NoSave(ConfigSelection(choices = [
851                         ("title", _("in Title")),
852                         ("short", _("in Shortdescription")),
853                         ("desc", _("in Description")),
854                         ("day", _("on Weekday"))]
855                 ))
856                 self.typeSelection.addNotifier(self.refresh, initial_call = False)
857
858                 self.enabled = NoSave(ConfigEnableDisable(default = filterset))
859
860                 self.excludes = excludes
861                 self.includes = includes
862
863                 self.reloadList()
864
865                 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
866
867                 # Initialize Buttons
868                 self["key_red"] = StaticText(_("Cancel"))
869                 self["key_green"] = StaticText(_("Save"))
870                 self["key_yellow"] = StaticText(_("delete"))
871                 self["key_blue"] = StaticText(_("New"))
872
873                 # Define Actions
874                 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
875                         {
876                                 "cancel": self.cancel,
877                                 "save": self.save,
878                                 "yellow": self.remove,
879                                 "blue": self.new
880                         }
881                 )
882
883                 # Trigger change
884                 self.changed()
885
886                 self.onLayoutFinish.append(self.setCustomTitle)
887
888         def setCustomTitle(self):
889                 self.setTitle(_("Edit AutoTimer filters"))
890
891
892         def changed(self):
893                 for x in self.onChangedEntry:
894                         try:
895                                 x()
896                         except Exception:
897                                 pass
898
899         def getCurrentEntry(self):
900                 return self["config"].getCurrent()[0]
901
902         def getCurrentValue(self):
903                 return str(self["config"].getCurrent()[1].getText())
904
905         def createSummary(self):
906                 return SetupSummary
907
908         def saveCurrent(self):
909                 del self.excludes[self.idx][:]
910                 del self.includes[self.idx][:]
911
912                 # Warning, accessing a ConfigListEntry directly might be considered evil!
913
914                 idx = -1
915                 for item in self["config"].getList()[:]:
916                         idx += 1
917                         # Skip empty entries (and those which are no filters)
918                         if item[1].value == "" or idx < 2:
919                                 continue
920                         elif idx < self.lenExcludes:
921                                 self.excludes[self.idx].append(item[1].value.encode("UTF-8"))
922                         else:
923                                 self.includes[self.idx].append(item[1].value.encode("UTF-8"))
924
925         def refresh(self, *args, **kwargs):
926                 self.saveCurrent()
927
928                 self.reloadList()
929                 self["config"].setList(self.list)
930
931         def reloadList(self):
932                 self.list = [
933                         getConfigListEntry(_("Enable Filtering"), self.enabled),
934                         getConfigListEntry(_("Filter"), self.typeSelection)
935                 ]
936
937                 if self.typeSelection.value == "day":
938                         self.idx = 3
939
940                         # Weekdays are presented as ConfigSelection
941                         self.list.extend([
942                                 getConfigListEntry(_("Exclude"), NoSave(ConfigSelection(choices = weekdays, default = x)))
943                                         for x in self.excludes[3]
944                         ])
945                         self.lenExcludes = len(self.list)
946                         self.list.extend([
947                                 getConfigListEntry(_("Include"), NoSave(ConfigSelection(choices = weekdays, default = x)))
948                                         for x in self.includes[3]
949                         ])
950                         return
951                 elif self.typeSelection.value == "title":
952                         self.idx = 0
953                 elif self.typeSelection.value == "short":
954                         self.idx = 1
955                 else: # self.typeSelection.value == "desc":
956                         self.idx = 2
957
958                 self.list.extend([
959                         getConfigListEntry(_("Exclude"), NoSave(ExtendedConfigText(default = x, fixed_size = False)))
960                                 for x in self.excludes[self.idx]
961                 ])
962                 self.lenExcludes = len(self.list)
963                 self.list.extend([
964                         getConfigListEntry(_("Include"), NoSave(ExtendedConfigText(default = x, fixed_size = False)))
965                                 for x in self.includes[self.idx]
966                 ])
967
968         def remove(self):
969                 idx = self["config"].getCurrentIndex()
970                 if idx and idx > 1:
971                         if idx < self.lenExcludes:
972                                 self.lenExcludes -= 1
973
974                         list = self["config"].getList()
975                         list.remove(self["config"].getCurrent())
976                         self["config"].setList(list)
977
978         def new(self):
979                 self.session.openWithCallback(
980                         self.typeSelected,
981                         ChoiceBox,
982                         _("Select type of Filter"),
983                         [
984                                 (_("Exclude"), 0),
985                                 (_("Include"), 1),
986                         ]
987                 )
988
989         def typeSelected(self, ret):
990                 if ret is not None:
991                         list = self["config"].getList()
992
993                         if ret[1] == 0:
994                                 pos = self.lenExcludes
995                                 self.lenExcludes += 1
996                                 text = ret[0]
997                         else:
998                                 pos = len(self.list)
999                                 text = ret[0]
1000
1001                         if self.typeSelection.value == "day":
1002                                 entry = getConfigListEntry(text, NoSave(ConfigSelection(choices = weekdays)))
1003                         else:
1004                                 entry = getConfigListEntry(text, NoSave(ExtendedConfigText(fixed_size = False)))
1005
1006                         list.insert(pos, entry)
1007                         self["config"].setList(list)
1008
1009         def cancel(self):
1010                 if self["config"].isChanged():
1011                         self.session.openWithCallback(
1012                                 self.cancelConfirm,
1013                                 MessageBox,
1014                                 _("Really close without saving settings?")
1015                         )
1016                 else:
1017                         self.close(None)
1018
1019         def cancelConfirm(self, ret):
1020                 if ret:
1021                         self.close(None)
1022
1023         def save(self):
1024                 self.refresh()
1025
1026                 self.close((
1027                         self.enabled.value,
1028                         self.excludes,
1029                         self.includes
1030                 ))
1031
1032 class AutoTimerServiceEditor(Screen, ConfigListScreen):
1033         """Edit allowed Services of a AutoTimer"""
1034
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" />
1045         </screen>"""
1046
1047         def __init__(self, session, servicerestriction, servicelist, bouquetlist):
1048                 Screen.__init__(self, session)
1049
1050                 # Summary
1051                 self.setup_title = _("AutoTimer Services")
1052                 self.onChangedEntry = []
1053
1054                 self.services = (
1055                         servicelist[:],
1056                         bouquetlist[:]
1057                 )
1058
1059                 self.enabled = NoSave(ConfigEnableDisable(default = servicerestriction))
1060                 self.typeSelection = NoSave(ConfigSelection(choices = [
1061                         ("channels", _("Channels")),
1062                         ("bouquets", _("Bouquets"))]
1063                 ))
1064                 self.typeSelection.addNotifier(self.refresh, initial_call = False)
1065
1066                 self.reloadList()
1067
1068                 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
1069
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"))
1075
1076                 # Define Actions
1077                 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
1078                         {
1079                                 "cancel": self.cancel,
1080                                 "save": self.save,
1081                                 "yellow": self.remove,
1082                                 "blue": self.new
1083                         }
1084                 )
1085
1086                 # Trigger change
1087                 self.changed()
1088
1089                 self.onLayoutFinish.append(self.setCustomTitle)
1090
1091         def setCustomTitle(self):
1092                 self.setTitle(_("Edit AutoTimer services"))
1093
1094         def saveCurrent(self):
1095                 del self.services[self.idx][:]
1096
1097                 # Warning, accessing a ConfigListEntry directly might be considered evil!
1098
1099                 myl = self["config"].getList()[:]
1100                 myl.pop(0) # Enabled
1101                 myl.pop(0) # Type
1102                 for item in myl:
1103                         self.services[self.idx].append(item[1].value)
1104
1105         def refresh(self, *args, **kwargs):
1106                 self.saveCurrent()
1107
1108                 self.reloadList()
1109                 self["config"].setList(self.list)
1110
1111         def reloadList(self):
1112                 self.list = [
1113                         getConfigListEntry(_("Enable Service Restriction"), self.enabled),
1114                         getConfigListEntry(_("Editing"), self.typeSelection)
1115                 ]
1116
1117                 if self.typeSelection.value == "channels":
1118                         self.idx = 0
1119                 else: # self.typeSelection.value == "bouquets":
1120                         self.idx = 1
1121
1122                 self.list.extend([
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]
1125                 ])
1126
1127         def changed(self):
1128                 for x in self.onChangedEntry:
1129                         try:
1130                                 x()
1131                         except Exception:
1132                                 pass
1133
1134         def getCurrentEntry(self):
1135                 return self["config"].getCurrent()[0]
1136
1137         def getCurrentValue(self):
1138                 return str(self["config"].getCurrent()[1].getText())
1139
1140         def createSummary(self):
1141                 return SetupSummary
1142
1143         def remove(self):
1144                 if self["config"].getCurrentIndex() != 0:
1145                         list = self["config"].getList()
1146                         list.remove(self["config"].getCurrent())
1147                         self["config"].setList(list)
1148
1149         def new(self):
1150                 if self.typeSelection.value == "channels":
1151                         self.session.openWithCallback(
1152                                 self.finishedServiceSelection,
1153                                 SimpleChannelSelection,
1154                                 _("Select channel to record on")
1155                         )
1156                 else: # self.typeSelection.value == "bouquets":
1157                         self.session.openWithCallback(
1158                                 self.finishedServiceSelection,
1159                                 SimpleBouquetSelection,
1160                                 _("Select bouquet to record on")
1161                         )
1162
1163         def finishedServiceSelection(self, *args):
1164                 if args:
1165                         list = self["config"].getList()
1166                         sname = args[0].toString()
1167
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(':')
1171                                 if pos != -1:
1172                                         if sname[pos-1] == ':':
1173                                                 pos -= 1
1174                                         sname = sname[:pos+1]
1175
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)
1178
1179         def cancel(self):
1180                 if self["config"].isChanged():
1181                         self.session.openWithCallback(
1182                                 self.cancelConfirm,
1183                                 MessageBox,
1184                                 _("Really close without saving settings?")
1185                         )
1186                 else:
1187                         self.close(None)
1188
1189         def cancelConfirm(self, ret):
1190                 if ret:
1191                         self.close(None)
1192
1193         def save(self):
1194                 self.refresh()
1195
1196                 self.close((
1197                         self.enabled.value,
1198                         self.services
1199                 ))
1200
1201 def addAutotimerFromSearchString(session, match):
1202         from AutoTimerComponent import preferredAutoTimerComponent
1203         from AutoTimerImporter import AutoTimerImporter
1204         from plugin import autotimer
1205
1206         # Create instance if needed
1207         if autotimer is None:
1208                 from AutoTimer import AutoTimer
1209                 autotimer = AutoTimer()
1210                 autotimer.readXml()
1211
1212         newTimer = autotimer.defaultTimer.clone()
1213         newTimer.id = autotimer.getUniqueId()
1214         newTimer.name = match
1215         newTimer.match = ''
1216         newTimer.enabled = True
1217
1218         session.openWithCallback(
1219                 importerCallback,
1220                 AutoTimerImporter,
1221                 newTimer,
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?
1230                 []                      # Proposed tags
1231         )
1232
1233 def addAutotimerFromEvent(session, evt = None, service = None):
1234         from AutoTimerComponent import preferredAutoTimerComponent
1235         from AutoTimerImporter import AutoTimerImporter
1236         from plugin import autotimer
1237
1238         # Create instance if needed
1239         if autotimer is None:
1240                 from AutoTimer import AutoTimer
1241                 autotimer = AutoTimer()
1242                 autotimer.readXml()
1243
1244         match = evt and evt.getEventName() or ""
1245         name = match or "New AutoTimer"
1246         sref = None
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(':')
1253                         if pos != -1:
1254                                 if service[pos-1] == ':':
1255                                         pos -= 1
1256                                 service = service[:pos+1]
1257
1258                 sref = ServiceReference(myref)
1259         if evt:
1260                 # timespan defaults to +- 1h
1261                 begin = evt.getBeginTime()-3600
1262                 end = begin + evt.getDuration()+7200
1263         else:
1264                 begin = end = 0
1265
1266         # XXX: we might want to make sure that we actually collected any data because the importer does not do so :-)
1267
1268         newTimer = autotimer.defaultTimer.clone()
1269         newTimer.id = autotimer.getUniqueId()
1270         newTimer.name = name
1271         newTimer.match = ''
1272         newTimer.enabled = True
1273
1274         session.openWithCallback(
1275                 importerCallback,
1276                 AutoTimerImporter,
1277                 newTimer,
1278                 match,          # Proposed Match
1279                 begin,          # Proposed Begin
1280                 end,            # Proposed End
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?
1286                 []                      # Proposed tags
1287         )
1288
1289 def addAutotimerFromService(session, service = None):
1290         from AutoTimerComponent import preferredAutoTimerComponent
1291         from AutoTimerImporter import AutoTimerImporter
1292         from plugin import autotimer
1293
1294         # Create instance if needed
1295         if autotimer is None:
1296                 from AutoTimer import AutoTimer
1297                 autotimer = AutoTimer()
1298                 autotimer.readXml()
1299
1300         serviceHandler = eServiceCenter.getInstance()
1301         info = serviceHandler.info(service)
1302
1303         match = info and info.getName(service) or ""
1304         name = match or "New AutoTimer"
1305         sref = info and info.getInfoString(service, iServiceInformation.sServiceref)
1306         if sref:
1307                 # strip all after last :
1308                 pos = sref.rfind(':')
1309                 if pos != -1:
1310                         if sref[pos-1] == ':':
1311                                 pos -= 1
1312                         sref = sref[:pos+1]
1313
1314                 sref = ServiceReference(sref)
1315         if info:
1316                 begin = info.getInfo(service, iServiceInformation.sTimeCreate)
1317                 end = begin + info.getLength(service)
1318         else:
1319                 begin = end = 0
1320
1321         from os.path import dirname
1322         path = dirname(service.getPath())
1323         if not path == '/':
1324                 path += '/'
1325
1326         tags = info.getInfoString(service, iServiceInformation.sTags)
1327         tags = tags and tags.split(' ') or []
1328
1329         # XXX: we might want to make sure that we actually collected any data because the importer does not do so :-)
1330
1331         session.openWithCallback(
1332                 importerCallback,
1333                 AutoTimerImporter,
1334                 preferredAutoTimerComponent(
1335                         autotimer.getUniqueId(),
1336                         name,
1337                         '',             # Match
1338                         True    # Enabled
1339                 ),
1340                 match,          # Proposed Match
1341                 begin,          # Proposed Begin
1342                 end,            # Proposed End
1343                 None,           # Proposed Disabled
1344                 sref,           # Proposed ServiceReference
1345                 None,           # Proposed afterEvent
1346                 None,           # Proposed justplay
1347                 path,           # Proposed dirname
1348                 tags            # Proposed tags
1349         )
1350
1351 def importerCallback(ret):
1352         if ret:
1353                 ret, session = ret
1354
1355                 session.openWithCallback(
1356                         editorCallback,
1357                         AutoTimerEditor,
1358                         ret
1359                 )
1360         else:
1361                 # Remove instance if not running in background
1362                 if not config.plugins.autotimer.autopoll.value:
1363                         from plugin import autotimer
1364                         autotimer = None
1365
1366 def editorCallback(ret):
1367         if ret:
1368                 from plugin import autotimer
1369
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()
1374                         autotimer.readXml()
1375
1376                 autotimer.add(ret)
1377
1378                 # Save modified xml
1379                 autotimer.writeXml()
1380
1381         # Remove instance if not running in background
1382         if not config.plugins.autotimer.autopoll.value:
1383                 autotimer = None
1384