1 from Components.config import config, ConfigSubsection, ConfigSelection
2 from Components.UsageConfig import preferredInstantRecordPath, defaultMoviePath
4 from enigma import eTimer, eServiceReference, eServiceCenter, iServiceInformation, iRecordableService
5 from RecordTimer import RecordTimerEntry, RecordTimer
6 from Tools.Directories import fileExists
7 from ServiceReference import ServiceReference
9 from Tools import Notifications
10 from Screens.MessageBox import MessageBox
16 config.plugins.pvrdesconvertsetup = ConfigSubsection()
17 config.plugins.pvrdesconvertsetup.activate = ConfigSelection(default = "disable", choices = [ ("enable", _("Enable")), ("disable", _("Disable"))] )
20 SERVICETYPE_PVR_DESCRAMBLE = 11
22 def fileExist(fileName, flag = os.W_OK):
23 return os.access(fileName, flag)
26 if hasattr(os, 'sync'):
30 libc = ctypes.CDLL("libc.so.6")
33 # iStaticServiceInformation
35 def getName(self, sref):
36 return os.path.split(sref.getPath())[1]
37 def getLength(self, sref):
39 def getEvent(self, sref, *args):
43 def getInfo(self, sref, w):
44 if w == iServiceInformation.sTimeCreate:
45 return os.stat(sref.getPath()).st_ctime
46 if w == iServiceInformation.sFileSize:
47 return os.stat(sref.getPath()).st_size
48 if w == iServiceInformation.sDescription:
51 def getInfoString(self, sref, w):
55 class PVRDescrambleConvertInfos:
57 self.navigation = None
59 def getNavigation(self):
60 if not self.navigation:
61 import NavigationInstance
62 if NavigationInstance:
63 self.navigation = NavigationInstance.instance
65 return self.navigation
67 def getRecordings(self):
69 nav = self.getNavigation()
71 recordings = nav.getRecordings()
72 print "getRecordings : ", recordings
76 def getInstandby(self):
77 from Screens.Standby import inStandby
80 def getCurrentMoviePath(self):
81 if not fileExists(config.movielist.last_videodir.value):
82 config.movielist.last_videodir.value = defaultMoviePath()
83 config.movielist.last_videodir.save()
85 curMovieRef = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + config.movielist.last_videodir.value)
88 class PVRDescrambleConvert(PVRDescrambleConvertInfos):
90 PVRDescrambleConvertInfos.__init__(self)
91 config.misc.standbyCounter.addNotifier(self.enterStandby, initial_call = False)
93 self.convertTimer = eTimer()
94 self.convertTimer.callback.append(self.startConvert)
96 self.stopConvertTimer = eTimer()
97 self.stopConvertTimer.callback.append(self.stopConvert)
99 self.converting = None
100 self.convertFilename = None
101 self.currentPvr = None
105 self.oldService = None
107 def enterStandby(self, configElement):
108 if config.plugins.pvrdesconvertsetup.activate.value == "enable":
109 instandby = self.getInstandby()
110 instandby.onClose.append(self.leaveStandby)
112 self.loadScrambledPvrList()
114 # register record callback
115 self.appendRecordEventCB()
117 self.startConvertTimer()
119 def leaveStandby(self):
120 self.removeRecordEventCB()
121 self.convertTimer.stop()
124 def startConvertTimer(self):
125 self.convertTimer.start(3000, True)
127 def startStopConvertTimer(self):
128 self.stopConvertTimer.start(500, True)
130 def appendRecordEventCB(self):
131 nav = self.getNavigation()
133 if self.gotRecordEvent not in nav.record_event:
134 nav.record_event.append(self.gotRecordEvent)
136 def removeRecordEventCB(self):
137 nav = self.getNavigation()
139 if self.gotRecordEvent in nav.record_event:
140 nav.record_event.remove(self.gotRecordEvent)
142 def gotRecordEvent(self, service, event):
143 if service.getServiceType() == SERVICETYPE_PVR_DESCRAMBLE:
144 if event == iRecordableService.evEnd:
145 if self.getInstandby():
146 self.startConvertTimer()
147 elif event == iRecordableService.evPvrEof:
148 self.stopConvert(convertFinished = True)
149 elif event == iRecordableService.evRecordFailed:
150 self.startStopConvertTimer()
152 if event in (iRecordableService.evPvrTuneStart, iRecordableService.evTuneStart):
154 self.pvrLists.insert(0, self.currentPvr)
155 self.currentPvr = None
156 self.startStopConvertTimer()
157 elif event == iRecordableService.evEnd:
158 if self.getInstandby():
159 self.startConvertTimer()
161 def loadScrambledPvrList(self):
164 serviceHandler = eServiceCenter.getInstance()
165 curMovieRef = self.getCurrentMoviePath()
166 movieRefList = serviceHandler.list(curMovieRef)
168 if movieRefList is None:
169 print "Load pvr list failed!"
173 sref = movieRefList.getNext()
177 if config.ParentalControl.servicepinactive.value and config.ParentalControl.storeservicepin.value != "never":
178 from Components.ParentalControl import parentalControl
179 if not parentalControl.sessionPinCached and parentalControl.isProtected(sref):
182 if sref.flags & eServiceReference.mustDescent:
185 if not sref.getPath():
188 info = serviceHandler.info(sref)
190 real_sref = "1:0:0:0:0:0:0:0:0:0:"
192 real_sref = info.getInfoString(sref, iServiceInformation.sServiceref)
197 begin = info.getInfo(sref, iServiceInformation.sTimeCreate)
199 # convert separe-separated list of tags into a set
200 name = info.getName(sref)
201 scrambled = info.getInfo(sref, iServiceInformation.sIsScrambled)
202 length = info.getLength(sref)
206 #print "[loadScrambledPvrList] sref.toString() : ", sref.toString()
207 #print "[loadScrambledPvrList] sref.getPath() : ", sref.getPath()
208 #print "[loadScrambledPvrList] name : ", name
209 #print "[loadScrambledPvrList] begin : ", begin
210 #print "[loadScrambledPvrList] length : ", length
211 #print "[loadScrambledPvrList] scrambled : ", scrambled
213 rec = (begin, sref, name, length, real_sref)
214 if rec not in self.pvrLists:
215 self.pvrLists.append( rec )
219 def checkBeforeStartConvert(self):
220 return self.pvrLists and (not bool(self.getRecordings())) and (not self.converting) and self.getInstandby()
222 def startConvert(self):
223 if not self.checkBeforeStartConvert():
226 self.currentPvr = self.pvrLists.pop(0)
227 if self.currentPvr is None:
230 (_begin, sref, name, length, real_ref) = self.currentPvr
232 m_path = sref.getPath()
233 sref = eServiceReference(real_ref + m_path)
235 begin = int(time.time())
236 end = begin + 3600 # dummy
237 #end = begin + int(length) + 2
241 if isinstance(sref, eServiceReference):
242 sref = ServiceReference(sref)
244 if m_path.endswith('.ts'):
247 filename = m_path + "_pvrdesc"
249 recording = RecordTimerEntry(sref, begin, end, name, description, eventid, dirname = preferredInstantRecordPath(), filename=filename)
250 recording.dontSave = True
251 recording.autoincrease = True
252 recording.setAutoincreaseEnd()
253 recording.pvrConvert = True # do not handle evStart event
255 nav = self.getNavigation()
256 simulTimerList = nav.RecordTimer.record(recording)
257 if simulTimerList is None: # no conflict
258 recordings = self.getRecordings()
259 if len(recordings) == 1:
260 self.converting = recording
261 self.convertFilename = (sref.getPath(), filename + ".ts")
263 print "[PVRDescrambleConvert] error, wrong recordings info."
265 self.currentPvr = None
266 self.startConvertTimer()
268 if len(simulTimerList) > 1: # with other recording
269 print "[PVRDescrambleConvert] conflicts !"
271 print "[PVRDescrambleConvert] Couldn't record due to invalid service %s" % sref
272 recording.autoincrease = False
274 print "[PVRDescrambleConvert] startConvert, self.converting : ", self.converting
276 def removeStr(self, fileName, s):
277 if fileName.find(s) == -1:
280 sp = fileName.split(s)
284 def renameDelPvr(self, pvrName, subName):
285 targetName = pvrName + subName
286 outName = self.removeStr(pvrName, ".ts") + "_del" + ".ts" + subName
288 if fileExist(targetName):
289 #print "RENAME %s -> %s" % (targetName, outName)
290 os.rename(targetName, outName)
295 def renameConvertPvr(self, pvrName, subName):
296 targetName = pvrName + subName
297 outName = self.removeStr(pvrName, "_pvrdesc") + subName
299 if fileExist(targetName):
300 #print "RENAME %s -> %s" % (targetName, outName)
301 os.rename(targetName, outName)
306 def renamePvr(self, pvr_ori, pvr_convert):
307 pvr_ori_del = self.renameDelPvr(pvr_ori, "")
311 self.renameDelPvr(pvr_ori, ".meta")
312 self.renameDelPvr(pvr_ori, ".ap")
313 self.renameDelPvr(pvr_ori, ".sc")
314 self.renameDelPvr(pvr_ori, ".cuts")
316 pvr_convert_fixed = self.renameConvertPvr(pvr_convert, "")
317 if not pvr_convert_fixed:
320 self.renameConvertPvr(pvr_convert, ".meta")
321 self.renameConvertPvr(pvr_convert, ".ap")
322 self.renameConvertPvr(pvr_convert, ".sc")
323 self.renameConvertPvr(pvr_convert, ".cuts")
325 if os.path.exists(pvr_convert[:-3] + '.eit'):
326 os.remove(pvr_convert[:-3] + '.eit')
330 def stopConvert(self, convertFinished = False):
333 (_begin, sref, name, length, real_ref) = self.currentPvr
334 self.currentPvr = None
337 nav = self.getNavigation()
338 nav.RecordTimer.removeEntry(self.converting)
339 convertFilename = self.convertFilename
340 self.converting = None
341 self.convertFilename = None
344 (pvr_ori, pvr_convert) = convertFilename
347 if fileExist(pvr_convert, os.F_OK) and os.stat(pvr_convert).st_size:
348 pvr_ori_del = self.renamePvr(pvr_ori, pvr_convert)
350 self.deletePvr(pvr_ori_del)
351 self.addNotification(_("A PVR descramble converting is finished.\n%s") % name)
353 self.deletePvr(pvr_convert)
355 self.deletePvr(pvr_convert)
359 def deletePvr(self, filename):
360 serviceHandler = eServiceCenter.getInstance()
361 ref = eServiceReference(1, 0, filename)
362 offline = serviceHandler.offlineOperations(ref)
363 if offline.deleteFromDisk(0):
364 print "[PVRDescrambleConvert] delete failed : ", filename
366 def addNotification(self, text):
367 Notifications.AddNotification(MessageBox, text, type=MessageBox.TYPE_INFO, timeout=5)
369 pvr_descramble_convert = PVRDescrambleConvert()