initial version
[enigma2-plugins.git] / vlcplayer / src / VlcPlayer.py
1 from enigma import iPlayableServicePtr\r
2 import time\r
3 from Screens.Screen import Screen\r
4 from Screens.MessageBox import MessageBox\r
5 from Components.config import config\r
6 from enigma import eServiceReference\r
7 from Components.Sources.Source import Source\r
8 from Components.ServiceEventTracker import ServiceEventTracker\r
9 from enigma import iPlayableService\r
10 from enigma import eTimer\r
11 from Components.ActionMap import ActionMap\r
12 \r
13 from VlcControlTelnet import VlcControlTelnet\r
14 from VlcControlHttp import VlcControlHttp\r
15 \r
16 \r
17 class VlcService(Source, iPlayableServicePtr):\r
18         refreshInterval = 3000\r
19         \r
20         class Info:\r
21                 def __init__(self, name=""):\r
22                         self.name = name\r
23                 def getName(self):\r
24                         return self.name\r
25                 def getInfoObject(self, *args, **kwargs):\r
26                         return { }\r
27                 def getInfo(self, what):\r
28                         return -1\r
29                 def getInfoString(self, *args, **kwargs):\r
30                         return self.name\r
31                 def isPlayable(self):\r
32                         return True\r
33 \r
34         def __init__(self, player):\r
35                 Source.__init__(self)\r
36                 self.__info = VlcService.Info()\r
37                 self.vlccontrol = None\r
38                 self.service = self\r
39                 self.player = player\r
40                 self.lastrefresh = time.time()\r
41                 self.stats = None\r
42                 self.refreshTimer = eTimer()\r
43                 self.refreshTimer.timeout.get().append(self.__onRefresh)\r
44                 self.refreshTimer.start(self.refreshInterval)\r
45         \r
46         def setFilename(self, filename):\r
47                 i = filename.rfind("/")\r
48                 if i >= 0:\r
49                         filename = filename[i+1:]\r
50                 i = filename.rfind("\\")\r
51                 if i >= 0:\r
52                         filename = filename[i+1:]\r
53                 self.__info.name = filename\r
54                 self.changed( (self.CHANGED_SPECIFIC, iPlayableService.evStart) )\r
55         \r
56         def setControl(self, control):\r
57                 self.vlccontrol = control\r
58                 \r
59         def __onRefresh(self):\r
60                 if self.vlccontrol is None: \r
61                         self.stats = None\r
62                         return\r
63                 print "[VLC] refresh"\r
64                 self.lastrefresh = time.time()\r
65                 self.stats = self.vlccontrol.status()\r
66         \r
67         def refresh(self):\r
68                 self.__onRefresh()\r
69         \r
70         def info(self):\r
71                 return self.__info\r
72         \r
73         # iSeekableService\r
74         def seek(self):\r
75                 return self\r
76         def getPlayPosition(self):\r
77                 if self.stats and self.stats.has_key("time"):\r
78                         pos = float(self.stats["time"])\r
79                         if self.player.state == VlcPlayer.STATE_PLAYING:\r
80                                 pos += time.time() - self.lastrefresh\r
81                         return (False, int(pos*90000))\r
82                 else:\r
83                         return (True, 0)\r
84         \r
85         def getLength(self):\r
86                 if self.stats and self.stats.has_key("length"):\r
87                         return (False, int(self.stats["length"])*90000)\r
88                 else:\r
89                         return (True, 0)\r
90         \r
91         # iPlayableService\r
92         def cueSheet(self): return None\r
93         def pause(self): return self.player\r
94         def audioTracks(self): return None\r
95         def audioChannel(self): return None\r
96         def subServices(self): return None\r
97         def frontendInfo(self): return None\r
98         def timeshift(self): return None\r
99         def subtitle(self): return None\r
100         def audioDelay(self): return None\r
101         def rdsDecoder(self): return None\r
102         def stream(self): return None\r
103         def start(self):\r
104                 self.player.play()\r
105         def stop(self):\r
106                 self.player.stop()\r
107 \r
108 class VlcPlayer(Screen):\r
109         screen_timeout = 5000\r
110         \r
111         STATE_IDLE = 0\r
112         STATE_PLAYING = 1\r
113         STATE_PAUSED = 2\r
114         \r
115         def __init__(self, session):\r
116                 Screen.__init__(self, session)\r
117                 self.skinName = "MoviePlayer"\r
118                 self.state = self.STATE_IDLE\r
119                 self.url = None\r
120                 self.vlcservice = VlcService(self)\r
121                 self["CurrentService"] = self.vlcservice\r
122                 self.hidetimer = eTimer()\r
123                 self.hidetimer.timeout.get().append(self.ok)\r
124 \r
125                 class InfoBarSeekActionMap(ActionMap):\r
126                         def __init__(self, player, contexts = [ ], actions = { }, prio=0):\r
127                                 ActionMap.__init__(self, contexts, actions, prio)\r
128                                 self.player = player\r
129                                 \r
130                         def action(self, contexts, action):\r
131                                 if action[:5] == "seek:":\r
132                                         time = int(action[5:])\r
133                                         self.player.seekRelative(time)\r
134                                         return 1\r
135                                 else:\r
136                                         return ActionMap.action(self, contexts, action)\r
137                 \r
138                 self["actions"] = InfoBarSeekActionMap(self, ["OkCancelActions", "TvRadioActions", "InfobarSeekActions"],\r
139                 {\r
140                                 "ok": self.ok,\r
141                                 "cancel": self.cancel,\r
142                                 "keyTV": self.stop,\r
143                                 "pauseService": self.pause,\r
144                                 "unPauseService": self.play,\r
145                                 "seekFwd": self.seekFwd,\r
146                                 "seekBack": self.seekBack,\r
147                                 "seekFwdDown": self.seekFwd,\r
148                                 "seekBackDown": self.seekBack\r
149                         }, -2)\r
150 \r
151                 print "evEOF=%d" % iPlayableService.evEOF\r
152                 self.__event_tracker = ServiceEventTracker(screen=self, eventmap=\r
153                         {\r
154                                 iPlayableService.evEOF: self.__evEOF,\r
155 #                               iPlayableService.evSOF: self.__evSOF,\r
156                         })\r
157         \r
158         def __evEOF(self):\r
159                 print "[VLC] Event EOF"\r
160                 self.stop()\r
161         \r
162         def playfile(self, servernum, path):\r
163                 if self.state != self.STATE_IDLE:\r
164                         self.stop()\r
165 \r
166                 cfg = config.plugins.vlcplayer.servers[servernum]\r
167                 if cfg.method.value == "telnet":\r
168                         self.vlccontrol = VlcControlTelnet(servernum)\r
169                 else:\r
170                         self.vlccontrol = VlcControlHttp(servernum)\r
171                 self.vlcservice.setFilename(path)\r
172                 \r
173                 self.url = "http://%s:%d/%s.ts" % (cfg.host.value, cfg.httpport.value, self.vlccontrol.defaultStreamName)\r
174                 self.filename = path\r
175                 self.output = "#transcode{vcodec=%s,vb=%d,width=%s,height=%s,fps=%s,scale=%s,acodec=%s,ab=%d,channels=%d}:std{access=http,mux=ts,dst=/%s.ts}" % (\r
176                         config.plugins.vlcplayer.vcodec.value, \r
177                         config.plugins.vlcplayer.vb.value, \r
178                         config.plugins.vlcplayer.width.value, \r
179                         config.plugins.vlcplayer.height.value, \r
180                         config.plugins.vlcplayer.fps.value, \r
181                         config.plugins.vlcplayer.scale.value, \r
182                         config.plugins.vlcplayer.acodec.value, \r
183                         config.plugins.vlcplayer.ab.value, \r
184                         config.plugins.vlcplayer.channels.value,\r
185                         self.vlccontrol.defaultStreamName\r
186                 )\r
187                 self.play()\r
188 \r
189         def play(self):\r
190                 if self.state == self.STATE_PAUSED:\r
191                         self.unpause()\r
192                         return\r
193                 elif self.state == self.STATE_IDLE and self.url is not None:\r
194                         print "[VLC] setupStream: " + self.filename + " " + self.output\r
195                         try:\r
196                                 self.vlccontrol.playfile(self.filename, self.output)\r
197                         except Exception, e:\r
198                                 self.session.open(\r
199                                         MessageBox, _("Error with VLC server:\n%s" % e), MessageBox.TYPE_ERROR)\r
200                                 return\r
201                         self.session.nav.playService(eServiceReference(0x1001, 0, self.url))\r
202                         self.state = self.STATE_PLAYING\r
203                         if self.shown:\r
204                                 self.__setHideTimer()\r
205                 self.vlcservice.setControl(self.vlccontrol)\r
206                 self.vlcservice.refresh()\r
207 \r
208         def pause(self):\r
209                 print "[VLC] pause"\r
210                 if self.state == self.STATE_PLAYING:\r
211                         self.session.nav.pause(True)\r
212                         self.vlccontrol.pause()\r
213                         self.state = self.STATE_PAUSED\r
214                         self.vlcservice.refresh()\r
215                         if not self.shown:\r
216                                 self.hidetimer.stop()\r
217                                 self.show()\r
218                 elif self.state == self.STATE_PAUSED:\r
219                         self.unpause()\r
220 \r
221         def unpause(self):\r
222                 print "[VLC] unpause"\r
223                 try:\r
224                         self.vlccontrol.seek("-2")\r
225                         self.vlccontrol.play()\r
226                 except Exception, e:\r
227                         self.session.open(\r
228                                 MessageBox, _("Error with VLC server:\n%s" % e), MessageBox.TYPE_ERROR)\r
229                         self.stop()\r
230                         return\r
231                 self.session.nav.stopService()\r
232                 self.session.nav.playService(eServiceReference(0x1001, 0, self.url))\r
233                 self.state = self.STATE_PLAYING\r
234                 self.vlcservice.refresh()\r
235                 if self.shown:\r
236                         self.__setHideTimer()\r
237                 \r
238         def stop(self):\r
239                 print "[VLC] stop"\r
240                 self.session.nav.stopService()\r
241                 if self.state == self.STATE_IDLE:\r
242                         self.close()\r
243                         return\r
244                 if self.vlccontrol is not None:\r
245                         try:\r
246                                 self.vlccontrol.stop()\r
247                                 self.vlccontrol.delete()\r
248                         except Exception, e:\r
249                                 self.session.open(\r
250                                         MessageBox, _("Error with VLC server:\n%s" % e), MessageBox.TYPE_ERROR)\r
251                 self.state = self.STATE_IDLE\r
252                 self.vlcservice.setControl(None)\r
253                 self.vlcservice.refresh()\r
254                 self.show()\r
255 \r
256         def __setHideTimer(self):\r
257                 self.hidetimer.start(self.screen_timeout)\r
258 \r
259         def ok(self):\r
260                 if self.shown:\r
261                         self.hide()\r
262                         self.hidetimer.stop()\r
263                         self.vlcservice.refreshTimer.stop()\r
264                 else:\r
265                         self.vlcservice.refresh()\r
266                         self.show()\r
267                         if self.state == self.STATE_PLAYING:\r
268                                 self.__setHideTimer()\r
269                         else:\r
270                                 self.vlcservice.refreshTimer.start(self.vlcservice.refreshInterval)\r
271 \r
272         def cancel(self):\r
273                 self.stop()\r
274                 self.close()\r
275 \r
276         def seekRelative(self, delta):\r
277                 """delta is seconds as integer number\r
278                 positive=forwards, negative=backwards"""\r
279                 if self.state != self.STATE_IDLE:\r
280                         if (delta >= 0):\r
281                                 self.vlccontrol.seek("+"+str(delta))\r
282                         else:\r
283                                 self.vlccontrol.seek(str(delta))\r
284                 self.vlcservice.refresh()\r
285                 if not self.shown:\r
286                         self.show()\r
287                         self.__setHideTimer()\r
288 \r
289         def seekFwd(self):\r
290                 self.seekRelative(600)\r
291 \r
292         def seekBack(self):\r
293                 self.seekRelative(-600)\r