mosaic/plugin.py

changeset 21
6bb708a2265f
child 22
61eb8a9b53a6
equal deleted inserted replaced
-1:000000000000 0:dd677fcad583
1 # -*- coding: UTF-8 -*-
2 # Mosaic by AliAbdul
3 from Components.ActionMap import NumberActionMap
4 from Components.config import config, ConfigSubsection, ConfigInteger
5 from Components.Console import Console
6 from Components.Label import Label
7 from Components.Language import language
8 from Components.Pixmap import Pixmap
9 from Components.VideoWindow import VideoWindow
10 from enigma import eServiceCenter, eServiceReference, eTimer, getDesktop, loadPNG
11 from os import environ
12 from Plugins.Plugin import PluginDescriptor
13 from Screens.ChannelSelection import BouquetSelector
14 from Screens.MessageBox import MessageBox
15 from Screens.Screen import Screen
16 from Tools.Directories import resolveFilename, SCOPE_SKIN_IMAGE, SCOPE_LANGUAGE, SCOPE_PLUGINS
17 from Tools.LoadPixmap import LoadPixmap
18 import gettext
19
20 ################################################
21
22 grab_binary = "/usr/bin/grab"
23 grab_picture = "/tmp/mosaic.jpg"
24 grab_errorlog = "/tmp/mosaic.log"
25
26 config_limits = (3, 30)
27 config.plugins.Mosaic = ConfigSubsection()
28 config.plugins.Mosaic.countdown = ConfigInteger(default=5, limits=config_limits)
29
30 playingIcon = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/ico_mp_play.png'))
31 pausedIcon = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, 'skin_default/icons/ico_mp_pause.png'))
32
33 ################################################
34
35 lang = language.getLanguage()
36 environ["LANGUAGE"] = lang[:2]
37 gettext.bindtextdomain("enigma2", resolveFilename(SCOPE_LANGUAGE))
38 gettext.textdomain("enigma2")
39 gettext.bindtextdomain("Mosaic", "%s%s" % (resolveFilename(SCOPE_PLUGINS), "Extensions/Mosaic/locale/"))
40
41 def _(txt):
42 t = gettext.dgettext("Mosaic", txt)
43 if t == txt:
44 t = gettext.gettext(txt)
45 return t
46
47 ################################################
48
49 class Mosaic(Screen):
50 PLAY = 0
51 PAUSE = 1
52
53 desktop = getDesktop(0)
54 size = desktop.size()
55 width = size.width()
56 height = size.height()
57 windowWidth = width / 4
58 windowHeight = height / 4
59
60 positions = []
61 x = 80
62 y = 50
63 for i in range(1, 10):
64 positions.append([x, y])
65 x += windowWidth
66 x += ((width - 160) - (windowWidth * 3)) / 2
67 if (i == 3) or (i == 6):
68 y = y + windowHeight + 20
69 x = 80
70
71 skin = ""
72 skin += """<screen position="0,0" size="%d,%d" title="Mosaic" flags="wfNoBorder" backgroundColor="#ffffff" >""" % (width, height)
73 skin += """<widget name="playState" position="55,55" size="16,16" alphatest="on" />"""
74 skin += """<eLabel position="%d,%d" size="%d,%d" />""" % (positions[0][0]-2, positions[0][1]-1, windowWidth, windowHeight)
75 skin += """<eLabel position="%d,%d" size="%d,%d" />""" % (positions[1][0]-2, positions[1][1]-1, windowWidth, windowHeight)
76 skin += """<eLabel position="%d,%d" size="%d,%d" />""" % (positions[2][0]-2, positions[2][1]-1, windowWidth, windowHeight)
77 skin += """<eLabel position="%d,%d" size="%d,%d" />""" % (positions[3][0]-2, positions[3][1]-1, windowWidth, windowHeight)
78 skin += """<eLabel position="%d,%d" size="%d,%d" />""" % (positions[4][0]-2, positions[4][1]-1, windowWidth, windowHeight)
79 skin += """<eLabel position="%d,%d" size="%d,%d" />""" % (positions[5][0]-2, positions[5][1]-1, windowWidth, windowHeight)
80 skin += """<eLabel position="%d,%d" size="%d,%d" />""" % (positions[6][0]-2, positions[6][1]-1, windowWidth, windowHeight)
81 skin += """<eLabel position="%d,%d" size="%d,%d" />""" % (positions[7][0]-2, positions[7][1]-1, windowWidth, windowHeight)
82 skin += """<eLabel position="%d,%d" size="%d,%d" />""" % (positions[8][0]-2, positions[8][1]-1, windowWidth, windowHeight)
83 skin += """<widget name="channel1" position="%d,%d" size="%d,20" font="Regular;18" backgroundColor="#ffffff" foregroundColor="#000000" />""" % (positions[0][0], positions[0][1]-18, windowWidth-4)
84 skin += """<widget name="channel2" position="%d,%d" size="%d,20" font="Regular;18" backgroundColor="#ffffff" foregroundColor="#000000" />""" % (positions[1][0], positions[1][1]-18, windowWidth-4)
85 skin += """<widget name="channel3" position="%d,%d" size="%d,20" font="Regular;18" backgroundColor="#ffffff" foregroundColor="#000000" />""" % (positions[2][0], positions[2][1]-18, windowWidth-4)
86 skin += """<widget name="channel4" position="%d,%d" size="%d,20" font="Regular;18" backgroundColor="#ffffff" foregroundColor="#000000" />""" % (positions[3][0], positions[3][1]-18, windowWidth-4)
87 skin += """<widget name="channel5" position="%d,%d" size="%d,20" font="Regular;18" backgroundColor="#ffffff" foregroundColor="#000000" />""" % (positions[4][0], positions[4][1]-18, windowWidth-4)
88 skin += """<widget name="channel6" position="%d,%d" size="%d,20" font="Regular;18" backgroundColor="#ffffff" foregroundColor="#000000" />""" % (positions[5][0], positions[5][1]-18, windowWidth-4)
89 skin += """<widget name="channel7" position="%d,%d" size="%d,20" font="Regular;18" backgroundColor="#ffffff" foregroundColor="#000000" />""" % (positions[6][0], positions[6][1]-18, windowWidth-4)
90 skin += """<widget name="channel8" position="%d,%d" size="%d,20" font="Regular;18" backgroundColor="#ffffff" foregroundColor="#000000" />""" % (positions[7][0], positions[7][1]-18, windowWidth-4)
91 skin += """<widget name="channel9" position="%d,%d" size="%d,20" font="Regular;18" backgroundColor="#ffffff" foregroundColor="#000000" />""" % (positions[8][0], positions[8][1]-18, windowWidth-4)
92 skin += """<widget name="window1" position="%d,%d" zPosition="1" size="%d,%d" />""" % (positions[0][0]-2, positions[0][1]-1, windowWidth, windowHeight)
93 skin += """<widget name="window2" position="%d,%d" zPosition="1" size="%d,%d" />""" % (positions[1][0]-2, positions[1][1]-1, windowWidth, windowHeight)
94 skin += """<widget name="window3" position="%d,%d" zPosition="1" size="%d,%d" />""" % (positions[2][0]-2, positions[2][1]-1, windowWidth, windowHeight)
95 skin += """<widget name="window4" position="%d,%d" zPosition="1" size="%d,%d" />""" % (positions[3][0]-2, positions[3][1]-1, windowWidth, windowHeight)
96 skin += """<widget name="window5" position="%d,%d" zPosition="1" size="%d,%d" />""" % (positions[4][0]-2, positions[4][1]-1, windowWidth, windowHeight)
97 skin += """<widget name="window6" position="%d,%d" zPosition="1" size="%d,%d" />""" % (positions[5][0]-2, positions[5][1]-1, windowWidth, windowHeight)
98 skin += """<widget name="window7" position="%d,%d" zPosition="1" size="%d,%d" />""" % (positions[6][0]-2, positions[6][1]-1, windowWidth, windowHeight)
99 skin += """<widget name="window8" position="%d,%d" zPosition="1" size="%d,%d" />""" % (positions[7][0]-2, positions[7][1]-1, windowWidth, windowHeight)
100 skin += """<widget name="window9" position="%d,%d" zPosition="1" size="%d,%d" />""" % (positions[8][0]-2, positions[8][1]-1, windowWidth, windowHeight)
101 skin += """<widget name="video1" position="%d,%d" zPosition="2" size="%d,%d" backgroundColor="#ffffffff" />""" % (positions[0][0]-2, positions[0][1]-1, windowWidth, windowHeight)
102 skin += """<widget name="video2" position="%d,%d" zPosition="2" size="%d,%d" backgroundColor="#ffffffff" />""" % (positions[1][0]-2, positions[1][1]-1, windowWidth, windowHeight)
103 skin += """<widget name="video3" position="%d,%d" zPosition="2" size="%d,%d" backgroundColor="#ffffffff" />""" % (positions[2][0]-2, positions[2][1]-1, windowWidth, windowHeight)
104 skin += """<widget name="video4" position="%d,%d" zPosition="2" size="%d,%d" backgroundColor="#ffffffff" />""" % (positions[3][0]-2, positions[3][1]-1, windowWidth, windowHeight)
105 skin += """<widget name="video5" position="%d,%d" zPosition="2" size="%d,%d" backgroundColor="#ffffffff" />""" % (positions[4][0]-2, positions[4][1]-1, windowWidth, windowHeight)
106 skin += """<widget name="video6" position="%d,%d" zPosition="2" size="%d,%d" backgroundColor="#ffffffff" />""" % (positions[5][0]-2, positions[5][1]-1, windowWidth, windowHeight)
107 skin += """<widget name="video7" position="%d,%d" zPosition="2" size="%d,%d" backgroundColor="#ffffffff" />""" % (positions[6][0]-2, positions[6][1]-1, windowWidth, windowHeight)
108 skin += """<widget name="video8" position="%d,%d" zPosition="2" size="%d,%d" backgroundColor="#ffffffff" />""" % (positions[7][0]-2, positions[7][1]-1, windowWidth, windowHeight)
109 skin += """<widget name="video9" position="%d,%d" zPosition="2" size="%d,%d" backgroundColor="#ffffffff" />""" % (positions[8][0]-2, positions[8][1]-1, windowWidth, windowHeight)
110 skin += """<widget name="event1" position="%d,%d" size="%d,20" zPosition="3" font="Regular;18" backgroundColor="#000000" foregroundColor="#ffffff" />""" % (positions[0][0]-2, positions[0][1]-1, windowWidth)
111 skin += """<widget name="event2" position="%d,%d" size="%d,20" zPosition="3" font="Regular;18" backgroundColor="#000000" foregroundColor="#ffffff" />""" % (positions[1][0]-2, positions[1][1]-1, windowWidth)
112 skin += """<widget name="event3" position="%d,%d" size="%d,20" zPosition="3" font="Regular;18" backgroundColor="#000000" foregroundColor="#ffffff" />""" % (positions[2][0]-2, positions[2][1]-1, windowWidth)
113 skin += """<widget name="event4" position="%d,%d" size="%d,20" zPosition="3" font="Regular;18" backgroundColor="#000000" foregroundColor="#ffffff" />""" % (positions[3][0]-2, positions[3][1]-1, windowWidth)
114 skin += """<widget name="event5" position="%d,%d" size="%d,20" zPosition="3" font="Regular;18" backgroundColor="#000000" foregroundColor="#ffffff" />""" % (positions[4][0]-2, positions[4][1]-1, windowWidth)
115 skin += """<widget name="event6" position="%d,%d" size="%d,20" zPosition="3" font="Regular;18" backgroundColor="#000000" foregroundColor="#ffffff" />""" % (positions[5][0]-2, positions[5][1]-1, windowWidth)
116 skin += """<widget name="event7" position="%d,%d" size="%d,20" zPosition="3" font="Regular;18" backgroundColor="#000000" foregroundColor="#ffffff" />""" % (positions[6][0]-2, positions[6][1]-1, windowWidth)
117 skin += """<widget name="event8" position="%d,%d" size="%d,20" zPosition="3" font="Regular;18" backgroundColor="#000000" foregroundColor="#ffffff" />""" % (positions[7][0]-2, positions[7][1]-1, windowWidth)
118 skin += """<widget name="event9" position="%d,%d" size="%d,20" zPosition="3" font="Regular;18" backgroundColor="#000000" foregroundColor="#ffffff" />""" % (positions[8][0]-2, positions[8][1]-1, windowWidth)
119
120 skin += """<widget name="countdown" position="80,%d" size="%d,20" font="Regular;18" backgroundColor="#ffffff" foregroundColor="#000000" />""" % (height-50, windowWidth)
121 skin += """<widget name="count" position="%d,%d" size="%d,20" font="Regular;18" backgroundColor="#ffffff" foregroundColor="#000000" halign="right" />
122 </screen>""" % (positions[2][0] ,height-50, windowWidth)
123
124 def __init__(self, session, services):
125 Screen.__init__(self, session)
126
127 self.session = session
128 self.oldService = self.session.nav.getCurrentlyPlayingServiceReference()
129 self.consoleCmd = ""
130 self.Console = Console()
131 self.serviceHandler = eServiceCenter.getInstance()
132 self.ref_list = services
133 self.window_refs = [None, None, None, None, None, None, None, None, None]
134 self.current_refidx = 0
135 self.current_window = 1
136 self.countdown = config.plugins.Mosaic.countdown.value
137 self.working = False
138 self.state = self.PLAY
139
140 self["playState"] = Pixmap()
141 for i in range(1, 10):
142 self["window" + str(i)] = Pixmap()
143 self["video" + str(i)] = VideoWindow(decoder=0, fb_width=self.width, fb_height=self.height)
144 self["video" + str(i)].hide()
145 self["channel" + str(i)] = Label("")
146 self["event" + str(i)] = Label("")
147 self["event" + str(i)].hide()
148 self["video1"].decoder = 0
149 self["video1"].show()
150 self["countdown"] = Label()
151 self.updateCountdownLabel()
152 self["count"] = Label()
153
154 self["actions"] = NumberActionMap(["MosaicActions"],
155 {
156 "ok": self.exit,
157 "cancel": self.closeWithOldService,
158 "green": self.play,
159 "yellow": self.pause,
160 "channelup": self.countdownPlus,
161 "channeldown": self.countdownMinus,
162 "1": self.numberPressed,
163 "2": self.numberPressed,
164 "3": self.numberPressed,
165 "4": self.numberPressed,
166 "5": self.numberPressed,
167 "6": self.numberPressed,
168 "7": self.numberPressed,
169 "8": self.numberPressed,
170 "9": self.numberPressed
171 }, prio=-1)
172
173 self.updateTimer = eTimer()
174 self.updateTimer.callback.append(self.updateCountdown)
175 self.checkTimer = eTimer()
176 self.checkTimer.callback.append(self.checkGrab)
177 self.checkTimer.start(500, 1)
178
179 def checkGrab(self):
180 # Start the first service in the bouquet and show the service-name
181 ref = self.ref_list[0]
182 self.window_refs[0] = ref
183 info = self.serviceHandler.info(ref)
184 name = info.getName(ref).replace('\xc2\x86', '').replace('\xc2\x87', '')
185 event_name = self.getEventName(info, ref)
186 self["channel1"].setText(name)
187 self["event1"].setText(event_name)
188 self.session.nav.playService(ref)
189 self["count"].setText(_("Channel: ") + "1 / " + str(len(self.ref_list)))
190 self["playState"].instance.setPixmap(playingIcon)
191 # Start updating the video-screenshots
192 self.updateTimer.start(1, 1)
193
194 def exit(self, callback=None):
195 self.deleteConsoleCallbacks()
196 self.close()
197
198 def deleteConsoleCallbacks(self):
199 if self.Console.appContainers.has_key(self.consoleCmd):
200 del self.Console.appContainers[self.consoleCmd].dataAvail[:]
201 del self.Console.appContainers[self.consoleCmd].appClosed[:]
202 del self.Console.appContainers[self.consoleCmd]
203 del self.Console.extra_args[self.consoleCmd]
204 del self.Console.callbacks[self.consoleCmd]
205
206 def closeWithOldService(self):
207 self.session.nav.playService(self.oldService)
208 self.deleteConsoleCallbacks()
209 self.close()
210
211 def numberPressed(self, number):
212 ref = self.window_refs[number-1]
213 if ref is not None:
214 self.session.nav.playService(ref)
215 self.deleteConsoleCallbacks()
216 self.close()
217
218 def play(self):
219 if self.working == False and self.state == self.PAUSE:
220 self.state = self.PLAY
221 self.updateTimer.start(1000, 1)
222 self["playState"].instance.setPixmap(playingIcon)
223
224 def pause(self):
225 if self.working == False and self.state == self.PLAY:
226 self.state = self.PAUSE
227 self.updateTimer.stop()
228 self["playState"].instance.setPixmap(pausedIcon)
229
230 def countdownPlus(self):
231 self.changeCountdown(1)
232
233 def countdownMinus(self):
234 self.changeCountdown(-1)
235
236 def changeCountdown(self, direction):
237 if self.working == False:
238 configNow = config.plugins.Mosaic.countdown.value
239 configNow += direction
240
241 if configNow < config_limits[0]:
242 configNow = config_limits[0]
243 elif configNow > config_limits[1]:
244 configNow = config_limits[1]
245
246 config.plugins.Mosaic.countdown.value = configNow
247 config.plugins.Mosaic.countdown.save()
248
249 self.updateCountdownLabel()
250
251 def makeNextScreenshot(self):
252 # Grab video
253 if not self.Console:
254 self.Console = Console()
255 self.consoleCmd = "%s -v -r %d -l -j 100 %s" % (grab_binary, self.windowWidth, grab_picture)
256 self.Console.ePopen(self.consoleCmd, self.showNextScreenshot)
257
258 def showNextScreenshot(self, result, retval, extra_args):
259 if retval == 0:
260 # Show screenshot in the current window
261 pic = LoadPixmap(grab_picture)
262 self["window" + str(self.current_window)].instance.setPixmap(pic)
263
264 # Hide current video-window and show the running event-name
265 self["video" + str(self.current_window)].hide()
266 self["event" + str(self.current_window)].show()
267
268 # Get next ref
269 self.current_refidx += 1
270 if self.current_refidx > (len(self.ref_list) -1):
271 self.current_refidx = 0
272
273 # Play next ref
274 ref = self.ref_list[self.current_refidx]
275 info = self.serviceHandler.info(ref)
276 name = info.getName(ref).replace('\xc2\x86', '').replace('\xc2\x87', '')
277 event_name = self.getEventName(info, ref)
278 self.session.nav.playService(ref)
279
280 # Get next window index
281 self.current_window += 1
282 if self.current_window > 9:
283 self.current_window = 1
284
285 # Save the ref
286 self.window_refs[self.current_window-1] = ref
287
288 # Save the event-name and hide the label
289 self["event" + str(self.current_window)].hide()
290 self["event" + str(self.current_window)].setText(event_name)
291
292 # Show the new video-window
293 self["video" + str(self.current_window)].show()
294 self["video" + str(self.current_window)].decoder = 0
295
296 # Show the servicename
297 self["channel" + str(self.current_window)].setText(name)
298 self["count"].setText(_("Channel: ") + str(self.current_refidx + 1) + " / " + str(len(self.ref_list)))
299
300 # Restart timer
301 self.working = False
302 self.updateTimer.start(1, 1)
303 else:
304 print "[Mosaic] retval: %d result: %s" % (retval, result)
305
306 try:
307 f = open(grab_errorlog, "w")
308 f.write("retval: %d\nresult: %s" % (retval, result))
309 f.close()
310 except:
311 pass
312
313 self.session.openWithCallback(self.exit, MessageBox, _("Error while creating screenshot. You need grab version 0.8 or higher!"), MessageBox.TYPE_ERROR, timeout=5)
314
315 def updateCountdown(self, callback=None):
316 self.countdown -= 1
317 self.updateCountdownLabel()
318 if self.countdown == 0:
319 self.countdown = config.plugins.Mosaic.countdown.value
320 self.working = True
321 self.makeNextScreenshot()
322 else:
323 self.updateTimer.start(1000, 1)
324
325 def updateCountdownLabel(self):
326 self["countdown"].setText("%s %s / %s" % (_("Countdown:"), str(self.countdown), str(config.plugins.Mosaic.countdown.value)))
327
328 def getEventName(self, info, ref):
329 event = info.getEvent(ref)
330 if event is not None:
331 eventName = event.getEventName()
332 if eventName is None:
333 eventName = ""
334 else:
335 eventName = ""
336 return eventName
337
338 ################################################
339 # Most stuff stolen from the GraphMultiEPG
340
341 Session = None
342 Servicelist = None
343 BouquetSelectorScreen = None
344
345 def getBouquetServices(bouquet):
346 services = []
347 Servicelist = eServiceCenter.getInstance().list(bouquet)
348 if Servicelist is not None:
349 while True:
350 service = Servicelist.getNext()
351 if not service.valid():
352 break
353 if service.flags & (eServiceReference.isDirectory | eServiceReference.isMarker):
354 continue
355 services.append(service)
356 return services
357
358 def closeBouquetSelectorScreen(ret=None):
359 if BouquetSelectorScreen is not None:
360 BouquetSelectorScreen.close()
361
362 def openMosaic(bouquet):
363 if bouquet is not None:
364 services = getBouquetServices(bouquet)
365 if len(services):
366 Session.openWithCallback(closeBouquetSelectorScreen, Mosaic, services)
367
368 def main(session, servicelist, **kwargs):
369 global Session
370 Session = session
371 global Servicelist
372 Servicelist = servicelist
373 global BouquetSelectorScreen
374
375 bouquets = Servicelist.getBouquetList()
376 if bouquets is not None:
377 if len(bouquets) == 1:
378 openMosaic(bouquets[0][1])
379 elif len(bouquets) > 1:
380 BouquetSelectorScreen = Session.open(BouquetSelector, bouquets, openMosaic, enableWrapAround=True)
381
382 def Plugins(**kwargs):
383 return PluginDescriptor(name=_("Mosaic"), where=PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=main)

mercurial