SeriesPlugin 1.3.1: Fixed typos
[enigma2-plugins.git] / seriesplugin / src / SeriesPluginRenamer.py
1 #######################################################################
2 #
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
6 #
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.
11 #
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.
16 #
17 #######################################################################
18
19 import os
20 import re
21 import glob
22
23 # for localized messages
24 from . import _
25
26 # Config
27 from Components.config import config
28
29 from Screens.MessageBox import MessageBox
30 from Tools.Notifications import AddPopup
31
32 from Tools.BoundFunction import boundFunction
33 from Tools.ASCIItranslit import ASCIItranslit
34
35 from enigma import eServiceCenter, iServiceInformation, eServiceReference
36 from ServiceReference import ServiceReference
37
38 # Plugin internal
39 from SeriesPlugin import getInstance, refactorTitle, refactorDescription   #, refactorRecord
40 from Logger import splog
41
42
43 # By Bin4ry
44 def newLegacyEncode(string):
45         string2 = ""
46         for z, char in enumerate(string.decode("utf-8")):
47                 i = ord(char)
48                 if i < 33:
49                         string2 += " "
50                 elif i in ASCIItranslit:
51                         # There is a bug in the E2 ASCIItranslit some (not all) german-umlaut(a) -> AE
52                         if char.islower():
53                                 string2 += ASCIItranslit[i].lower()
54                         else:
55                                 string2 += ASCIItranslit[i]
56                                 
57                 else:
58                         try:
59                                 string2 += char.encode('ascii', 'strict')
60                         except:
61                                 string2 += " "
62         return string2
63
64 def rename(service, name, short, data):
65         # Episode data available
66         splog("SPR: rename:", data)
67         
68         #MAYBE Check if it is already renamed?
69         try:
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":
73
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)
78                 return True
79         except:
80                 #pass
81                 raise
82         return False
83
84 # Adapted from MovieRetitle setTitleDescr
85 def renameMeta(service, data):
86         try:
87                 #TODO Use MetaSupport EitSupport classes from EMC ?
88                 if service.getPath().endswith(".ts"):
89                         meta_file = service.getPath() + ".meta"
90                 else:
91                         meta_file = service.getPath() + ".ts.meta"
92                 
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])
97                         else:
98                                 _title = service.getName()
99                         _sid = ""
100                         _descr = ""
101                         _time = ""
102                         _tags = ""
103                         metafile = open(meta_file, "w")
104                         metafile.write("%s\n%s\n%s\n%s\n%s" % (_sid, _title, _descr, _time, _tags))
105                         metafile.close()
106                 
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()
113                         metafile.close()
114                         
115                         if config.plugins.seriesplugin.pattern_title.value and not config.plugins.seriesplugin.pattern_title.value == "Off":
116                                 title = refactorTitle(oldtitle, data)
117                         else:
118                                 title = oldtitle
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)
122                         else:
123                                 descr = olddescr
124                         splog("SPR: descr",descr)
125                         
126                         metafile = open(meta_file, "w")
127                         metafile.write("%s%s\n%s\n%s" % (sid, title, descr, rest))
128                         metafile.close()
129         except Exception as e:
130                 splog("SPR: renameMeta:", e)
131
132 def renameFile(service, name, data):
133         try:
134                 servicepath = service.getPath()
135                 splog("SPR: servicepath", servicepath)
136                 
137                 path = os.path.dirname(servicepath)
138                 file_name = os.path.basename(os.path.splitext(servicepath)[0])
139                 
140                 # Refactor title
141                 if config.plugins.seriesplugin.tidy_rename.value:
142                         name = refactorTitle(name, data)
143                 else:
144                         name = refactorTitle(file_name, data)
145                 # Refactor record file name
146                 #name = refactorRecord(file_name, data)
147                 name = newLegacyEncode(name)
148                 
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)
153
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):
159                                 os.rename(f, to)
160                         else:
161                                 splog("SPR: Skip rename: Destination file alreadey exists", to)
162         except Exception as e:
163                 splog("SPR: renameFile:", e)
164
165
166 from ThreadQueue import ThreadQueue
167 from threading import Thread
168 from enigma import ePythonMessagePump
169
170 class SeriesPluginRenameService(Thread):
171         
172         def __init__(self):
173                 Thread.__init__(self)
174                 self.__running = False
175                 self.__messages = ThreadQueue()
176                 self.__messagePump = ePythonMessagePump()
177
178         def __getMessagePump(self):
179                 return self.__messagePump
180         MessagePump = property(__getMessagePump)
181
182         def __getMessageQueue(self):
183                 return self.__messages
184         Message = property(__getMessageQueue)
185
186         def __getRunning(self):
187                 return self.__running
188         isRunning = property(__getRunning)
189
190         def Start(self, services):
191         
192                 if not self.__running:
193                         self.__running = True
194                         self.__services = services
195                         self.start() # Start blocking code in Thread 
196                         
197         def run(self):
198                 
199                 for service in self.__services:
200                         
201                         splog("SPR: run")
202                         seriesPlugin = getInstance()
203                         self.serviceHandler = eServiceCenter.getInstance()
204                         
205                         if isinstance(service, eServiceReference):
206                                 service = service
207                         elif isinstance(service, ServiceReference):
208                                 service = service.ref
209                         else:
210                                 splog("SPR: Wrong instance")
211                                 self.__messages.push(service)
212                                 self.__messagePump.send(0)
213                                 self.__running = False
214                                 Thread.__init__(self)
215                                 return
216                         
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)
223                                 return
224                         
225                         info = self.serviceHandler.info(service)
226                         if not info:
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)
232                                 return 
233                         
234                         name = service.getName() or info.getName(service) or ""
235                         #splog("SPR: name", name)
236                         
237                         short = ""
238                         
239                         event = info.getEvent(service)
240                         if event:
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
246                         
247                         if not begin:
248                                 begin = info.getInfo(service, iServiceInformation.sTimeCreate) or -1
249                                 if begin != -1:
250                                         end = begin + (info.getLength(service) or 0)
251                                 else:
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)
258                         
259                         rec_ref_str = info.getInfoString(service, iServiceInformation.sServiceref)
260                         #channel = ServiceReference(rec_ref_str).getServiceName()
261                         
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
266                                 )
267
268         def serviceCallback(self, service, name, short, data=None):
269                 splog("SPR: serviceCallback", name, data)
270                 
271                 result = None
272                 
273                 if data and len(data) == 4:
274                         if rename(service, name, short, data):
275                                 # Rename was successfully
276                                 result = None
277                 elif data:
278                         result = service.getPath() + " : " + str( data )
279                 else:
280                         result = service.getPath()
281                 
282                 self.__messages.push(result)
283                 self.__messagePump.send(0)
284
285                 self.__running = False
286                 Thread.__init__(self)
287                 splog("SPR: Service done")
288
289                 
290 seriespluginrenameservice = SeriesPluginRenameService()
291
292 #######################################################
293 # Rename movies
294 class SeriesPluginRenamer(object):
295         def __init__(self, session, services, *args, **kwargs):
296                 
297                 splog("SPR: SeriesPluginRenamer")
298                 
299                 if services and not isinstance(services, list):
300                         services = [services]   
301                 
302                 splog("SPR: len()", len(services))
303                 
304                 self.services = services
305                 
306                 self.data = []
307                 self.counter = 0
308                 self.__pump_recv_msg_conn = None
309                 
310                 session.openWithCallback(
311                         self.confirm,
312                         MessageBox,
313                         _("Do You want to start renaming?"),
314                         MessageBox.TYPE_YESNO,
315                         timeout = 15,
316                         default = True
317                 )
318
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)
323
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
329
330         def renamerCallback(self, result=None):
331                 splog("SPR: renamerCallback", result)
332                 
333                 if result and isinstance(result, basestring):
334                         self.data.append( result )
335                 
336                 if config.plugins.seriesplugin.rename_popups.value and config.plugins.seriesplugin.rename_popups_success.value:
337                         
338                         self.counter = self.counter +1
339                         
340                         if self.data or config.plugins.seriesplugin.renamer_popups_success.value:
341                         
342                                 # Maybe there is a better way to avoid multiple Popups
343                                 from SeriesPlugin import seriespluginworker
344                                 if not seriespluginworker or seriespluginworker.isListEmpty():
345                                         if self.data:
346                                                 AddPopup(
347                                                         "SeriesPlugin:\n" + _("Record rename has been finished with %d errors:\n") % (len(self.data)) +"\n" +"\n".join(self.data),
348                                                         MessageBox.TYPE_ERROR,
349                                                         0,
350                                                         'SP_PopUp_ID_RenameFinished'
351                                                 )
352                                         else:
353                                                 AddPopup(
354                                                         "SeriesPlugin:\n" + _("%d records renamed successfully") % (self.counter),
355                                                         MessageBox.TYPE_INFO,
356                                                         0,
357                                                         'SP_PopUp_ID_RenameFinished'
358                                                 )
359                                         self.data = []
360                                         self.counter = 0