From f5cffaf896d237b30ed74ff2c2ae59e4f193f79a Mon Sep 17 00:00:00 2001 From: Starbuck5 <46412508+Starbuck5@users.noreply.github.com> Date: Sun, 16 Jun 2024 23:26:44 -0700 Subject: [PATCH] Fixes for rwobject (now iostream) SDL3 --- src_c/font.c | 8 +++- src_c/imageext.c | 22 +++++++++- src_c/mixer.c | 4 ++ src_c/music.c | 4 ++ src_c/rwobject.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 3 deletions(-) diff --git a/src_c/font.c b/src_c/font.c index 5817e896f6..cae985f1cc 100644 --- a/src_c/font.c +++ b/src_c/font.c @@ -1174,15 +1174,19 @@ font_init(PyFontObject *self, PyObject *args, PyObject *kwds) if (fontsize <= 1) fontsize = 1; - if (rw->size(rw) <= 0) { + if (SDL_RWsize(rw) <= 0) { PyErr_Format(PyExc_ValueError, "Font file object has an invalid file size: %lld", - rw->size(rw)); + SDL_RWsize(rw)); goto error; } Py_BEGIN_ALLOW_THREADS; +#if SDL_VERSION_ATLEAST(3, 0, 0) + font = TTF_OpenFontIO(rw, 1, fontsize); +#else font = TTF_OpenFontRW(rw, 1, fontsize); +#endif Py_END_ALLOW_THREADS; Py_DECREF(obj); diff --git a/src_c/imageext.c b/src_c/imageext.c index 0d68d59070..d2823fcb00 100644 --- a/src_c/imageext.c +++ b/src_c/imageext.c @@ -117,10 +117,18 @@ image_load_ext(PyObject *self, PyObject *arg, PyObject *kwarg) SDL_UnlockMutex(_pg_img_mutex); */ +#if SDL_VERSION_ATLEAST(3, 0, 0) + surf = IMG_LoadTyped_IO(rw, 1, type); +#else surf = IMG_LoadTyped_RW(rw, 1, type); +#endif Py_END_ALLOW_THREADS; -#else /* ~WITH_THREAD */ +#else /* ~WITH_THREAD */ +#if SDL_VERSION_ATLEAST(3, 0, 0) + surf = IMG_LoadTyped_IO(rw, 1, type); +#else surf = IMG_LoadTyped_RW(rw, 1, type); +#endif #endif /* ~WITH_THREAD */ if (ext) { @@ -166,7 +174,11 @@ imageext_load_sized_svg(PyObject *self, PyObject *arg, PyObject *kwargs) } Py_BEGIN_ALLOW_THREADS; +#if SDL_VERSION_ATLEAST(3, 0, 0) + surf = IMG_LoadSizedSVG_IO(rw, width, height); +#else surf = IMG_LoadSizedSVG_RW(rw, width, height); +#endif SDL_RWclose(rw); Py_END_ALLOW_THREADS; if (surf == NULL) { @@ -231,7 +243,11 @@ image_save_ext(PyObject *self, PyObject *arg, PyObject *kwarg) char *ext = iext_find_extension(name); if (!strcasecmp(ext, "jpeg") || !strcasecmp(ext, "jpg")) { if (rw != NULL) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + result = IMG_SaveJPG_IO(surf, rw, 0, JPEG_QUALITY); +#else result = IMG_SaveJPG_RW(surf, rw, 0, JPEG_QUALITY); +#endif } else { result = IMG_SaveJPG(surf, name, JPEG_QUALITY); @@ -240,7 +256,11 @@ image_save_ext(PyObject *self, PyObject *arg, PyObject *kwarg) else if (!strcasecmp(ext, "png")) { /*Py_BEGIN_ALLOW_THREADS; */ if (rw != NULL) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + result = IMG_SavePNG_IO(surf, rw, 0); +#else result = IMG_SavePNG_RW(surf, rw, 0); +#endif } else { result = IMG_SavePNG(surf, name); diff --git a/src_c/mixer.c b/src_c/mixer.c index 0d3fa8f393..f342e18216 100644 --- a/src_c/mixer.c +++ b/src_c/mixer.c @@ -1875,7 +1875,11 @@ sound_init(PyObject *self, PyObject *arg, PyObject *kwarg) return -1; } Py_BEGIN_ALLOW_THREADS; +#if SDL_VERSION_ATLEAST(3, 0, 0) + chunk = Mix_LoadWAV_IO(rw, 1); +#else chunk = Mix_LoadWAV_RW(rw, 1); +#endif Py_END_ALLOW_THREADS; if (chunk == NULL) { PyErr_SetString(pgExc_SDLError, SDL_GetError()); diff --git a/src_c/music.c b/src_c/music.c index b6b733f90c..71bc776fb2 100644 --- a/src_c/music.c +++ b/src_c/music.c @@ -388,7 +388,11 @@ _load_music(PyObject *obj, char *namehint) } Py_BEGIN_ALLOW_THREADS; +#if SDL_VERSION_ATLEAST(3, 0, 0) + new_music = Mix_LoadMUSType_IO(rw, _get_type_from_hint(type), SDL_TRUE); +#else new_music = Mix_LoadMUSType_RW(rw, _get_type_from_hint(type), SDL_TRUE); +#endif Py_END_ALLOW_THREADS; if (ext) { diff --git a/src_c/rwobject.c b/src_c/rwobject.c index a88c2495b2..f750d90539 100644 --- a/src_c/rwobject.c +++ b/src_c/rwobject.c @@ -46,6 +46,18 @@ static const char pg_default_errors[] = "backslashreplace"; static PyObject *os_module = NULL; +#if SDL_VERSION_ATLEAST(3, 0, 0) +static Sint64 +_pg_rw_size(void *); +static Sint64 +_pg_rw_seek(void *, Sint64, SDL_IOWhence); +static size_t +_pg_rw_read(void *, void *, size_t, SDL_IOStatus *); +static size_t +_pg_rw_write(void *, const void *, size_t, SDL_IOStatus *); +static int +_pg_rw_close(void *); +#else static Sint64 _pg_rw_size(SDL_RWops *); static Sint64 @@ -56,6 +68,7 @@ static size_t _pg_rw_write(SDL_RWops *, const void *, size_t, size_t); static int _pg_rw_close(SDL_RWops *); +#endif /* Converter function used by PyArg_ParseTupleAndKeywords with the "O&" format. * @@ -291,13 +304,31 @@ pg_EncodeFilePath(PyObject *obj, PyObject *eclass) static int pgRWops_IsFileObject(SDL_RWops *rw) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_PropertiesID props = SDL_GetIOProperties(rw); + if (!props) { + // pgRWops_IsFileObject doesn't have any error checking facility + // so when in doubt let's say it isn't a file object. + return 0; + } + return SDL_GetBooleanProperty(props, "_pygame_is_file_object", 0); +#else return rw->close == _pg_rw_close; +#endif } +#if SDL_VERSION_ATLEAST(3, 0, 0) +static Sint64 +_pg_rw_size(void *userdata) +{ + pgRWHelper *helper = (pgRWHelper *)userdata; +#else static Sint64 _pg_rw_size(SDL_RWops *context) { pgRWHelper *helper = (pgRWHelper *)context->hidden.unknown.data1; +#endif + PyObject *pos = NULL; PyObject *tmp = NULL; Sint64 size; @@ -361,10 +392,19 @@ _pg_rw_size(SDL_RWops *context) return retval; } +#if SDL_VERSION_ATLEAST(3, 0, 0) +static size_t +_pg_rw_write(void *userdata, const void *ptr, size_t size, + SDL_IOStatus *status) +{ + pgRWHelper *helper = (pgRWHelper *)userdata; + size_t num = 1; +#else static size_t _pg_rw_write(SDL_RWops *context, const void *ptr, size_t size, size_t num) { pgRWHelper *helper = (pgRWHelper *)context->hidden.unknown.data1; +#endif PyObject *result; size_t retval; @@ -382,17 +422,28 @@ _pg_rw_write(SDL_RWops *context, const void *ptr, size_t size, size_t num) } Py_DECREF(result); +#if SDL_VERSION_ATLEAST(3, 0, 0) + retval = size; +#else retval = num; +#endif end: PyGILState_Release(state); return retval; } +#if SDL_VERSION_ATLEAST(3, 0, 0) +static int +_pg_rw_close(void *userdata) +{ + pgRWHelper *helper = (pgRWHelper *)userdata; +#else static int _pg_rw_close(SDL_RWops *context) { pgRWHelper *helper = (pgRWHelper *)context->hidden.unknown.data1; +#endif PyObject *result; int retval = 0; PyGILState_STATE state = PyGILState_Ensure(); @@ -414,7 +465,9 @@ _pg_rw_close(SDL_RWops *context) PyMem_Free(helper); PyGILState_Release(state); +#if !SDL_VERSION_ATLEAST(3, 0, 0) SDL_FreeRW(context); +#endif return retval; } @@ -437,6 +490,37 @@ pgRWops_FromFileObject(PyObject *obj) return NULL; } +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_IOStreamInterface iface; + iface.size = _pg_rw_size; + iface.seek = _pg_rw_seek; + iface.read = _pg_rw_read; + iface.write = _pg_rw_write; + iface.close = _pg_rw_close; + + // TODO: These should raise SDLError probably? + // rwobject.c hasn't required pygame.base before (the source of SDLError) + // so omitting that for now. + + rw = SDL_OpenIO(&iface, helper); + if (rw == NULL) { + iface.close(helper); + PyMem_Free(helper); + return (SDL_RWops *)RAISE(PyExc_IOError, SDL_GetError()); + } + + SDL_PropertiesID props = SDL_GetIOProperties(rw); + if (!props) { + PyMem_Free(helper); + return (SDL_RWops *)RAISE(PyExc_IOError, SDL_GetError()); + } + + if (SDL_SetBooleanProperty(props, "_pygame_is_file_object", 1) < 0) { + PyMem_Free(helper); + return (SDL_RWops *)RAISE(PyExc_IOError, SDL_GetError()); + } + +#else rw = SDL_AllocRW(); if (rw == NULL) { PyMem_Free(helper); @@ -450,14 +534,22 @@ pgRWops_FromFileObject(PyObject *obj) rw->read = _pg_rw_read; rw->write = _pg_rw_write; rw->close = _pg_rw_close; +#endif return rw; } +#if SDL_VERSION_ATLEAST(3, 0, 0) +static Sint64 +_pg_rw_seek(void *userdata, Sint64 offset, SDL_IOWhence whence) +{ + pgRWHelper *helper = (pgRWHelper *)userdata; +#else static Sint64 _pg_rw_seek(SDL_RWops *context, Sint64 offset, int whence) { pgRWHelper *helper = (pgRWHelper *)context->hidden.unknown.data1; +#endif PyObject *result; Sint64 retval; @@ -498,10 +590,18 @@ _pg_rw_seek(SDL_RWops *context, Sint64 offset, int whence) return retval; } +#if SDL_VERSION_ATLEAST(3, 0, 0) +static size_t +_pg_rw_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status) +{ + pgRWHelper *helper = (pgRWHelper *)userdata; + size_t maxnum = 1; +#else static size_t _pg_rw_read(SDL_RWops *context, void *ptr, size_t size, size_t maxnum) { pgRWHelper *helper = (pgRWHelper *)context->hidden.unknown.data1; +#endif PyObject *result; Py_ssize_t retval; @@ -527,7 +627,9 @@ _pg_rw_read(SDL_RWops *context, void *ptr, size_t size, size_t maxnum) retval = PyBytes_GET_SIZE(result); if (retval) { memcpy(ptr, PyBytes_AsString(result), retval); +#if !SDL_VERSION_ATLEAST(3, 0, 0) retval /= size; +#endif } Py_DECREF(result);