Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 94 additions & 28 deletions examples/pysdl2.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@
further down. Pull requests for the missing functionality are welcome.

Requires PySDL2 and SDL2 libraries.


Usage:

python pysdl2.py [-v] [-h]

-v turn on debug messages
-h display help info

Tested configurations:
- Windows 7: SDL 2.0.7 and PySDL2 0.9.6
- Fedora 25: SDL2 2.0.5 with PySDL2 0.9.3
- Fedora 26: SDL2 2.0.7 with PySDL2 0.9.6
- Ubuntu 14.04: SDL2 with PySDL2 0.9.6

Install instructions:
Expand All @@ -19,7 +26,7 @@
- Ubuntu: sudo apt-get install libsdl2-dev
2. Install PySDL2 using pip package manager:
pip install PySDL2

Missing functionality:
- Performance is still not perfect, see Issue #324 for further details
- Keyboard modifiers that are not yet handled in this example:
Expand All @@ -36,33 +43,65 @@
https://github.com/neilmunday/pes/blob/master/lib/pes/ui.py
"""

import argparse
import logging
import sys

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PEP 8 requires two blank lines here. There are several PEP8 issues in this commit that should be fixed. There is a tool that can check code for pep8 issues.


def die(msg):
"""
Helper function to exit application on failed imports etc.
"""
sys.stderr.write("%s\n" % msg)
sys.exit(1)


try:
# noinspection PyUnresolvedReferences
from cefpython3 import cefpython as cef
except ImportError:
print("ERROR: cefpython3 package not found")
print("To install type: `pip install cefpython3`")
sys.exit(1)
die("""ERROR: cefpython3 package not found\n
To install type: `pip install cefpython3`""")
try:
# noinspection PyUnresolvedReferences
import sdl2
# noinspection PyUnresolvedReferences
import sdl2.ext
except ImportError:
print("ERROR: SDL2 package not found")
print("To install type: `pip install PySDL2`")
sys.exit(1)
die("ERROR: SDL2 package not found\nTo install type: `pip install PySDL2`")
try:
# noinspection PyUnresolvedReferences
from PIL import Image
except ImportError:
print("ERROR: PIL package not found")
print("To install type: pip install Pillow")
sys.exit(1)
die("ERROR: PIL package not found\nTo install type: pip install Pillow")


def main():
parser = argparse.ArgumentParser(
description='PySDL2 / cefpython example',
add_help=True
)
parser.add_argument(
'-v',
'--verbose',
help='Turn on debug info',
dest='verbose',
action='store_true'
)
args = parser.parse_args()
logLevel = logging.INFO
if args.verbose:
logLevel = logging.DEBUG
logging.basicConfig(
format='[%(filename)s %(levelname)s]: %(message)s',
level=logLevel
)
logging.info("Using PySDL2 %s" % sdl2.__version__)
version = sdl2.SDL_version()
sdl2.SDL_GetVersion(version)
logging.info(
"Using SDL2 %s.%s.%s" % (version.major, version.minor, version.patch)
)
# The following variables control the dimensions of the window
# and browser display area
width = 800
Expand All @@ -74,6 +113,8 @@ def main():
browserWidth = width
# Mouse wheel fudge to enhance scrolling
scrollEnhance = 40
# desired frame rate
frameRate = 100
# Initialise CEF for offscreen rendering
sys.excepthook = cef.ExceptHook
switches = {
Expand All @@ -86,16 +127,18 @@ def main():
}
browser_settings = {
# Tweaking OSR performance (Issue #240)
"windowless_frame_rate": 100
"windowless_frame_rate": frameRate
}
cef.Initialize(settings={"windowless_rendering_enabled": True},
switches=switches)
logging.debug("cef initialised")
window_info = cef.WindowInfo()
window_info.SetAsOffscreen(0)
# Initialise SDL2 for video (add other init constants if you
# require other SDL2 functionality e.g. mixer,
# TTF, joystick etc.
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
logging.debug("SDL2 initialised")
# Create the window
window = sdl2.video.SDL_CreateWindow(
'cefpython3 SDL2 Demo',
Expand Down Expand Up @@ -124,7 +167,17 @@ def main():
browser.WasResized()
# Begin the main rendering loop
running = True
# FPS debug variables
frames = 0
logging.debug("beginning rendering loop")
resetFpsTime = True
fpsTime = 0
while running:
# record when we started drawing this frame
startTime = sdl2.timer.SDL_GetTicks()
if resetFpsTime:
fpsTime = sdl2.timer.SDL_GetTicks()
resetFpsTime = False
# Convert SDL2 events into CEF events (where appropriate)
events = sdl2.ext.get_events()
for event in events:
Expand Down Expand Up @@ -269,6 +322,17 @@ def main():
sdl2.SDL_Rect(0, headerHeight, browserWidth, browserHeight)
)
sdl2.SDL_RenderPresent(renderer)
# FPS debug code
frames += 1
if sdl2.timer.SDL_GetTicks() - fpsTime > 1000:
logging.debug("FPS: %d" % frames)
frames = 0
resetFpsTime = True
# regulate frame rate
if sdl2.timer.SDL_GetTicks() - startTime < 1000.0 / frameRate:
sdl2.timer.SDL_Delay(
(1000 / frameRate) - (sdl2.timer.SDL_GetTicks() - startTime)
)
# User exited
exit_app()

Expand All @@ -289,31 +353,33 @@ def get_key_code(key):
if key in key_map:
return key_map[key]
# Key not mapped, raise exception
print("[pysdl2.py] Keyboard mapping incomplete:"
" unsupported SDL key %d."
" See https://wiki.libsdl.org/SDLKeycodeLookup for mapping."
% key)
logging.error(
"""
Keyboard mapping incomplete: unsupported SDL key %d.
See https://wiki.libsdl.org/SDLKeycodeLookup for mapping.
""" % key
)
return None


class LoadHandler(object):
"""Simple handler for loading URLs."""

def OnLoadingStateChange(self, is_loading, **_):
if not is_loading:
print("[pysdl2.py] Page loading complete")
logging.info("Page loading complete")

def OnLoadError(self, frame, failed_url, **_):
if not frame.IsMain():
return
print("[pysdl2.py] Failed to load %s" % failed_url)
logging.error("Failed to load %s" % failed_url)


class RenderHandler(object):
"""
Handler for rendering web pages to the
screen via SDL2.

The object's texture property is exposed
to allow the main rendering loop to access
the SDL2 texture.
Expand All @@ -324,11 +390,11 @@ def __init__(self, renderer, width, height):
self.__height = height
self.__renderer = renderer
self.texture = None

def GetViewRect(self, rect_out, **_):
rect_out.extend([0, 0, self.__width, self.__height])
return True

def OnPaint(self, element_type, paint_buffer, **_):
"""
Using the pixel data from CEF's offscreen rendering
Expand Down Expand Up @@ -378,9 +444,9 @@ def OnPaint(self, element_type, paint_buffer, **_):
depth = 32
pitch = self.__width * 4
else:
print("[pysdl2.py] ERROR: Unsupported mode: %s" % mode)
logging.error("ERROR: Unsupported mode: %s" % mode)
exit_app()

pxbuf = image.tobytes()
# Create surface
surface = sdl2.SDL_CreateRGBSurfaceFrom(
Expand All @@ -403,14 +469,14 @@ def OnPaint(self, element_type, paint_buffer, **_):
# Free the surface
sdl2.SDL_FreeSurface(surface)
else:
print("[pysdl2.py] WARNING: Unsupport element_type in OnPaint")
logging.warning("Unsupport element_type in OnPaint")


def exit_app():
"""Tidy up SDL2 and CEF before exiting."""
sdl2.SDL_Quit()
cef.Shutdown()
print("[pysdl2.py] Exited gracefully")
logging.info("Exited gracefully")


if __name__ == "__main__":
Expand Down