Small timer-location/tags fixes
[vuplus_dvbapp-plugin] / webinterface / src / WebComponents / Sources / Timer.py
1 Version = '$Header$';
2
3 from enigma import eServiceReference, eEPGCache
4 from Components.Sources.Source import Source
5 from Components.config import config
6 from ServiceReference import ServiceReference
7 from RecordTimer import RecordTimerEntry, RecordTimer, AFTEREVENT, parseEvent
8 from Components.config import config
9 from xml.sax.saxutils import unescape
10 from time import time, strftime, localtime, mktime
11 from string import split
12
13 class Timer( Source):
14     LIST = 0
15     ADDBYID = 1
16     ADD = 2
17     DEL = 3
18     TVBROWSER = 4
19     CHANGE = 5
20     WRITE = 6
21     RECNOW = 7
22     
23     def __init__(self, session, func = LIST):
24         self.func = func
25         Source.__init__(self)
26         self.session = session
27         self.recordtimer = session.nav.RecordTimer
28         self.epgcache = eEPGCache.getInstance()
29         self.result = False,"unknown command"
30         
31
32     def handleCommand(self, cmd):
33         if self.func is self.ADDBYID:
34             self.result = self.addTimerByEventID(cmd)
35             self.writeTimerList()
36         elif self.func is self.ADD:
37             self.result = self.editTimer(cmd)
38             self.writeTimerList()
39         elif self.func is self.TVBROWSER:
40             self.result = self.tvBrowser(cmd)
41             self.writeTimerList()
42         elif self.func is self.DEL:
43             self.result = self.delTimer(cmd)
44             self.writeTimerList()
45         elif self.func is self.CHANGE:
46             self.result = self.editTimer(cmd)
47             self.writeTimerList()
48         elif self.func is self.WRITE:
49             self.result = self.writeTimerList(force=True)
50         elif self.func is self.RECNOW:
51             print "RECNOW"
52             self.result = self.recordNow(cmd)
53         else:
54             self.result = False, "Unknown function: '%s'" %(self.func)
55
56
57
58     def delTimer(self, param):
59         print "[WebComponents.Timer] delTimer"
60         
61         if param.has_key('sRef'):
62             service_ref = ServiceReference(param['sRef'])            
63         else: 
64             return False, "Missing Parameter: sRef"
65         
66         if param.has_key('begin'):
67             begin = int(param['begin'])
68         else:
69             return False, "Missing Parameter: begin"
70         
71         if param.has_key('end'):
72             end = int(param['end'])
73         else:
74                 return False, "Missing Parameter: end"
75              
76         try:
77             for timer in self.recordtimer.timer_list + self.recordtimer.processed_timers:
78                 if str(timer.service_ref) == str(service_ref) and int(timer.begin) == begin and int(timer.end) == end:
79                     self.recordtimer.removeEntry(timer)
80                     return True, "The timer '%s' has been deleted successfully" %(timer.name)
81         except:
82             return False, "The timer has NOT been deleted"
83             
84         return False, "No matching Timer found"
85
86     
87     def tvBrowser(self, param):
88         print "[WebComponents.Timer] tvbrowser"
89         
90         """ The URL's for the tvBrowser-Capture-Driver are:
91         
92             http://dreambox/web/tvbrowser? +
93             
94         To add something:
95             &command=add&&year={year}&month={month}&day={day}&shour={start_hour}&smin={start_minute}&ehour={end_hour}&emin={end_minute}&sRef={urlencode(channel_name_external, "utf8")}&name={urlencode(title, "utf8")}&description={urlencode(descr, "utf8")}&dirname={dirname}&tags={urlencode("tag1 tag2...", "utf8")}&afterevent=0&eit=&disabled=0&justplay=0&repeated=0
96         
97         to zap for some time:
98             &command=add&&year={year}&month={month}&day={day}&shour={start_hour}&smin={start_minute}&ehour={end_hour}&emin={end_minute}&sRef={urlencode(channel_name_external, "utf8")}&name={urlencode(title, "utf8")}&description={urlencode(descr, "utf8")}&dirname={dirname}&tags={urlencode("tag1 tag2...", "utf8")}&afterevent=0&eit=&disabled=0&justplay=1&repeated=0
99         
100         to delete something:
101             &command=del&&year={year}&month={month}&day={day}&shour={start_hour}&smin={start_minute}&ehour={end_hour}&emin={end_minute}&sRef={urlencode(channel_name_external, "utf8")}
102         """
103         
104         listDate = ['year','month','day','shour','smin','ehour','emin']
105         for element in listDate:
106             if param[element] is None:
107                 return False,"%s missing"%element
108             else:
109                 param[element] = int(param[element])
110         param['begin'] = int(mktime( (param['year'], param['month'], param['day'], param['shour'], param['smin'], 0, 0, 0, -1) ) )
111         param['end']   = int(mktime( (param['year'], param['month'], param['day'], param['ehour'], param['emin'], 0, 0, 0, -1) ) )
112         if param['end'] < param['begin']:
113             param['end'] += 86400
114         for element in listDate:
115             del param[element]
116         
117         if param['sRef'] is None:
118             return False, "Missing Parameter: sRef"
119         else:
120             takeApart = split(param['sRef'], '|')
121             if len(takeApart) > 1:
122                 param['sRef'] = takeApart[1]
123         
124         repeated = 0
125         if param.has_key('repeated'):
126             repeated = int(param['repeated'])
127         if repeated == 0:
128             list = ["mo","tu","we","th","fr","sa","su","ms","mf"]
129             for element in list:
130                 if param.has_key(element):
131                     number = param[element] or 0
132                     del param[element]
133                     repeated = repeated + int(number)
134             if repeated > 127:
135                 repeated = 127
136         param['repeated'] = repeated
137
138         if param['command'] == "add":
139             del param['command']
140             return self.editTimer(param)
141         elif param['command'] == "del":
142             del param['command']
143             return self.delTimer(param)
144         elif param['command'] == "change":
145             del param['command']
146             return self.editTimer(param)
147         else:
148             return False, "Unknown command: '%s'" %param['command']
149     
150     def recordNow(self,param):
151         print "recordNow ",param
152         
153         limitEvent = True
154         if param == "undefinitely":
155             limitEvent = False
156         
157         serviceref = self.session.nav.getCurrentlyPlayingServiceReference()
158         print serviceref
159         #assert isinstance(serviceref, ServiceReference)
160         serviceref = ServiceReference(serviceref.toString())
161         event = None
162         try:
163             service = self.session.nav.getCurrentService()
164             event = self.epgcache.lookupEventTime(serviceref, -1, 0)
165             if event is None:
166                 info = service.info()
167                 ev = info.getEvent(0)
168                 event = ev
169         except:
170             pass
171
172         begin = time()
173         end = begin + 3600 * 10
174         name = "instant record"
175         description = ""
176         eventid = 0
177
178         if event is not None:
179             curEvent = parseEvent(event)
180             name = curEvent[2]
181             description = curEvent[3]
182             eventid = curEvent[4]
183             if limitEvent:
184                 end = curEvent[1]
185         else:
186             if limitEvent:
187                 return False, "No event found, started infinite recording"
188
189         location = config.movielist.last_videodir.value
190         timer = RecordTimerEntry(serviceref, begin, end, name, description, eventid, False, False, 0, dirname = location)
191         timer.dontSave = True
192         self.recordtimer.record(timer)
193
194         return True, "Instant recording started"
195
196
197 #===============================================================================
198 # This Function can add a new or edit an exisiting Timer.
199 # When the Parameter "deleteOldOnSave" is not set, a new Timer will be added.
200 # Otherwise, and if the parameters channelOld, beginOld and endOld are set,
201 # an existing timer with corresponding values will be changed.
202 #===============================================================================
203     def editTimer(self, param):
204         print "[WebComponents.Timer] editTimer"
205         
206         #OK first we need to parse all of your Parameters
207         #For some of them (like afterEvent or justplay) we can use default values
208         #for others (the serviceReference or the Begin/End time of the timer 
209         #we have to quit if they are not set/have illegal values
210               
211         if param.has_key('sRef'):
212             service_ref = ServiceReference(param['sRef'])
213         else:
214             return False, "Missing Parameter: sRef"
215                 
216         repeated = 0
217         if param.has_key('repeated'):
218             repeated = int(param['repeated'])
219         
220             
221         if param.has_key('begin'):
222             begin = int(param['begin'])
223             if time() <= begin:                
224                 pass
225             elif time() > int(begin) and repeated == 0:
226                 begin = time()
227             else:
228                 return False, "Illegal Parameter value for Parameter begin : '%s'" %begin              
229         else:
230             return False, "Missing Parameter: begin"
231         
232         if param.has_key('end'): 
233             end = int(param['end'])
234         else:
235             return False, "Missing Parameter: end"
236           
237         if param.has_key('name'):
238             name = param['name']
239         else:
240             return False, "Missing Parameter: name"
241         
242         if param.has_key('description'):
243             description = param['description'].replace("\n", " ")
244         else:
245             return False, "Missing Parameter: description"
246                 
247         disabled = False #Default to: Enabled
248         if param.has_key('disabled'):            
249             if param['disabled'] == "1":
250                 disabled = True
251             else:
252                 #TODO - maybe we can give the user some useful hint here
253                 pass
254             
255         justplay = False #Default to: Record
256         if param.has_key('justplay'):
257             if param['justplay'] == "1":
258                 justplay =  True
259             
260         afterEvent = 3 #Default to Afterevent: Auto
261         if param.has_key('afterevent'):
262             if ( param['afterevent'] == "0") or (param['afterevent'] == "1") or (param['afterevent'] == "2"):
263                 afterEvent = int(param['afterevent'])
264
265         dirname = config.movielist.last_timer_videodir.value
266         if param.has_key('dirname'):
267             dirname = param['dirname']
268
269         tags = None
270         if param.has_key('tags'):
271             tags = unescape(param['tags']).split(' ')
272
273         delold = 0
274         if param.has_key('deleteOldOnSave'):
275             delold = int(param['deleteOldOnSave'])
276
277         #Try to edit an existing Timer
278         if delold:
279             if param.has_key('channelOld') and param['channelOld'] != '':
280                 channelOld = ServiceReference(param['channelOld'])
281             else:
282                 return False, "Missing Parameter: channelOld"
283             # We do need all of the following Parameters, too, for being able of finding the Timer.
284             # Therefore so we can neither use default values in this part nor can we 
285             # continue if a parameter is missing            
286             if param.has_key('beginOld'):
287                 beginOld = int(param['beginOld'])
288             else:
289                 return False, "Missing Parameter: beginOld"
290             
291             if param.has_key('endOld'):
292                 endOld = int(param['endOld'])
293             else:
294                 return False, "Missing Parameter: endOld"
295             
296             #let's try to find the timer
297             try:
298                 for timer in self.recordtimer.timer_list + self.recordtimer.processed_timers:
299                     if str(timer.service_ref) == str(channelOld):
300                         if int(timer.begin) == beginOld:
301                             if int(timer.end) == endOld:
302                                 #we've found the timer we've been searching for
303                                 #Let's apply the new values
304                                 timer.service_ref = service_ref
305                                 timer.begin = int(begin)
306                                 timer.end = int(end)
307                                 timer.name = name
308                                 timer.description = description
309                                 timer.disabled = disabled
310                                 timer.justplay = justplay
311                                 timer.afterEvent = afterEvent
312                                 timer.repeated = repeated
313                                 timer.dirname = dirname
314                                 timer.tags = tags
315                                 
316                                 #send the changed timer back to enigma2 and hope it's good
317                                 self.session.nav.RecordTimer.timeChanged(timer)
318                                 print "[WebComponents.Timer] editTimer: Timer changed!"
319                                 return True, "Timer %s has been changed!" %(timer.name)
320             except:
321                 #obviously some value was not good, return an error
322                 return False, "Changing the timer for '%s' failed!" %name
323             
324             return False, "Could not find timer '%s' with given start and end time!" %name
325
326         #Try adding a new Timer
327
328         try:
329             #Create a new instance of recordtimerentry
330             timer = RecordTimerEntry(service_ref, begin, end, name, description, 0, disabled, justplay, afterEvent, dirname = dirname, tags = tags)
331             timer.repeated = repeated
332             #add the new timer
333             self.recordtimer.record(timer)
334             return True, "Timer added successfully!"
335         except:
336             #something went wrong, most possibly one of the given paramater-values was wrong
337             return False, "Could not add timer '%s'!" %name
338             
339         return False, "Unexpected Error"
340                 
341
342     def addTimerByEventID(self, param):
343         print "[WebComponents.Timer] addTimerByEventID", param
344         if param['sRef'] is None:
345             return False, "Missing Parameter: sRef"
346         if param['eventid'] is None:
347             return False, "Missing Parameter: eventid"
348         
349         justplay = False
350         if param['justplay'] is not None:
351             if param['justplay'] == "1":
352                 justplay = True
353
354         location = config.movielist.last_timer_videodir.value
355         if param['dirname'] is not None and param['dirname'] != "":
356             location = param['dirname']
357         tags = None
358         if param['tags'] is not None and param['tags'] != "":
359             tags = param['tags']
360
361         epgcache = eEPGCache.getInstance()
362         event = epgcache.lookupEventId(eServiceReference(param['sRef']),int(param['eventid']))
363         if event is None:
364             return False, "EventId not found"
365         
366         (begin, end, name, description, eit) = parseEvent(event)
367
368         timer = RecordTimerEntry(ServiceReference(param['sRef']), begin , end, name, description, eit, False, justplay, AFTEREVENT.NONE, dirname=location, tags=tags)
369         self.recordtimer.record(timer)
370         return True, "Timer '%s' added" %(timer.name)  
371             
372         
373     def writeTimerList(self, force=False):
374         # is there an easier and better way? :\
375         if config.plugins.Webinterface.autowritetimer.value or force: 
376             print "Timer.py writing timer to flash"
377             self.session.nav.RecordTimer.saveTimer()
378             return True, "TimerList was saved "
379         else:
380             return False, "TimerList was not saved "    
381
382
383     def getText(self):
384         print "[WebComponents.Timer] result: ", self.result
385         (result, text) = self.result
386         xml  = "<e2simplexmlresult>\n"
387         if result:
388             xml += "<e2state>True</e2state>\n"
389         else:
390             xml += "<e2state>False</e2state>\n"
391         xml += "<e2statetext>%s</e2statetext>\n" % text
392         xml += "</e2simplexmlresult>\n"
393         return xml
394     
395     text = property(getText)
396     
397     ## part for listfiller requests
398     def command(self):
399         timerlist = []
400
401         for item in self.recordtimer.timer_list + self.recordtimer.processed_timers:
402             timer = []
403             timer.append(item.service_ref)
404             timer.append(item.service_ref.getServiceName())
405             timer.append(item.eit)
406             timer.append(item.name)
407             timer.append(item.description)
408
409             if item.disabled is True:
410                 timer.append("1")
411             else:
412                 timer.append("0")
413
414             timer.append(item.begin)
415             timer.append(item.end)
416             timer.append(item.end - item.begin)
417             timer.append(item.start_prepare)
418             
419             if item.justplay is True:
420                 timer.append(1)
421             else:
422                 timer.append(0)
423
424             timer.append(item.afterEvent)
425             
426             timer.append(item.dirname)
427             timer.append(" ".join(item.tags))
428
429             timer.append(item.log_entries)
430             
431             try:
432                 timer.append(item.Filename)
433             except:
434                 timer.append("")
435             
436             timer.append(item.backoff)
437             
438             try:
439                 timer.append(item.next_activation)
440             except:
441                 timer.append("")
442                 
443             timer.append(item.first_try_prepare)  
444             timer.append(item.state)
445             timer.append(item.repeated)
446             
447             if item.dontSave is True:
448                 timer.append(1)
449             else:
450                 timer.append(0)
451
452             timer.append(item.cancelled)
453             
454             if item.eit is not None:
455                 event = self.epgcache.lookupEvent(['EX',("%s" % item.service_ref ,2,item.eit)])
456                 if event[0][0] is not None:
457                     timer.append(event[0][0])
458                 else:
459                     timer.append("N/A")
460             else:
461                 timer.append("N/A")
462             
463             #toggleDisabled
464             if item.disabled is True:
465                 timer.append("0")
466                 timer.append("on")
467             else:
468                 timer.append("1")
469                 timer.append("off")
470
471             timerlist.append(timer)
472             
473         return timerlist
474     
475     list = property(command)
476     lut = {
477                "ServiceReference":0,
478                "ServiceName": 1,
479                "EIT":2,
480                "Name":3,
481                "Description":4,
482                "Disabled":5,
483                "TimeBegin":6,
484                "TimeEnd":7,
485                "Duration":8,
486                "startPrepare":9,
487                "justPlay":10,
488                "afterEvent":11,
489                "Location":12,
490                "Tags":13,
491                "LogEntries":14,
492                "Filename":15,
493                "Backoff":16,
494                "nextActivation":17,
495                "firstTryPrepare":18,
496                "State":19,
497                "Repeated":20,
498                "dontSave":21,
499                "Cancled":22,
500                "DescriptionExtended":23,
501                "toggleDisabled":24,
502                "toggleDisabledIMG":25,
503            }