diff --git a/demos/basic/main.py b/demos/basic/main.py index 7d5f250a..f601386e 100644 --- a/demos/basic/main.py +++ b/demos/basic/main.py @@ -42,7 +42,6 @@ def __init__(self, sound_path, music_path): if music_path: self.music = Music(music_path) - self.music.play() else: self.music = None @@ -65,6 +64,8 @@ def update(self, dt): self.engine.quit() keyboard = event.keyboard + audio = event.audio + if keyboard: if keyboard.is_pressing(Keycode.q): self.engine.quit() @@ -87,6 +88,44 @@ def update(self, dt): self.engine.virtual_resolution_mode)) elif keyboard.is_pressing(Keycode.p): print("Mouse position: {}".format(self.input.mouse.get_position())) + elif keyboard.is_pressing(Keycode.num_9): + print("Decreasing master volume") + self.engine.audio.master_volume -= 0.1 + print("Master volume: {}".format(self.engine.audio.master_volume)) + elif keyboard.is_pressing(Keycode.num_0): + print("Increasing master volume") + self.engine.audio.master_volume += 0.1 + print("Master volume: {}".format(self.engine.audio.master_volume)) + elif keyboard.is_pressing(Keycode.num_7): + print("Decreasing master music volume") + self.engine.audio.master_music_volume -= 0.1 + print("Master music volume: {}".format(self.engine.audio.master_music_volume)) + elif keyboard.is_pressing(Keycode.num_8): + print("Increasing master music volume") + self.engine.audio.master_music_volume += 0.1 + print("Master music volume: {}".format(self.engine.audio.master_music_volume)) + elif keyboard.is_pressing(Keycode.num_5): + print("Decreasing master sound volume") + self.engine.audio.master_sound_volume -= 0.1 + print("Master sound volume: {}".format(self.engine.audio.master_sound_volume)) + elif keyboard.is_pressing(Keycode.num_6): + print("Increasing master sound volume") + self.engine.audio.master_sound_volume += 0.1 + print("Master sound volume: {}".format(self.engine.audio.master_sound_volume)) + elif keyboard.is_pressing(Keycode.x): + self.music.play() + print("Playing music") + elif keyboard.is_pressing(Keycode.c): + ret = self.music.pause() + print("Pausing music, success: {}".format(ret)) + elif keyboard.is_pressing(Keycode.v): + ret = self.music.resume() + print("Resuming music, success: {}".format(ret)) + elif keyboard.is_pressing(Keycode.b): + ret = self.music.stop() + print("Stopping music, success: {}".format(ret)) + elif audio and audio.music_finished: + print("Music finished!") if __name__ == '__main__': diff --git a/kaa/audio.pxi b/kaa/audio.pxi index c9e023d6..80d34f2f 100644 --- a/kaa/audio.pxi +++ b/kaa/audio.pxi @@ -1,6 +1,21 @@ -from .kaacore.audio cimport CSound, CMusic +from enum import IntEnum +cimport cython +from .kaacore.engine cimport get_c_engine +from .kaacore.audio cimport CAudioManager, CSound, CMusic, CMusicState + +DEF SOUND_FREELIST_SIZE = 30 +DEF MUSIC_FREELIST_SIZE = 10 + + +class MusicState(IntEnum): + playing = CMusicState.playing + paused = CMusicState.paused + stopped = CMusicState.stopped + + +@cython.freelist(SOUND_FREELIST_SIZE) cdef class Sound: cdef CSound c_sound @@ -10,6 +25,14 @@ cdef class Sound: def __init__(self, str sound_filepath, double volume=1.): self._attach_c_sound(CSound.load(sound_filepath.encode(), volume)) + @property + def volume(self): + return self.c_sound.volume() + + @volume.setter + def volume(self, double vol): + self.c_sound.volume(vol) + def play(self, double volume=1.): self.c_sound.play(volume) @@ -20,6 +43,7 @@ cdef Sound get_sound_wrapper(const CSound& c_sound): return sound +@cython.freelist(MUSIC_FREELIST_SIZE) cdef class Music: cdef CMusic c_music @@ -29,11 +53,86 @@ cdef class Music: def __init__(self, str music_filepath, double volume=1.): self._attach_c_music(CMusic.load(music_filepath.encode(), volume)) - def play(self): - self.c_music.play() + @staticmethod + def get_current(): + return get_music_wrapper(CMusic.get_current()) + + @staticmethod + def get_state(): + return MusicState(CMusic.get_state()) + + @property + def volume(self): + return self.c_music.volume() + + @volume.setter + def volume(self, double vol): + self.c_music.volume(vol) + + @property + def is_playing(self): + return self.c_music.is_playing() + + def play(self, double volume=1.): + self.c_music.play(volume) + + @property + def is_paused(self): + return self.c_music.is_paused() + + def pause(self): + return self.c_music.pause() + + def resume(self): + return self.c_music.resume() + + def stop(self): + return self.c_music.stop() cdef Music get_music_wrapper(const CMusic& c_music): cdef Music music = Music.__new__(Music) music._attach_c_music(c_music) return music + + +@cython.final +cdef class _AudioManager: + cdef CAudioManager* _get_c_audio_manager(self): + cdef CEngine* c_engine = get_c_engine() + assert c_engine != NULL + cdef CAudioManager* c_audio_manager = c_engine.audio_manager.get() + assert c_audio_manager != NULL + return c_audio_manager + + @property + def master_volume(self): + return self._get_c_audio_manager().master_volume() + + @master_volume.setter + def master_volume(self, double vol): + self._get_c_audio_manager().master_volume(vol) + + @property + def master_sound_volume(self): + return self._get_c_audio_manager().master_sound_volume() + + @master_sound_volume.setter + def master_sound_volume(self, double vol): + self._get_c_audio_manager().master_sound_volume(vol) + + @property + def master_music_volume(self): + return self._get_c_audio_manager().master_music_volume() + + @master_music_volume.setter + def master_music_volume(self, double vol): + self._get_c_audio_manager().master_music_volume(vol) + + @property + def mixing_channels(self): + return self._get_c_audio_manager().mixing_channels() + + @mixing_channels.setter + def mixing_channels(self, int ch): + self._get_c_audio_manager().mixing_channels(ch) diff --git a/kaa/engine.pxi b/kaa/engine.pxi index 08a2a66b..eaa5bd03 100644 --- a/kaa/engine.pxi +++ b/kaa/engine.pxi @@ -27,10 +27,12 @@ class VirtualResolutionMode(IntEnum): cdef class _Engine: cdef _Window _window cdef _Renderer _renderer + cdef _AudioManager _audio_manager def __init__(self): self._window = _Window() self._renderer = _Renderer() + self._audio_manager = _AudioManager() cdef inline CEngine* _get_c_engine(self): cdef CEngine* c_engine = get_c_engine() @@ -98,6 +100,10 @@ cdef class _Engine: def renderer(self): return self._renderer + @property + def audio(self): + return self._audio_manager + def stop(self): if get_c_engine() == NULL: raise ValueError("Engine is stopped") diff --git a/kaa/input.pxi b/kaa/input.pxi index f38aaa2c..339a4da9 100644 --- a/kaa/input.pxi +++ b/kaa/input.pxi @@ -9,7 +9,7 @@ from .kaacore.input cimport ( CKeycode, CMouseButton, CControllerButton, CControllerAxis, CCompoundControllerAxis, CCompoundEventType, CEventType, CWindowEventType, CSystemEvent, CWindowEvent, CKeyboardEvent, CMouseEvent, - CControllerEvent, CEvent, CInputManager, CSystemManager, + CControllerEvent, CAudioEvent, CEvent, CInputManager, CSystemManager, CKeyboardManager, CMouseManager, CControllerManager, CControllerID ) @@ -336,6 +336,9 @@ class EventType(IntEnum): controller_removed = CEventType.controller_removed controller_remapped = CEventType.controller_remapped + music_finished = CEventType.music_finished + channel_finished = CEventType.channel_finished + class WindowEventType(IntEnum): shown = CWindowEventType.shown, @@ -580,6 +583,19 @@ cdef class ControllerEvent(_BaseEvent): return self.c_event.controller().removed() +@cython.final +cdef class AudioEvent(_BaseEvent): + @staticmethod + cdef AudioEvent create(CEvent c_event): + cdef AudioEvent instance = AudioEvent.__new__(AudioEvent) + instance.c_event = c_event + return instance + + @typed_property(EventType.music_finished) + def music_finished(self): + return self.c_event.audio().music_finished() + + @cython.final cdef class Event(_BaseEvent): def __repr__(self): @@ -616,6 +632,11 @@ cdef class Event(_BaseEvent): if self.c_event.controller(): return ControllerEvent.create(self.c_event) + @property + def audio(self): + if self.c_event.audio(): + return AudioEvent.create(self.c_event) + cdef class _BaseInputManager: cdef CInputManager* c_input_manager diff --git a/kaa/kaacore/audio.pxd b/kaa/kaacore/audio.pxd index 8554c9b9..b2e3359f 100644 --- a/kaa/kaacore/audio.pxd +++ b/kaa/kaacore/audio.pxd @@ -1,4 +1,5 @@ from libcpp cimport bool +from libc.stdint cimport uint16_t from .exceptions cimport raise_py_error @@ -14,6 +15,15 @@ cdef extern from "kaacore/audio.h" nogil: void play(double volume) \ except +raise_py_error + double volume() except +raise_py_error + void volume(const double) except +raise_py_error + + + cdef enum CMusicState "kaacore::MusicState": + playing "kaacore::MusicState::playing", + paused "kaacore::MusicState::paused", + stopped "kaacore::MusicState::stopped", + cdef cppclass CMusic "kaacore::Music": CMusic() @@ -26,7 +36,32 @@ cdef extern from "kaacore/audio.h" nogil: CMusic get_current() \ except +raise_py_error + @staticmethod + CMusicState get_state() \ + except +raise_py_error + + double volume() except +raise_py_error + void volume(const double) except +raise_py_error + bool is_playing() \ except +raise_py_error - void play() \ + void play(double volume) \ except +raise_py_error + + bool is_paused() except +raise_py_error + bool pause() except +raise_py_error + bool resume() except +raise_py_error + bool stop() except +raise_py_error + + cdef cppclass CAudioManager "kaacore::AudioManager": + double master_volume() except +raise_py_error + void master_volume(const double vol) except +raise_py_error + + double master_sound_volume() except +raise_py_error + void master_sound_volume(const double vol) except +raise_py_error + + double master_music_volume() except +raise_py_error + void master_music_volume(const double vol) except +raise_py_error + + uint16_t mixing_channels() except +raise_py_error + void mixing_channels(const uint16_t channels) except +raise_py_error diff --git a/kaa/kaacore/engine.pxd b/kaa/kaacore/engine.pxd index ce8356c2..fc7c4431 100644 --- a/kaa/kaacore/engine.pxd +++ b/kaa/kaacore/engine.pxd @@ -6,6 +6,7 @@ from libc.stdint cimport int32_t, uint64_t from .display cimport CDisplay from .scenes cimport CScene from .window cimport CWindow +from .audio cimport CAudioManager from .renderer cimport CRenderer from .input cimport CInputManager from .exceptions cimport raise_py_error @@ -22,6 +23,7 @@ cdef extern from "kaacore/engine.h" nogil: unique_ptr[CWindow] window unique_ptr[CRenderer] renderer unique_ptr[CInputManager] input_manager + unique_ptr[CAudioManager] audio_manager CScene* scene uint64_t time diff --git a/kaa/kaacore/input.pxd b/kaa/kaacore/input.pxd index a26970c1..6339abea 100644 --- a/kaa/kaacore/input.pxd +++ b/kaa/kaacore/input.pxd @@ -319,7 +319,9 @@ cdef extern from "kaacore/input.h" nogil: controller_button_up "kaacore::EventType::controller_button_up", controller_added "kaacore::EventType::controller_added", controller_removed "kaacore::EventType::controller_removed", - controller_remapped "kaacore::EventType::controller_remapped" + controller_remapped "kaacore::EventType::controller_remapped", + music_finished "kaacore::EventType::music_finished", + channel_finished "kaacore::EventType::channel_finished", cdef enum CWindowEventType "kaacore::WindowEventType": shown "kaacore::WindowEventType::shown", @@ -425,6 +427,10 @@ cdef extern from "kaacore/input.h" nogil: bint axis_motion(CControllerAxis ca) \ except +raise_py_error + cdef cppclass CAudioEvent "kaacore::AudioEvent": + bint music_finished() \ + except +raise_py_error + cdef cppclass CEvent "kaacore::Event": uint32_t type() \ except +raise_py_error @@ -440,6 +446,8 @@ cdef extern from "kaacore/input.h" nogil: except +raise_py_error const CControllerEvent* const controller() \ except +raise_py_error + const CAudioEvent* const audio() \ + except +raise_py_error cdef cppclass CSystemManager "kaacore::InputManager::SystemManager": string get_clipboard_text() \ diff --git a/kaacore b/kaacore index 7ff29968..54e0d04e 160000 --- a/kaacore +++ b/kaacore @@ -1 +1 @@ -Subproject commit 7ff29968ff5a6944af6b2adacffe0c2cd4d5088f +Subproject commit 54e0d04e5b17f872136ef2ed94bfda416652e8d2