fix currentCursorSelectable for multi content lists
[enigma2.git] / lib / python / Plugins / Extensions / CutListEditor / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2
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
11 from Screens.InfoBarGenerics import InfoBarSeek, InfoBarCueSheetSupport
12
13 from Components.GUIComponent import GUIComponent
14
15 from enigma import eListboxPythonMultiContent, eListbox, gFont, iPlayableService
16
17 def CutListEntry(where, what):
18         res = [ (where, what) ]
19         w = where / 90
20         ms = w % 1000
21         s = (w / 1000) % 60
22         m = (w / 60000) % 60
23         h = w / 3600000
24         if what == 0:
25                 type = "IN"
26         elif what == 1:
27                 type = "OUT"
28         elif what == 2:
29                 type = "MARK"
30         res.append(MultiContentEntryText(size=(400, 20), text = "%dh:%02dm:%02ds:%03d" % (h, m, s, ms)))
31         res.append(MultiContentEntryText(pos=(400,0), size=(130, 20), text = type, flags = RT_HALIGN_RIGHT))
32
33         return res
34
35 class CutList(GUIComponent):
36         def __init__(self, list):
37                 GUIComponent.__init__(self)
38                 self.l = eListboxPythonMultiContent()
39                 self.setList(list)
40                 self.l.setFont(0, gFont("Regular", 20))
41                 self.onSelectionChanged = [ ]
42         
43         def getCurrent(self):
44                 return self.l.getCurrentSelection()
45         
46         def getCurrentIndex(self):
47                 return self.l.getCurrentSelectionIndex()
48         
49         def GUIcreate(self, parent):
50                 self.instance = eListbox(parent)
51                 self.instance.setContent(self.l)
52                 self.instance.setItemHeight(30)
53                 self.instance.selectionChanged.get().append(self.selectionChanged)
54
55         def selectionChanged(self):
56                 for x in self.onSelectionChanged:
57                         x()
58         
59         def GUIdelete(self):
60                 self.instance.selectionChanged.get().remove(self.selectionChanged)
61                 self.instance.setContent(None)
62                 self.instance = None
63         
64         def invalidateEntry(self, index):
65                 self.l.invalidateEntry(index)
66         
67         def setIndex(self, index, data):
68                 self.list[index] = data
69                 self.invalidateEntry(index)
70
71         def setList(self, list):
72                 self.list = list
73                 self.l.setList(self.list)
74         
75         def setSelection(self, index):
76                 if self.instance is not None:
77                         self.instance.moveSelectionTo(index)
78
79 class CutListEditor(Screen, InfoBarSeek, InfoBarCueSheetSupport):
80         skin = """
81                 <screen position="100,100" size="550,400" title="Test" >
82                         <widget name="Timeline" position="10,0" size="530,40" 
83                                 pointer="/usr/share/enigma2/position_pointer.png:3,5" />
84                         <widget name="Cutlist" position="10,50" size="530,200" />
85                 </screen>"""
86         def __init__(self, session, service):
87                 self.skin = CutListEditor.skin
88                 Screen.__init__(self, session)
89                 InfoBarSeek.__init__(self)
90                 InfoBarCueSheetSupport.__init__(self)
91                 session.nav.playService(service)
92                 
93                 service = session.nav.getCurrentService()
94                 cue = service and service.cueSheet()
95                 if cue is not None:
96                         # disable cutlists. we want to freely browse around in the movie
97                         print "cut lists disabled!"
98                         cue.setCutListEnable(0)
99                 
100                 self.downloadCuesheet()
101         
102                 self["Timeline"] = ServicePositionGauge(self.session.nav)
103                 self["Cutlist"] = CutList(self.getCutlist())
104                 self["Cutlist"].onSelectionChanged.append(self.selectionChanged)
105                 
106                 self["actions"] = HelpableActionMap(self, "CutListEditorActions",
107                         {
108                                 "setIn": (self.setIn, _("Make this mark an 'in' point")),
109                                 "setOut": (self.setOut, _("Make this mark an 'out' point")),
110                                 "setMark": (self.setMark, _("Make this mark just a mark")),
111                                 "addMark": (self.__addMark, _("Add a mark")),
112                                 "removeMark": (self.__removeMark, _("Remove a mark")),
113                                 "leave": (self.exit, _("Exit editor"))
114                         })
115                 
116                 self.tutorial_seen = False
117                 
118                 self.onExecBegin.append(self.showTutorial)
119                 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
120                         {
121                                 iPlayableService.evCuesheetChanged: self.refillList
122                         })
123
124                 # to track new entries we save the last version of the cutlist
125                 self.last_cuts = [ ]
126                 
127         def showTutorial(self):
128                 if not self.tutorial_seen:
129                         self.tutorial_seen = True
130                         self.session.open(MessageBox, 
131                                 """Welcome to the Cutlist editor. It has a *very* unintuitive handling:
132
133 You can add use the color keys to move around in the recorded movie. 
134 By pressing shift-yellow, you can add a mark or remove an existing one.
135 You can then assign them to be either 'in' or 'out' positions by selecting them in the list and pressing 1 or 2.
136                                 """, MessageBox.TYPE_INFO)
137         
138         def checkSkipShowHideLock(self):
139                 pass
140         
141         def setType(self, index, type):
142                 self.cut_list[index] = (self.cut_list[index][0], type)
143                 self["Cutlist"].setIndex(index, CutListEntry(*self.cut_list[index]))
144         
145         def setIn(self):
146                 m = self["Cutlist"].getCurrentIndex()
147                 self.setType(m, 0)
148                 self.uploadCuesheet()
149         
150         def setOut(self):
151                 m = self["Cutlist"].getCurrentIndex()
152                 self.setType(m, 1)
153                 self.uploadCuesheet()
154
155         def setMark(self):
156                 m = self["Cutlist"].getCurrentIndex()
157                 self.setType(m, 2)
158                 self.uploadCuesheet()
159         
160         def __addMark(self):
161                 self.toggleMark(onlyadd=True, tolerance=90000) # do not allow two marks in <1s
162         
163         def __removeMark(self):
164                 m = self["Cutlist"].getCurrent()
165                 m = m and m[0]
166                 if m is not None:
167                         self.removeMark(m)
168         
169         def exit(self):
170                 self.close()
171
172         def getCutlist(self):
173                 r = [ ]
174                 for e in self.cut_list:
175                         r.append(CutListEntry(*e))
176                 return r
177
178         def selectionChanged(self):
179                 where = self["Cutlist"].getCurrent()
180                 if where is None:
181                         print "no selection"
182                         return
183                 pts = where[0][0]
184                 seek = self.getSeek()
185                 if seek is None:
186                         print "no seek"
187                         return
188                 seek.seekTo(pts)
189
190         def refillList(self):
191                 print "cue sheet changed, refilling"
192                 self.downloadCuesheet()
193                 
194                 # get the first changed entry, and select it
195                 new_list = self.getCutlist()
196                 self["Cutlist"].setList(new_list)
197                 
198                 for i in range(min(len(new_list), len(self.last_cuts))):
199                         if new_list[i] != self.last_cuts[i]:
200                                 self["Cutlist"].setSelection(i)
201                                 break
202                 self.last_cuts = new_list
203
204 def main(session, service):
205         session.open(CutListEditor, service)
206
207 def Plugins():
208         return PluginDescriptor(name="Cutlist Editor", description=_("Cutlist editor..."), where = PluginDescriptor.WHERE_MOVIELIST, fnc=main)