Skip to content

Commit

Permalink
Extended sdl2.ext.init to support all subsystems
Browse files Browse the repository at this point in the history
  • Loading branch information
a-hurst committed Sep 1, 2022
1 parent 6d9c1bc commit 425acc4
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 14 deletions.
7 changes: 6 additions & 1 deletion doc/news.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ This describes the latest changes between the PySDL2 releases.
0.9.14 (Unreleased)
-------------------

New Features:

* Added a new function :func:`~sdl2.ext.get_displays` and class
:class:`~sdl2.ext.DisplayInfo` to provide an easier and more Pythonic API for
getting information about the names, locations, and supported video modes
of the connected displays.
* Extended :func:`~sdl2.ext.init` to allow initializing all SDL2 subsystems
individually using keyword arguments (e.g. ``sdl2.ext.init(audio=True)`` to
initialize the audio subsystem as well as the default video subsystem).
Previously, this function only initailized the video subsystem.


0.9.13
Expand Down Expand Up @@ -46,7 +52,6 @@ New Features:
that will not break when other SDL2 modules are eventually migrated to similar
Python-wrapped bindings.


Fixed Bugs:

* Fixed a bug in :func:`~sdl2.rw_from_object` where calling
Expand Down
83 changes: 75 additions & 8 deletions sdl2/ext/common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import ctypes
from .. import SDL_Init, SDL_Quit, SDL_QuitSubSystem, SDL_WasInit, \
SDL_INIT_VIDEO, error, events, timer
from .. import (events, timer, error, dll,
SDL_Init, SDL_InitSubSystem, SDL_Quit, SDL_QuitSubSystem, SDL_WasInit,
SDL_INIT_VIDEO, SDL_INIT_AUDIO, SDL_INIT_TIMER, SDL_INIT_HAPTIC,
SDL_INIT_JOYSTICK, SDL_INIT_GAMECONTROLLER, SDL_INIT_SENSOR, SDL_INIT_EVENTS,
)

_HASSDLTTF = True
try:
Expand All @@ -16,6 +19,18 @@
__all__ = ["SDLError", "init", "quit", "get_events", "TestEventProcessor"]


_sdl_subsystems = {
'timer': SDL_INIT_TIMER,
'audio': SDL_INIT_AUDIO,
'video': SDL_INIT_VIDEO,
'joystick': SDL_INIT_JOYSTICK,
'haptic': SDL_INIT_HAPTIC,
'gamecontroller': SDL_INIT_GAMECONTROLLER,
'events': SDL_INIT_EVENTS,
'sensor': SDL_INIT_SENSOR,
}


class SDLError(Exception):
"""An SDL2-specific exception class."""

Expand Down Expand Up @@ -48,19 +63,71 @@ def raise_sdl_err(desc=None):
raise SDLError(e)


def init():
"""Initializes the SDL2 video subsystem.
def init(
video=True, audio=False, timer=False, joystick=False, controller=False,
haptic=False, sensor=False, events=True
):
"""Initializes SDL and its optional subsystems.
By default, only the video and events subsystems are initialized. Note that
the sensor subsystem requires SDL 2.0.9 or later.
Args:
video (bool, optional): Whether to initialize the SDL video subsystem.
If True, the events subsystem will also be initialized. Defaults
to True.
audio (bool, optional): Whether to initialize the SDL audio subsystem.
Defaults to False.
timer (bool, optional): Whether to initialize the SDL timer subsystem.
Defaults to False.
joystick (bool, optional): Whether to initialize the SDL joystick
subsystem. If True, the events subsystem will also be initialized.
Defaults to False.
controller (bool, optional): Whether to initialize the SDL gamecontroller
subsystem. If True, the joystick subsystem will also be initialized.
Defaults to False.
haptic (bool, optional): Whether to initialize the SDL haptic (force
feedback) subsystem. Defaults to False.
sensor (bool, optional): Whether to initialize the SDL sensor subsystem.
Defaults to False.
events (bool, optional): Whether to initialize the SDL events subsystem.
Will automatically be initialized if the video, joystick, or
gamecontroller subsystems are enabled. Defaults to False.
See :ref:`pygamers_pygame` for a comparison between this function and
``pygame.init()``.
Raises:
:exc:`SDLError`: If the SDL2 video subsystem cannot be initialized.
:exc:`SDLError`: If a requested SDL subsystem cannot be initialized.
"""
# TODO: More subsystems?
if SDL_Init(SDL_INIT_VIDEO) != 0:
raise SDLError()
subsystems = []
if events:
subsystems.append("events")
if video:
subsystems.append("video")
if audio:
subsystems.append("audio")
if timer:
subsystems.append("timer")
if joystick:
subsystems.append("joystick")
if controller:
subsystems.append("gamecontroller")
if haptic:
subsystems.append("haptic")
if sensor:
subsystems.append("sensor")

if SDL_Init(0) != 0:
raise_sdl_err("initializing SDL2")

for s in subsystems:
if s == "sensor" and dll.version < 2009:
e = "The sensor subsystem requires SDL 2.0.9 or later."
raise RuntimeError(e)
if SDL_InitSubSystem(_sdl_subsystems[s]) != 0:
raise_sdl_err("initializing the {0} subsystem".format(s))


def quit():
Expand Down
37 changes: 32 additions & 5 deletions sdl2/test/sdl2ext_test.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import sys
import pytest
import sdl2
from sdl2 import ext as sdl2ext
from sdl2 import SDL_WasInit, SDL_INIT_VIDEO, SDL_FlushEvent, SDL_USEREVENT, \
from sdl2 import SDL_Quit, SDL_WasInit, SDL_FlushEvent, SDL_USEREVENT, \
SDL_FIRSTEVENT, SDL_LASTEVENT, SDL_Event, SDL_UserEvent, SDL_PushEvent

@pytest.fixture(scope="module")
def with_sdl_ext():
if SDL_WasInit(0) != 0:
SDL_Quit()
sdl2ext.init()
yield
sdl2ext.quit()
Expand All @@ -18,15 +21,39 @@ def test_init_quit():
sdl2ext.init()
except sdl2ext.SDLError:
raise pytest.skip('Video subsystem not supported')
assert SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO
assert SDL_WasInit(sdl2.SDL_INIT_VIDEO) == sdl2.SDL_INIT_VIDEO
assert SDL_WasInit(sdl2.SDL_INIT_EVENTS) == sdl2.SDL_INIT_EVENTS
sdl2ext.quit()
assert SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO
assert SDL_WasInit(sdl2.SDL_INIT_VIDEO) != sdl2.SDL_INIT_VIDEO
sdl2ext.init()
sdl2ext.init()
sdl2ext.init()
assert SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO
assert SDL_WasInit(sdl2.SDL_INIT_VIDEO) == sdl2.SDL_INIT_VIDEO
sdl2ext.quit()
assert SDL_WasInit(sdl2.SDL_INIT_VIDEO) != sdl2.SDL_INIT_VIDEO

# Test initializing other subsystems
sdl2ext.init(video=False, events=True)
assert SDL_WasInit(sdl2.SDL_INIT_VIDEO) != sdl2.SDL_INIT_VIDEO
assert SDL_WasInit(sdl2.SDL_INIT_EVENTS) == sdl2.SDL_INIT_EVENTS
sdl2ext.init(video=True, audio=True, timer=True)
assert SDL_WasInit(sdl2.SDL_INIT_VIDEO) == sdl2.SDL_INIT_VIDEO
assert SDL_WasInit(sdl2.SDL_INIT_AUDIO) == sdl2.SDL_INIT_AUDIO
assert SDL_WasInit(sdl2.SDL_INIT_TIMER) == sdl2.SDL_INIT_TIMER
sdl2ext.init(joystick=True, haptic=True)
assert SDL_WasInit(sdl2.SDL_INIT_VIDEO) == sdl2.SDL_INIT_VIDEO
assert SDL_WasInit(sdl2.SDL_INIT_JOYSTICK) == sdl2.SDL_INIT_JOYSTICK
assert SDL_WasInit(sdl2.SDL_INIT_HAPTIC) == sdl2.SDL_INIT_HAPTIC
assert SDL_WasInit(sdl2.SDL_INIT_GAMECONTROLLER) != sdl2.SDL_INIT_GAMECONTROLLER
sdl2ext.init(controller=True)
assert SDL_WasInit(sdl2.SDL_INIT_GAMECONTROLLER) == sdl2.SDL_INIT_GAMECONTROLLER
if sdl2.dll.version < 2009:
with pytest.raises(RuntimeError):
sdl2ext.init(sensor=True)
else:
sdl2ext.init(sensor=True)
assert SDL_WasInit(sdl2.SDL_INIT_SENSOR) == sdl2.SDL_INIT_SENSOR
sdl2ext.quit()
assert SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO

def test_get_events(with_sdl_ext):
SDL_FlushEvent(SDL_FIRSTEVENT, SDL_LASTEVENT)
Expand Down

0 comments on commit 425acc4

Please sign in to comment.