label -> statictext,
[enigma2-plugins.git] / moviecut / src_py / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2 from Screens.Screen import Screen
3 from Screens.MessageBox import MessageBox
4 from Screens.ChoiceBox import ChoiceBox
5 from Screens.LocationBox import MovieLocationBox
6 import Screens.Standby
7 from Components.config import config, ConfigText, ConfigSelection, ConfigNothing, getConfigListEntry
8 from Components.ActionMap import ActionMap
9 from Components.ConfigList import ConfigList, ConfigListScreen
10 from Components.Sources.StaticText import StaticText
11 from enigma import eTimer, eServiceCenter, iServiceInformation, eConsoleAppContainer
12 from os import access, chmod, X_OK
13
14 mcut_path = "/usr/lib/enigma2/python/Plugins/Extensions/MovieCut/bin/mcut"
15 # Hack to make sure it is executable
16 if not access(mcut_path, X_OK):
17         chmod(mcut_path, 493)
18
19 def main(session, service, **kwargs):
20         session.open(MovieCut, service, **kwargs)
21
22 def Plugins(**kwargs):
23         return PluginDescriptor(name="MovieCut", description=_("Execute cuts..."), where = PluginDescriptor.WHERE_MOVIELIST, fnc=main)
24
25
26 class MovieCut(ChoiceBox):
27         def __init__(self, session, service):
28                 self.service = service
29                 serviceHandler = eServiceCenter.getInstance()
30                 path = self.service.getPath()
31                 info = serviceHandler.info(self.service)
32                 if not info:
33                         self.name = path
34                 else:
35                         self.name = info.getName(self.service)
36                 tlist = [
37                         (_("Don't cut"), "CALLFUNC", self.confirmed0),
38                         (_("Replace the original movie with the cut movie"), "CALLFUNC", self.confirmed1),
39                         (_("Place the cut movie in a new file ending with \" cut\""), "CALLFUNC", self.confirmed2),
40                         (_("Advanced cut specification..."), "CALLFUNC", self.confirmed3),
41                 ]
42                 ChoiceBox.__init__(self, session, _("How would you like to cut \"%s\"?") % (self.name), list = tlist, selection = 0)
43                 self.skinName = "ChoiceBox"
44
45         def confirmed0(self, arg):
46                 self.close()
47
48         def confirmed1(self, arg):
49                 MovieCutSpawn(self.session, self, [mcut_path, "-r", self.service.getPath()], self.name)
50
51         def confirmed2(self, arg):
52                 MovieCutSpawn(self.session, self, [mcut_path, self.service.getPath()], self.name)
53
54         def confirmed3(self, arg):
55                 serviceHandler = eServiceCenter.getInstance()
56                 info = serviceHandler.info(self.service)
57                 self.path = self.service.getPath()
58                 self.name = info.getName(self.service)
59                 self.descr = info.getInfoString(self.service, iServiceInformation.sDescription)
60                 self.session.openWithCallback(self.advcutConfirmed, AdvancedCutInput, self.name, self.path, self.descr)
61
62         def advcutConfirmed(self, ret):
63                 if len(ret) <= 1 or not ret[0]:
64                         self.close()
65                         return
66                 clist = [mcut_path]
67                 if ret[1] == True:
68                         clist.append("-r")
69                 clist.append(self.service.getPath())
70                 if ret[2] != False:
71                         clist += ["-o", ret[2]]
72                 if ret[3] != False:
73                         clist += ["-n", ret[3]]
74                 if ret[4] != False:
75                         clist += ["-d", ret[4]]
76                 if ret[5] != False:
77                         clist.append("-c")
78                         clist += ret[5]
79                 MovieCutSpawn(self.session, self, clist, self.name)
80                 
81 class AdvancedCutInput(Screen, ConfigListScreen):
82         skin = """
83         <screen name="AdvancedCutInput" position="center,center" size="560,300" title="Cut Parameter Input">
84                 <ePixmap position="0,0" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
85                 <ePixmap position="140,0" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
86                 <ePixmap position="280,0" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
87                 <ePixmap position="420,0" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
88                 <widget source="key_red" render="Label" position="0,0" size="140,40" valign="center" halign="center" zPosition="1" font="Regular;20" transparent="1" />
89                 <widget source="key_green" render="Label" position="140,0" size="140,40" valign="center" halign="center" zPosition="1" font="Regular;20" transparent="1" />
90                 <widget name="config" position="5,50" size="550,250" />
91         </screen>"""
92
93         def __init__(self, session, name, path, descr):
94                 Screen.__init__(self, session)
95
96                 self["key_green"] = StaticText(_("OK"))
97                 self["key_red"] = StaticText(_("Cancel"))
98
99                 if self.baseName(path) == self.baseName(name):
100                         self.title = ""
101                 else:
102                         self.title = name
103                 self.dir = self.dirName(path)
104                 self.file = self.baseName(path) + " cut"
105                 self.descr = descr
106                 self.input_replace = ConfigSelection(choices = [("no", _("No")), ("yes", _("Yes"))], default = "no")
107                 self.input_file = ConfigText(default = self.file, fixed_size = False, visible_width = 45)
108                 self.input_title = ConfigText(default = self.title, fixed_size = False, visible_width = 45)
109                 self.input_descr = ConfigText(default = self.descr, fixed_size = False, visible_width = 45)
110                 tmp = config.movielist.videodirs.value
111                 if not self.dir in tmp:
112                         tmp.append(self.dir)
113                 self.input_dir = ConfigSelection(choices = tmp, default = self.dir)
114                 self.input_manual = ConfigSelection(choices = [("no", _("Cutlist")), ("yes", _("Manual specification"))], default = "no")
115                 self.input_space = ConfigNothing()
116                 self.input_manualcuts = ConfigText(default = "", fixed_size = False)
117                 self.input_manualcuts.setUseableChars(" 0123456789:.")
118                 self["actions"] = ActionMap(["SetupActions"],
119                 {
120                         "ok": self.keySelectOrGo,
121                         "save": self.keyGo,
122                         "cancel": self.keyCancel,
123                 }, -2)
124
125                 self.list = []
126                 ConfigListScreen.__init__(self, self.list)
127                 self.entry_replace = getConfigListEntry(_("Replace original:"), self.input_replace)
128                 self.entry_file = getConfigListEntry(_("New filename:"), self.input_file)
129                 self.entry_title = getConfigListEntry(_("New title:"), self.input_title)
130                 self.entry_descr = getConfigListEntry(_("New description:"), self.input_descr)
131                 self.entry_dir = getConfigListEntry(_("New location:"), self.input_dir)
132                 self.entry_manual = getConfigListEntry(_("Cut source:"), self.input_manual)
133                 self.entry_space = getConfigListEntry(_("Cuts (an IN OUT IN OUT ... sequence of hour:min:sec)"), self.input_space)
134                 self.entry_manualcuts = getConfigListEntry(":", self.input_manualcuts)
135                 self.createSetup(self["config"])
136
137         def createSetup(self, configlist):
138                 list = [
139                         self.entry_replace
140                 ]
141                 if self.input_replace.value == "no":
142                         list.extend((
143                                 self.entry_file,
144                                 self.entry_dir,
145                         ))
146                 list.extend((
147                         self.entry_title,
148                         self.entry_descr,
149                         self.entry_manual,
150                 ))
151                 if self.input_manual.value == "yes":
152                         list.extend((
153                                 self.entry_space,
154                                 self.entry_manualcuts,
155                         ))
156                 self.list = list
157                 configlist.list = list
158                 configlist.l.setList(list)
159
160         def keyLeft(self):
161                 ConfigListScreen.keyLeft(self)
162                 cc = self["config"].getCurrent()
163                 if cc is self.entry_replace or cc is self.entry_manual:
164                         self.createSetup(self["config"])
165
166         def keyRight(self):
167                 ConfigListScreen.keyRight(self)
168                 cc = self["config"].getCurrent()
169                 if cc is self.entry_replace or cc is self.entry_manual:
170                         self.createSetup(self["config"])
171
172         def pathSelected(self, res):
173                 if res is not None:
174                         if config.movielist.videodirs.value != self.input_dir.choices:
175                                 self.input_dir.setChoices(config.movielist.videodirs.value, default=res)
176                         self.input_dir.value = res
177
178         def keySelectOrGo(self):
179                 if self["config"].getCurrent() == self.entry_dir:
180                         self.session.openWithCallback(
181                                 self.pathSelected,
182                                 MovieLocationBox,
183                                 _("Choose target folder"),
184                                 self.input_dir.value,
185                         )
186                 else:
187                         self.keyGo()
188
189         def keyGo(self):
190                 if self.input_replace.value == "yes":
191                         path = False
192                 else:
193                         path = self.rejoinName(self.input_dir.value, self.input_file.value)
194                 if self.input_manual.value == "no":
195                         cuts = False
196                 else:
197                         cuts = self.input_manualcuts.value.split(' ')
198                         while "" in cuts:
199                                 cuts.remove("")
200                 self.close((True, self.input_replace.value, path, self.input_title.value, self.input_descr.value, cuts))
201
202         def keyCancel(self):
203                 self.close((False,))
204
205         def baseName(self, str):
206                 name = str.split('/')[-1]
207                 if name.endswith(".ts") is True:
208                         return name[:-3]
209                 else:
210                         return name
211
212         def dirName(self, str):
213                 return '/'.join(str.split('/')[:-1]) + '/'
214
215         def rejoinName(self, dir, name):
216                 name = name.strip()
217                 if name.endswith(".ts") is True:
218                         return dir + name[:-3]
219                 else:
220                         return dir + name
221
222 class MovieCutQueue:
223         def __init__(self):
224                 self.container = eConsoleAppContainer()
225                 self.container.appClosed.append(self.runDone)
226                 self.queue = []
227                 self.running = False
228
229         def enqueue(self, cb, cmd):
230                 self.queue.append((cb, cmd))
231                 if not self.running:
232                         self.running = True
233                         self.runNext()
234                         return True
235                 else:
236                         return False
237
238         def runNext(self):
239                 if not self.queue:
240                         self.running = False
241                 else:
242                         self.container.execute(*self.queue[0][1])
243
244         def runDone(self, retval):
245                 cb = self.queue[0][0]
246                 self.queue = self.queue[1:]
247                 cb(retval)
248                 self.runNext()
249
250 global_mcut_errors = [_("The movie \"%s\" is successfully cut"),
251                       _("Cutting failed for movie \"%s\"")+":\n"+_("Bad arguments"),
252                       _("Cutting failed for movie \"%s\"")+":\n"+_("Couldn't open input .ts file"),
253                       _("Cutting failed for movie \"%s\"")+":\n"+_("Couldn't open input .cuts file"),
254                       _("Cutting failed for movie \"%s\"")+":\n"+_("Couldn't open input .ap file"),
255                       _("Cutting failed for movie \"%s\"")+":\n"+_("Couldn't open output .ts file"),
256                       _("Cutting failed for movie \"%s\"")+":\n"+_("Couldn't open output .cuts file"),
257                       _("Cutting failed for movie \"%s\"")+":\n"+_("Couldn't open output .ap file"),
258                       _("Cutting failed for movie \"%s\"")+":\n"+_("Empty .ap file"),
259                       _("Cutting failed for movie \"%s\"")+":\n"+_("No cuts specified"),
260                       _("Cutting failed for movie \"%s\"")+":\n"+_("Read/write error (disk full?)"),
261                       _("Cutting was aborted for movie \"%s\"")]
262
263 global_mcut_queue = MovieCutQueue()
264
265 global_mcut_block = False
266
267 class MovieCutSpawn:
268         def __init__(self, session, parent, clist, name):
269                 global global_mcut_queue
270                 global global_mcut_block
271                 self.session = session
272                 self.parent = parent
273                 self.name = name
274                 self.clist = [clist[0]] + clist
275                 self.mess = ""
276                 self.dialog = False
277                 self.waitTimer = eTimer()
278                 self.waitTimer.callback.append(self.doWaitAck)
279                 if global_mcut_queue.enqueue(self.doAck, self.clist):
280                         mess = _("The movie \"%s\" is cut in the background.") % (self.name)
281                 else:
282                         mess = _("Another movie is currently cut.\nThe movie \"%s\" will be cut in the background after it.") % (self.name)
283                 global_mcut_block = True
284                 self.dialog = self.session.openWithCallback(self.endc, MessageBox, mess, MessageBox.TYPE_INFO)
285
286         def doAck(self, retval):
287                 global global_mcut_errors
288 #               if WIFEXITED(retval):
289 #                       self.mess = global_mcut_errors[WEXITSTATUS(retval)] % (self.name)
290 #               else:
291 #                       self.mess = global_mcut_errors[-1] % (self.name)
292                 self.mess = global_mcut_errors[retval] % (self.name)
293                 self.doWaitAck()
294
295         def doWaitAck(self):
296                 global global_mcut_block
297                 if Screens.Standby.inStandby or not self.session.in_exec or (global_mcut_block and not self.dialog):
298                         self.waitTimer.start(2000, True)
299                 else:
300                         global_mcut_block = True
301                         self.session.openWithCallback(self.endw, MessageBox, self.mess, MessageBox.TYPE_INFO)
302
303         def endw(self, arg = 0):
304                 global global_mcut_block
305                 global_mcut_block = False
306                 if self.session.current_dialog == self.dialog:
307                         self.session.current_dialog.close(True)
308                         self.endc(arg)
309
310         def endc(self, arg = 0):
311                 global global_mcut_block
312                 global_mcut_block = False
313                 self.dialog = False
314                 self.parent.close()
315 #               self.session.current_dialog.close()