added seekbar plugin
[enigma2-plugins.git] / seekbar / src / plugin.py
1 ##
2 ## Seekbar
3 ## by AliAbdul
4 ##
5 from Components.ActionMap import ActionMap
6 from Components.config import config, ConfigInteger, ConfigNumber, ConfigSelection, ConfigSubsection, ConfigYesNo, getConfigListEntry
7 from Components.ConfigList import ConfigListScreen
8 from Components.Label import Label
9 from Components.Language import language
10 from Components.Pixmap import MovingPixmap
11 from enigma import eTimer
12 from keyids import KEYIDS
13 from os import environ
14 from Screens.InfoBar import MoviePlayer
15 from Screens.Screen import Screen
16 from Tools.Directories import fileExists, resolveFilename, SCOPE_LANGUAGE, SCOPE_PLUGINS
17 from Tools.KeyBindings import addKeyBinding
18 import gettext, keymapparser
19
20 ##############################################
21
22 config.plugins.Seekbar = ConfigSubsection()
23 config.plugins.Seekbar.overwrite_left_right = ConfigYesNo(default=True)
24 config.plugins.Seekbar.sensibility = ConfigInteger(default=10, limits=(1, 10))
25
26 ##############################################
27
28 lang = language.getLanguage()
29 environ["LANGUAGE"] = lang[:2]
30 gettext.bindtextdomain("enigma2", resolveFilename(SCOPE_LANGUAGE))
31 gettext.textdomain("enigma2")
32 gettext.bindtextdomain("Seekbar", "%s%s" % (resolveFilename(SCOPE_PLUGINS), "Extensions/Seekbar/locale/"))
33
34 def _(txt):
35         t = gettext.dgettext("Seekbar", txt)
36         if t == txt:
37                 t = gettext.gettext(txt)
38         return t
39
40 ##############################################
41
42 class Seekbar(ConfigListScreen, Screen):
43         skin = """
44         <screen position="center,center" size="560,160" title="%s">
45                 <widget name="config" position="10,10" size="540,100" scrollbarMode="showOnDemand" />
46                 <widget name="cursor" position="0,125" size="8,18" pixmap="skin_default/position_arrow.png" alphatest="on" />\r
47                 <widget source="session.CurrentService" render="PositionGauge" position="145,140" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" foregroundColor="#20224f">
48                         <convert type="ServicePosition">Gauge</convert>
49                 </widget>
50                 <widget name="time" position="50,130" size="100,20" font="Regular;20" halign="left" backgroundColor="#4e5a74" transparent="1" />
51                 <widget source="session.CurrentService" render="Label" position="420,130" size="90,24" font="Regular;20" halign="right" backgroundColor="#4e5a74" transparent="1">
52                         <convert type="ServicePosition">Length</convert>
53                 </widget>
54         </screen>""" % _("Seek")
55
56         def __init__(self, session, instance, fwd):
57                 Screen.__init__(self, session)
58                 
59                 self.session = session
60                 self.infobarInstance = instance
61                 self.fwd = fwd
62                 if isinstance(session.current_dialog, MoviePlayer):
63                         self.dvd = False
64                 else:
65                         self.dvd = True
66                 self.percent = 0.0
67                 self.length = None
68                 service = session.nav.getCurrentService()
69                 if service:
70                         self.seek = service.seek()
71                         if self.seek:
72                                 self.length = self.seek.getLength()
73                                 position = self.seek.getPlayPosition()
74                                 if self.length and position:
75                                         if int(position[1]) > 0:
76                                                 self.percent = float(position[1]) * 100.0 / float(self.length[1])
77                 
78                 self.minuteInput = ConfigNumber(default=5)
79                 self.positionEntry = ConfigSelection(choices=["<>"], default="<>")
80                 if self.fwd:
81                         txt = _("Jump x minutes forward:")
82                 else:
83                         txt = _("Jump x minutes back:")
84                 ConfigListScreen.__init__(self, [
85                         getConfigListEntry(txt, self.minuteInput),
86                         getConfigListEntry(_("Go to position:"), self.positionEntry),
87                         getConfigListEntry(_("Sensibility:"), config.plugins.Seekbar.sensibility),
88                         getConfigListEntry(_("Overwrite left and right buttons:"), config.plugins.Seekbar.overwrite_left_right)])
89                 
90                 self["cursor"] = MovingPixmap()
91                 self["time"] = Label()
92                 
93                 self["actions"] = ActionMap(["WizardActions"], {"back": self.exit}, -1)
94                 
95                 self.cursorTimer = eTimer()
96                 self.cursorTimer.callback.append(self.updateCursor)
97                 self.cursorTimer.start(200, False)
98                 
99                 self.onLayoutFinish.append(self.firstStart)
100
101         def firstStart(self):
102                 self["config"].setCurrentIndex(1)
103
104         def updateCursor(self):
105                 if self.length:
106                         x = 145 + int(2.7 * self.percent)
107                         self["cursor"].moveTo(x, 125, 1)\r
108                         self["cursor"].startMoving()
109                         pts = int(float(self.length[1]) / 100.0 * self.percent)
110                         self["time"].setText("%d:%02d" % ((pts/60/90000), ((pts/90000)%60)))
111
112         def exit(self):
113                 self.cursorTimer.stop()
114                 ConfigListScreen.saveAll(self)
115                 self.close()
116
117         def keyOK(self):
118                 sel = self["config"].getCurrent()[1]
119                 if sel == self.positionEntry:
120                         if self.length:
121                                 if self.dvd: # seekTo() doesn't work for DVD Player
122                                         oldPosition = self.seek.getPlayPosition()[1]
123                                         newPosition = int(float(self.length[1]) / 100.0 * self.percent)
124                                         if newPosition > oldPosition:
125                                                 pts = newPosition - oldPosition
126                                         else:
127                                                 pts = -1*(oldPosition - newPosition)
128                                         DVDPlayer.doSeekRelative(self.infobarInstance, pts)
129                                 else:
130                                         self.seek.seekTo(int(float(self.length[1]) / 100.0 * self.percent))
131                                 self.exit()
132                 elif sel == self.minuteInput:
133                         pts = self.minuteInput.value * 60 * 90000
134                         if self.fwd == False:
135                                 pts = -1*pts
136                         if self.dvd:
137                                 DVDPlayer.doSeekRelative(self.infobarInstance, pts)
138                         else:
139                                 MoviePlayer.doSeekRelative(self.infobarInstance, pts)
140                         self.exit()
141
142         def keyLeft(self):
143                 sel = self["config"].getCurrent()[1]
144                 if sel == self.positionEntry:
145                         self.percent -= float(config.plugins.Seekbar.sensibility.value) / 10.0
146                         if self.percent < 0.0:
147                                 self.percent = 0.0
148                 else:
149                         ConfigListScreen.keyLeft(self)
150
151         def keyRight(self):
152                 sel = self["config"].getCurrent()[1]
153                 if sel == self.positionEntry:
154                         self.percent += float(config.plugins.Seekbar.sensibility.value) / 10.0
155                         if self.percent > 100.0:
156                                 self.percent = 100.0
157                 else:
158                         ConfigListScreen.keyRight(self)
159
160         def keyNumberGlobal(self, number):
161                 sel = self["config"].getCurrent()[1]
162                 if sel == self.positionEntry:
163                         self.percent = float(number) * 10.0
164                 else:
165                         ConfigListScreen.keyNumberGlobal(self, number)
166
167 ##############################################
168 # This hack overwrites the functions seekFwdManual and seekBackManual of the InfoBarSeek class (MoviePlayer and DVDPlayer)
169
170 def seekbar(instance, fwd=True):
171         if instance and instance.session:
172                 instance.session.open(Seekbar, instance, fwd)
173
174 def seekbarBack(instance):
175         seekbar(instance, False)
176
177 MoviePlayer.seekFwdManual = seekbar
178 MoviePlayer.seekBackManual = seekbarBack
179
180 dvdPlayer = "%s%s"%(resolveFilename(SCOPE_PLUGINS), "Extensions/DVDPlayer/plugin.py")
181 if fileExists(dvdPlayer) or fileExists("%sc"%dvdPlayer):
182         from Plugins.Extensions.DVDPlayer.plugin import DVDPlayer
183         DVDPlayer.seekFwdManual = seekbar
184         DVDPlayer.seekBackManual = seekbarBack
185
186 ##############################################
187 # This hack puts the functions seekFwdManual and seekBackManual to the maped keys to seekbarRight and seekbarLeft
188
189 DoBind = ActionMap.doBind
190 def doBind(instance):
191         if not instance.bound:
192                 for ctx in instance.contexts:
193                         if ctx == "InfobarSeekActions":
194                                 if instance.actions.has_key("seekFwdManual"):
195                                         instance.actions["seekbarRight"] = instance.actions["seekFwdManual"]
196                                 if instance.actions.has_key("seekBackManual"):
197                                         instance.actions["seekbarLeft"] = instance.actions["seekBackManual"]
198                         DoBind(instance)
199
200 if config.plugins.Seekbar.overwrite_left_right.value:
201         ActionMap.doBind = doBind
202
203 ##############################################
204 # This hack maps the keys left and right to seekbarRight and seekbarLeft in the InfobarSeekActions-context
205
206 KeymapError = keymapparser.KeymapError
207 ParseKeys = keymapparser.parseKeys
208 def parseKeys(context, filename, actionmap, device, keys):
209         if context == "InfobarSeekActions":
210                 if device == "generic":
211                         for x in keys.findall("key"):
212                                 get_attr = x.attrib.get
213                                 mapto = get_attr("mapto")
214                                 id = get_attr("id")
215                                 if id == "KEY_LEFT":
216                                         mapto = "seekbarLeft"
217                                 if id == "KEY_RIGHT":
218                                         mapto = "seekbarRight"
219                                 flags = get_attr("flags")
220                                 flag_ascii_to_id = lambda x: {'m':1,'b':2,'r':4,'l':8}[x]
221                                 flags = sum(map(flag_ascii_to_id, flags))
222                                 assert mapto, "%s: must specify mapto in context %s, id '%s'" % (filename, context, id)
223                                 assert id, "%s: must specify id in context %s, mapto '%s'" % (filename, context, mapto)
224                                 assert flags, "%s: must specify at least one flag in context %s, id '%s'" % (filename, context, id)
225                                 if len(id) == 1:
226                                         keyid = ord(id) | 0x8000
227                                 elif id[0] == '\\':
228                                         if id[1] == 'x':
229                                                 keyid = int(id[2:], 0x10) | 0x8000
230                                         elif id[1] == 'd':
231                                                 keyid = int(id[2:]) | 0x8000
232                                         else:
233                                                 raise KeymapError("key id '" + str(id) + "' is neither hex nor dec")
234                                 else:
235                                         try:
236                                                 keyid = KEYIDS[id]
237                                         except:
238                                                 raise KeymapError("key id '" + str(id) + "' is illegal")
239                                 actionmap.bindKey(filename, device, keyid, flags, context, mapto)
240                                 addKeyBinding(filename, keyid, context, mapto, flags)
241                 else:
242                         ParseKeys(context, filename, actionmap, device, keys)
243         else:
244                 ParseKeys(context, filename, actionmap, device, keys)
245
246 if config.plugins.Seekbar.overwrite_left_right.value:
247         keymapparser.parseKeys = parseKeys
248         keymapparser.removeKeymap(config.usage.keymap.value)
249         keymapparser.readKeymap(config.usage.keymap.value)
250
251 ##############################################
252
253 def Plugins(**kwargs):
254         return []