cleanup imports, use already present self.parent to keep parent screen (instead of...
[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, NumberActionMap
8 from Components.ConfigList import ConfigList, ConfigListScreen
9 from Components.Label import Label
10 from enigma import eTimer, eServiceReference, eServiceCenter, iServiceInformation, eConsoleAppContainer
11 import os
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         skin = """
22         <screen name="TitleDescrInput" position="100,150" size="500,200" title="Name and Description Input">
23                 <widget name="config" position="10,10" size="480,120" />
24                 <ePixmap position="70,140" size="140,40" pixmap="skin_default/buttons/green.png" alphatest="on" />
25                 <widget name="oktext" position="70,140" size="140,40" valign="center" halign="center" zPosition="2" font="Regular;20" transparent="1" />
26                 <ePixmap position="290,140" size="140,40" pixmap="skin_default/buttons/red.png" alphatest="on" />
27                 <widget name="canceltext" position="290,140" size="140,40" valign="center" halign="center" zPosition="2" font="Regular;20" transparent="1" />
28         </screen>"""
29
30         def __init__(self, session, service, parent, args = 0):
31                 Screen.__init__(self, session, parent = parent)
32                 serviceHandler = eServiceCenter.getInstance()
33                 info = serviceHandler.info(service)
34                 path = service.getPath()
35                 if path.endswith(".ts") is True:
36                         path = path[:-3]
37                 self.path = path
38                 self.dir = '/'.join(path.split('/')[:-1]) + '/'
39                 self.file = self.baseName(path)
40                 self.name = info.getName(service)
41                 if self.file == self.baseName(self.name):
42                         self.title = ""
43                 else:
44                         self.title = self.name
45                 self.descr = info.getInfoString(service, iServiceInformation.sDescription)
46
47                 self["oktext"] = Label(_("OK"))
48                 self["canceltext"] = Label(_("Cancel"))
49
50                 self.input_file = ConfigText(default = self.file, fixed_size = False, visible_width = 42)
51                 self.input_title = ConfigText(default = self.title, fixed_size = False, visible_width = 42)
52                 self.input_descr = ConfigText(default = self.descr, fixed_size = False, visible_width = 42)
53                 tmp = config.movielist.videodirs.value
54                 if not self.dir in tmp:
55                         tmp.append(self.dir)
56                 self.input_dir = ConfigSelection(choices = tmp, default = self.dir)
57
58                 self["actions"] = NumberActionMap(["SetupActions"],
59                 {
60                         "ok": self.keySelectOrGo,
61                         "save": self.keyGo,
62                         "cancel": self.keyCancel,
63                 }, -2)
64
65                 self.locationEl = getConfigListEntry(_("Location"), self.input_dir)
66                 l = [
67                         getConfigListEntry(_("Filename"), self.input_file),
68                         getConfigListEntry(_("Title"), self.input_title),
69                         getConfigListEntry(_("Description"), self.input_descr),
70                         self.locationEl
71                 ]
72
73                 ConfigListScreen.__init__(self, l)
74
75         def pathSelected(self, res):
76                 if res is not None:
77                         videodirs = config.movielist.videodirs.value
78                         if videodirs != self.input_dir.choices:
79                                 self.input_dir.setChoices(videodirs, default=res)
80                         self.input_dir.value = res
81
82         def keySelectOrGo(self):
83                 cur = self["config"].getCurrent()
84                 if cur is self.locationEl:
85                         self.session.openWithCallback(
86                                 self.pathSelected,
87                                 MovieLocationBox,
88                                 _("Choose target folder"),
89                                 self.input_dir.value,
90                         )
91                 else:
92                         self.keyGo()
93
94         def keyGo(self):
95                 if self.input_title.value != self.title or self.input_descr.value != self.descr:
96                         self.setTitleDescr(self.path, self.input_title.value, self.input_descr.value)
97                 if self.input_file.value != self.file or self.input_dir.value != self.dir:
98                         self.maybeMoveMovieFiles(self.path, self.rejoinName(self.input_dir.value, self.input_file.value))
99                 else:
100                         self.exitDialog()
101
102         def keyCancel(self):
103                 self.close()
104
105         def setTitleDescr(self, file, title, descr):
106                 if os.path.exists(file + ".ts.meta"):
107                         metafile = open(file + ".ts.meta", "r")
108                         sid = metafile.readline()
109                         oldtitle = metafile.readline().rstrip()
110                         olddescr = metafile.readline().rstrip()
111                         rest = metafile.read()
112                         metafile.close()
113                         if not title and title != "":
114                                 title = oldtitle
115                         if not descr and descr != "":
116                                 descr = olddescr
117                         metafile = open(file + ".ts.meta", "w")
118                         metafile.write("%s%s\n%s\n%s" %(sid, title, descr, rest))
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", ".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                         pass
158
159         def baseName(self, str):
160                 name = str.split('/')[-1]
161                 if name.endswith(".ts") is True:
162                         return name[:-3]
163                 else:
164                         return name
165
166         def rejoinName(self, dir, name):
167                 name = name.strip()
168                 if name.endswith(".ts") is True:
169                         return dir + name[:-3]
170                 else:
171                         return dir + name
172
173 class MovieRetitleBackgroundMover:
174         def __init__(self):
175                 self.container = eConsoleAppContainer()
176                 self.container.appClosed.append(self.moveNextSuffBG)
177                 self.currid = 0;
178                 self.queue = []
179                 self.running = False
180                 self.messageQueue = []
181                 self.messageTimer = eTimer()
182                 self.messageTimer.callback.append(self.tryLaunchMessage)
183
184         def message(self, session, id, cb, txt):
185                 global global_message_block
186                 done = False
187                 if global_message_block and global_message_block == id:
188                         self.messageQueue = [(session, id, txt)] + self.messageQueue
189                 else:
190                         i = 0
191                         for ele in self.messageQueue:
192                                 if ele[1] == id:
193                                         self.messageQueue[i] = (session, id, txt)
194                                         done = True
195                                         break
196                                 i += 1
197                         if not done:
198                                 self.messageQueue.append((session, id, txt))
199                 self.tryLaunchMessage(callback = cb)
200
201         def tryLaunchMessage(self, dummy=0, callback = None):
202                 global global_message_block
203                 self.messageTimer.stop()
204                 if not self.messageQueue:
205                         if callback:
206                                 callback()
207                 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]):
208                         self.messageTimer.stop()
209                         session = self.messageQueue[0][0]
210                         id = self.messageQueue[0][1]
211                         mess = self.messageQueue[0][2]
212                         self.messageQueue = self.messageQueue[1:]
213                         if global_message_block == id:
214                                 closeprev = session.current_dialog
215                         else:
216                                 closeprev = None
217                         global_message_block = id
218                         try:
219                                 session.openWithCallback(lambda x: self.tryLaunchMessageCallback(callback, closeprev), MessageBox, mess, MessageBox.TYPE_INFO)
220                         except:
221                                 global_message_block = False
222                                 self.tryLaunchMessage()
223                 else:
224                         self.messageTimer.start(1500, True)
225                         if callback:
226                                 callback()
227
228         def tryLaunchMessageCallback(self, callback, closeprev):
229                 global global_message_block
230                 global_message_block = False
231                 if closeprev:
232                         closeprev.close(True)
233                 self.tryLaunchMessage(callback = callback)
234
235         def enqueue(self, cb, session, fr, to):
236                 self.currid += 1
237                 mess = _("The movie is moved in the background from %s to %s.") % (os.path.dirname(fr), os.path.dirname(to))
238                 self.message(session, self.currid, cb, mess)
239                 self.queue.append((session, self.currid, fr, to))
240                 if not self.running:
241                         self.running = True
242                         self.runNext()
243                         return True
244                 else:
245                         return False
246
247         def runNext(self):
248                 if not self.queue:
249                         self.running = False
250                 else:
251                         self.moveMovieFilesBackground(self.queue[0])
252
253         def runDone(self, retval):
254                 ele = self.queue[0]
255                 self.queue = self.queue[1:]
256                 self.runNext()
257
258         def moveMovieFilesBackground(self, ele):
259                 self.ele = ele
260                 self.sufflst = (".ts.meta", ".ts.cuts", ".ts.ap", ".eit", ".ts")
261                 self.sufflst2 = self.sufflst
262                 self.moveNextSuffBG(0)
263
264         def moveNextSuffBG(self, retval):
265                 if self.sufflst and not retval:
266                         fr = self.ele[2] + self.sufflst[0]
267                         to = self.ele[3] + self.sufflst[0]
268                         self.sufflst = self.sufflst[1:]
269                         print "Moving %s to %s" % (fr, to)
270                         if os.path.exists(fr):
271                                 self.container.execute("/bin/cp", "/bin/cp", fr, to)
272                         else:
273                                 self.moveNextSuffBG(0)
274                 elif retval:
275                         for suff in self.sufflst2:
276                                 if os.path.exists(self.ele[3] + suff) and os.path.exists(self.ele[2] + suff):
277                                         os.unlink(self.ele[3] + suff)
278                         mess = _("Failed to move the movie %s to %s in the background") % (self.ele[2], self.ele[3])
279                         self.message(self.ele[0], self.ele[1], None, mess)
280                         self.runDone(1)
281                 else:
282                         for suff in self.sufflst2:
283                                 if os.path.exists(self.ele[2] + suff) and os.path.exists(self.ele[3] + suff):
284                                         os.unlink(self.ele[2] + suff)
285                         mess = _("Successfully moved the movie %s") % (self.ele[2])
286                         self.message(self.ele[0], self.ele[1], None, mess)
287                         self.runDone(0)
288
289 global_background_mover = MovieRetitleBackgroundMover()
290
291 global_message_block = False
292