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