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