Package libavg :: Module AVGAppStarter'

Source Code for Module libavg.AVGAppStarter'

  1  # libavg - Media Playback Engine. 
  2  # Copyright (C) 2003-2008 Ulrich von Zadow 
  3  # 
  4  # This library is free software; you can redistribute it and/or 
  5  # modify it under the terms of the GNU Lesser General Public 
  6  # License as published by the Free Software Foundation; either 
  7  # version 2 of the License, or (at your option) any later version. 
  8  # 
  9  # This library is distributed in the hope that it will be useful, 
 10  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 12  # Lesser General Public License for more details. 
 13  # 
 14  # You should have received a copy of the GNU Lesser General Public 
 15  # License along with this library; if not, write to the Free Software 
 16  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 17  # 
 18  # Current versions can be found at www.libavg.de 
 19  # 
 20  # Original author of this file is Martin Heistermann <mh at sponc dot de> 
 21  # 
 22   
 23  import os 
 24  import gc 
 25  import math 
 26  import time 
 27   
 28  from libavg import avg, Point2D 
 29  from mtemu import MTemu 
 30  from AVGAppStarterHelp import MThelp 
 31   
 32  try: 
 33      from alib.clicktest import ClickTest 
 34  except ImportError: 
 35      ClickTest = None 
 36   
 37   
 38  g_player = avg.Player.get() 
 39  g_log = avg.Logger.get() 
 40   
 41   
42 -class Graph():
43 - def __init__(self, graph,getValue):
44 self._getValue = getValue 45 46 self._values = [] 47 self._xSkip = 2 48 self._lastCurUsage = 0 49 self._maxFrameTime = 0 50 51 self._memGraphStartTime = g_player.getFrameTime() 52 self._curUsage = 0 53 self._usage = [0] 54 self._maxUsage = [0] 55 self._minutesUsage = [0] 56 self._minutesMaxUsage = [0] 57 self._rootNode = g_player.getRootNode() 58 size = avg.Point2D(self._rootNode.width-20, self._rootNode.height/6) 59 60 self._node = g_player.createNode(""" 61 <div opacity="0" sensitive="False" x="10" y="10" size="%(size)s"> 62 <rect strokewidth="0" fillopacity="0.6" fillcolor="FFFFFF" 63 size="%(size)s"/> 64 <words x="10" y="%(wordsheight0)i" color="000080"/> 65 <words x="10" y="%(wordsheight1)i" color="000080"/> 66 <polyline color="008000"/> 67 <polyline color="000080"/> 68 <words x="10" y="0" color="000080"/> 69 </div>""" 70 % {'size': str(size), 'wordsheight0':size.y-22, 'wordsheight1':size.y-39}) 71 72 self._graphSize = size-avg.Point2D(20, 20) 73 self._rootNode.appendChild(self._node) 74 self._textNode0 = self._node.getChild(1) 75 self._textNode1 = self._node.getChild(2) 76 self._maxLineNode = self._node.getChild(3) 77 self._lineNode = self._node.getChild(4) 78 self.__graphText = self._node.getChild(5) 79 self.__graphText.text = graph 80 81 self._setup() 82 self._sampleNum = 0 83 avg.fadeIn(self._node, 300)
84
85 - def _setup(self):
86 raise RuntimeError, 'Please overload _setup() function'
87
88 - def setYpos(self,ypos):
89 self._node.y = ypos
90
91 - def delete(self):
92 def kill(): 93 self._node.unlink()
94 avg.LinearAnim(self._node, "opacity", 300, 1, 0, None, kill).start() 95 g_player.clearInterval(self._interval) 96 self._interval = None
97 98 99
100 -class MemGraph(Graph):
101 - def _setup(self):
102 self._interval = g_player.setInterval(1000, self._nextMemSample)
103
104 - def _nextMemSample(self):
105 curUsage = self._getValue() 106 self._usage.append(curUsage) 107 maxUsage = self._maxUsage[-1] 108 if curUsage>maxUsage: 109 maxUsage = curUsage 110 lastMaxChangeTime = time.time() 111 self._textNode1.text = ("Last increase in maximum: " 112 +time.strftime("%H:%M:%S", time.localtime(lastMaxChangeTime))) 113 self._maxUsage.append(maxUsage) 114 self._sampleNum += 1 115 if self._sampleNum % 60 == 0: 116 lastMinuteAverage = sum(self._usage[-60:])/60 117 self._minutesUsage.append(lastMinuteAverage) 118 self._minutesMaxUsage.append(maxUsage) 119 120 if self._sampleNum < 60*60: 121 self._plotLine(self._usage, self._lineNode, maxUsage) 122 self._plotLine(self._maxUsage, self._maxLineNode, maxUsage) 123 else: 124 self._plotLine(self._minutesUsage, self._lineNode, maxUsage) 125 self._plotLine(self._minutesMaxUsage, self._maxLineNode, maxUsage) 126 self._textNode0.text = ("Max. memory usage: %(size).2f MB" 127 %{"size":maxUsage/(1024*1024.)})
128
129 - def _plotLine(self, data, node, maxy):
130 yfactor = self._graphSize.y/float(maxy) 131 xfactor = self._graphSize.x/float(len(data)-1) 132 node.pos = [(pos[0]*xfactor+10, (maxy-pos[1])*yfactor+10) 133 for pos in enumerate(data)]
134
135 -class FrameRateGraph(Graph):
136 - def _setup(self):
137 self._interval = g_player.setOnFrameHandler(self._nextFrameTimeSample)
138
139 - def _nextFrameTimeSample(self):
140 val = self._frameTimeSample() 141 self._appendValue(val) 142 self._sampleNum += 1
143
144 - def _appendValue(self,value):
145 y = value + self._rootNode.height/6 146 numValues = int(self._rootNode.width/self._xSkip)-10 147 self._values = (self._values + [y])[-numValues:] 148 self._plotGraph()
149
150 - def _frameTimeSample(self):
151 frameTime = self._getValue() 152 diff = frameTime - self._lastCurUsage 153 #if(self._sampleNum % 1800 == 0): 154 # self._maxFrameTime = 0 155 if(self._sampleNum<2): 156 self._maxFrameTime = 0 157 if(diff>self._maxFrameTime): 158 lastMaxChangeTime = time.time() 159 self._maxFrameTime = diff 160 self._textNode0.text = ("Max FrameTime: %.f" %self._maxFrameTime + " ms" + 161 " Time: " +time.strftime("%H:%M:%S", time.localtime(lastMaxChangeTime))) 162 if diff>self._node.y-1: 163 y = self._node.y-1 164 165 self._lastCurUsage = frameTime 166 self._textNode1.text = ("Current FrameTime: %.f" %diff + " ms" ) 167 return -diff
168
169 - def _plotGraph(self):
170 self._lineNode.pos = self._getCoords()
171
172 - def _getCoords(self):
173 return zip(xrange(10,len(self._values)*self._xSkip, self._xSkip), self._values)
174
175 -class AVGAppStarter(object):
176 """Starts an AVGApp"""
177 - def __init__(self, appClass, resolution, debugWindowSize = None):
178 self._AppClass = appClass 179 resolution = Point2D(resolution) 180 testMode = os.getenv("AVG_DEPLOY") == None 181 if testMode and debugWindowSize is not None: 182 debugWindowSize = Point2D(debugWindowSize) 183 else: 184 debugWindowSize = Point2D(0, 0) 185 186 width = int(resolution.x) 187 height = int(resolution.y) 188 self.__graphs = 0 189 # dynamic avg creation in order to set resolution 190 g_player.loadString(""" 191 <?xml version="1.0"?> 192 <!DOCTYPE avg SYSTEM "../../libavg/doc/avg.dtd"> 193 <avg width="%(width)u" height="%(height)u"> 194 </avg>""" % { 195 'width': width, 196 'height': height, 197 }) 198 rootNode = g_player.getRootNode() 199 200 self._appNode = g_player.createNode('div',{ 201 'opacity': 0, 202 'sensitive': False}) 203 # the app should know the size of its "root" node: 204 self._appNode.size = rootNode.size 205 rootNode.appendChild(self._appNode) 206 207 g_player.showCursor(testMode) 208 g_player.setResolution( 209 not testMode, # fullscreen 210 int(debugWindowSize.x), int(debugWindowSize.y), 211 0 # color depth 212 ) 213 214 self.__keyBindDown = {} 215 self.__keyBindUp = {} 216 self.__unicodeBindDown = {} 217 self.__unicodeBindUp = {} 218 219 rootNode.setEventHandler(avg.KEYDOWN, avg.NONE, self.__onKeyDown) 220 rootNode.setEventHandler(avg.KEYUP, avg.NONE, self.__onKeyUp) 221 222 self.bindKey('o', self.__dumpObjects, 'dump objects') 223 self.bindKey('m', self.__showMemoryUsage, 'show memory usage') 224 self.bindKey('f', self.__showFrameRateUsage, 'show frameTime usage') 225 self.bindKey('.', self.__switchClickTest, 'start clicktest', 'up') 226 self.bindKey('t', self.__switchMtemu, 'activate multitouch emulation') 227 self.bindUnicode('?', self.activateHelp, 'HELP') 228 229 230 self.helpInstance = MThelp(self) 231 self.showingHelp = False 232 self.__showingMemGraph = False 233 self.__showingFrGraph = False 234 self.__runningClickTest = False 235 self._initClickTest() 236 self._mtEmu = None 237 238 self._onBeforePlay() 239 g_player.setTimeout(0, self._onStart) 240 self._appInstance = self._AppClass(self._appNode) 241 self._appInstance.setStarter(self) 242 g_player.play()
243
244 - def _onBeforePlay(self):
245 pass
246
247 - def _onStart(self):
248 self._appInstance.init() 249 self._appNode.opacity = 1 250 self._appNode.sensitive = True 251 self._activeApp = self._appInstance 252 self._appInstance.enter()
253
254 - def _initClickTest(self):
255 if ClickTest: 256 self._clickTest = ClickTest(self._appNode, multiClick=False) 257 else: 258 self._clickTest = None
259
260 - def bindKey(self, key, func, funcName, state = 'down'):
261 if state == 'down': 262 if key in self.__keyBindDown: 263 raise KeyError # no double key bindings 264 self.__keyBindDown[key] = (func, funcName) 265 elif state == 'up': 266 if key in self.__keyBindUp: 267 print key 268 raise KeyError # no double key bindings 269 self.__keyBindUp[key] = (func, funcName) 270 else: 271 raise KeyError
272
273 - def unbindKey(self, key):
274 if key in self.__keyBindDown: 275 del self.__keyBindDown[key] 276 if key in self.__keyBindUp: 277 del self.__keyBindUp[key] 278 if key in self.__unicodeBindDown: 279 del self.__unicodeBindDown[key] 280 if key in self.__unicodeBindUp: 281 del self.__unicodeBindUp[key]
282
283 - def bindUnicode(self, key, func, funcName, state = 'down'):
284 if state == 'down': 285 if key in self.__unicodeBindDown: 286 raise KeyError # no double key bindings 287 self.__unicodeBindDown[key] = (func, funcName) 288 elif state == 'up': 289 if key in self.__unicodeBindUp: 290 raise KeyError # no double key bindings 291 self.__unicodeBindUp[key] = (func, funcName) 292 else: 293 raise KeyError
294
295 - def getKeys(self, bindtype = 'key', action = 'down'):
296 if bindtype == 'key': 297 if action == 'down': 298 return self.__keyBindDown 299 elif action == 'up': 300 return self.__keyBindUp 301 elif bindtype == 'unicode': 302 if action == 'down': 303 return self.__unicodeBindDown 304 elif action == 'up': 305 return self.__unicodeBindUp
306
307 - def setKeys(self, newKeyBindings, bindtype = 'key', action = 'down'):
308 if bindtype == 'key': 309 if action == 'down': 310 self.__keyBindDown = newKeyBindings 311 elif action == 'up': 312 self.__keyBindUp = newKeyBindings 313 elif bindtype == 'unicode': 314 if action == 'down': 315 self.__unicodeBindDown = newKeyBindings 316 elif action == 'up': 317 self.__unicodeBindUp = newKeyBindings
318
319 - def __checkUnicode(self, event, Bindings):
320 x = 0 321 try: 322 if str(unichr(event.unicode)) in Bindings: 323 x = 1 324 return x 325 except: 326 pass 327 try: 328 if unichr(event.unicode).encode("utf-8") in Bindings: 329 x = 2 330 return x 331 except: 332 pass 333 return x
334
335 - def __onKeyDown(self, event):
336 handledByApp = self._activeApp.onKey(event) 337 if handledByApp: 338 return 339 elif event.keystring in self.__keyBindDown: 340 self.__keyBindDown[event.keystring][0]() 341 elif self.__checkUnicode(event, self.__unicodeBindDown) == 1: 342 self.__unicodeBindDown[str(unichr(event.unicode))][0]() 343 return 344 elif self.__checkUnicode(event, self.__unicodeBindDown) == 2: 345 self.__unicodeBindDown[unichr(event.unicode).encode("utf-8")][0]() 346 return
347 348
349 - def __onKeyUp(self, event):
350 if event.keystring in self.__keyBindUp: 351 if event.unicode == event.keycode: 352 self.__keyBindUp[event.keystring][0]() 353 return 354 elif event.unicode == 0: #shift and ctrl 355 self.__keyBindUp[event.keystring][0]() 356 elif self.__checkUnicode(event, self.__unicodeBindUp) == 1: 357 self.__unicodeBindUp[str(unichr(event.unicode))][0]() 358 return 359 elif self.__checkUnicode(event, self.__unicodeBindUp) == 2: 360 self.__unicodeBindUp[unichr(event.unicode).encode("utf-8")][0]() 361 return
362 363
364 - def __dumpObjects(self):
365 gc.collect() 366 testHelper = g_player.getTestHelper() 367 testHelper.dumpObjects() 368 print "Num anims: ", avg.getNumRunningAnims() 369 print "Num python objects: ", len(gc.get_objects())
370
371 - def __showMemoryUsage(self):
372 if self.__showingMemGraph: 373 self.__memGraph.delete() 374 self.__memGraph = None 375 self.__graphs = self.__graphs -1 376 if(self.__graphs == 1 ): 377 self.__frGraph.setYpos(10) 378 else: 379 self.__memGraph = MemGraph("Memory Graph", getValue = lambda: avg.getMemoryUsage()) 380 self.__graphs = self.__graphs +1 381 if(self.__graphs > 1 ): 382 self.__memGraph.setYpos(190) 383 self.__showingMemGraph = not(self.__showingMemGraph)
384 385
386 - def __showFrameRateUsage(self):
387 if self.__showingFrGraph: 388 self.__frGraph.delete() 389 self.__frGraph = None 390 self.__graphs = self.__graphs -1 391 if(self.__graphs == 1 ): 392 self.__memGraph.setYpos(10) 393 else: 394 self.__frGraph = FrameRateGraph("FrameTime Graph",getValue = lambda: g_player.getFrameTime()) 395 self.__graphs = self.__graphs +1 396 if(self.__graphs >1): 397 self.__frGraph.setYpos(190) 398 self.__showingFrGraph = not(self.__showingFrGraph)
399
400 - def __switchClickTest(self):
401 if self._clickTest: 402 if self.__runningClickTest: 403 g_log.trace(g_log.APP, 'Stopping clicktest') 404 self._clickTest.stop() 405 else: 406 g_log.trace(g_log.APP, 'Starting clicktest') 407 self._clickTest.start() 408 409 self.__runningClickTest = not self.__runningClickTest
410
411 - def __switchMtemu(self):
412 if self._mtEmu is None: 413 self._mtEmu = MTemu() 414 self.bindKey('left ctrl', self._mtEmu.changeMode, 'switch event mode') 415 self.bindKey('right ctrl', self._mtEmu.changeMode, 'switch event mode') 416 self.bindKey('left shift', self._mtEmu.multiTouch, 'create 2nd event') 417 self.bindKey('right shift', self._mtEmu.multiTouch, 'create 2nd event') 418 self.bindKey('left shift', self._mtEmu.multiTouch, 'create 2nd event', 'up') 419 self.bindKey('right shift', self._mtEmu.multiTouch, 'create 2nd event', 'up') 420 421 else: 422 self.unbindKey('left ctrl') 423 self.unbindKey('right ctrl') 424 self.unbindKey('left shift') 425 self.unbindKey('right shift') 426 self._mtEmu.delete() 427 self._mtEmu = None
428
429 - def activateHelp(self):
430 if self.showingHelp == False: 431 self.showingHelp = True 432 else: 433 self.showingHelp = False 434 self.helpInstance.showHelp()
435