/
InfoBarSupport.py
336 lines (300 loc) · 11 KB
/
InfoBarSupport.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
#!/usr/bin/python
# encoding: utf-8
#
# Copyright (C) 2011 by betonme
#
# In case of reuse of this source code please do not remove this copyright.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For more information on the GNU General Public License see:
# <http://www.gnu.org/licenses/>.
#
import os
from Components.config import *
from Components.ActionMap import ActionMap, NumberActionMap, HelpableActionMap
from Components.Label import Label
from Components.Pixmap import Pixmap
from Components.ServiceEventTracker import ServiceEventTracker, InfoBarBase
from enigma import eTimer, iPlayableService, iServiceInformation, eServiceReference, iServiceKeys, getDesktop
from Screens.Screen import Screen
from Screens.InfoBarGenerics import *
from Screens.InfoBar import InfoBar
from Screens.MessageBox import MessageBox
from Screens.HelpMenu import HelpableScreen
from Tools.BoundFunction import boundFunction
from Tools.Directories import fileExists, resolveFilename, SCOPE_LANGUAGE, SCOPE_PLUGINS
from EnhancedMovieCenter import _
from EMCTasker import emcDebugOut
from DelayedFunction import DelayedFunction
from MovieCenter import sidDVD, sidDVB
SeekbarPlg = "%s%s"%(resolveFilename(SCOPE_PLUGINS), "Extensions/Seekbar/plugin.py")
try:
from boxbranding import getImageDistro
distro = getImageDistro()
if distro.lower() in ('openatv', 'openbh', 'openvix', 'openmips'):
hasmkvcuesheetsupport = True
else:
hasmkvcuesheetsupport = False
except:
hasmkvcuesheetsupport = False
try:
from enigma import eMediaDatabase
isDreamOS = True
except:
isDreamOS = False
# Overwrite Seekbar
def EMCkeyOK(self):
sel = self["config"].getCurrent()[1]
if sel == self.positionEntry:
if self.length:
# seekTo() doesn't work for DVD Player
oldPosition = self.seek.getPlayPosition()[1]
newPosition = int(float(self.length[1]) / 100.0 * self.percent)
if newPosition > oldPosition:
pts = newPosition - oldPosition
else:
pts = -1*(oldPosition - newPosition)
from EMCMediaCenter import EMCMediaCenter
EMCMediaCenter.doSeekRelative(self.infobarInstance, pts)
self.exit()
elif sel == self.minuteInput:
pts = self.minuteInput.value * 60 * 90000
if self.fwd == False:
pts = -1*pts
from EMCMediaCenter import EMCMediaCenter
EMCMediaCenter.doSeekRelative(self.infobarInstance, pts)
self.exit()
class InfoBarSupport( InfoBarBase, \
InfoBarNotifications, \
InfoBarSeek, \
InfoBarShowHide, \
InfoBarMenu, \
InfoBarShowMovies, \
InfoBarAudioSelection, \
InfoBarSimpleEventView, \
InfoBarServiceNotifications, \
InfoBarPVRState, \
InfoBarCueSheetSupport, \
InfoBarSubtitleSupport, \
InfoBarTeletextPlugin, \
InfoBarServiceErrorPopupSupport, \
InfoBarExtensions, \
InfoBarPlugins, \
InfoBarNumberZap, \
InfoBarPiP, \
InfoBarEPG ):
def __init__(self):
self.allowPiP = True # both are needed here !
self.allowPiPSwap = False # this is needed for vti-images
for x in InfoBarShowHide, InfoBarMenu, \
InfoBarBase, InfoBarSeek, InfoBarShowMovies, \
InfoBarAudioSelection, InfoBarSimpleEventView, \
InfoBarServiceNotifications, InfoBarPVRState, \
InfoBarSubtitleSupport, \
InfoBarTeletextPlugin, InfoBarServiceErrorPopupSupport, InfoBarExtensions, InfoBarNotifications, \
InfoBarPlugins, InfoBarNumberZap, \
InfoBarPiP, InfoBarEPG:
#InfoBarCueSheetSupport
#InfoBarMoviePlayerSummarySupport
x.__init__(self)
# Initialize InfoBarCueSheetSupport because we cannot override __serviceStarted
#def __init__(self, actionmap = "InfobarCueSheetActions"):
actionmap = "InfobarCueSheetActions"
self["CueSheetActions"] = HelpableActionMap(self, actionmap,
{
"jumpPreviousMark": (self.jumpPreviousMark, _("jump to previous marked position")),
"jumpNextMark": (self.jumpNextMark, _("jump to next marked position")),
"toggleMark": (self.toggleMark, _("toggle a cut mark at the current position"))
}, prio=1)
self.cut_list = [ ]
self.is_closing = False
self.resume_point = 0
if hasmkvcuesheetsupport:
self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
{
iPlayableService.evStart: self.__serviceStarted,
iPlayableService.evCuesheetChanged: self.downloadCuesheet,
})
else:
self.__event_tracker = ServiceEventTracker(screen=self, eventmap=
{
iPlayableService.evStart: self.__serviceStarted,
})
##############################################################################
## Override from InfoBarGenerics.py
# InfoBarCueSheetSupport
def __serviceStarted(self):
if self.is_closing:
return
print "new service started! trying to download cuts!"
self.downloadCuesheet()
# From Merlin2 InfoBarCueSheetSupport __serviceStarted
if config.usage.on_movie_start.value == "beginning" and config.EMC.movie_jump_first_mark.value == True:
self.jumpToFirstMark()
return
if self.ENABLE_RESUME_SUPPORT:
last = None
for (pts, what) in self.cut_list:
if what == self.CUT_TYPE_LAST:
last = pts
if last is not None:
self.resume_point = last
l = last / 90000
val = config.usage.on_movie_start.value
if val == "ask" or val == "ask yes":
Notifications.AddNotificationWithCallback(self.playLastCB, MessageBox, _("Do you want to resume this playback?") + "\n" + (_("Resume position at %s") % ("%d:%02d:%02d" % (l/3600, l%3600/60, l%60))), timeout=10, default=True)
elif val == "ask no":
Notifications.AddNotificationWithCallback(self.playLastCB, MessageBox, _("Do you want to resume this playback?") + "\n" + (_("Resume position at %s") % ("%d:%02d:%02d" % (l/3600, l%3600/60, l%60))), timeout=10, default=False)
elif val == "resume":
Notifications.AddNotificationWithCallback(self.playLastCB, MessageBox, _("Resuming playback"), timeout=2, type=MessageBox.TYPE_INFO)
elif config.EMC.movie_jump_first_mark.value == True:
self.jumpToFirstMark()
elif config.EMC.movie_jump_first_mark.value == True:
self.jumpToFirstMark()
def playLastCB(self, answer):
if answer == True:
self.doSeek(self.resume_point)
# From Merlin2
elif config.EMC.movie_jump_first_mark.value == True:
self.jumpToFirstMark()
elif self.service and self.service.type == sidDVD:
DelayedFunction(50, boundFunction(self.dvdPlayerWorkaround))
self.showAfterSeek()
def numberEntered(self, retval):
if retval and retval > 0 and retval != "":
self.zapToNumber(retval)
def zapToNumber(self, number):
if self.service:
seekable = self.getSeek()
if seekable:
seekable.seekChapter(number)
# From Merlin2
def jumpToFirstMark(self):
firstMark = None
current_pos = self.cueGetCurrentPosition() or 0
# Increase current_pos by 2 seconds to make sure we get the correct mark
current_pos = current_pos+180000
# EMC enhancement: increase recording margin to make sure we get the correct mark
margin = config.recording.margin_before.value*60*90000 *2 or 20*60*90000
middle = (self.getSeekLength() or 90*60*90000) / 2
for (pts, what) in self.cut_list:
if what == self.CUT_TYPE_MARK:
if pts != None and ( current_pos < pts and pts < margin and pts < middle ):
if firstMark == None or pts < firstMark:
firstMark = pts
if firstMark is not None:
self.start_point = firstMark
#== wait to seek - in OE2.5 not seek without wait
if isDreamOS:
DelayedFunction(500, self.doSeek, self.start_point)
else:
self.doSeek(self.start_point)
def jumpNextMark(self):
if not self.jumpPreviousNextMark(lambda x: x-90000):
# There is no further mark
self.doSeekEOF()
else:
if config.usage.show_infobar_on_skip.value:
# InfoBarSeek
self.showAfterSeek()
# InfoBarSeek
# Seekbar workaround
def seekFwdManual(self):
if fileExists("%so"%SeekbarPlg) or fileExists("%sc"%SeekbarPlg):
from Plugins.Extensions.Seekbar.plugin import Seekbar, seekbar
Seekbar.keyOK = EMCkeyOK
seekbar(self)
Seekbar.keyOK = Seekbar.keyOK
else:
# InfoBarSeek
InfoBarSeek.seekFwdManual(self)
# Seekbar workaround
def seekBackManual(self):
if fileExists("%so"%SeekbarPlg) or fileExists("%sc"%SeekbarPlg):
from Plugins.Extensions.Seekbar.plugin import Seekbar, seekbarBack
Seekbar.keyOK = EMCkeyOK
seekbarBack(self)
Seekbar.keyOK = Seekbar.keyOK
else:
# InfoBarSeek
InfoBarSeek.seekBackManual(self)
def doSeekRelative(self, pts):
if self.getSeekLength() < self.getSeekPlayPosition() + pts:
# Relative jump is behind the movie length
self.doSeekEOF()
else:
# Call baseclass function
InfoBarSeek.doSeekRelative(self, pts)
def doSeek(self, pts):
len = self.getSeekLength()
if len and len < pts:
# PTS is behind the movie length
self.doSeekEOF()
else:
# Call baseclass function
InfoBarSeek.doSeek(self, pts)
if self.service and self.service.type == sidDVD:
DelayedFunction(500, boundFunction(self.dvdPlayerWorkaround))
if pts and config.usage.show_infobar_on_skip.value:
# InfoBarSeek
self.showAfterSeek()
def dvdPlayerWorkaround(self):
self.pauseService()
self.unPauseService()
def getSeekPlayPosition(self):
try:
# InfoBarCueSheetSupport
return self.cueGetCurrentPosition() or 0
except Exception, e:
emcDebugOut("[EMCMC] getSeekPlayPosition exception:" + str(e))
return 0
def getSeekLength(self):
try:
# Call private InfoBarCueSheetSupport function
seek = InfoBarCueSheetSupport._InfoBarCueSheetSupport__getSeekable(self)
except Exception, e:
emcDebugOut("[EMCMC] getSeekLength exception:" + str(e))
if seek is None:
return None
len = seek.getLength()
return long(len[1])
# Handle EOF
def doSeekEOF(self):
# Stop one second before eof : 1 * 90 * 1000
state = self.seekstate
play = self.getSeekPlayPosition()
length = self.getSeekLength()
end = length and length - 2 * 90000
# Validate play and end values
if play and end and play < end and 0 < end:
# InfoBarSeek
InfoBarSeek.doSeek(self, end)
#TODO find a better solution
# If player is in pause mode do not call eof
if state != self.SEEK_STATE_PAUSE:
#try:
# #self.pvrStateDialog["state"].setText(self.SEEK_STATE_EOF[3])
# InfoBarPVRState._InfoBarPVRState__playStateChanged(self, self.SEEK_STATE_EOF)
#except:
# pass
#self.setSeekState(self.SEEK_STATE_EOF)
#self.unPauseService()
# Wait one second before signaling eof
# Call private InfoBarSeek function
#if hasattr(self, "seekstate"):
#InfoBarSeek._InfoBarSeek__evEOF(self)
# Use only 800ms because the player will run for max 1 seconds until eof
#DelayedFunction(800, boundFunction(InfoBarSeek._InfoBarSeek__evEOF, self))
##InfoBarSeek.doSeek(self, end)
#InfoBarSeek._InfoBarSeek__evEOF(self)
#if self.service.type != sidDVB:
InfoBarSeek._InfoBarSeek__evEOF(self)