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