Add location and tags to the timer dialog in the web interface
[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 "channelOld" is not set, a new Timer will be added to the
200 # Timerlist.
201 # IF the parameters channelOld, beginOld and endOld are set
202 # it's an existing timer will be changed (if possible with the given values)
203 #===============================================================================
204     def editTimer(self, param):
205         print "[WebComponents.Timer] editTimer"
206         
207         #OK first we need to parse all of your Parameters
208         #For some of them (like afterEvent or justplay) we can use default values
209         #for others (the serviceReference or the Begin/End time of the timer 
210         #we have to quit if they are not set/have illegal values
211               
212         if param.has_key('sRef'):
213             service_ref = ServiceReference(param['sRef'])
214         else:
215             return False, "Missing Parameter: sRef"
216                 
217         repeated = 0
218         if param.has_key('repeated'):
219             repeated = int(param['repeated'])
220         
221             
222         if param.has_key('begin'):
223             begin = int(param['begin'])
224             if time() <= begin:                
225                 pass
226             elif time() > int(begin) and repeated == 0:
227                 begin = time()
228             else:
229                 return False, "Illegal Parameter value for Parameter begin : '%s'" %begin              
230         else:
231             return False, "Missing Parameter: begin"
232         
233         
234         if param.has_key('end'): 
235             end = int(param['end'])
236         else:
237             return False, "Missing Parameter: end"
238           
239         if param.has_key('name'):
240             name = param['name']
241         else:
242             return False, "Missing Parameter: name"
243         
244         if param.has_key('description'):
245             description = param['description'].replace("\n", " ")
246         else:
247             return False, "Missing Parameter: description"
248                 
249         disabled = False #Default to: Enabled
250         if param.has_key('disabled'):            
251             if param['disabled'] == "1":
252                 disabled = True
253             else:
254                 #TODO - maybe we can give the user some useful hint here
255                 pass
256             
257         justplay = False #Default to: Record
258         if param.has_key('justplay'):
259             if param['justplay'] == "1":
260                 justplay =  True
261             
262         afterEvent = 3 #Default to Afterevent: Auto
263         if param.has_key('afterevent'):
264             if ( param['afterevent'] == "0") or (param['afterevent'] == "1") or (param['afterevent'] == "2"):
265                 afterEvent = int(param['afterevent'])
266
267         dirname = None
268         if param.has_key('dirname'):
269             dirname = param['dirname']
270
271         tags = None
272         if param.has_key('tags'):
273             tags = unescape(param['tags']).split(' ')
274
275         #Try to edit an existing Timer
276         if param.has_key('channelOld'):
277             print "ChannelOld: %s" %param['channelOld']
278             if param['channelOld'] != '':
279                 channelOld = ServiceReference(param['channelOld'])
280                 
281                 # We do need all of the following Parameters, too, for being able of finding the Timer.
282                 # Therefore so we can neither use default values in this part nor can we 
283                 # continue if a parameter is missing            
284                 if param.has_key('beginOld'):
285                     beginOld = int(param['beginOld'])
286                 else:
287                     return False, "Missing Parameter: beginOld"
288                 
289                 if param.has_key('endOld'):
290                     endOld = int(param['endOld'])
291                 else:
292                     return False, "Missing Parameter: endOld"
293                 
294                 #let's try to find the timer
295                 try:
296                     for timer in self.recordtimer.timer_list + self.recordtimer.processed_timers:
297                         if str(timer.service_ref) == str(channelOld):
298                             if int(timer.begin) == beginOld:
299                                 if int(timer.end) == endOld:
300                                     #we've found the timer we've been searching for
301                                     #Let's apply the new values
302                                     timer.service_ref = service_ref
303                                     timer.begin = int(begin)
304                                     timer.end = int(end)
305                                     timer.name = name
306                                     timer.description = description
307                                     timer.disabled = disabled
308                                     timer.justplay = justplay
309                                     timer.afterEvent = afterEvent
310                                     timer.repeated = repeated
311                                     timer.dirname = dirname
312                                     timer.tags = tags
313                                     
314                                     #send the changed timer back to enigma2 and hope it's good
315                                     self.session.nav.RecordTimer.timeChanged(timer)
316                                     print "[WebComponents.Timer] editTimer: Timer changed!"
317                                     return True, "Timer %s has been changed!" %(timer.name)
318                 except:
319                     #obviously some value was not good, return an error
320                     return False, "Changing the timer for '%s' failed!" %name
321                 
322                 return False, "Could not find timer '%s' with given start and end time!" %name
323         
324         #Try adding a new Timer
325
326         try:
327             #Create a new instance of recordtimerentry
328             timer = RecordTimerEntry(service_ref, begin, end, name, description, 0, disabled, justplay, afterEvent, dirname = dirname, tags = tags)
329             timer.repeated = repeated
330             #add the new timer
331             self.recordtimer.record(timer)
332             return True, "Timer added successfully!"
333         except:
334             #something went wrong, most possibly one of the given paramater-values was wrong
335             return False, "Could not add timer '%s'!" %name
336             
337         return False, "Unexpected Error"
338                 
339
340     def addTimerByEventID(self, param):
341         print "[WebComponents.Timer] addTimerByEventID", param
342         if param['sRef'] is None:
343             return False, "Missing Parameter: sRef"
344         if param['eventid'] is None:
345             return False, "Missing Parameter: eventid"
346         
347         justplay = False
348         if param['justplay'] is not None:
349             if param['justplay'] == "1":
350                 justplay = True
351
352         epgcache = eEPGCache.getInstance()
353         event = epgcache.lookupEventId(eServiceReference(param['sRef']),int(param['eventid']))
354         if event is None:
355             return False, "EventId not found"
356         
357         (begin, end, name, description, eit) = parseEvent(event)
358         
359         timer = RecordTimerEntry(ServiceReference(param['sRef']), begin , end, name, description, eit, False, justplay, AFTEREVENT.NONE)                                
360         self.recordtimer.record(timer)
361         return True, "Timer '%s' added" %(timer.name)  
362             
363         
364     def writeTimerList(self, force=False):
365         # is there an easier and better way? :\
366         if config.plugins.Webinterface.autowritetimer.value or force: 
367             print "Timer.py writing timer to flash"
368             self.session.nav.RecordTimer.saveTimer()
369             return True, "TimerList was saved "
370         else:
371             return False, "TimerList was not saved "    
372
373
374     def getText(self):
375         print "[WebComponents.Timer] result: ", self.result
376         (result, text) = self.result
377         xml  = "<e2simplexmlresult>\n"
378         if result:
379             xml += "<e2state>True</e2state>\n"
380         else:
381             xml += "<e2state>False</e2state>\n"
382         xml += "<e2statetext>%s</e2statetext>\n" % text
383         xml += "</e2simplexmlresult>\n"
384         return xml
385     
386     text = property(getText)
387     
388     ## part for listfiller requests
389     def command(self):
390         timerlist = []
391
392         for item in self.recordtimer.timer_list + self.recordtimer.processed_timers:
393             timer = []
394             timer.append(item.service_ref)
395             timer.append(item.service_ref.getServiceName())
396             timer.append(item.eit)
397             timer.append(item.name)
398             timer.append(item.description)
399
400             if item.disabled is True:
401                 timer.append("1")
402             else:
403                 timer.append("0")
404
405             timer.append(item.begin)
406             timer.append(item.end)
407             timer.append(item.end - item.begin)
408             timer.append(item.start_prepare)
409             
410             if item.justplay is True:
411                 timer.append(1)
412             else:
413                 timer.append(0)
414
415             timer.append(item.afterEvent)
416             
417             timer.append(item.dirname)
418             timer.append(" ".join(item.tags))
419
420             timer.append(item.log_entries)
421             
422             try:
423                 timer.append(item.Filename)
424             except:
425                 timer.append("")
426             
427             timer.append(item.backoff)
428             
429             try:
430                 timer.append(item.next_activation)
431             except:
432                 timer.append("")
433                 
434             timer.append(item.first_try_prepare)  
435             timer.append(item.state)
436             timer.append(item.repeated)
437             
438             if item.dontSave is True:
439                 timer.append(1)
440             else:
441                 timer.append(0)
442
443             timer.append(item.cancelled)
444             
445             if item.eit is not None:
446                 event = self.epgcache.lookupEvent(['EX',("%s" % item.service_ref ,2,item.eit)])
447                 if event[0][0] is not None:
448                     timer.append(event[0][0])
449                 else:
450                     timer.append("N/A")
451             else:
452                 timer.append("N/A")
453             
454             #toggleDisabled
455             if item.disabled is True:
456                 timer.append("0")
457                 timer.append("on")
458             else:
459                 timer.append("1")
460                 timer.append("off")
461
462             timerlist.append(timer)
463             
464         return timerlist
465     
466     list = property(command)
467     lut = {
468                "ServiceReference":0,
469                "ServiceName": 1,
470                "EIT":2,
471                "Name":3,
472                "Description":4,
473                "Disabled":5,
474                "TimeBegin":6,
475                "TimeEnd":7,
476                "Duration":8,
477                "startPrepare":9,
478                "justPlay":10,
479                "afterEvent":11,
480                "Location":12,
481                "Tags":13,
482                "LogEntries":14,
483                "Filename":15,
484                "Backoff":16,
485                "nextActivation":17,
486                "firstTryPrepare":18,
487                "State":19,
488                "Repeated":20,
489                "dontSave":21,
490                "Cancled":22,
491                "DescriptionExtended":23,
492                "toggleDisabled":24,
493                "toggleDisabledIMG":25,
494            }