fix memleak
[enigma2.git] / RecordTimer.py
1 import time
2 import codecs
3 #from time import datetime
4 from Tools import Directories, Notifications
5
6 from Components.config import config
7 import timer
8 import xml.dom.minidom
9
10 from Screens.MessageBox import MessageBox
11 from Screens.SubserviceSelection import SubserviceSelection
12 import NavigationInstance
13
14 from Tools.XMLTools import elementsWithTag
15 from ServiceReference import ServiceReference
16
17 # ok, for descriptions etc we have:
18 # service reference  (to get the service name)
19 # name               (title)
20 # description        (description)
21 # event data         (ONLY for time adjustments etc.)
22
23
24 # parses an event, and gives out a (begin, end, name, duration, eit)-tuple.
25 def parseEvent(ev):
26         name = ev.getEventName()
27         description = ev.getShortDescription()
28         begin = ev.getBeginTime()
29         end = begin + ev.getDuration()
30         eit = ev.getEventId()
31         return (begin, end, name, description, eit)
32
33 class RecordTimerEntry(timer.TimerEntry):
34         def __init__(self, serviceref, begin, end, name, description, eit):
35                 timer.TimerEntry.__init__(self, int(begin), int(end))
36                 
37                 assert isinstance(serviceref, ServiceReference)
38                 
39                 self.service_ref = serviceref
40                 
41                 self.eit = eit
42                 
43                 self.dontSave = False
44                 self.name = name
45                 self.description = description
46                 self.timer = None
47                 self.record_service = None
48                 self.wantStart = False
49                 self.prepareOK = False
50                 
51         def calculateFilename(self):
52                 service_name = self.service_ref.getServiceName()
53 #               begin_date = datetime.fromtimestamp(begin).strf...
54                 begin_date = ""
55                 
56                 print "begin_date: ", begin_date
57                 print "service_name: ", service_name
58                 print "name:", self.name
59                 print "description: ", self.description
60
61                 self.Filename = Directories.getRecordingFilename(service_name)
62                 #begin_date + " - " + service_name + description)
63                 
64         
65         def tryPrepare(self):
66                 self.calculateFilename()
67                 self.record_service = NavigationInstance.instance.recordService(self.service_ref)
68                 if self.record_service == None:
69                         return False
70                 else:
71                         if self.record_service.prepare(self.Filename + ".ts"):
72                                 self.record_service = None
73                                 return False
74
75                         f = open(self.Filename + ".ts.meta", "w")
76                         f.write(str(self.service_ref) + "\n")
77                         f.write(self.name + "\n")
78                         f.write(self.description + "\n")
79                         f.write(str(self.begin) + "\n")
80                         del f
81                         return True
82
83         def activate(self, event):
84                 if event == self.EventPrepare:
85                         self.prepareOK = False
86                         if self.tryPrepare():
87                                 self.prepareOK = True
88                         else:
89                                 # error.
90                                 if config.recording.asktozap.value == 0:
91                                         Notifications.AddNotificationWithCallback(self.failureCB, MessageBox, _("A timer failed to record!\nDisable TV and try again?\n"))
92                                 else: # zap without asking
93                                         self.failureCB(True)
94                 elif event == self.EventStart:
95                         if self.prepareOK:
96                                 self.record_service.start()
97                                 print "timer started!"
98                         else:
99                                 print "prepare failed, thus start failed, too."
100                                 self.wantStart = True
101                 elif event == self.EventEnd or event == self.EventAbort:
102                         self.wantStart = False
103                         if self.prepareOK:
104                                 self.record_service.stop()
105                                 self.record_service = None
106                                 
107                                 print "Timer successfully ended"
108                         else:
109                                 print "prepare failed, thus nothing was recorded."
110
111         def abort():
112                 # fixme
113                 pass
114
115         def failureCB(self, answer):
116                 if answer == True:
117                         #NavigationInstance.instance.stopUserServices()
118                         print "[RecordTimer] zapping to", self.service_ref
119                         NavigationInstance.instance.playService(self.service_ref.ref)
120                         self.activate(self.EventPrepare)
121
122                         if self.wantStart:
123                                 print "post-activating record"
124                                 self.activate(self.EventStart)
125                 else:
126                         print "user killed record"
127
128 def createTimer(xml):
129         begin = int(xml.getAttribute("begin"))
130         end = int(xml.getAttribute("end"))
131         serviceref = ServiceReference(str(xml.getAttribute("serviceref")))
132         description = xml.getAttribute("description").encode("utf-8")
133         repeated = xml.getAttribute("repeated").encode("utf-8")
134         eit = xml.getAttribute("eit").encode("utf-8")
135         name = xml.getAttribute("name").encode("utf-8")
136         #filename = xml.getAttribute("filename").encode("utf-8")
137         entry = RecordTimerEntry(serviceref, begin, end, name, description, eit)
138         entry.repeated = int(repeated)
139         return entry
140
141 class RecordTimer(timer.Timer):
142         def __init__(self):
143                 timer.Timer.__init__(self)
144                 
145                 self.Filename = Directories.resolveFilename(Directories.SCOPE_CONFIG, "timers.xml")
146                 
147                 try:
148                         self.loadTimer()
149                 except IOError:
150                         print "unable to load timers from file!"
151                         
152         def isRecording(self):
153                 isRunning = False
154                 for timer in self.timer_list:
155                         if timer.isRunning():
156                                 isRunning = True
157                 return isRunning
158         
159         def loadTimer(self):
160                 # TODO: PATH!
161                 doc = xml.dom.minidom.parse(self.Filename)
162                 
163                 root = doc.childNodes[0]
164                 for timer in elementsWithTag(root.childNodes, "timer"):
165                         self.record(createTimer(timer))
166         
167         def saveTimer(self):
168                 doc = xml.dom.minidom.Document()
169                 root_element = doc.createElement('timers')
170                 doc.appendChild(root_element)
171                 root_element.appendChild(doc.createTextNode("\n"))
172                 
173                 for timer in self.timer_list + self.processed_timers:
174                         # some timers (instant records) don't want to be saved.
175                         # skip them
176                         if timer.dontSave:
177                                 continue
178                         t = doc.createTextNode("\t")
179                         root_element.appendChild(t)
180                         t = doc.createElement('timer')
181                         t.setAttribute("begin", str(timer.begin))
182                         t.setAttribute("end", str(timer.end))
183                         t.setAttribute("serviceref", str(timer.service_ref))
184                         t.setAttribute("repeated", str(timer.repeated))                 
185                         t.setAttribute("name", timer.name)
186                         t.setAttribute("description", timer.description)
187                         t.setAttribute("eit", str(timer.eit))
188                         
189                         root_element.appendChild(t)
190                         t = doc.createTextNode("\n")
191                         root_element.appendChild(t)
192
193                 file = open(self.Filename, "w")
194                 doc.writexml(file)
195                 file.write("\n")
196                 file.close()
197         
198         def record(self, entry):
199                 print "[Timer] Record " + str(entry)
200                 entry.Timer = self
201                 self.addTimerEntry(entry)
202
203         def removeEntry(self, entry):
204                 print "[Timer] Remove " + str(entry)
205                 
206                 entry.repeated = False
207
208                 if entry.state == timer.TimerEntry.StateRunning:
209                         print "remove running timer."
210                         entry.end = time.time()
211                         self.timeChanged(entry)
212                 elif entry.state != timer.TimerEntry.StateEnded:
213                         entry.activate(timer.TimerEntry.EventAbort)
214                         self.timer_list.remove(entry)
215
216                         self.calcNextActivation()
217                         print "timer did not yet start - removing"
218
219                         # the timer was aborted, and removed.
220                         return
221                 else:
222                         print "timer did already end - doing nothing."
223                 
224                 print "state: ", entry.state
225                 print "in processed: ", entry in self.processed_timers
226                 print "in running: ", entry in self.timer_list
227                 # now the timer should be in the processed_timers list. remove it from there.
228                 self.processed_timers.remove(entry)
229
230         def shutdown(self):
231                 self.saveTimer()