[EPGSearch] - include PluginDescriptor.WHERE_CHANNEL_SELECTION_RED for other plugins...
[enigma2-plugins.git] / dreammediathek / src / MoviePlayer.py
1 # -*- coding: UTF-8 -*-
2 from Screens.Screen import Screen
3 from Screens.ChoiceBox import ChoiceBox
4 from Screens.InfoBarGenerics import InfoBarNotifications
5 from Components.ActionMap import ActionMap
6 from Components.config import config, ConfigSelection, ConfigSubsection
7 from Components.ServiceEventTracker import ServiceEventTracker
8 from enigma import eTimer, iPlayableService
9
10 config.plugins.dreamMediathek = ConfigSubsection()
11 config.plugins.dreamMediathek.general = ConfigSubsection()
12 config.plugins.dreamMediathek.general.on_movie_stop = ConfigSelection(default = "ask", choices = [
13         ("ask", _("Ask user")), ("quit", _("Return to movie list")), ("playnext", _("Play next video")), ("playagain", _("Play video again")) ])
14 config.plugins.dreamMediathek.general.on_exit = ConfigSelection(default = "ask", choices = [
15         ("ask", _("Ask user")), ("quit", _("Return to movie list"))])
16
17
18 class dreamMediathekPlayer(Screen, InfoBarNotifications):
19         STATE_IDLE = 0
20         STATE_PLAYING = 1
21         STATE_PAUSED = 2
22         ENABLE_RESUME_SUPPORT = True
23         ALLOW_SUSPEND = True
24
25         skin = """<screen name="dreamMediathekPlayer" flags="wfNoBorder" position="0,380" size="720,160" title="dreamMediathekPlayer" backgroundColor="transparent">
26                 <ePixmap position="0,0" pixmap="skin_default/info-bg_mp.png" zPosition="-1" size="720,160" />
27                 <ePixmap position="29,40" pixmap="skin_default/screws_mp.png" size="665,104" alphatest="on" />
28                 <ePixmap position="48,70" pixmap="skin_default/icons/mp_buttons.png" size="108,13" alphatest="on" />
29                 <ePixmap pixmap="skin_default/icons/icon_event.png" position="207,78" size="15,10" alphatest="on" />
30                 <widget source="session.CurrentService" render="Label" position="230,73" size="360,40" font="Regular;20" backgroundColor="#263c59" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1">
31                         <convert type="ServiceName">Name</convert>
32                 </widget>
33                 <widget source="session.CurrentService" render="Label" position="580,73" size="90,24" font="Regular;20" halign="right" backgroundColor="#4e5a74" transparent="1">
34                         <convert type="ServicePosition">Length</convert>
35                 </widget>
36                 <widget source="session.CurrentService" render="Label" position="205,129" size="100,20" font="Regular;18" halign="center" valign="center" backgroundColor="#06224f" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1">
37                         <convert type="ServicePosition">Position</convert>
38                 </widget>
39                 <widget source="session.CurrentService" render="PositionGauge" position="300,133" size="270,10" zPosition="2" pointer="skin_default/position_pointer.png:540,0" transparent="1" foregroundColor="#20224f">
40                         <convert type="ServicePosition">Gauge</convert>
41                 </widget>
42                 <widget source="session.CurrentService" render="Label" position="576,129" size="100,20" font="Regular;18" halign="center" valign="center" backgroundColor="#06224f" shadowColor="#1d354c" shadowOffset="-1,-1" transparent="1">
43                         <convert type="ServicePosition">Remaining</convert>
44                 </widget>
45                 </screen>"""
46
47         def __init__(self, session, service, lastservice, infoCallback = None, nextCallback = None, prevCallback = None):
48                 Screen.__init__(self, session)
49                 InfoBarNotifications.__init__(self)
50                 self.session = session
51                 self.service = service
52                 self.infoCallback = infoCallback
53                 self.nextCallback = nextCallback
54                 self.prevCallback = prevCallback
55                 self.screen_timeout = 5000
56                 self.nextservice = None
57
58                 print "evEOF=%d" % iPlayableService.evEOF
59                 self.__event_tracker = ServiceEventTracker(screen = self, eventmap =
60                         {
61                                 iPlayableService.evSeekableStatusChanged: self.__seekableStatusChanged,
62                                 iPlayableService.evStart: self.__serviceStarted,
63                                 iPlayableService.evEOF: self.__evEOF,
64                         })
65                 
66                 self["actions"] = ActionMap(["OkCancelActions", "InfobarSeekActions", "MediaPlayerActions", "MovieSelectionActions"],
67                 {
68                                 "ok": self.ok,
69                                 "cancel": self.leavePlayer,
70                                 "stop": self.leavePlayer,
71                                 "playpauseService": self.playpauseService,
72                                 "seekFwd": self.playNextFile,
73                                 "seekBack": self.playPrevFile,
74                                 "showEventInfo": self.showVideoInfo,
75                         }, -2)
76
77
78                 self.lastservice = lastservice
79
80                 self.hidetimer = eTimer()
81                 self.hidetimer_conn = self.hidetimer.timeout.connect(self.ok)
82                 self.returning = False
83
84                 self.state = self.STATE_PLAYING
85                 self.lastseekstate = self.STATE_PLAYING
86
87                 self.onPlayStateChanged = [ ]
88                 self.__seekableStatusChanged()
89         
90                 self.play()
91                 self.onClose.append(self.__onClose)
92                 
93         def __onClose(self):
94                 self.session.nav.stopService()
95
96         def __evEOF(self):
97                 print "evEOF=%d" % iPlayableService.evEOF
98                 print "Event EOF"
99                 self.handleLeave(config.plugins.dreamMediathek.general.on_movie_stop.value)
100
101         def __setHideTimer(self):
102                 self.hidetimer.start(self.screen_timeout)
103
104         def showInfobar(self):
105                 self.show()
106                 if self.state == self.STATE_PLAYING:
107                         self.__setHideTimer()
108                 else:
109                         pass
110
111         def hideInfobar(self):
112                 self.hide()
113                 self.hidetimer.stop()
114
115         def ok(self):
116                 if self.shown:
117                         self.hideInfobar()
118                 else:
119                         self.showInfobar()
120
121         def showVideoInfo(self):
122                 if self.shown:
123                         self.hideInfobar()
124                 if self.infoCallback is not None:       
125                         self.infoCallback()
126
127
128         def playNextFile(self):
129                 print "playNextFile"
130                 if self.nextCallback() is not None:
131                         nextservice,error = self.nextCallback()
132                         print "nextservice--->",nextservice
133                         if nextservice is None:
134                                 self.handleLeave(config.plugins.dreamMediathek.general.on_movie_stop.value, error)
135                         else:
136                                 self.playService(nextservice)
137                                 self.showInfobar()
138
139         def playPrevFile(self):
140                 print "playPrevFile"
141                 if self.prevCallback() is not None:
142                         prevservice,error = self.prevCallback()
143                         if prevservice is None:
144                                 self.handleLeave(config.plugins.dreamMediathek.general.on_movie_stop.value, error)
145                         else:
146                                 self.playService(prevservice)
147                                 self.showInfobar()
148
149         def playagain(self):
150                 print "playagain"
151                 if self.state != self.STATE_IDLE:
152                         self.stopCurrent()
153                 self.play()
154         
155         def playService(self, newservice):
156                 if self.state != self.STATE_IDLE:
157                         self.stopCurrent()
158                 self.service = newservice
159                 self.play()
160
161         def play(self):
162                 if self.state == self.STATE_PAUSED:
163                         if self.shown:
164                                 self.__setHideTimer()   
165                 self.state = self.STATE_PLAYING
166                 self.session.nav.playService(self.service)
167                 if self.shown:
168                         self.__setHideTimer()
169
170         def stopCurrent(self):
171                 print "stopCurrent"
172                 self.session.nav.stopService()
173                 self.state = self.STATE_IDLE
174
175         def playpauseService(self):
176                 print "playpauseService"
177                 if self.state == self.STATE_PLAYING:
178                         self.pauseService()
179                 elif self.state == self.STATE_PAUSED:
180                         self.unPauseService()
181
182         def pauseService(self):
183                 print "pauseService"
184                 if self.state == self.STATE_PLAYING:
185                         self.setSeekState(self.STATE_PAUSED)
186                 
187         def unPauseService(self):
188                 print "unPauseService"
189                 if self.state == self.STATE_PAUSED:
190                         self.setSeekState(self.STATE_PLAYING)
191
192
193         def getSeek(self):
194                 service = self.session.nav.getCurrentService()
195                 if service is None:
196                         return None
197
198                 seek = service.seek()
199
200                 if seek is None or not seek.isCurrentlySeekable():
201                         return None
202
203                 return seek
204
205         def isSeekable(self):
206                 if self.getSeek() is None:
207                         return False
208                 return True
209
210         def __seekableStatusChanged(self):
211                 print "seekable status changed!"
212                 if not self.isSeekable():
213                         self.setSeekState(self.STATE_PLAYING)
214                 else:
215                         print "seekable"
216
217         def __serviceStarted(self):
218                 self.state = self.STATE_PLAYING
219                 self.__seekableStatusChanged()
220
221         def setSeekState(self, wantstate):
222                 print "setSeekState"
223                 if wantstate == self.STATE_PAUSED:
224                         print "trying to switch to Pause- state:",self.STATE_PAUSED
225                 elif wantstate == self.STATE_PLAYING:
226                         print "trying to switch to playing- state:",self.STATE_PLAYING
227                 service = self.session.nav.getCurrentService()
228                 if service is None:
229                         print "No Service found"
230                         return False
231                 pauseable = service.pause()
232                 if pauseable is None:
233                         print "not pauseable."
234                         self.state = self.STATE_PLAYING
235
236                 if pauseable is not None:
237                         print "service is pausable"
238                         if wantstate == self.STATE_PAUSED:
239                                 print "WANT TO PAUSE"
240                                 pauseable.pause()
241                                 self.state = self.STATE_PAUSED
242                                 if not self.shown:
243                                         self.hidetimer.stop()
244                                         self.show()
245                         elif wantstate == self.STATE_PLAYING:
246                                 print "WANT TO PLAY"
247                                 pauseable.unpause()
248                                 self.state = self.STATE_PLAYING
249                                 if self.shown:
250                                         self.__setHideTimer()
251
252                 for c in self.onPlayStateChanged:
253                         c(self.state)
254                 
255                 return True
256
257         def handleLeave(self, how, error = False):
258                 self.is_closing = True
259                 if how == "ask":
260                         list = (
261                                 (_("Yes"), "quit"),
262                                 (_("No, but play video again"), "playagain"),
263                                 (_("Yes, but play next video"), "playnext"),
264                                 (_("Yes, but play previous video"), "playprev"),
265                         )
266                         if error is False:
267                                 self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("Stop playing this movie?"), list = list)
268                         else:
269                                 self.session.openWithCallback(self.leavePlayerConfirmed, ChoiceBox, title=_("No playable video found! Stop playing this movie?"), list = list)
270                 else:
271                         self.leavePlayerConfirmed([True, how])
272
273         def leavePlayer(self):
274                 self.handleLeave(config.plugins.dreamMediathek.general.on_movie_stop.value)
275
276         def leavePlayerConfirmed(self, answer):
277                 answer = answer and answer[1]
278                 if answer == "quit":
279                         self.close()
280                 elif answer == "playnext":
281                         self.playNextFile()
282                 elif answer == "playprev":
283                         self.playPrevFile()
284                 elif answer == "playagain":
285                         self.playagain()
286                         
287         def doEofInternal(self, playing):
288                 if not self.execing:
289                         return
290                 if not playing :
291                         return
292                 self.handleLeave(config.usage.on_movie_eof.value)
293