1 #######################################################################
3 # Series Plugin for Enigma-2
4 # Coded by betonme (c) 2012 <glaserfrank(at)gmail.com>
5 # Support: http://www.i-have-a-dreambox.com/wbb2/thread.php?threadid=TBD
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 #######################################################################
23 # for localized messages
27 from Components.config import config
29 from Screens.MessageBox import MessageBox
30 from Tools.Notifications import AddPopup
32 from Tools.BoundFunction import boundFunction
33 from Tools.ASCIItranslit import ASCIItranslit
35 from enigma import eServiceCenter, iServiceInformation, eServiceReference
36 from ServiceReference import ServiceReference
39 from SeriesPlugin import getInstance, refactorTitle, refactorDescription #, refactorRecord
40 from Logger import splog
44 def newLegacyEncode(string):
46 for z, char in enumerate(string.decode("utf-8")):
50 elif i in ASCIItranslit:
51 # There is a bug in the E2 ASCIItranslit some (not all) german-umlaut(a) -> AE
53 string2 += ASCIItranslit[i].lower()
55 string2 += ASCIItranslit[i]
59 string2 += char.encode('ascii', 'strict')
64 def rename(service, name, short, data):
65 # Episode data available
66 splog("SPR: rename:", data)
68 #MAYBE Check if it is already renamed?
70 # Before renaming change content
71 renameMeta(service, data)
72 if config.plugins.seriesplugin.pattern_title.value and not config.plugins.seriesplugin.pattern_title.value == "Off":
74 if config.plugins.seriesplugin.rename_file.value == True:
75 renameFile(service, name, data)
76 #if config.plugins.seriesplugin.pattern_record.value and not config.plugins.seriesplugin.pattern_record.value == "Off":
77 # renameFile(service, name, data)
84 # Adapted from MovieRetitle setTitleDescr
85 def renameMeta(service, data):
87 #TODO Use MetaSupport EitSupport classes from EMC ?
88 if service.getPath().endswith(".ts"):
89 meta_file = service.getPath() + ".meta"
91 meta_file = service.getPath() + ".ts.meta"
93 # Create new meta for ts files
94 if not os.path.exists(meta_file):
95 if os.path.isfile(service.getPath()):
96 _title = os.path.basename(os.path.splitext(service.getPath())[0])
98 _title = service.getName()
103 metafile = open(meta_file, "w")
104 metafile.write("%s\n%s\n%s\n%s\n%s" % (_sid, _title, _descr, _time, _tags))
107 if os.path.exists(meta_file):
108 metafile = open(meta_file, "r")
109 sid = metafile.readline()
110 oldtitle = metafile.readline().rstrip()
111 olddescr = metafile.readline().rstrip()
112 rest = metafile.read()
115 if config.plugins.seriesplugin.pattern_title.value and not config.plugins.seriesplugin.pattern_title.value == "Off":
116 title = refactorTitle(oldtitle, data)
119 splog("SPR: title",title)
120 if config.plugins.seriesplugin.pattern_description.value and not config.plugins.seriesplugin.pattern_description.value == "Off":
121 descr = refactorDescription(olddescr, data)
124 splog("SPR: descr",descr)
126 metafile = open(meta_file, "w")
127 metafile.write("%s%s\n%s\n%s" % (sid, title, descr, rest))
129 except Exception as e:
130 splog("SPR: renameMeta:", e)
132 def renameFile(service, name, data):
134 servicepath = service.getPath()
135 splog("SPR: servicepath", servicepath)
137 path = os.path.dirname(servicepath)
138 file_name = os.path.basename(os.path.splitext(servicepath)[0])
141 if config.plugins.seriesplugin.tidy_rename.value:
142 name = refactorTitle(name, data)
144 name = refactorTitle(file_name, data)
145 # Refactor record file name
146 #name = refactorRecord(file_name, data)
147 name = newLegacyEncode(name)
149 src = os.path.join(path, file_name)
150 splog("SPR: servicepathSrc", src)
151 dst = os.path.join(path, name)
152 splog("SPR: servicepathDst", dst)
154 for f in glob.glob(os.path.join(path, src + "*")):
155 splog("SPR: servicepathRnm", f)
156 to = f.replace(src, dst)
157 splog("SPR: servicepathTo ", to)
158 if not os.path.exists(to):
161 splog("SPR: Skip rename: Destination file alreadey exists", to)
162 except Exception as e:
163 splog("SPR: renameFile:", e)
166 from ThreadQueue import ThreadQueue
167 from threading import Thread
168 from enigma import ePythonMessagePump
170 class SeriesPluginRenameService(Thread):
173 Thread.__init__(self)
174 self.__running = False
175 self.__messages = ThreadQueue()
176 self.__messagePump = ePythonMessagePump()
178 def __getMessagePump(self):
179 return self.__messagePump
180 MessagePump = property(__getMessagePump)
182 def __getMessageQueue(self):
183 return self.__messages
184 Message = property(__getMessageQueue)
186 def __getRunning(self):
187 return self.__running
188 isRunning = property(__getRunning)
190 def Start(self, services):
192 if not self.__running:
193 self.__running = True
194 self.__services = services
195 self.start() # Start blocking code in Thread
199 for service in self.__services:
202 seriesPlugin = getInstance()
203 self.serviceHandler = eServiceCenter.getInstance()
205 if isinstance(service, eServiceReference):
207 elif isinstance(service, ServiceReference):
208 service = service.ref
210 splog("SPR: Wrong instance")
211 self.__messages.push(service)
212 self.__messagePump.send(0)
213 self.__running = False
214 Thread.__init__(self)
217 if not os.path.exists( service.getPath() ):
218 splog("SPR: File not exists: " + service.getPath())
219 self.__messages.push(service)
220 self.__messagePump.send(0)
221 self.__running = False
222 Thread.__init__(self)
225 info = self.serviceHandler.info(service)
227 splog("SPR: No info available: " + service.getPath())
228 self.__messages.push(service)
229 self.__messagePump.send(0)
230 self.__running = False
231 Thread.__init__(self)
234 name = service.getName() or info.getName(service) or ""
235 #splog("SPR: name", name)
239 event = info.getEvent(service)
241 short = event.getShortDescription()
242 begin = event.getBeginTime()
243 duration = event.getDuration() or 0
244 end = begin + duration or 0
245 # We got the exact start times, no need for margin handling
248 begin = info.getInfo(service, iServiceInformation.sTimeCreate) or -1
250 end = begin + (info.getLength(service) or 0)
252 end = os.path.getmtime(service.getPath())
253 begin = end - (info.getLength(service) or 0)
254 #MAYBE we could also try to parse the filename
255 # We don't know the exact margins, we will assume the E2 default margins
256 begin + (int(config.recording.margin_before.value) * 60)
257 end - (int(config.recording.margin_after.value) * 60)
259 rec_ref_str = info.getInfoString(service, iServiceInformation.sServiceref)
260 #channel = ServiceReference(rec_ref_str).getServiceName()
262 splog("SPR: getEpisode:", name, begin, end)
263 seriesPlugin.getEpisode(
264 boundFunction(self.serviceCallback, service, name, short),
265 name, begin, end, rec_ref_str, elapsed=True
268 def serviceCallback(self, service, name, short, data=None):
269 splog("SPR: serviceCallback", name, data)
273 if data and len(data) == 4:
274 if rename(service, name, short, data):
275 # Rename was successfully
278 result = service.getPath() + " : " + str( data )
280 result = service.getPath()
282 self.__messages.push(result)
283 self.__messagePump.send(0)
285 self.__running = False
286 Thread.__init__(self)
287 splog("SPR: Service done")
290 seriespluginrenameservice = SeriesPluginRenameService()
292 #######################################################
294 class SeriesPluginRenamer(object):
295 def __init__(self, session, services, *args, **kwargs):
297 splog("SPR: SeriesPluginRenamer")
299 if services and not isinstance(services, list):
300 services = [services]
302 splog("SPR: len()", len(services))
304 self.services = services
308 self.__pump_recv_msg_conn = None
310 session.openWithCallback(
313 _("Do You want to start renaming?"),
314 MessageBox.TYPE_YESNO,
319 def confirm(self, confirmed):
320 if confirmed and self.services:
321 self.__pump_recv_msg_conn = seriespluginrenameservice.MessagePump.recv_msg.connect(self.gotThreadMsg_seriespluginrenameservice) # interconnect to thread start
322 seriespluginrenameservice.Start(self.services)
324 def gotThreadMsg_seriespluginrenameservice(self, msg):
325 msg = seriespluginrenameservice.Message.pop()
326 splog("SPR: gotThreadMsg", msg)
327 self.renamerCallback(msg)
328 self.__pump_recv_msg_conn = None
330 def renamerCallback(self, result=None):
331 splog("SPR: renamerCallback", result)
333 if result and isinstance(result, basestring):
334 self.data.append( result )
336 if config.plugins.seriesplugin.rename_popups.value and config.plugins.seriesplugin.rename_popups_success.value:
338 self.counter = self.counter +1
340 if self.data or config.plugins.seriesplugin.renamer_popups_success.value:
342 # Maybe there is a better way to avoid multiple Popups
343 from SeriesPlugin import seriespluginworker
344 if not seriespluginworker or seriespluginworker.isListEmpty():
347 "SeriesPlugin:\n" + _("Record rename has been finished with %d errors:\n") % (len(self.data)) +"\n" +"\n".join(self.data),
348 MessageBox.TYPE_ERROR,
350 'SP_PopUp_ID_RenameFinished'
354 "SeriesPlugin:\n" + _("%d records renamed successfully") % (self.counter),
355 MessageBox.TYPE_INFO,
357 'SP_PopUp_ID_RenameFinished'