Added swedish translation to emailclient plugin.
[enigma2-plugins.git] / vlcplayer / src / VlcPlayer.py
1 # -*- coding: ISO-8859-1 -*-
2 #===============================================================================
3 # VLC Player Plugin by A. Lätsch 2007
4 #                   modified by Volker Christian 2008
5 #
6 # This is free software; you can redistribute it and/or modify it under
7 # the terms of the GNU General Public License as published by the Free
8 # Software Foundation; either version 2, or (at your option) any later
9 # version.
10 #===============================================================================
11
12
13 from time import time
14
15 from enigma import iPlayableServicePtr
16 from enigma import iPlayableService
17 from enigma import iServiceInformation
18 from enigma import iSeekableService
19 from enigma import eServiceReference
20 from enigma import eServiceCenter
21 from enigma import eTimer
22 from Screens.Screen import Screen
23 from Screens.MessageBox import MessageBox
24 from Screens.MinuteInput import MinuteInput
25 from Screens.InfoBarGenerics import InfoBarNotifications, InfoBarAudioSelection
26 from Components.Sources.Source import Source
27 from Components.ServiceEventTracker import ServiceEventTracker
28 from Components.ActionMap import ActionMap
29 from Components.config import config
30
31
32 def isValidServiceId(id):
33         testSRef = eServiceReference(id, 0, "Just a TestReference")
34         info = eServiceCenter.getInstance().info(testSRef)
35         return info is not None
36
37 ENIGMA_SERVICEGS_ID = 0x1001
38 ENIGMA_SERVICETS_ID = 0x1002
39
40 ENIGMA_SERVICE_ID = 0
41
42 print "[VLC] Checking for buildin servicets ... ",
43 if isValidServiceId(ENIGMA_SERVICETS_ID):
44         print "yes"
45         ENIGMA_SERVICE_ID = ENIGMA_SERVICETS_ID
46         STOP_BEFORE_UNPAUSE = False
47 else:
48         print "no"
49         print "[VLC] Checking for existing and usable servicets.so ... ",
50         try:
51                 import servicets
52         except Exception, e:
53                 print e
54                 print "[VLC] Checking for usable gstreamer service ... ",
55                 if isValidServiceId(ENIGMA_SERVICEGS_ID):
56                         print "yes"
57                         ENIGMA_SERVICE_ID = ENIGMA_SERVICEGS_ID
58                         STOP_BEFORE_UNPAUSE = True
59                 else:
60                         print "no"
61                         print "[VLC] No valid VLC-Service found - VLC-streaming not supported"
62         else:
63                 print "yes"
64                 ENIGMA_SERVICE_ID = ENIGMA_SERVICETS_ID
65                 STOP_BEFORE_UNPAUSE = False
66
67 DEFAULT_VIDEO_PID = 0x44
68 DEFAULT_AUDIO_PID = 0x45
69
70
71 def isDvdUrl(url):
72         return url.startswith("dvd://") or url.startswith("dvdsimple://")
73
74
75 def splitDvdUrl(url):
76         pos = url.rfind("@", len(url)-8)
77         if pos > 0:
78                 track = url[pos+1:]
79                 url = url[0:pos]
80                 if track.find(":") >= 0:
81                         track, chapter = track.split(":")
82                 else:
83                         chapter = None
84         else:
85                 track, chapter = (None, None)
86         return (url, track, chapter)
87
88
89 class VlcService(Source, iPlayableServicePtr, iSeekableService):
90         refreshInterval = 3000
91
92         class Info(iServiceInformation):
93                 def __init__(self, name=""):
94                         self.name = name
95
96                 def getName(self):
97                         return self.name
98
99                 def getInfoObject(self, *args, **kwargs):
100                         return { }
101
102                 def getInfo(self, what):
103                         return -1
104
105                 def getInfoString(self, *args, **kwargs):
106                         return self.name
107
108                 def isPlayable(self):
109                         return True
110
111                 def getEvent(self, what):
112                         return None
113
114         def __init__(self, player):
115                 Source.__init__(self)
116                 self.__info = VlcService.Info()
117                 self.server = None
118                 self.service = self
119                 self.player = player
120                 self.lastrefresh = time()
121                 self.stats = None
122
123         def setName(self, name):
124                 i = name.rfind("/")
125                 if i >= 0:
126                         name = name[i+1:]
127                 i = name.rfind("\\")
128                 if i >= 0:
129                         name = name[i+1:]
130                 self.__info.name = name
131                 self.setChanged()
132
133         def setChanged(self):
134                 self.changed( (self.CHANGED_SPECIFIC, iPlayableService.evStart) )
135
136         def setServer(self, server):
137                 self.server = server
138
139         def __onRefresh(self):
140                 if self.server is None:
141                         self.stats = None
142                         return
143                 print "[VLC] refresh"
144                 try:
145                         self.stats = self.server.status()
146                         self.lastrefresh = time()
147                         if self.stats and self.stats.has_key("time"):
148                                 print "Time: ", self.stats["time"]
149                 except Exception, e:
150                         print e
151
152         def refresh(self):
153                 self.__onRefresh()
154
155         def info(self):
156                 return self.__info
157
158         # iSeekableService
159         def seek(self):
160                 return self
161
162         def getPlayPosition(self):
163                 if self.stats and self.stats.has_key("time"):
164                         pos = float(self.stats["time"])
165                         if self.player.state == VlcPlayer.STATE_PLAYING:
166                                 pos += time() - self.lastrefresh
167                         return (False, int(pos*90000))
168                 else:
169                         return (True, 0)
170
171         def getLength(self):
172                 if self.stats and self.stats.has_key("length"):
173                         return (False, int(self.stats["length"])*90000)
174                 else:
175                         return (True, 0)
176
177         # iPlayableService
178         def cueSheet(self): return None
179         def pause(self): return self.player
180         def audioTracks(self):
181                 return self.player.audioTracks()
182
183         def audioChannel(self): return None
184         def subServices(self): return None
185         def frontendInfo(self): return None
186         def timeshift(self): return None
187         def subtitle(self): return None
188         def audioDelay(self): return None
189         def rdsDecoder(self): return None
190         def stream(self): return None
191         def start(self):
192                 self.player.play()
193         def stop(self):
194                 self.player.stop()
195
196
197 class VlcPlayerSummary(Screen):
198         skin = """
199         <screen name="InfoBarMoviePlayerSummary" position="0,0" size="132,64">
200                 <widget source="session.CurrentService" render="Label" position="6,0" size="120,25" font="Regular;14" halign="center" valign="center" >
201                         <convert type="ServiceName">Name</convert>
202                 </widget>
203                 <widget source="session.CurrentService" render="Progress" position="16,27" size="100,5" borderWidth="1">
204                         <convert type="ServicePosition">Position</convert>
205                 </widget>
206                 <widget source="global.CurrentTime" render="Label" position="6,32" size="120,32" font="Regular;32" halign="center" valign="center">
207                         <convert type="ClockToText">Format:%H:%M</convert>
208                 </widget>
209                 <widget source="session.RecordState" render="FixedLabel" text=" " position="6,32" zPosition="1" size="120,32">
210                         <convert type="ConfigEntryTest">config.usage.blinking_display_clock_during_recording,True,CheckSourceBoolean</convert>
211                         <convert type="ConditionalShowHide">Blink</convert>
212                 </widget>
213         </screen>"""
214
215         def __init__(self, session, parent):
216                 Screen.__init__(self, session)
217                 self.skinName = "InfoBarMoviePlayerSummary"
218                 
219
220 class VlcPlayer(Screen, InfoBarNotifications, InfoBarAudioSelection):
221         screen_timeout = 5000
222
223         STATE_IDLE = 0
224         STATE_PLAYING = 1
225         STATE_PAUSED = 2
226
227         def __init__(self, session, server, currentList):
228                 Screen.__init__(self, session)
229                 InfoBarNotifications.__init__(self)
230                 InfoBarAudioSelection.__init__(self)
231                 self.server = server
232                 self.currentList = currentList
233                 self.skinName = "MoviePlayer"
234                 self.state = self.STATE_IDLE
235                 self.oldservice = self.session.screen["CurrentService"]
236                 self.oldNavService = self.session.nav.getCurrentlyPlayingServiceReference()
237                 self.session.nav.stopService()
238                 self.vlcservice = VlcService(self)
239                 self.session.screen["CurrentService"] = self.vlcservice
240                 self.hidetimer = eTimer()
241                 self.hidetimer.timeout.get().append(self.ok)
242                 self.onClose.append(self.__onClose)
243
244                 class VlcPlayerActionMap(ActionMap):
245                         def __init__(self, player, contexts = [ ], actions = { }, prio=0):
246                                 ActionMap.__init__(self, contexts, actions, prio)
247                                 self.player = player
248
249                         def action(self, contexts, action):
250                                 if action[:5] == "seek:":
251                                         time = int(action[5:])
252                                         self.player.seekRelative(time)
253                                         return 1
254                                 elif action[:8] == "seekdef:":
255                                         key = int(action[8:])
256                                         time = [-config.seek.selfdefined_13.value, False, config.seek.selfdefined_13.value,
257                                                         -config.seek.selfdefined_46.value, False, config.seek.selfdefined_46.value,
258                                                         -config.seek.selfdefined_79.value, False, config.seek.selfdefined_79.value][key-1]
259                                         self.player.seekRelative(time)
260                                         return 1
261                                 else:
262                                         return ActionMap.action(self, contexts, action)
263
264                 self["actions"] = VlcPlayerActionMap(self, ["OkCancelActions", "TvRadioActions", "InfobarSeekActions", "MediaPlayerActions"],
265                 {
266                                 "ok": self.ok,
267                                 "cancel": self.stop,
268                                 "keyTV": self.stop,
269                                 "pauseService": self.pause,
270                                 "unPauseService": self.play,
271                                 "play": self.play,
272                                 "seekFwd": self.seekFwd,
273                                 "seekBack": self.seekBack,
274                                 "seekFwdDown": self.seekFwd,
275                                 "seekBackDown": self.seekBack,
276                                 "seekFwdManual": self.seekManual,
277                                 "seekBackManual": self.seekManual,
278                                 "next": self.playNextFile,
279                                 "previous": self.playPrevFile
280                         }, -2)
281
282                 print "[VLC] evEOF=%d" % iPlayableService.evEOF
283                 self.__event_tracker = ServiceEventTracker(screen = self, eventmap =
284                         {
285                                 iPlayableService.evEOF: self.__evEOF,
286                                 iPlayableService.evSOF: self.__evSOF
287                         })
288
289         def createSummary(self):
290                 print "[VLC] createSummary"
291                 return VlcPlayerSummary
292
293         def __onClose(self):
294                 self.session.screen["CurrentService"] = self.oldservice
295                 self.session.nav.playService(self.oldNavService)
296
297         def __evEOF(self):
298                 print "[VLC] Event EOF"
299                 self.stop()
300
301         def __evSOF(self):
302                 print "[VLC] Event SOF"
303                 self.vlcservice.refresh()
304
305         def playfile(self, path, name):
306                 if self.state != self.STATE_IDLE:
307                         self.stopCurrent()
308                 self.filename = path
309                 self.vlcservice.setName(name)
310                 self.play()
311
312         def play(self):
313                 if self.state == self.STATE_PAUSED:
314                         self.unpause()
315                         return
316                 print "[VLC] setupStream: " + self.filename
317                 if ENIGMA_SERVICE_ID == 0:
318                         self.hide()
319                         self.session.open(
320                                         MessageBox, _("No valid Enigma-Service to play a VLC-Stream\nCheck your installation and try again!"), MessageBox.TYPE_ERROR
321                         )
322                         self.close()
323                         return
324                 try:
325                         url = self.server.playFile(self.filename, DEFAULT_VIDEO_PID, DEFAULT_AUDIO_PID)
326                         print "[VLC] url: " + url
327                 except Exception, e:
328                         self.hide()
329                         self.session.open(
330                                         MessageBox, _("Error with VLC server:\n%s" % e), MessageBox.TYPE_ERROR
331                         )
332                         self.close()
333                         return
334                 if url is not None:
335                         sref = eServiceReference(ENIGMA_SERVICE_ID, 0, url)
336                         print "sref valid=", sref.valid()
337                         sref.setData(0, DEFAULT_VIDEO_PID)
338                         sref.setData(1, DEFAULT_AUDIO_PID)
339                         self.session.nav.playService(sref)
340                         self.state = self.STATE_PLAYING
341                         if self.shown:
342                                 self.__setHideTimer()
343                         self.vlcservice.setServer(self.server)
344
345         def pause(self):
346                 print "[VLC] pause"
347                 if self.state == self.STATE_PLAYING:
348                         self.session.nav.pause(True)
349                         self.server.pause()
350                         self.state = self.STATE_PAUSED
351                         self.vlcservice.refresh()
352                         if not self.shown:
353                                 self.hidetimer.stop()
354                                 self.show()
355                 elif self.state == self.STATE_PAUSED:
356                         self.unpause()
357
358         def unpause(self):
359                 print "[VLC] unpause"
360                 try:
361                         self.server.seek("-2")
362                         self.server.unpause()
363                 except Exception, e:
364                         self.session.open(
365                                 MessageBox, _("Error with VLC server:\n%s" % e), MessageBox.TYPE_ERROR
366                         )
367                         self.stop()
368                         return
369                 if STOP_BEFORE_UNPAUSE:
370                         self.session.nav.stopService()
371                         sref = self.session.nav.getCurrentlyPlayingServiceReference()
372                         sref.setData(0, DEFAULT_VIDEO_PID)
373                         sref.setData(1, DEFAULT_AUDIO_PID)
374                         self.session.nav.playService(sref)
375                 else:
376                         self.session.nav.pause(False)
377                 self.state = self.STATE_PLAYING
378                 self.vlcservice.refresh()
379                 if self.shown:
380                         self.__setHideTimer()
381
382         def stopCurrent(self):
383                 print "[VLC] stopCurrent"
384                 self.session.nav.stopService()
385                 if self.state == self.STATE_IDLE:
386                         self.close()
387                         return
388                 try:
389                         self.server.stop()
390                         self.server.deleteCurrentTree()
391                 except Exception, e:
392                         self.session.open(
393                                 MessageBox, _("Error with VLC server:\n%s" % e), MessageBox.TYPE_ERROR
394                         )
395                 self.state = self.STATE_IDLE
396                 self.vlcservice.setServer(None)
397                 self.vlcservice.refresh()
398
399         def stop(self):
400                 print "[VLC] stop"
401                 self.stopCurrent()
402                 self.close()
403
404         def __setHideTimer(self):
405                 self.hidetimer.start(self.screen_timeout)
406
407         def showInfobar(self):
408                 self.vlcservice.refresh()
409                 self.show()
410                 if self.state == self.STATE_PLAYING:
411                         self.__setHideTimer()
412                 else:
413                         pass
414
415         def hideInfobar(self):
416                 self.hide()
417                 self.hidetimer.stop()
418
419         def ok(self):
420                 if self.shown:
421                         self.hideInfobar()
422                 else:
423                         self.showInfobar()
424
425         def playNextFile(self):
426                 print "[VLC] playNextFile"
427                 if isDvdUrl(self.filename):
428                         url, track, chapter = splitDvdUrl(self.filename)
429                         if track is None:
430                                 track = 1
431                         else:
432                                 track = int(track)
433                         if chapter is None:
434                                 chapter = 2
435                         else:
436                                 chapter = int(chapter) + 1
437                         url = "%s@%d:%d" % (url, track, chapter)
438                         self.playfile(url, "DVD")
439                         self.showInfobar()
440                 else:
441                         if self.currentList != None:
442                                 media, name = self.currentList.getNextFile()
443                                 if media is None:
444                                         self.session.open(
445                                                         MessageBox, _("No more files in this directory"), MessageBox.TYPE_INFO
446                                         )
447                                         self.close()
448                                 else:
449                                         self.playfile(media, name)
450                                         self.showInfobar()
451
452         def playPrevFile(self):
453                 print "[VLC] playPrevFile"
454                 if isDvdUrl(self.filename):
455                         url, track, chapter = splitDvdUrl(self.filename)
456                         if track is None:
457                                 track = 1
458                         else:
459                                 track = int(track)
460                         if chapter is not None and int(chapter) > 1:
461                                 chapter = int(chapter) - 1
462                         else:
463                                 chapter = 1
464                         url = "%s@%d:%d" % (url, track, chapter)
465                         self.playfile(url, "DVD")
466                         self.showInfobar()
467                 else:
468                         if self.currentList != None:
469                                 media, name = self.currentList.getPrevFile()
470                                 if media is None:
471                                         self.session.open(
472                                                         MessageBox, _("No previous file in this directory"), MessageBox.TYPE_INFO
473                                         )
474                                         self.close()
475                                 else:
476                                         self.playfile(media, name)
477                                         self.showInfobar()
478
479         def audioTracks(self):
480                 return self.session.nav.getCurrentService() and self.session.nav.getCurrentService().audioTracks();
481
482         def seekRelative(self, delta):
483                 """delta is seconds as integer number
484                 positive=forwards, negative=backwards"""
485                 if self.state != self.STATE_IDLE:
486                         if (delta >= 0):
487                                 self.server.seek("+" + str(delta))
488                         else:
489                                 self.server.seek(str(delta))
490                 self.showInfobar()
491
492         def seekFwd(self):
493                 if isDvdUrl(self.filename):
494                         url, track, chapter = splitDvdUrl(self.filename)
495                         if track is None:
496                                 track = 2
497                         else:
498                                 track = int(track) + 1
499                         url = "%s@%d" % (url, track)
500                         self.playfile(url, "DVD")
501                         self.showInfobar()
502                 else:
503                         self.seekRelative(600)
504
505         def seekBack(self):
506                 if isDvdUrl(self.filename):
507                         url, track, chapter = splitDvdUrl(self.filename)
508                         if track is not None and int(track) > 2:
509                                 track = int(track) - 1
510                                 url = "%s@%d" % (url, track)
511                         else:
512                                 track = 1
513                         self.playfile(url, "DVD")
514                         self.showInfobar()
515                 else:
516                         self.seekRelative(-600)
517
518         def seekToMinute(self, minutes):
519                 self.server.seek(str(int(minutes)*60))
520                 self.showInfobar()
521
522         def seekManual(self):
523                 self.session.openWithCallback(self.seekToMinute, MinuteInput)