Mercurial > touhou
changeset 455:6864a38b2413
Make pytouhou.lib.sdl cimportable, and convert pytouhou.ui.window.* to extension types.
| author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
|---|---|
| date | Mon, 02 Sep 2013 22:16:38 +0200 |
| parents | a502887557ac |
| children | cae1ae9de430 |
| files | pytouhou/lib/_sdl.pxd pytouhou/lib/sdl.pxd pytouhou/lib/sdl.pyx pytouhou/ui/anmrenderer.pyx pytouhou/ui/gamerunner.pyx pytouhou/ui/music.py pytouhou/ui/music.pyx pytouhou/ui/texture.pyx pytouhou/ui/window.pyx setup.py |
| diffstat | 10 files changed, 408 insertions(+), 313 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pytouhou/lib/_sdl.pxd Mon Sep 02 22:16:38 2013 +0200 @@ -0,0 +1,166 @@ +# -*- encoding: utf-8 -*- +## +## Copyright (C) 2013 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + +cdef extern from "SDL.h" nogil: + ctypedef unsigned int Uint32 + ctypedef unsigned short Uint16 + ctypedef unsigned char Uint8 + + int SDL_INIT_VIDEO + + int SDL_Init(Uint32 flags) + void SDL_Quit() + + +IF UNAME_SYSNAME == "Windows": + cdef extern from "SDL_main.h" nogil: + void SDL_SetMainReady() + + +cdef extern from "SDL_error.h" nogil: + const char *SDL_GetError() + + +cdef extern from "SDL_video.h" nogil: + ctypedef enum SDL_GLattr: + SDL_GL_CONTEXT_MAJOR_VERSION + SDL_GL_CONTEXT_MINOR_VERSION + SDL_GL_DOUBLEBUFFER + SDL_GL_DEPTH_SIZE + + ctypedef enum SDL_WindowFlags: + SDL_WINDOWPOS_CENTERED + SDL_WINDOW_OPENGL + SDL_WINDOW_SHOWN + + ctypedef struct SDL_Window: + pass + + ctypedef void *SDL_GLContext + + int SDL_GL_SetAttribute(SDL_GLattr attr, int value) + SDL_Window *SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) + SDL_GLContext SDL_GL_CreateContext(SDL_Window *window) + void SDL_GL_SwapWindow(SDL_Window *window) + void SDL_GL_DeleteContext(SDL_GLContext context) + void SDL_DestroyWindow(SDL_Window *window) + + void SDL_SetWindowSize(SDL_Window *window, int w, int h) + + +cdef extern from "SDL_scancode.h" nogil: + ctypedef enum SDL_Scancode: + SDL_SCANCODE_Z + SDL_SCANCODE_X + SDL_SCANCODE_LSHIFT + SDL_SCANCODE_UP + SDL_SCANCODE_DOWN + SDL_SCANCODE_LEFT + SDL_SCANCODE_RIGHT + SDL_SCANCODE_LCTRL + SDL_SCANCODE_ESCAPE + + +cdef extern from "SDL_events.h" nogil: + ctypedef enum SDL_EventType: + SDL_KEYDOWN + SDL_QUIT + + ctypedef struct SDL_Keysym: + SDL_Scancode scancode + + ctypedef struct SDL_KeyboardEvent: + Uint32 type + SDL_Keysym keysym + + ctypedef union SDL_Event: + Uint32 type + SDL_KeyboardEvent key + + int SDL_PollEvent(SDL_Event *event) + + +cdef extern from "SDL_keyboard.h" nogil: + const Uint8 *SDL_GetKeyboardState(int *numkeys) + + +cdef extern from "SDL_timer.h" nogil: + Uint32 SDL_GetTicks() + void SDL_Delay(Uint32 ms) + + +cdef extern from "SDL_rect.h" nogil: + ctypedef struct SDL_Rect: + int x, y + int w, h + + +cdef extern from "SDL_surface.h" nogil: + ctypedef struct SDL_Surface: + int w, h + unsigned char *pixels + + void SDL_FreeSurface(SDL_Surface *surface) + int SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect) + SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) + + +cdef extern from "SDL_rwops.h" nogil: + ctypedef struct SDL_RWops: + pass + + SDL_RWops *SDL_RWFromConstMem(const void *mem, int size) + int SDL_RWclose(SDL_RWops *context) + + +cdef extern from "SDL_image.h" nogil: + int IMG_INIT_PNG + + int IMG_Init(int flags) + void IMG_Quit() + SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) + + +cdef extern from "SDL_mixer.h" nogil: + ctypedef enum: + MIX_DEFAULT_FORMAT + + ctypedef struct Mix_Music: + pass + + ctypedef struct Mix_Chunk: + pass + + int Mix_Init(int flags) + void Mix_Quit() + + int Mix_OpenAudio(int frequency, Uint16 format_, int channels, int chunksize) + void Mix_CloseAudio() + + int Mix_AllocateChannels(int numchans) + + Mix_Music *Mix_LoadMUS(const char *filename) + Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc) + + void Mix_FreeMusic(Mix_Music *music) + void Mix_FreeChunk(Mix_Chunk *chunk) + + int Mix_PlayMusic(Mix_Music *music, int loops) + #int Mix_SetLoopPoints(Mix_Music *music, double start, double end) + + int Mix_Volume(int channel, int volume) + int Mix_VolumeChunk(Mix_Chunk *chunk, int volume) + int Mix_VolumeMusic(int volume) + + int Mix_PlayChannel(int channel, Mix_Chunk *chunk, int loops)
--- a/pytouhou/lib/sdl.pxd Sat Aug 31 07:39:04 2013 +0200 +++ b/pytouhou/lib/sdl.pxd Mon Sep 02 22:16:38 2013 +0200 @@ -12,155 +12,89 @@ ## GNU General Public License for more details. ## -cdef extern from "SDL.h": - ctypedef unsigned int Uint32 - ctypedef unsigned short Uint16 - ctypedef unsigned char Uint8 - - int SDL_INIT_VIDEO - - int SDL_Init(Uint32 flags) - void SDL_Quit() - - -IF UNAME_SYSNAME == "Windows": - cdef extern from "SDL_main.h": - void SDL_SetMainReady() - - -cdef extern from "SDL_error.h": - const char *SDL_GetError() +from _sdl cimport * -cdef extern from "SDL_video.h": - ctypedef enum SDL_GLattr: - SDL_GL_CONTEXT_MAJOR_VERSION - SDL_GL_CONTEXT_MINOR_VERSION - SDL_GL_DOUBLEBUFFER - SDL_GL_DEPTH_SIZE +cdef Uint32 INIT_VIDEO +cdef Uint32 INIT_PNG - ctypedef enum SDL_WindowFlags: - SDL_WINDOWPOS_CENTERED - SDL_WINDOW_OPENGL - SDL_WINDOW_SHOWN +cdef SDL_GLattr GL_CONTEXT_MAJOR_VERSION +cdef SDL_GLattr GL_CONTEXT_MINOR_VERSION +cdef SDL_GLattr GL_DOUBLEBUFFER +cdef SDL_GLattr GL_DEPTH_SIZE + +cdef SDL_WindowFlags WINDOWPOS_CENTERED +cdef SDL_WindowFlags WINDOW_OPENGL +cdef SDL_WindowFlags WINDOW_SHOWN - ctypedef struct SDL_Window: - pass - - ctypedef void *SDL_GLContext +#TODO: should be SDL_Scancode, but Cython doesn’t allow enum for array indexing. +cdef long SCANCODE_Z +cdef long SCANCODE_X +cdef long SCANCODE_LSHIFT +cdef long SCANCODE_UP +cdef long SCANCODE_DOWN +cdef long SCANCODE_LEFT +cdef long SCANCODE_RIGHT +cdef long SCANCODE_LCTRL +cdef long SCANCODE_ESCAPE - int SDL_GL_SetAttribute(SDL_GLattr attr, int value) - SDL_Window *SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) - SDL_GLContext SDL_GL_CreateContext(SDL_Window *window) - void SDL_GL_SwapWindow(SDL_Window *window) - void SDL_GL_DeleteContext(SDL_GLContext context) - void SDL_DestroyWindow(SDL_Window *window) +cdef SDL_EventType KEYDOWN +cdef SDL_EventType QUIT - void SDL_SetWindowSize(SDL_Window *window, int w, int h) +cdef Uint16 DEFAULT_FORMAT -cdef extern from "SDL_scancode.h": - ctypedef enum SDL_Scancode: - SDL_SCANCODE_Z - SDL_SCANCODE_X - SDL_SCANCODE_LSHIFT - SDL_SCANCODE_UP - SDL_SCANCODE_DOWN - SDL_SCANCODE_LEFT - SDL_SCANCODE_RIGHT - SDL_SCANCODE_LCTRL - SDL_SCANCODE_ESCAPE +cdef class Window: + cdef SDL_Window *window + cdef SDL_GLContext context + + cdef void gl_create_context(self) except * + cdef void gl_swap_window(self) nogil + cdef void set_window_size(self, int width, int height) nogil -cdef extern from "SDL_events.h": - ctypedef enum SDL_EventType: - SDL_KEYDOWN - SDL_QUIT - - ctypedef struct SDL_Keysym: - SDL_Scancode scancode +cdef class Surface: + cdef SDL_Surface *surface - ctypedef struct SDL_KeyboardEvent: - Uint32 type - SDL_Keysym keysym - - ctypedef union SDL_Event: - Uint32 type - SDL_KeyboardEvent key - - int SDL_PollEvent(SDL_Event *event) + cdef void blit(self, Surface other) except * + cdef void set_alpha(self, Surface alpha_surface) nogil -cdef extern from "SDL_keyboard.h": - const Uint8 *SDL_GetKeyboardState(int *numkeys) - +cdef class Music: + cdef Mix_Music *music -cdef extern from "SDL_timer.h": - Uint32 SDL_GetTicks() - void SDL_Delay(Uint32 ms) + cdef void play(self, int loops) nogil + cdef void set_loop_points(self, double start, double end) nogil -cdef extern from "SDL_rect.h": - ctypedef struct SDL_Rect: - int x, y - int w, h - +cdef class Chunk: + cdef Mix_Chunk *chunk -cdef extern from "SDL_surface.h": - ctypedef struct SDL_Surface: - int w, h - unsigned char *pixels - - void SDL_FreeSurface(SDL_Surface *surface) - int SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect) - SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) + cdef void play(self, int channel, int loops) nogil + cdef void set_volume(self, float volume) nogil -cdef extern from "SDL_rwops.h": - ctypedef struct SDL_RWops: - pass - - SDL_RWops *SDL_RWFromConstMem(const void *mem, int size) - int SDL_RWclose(SDL_RWops *context) - - -cdef extern from "SDL_image.h": - int IMG_INIT_PNG +cdef void init(Uint32 flags) except * +cdef void img_init(Uint32 flags) except * +cdef void mix_init(int flags) except * - int IMG_Init(int flags) - void IMG_Quit() - SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) - - -cdef extern from "SDL_mixer.h": - ctypedef enum: - MIX_DEFAULT_FORMAT - - ctypedef struct Mix_Music: - pass +IF UNAME_SYSNAME == "Windows": + cdef void set_main_ready() - ctypedef struct Mix_Chunk: - pass - - int Mix_Init(int flags) - void Mix_Quit() - - int Mix_OpenAudio(int frequency, Uint16 format_, int channels, int chunksize) - void Mix_CloseAudio() - - int Mix_AllocateChannels(int numchans) - - Mix_Music *Mix_LoadMUS(const char *filename) - Mix_Chunk *Mix_LoadWAV_RW(SDL_RWops *src, int freesrc) - - void Mix_FreeMusic(Mix_Music *music) - void Mix_FreeChunk(Mix_Chunk *chunk) - - int Mix_PlayMusic(Mix_Music *music, int loops) - #int Mix_SetLoopPoints(Mix_Music *music, double start, double end) - - int Mix_Volume(int channel, int volume) - int Mix_VolumeChunk(Mix_Chunk *chunk, int volume) - int Mix_VolumeMusic(int volume) - - int Mix_PlayChannel(int channel, Mix_Chunk *chunk, int loops) +cdef void quit() nogil +cdef void img_quit() nogil +cdef void mix_quit() nogil +cdef void gl_set_attribute(SDL_GLattr attr, int value) except * +cdef list poll_events() +cdef const Uint8* get_keyboard_state() nogil +cdef Surface load_png(file_) +cdef Surface create_rgb_surface(int width, int height, int depth, Uint32 rmask=*, Uint32 gmask=*, Uint32 bmask=*, Uint32 amask=*) +cdef void mix_open_audio(int frequency, Uint16 format_, int channels, int chunksize) except * +cdef void mix_close_audio() nogil +cdef void mix_allocate_channels(int numchans) except * +cdef int mix_volume(int channel, float volume) nogil +cdef int mix_volume_music(float volume) nogil +cdef Music load_music(const char *filename) +cdef Chunk load_chunk(file_) +cdef Uint32 get_ticks() nogil +cdef void delay(Uint32 ms) nogil
--- a/pytouhou/lib/sdl.pyx Sat Aug 31 07:39:04 2013 +0200 +++ b/pytouhou/lib/sdl.pyx Mon Sep 02 22:16:38 2013 +0200 @@ -45,56 +45,43 @@ cdef class Window: - cdef SDL_Window *window - cdef SDL_GLContext context - def __init__(self, const char *title, int x, int y, int w, int h, Uint32 flags): self.window = SDL_CreateWindow(title, x, y, w, h, flags) if self.window == NULL: raise SDLError(SDL_GetError()) - def destroy_window(self): - SDL_DestroyWindow(self.window) + def __dealloc__(self): + if self.context != NULL: + SDL_GL_DeleteContext(self.context) + if self.window != NULL: + SDL_DestroyWindow(self.window) - def gl_create_context(self): + cdef void gl_create_context(self) except *: self.context = SDL_GL_CreateContext(self.window) if self.context == NULL: raise SDLError(SDL_GetError()) - def gl_swap_window(self): + cdef void gl_swap_window(self) nogil: SDL_GL_SwapWindow(self.window) - def gl_delete_context(self): - SDL_GL_DeleteContext(self.context) - - def set_window_size(self, width, height): + cdef void set_window_size(self, int width, int height) nogil: SDL_SetWindowSize(self.window, width, height) cdef class Surface: - cdef SDL_Surface *surface - def __dealloc__(self): if self.surface != NULL: SDL_FreeSurface(self.surface) - property width: - def __get__(self): - return self.surface.w - - property height: - def __get__(self): - return self.surface.h - property pixels: def __get__(self): return bytes(self.surface.pixels[:self.surface.w * self.surface.h * 4]) - def blit(self, Surface other): + cdef void blit(self, Surface other): if SDL_BlitSurface(other.surface, NULL, self.surface, NULL) < 0: raise SDLError(SDL_GetError()) - def set_alpha(self, Surface alpha_surface): + cdef void set_alpha(self, Surface alpha_surface) nogil: nb_pixels = self.surface.w * self.surface.h image = self.surface.pixels alpha = alpha_surface.surface.pixels @@ -105,73 +92,68 @@ cdef class Music: - cdef Mix_Music *music - def __dealloc__(self): if self.music != NULL: Mix_FreeMusic(self.music) - def play(self, int loops): + cdef void play(self, int loops) nogil: Mix_PlayMusic(self.music, loops) - def set_loop_points(self, double start, double end): + cdef void set_loop_points(self, double start, double end) nogil: #Mix_SetLoopPoints(self.music, start, end) pass cdef class Chunk: - cdef Mix_Chunk *chunk - def __dealloc__(self): if self.chunk != NULL: Mix_FreeChunk(self.chunk) - property volume: - def __set__(self, float volume): - Mix_VolumeChunk(self.chunk, int(volume * 128)) - - def play(self, int channel, int loops): + cdef void play(self, int channel, int loops) nogil: Mix_PlayChannel(channel, self.chunk, loops) + cdef void set_volume(self, float volume) nogil: + Mix_VolumeChunk(self.chunk, int(volume * 128)) -def init(Uint32 flags): + +cdef void init(Uint32 flags) except *: if SDL_Init(flags) < 0: raise SDLError(SDL_GetError()) -def img_init(Uint32 flags): +cdef void img_init(Uint32 flags) except *: if IMG_Init(flags) != flags: raise SDLError(SDL_GetError()) -def mix_init(int flags): +cdef void mix_init(int flags) except *: if Mix_Init(flags) != flags: raise SDLError(SDL_GetError()) IF UNAME_SYSNAME == "Windows": - def set_main_ready(): + cdef void set_main_ready(): SDL_SetMainReady() -def quit(): +cdef void quit() nogil: SDL_Quit() -def img_quit(): +cdef void img_quit() nogil: IMG_Quit() -def mix_quit(): +cdef void mix_quit() nogil: Mix_Quit() -def gl_set_attribute(SDL_GLattr attr, int value): +cdef void gl_set_attribute(SDL_GLattr attr, int value) except *: if SDL_GL_SetAttribute(attr, value) < 0: raise SDLError(SDL_GetError()) -def poll_events(): +cdef list poll_events(): cdef SDL_Event event ret = [] while SDL_PollEvent(&event): @@ -182,15 +164,11 @@ return ret -def get_keyboard_state(): - cdef int numkeys - cdef bint k - cdef const Uint8 *state - state = SDL_GetKeyboardState(&numkeys) - return tuple([k is not False for k in state[:numkeys]]) +cdef const Uint8* get_keyboard_state() nogil: + return SDL_GetKeyboardState(NULL) -def load_png(file_): +cdef Surface load_png(file_): data = file_.read() rwops = SDL_RWFromConstMem(<char*>data, len(data)) surface = Surface() @@ -201,7 +179,7 @@ return surface -def create_rgb_surface(int width, int height, int depth, Uint32 rmask=0, Uint32 gmask=0, Uint32 bmask=0, Uint32 amask=0): +cdef Surface create_rgb_surface(int width, int height, int depth, Uint32 rmask=0, Uint32 gmask=0, Uint32 bmask=0, Uint32 amask=0): surface = Surface() surface.surface = SDL_CreateRGBSurface(0, width, height, depth, rmask, gmask, bmask, amask) if surface.surface == NULL: @@ -209,29 +187,29 @@ return surface -def mix_open_audio(int frequency, Uint16 format_, int channels, int chunksize): +cdef void mix_open_audio(int frequency, Uint16 format_, int channels, int chunksize) except *: if Mix_OpenAudio(frequency, format_, channels, chunksize) < 0: raise SDLError(SDL_GetError()) -def mix_close_audio(): +cdef void mix_close_audio() nogil: Mix_CloseAudio() -def mix_allocate_channels(int numchans): +cdef void mix_allocate_channels(int numchans) except *: if Mix_AllocateChannels(numchans) != numchans: raise SDLError(SDL_GetError()) -def mix_volume(int channel, float volume): +cdef int mix_volume(int channel, float volume) nogil: return Mix_Volume(channel, int(volume * 128)) -def mix_volume_music(float volume): +cdef int mix_volume_music(float volume) nogil: return Mix_VolumeMusic(int(volume * 128)) -def load_music(const char *filename): +cdef Music load_music(const char *filename): music = Music() music.music = Mix_LoadMUS(filename) if music.music == NULL: @@ -239,7 +217,7 @@ return music -def load_chunk(file_): +cdef Chunk load_chunk(file_): cdef SDL_RWops *rwops chunk = Chunk() data = file_.read() @@ -250,9 +228,9 @@ return chunk -def get_ticks(): +cdef Uint32 get_ticks() nogil: return SDL_GetTicks() -def delay(Uint32 ms): +cdef void delay(Uint32 ms) nogil: SDL_Delay(ms)
--- a/pytouhou/ui/anmrenderer.pyx Sat Aug 31 07:39:04 2013 +0200 +++ b/pytouhou/ui/anmrenderer.pyx Mon Sep 02 22:16:38 2013 +0200 @@ -24,7 +24,7 @@ from .renderer import Renderer from .shaders.eosd import GameShader -from pytouhou.lib import sdl +from pytouhou.lib cimport sdl logger = get_logger(__name__)
--- a/pytouhou/ui/gamerunner.pyx Sat Aug 31 07:39:04 2013 +0200 +++ b/pytouhou/ui/gamerunner.pyx Mon Sep 02 22:16:38 2013 +0200 @@ -12,7 +12,7 @@ ## GNU General Public License for more details. ## -from pytouhou.lib import sdl +from pytouhou.lib cimport sdl from pytouhou.lib.opengl cimport \ (glMatrixMode, glEnable, glDisable, glViewport, glScissor, @@ -179,7 +179,7 @@ def render_interface(self): elements = [] interface = self.game.interface - interface.labels['framerate'].set_text('%.2ffps' % self.window.clock.get_fps()) + interface.labels['framerate'].set_text('%.2ffps' % self.window.get_fps()) if self.use_fixed_pipeline: glMatrixMode(GL_MODELVIEW)
--- a/pytouhou/ui/music.py Sat Aug 31 07:39:04 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -# -*- encoding: utf-8 -*- -## -## Copyright (C) 2012 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published -## by the Free Software Foundation; version 3 only. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## - - -from os.path import join -from glob import glob -from pytouhou.lib import sdl -from pytouhou.utils.helpers import get_logger - -logger = get_logger(__name__) - - -class MusicPlayer(object): - def __init__(self, resource_loader, bgms): - self.bgms = [] - for bgm in bgms: - if not bgm: - self.bgms.append(None) - continue - posname = bgm[1].replace('bgm/', '').replace('.mid', '.pos') - try: - track = resource_loader.get_track(posname) - except KeyError: - self.bgms.append(None) - logger.warn(u'Music description “%s” not found.', posname) - continue - globname = join(resource_loader.game_dir, bgm[1]).replace('.mid', '.*') - filenames = glob(globname) - for filename in reversed(filenames): - try: - source = sdl.load_music(filename) - except sdl.SDLError as error: - logger.debug(u'Music file “%s” unreadable: %s', filename, error) - continue - else: - source.set_loop_points(track.start / 44100., track.end / 44100.) #TODO: retrieve the sample rate from the actual track. - self.bgms.append(source) - logger.debug(u'Music file “%s” opened.', filename) - break - else: - self.bgms.append(None) - logger.warn(u'No working music file for “%s”, disabling bgm.', globname) - - def play(self, index): - bgm = self.bgms[index] - if bgm: - bgm.play(-1) - - -class SFXPlayer(object): - def __init__(self, loader, volume=.42): - self.loader = loader - self.channels = {} - self.sounds = {} - self.volume = volume - self.next_channel = 0 - - def get_channel(self, name): - if name not in self.channels: - self.channels[name] = self.next_channel - self.next_channel += 1 - return self.channels[name] - - def get_sound(self, name): - if name not in self.sounds: - wave_file = self.loader.get_file(name) - self.sounds[name] = sdl.load_chunk(wave_file) - self.sounds[name].volume = self.volume - return self.sounds[name] - - def play(self, name, volume=None): - sound = self.get_sound(name) - channel = self.get_channel(name) - if volume: - sdl.mix_volume(channel, volume) - sound.play(channel, 0) - - -class NullPlayer(object): - def __init__(self, loader=None, bgms=None): - pass - - def play(self, name, volume=None): - pass
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pytouhou/ui/music.pyx Mon Sep 02 22:16:38 2013 +0200 @@ -0,0 +1,98 @@ +# -*- encoding: utf-8 -*- +## +## Copyright (C) 2012 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + + +from os.path import join +from glob import glob +from pytouhou.lib cimport sdl +from pytouhou.utils.helpers import get_logger + +logger = get_logger(__name__) + + +class MusicPlayer(object): + def __init__(self, resource_loader, bgms): + self.bgms = [] + for bgm in bgms: + if not bgm: + self.bgms.append(None) + continue + posname = bgm[1].replace('bgm/', '').replace('.mid', '.pos') + try: + track = resource_loader.get_track(posname) + except KeyError: + self.bgms.append(None) + logger.warn(u'Music description “%s” not found.', posname) + continue + globname = join(resource_loader.game_dir, bgm[1]).replace('.mid', '.*') + filenames = glob(globname) + for filename in reversed(filenames): + try: + source = sdl.load_music(filename) + except sdl.SDLError as error: + logger.debug(u'Music file “%s” unreadable: %s', filename, error) + continue + else: + source.set_loop_points(track.start / 44100., track.end / 44100.) #TODO: retrieve the sample rate from the actual track. + self.bgms.append(source) + logger.debug(u'Music file “%s” opened.', filename) + break + else: + self.bgms.append(None) + logger.warn(u'No working music file for “%s”, disabling bgm.', globname) + + def play(self, index): + cdef sdl.Music bgm + bgm = self.bgms[index] + if bgm: + bgm.play(-1) + + +class SFXPlayer(object): + def __init__(self, loader, volume=.42): + self.loader = loader + self.channels = {} + self.sounds = {} + self.volume = volume + self.next_channel = 0 + + def get_channel(self, name): + if name not in self.channels: + self.channels[name] = self.next_channel + self.next_channel += 1 + return self.channels[name] + + def get_sound(self, name): + if name not in self.sounds: + wave_file = self.loader.get_file(name) + chunk = sdl.load_chunk(wave_file) + chunk.set_volume(self.volume) + self.sounds[name] = chunk + return self.sounds[name] + + def play(self, name, volume=None): + cdef sdl.Chunk sound + sound = self.get_sound(name) + channel = self.get_channel(name) + if volume: + sdl.mix_volume(channel, volume) + sound.play(channel, 0) + + +class NullPlayer(object): + def __init__(self, loader=None, bgms=None): + pass + + def play(self, name, volume=None): + pass
--- a/pytouhou/ui/texture.pyx Sat Aug 31 07:39:04 2013 +0200 +++ b/pytouhou/ui/texture.pyx Mon Sep 02 22:16:38 2013 +0200 @@ -19,7 +19,7 @@ glGenTextures, glBindTexture, glTexImage2D, GL_TEXTURE_2D, GLuint, glDeleteTextures) -from pytouhou.lib.sdl import load_png, create_rgb_surface +from pytouhou.lib.sdl cimport load_png, create_rgb_surface from pytouhou.formats.thtx import Texture #TODO: perhaps define that elsewhere? import os @@ -52,7 +52,7 @@ cdef decode_png(loader, first_name, secondary_name): image_file = load_png(loader.get_file(os.path.basename(first_name))) - width, height = image_file.width, image_file.height + width, height = image_file.surface.w, image_file.surface.h # Support only 32 bits RGBA. Paletted surfaces are awful to work with. #TODO: verify it doesn’t blow up on big-endian systems. @@ -61,7 +61,7 @@ if secondary_name: alpha_file = load_png(loader.get_file(os.path.basename(secondary_name))) - assert (width == alpha_file.width and height == alpha_file.height) + assert (width == alpha_file.surface.w and height == alpha_file.surface.h) new_alpha_file = create_rgb_surface(width, height, 24) new_alpha_file.blit(alpha_file)
--- a/pytouhou/ui/window.pyx Sat Aug 31 07:39:04 2013 +0200 +++ b/pytouhou/ui/window.pyx Mon Sep 02 22:16:38 2013 +0200 @@ -13,7 +13,7 @@ ## -from pytouhou.lib import sdl +from pytouhou.lib cimport sdl from pytouhou.lib.opengl cimport \ (glEnable, glHint, glEnableClientState, GL_TEXTURE_2D, GL_BLEND, @@ -24,8 +24,11 @@ from pytouhou.lib.opengl cimport glewInit -class Clock: - def __init__(self, fps=None): +cdef class Clock: + cdef long _target_fps, _ref_tick, _ref_frame, _fps_tick, _fps_frame + cdef double _rate + + def __init__(self, long fps=-1): self._target_fps = 0 self._ref_tick = 0 self._ref_frame = 0 @@ -35,17 +38,17 @@ self.set_target_fps(fps) - def set_target_fps(self, fps): + cdef void set_target_fps(self, long fps) nogil: self._target_fps = fps self._ref_tick = 0 self._fps_tick = 0 - def get_fps(self): + cdef double get_fps(self) nogil: return self._rate - def tick(self): + cdef void tick(self) nogil except *: current = sdl.get_ticks() if not self._ref_tick: @@ -66,7 +69,7 @@ target_tick = self._ref_tick if self._target_fps: - target_tick += int(self._ref_frame * 1000 / self._target_fps) + target_tick += <long>(self._ref_frame * 1000 / self._target_fps) if current <= target_tick: sdl.delay(target_tick - current) @@ -76,9 +79,16 @@ -class Window(object): - def __init__(self, size=None, double_buffer=True, fps_limit=60, - fixed_pipeline=False, sound=True): +cdef class Window: + cdef sdl.Window win + cdef long fps_limit + cdef public long width, height + cdef public bint use_fixed_pipeline + cdef object runner + cdef Clock clock + + def __init__(self, size=None, bint double_buffer=True, long fps_limit=-1, + bint fixed_pipeline=False, bint sound=True): self.fps_limit = fps_limit self.use_fixed_pipeline = fixed_pipeline self.runner = None @@ -95,7 +105,7 @@ sdl.gl_set_attribute(sdl.GL_DOUBLEBUFFER, int(double_buffer)) sdl.gl_set_attribute(sdl.GL_DEPTH_SIZE, 24) - self.width, self.height = size if size else (640, 480) + self.width, self.height = size if size is not None else (640, 480) self.win = sdl.Window('PyTouhou', sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, @@ -125,16 +135,17 @@ self.clock = Clock(self.fps_limit) - def set_size(self, width, height): + cdef void set_size(self, int width, int height) nogil: self.win.set_window_size(width, height) - def set_runner(self, runner): + cpdef set_runner(self, runner=None): self.runner = runner - runner.start() + if runner is not None: + runner.start() - def run(self): + cpdef run(self): try: while self.run_frame(): pass @@ -142,17 +153,20 @@ self.runner.finish() - def run_frame(self): - if self.runner: + cdef bint run_frame(self) except? False: + cdef bint running = False + if self.runner is not None: running = self.runner.update() self.win.gl_swap_window() self.clock.tick() return running + cpdef double get_fps(self): + return self.clock.get_fps() + + def __dealloc__(self): - self.win.gl_delete_context() - self.win.destroy_window() sdl.mix_close_audio() sdl.mix_quit() sdl.img_quit()
--- a/setup.py Sat Aug 31 07:39:04 2013 +0200 +++ b/setup.py Mon Sep 02 22:16:38 2013 +0200 @@ -45,8 +45,8 @@ compile_args = get_arguments('--cflags', SDL_LIBRARIES) link_args = get_arguments('--libs', SDL_LIBRARIES) elif extension_name.startswith('pytouhou.ui.'): #XXX - compile_args = get_arguments('--cflags', ['gl']) - link_args = get_arguments('--libs', ['gl']) + compile_args = get_arguments('--cflags', ['gl'] + SDL_LIBRARIES) + link_args = get_arguments('--libs', ['gl'] + SDL_LIBRARIES) else: compile_args = None link_args = None
