1 from Plugins.Plugin import PluginDescriptor
3 from Screens.Screen import Screen
4 from Screens.MessageBox import MessageBox
5 from Components.ServicePosition import ServicePositionGauge
6 from Components.ActionMap import HelpableActionMap
7 from Components.MenuList import MenuList
8 from Components.MultiContent import MultiContentEntryText, RT_HALIGN_RIGHT
9 from Components.ServiceEventTracker import ServiceEventTracker
10 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarCueSheetSupport
11 from Components.GUIComponent import GUIComponent
12 from enigma import eListboxPythonMultiContent, eListbox, gFont, iPlayableService
13 from Screens.FixedMenu import FixedMenu
16 def CutListEntry(where, what):
17 res = [ (where, what) ]
29 res.append(MultiContentEntryText(size=(400, 20), text = "%dh:%02dm:%02ds:%03d" % (h, m, s, ms)))
30 res.append(MultiContentEntryText(pos=(400,0), size=(130, 20), text = type, flags = RT_HALIGN_RIGHT))
34 class CutListContextMenu(FixedMenu):
45 def __init__(self, session, state, nearmark):
46 menu = [(_("back"), self.close), (None, )]
48 if state == self.SHOW_STARTCUT:
49 menu.append((_("start cut here"), self.startCut))
51 menu.append((_("start cut here"), ))
53 if state == self.SHOW_ENDCUT:
54 menu.append((_("end cut here"), self.endCut))
56 menu.append((_("end cut here"), ))
58 if state == self.SHOW_DELETECUT:
59 menu.append((_("delete cut"), self.deleteCut))
61 menu.append((_("delete cut"), ))
66 menu.append((_("insert mark here"), self.insertMark))
68 menu.append((_("remove this mark"), self.removeMark))
70 FixedMenu.__init__(self, session, _("Cut"), menu)
71 self.skinName = "Menu"
74 self.close(self.RET_STARTCUT)
77 self.close(self.RET_ENDCUT)
80 self.close(self.RET_DELETECUT)
83 self.close(self.RET_MARK)
86 self.close(self.RET_DELETEMARK)
88 class CutList(GUIComponent):
89 def __init__(self, list):
90 GUIComponent.__init__(self)
91 self.l = eListboxPythonMultiContent()
93 self.l.setFont(0, gFont("Regular", 20))
94 self.onSelectionChanged = [ ]
97 return self.l.getCurrentSelection()
99 def getCurrentIndex(self):
100 return self.l.getCurrentSelectionIndex()
102 def GUIcreate(self, parent):
103 self.instance = eListbox(parent)
104 self.instance.setContent(self.l)
105 self.instance.setItemHeight(30)
106 self.instance.selectionChanged.get().append(self.selectionChanged)
108 def selectionChanged(self):
109 for x in self.onSelectionChanged:
113 self.instance.selectionChanged.get().remove(self.selectionChanged)
114 self.instance.setContent(None)
117 def invalidateEntry(self, index):
118 self.l.invalidateEntry(index)
120 def setIndex(self, index, data):
121 self.list[index] = data
122 self.invalidateEntry(index)
124 def setList(self, list):
126 self.l.setList(self.list)
128 def setSelection(self, index):
129 if self.instance is not None:
130 self.instance.moveSelectionTo(index)
132 class CutListEditor(Screen, InfoBarSeek, InfoBarCueSheetSupport):
134 <screen position="100,100" size="550,400" title="Test" >
135 <widget name="Timeline" position="10,0" size="530,40"
136 pointer="/usr/share/enigma2/position_pointer.png:3,5" />
137 <widget name="Cutlist" position="10,50" size="530,300" scrollbarMode="showOnDemand" />
139 def __init__(self, session, service):
140 self.skin = CutListEditor.skin
141 Screen.__init__(self, session)
142 InfoBarSeek.__init__(self)
143 InfoBarCueSheetSupport.__init__(self)
144 session.nav.playService(service)
146 service = session.nav.getCurrentService()
147 cue = service and service.cueSheet()
149 # disable cutlists. we want to freely browse around in the movie
150 print "cut lists disabled!"
151 cue.setCutListEnable(0)
153 self.downloadCuesheet()
155 self["Timeline"] = ServicePositionGauge(self.session.nav)
156 self["Cutlist"] = CutList(self.getCutlist())
157 self["Cutlist"].onSelectionChanged.append(self.selectionChanged)
159 self["actions"] = HelpableActionMap(self, "CutListEditorActions",
161 "setIn": (self.setIn, _("Make this mark an 'in' point")),
162 "setOut": (self.setOut, _("Make this mark an 'out' point")),
163 "setMark": (self.setMark, _("Make this mark just a mark")),
164 "addMark": (self.__addMark, _("Add a mark")),
165 "removeMark": (self.__removeMark, _("Remove a mark")),
166 "leave": (self.exit, _("Exit editor")),
167 "showMenu": self.showMenu,
170 self.tutorial_seen = False
172 self.onExecBegin.append(self.showTutorial)
173 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
175 iPlayableService.evCuesheetChanged: self.refillList
178 # to track new entries we save the last version of the cutlist
181 self.cut_start = None
183 def showTutorial(self):
184 if not self.tutorial_seen:
185 self.tutorial_seen = True
186 self.session.open(MessageBox,
187 """Welcome to the Cutlist editor. It's still a bit strange to use, but anyway:
189 Seek to the start of the stuff you want to cut away. Press OK, select 'start cut'.
191 Then seek to the end, press OK, select 'end cut'. That's it.
192 """, MessageBox.TYPE_INFO)
194 def checkSkipShowHideLock(self):
197 def setType(self, index, type):
198 self.cut_list[index] = (self.cut_list[index][0], type)
199 self["Cutlist"].setIndex(index, CutListEntry(*self.cut_list[index]))
202 m = self["Cutlist"].getCurrentIndex()
204 self.uploadCuesheet()
207 m = self["Cutlist"].getCurrentIndex()
209 self.uploadCuesheet()
212 m = self["Cutlist"].getCurrentIndex()
214 self.uploadCuesheet()
217 self.toggleMark(onlyadd=True, tolerance=90000) # do not allow two marks in <1s
219 def __removeMark(self):
220 m = self["Cutlist"].getCurrent()
228 def getCutlist(self):
230 for e in self.cut_list:
231 r.append(CutListEntry(*e))
234 def selectionChanged(self):
235 where = self["Cutlist"].getCurrent()
240 seek = self.getSeek()
246 def refillList(self):
247 print "cue sheet changed, refilling"
248 self.downloadCuesheet()
250 # get the first changed entry, and select it
251 new_list = self.getCutlist()
252 self["Cutlist"].setList(new_list)
254 for i in range(min(len(new_list), len(self.last_cuts))):
255 if new_list[i] != self.last_cuts[i]:
256 self["Cutlist"].setSelection(i)
258 self.last_cuts = new_list
260 def getStateForPosition(self, pos):
262 for (where, what) in self.cut_list:
266 elif what == 1: # out
271 curpos = self.cueGetCurrentPosition()
275 self.setSeekState(self.SEEK_STATE_PAUSE)
277 self.context_position = curpos
279 self.context_nearest_mark = self.toggleMark(onlyreturn=True)
281 cur_state = self.getStateForPosition(curpos)
283 print "currently in 'IN'"
284 if self.cut_start is None or self.context_position < self.cut_start:
285 state = CutListContextMenu.SHOW_STARTCUT
287 state = CutListContextMenu.SHOW_ENDCUT
289 print "currently in 'OUT'"
290 state = CutListContextMenu.SHOW_DELETECUT
292 if self.context_nearest_mark is None:
297 self.session.openWithCallback(self.menuCallback, CutListContextMenu, state, nearmark)
299 def menuCallback(self, *result):
300 self.setSeekState(self.SEEK_STATE_PLAY)
305 if result == CutListContextMenu.RET_STARTCUT:
306 self.cut_start = self.context_position
307 elif result == CutListContextMenu.RET_ENDCUT:
308 # remove in/out marks between the new cut
309 for (where, what) in self.cut_list[:]:
310 if self.cut_start <= where <= self.context_position and what in [0,1]:
311 self.cut_list.remove((where, what))
313 bisect.insort(self.cut_list, (self.cut_start, 1))
314 bisect.insort(self.cut_list, (self.context_position, 0))
315 self.uploadCuesheet()
316 self.cut_start = None
317 elif result == CutListContextMenu.RET_DELETECUT:
321 for (where, what) in self.cut_list:
322 if what == 1 and where < self.context_position: # out
323 out_before = (where, what)
324 elif what == 0 and where < self.context_position: # in, before out
326 elif what == 0 and where > self.context_position and in_after is None:
327 in_after = (where, what)
329 if out_before is not None:
330 self.cut_list.remove(out_before)
332 if in_after is not None:
333 self.cut_list.remove(in_after)
334 self.uploadCuesheet()
335 elif result == CutListContextMenu.RET_MARK:
337 elif result == CutListContextMenu.RET_DELETEMARK:
338 self.cut_list.remove(self.context_nearest_mark)
339 self.uploadCuesheet()
341 def main(session, service):
342 session.open(CutListEditor, service)
345 return PluginDescriptor(name="Cutlist Editor", description=_("Cutlist editor..."), where = PluginDescriptor.WHERE_MOVIELIST, fnc=main)