Follow Enigma2 API change... its not allowed to directly access ConfigElement notifie...
[enigma2-plugins.git] / autotimer / src / AutoTimerConfiguration.py
1 # -*- coding: UTF-8 -*-
2 from __future__ import print_function
3
4 # for localized messages
5 from . import _
6
7 from AutoTimerComponent import preferredAutoTimerComponent
8 from RecordTimer import AFTEREVENT
9 from Tools.XMLTools import stringToXML
10 from ServiceReference import ServiceReference
11
12 from enigma import eServiceReference
13
14 CURRENT_CONFIG_VERSION = "5"
15
16 def getValue(definitions, default):
17         # Initialize Output
18         ret = ""
19
20         # How many definitions are present
21         if isinstance(definitions, list):
22                 Len = len(definitions)
23                 if Len > 0:
24                         childNodes = definitions[Len-1].text
25                 else:
26                         childNodes = ""
27         else:
28                 ret = definitions.text
29
30         # Return stripped output or (if empty) default
31         return ret.strip() or default
32
33 def parseConfig(configuration, list, version = None, uniqueTimerId = 0, defaultTimer = None):
34         if version != CURRENT_CONFIG_VERSION:
35                 parseConfigOld(configuration, list, uniqueTimerId)
36                 return
37
38         if defaultTimer is not None:
39                 # Read in defaults for a new timer
40                 for defaults in configuration.findall("defaults"):
41                         parseEntry(defaults, defaultTimer, True)
42
43         for timer in configuration.findall("timer"):
44                 uniqueTimerId += 1
45                 baseTimer = preferredAutoTimerComponent(
46                         uniqueTimerId,
47                         '',
48                         '',
49                         True
50                 )
51
52                 if parseEntry(timer, baseTimer):
53                         list.append(baseTimer)
54
55 def parseEntry(element, baseTimer, defaults = False):
56         if not defaults:
57                 # Read out match
58                 baseTimer.match = element.get("match", "").encode("UTF-8")
59                 if not baseTimer.match:
60                         print('[AutoTimer] Erroneous config is missing attribute "match", skipping entry')
61                         return False
62
63                 # Read out name
64                 baseTimer.name = element.get("name", "").encode("UTF-8")
65                 if not baseTimer.name:
66                         print('[AutoTimer] Timer is missing attribute "name", defaulting to match')
67                         baseTimer.name = baseTimer.match
68
69                 # Read out enabled
70                 enabled = element.get("enabled", "yes")
71                 if enabled == "no":
72                         baseTimer.enabled = False
73                 elif enabled == "yes":
74                         baseTimer.enabled = True
75                 else:
76                         print('[AutoTimer] Erroneous config contains invalid value for "enabled":', enabled,', disabling')
77                         baseTimer.enabled = False
78
79                 # Read timeframe
80                 before = element.get("before")
81                 after = element.get("after")
82                 if before and after:
83                         baseTimer.timeframe = (int(after), int(before))
84
85                 # VPS-Plugin settings
86                 vps_enabled = element.get("vps_enabled", "no")
87                 vps_overwrite = element.get("vps_overwrite", "no")
88                 baseTimer.vps_enabled = True if vps_enabled == "yes" else False
89                 baseTimer.vps_overwrite = True if vps_overwrite == "yes" else False
90                 del vps_enabled, vps_overwrite
91
92         # Read out encoding (won't change if no value is set)
93         baseTimer.encoding = element.get("encoding")
94
95         # Read out search type/case
96         baseTimer.searchType = element.get("searchType", baseTimer.searchType)
97         baseTimer.searchCase = element.get("searchCase", baseTimer.searchCase)
98
99         # Read out if we should change to alternative services
100         baseTimer.overrideAlternatives = int(element.get("overrideAlternatives", baseTimer.overrideAlternatives))
101
102         # Read out timespan
103         start = element.get("from")
104         end = element.get("to")
105         if start and end:
106                 start = [int(x) for x in start.split(':')]
107                 end = [int(x) for x in end.split(':')]
108                 baseTimer.timespan = (start, end)
109
110         # Read out max length
111         maxduration = element.get("maxduration")
112         if maxduration:
113                 baseTimer.maxduration = int(maxduration)*60
114
115         # Read out recording path
116         default = baseTimer.destination or ""
117         baseTimer.destination = element.get("location", default).encode("UTF-8") or None
118
119         # Read out offset
120         offset = element.get("offset")
121         if offset:
122                 offset = offset.split(",")
123                 if len(offset) == 1:
124                         before = after = int(offset[0] or 0) * 60
125                 else:
126                         before = int(offset[0] or 0) * 60
127                         after = int(offset[1] or 0) * 60
128                 baseTimer.offset = (before, after)
129
130         # Read out counter
131         baseTimer.matchCount = int(element.get("counter", 0))
132         baseTimer.matchFormatString = element.get("counterFormat", "")
133         if not defaults:
134                 baseTimer.matchLeft = int(element.get("left", baseTimer.matchCount))
135                 baseTimer.matchLimit = element.get("lastActivation", "")
136                 baseTimer.lastBegin = int(element.get("lastBegin", 0))
137
138         # Read out justplay
139         baseTimer.justplay = int(element.get("justplay", 0))
140
141         # Read out avoidDuplicateDescription
142         baseTimer.avoidDuplicateDescription = int(element.get("avoidDuplicateDescription", 0))
143
144         # Read out allowed services
145         l = element.findall("serviceref")
146         if l:
147                 servicelist = []
148
149                 for service in l:
150                         value = service.text
151                         if value:
152                                 myref = eServiceReference(str(value))
153                                 if not (myref.flags & eServiceReference.isGroup):
154                                         # strip all after last :
155                                         pos = value.rfind(':')
156                                         if pos != -1:
157                                                 if value[pos-1] == ':':
158                                                         pos -= 1
159                                                 value = value[:pos+1]
160
161                                 servicelist.append(value)
162                 baseTimer.services = servicelist
163
164         # Read out allowed bouquets
165         l = element.findall("bouquet")
166         if l:
167                 bouquets = []
168                 for bouquet in l:
169                         value = bouquet.text
170                         if value:
171                                 bouquets.append(value)
172                 baseTimer.bouquets = bouquets
173
174         # Read out afterevent
175         l = element.findall("afterevent")
176         if l:
177                 idx = {
178                         "none": AFTEREVENT.NONE,
179                         "deepstandby": AFTEREVENT.DEEPSTANDBY,
180                         "shutdown": AFTEREVENT.DEEPSTANDBY,
181                         "standby": AFTEREVENT.STANDBY,
182                         "auto": AFTEREVENT.AUTO
183                 }
184                 afterevents = []
185                 for afterevent in l:
186                         value = afterevent.text
187
188                         if value in idx:
189                                 value = idx[value]
190                         else:
191                                 print('[AutoTimer] Erroneous config contains invalid value for "afterevent":', afterevent,', ignoring definition')
192                                 continue
193
194                         start = afterevent.get("from")
195                         end = afterevent.get("to")
196                         if start and end:
197                                 start = [int(x) for x in start.split(':')]
198                                 end = [int(x) for x in end.split(':')]
199                                 afterevents.append((value, (start, end)))
200                         else:
201                                 afterevents.append((value, None))
202                 baseTimer.afterevent = afterevents
203
204         # Read out exclude
205         l = element.findall("exclude")
206         idx = {"title": 0, "shortdescription": 1, "description": 2, "dayofweek": 3}
207         if l:
208                 excludes = ([], [], [], [])
209                 for exclude in l:
210                         where = exclude.get("where")
211                         value = exclude.text
212                         if not (value and where):
213                                 continue
214
215                         if where in idx:
216                                 excludes[idx[where]].append(value.encode("UTF-8"))
217                 baseTimer.exclude = excludes
218
219         # Read out includes (use same idx)
220         l = element.findall("include")
221         if l:
222                 includes = ([], [], [], [])
223                 for include in l:
224                         where = include.get("where")
225                         value = include.text
226                         if not (value and where):
227                                 continue
228
229                         if where in idx:
230                                 includes[idx[where]].append(value.encode("UTF-8"))
231                 baseTimer.include = includes
232
233         # Read out recording tags
234         l =  element.findall("tag")
235         if l:
236                 tags = []
237                 for tag in l:
238                         value = tag.text
239                         if not value:
240                                 continue
241
242                         tags.append(value.encode("UTF-8"))
243                 baseTimer.tags = tags
244
245         return True
246
247 def parseConfigOld(configuration, list, uniqueTimerId = 0):
248         print("[AutoTimer] Trying to parse old config")
249
250         # Iterate Timers
251         for timer in configuration.findall("timer"):
252                 # Increment uniqueTimerId
253                 uniqueTimerId += 1
254
255                 # Get name (V2+)
256                 name = timer.get("name")
257                 if name:
258                         name = name.encode("UTF-8")
259                 # Get name (= match) (V1)
260                 else:
261                         # Read out name
262                         name = getValue(timer.findall("name"), "").encode("UTF-8")
263
264                 if not name:
265                         print('[AutoTimer] Erroneous config is missing attribute "name", skipping entry')
266                         continue
267
268                 # Read out match (V3+)
269                 match = timer.get("match")
270                 if match:
271                         # Read out match
272                         match = match.encode("UTF-8")
273                         if not match:
274                                 print('[AutoTimer] Erroneous config contains empty attribute "match", skipping entry')
275                                 continue
276                 # V2-
277                 else:
278                         # Setting match to name
279                         match = name
280
281
282                 # See if Timer is ensabled (V2+)
283                 enabled = timer.get("enabled")
284                 if enabled:
285                         if enabled == "no":
286                                 enabled = False
287                         elif enabled == "yes":
288                                 enabled = True
289                         else:
290                                 print('[AutoTimer] Erroneous config contains invalid value for "enabled":', enabled,', skipping entry')
291                                 enabled = False
292                 # V1
293                 else:
294                         elements = timer.findall("enabled")
295                         if elements:
296                                 if getValue(elements, "yes") == "no":
297                                         enabled = False
298                                 else:
299                                         enabled = True
300                         else:
301                                 enabled = True
302
303                 # Read out timespan (V4+; Falling back on missing definition should be OK)
304                 start = timer.get("from")
305                 end = timer.get("to")
306                 if start and end:
307                         start = [int(x) for x in start.split(':')]
308                         end = [int(x) for x in end.split(':')]
309                         timetuple = (start, end)
310                 # V3-
311                 else:
312                         elements = timer.findall("timespan")
313                         Len = len(elements)
314                         if Len:
315                                 # Read out last definition
316                                 start = elements[Len-1].get("from")
317                                 end = elements[Len-1].get("to")
318                                 if start and end:
319                                         start = [int(x) for x in start.split(':')]
320                                         end = [int(x) for x in end.split(':')]
321                                         timetuple = (start, end)
322                                 else:
323                                         print('[AutoTimer] Erroneous config contains invalid definition of "timespan", ignoring definition')
324                                         timetuple = None
325                         else:
326                                 timetuple = None
327
328                 # Read out allowed services (V*)
329                 elements = timer.findall("serviceref")
330                 if elements:
331                         servicelist = []
332                         for service in elements:
333                                 value = service.text
334                                 if value:
335                                         myref = eServiceReference(str(value))
336                                         if not (myref.flags & eServiceReference.isGroup):
337                                                 # strip all after last :
338                                                 pos = value.rfind(':')
339                                                 if pos != -1:
340                                                         if value[pos-1] == ':':
341                                                                 pos -= 1
342                                                         value = value[:pos+1]
343
344                                         servicelist.append(value)
345                 else:
346                         servicelist = None
347
348                 # Read out allowed bouquets (V* though officially supported since V4)
349                 bouquets = []
350                 for bouquet in timer.findall("bouquet"):
351                         value = bouquet.text
352                         if value:
353                                 bouquets.append(value)
354
355                 # Read out offset (V4+)
356                 offset = timer.get("offset")
357                 if offset:
358                         offset = offset.split(",")
359                         if len(offset) == 1:
360                                 before = after = int(offset[0] or 0) * 60
361                         else:
362                                 before = int(offset[0] or 0) * 60
363                                 after = int(offset[1] or 0) * 60
364                         offset = (before, after)
365                 # V3-
366                 else:
367                         elements = timer.findall("offset")
368                         Len = len(elements)
369                         if Len:
370                                 value = elements[Len-1].get("both")
371                                 if value == '':
372                                         before = int(elements[Len-1].get("before", 0)) * 60
373                                         after = int(elements[Len-1].get("after", 0)) * 60
374                                 else:
375                                         before = after = int(value) * 60
376                                 offset = (before, after)
377                         else:
378                                 offset = None
379
380                 # Read out counter
381                 counter = int(timer.get("counter", '0'))
382                 counterLeft = int(timer.get("left", counter))
383                 counterLimit = timer.get("lastActivation")
384                 counterFormat = timer.get("counterFormat", "")
385                 lastBegin = int(timer.get("lastBegin", 0))
386
387                 # Read out justplay
388                 justplay = int(timer.get("justplay", '0'))
389
390                 # Read out avoidDuplicateDescription
391                 avoidDuplicateDescription = int(timer.get("avoidDuplicateDescription", 0))
392
393                 # Read out afterevent (compatible to V* though behaviour for V3- is different as V4+ allows multiple afterevents while the last definication was chosen before)
394                 idx = {
395                         "none": AFTEREVENT.NONE,
396                         "deepstandby": AFTEREVENT.DEEPSTANDBY,
397                         "shutdown": AFTEREVENT.DEEPSTANDBY,
398                         "standby": AFTEREVENT.STANDBY,
399                         "auto": AFTEREVENT.AUTO
400                 }
401                 afterevent = []
402                 for element in timer.findall("afterevent"):
403                         value = element.text
404
405                         if value in idx:
406                                 value = idx[value]
407                         else:
408                                 print('[AutoTimer] Erroneous config contains invalid value for "afterevent":', afterevent,', ignoring definition')
409                                 continue
410
411                         start = element.get("from")
412                         end = element.get("to")
413                         if start and end:
414                                 start = [int(x) for x in start.split(':')]
415                                 end = [int(x) for x in end.split(':')]
416                                 afterevent.append((value, (start, end)))
417                         else:
418                                 afterevent.append((value, None))
419
420                 # Read out exclude (V*)
421                 idx = {"title": 0, "shortdescription": 1, "description": 2, "dayofweek": 3}
422                 excludes = ([], [], [], [])
423                 for exclude in timer.findall("exclude"):
424                         where = exclude.get("where")
425                         value = exclude.text
426                         if not (value and where):
427                                 continue
428
429                         if where in idx:
430                                 excludes[idx[where]].append(value.encode("UTF-8"))
431
432                 # Read out includes (use same idx) (V4+ feature, should not harm V3-)
433                 includes = ([], [], [], [])
434                 for include in timer.findall("include"):
435                         where = include.get("where")
436                         value = include.text
437                         if not (value and where):
438                                 continue
439
440                         if where in idx:
441                                 includes[idx[where]].append(value.encode("UTF-8"))
442
443                 # Read out max length (V4+)
444                 maxlen = timer.get("maxduration")
445                 if maxlen:
446                         maxlen = int(maxlen)*60
447                 # V3-
448                 else:
449                         elements = timer.findall("maxduration")
450                         if elements:
451                                 maxlen = getValue(elements, None)
452                                 if maxlen is not None:
453                                         maxlen = int(maxlen)*60
454                         else:
455                                 maxlen = None
456
457                 # Read out recording path
458                 destination = timer.get("destination", "").encode("UTF-8") or None
459
460                 # Read out recording tags
461                 tags = []
462                 for tag in timer.findall("tag"):
463                         value = tag.text
464                         if not value:
465                                 continue
466
467                         tags.append(value.encode("UTF-8"))
468
469                 # Finally append timer
470                 list.append(preferredAutoTimerComponent(
471                                 uniqueTimerId,
472                                 name,
473                                 match,
474                                 enabled,
475                                 timespan = timetuple,
476                                 services = servicelist,
477                                 offset = offset,
478                                 afterevent = afterevent,
479                                 exclude = excludes,
480                                 include = includes,
481                                 maxduration = maxlen,
482                                 destination = destination,
483                                 matchCount = counter,
484                                 matchLeft = counterLeft,
485                                 matchLimit = counterLimit,
486                                 matchFormatString = counterFormat,
487                                 lastBegin = lastBegin,
488                                 justplay = justplay,
489                                 avoidDuplicateDescription = avoidDuplicateDescription,
490                                 bouquets = bouquets,
491                                 tags = tags
492                 ))
493
494 def buildConfig(defaultTimer, timers, webif = False):
495         # Generate List in RAM
496         list = ['<?xml version="1.0" ?>\n<autotimer version="', CURRENT_CONFIG_VERSION, '">\n\n']
497         append = list.append
498         extend = list.extend
499
500         # This gets deleted afterwards if we do not have set any defaults
501         append(' <defaults')
502         if webif:
503                 extend((' id="', str(defaultTimer.getId()),'"'))
504
505         # Timespan
506         if defaultTimer.hasTimespan():
507                 extend((' from="', defaultTimer.getTimespanBegin(), '" to="', defaultTimer.getTimespanEnd(), '"'))
508
509         # Duration
510         if defaultTimer.hasDuration():
511                 extend((' maxduration="', str(defaultTimer.getDuration()), '"'))
512
513         # Destination
514         if defaultTimer.hasDestination():
515                 extend((' location="', stringToXML(defaultTimer.destination), '"'))
516
517         # Offset
518         if defaultTimer.hasOffset():
519                 if defaultTimer.isOffsetEqual():
520                         extend((' offset="', str(defaultTimer.getOffsetBegin()), '"'))
521                 else:
522                         extend((' offset="', str(defaultTimer.getOffsetBegin()), ',', str(defaultTimer.getOffsetEnd()), '"'))
523
524         # Counter
525         if defaultTimer.hasCounter():
526                 extend((' counter="', str(defaultTimer.getCounter()), '"'))
527                 if defaultTimer.hasCounterFormatString():
528                         extend((' counterFormat="', str(defaultTimer.getCounterFormatString()), '"'))
529
530         # Duplicate Description
531         if defaultTimer.getAvoidDuplicateDescription():
532                 extend((' avoidDuplicateDescription="', str(defaultTimer.getAvoidDuplicateDescription()), '"'))
533
534         # Only display justplay if true
535         if defaultTimer.justplay:
536                 extend((' justplay="', str(defaultTimer.getJustplay()), '"'))
537
538         # Only display encoding if != utf-8
539         if defaultTimer.encoding != 'UTF-8' or webif:
540                 extend((' encoding="', str(defaultTimer.encoding), '"'))
541
542         # Only display searchType if exact
543         if defaultTimer.searchType == "exact":
544                 extend((' searchType="', str(defaultTimer.searchType), '"'))
545
546         # Only display searchCase if sensitive
547         if defaultTimer.searchCase == "sensitive":
548                 extend((' searchCase="', str(defaultTimer.searchCase), '"'))
549
550         # Close still opened defaults tag
551         append('>\n')
552
553         if webif:
554                 # Services + Bouquets
555                 for serviceref in defaultTimer.services + defaultTimer.bouquets:
556                         ref = ServiceReference(str(serviceref))
557                         extend((
558                                 '  <e2service>\n',
559                                 '   <e2servicereference>', str(serviceref), '</e2servicereference>\n',
560                                 '   <e2servicename>', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), '</e2servicename>\n',
561                                 '  </e2service>\n',
562                         ))
563         else:
564                 # Services
565                 for serviceref in defaultTimer.services:
566                         ref = ServiceReference(str(serviceref))
567                         extend(('  <serviceref>', serviceref, '</serviceref>',
568                                                 ' <!-- ', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), ' -->\n',
569                         ))
570
571                 # Bouquets
572                 for bouquet in defaultTimer.bouquets:
573                         ref = ServiceReference(str(bouquet))
574                         extend(('  <bouquet>', str(bouquet), '</bouquet>',
575                                                 ' <!-- ', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), ' -->\n',
576                         ))
577
578         # AfterEvent
579         if defaultTimer.hasAfterEvent():
580                 idx = {
581                         AFTEREVENT.NONE: "none",
582                         AFTEREVENT.STANDBY: "standby",
583                         AFTEREVENT.DEEPSTANDBY: "shutdown",
584                         AFTEREVENT.AUTO: "auto"
585                 }
586                 for afterevent in defaultTimer.afterevent:
587                         action, timespan = afterevent
588                         append('  <afterevent')
589                         if timespan[0] is not None:
590                                 append(' from="%02d:%02d" to="%02d:%02d"' % (timespan[0][0], timespan[0][1], timespan[1][0], timespan[1][1]))
591                         extend(('>', idx[action], '</afterevent>\n'))
592
593         # Excludes
594         for title in defaultTimer.getExcludedTitle():
595                 extend(('  <exclude where="title">', stringToXML(title), '</exclude>\n'))
596         for short in defaultTimer.getExcludedShort():
597                 extend(('  <exclude where="shortdescription">', stringToXML(short), '</exclude>\n'))
598         for desc in defaultTimer.getExcludedDescription():
599                 extend(('  <exclude where="description">', stringToXML(desc), '</exclude>\n'))
600         for day in defaultTimer.getExcludedDays():
601                 extend(('  <exclude where="dayofweek">', stringToXML(day), '</exclude>\n'))
602
603         # Includes
604         for title in defaultTimer.getIncludedTitle():
605                 extend(('  <include where="title">', stringToXML(title), '</include>\n'))
606         for short in defaultTimer.getIncludedShort():
607                 extend(('  <include where="shortdescription">', stringToXML(short), '</include>\n'))
608         for desc in defaultTimer.getIncludedDescription():
609                 extend(('  <include where="description">', stringToXML(desc), '</include>\n'))
610         for day in defaultTimer.getIncludedDays():
611                 extend(('  <include where="dayofweek">', stringToXML(day), '</include>\n'))
612
613         # Tags
614         if webif and defaultTimer.tags:
615                 extend(('  <e2tags>', stringToXML(' '.join(defaultTimer.tags)), '</e2tags>\n'))
616         else:
617                 for tag in defaultTimer.tags:
618                         extend(('  <tag>', stringToXML(tag), '</tag>\n'))
619
620         # Keep the list clean
621         if len(list) == 5:
622                 list.pop() # >
623                 list.pop() # <defaults
624         else:
625                 append(' </defaults>\n\n')
626
627         # Iterate timers
628         for timer in timers:
629                 # Common attributes (match, enabled)
630                 extend((' <timer name="', stringToXML(timer.name), '" match="', stringToXML(timer.match), '" enabled="', timer.getEnabled(), '"'))
631                 if webif:
632                         extend((' id="', str(timer.getId()),'"'))
633
634                 # Timespan
635                 if timer.hasTimespan():
636                         extend((' from="', timer.getTimespanBegin(), '" to="', timer.getTimespanEnd(), '"'))
637
638                 # Timeframe
639                 if timer.hasTimeframe():
640                         extend((' after="', str(timer.getTimeframeBegin()), '" before="', str(timer.getTimeframeEnd()), '"'))
641
642                 # Duration
643                 if timer.hasDuration():
644                         extend((' maxduration="', str(timer.getDuration()), '"'))
645
646                 # Destination
647                 if timer.hasDestination():
648                         extend((' location="', stringToXML(timer.destination), '"'))
649
650                 # Offset
651                 if timer.hasOffset():
652                         if timer.isOffsetEqual():
653                                 extend((' offset="', str(timer.getOffsetBegin()), '"'))
654                         else:
655                                 extend((' offset="', str(timer.getOffsetBegin()), ',', str(timer.getOffsetEnd()), '"'))
656
657                 # Counter
658                 if timer.hasCounter():
659                         extend((' lastBegin="', str(timer.getLastBegin()), '" counter="', str(timer.getCounter()), '" left="', str(timer.getCounterLeft()) ,'"'))
660                         if timer.hasCounterFormatString():
661                                 extend((' lastActivation="', str(timer.getCounterLimit()), '"'))
662                                 extend((' counterFormat="', str(timer.getCounterFormatString()), '"'))
663
664                 # Duplicate Description
665                 if timer.getAvoidDuplicateDescription():
666                         extend((' avoidDuplicateDescription="', str(timer.getAvoidDuplicateDescription()), '"'))
667
668                 # Only display justplay if true
669                 if timer.justplay:
670                         extend((' justplay="', str(timer.getJustplay()), '"'))
671
672                 # Only display encoding if != utf-8
673                 if timer.encoding != 'UTF-8' or webif:
674                         extend((' encoding="', str(timer.encoding), '"'))
675
676                 # Only display searchType if exact
677                 if timer.searchType == "exact":
678                         extend((' searchType="', str(timer.searchType), '"'))
679
680                 # Only display searchCase if sensitive
681                 if timer.searchCase == "sensitive":
682                         extend((' searchCase="', str(timer.searchCase), '"'))
683
684                 # Only display overrideAlternatives if true
685                 if timer.overrideAlternatives:
686                         extend((' overrideAlternatives="', str(timer.getOverrideAlternatives()), '"'))
687
688                 # Only add vps related entries if true
689                 if timer.vps_enabled:
690                         append(' vps_enabled="yes"')
691                         if timer.vps_overwrite:
692                                 append(' vps_overwrite="yes"')
693
694                 # Close still opened timer tag
695                 append('>\n')
696
697                 if webif:
698                         # Services + Bouquets
699                         for serviceref in timer.services + timer.bouquets:
700                                 ref = ServiceReference(str(serviceref))
701                                 extend((
702                                         '  <e2service>\n',
703                                         '   <e2servicereference>', str(serviceref), '</e2servicereference>\n',
704                                         '   <e2servicename>', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), '</e2servicename>\n',
705                                         '  </e2service>\n',
706                                 ))
707                 else:
708                         # Services
709                         for serviceref in timer.services:
710                                 ref = ServiceReference(str(serviceref))
711                                 extend(('  <serviceref>', serviceref, '</serviceref>',
712                                                         ' <!-- ', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), ' -->\n',
713                                 ))
714
715                         # Bouquets
716                         for bouquet in timer.bouquets:
717                                 ref = ServiceReference(str(bouquet))
718                                 extend(('  <bouquet>', str(bouquet), '</bouquet>',
719                                                         ' <!-- ', stringToXML(ref.getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', '')), ' -->\n',
720                                 ))
721
722                 # AfterEvent
723                 if timer.hasAfterEvent():
724                         idx = {
725                                 AFTEREVENT.NONE: "none",
726                                 AFTEREVENT.STANDBY: "standby",
727                                 AFTEREVENT.DEEPSTANDBY: "shutdown",
728                                 AFTEREVENT.AUTO: "auto"
729                         }
730                         for afterevent in timer.afterevent:
731                                 action, timespan = afterevent
732                                 append('  <afterevent')
733                                 if timespan[0] is not None:
734                                         append(' from="%02d:%02d" to="%02d:%02d"' % (timespan[0][0], timespan[0][1], timespan[1][0], timespan[1][1]))
735                                 extend(('>', idx[action], '</afterevent>\n'))
736
737                 # Excludes
738                 for title in timer.getExcludedTitle():
739                         extend(('  <exclude where="title">', stringToXML(title), '</exclude>\n'))
740                 for short in timer.getExcludedShort():
741                         extend(('  <exclude where="shortdescription">', stringToXML(short), '</exclude>\n'))
742                 for desc in timer.getExcludedDescription():
743                         extend(('  <exclude where="description">', stringToXML(desc), '</exclude>\n'))
744                 for day in timer.getExcludedDays():
745                         extend(('  <exclude where="dayofweek">', stringToXML(day), '</exclude>\n'))
746
747                 # Includes
748                 for title in timer.getIncludedTitle():
749                         extend(('  <include where="title">', stringToXML(title), '</include>\n'))
750                 for short in timer.getIncludedShort():
751                         extend(('  <include where="shortdescription">', stringToXML(short), '</include>\n'))
752                 for desc in timer.getIncludedDescription():
753                         extend(('  <include where="description">', stringToXML(desc), '</include>\n'))
754                 for day in timer.getIncludedDays():
755                         extend(('  <include where="dayofweek">', stringToXML(day), '</include>\n'))
756
757                 # Tags
758                 if webif and timer.tags:
759                         extend(('  <e2tags>', stringToXML(' '.join(timer.tags)), '</e2tags>\n'))
760                 else:
761                         for tag in timer.tags:
762                                 extend(('  <tag>', stringToXML(tag), '</tag>\n'))
763
764                 # End of Timer
765                 append(' </timer>\n\n')
766
767         # End of Configuration
768         append('</autotimer>\n')
769
770         return list
771