mosaic/plugin.py

Mon, 16 Jan 2012 22:56:52 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 16 Jan 2012 22:56:52 +0100
changeset 21
6bb708a2265f
child 22
61eb8a9b53a6
permissions
-rw-r--r--

Import original vendor code for correction and improvement.

     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
    20 ################################################
    22 grab_binary = "/usr/bin/grab"
    23 grab_picture = "/tmp/mosaic.jpg"
    24 grab_errorlog = "/tmp/mosaic.log"
    26 config_limits = (3, 30)
    27 config.plugins.Mosaic = ConfigSubsection()
    28 config.plugins.Mosaic.countdown = ConfigInteger(default=5, limits=config_limits)
    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'))
    33 ################################################
    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/"))
    41 def _(txt):
    42 	t = gettext.dgettext("Mosaic", txt)
    43 	if t == txt:
    44 		t = gettext.gettext(txt)
    45 	return t
    47 ################################################
    49 class Mosaic(Screen):
    50 	PLAY = 0
    51 	PAUSE = 1
    53 	desktop = getDesktop(0)
    54 	size = desktop.size()
    55 	width = size.width()
    56 	height = size.height()
    57 	windowWidth = width / 4
    58 	windowHeight = height / 4
    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
    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)
   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)
   124 	def __init__(self, session, services):
   125 		Screen.__init__(self, session)
   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
   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()
   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)
   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)
   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)
   194 	def exit(self, callback=None):
   195 		self.deleteConsoleCallbacks()
   196 		self.close()
   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]
   206 	def closeWithOldService(self):
   207 		self.session.nav.playService(self.oldService)
   208 		self.deleteConsoleCallbacks()
   209 		self.close()
   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()
   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)
   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)
   230 	def countdownPlus(self):
   231 		self.changeCountdown(1)
   233 	def countdownMinus(self):
   234 		self.changeCountdown(-1)
   236 	def changeCountdown(self, direction):
   237 		if self.working == False:
   238 			configNow = config.plugins.Mosaic.countdown.value
   239 			configNow += direction
   241 			if configNow < config_limits[0]:
   242 				configNow = config_limits[0]
   243 			elif configNow > config_limits[1]:
   244 				configNow = config_limits[1]
   246 			config.plugins.Mosaic.countdown.value = configNow
   247 			config.plugins.Mosaic.countdown.save()
   249 			self.updateCountdownLabel()
   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)
   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)
   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()
   268 			# Get next ref
   269 			self.current_refidx += 1
   270 			if self.current_refidx > (len(self.ref_list) -1):
   271 				self.current_refidx = 0
   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)
   280 			# Get next window index
   281 			self.current_window += 1
   282 			if self.current_window > 9:
   283 				self.current_window = 1
   285 			# Save the ref
   286 			self.window_refs[self.current_window-1] = ref
   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)
   292 			# Show the new video-window
   293 			self["video" + str(self.current_window)].show()
   294 			self["video" + str(self.current_window)].decoder = 0
   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)))
   300 			# Restart timer
   301 			self.working = False
   302 			self.updateTimer.start(1, 1)
   303 		else:
   304 			print "[Mosaic] retval: %d result: %s" % (retval, result)
   306 			try:
   307 				f = open(grab_errorlog, "w")
   308 				f.write("retval: %d\nresult: %s" % (retval, result))
   309 				f.close()
   310 			except:
   311 				pass
   313 			self.session.openWithCallback(self.exit, MessageBox, _("Error while creating screenshot. You need grab version 0.8 or higher!"), MessageBox.TYPE_ERROR, timeout=5)
   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)
   325 	def updateCountdownLabel(self):
   326 		self["countdown"].setText("%s %s / %s" % (_("Countdown:"), str(self.countdown), str(config.plugins.Mosaic.countdown.value)))
   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
   338 ################################################
   339 # Most stuff stolen from the GraphMultiEPG
   341 Session = None
   342 Servicelist = None
   343 BouquetSelectorScreen = None
   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
   358 def closeBouquetSelectorScreen(ret=None):
   359 	if BouquetSelectorScreen is not None:
   360 		BouquetSelectorScreen.close()
   362 def openMosaic(bouquet):
   363 	if bouquet is not None:
   364 		services = getBouquetServices(bouquet)
   365 		if len(services):
   366 			Session.openWithCallback(closeBouquetSelectorScreen, Mosaic, services)
   368 def main(session, servicelist, **kwargs):
   369 	global Session
   370 	Session = session
   371 	global Servicelist
   372 	Servicelist = servicelist
   373 	global BouquetSelectorScreen
   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)
   382 def Plugins(**kwargs):
   383 	return PluginDescriptor(name=_("Mosaic"), where=PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=main)

mercurial