[MerlinSkinThemes]
[enigma2-plugins.git] / movieretitle / src / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2 from Screens.Screen import Screen
3 from Screens.MessageBox import MessageBox
4 from Screens.LocationBox import MovieLocationBox
5 import Screens.Standby
6 from Components.config import config, ConfigText, ConfigSelection, getConfigListEntry
7 from Components.ActionMap import ActionMap
8 from Components.ConfigList import ConfigListScreen
9 from Components.Sources.StaticText import StaticText
10 from enigma import eTimer, eServiceCenter, iServiceInformation, eConsoleAppContainer
11 from os import path as os_path, rename as os_rename, unlink as os_unlink, fsync
12
13 def main(session, service, **kwargs):
14         session.open(MovieRetitle, service, session.current_dialog, **kwargs)
15
16 def Plugins(**kwargs):
17         return PluginDescriptor(name="MovieRetitle", description=_("change name..."), where = PluginDescriptor.WHERE_MOVIELIST, fnc=main)
18
19
20 class MovieRetitle(Screen, ConfigListScreen):
21         def __init__(self, session, service, parent, args = 0):
22                 Screen.__init__(self, session, parent = parent)
23                 self.skinName = [ "MovieRetitle", "Setup" ]
24
25                 serviceHandler = eServiceCenter.getInstance()
26                 info = serviceHandler.info(service)
27                 path = service.getPath()
28                 if path.endswith(".ts") is True:
29                         path = path[:-3]
30                 self.path = path
31                 self.dir = '/'.join(path.split('/')[:-1]) + '/'
32                 self.file = self.baseName(path)
33                 self.name = info.getName(service)
34                 if self.file == self.baseName(self.name):
35                         self.orig_title = ""
36                 else:
37                         self.orig_title = self.name
38                 self.descr = info.getInfoString(service, iServiceInformation.sDescription)
39
40                 self["key_green"] = StaticText(_("OK"))
41                 self["key_red"] = StaticText(_("Cancel"))
42
43                 self.input_file = ConfigText(default = self.file, fixed_size = False, visible_width = 70)
44                 self.input_title = ConfigText(default = self.orig_title, fixed_size = False, visible_width = 70)
45                 self.input_descr = ConfigText(default = self.descr, fixed_size = False, visible_width = 70)
46                 tmp = config.movielist.videodirs.value
47                 if not self.dir in tmp:
48                         tmp.append(self.dir)
49                 self.input_dir = ConfigSelection(choices = tmp, default = self.dir)
50
51                 self["actions"] = ActionMap(["SetupActions"],
52                 {
53                         "ok": self.keySelectOrGo,
54                         "save": self.keyGo,
55                         "cancel": self.keyCancel,
56                 }, -2)
57
58                 self.locationEl = getConfigListEntry(_("Location"), self.input_dir)
59                 l = [
60                         getConfigListEntry(_("Filename"), self.input_file),
61                         getConfigListEntry(_("Title"), self.input_title),
62                         getConfigListEntry(_("Description"), self.input_descr),
63                         self.locationEl
64                 ]
65
66                 ConfigListScreen.__init__(self, l, session = session)
67
68                 self.onLayoutFinish.append(self.setCustomTitle)
69                 
70         def setCustomTitle(self):
71                 self.setTitle(_("Name and Description Input"))
72
73         def pathSelected(self, res):
74                 if res is not None:
75                         videodirs = config.movielist.videodirs.value
76                         if videodirs != self.input_dir.choices:
77                                 self.input_dir.setChoices(videodirs, default=res)
78                         self.input_dir.value = res
79
80         def keySelectOrGo(self):
81                 cur = self["config"].getCurrent()
82                 if cur is self.locationEl:
83                         self.session.openWithCallback(
84                                 self.pathSelected,
85                                 MovieLocationBox,
86                                 _("Choose target folder"),
87                                 self.input_dir.value,
88                         )
89                 else:
90                         self.keyGo()
91
92         def keyGo(self):
93                 if self.input_title.value != self.orig_title or self.input_descr.value != self.descr:
94                         self.setTitleDescr(self.path, self.input_title.value, self.input_descr.value)
95                 if self.input_file.value != self.file or self.input_dir.value != self.dir:
96                         self.maybeMoveMovieFiles(self.path, self.rejoinName(self.input_dir.value, self.input_file.value))
97                 else:
98                         self.exitDialog()
99
100         def keyCancel(self):
101                 self.close()
102
103         def setTitleDescr(self, file, title, descr):
104                 if os_path.exists(file + ".ts.meta"):
105                         metafile = open(file + ".ts.meta", "r")
106                         sid = metafile.readline()
107                         oldtitle = metafile.readline().rstrip()
108                         olddescr = metafile.readline().rstrip()
109                         rest = metafile.read()
110                         metafile.close()
111                         if not title and title != "":
112                                 title = oldtitle
113                         if not descr and descr != "":
114                                 descr = olddescr
115                         metafile = open(file + ".ts.meta", "w")
116                         metafile.write("%s%s\n%s\n%s" %(sid, title, descr, rest))
117                         metafile.flush()
118                         fsync(metafile.fileno())
119                         metafile.close()
120
121         def maybeMoveMovieFiles(self, fr, to):
122                 if os_path.exists(to+".ts"):
123                         self.inter_fr = fr
124                         self.inter_to = to
125                         self.session.openWithCallback(self.confirmedReplace, MessageBox, _("Target file %s.ts already exist.\nDo you want to replace it?") % (to), MessageBox.TYPE_YESNO)
126                 elif os_path.isdir(os_path.dirname(to)):
127                         self.moveMovieFiles(fr, to)
128                 else:
129                         self.session.openWithCallback(self.exitDialog, MessageBox, _("The target directory is not found. The file is not renamed."), MessageBox.TYPE_ERROR)
130
131         def confirmedReplace(self, answer):
132                 if answer == True:
133                         self.moveMovieFiles(self.inter_fr, self.inter_to)
134
135         def moveMovieFiles(self, fr, to):
136                 try:
137                         os_rename(fr + ".ts", to + ".ts")
138                 except OSError:
139                         print "Moving in background"
140                         global_background_mover.enqueue(self.exitDialog, self.session, fr, to)
141                 else:
142                         print "Moving in foreground"
143                         for suff in (".ts.meta", ".ts.cuts", ".ts.ap", ".ts.sc", ".eit"):
144                                 if os_path.exists(fr + suff):
145                                         os_rename(fr + suff, to + suff)
146                         self.exitDialog()
147
148         def exitDialog(self, dummy=None):
149                 self.close()
150                 # This will try to get back to an updated movie list.
151                 # A proper way to do this should be provided in enigma2.
152                 try:
153                         parent = self.parent
154                         parent.csel.reloadList()
155                         parent.close()
156                 except AttributeError:
157                         try:
158                                 # when started from MovieSelection Quickbutton Plugin, MovieSelection is parent, not MovieContextMenu --> try again
159                                 self.parent.reloadList()
160                         except: pass
161
162         def baseName(self, str):
163                 name = str.split('/')[-1]
164                 if name.endswith(".ts") is True:
165                         return name[:-3]
166                 else:
167                         return name
168
169         def rejoinName(self, dir, name):
170                 name = name.strip()
171                 if name.endswith(".ts") is True:
172                         return dir + name[:-3]
173                 else:
174                         return dir + name
175
176 class MovieRetitleBackgroundMover:
177         def __init__(self):
178                 self.container = eConsoleAppContainer()
179                 self.appClosed_conn = self.container.appClosed.connect(self.moveNextSuffBG)
180                 self.currid = 0;
181                 self.queue = []
182                 self.running = False
183                 self.messageQueue = []
184                 self.messageTimer = eTimer()
185                 self.messageTimer_conn = self.messageTimer.timeout.connect(self.tryLaunchMessage)
186
187         def message(self, session, id, cb, txt):
188                 global global_message_block
189                 done = False
190                 if global_message_block and global_message_block == id:
191                         self.messageQueue = [(session, id, txt)] + self.messageQueue
192                 else:
193                         i = 0
194                         for ele in self.messageQueue:
195                                 if ele[1] == id:
196                                         self.messageQueue[i] = (session, id, txt)
197                                         done = True
198                                         break
199                                 i += 1
200                         if not done:
201                                 self.messageQueue.append((session, id, txt))
202                 self.tryLaunchMessage(callback = cb)
203
204         def tryLaunchMessage(self, dummy=0, callback = None):
205                 global global_message_block
206                 self.messageTimer.stop()
207                 if not self.messageQueue:
208                         if callback:
209                                 callback()
210                 elif not Screens.Standby.inStandby and self.messageQueue[0][0].in_exec and (not global_message_block or global_message_block == self.messageQueue[0][1]):
211                         self.messageTimer.stop()
212                         session = self.messageQueue[0][0]
213                         id = self.messageQueue[0][1]
214                         mess = self.messageQueue[0][2]
215                         self.messageQueue = self.messageQueue[1:]
216                         if global_message_block == id:
217                                 closeprev = session.current_dialog
218                         else:
219                                 closeprev = None
220                         global_message_block = id
221                         try:
222                                 session.openWithCallback(lambda x: self.tryLaunchMessageCallback(callback, closeprev), MessageBox, mess, MessageBox.TYPE_INFO)
223                         except:
224                                 global_message_block = False
225                                 self.tryLaunchMessage()
226                 else:
227                         self.messageTimer.start(1500, True)
228                         if callback:
229                                 callback()
230
231         def tryLaunchMessageCallback(self, callback, closeprev):
232                 global global_message_block
233                 global_message_block = False
234                 if closeprev:
235                         closeprev.close(True)
236                 self.tryLaunchMessage(callback = callback)
237
238         def enqueue(self, cb, session, fr, to):
239                 self.currid += 1
240                 mess = _("The movie is moved in the background from %s to %s.") % (os_path.dirname(fr), os_path.dirname(to))
241                 self.message(session, self.currid, cb, mess)
242                 self.queue.append((session, self.currid, fr, to))
243                 if not self.running:
244                         self.running = True
245                         self.runNext()
246                         return True
247                 else:
248                         return False
249
250         def runNext(self):
251                 if not self.queue:
252                         self.running = False
253                 else:
254                         self.moveMovieFilesBackground(self.queue[0])
255
256         def runDone(self, retval):
257                 ele = self.queue[0]
258                 self.queue = self.queue[1:]
259                 self.runNext()
260
261         def moveMovieFilesBackground(self, ele):
262                 self.ele = ele
263                 self.sufflst = (".ts.meta", ".ts.cuts", ".ts.ap", ".ts.sc", ".eit", ".ts")
264                 self.sufflst2 = self.sufflst
265                 self.moveNextSuffBG(0)
266
267         def moveNextSuffBG(self, retval):
268                 if self.sufflst and not retval:
269                         fr = self.ele[2] + self.sufflst[0]
270                         to = self.ele[3] + self.sufflst[0]
271                         self.sufflst = self.sufflst[1:]
272                         print "Moving %s to %s" % (fr, to)
273                         if os_path.exists(fr):
274                                 self.container.execute("/bin/cp", "/bin/cp", fr, to)
275                         else:
276                                 self.moveNextSuffBG(0)
277                 elif retval:
278                         for suff in self.sufflst2:
279                                 if os_path.exists(self.ele[3] + suff) and os_path.exists(self.ele[2] + suff):
280                                         os_unlink(self.ele[3] + suff)
281                         mess = _("Failed to move the movie %s to %s in the background") % (self.ele[2], self.ele[3])
282                         self.message(self.ele[0], self.ele[1], None, mess)
283                         self.runDone(1)
284                 else:
285                         for suff in self.sufflst2:
286                                 if os_path.exists(self.ele[2] + suff) and os_path.exists(self.ele[3] + suff):
287                                         os_unlink(self.ele[2] + suff)
288                         mess = _("Successfully moved the movie %s") % (self.ele[2])
289                         self.message(self.ele[0], self.ele[1], None, mess)
290                         self.runDone(0)
291
292 global_background_mover = MovieRetitleBackgroundMover()
293
294 global_message_block = False
295