55further down. Pull requests for the missing functionality are welcome.
66
77Requires PySDL2 and SDL2 libraries.
8-
8+
9+ Usage:
10+
11+ python pysdl2.py [-v] [-h]
12+
13+ -v turn on debug messages
14+ -h display help info
15+
916Tested configurations:
1017- Windows 7: SDL 2.0.7 and PySDL2 0.9.6
11- - Fedora 25 : SDL2 2.0.5 with PySDL2 0.9.3
18+ - Fedora 26 : SDL2 2.0.7 with PySDL2 0.9.6
1219- Ubuntu 14.04: SDL2 with PySDL2 0.9.6
1320
1421Install instructions:
1926 - Ubuntu: sudo apt-get install libsdl2-dev
20272. Install PySDL2 using pip package manager:
2128 pip install PySDL2
22-
29+
2330Missing functionality:
2431- Performance is still not perfect, see Issue #324 for further details
2532- Keyboard modifiers that are not yet handled in this example:
3643 https://github.com/neilmunday/pes/blob/master/lib/pes/ui.py
3744"""
3845
46+ import argparse
47+ import logging
3948import sys
49+
50+
51+ def die (msg ):
52+ """
53+ Helper function to exit application on failed imports etc.
54+ """
55+ sys .stderr .write ("%s\n " % msg )
56+ sys .exit (1 )
57+
58+
4059try :
4160 # noinspection PyUnresolvedReferences
4261 from cefpython3 import cefpython as cef
4362except ImportError :
44- print ("ERROR: cefpython3 package not found" )
45- print ("To install type: `pip install cefpython3`" )
46- sys .exit (1 )
63+ die ("""ERROR: cefpython3 package not found\n
64+ To install type: `pip install cefpython3`""" )
4765try :
4866 # noinspection PyUnresolvedReferences
4967 import sdl2
5068 # noinspection PyUnresolvedReferences
5169 import sdl2 .ext
5270except ImportError :
53- print ("ERROR: SDL2 package not found" )
54- print ("To install type: `pip install PySDL2`" )
55- sys .exit (1 )
71+ die ("ERROR: SDL2 package not found\n To install type: `pip install PySDL2`" )
5672try :
5773 # noinspection PyUnresolvedReferences
5874 from PIL import Image
5975except ImportError :
60- print ("ERROR: PIL package not found" )
61- print ("To install type: pip install Pillow" )
62- sys .exit (1 )
76+ die ("ERROR: PIL package not found\n To install type: pip install Pillow" )
6377
6478
6579def main ():
80+ parser = argparse .ArgumentParser (
81+ description = 'PySDL2 / cefpython example' ,
82+ add_help = True
83+ )
84+ parser .add_argument (
85+ '-v' ,
86+ '--verbose' ,
87+ help = 'Turn on debug info' ,
88+ dest = 'verbose' ,
89+ action = 'store_true'
90+ )
91+ args = parser .parse_args ()
92+ logLevel = logging .INFO
93+ if args .verbose :
94+ logLevel = logging .DEBUG
95+ logging .basicConfig (
96+ format = '[%(filename)s %(levelname)s]: %(message)s' ,
97+ level = logLevel
98+ )
99+ logging .info ("Using PySDL2 %s" % sdl2 .__version__ )
100+ version = sdl2 .SDL_version ()
101+ sdl2 .SDL_GetVersion (version )
102+ logging .info (
103+ "Using SDL2 %s.%s.%s" % (version .major , version .minor , version .patch )
104+ )
66105 # The following variables control the dimensions of the window
67106 # and browser display area
68107 width = 800
@@ -74,6 +113,8 @@ def main():
74113 browserWidth = width
75114 # Mouse wheel fudge to enhance scrolling
76115 scrollEnhance = 40
116+ # desired frame rate
117+ frameRate = 100
77118 # Initialise CEF for offscreen rendering
78119 sys .excepthook = cef .ExceptHook
79120 switches = {
@@ -86,16 +127,18 @@ def main():
86127 }
87128 browser_settings = {
88129 # Tweaking OSR performance (Issue #240)
89- "windowless_frame_rate" : 100
130+ "windowless_frame_rate" : frameRate
90131 }
91132 cef .Initialize (settings = {"windowless_rendering_enabled" : True },
92133 switches = switches )
134+ logging .debug ("cef initialised" )
93135 window_info = cef .WindowInfo ()
94136 window_info .SetAsOffscreen (0 )
95137 # Initialise SDL2 for video (add other init constants if you
96138 # require other SDL2 functionality e.g. mixer,
97139 # TTF, joystick etc.
98140 sdl2 .SDL_Init (sdl2 .SDL_INIT_VIDEO )
141+ logging .debug ("SDL2 initialised" )
99142 # Create the window
100143 window = sdl2 .video .SDL_CreateWindow (
101144 'cefpython3 SDL2 Demo' ,
@@ -124,7 +167,17 @@ def main():
124167 browser .WasResized ()
125168 # Begin the main rendering loop
126169 running = True
170+ # FPS debug variables
171+ frames = 0
172+ logging .debug ("beginning rendering loop" )
173+ resetFpsTime = True
174+ fpsTime = 0
127175 while running :
176+ # record when we started drawing this frame
177+ startTime = sdl2 .timer .SDL_GetTicks ()
178+ if resetFpsTime :
179+ fpsTime = sdl2 .timer .SDL_GetTicks ()
180+ resetFpsTime = False
128181 # Convert SDL2 events into CEF events (where appropriate)
129182 events = sdl2 .ext .get_events ()
130183 for event in events :
@@ -269,6 +322,17 @@ def main():
269322 sdl2 .SDL_Rect (0 , headerHeight , browserWidth , browserHeight )
270323 )
271324 sdl2 .SDL_RenderPresent (renderer )
325+ # FPS debug code
326+ frames += 1
327+ if sdl2 .timer .SDL_GetTicks () - fpsTime > 1000 :
328+ logging .debug ("FPS: %d" % frames )
329+ frames = 0
330+ resetFpsTime = True
331+ # regulate frame rate
332+ if sdl2 .timer .SDL_GetTicks () - startTime < 1000.0 / frameRate :
333+ sdl2 .timer .SDL_Delay (
334+ (1000 / frameRate ) - (sdl2 .timer .SDL_GetTicks () - startTime )
335+ )
272336 # User exited
273337 exit_app ()
274338
@@ -289,31 +353,33 @@ def get_key_code(key):
289353 if key in key_map :
290354 return key_map [key ]
291355 # Key not mapped, raise exception
292- print ("[pysdl2.py] Keyboard mapping incomplete:"
293- " unsupported SDL key %d."
294- " See https://wiki.libsdl.org/SDLKeycodeLookup for mapping."
295- % key )
356+ logging .error (
357+ """
358+ Keyboard mapping incomplete: unsupported SDL key %d.
359+ See https://wiki.libsdl.org/SDLKeycodeLookup for mapping.
360+ """ % key
361+ )
296362 return None
297363
298364
299365class LoadHandler (object ):
300366 """Simple handler for loading URLs."""
301-
367+
302368 def OnLoadingStateChange (self , is_loading , ** _ ):
303369 if not is_loading :
304- print ( "[pysdl2.py] Page loading complete" )
305-
370+ logging . info ( " Page loading complete" )
371+
306372 def OnLoadError (self , frame , failed_url , ** _ ):
307373 if not frame .IsMain ():
308374 return
309- print ( "[pysdl2.py] Failed to load %s" % failed_url )
375+ logging . error ( " Failed to load %s" % failed_url )
310376
311377
312378class RenderHandler (object ):
313379 """
314380 Handler for rendering web pages to the
315381 screen via SDL2.
316-
382+
317383 The object's texture property is exposed
318384 to allow the main rendering loop to access
319385 the SDL2 texture.
@@ -324,11 +390,11 @@ def __init__(self, renderer, width, height):
324390 self .__height = height
325391 self .__renderer = renderer
326392 self .texture = None
327-
393+
328394 def GetViewRect (self , rect_out , ** _ ):
329395 rect_out .extend ([0 , 0 , self .__width , self .__height ])
330396 return True
331-
397+
332398 def OnPaint (self , element_type , paint_buffer , ** _ ):
333399 """
334400 Using the pixel data from CEF's offscreen rendering
@@ -378,9 +444,9 @@ def OnPaint(self, element_type, paint_buffer, **_):
378444 depth = 32
379445 pitch = self .__width * 4
380446 else :
381- print ( "[pysdl2.py] ERROR: Unsupported mode: %s" % mode )
447+ logging . error ( " ERROR: Unsupported mode: %s" % mode )
382448 exit_app ()
383-
449+
384450 pxbuf = image .tobytes ()
385451 # Create surface
386452 surface = sdl2 .SDL_CreateRGBSurfaceFrom (
@@ -403,14 +469,14 @@ def OnPaint(self, element_type, paint_buffer, **_):
403469 # Free the surface
404470 sdl2 .SDL_FreeSurface (surface )
405471 else :
406- print ( "[pysdl2.py] WARNING: Unsupport element_type in OnPaint" )
472+ logging . warning ( " Unsupport element_type in OnPaint" )
407473
408474
409475def exit_app ():
410476 """Tidy up SDL2 and CEF before exiting."""
411477 sdl2 .SDL_Quit ()
412478 cef .Shutdown ()
413- print ( "[pysdl2.py] Exited gracefully" )
479+ logging . info ( " Exited gracefully" )
414480
415481
416482if __name__ == "__main__" :
0 commit comments