Commits

Anonymous committed 86ce793

Added sys.prefix to search dirs in build system for local installations.
Fixed sdl hello_world example.
Fixed VC++ build with freetype2.
Fixed header detection with libconfig targets in unix build configuration.
Updated docs to reflect the lates pygame2.freetype changes.
Rewrote and fixed sdl.rwops to be suitable for arbitrary file-like objects.

Comments (0)

Files changed (27)

 
     Build with JPEG format saving support for pygame2.sdl.
 
+WITH_FREETYPE=[yes|no|1|True]   Example: make -WITH_FREETYPE=False
+    
+    Build and install the pygame2.freetype module. This wraps the
+    FreeType2 library.
+
 1.1 Dependencies
 ----------------
 Pygame2 is designed to run in as many environments as possible. As such,
 * SDL_gfx >= 2.0.18         (http://www.ferzkopp.net/Software/SDL_gfx-2.0/)
 * libpng >= 1.2.24          (http://www.libpng.org)
 * libjpeg >= 6b             (http://www.ijg.org/)
+* freetype >= 2.3.5         (http://www.freetype.org)
 
 1.2 Notes on SVN usage
 ----------------------
 * Rewrite and fix up numpysurfarray and numpysndarray
 * Add prebuilt package for Win32 VC++ builds.
 * Refine quitting for SDL_QuitSubSystem wrapper.
+* Rewrite RWops wrapper code to make it suitable for buffer-like objects and
+  to avoid unnecessary closes.
 
 Things to ADD:
 ==============

config/config_msys.py

 
 
 class Dependency (config_unix.Dependency):
-    _searchdirs = [ "/usr", "/usr/local"]#, "/mingw" ]
+    _searchdirs = [ "/usr", "/usr/local", "/mingw" ]
     _incdirs = [ "include", "X11/include" ]
     _libdirs = [ "lib", "X11/lib" ]
     _libprefix = "lib"

config/config_unix.py

-import os, glob
+import os, glob, sys
 from config import config_generic, libconfig, pkgconfig, helpers
 
 def get_sys_libs (module):
     return []
 
 class Dependency (config_generic.Dependency):
-    _searchdirs = [ "/usr", "/usr/local" ]
+    _searchdirs = [ "/usr", "/usr/local", sys.prefix ]
     _incdirs = [ "include", "X11/include" ]
     _libdirs = [ "lib", "X11/lib" ]
     _libprefix = "lib"
             Configuration callback using a generic CONFIG tool
         """
         lc = self.library_config_program
-        found_header = False
-
         if not lc or not libconfig.has_libconfig(lc):
             return False
 
-        incdirs = libconfig.get_incdirs(lc)
-        for d in incdirs:
-            for h in self.header_files:
-                if os.path.isfile(os.path.join(d, h)):
-                    found_header = True
-        if not found_header:
-            return False
-
-        self.incdirs += incdirs
+        self.incdirs += libconfig.get_incdirs(lc)
         self.libdirs += libconfig.get_libdirs(lc)
         self.libs += libconfig.get_libs(lc)
         self.cflags += libconfig.get_cflags(lc)

config/config_win.py

-import os, glob
+import os, glob, sys
 from config import helpers, dll
 from config import config_generic
 
     # Gets the libraries to install for the target platform.
     _libdirs = [ "", "VisualC\\SDL\\Release", "VisualC\\Release", "Release",
                  "lib"]
-    _searchdirs = [ "prebuilt", "..", "..\\.." ]
+    _searchdirs = [ "prebuilt", "..", "..\\..", sys.prefix ]
 
     libraries = {}
     values = {}
 
     return libraries.keys ()
 
-
 class Dependency (config_generic.Dependency):
-    _searchdirs = [ "prebuilt", "..", "..\\.." ]
+    _searchdirs = [ "prebuilt", "..", "..\\..", sys.prefix ]
     _incdirs = [ "", "include" ]
     _libdirs = [ "", "VisualC\\SDL\\Release", "VisualC\\Release", "Release",
                  "lib"]
     _libprefix = ""
+
+    def configure (self, cfg):
+        super(Dependency, self).configure (cfg)
+        
+        # HACK: freetype.h is in freetype2\\freetype, but we need
+        # freetype2\\.
+        if self.library_id != "freetype":
+            return
+        incs = []
+        for d in self.incdirs:
+            if d.endswith ("freetype2\\freetype"):
+                incs.append (d.replace ("freetype2\\freetype", "freetype2"))
+            else:
+                incs.append (d)
+        self.incdirs = incs

doc/BuildDarwin.txt

 * SDL_gfx >= 2.0.18          (http://www.ferzkopp.net/Software/SDL_gfx-2.0/)
 * libpng >= 1.2.24           (http://www.libpng.org)
 * libjpeg >= 6b              (http://www.ijg.org/)
+* freetype >= 2.3.5          (http://www.freetype.org)
 
 And you will need the dependency packages for the packages above:
 
 * tiff >= 3.8.2              (http://libtiff.org)
 * libvorbis >= 1.2.0         (http://www.xiph.org/vorbis/)
 * libogg >= 1.1.3            (http://www.xiph.org/ogg/)
-* freetype >= 2.3.5          (http://www.freetype.org)
 * FLAC >= 1.2.1              (http://flac.sourceforge.net)
 
 Where available, the prefered way to install these dependencies is by

doc/BuildMinGW.txt

 * SDL_gfx >= 2.0.18          (http://www.ferzkopp.net/Software/SDL_gfx-2.0/)
 * libpng >= 1.2.24           (http://www.libpng.org)
 * libjpeg >= 6b              (http://www.ijg.org/)
+* freetype >= 2.3.5          (http://www.freetype.org)
 
 And you will need the dependency packages for the packages above:
 
 * tiff >= 3.8.2              (http://libtiff.org)
 * libvorbis >= 1.2.0  	     (http://www.xiph.org/vorbis/)
 * libogg >= 1.1.3            (http://www.xiph.org/ogg/)
-* freetype >= 2.3.5          (http://www.freetype.org)
 * FLAC >= 1.2.1              (http://flac.sourceforge.net)
 
 Once you downloaded all source packages, unpack them and put them all into a

doc/BuildUnix.txt

 * SDL_gfx >= 2.0.18          (http://www.ferzkopp.net/Software/SDL_gfx-2.0/)
 * libpng >= 1.2.24           (http://www.libpng.org)
 * libjpeg >= 6b              (http://www.ijg.org/)
+* freetype >= 2.3.5          (http://www.freetype.org)
 
 And you will need the dependency packages for the packages above:
 
 * tiff >= 3.8.2              (http://libtiff.org)
 * libvorbis >= 1.2.0         (http://www.xiph.org/vorbis/)
 * libogg >= 1.1.3            (http://www.xiph.org/ogg/)
-* freetype >= 2.3.5          (http://www.freetype.org)
 * FLAC >= 1.2.1              (http://flac.sourceforge.net)
 
 The next step would be to build and install those dependencies in the
 
 .. note::
 
-    NOTE: If you are going to use the VC Toolkit 2003, make sure, you have some
+    If you are going to use the VC Toolkit 2003, make sure, you have some
     proper registry keys set. Otherwise Python's distutils will not be able to
     detect the settings. Within the util/ directory you can find an example
     registry key. Change the paths within it according to your system
 
 .. note::
 
-    NOTE: The following list of dependencies might not be the most actual
+    The following list of dependencies might not be the most actual
     one. Please check the README.txt file in the top source directory
     for the most actual dependency list!
 
 * SDL_gfx >= 2.0.18          (http://www.ferzkopp.net/Software/SDL_gfx-2.0/)
 * libpng >= 1.2.24           (http://www.libpng.org)
 * libjpeg >= 6b              (http://www.ijg.org/)
+* freetype >= 2.3.5          (http://www.freetype.org)
 
 The Win32 build chain for Pygame2 does not support building all
 dependencies from scratch. Instead it relies on already built libraries,
 dictionary in config.config_modules ::
 
     'dependency_name' : 
-        os_module.Dependency('header.h', 'library_id'),
+        dep(['header.h', header2.h, ...], 'library_id', ...),
 
 When defining a new dependency, 'dependency_name' is its full name (as
-referenced when instantiating a new Module object), 'header.h' is a
-representative header for the library, and 'library_id' is the linking
-id for the library: For example, a library that is linked with the
+referenced when instantiating a new Module object), [ 'header.h', ... ] is a
+representative list of required headers for the library, and 'library_id' is
+the linking id for the library: For example, a library that is linked with
 '-ljpeg' has 'jpeg' as its id.
 
 All the modules which depend on such library will be automatically
 
     build['dependency_name'] = False
 
-
 C Module Dependencies
 ---------------------
 If you have inter-module dependencies (e.g. parts of pygame.myownlib can make
   WITH_JPEG=[yes|no|1|True]               Example: make -DWITH_JPEG=False
 
 Build with JPEG format saving support for
-:meth:`pygame2.sdl.video.Surface.save`.
+:meth:`pygame2.sdl.video.Surface.save`. ::
 
+  WITH_FREETYPE=[yes|no|1|True]           Example: make -DWITH_FREETYPE=False
+
+Build and install the :mod:`pygame2.freetype` module. This wraps the
+FreeType2 library.

doc/capi/base.rst

   Tries to convert the PyObject to a double and stores the result in *val*, if
   successful. This returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int IntFromObj (PyObject* obj, int *val)
 
   Tries to convert the PyObject to an int and stores the result in *val*, if
   successful. This returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int UintFromObj (PyObject* obj, unsigned int *val)
 
   Tries to convert the PyObject to an unsigned int and stores the result in
   *val*, if successful. This returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int DoubleFromSeqIndex (PyObject *seq, Py_ssize_t index, double *val)
 
   Tries to get the item at the desired *index* from the passed sequence object
   and converts it to a double, which will be stored in *val*. This returns 1 on
   success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int IntFromSeqIndex (PyObject *seq, Py_ssize_t index, int *val)
 
   Tries to get the item at the desired *index* from the passed sequence object
   and converts it to an int, which will be stored in *val*. This returns 1 on
   success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int UintFromSeqIndex (PyObject *seq, Py_ssize_t index, unsigned int *val)
 
   Tries to get the item at the desired *index* from the passed sequence object
   and converts it to an unsigned int, which will be stored in *val*. This
   returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int PointFromObject (PyObject *obj, int *x, int *y)
 
   Tries to get two int values from the passed object. If the object is a
   if the object is a sequence type, the first two items are used. This returns
   1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int SizeFromObject (PyObject *obj, pgint32 *x, pgint32 *y)
 
   Tries to get two pgint32 values from the passed object. If the object is a
   if the object is a sequence type, the first two items are used. This returns
   1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int FPointFromObject (PyObject *obj, double *x, double *y)
 
   Tries to get two double values from the passed object. If the object is a
   if the object is a sequence type, the first two items are used. This returns
   1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int FSizeFromObject (PyObject *obj, double *x, double *y)
 
   Tries to get two double values from the passed object. If the object is a
   if the object is a sequence type, the first two items are used. This returns
   1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int ASCIIFromObject (PyObject *obj, char** text, PyObject **convobj)
 
   Tries to get ASCII text from the passed object and stores the result in
   stored in *convobj* and needs to be freed by the caller, once *text* is not
   required anymore. This returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int UTF8FromObject (PyObject *obj, char** text, PyObject **convobj)
 
   Tries to get UTF-8 encoded text from the passed object and stores the result
   stored in *convobj* and needs to be freed by the caller, once *text* is not
   required anymore. This returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 PyColor
 -------
 .. ctype:: PyColor

doc/capi/sdlbase.rst

 
   Tries to convert the PyObject to a Uint8 and stores the result in
   *val*, if successful. This returns 1 on success and 0 on failure.
-  
-  This will not check the arguments for being *NULL*.
 
 .. cfunction:: int Uint16FromObj (PyObject *obj, Uint16 *val)
 
   Tries to convert the PyObject to a Uint16 and stores the result in
   *val*, if successful. This returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int Sint16FromObj (PyObject *obj, Sint16 *val)
 
   Tries to convert the PyObject to a Sint16 and stores the result in
   *val*, if successful. This returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int Uint32FromObj (PyObject *obj, Uint32 *val)
 
   Tries to convert the PyObject to a Uint32 and stores the result in
   *val*, if successful. This returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int Uint8FromSeqIndex (PyObject *obj, Py_ssize_t index, Uint8 *val)
 
   Tries to get the item at the desired *index* from the passed sequence
   object and converts it to a Uint8, which will be stored in *val*. This
   returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int Uint16FromSeqIndex (PyObject *obj, Py_ssize_t index, Uint16 *val)
 
   Tries to get the item at the desired *index* from the passed sequence
   object and converts it to a Uint16, which will be stored in *val*. This
   returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int Sint16FromSeqIndex (PyObject *obj, Py_ssize_t index, Sint16 *val)
 
   Tries to get the item at the desired *index* from the passed sequence
   object and converts it to a Sint16, which will be stored in *val*. This
   returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int Uint32FromSeqIndex (PyObject *obj, Py_ssize_t index, Uint32 *val)
 
   Tries to get the item at the desired *index* from the passed sequence
   object and converts it to a Uint32, which will be stored in *val*. This
   returns 1 on success and 0 on failure.
 
-  This will not check the arguments for being *NULL*.
-
 .. cfunction:: int IsValidRect (PyObject *obj)
 
   Checks, if the passed object is a valid rectangle object. That is the
 
    ref/pygame2_base.rst
    ref/pygame2_font.rst
+   ref/pygame2_freetype_base.rst
    ref/pygame2_mask.rst
    ref/pygame2_physics.rst
    ref/pygame2_sdl_audio.rst

examples/sdl/hello_world.py

     else:
         surface = image.load_bmp (os.path.join (imgdir, "logo.bmp"))
 
-        screen = video.set_mode (surface.w + 10, surface.h + 10)
-        screen.fill (pygame2.Color (255, 255, 255))
-        screen.blit (surface, (5, 5))
-        screen.flip ()
+    screen = video.set_mode (surface.w + 10, surface.h + 10)
+    screen.fill (pygame2.Color (255, 255, 255))
+    screen.blit (surface, (5, 5))
+    screen.flip ()
 
     okay = True
     while okay:

src/sdl/imagemod.c

 _sdl_loadbmp (PyObject *self, PyObject *args)
 {
     SDL_Surface *surface;
+    SDL_RWops *rw;
+    int autoclose;
     PyObject *sf, *file;
     char *filename;
 
     if (!PyArg_ParseTuple (args, "O:load_bmp", &file))
         return NULL;
 
-    if (IsTextObj (file))
-    {
-        PyObject *tmp;
-        if (!UTF8FromObject (file, &filename, &tmp))
-            return NULL;
+    rw = PyRWops_NewRO (file, &autoclose);
+    if (!rw)
+        return NULL;
 
-        Py_BEGIN_ALLOW_THREADS;
-        surface = SDL_LoadBMP ((const char*)filename);
-        Py_END_ALLOW_THREADS;
-
-        Py_XDECREF (tmp);
-    }
-#ifdef IS_PYTHON_3
-    else if (PyObject_AsFileDescriptor (file) != -1)
-#else
-    else if (PyFile_Check (file))
-#endif
-    {
-        SDL_RWops *rw = RWopsFromPython (file);
-        if (!rw)
-            return NULL;
-
-        Py_BEGIN_ALLOW_THREADS;
-        surface = SDL_LoadBMP_RW (rw, 1);
-        Py_END_ALLOW_THREADS;
-    }
-    else
-    {
-#ifdef IS_PYTHON_3
-        PyErr_Clear (); /* Set by the PyObject_AsFileDescriptor() call */
-#endif
-        PyErr_SetString (PyExc_TypeError, "file must be a string or file");
-        return NULL;
-    }
+    Py_BEGIN_ALLOW_THREADS;
+    surface = SDL_LoadBMP_RW (rw, autoclose);
+    Py_END_ALLOW_THREADS;
+    
+    if (!autoclose)
+        PyRWops_Close (rw, autoclose);
 
     if (!surface)
     {
 _sdl_savebmp (PyObject *self, PyObject *args)
 {
     PyObject *surface, *file;
+    SDL_RWops *rw;
     char *filename;
-    int _stat;
+    int _stat, autoclose;
     
     if (!PyArg_ParseTuple (args, "OO:save_bmp", &surface, &file))
         return NULL;
         return NULL;
     }
 
-    if (IsTextObj (file))
-    {
-        PyObject *tmp;
-        if (!UTF8FromObject (file, &filename, &tmp))
-            return NULL;
-
-        Py_BEGIN_ALLOW_THREADS;
-        _stat = SDL_SaveBMP (((PySDLSurface*)surface)->surface, filename);
-        Py_END_ALLOW_THREADS;
-
-        Py_XDECREF (tmp);
-    }
-#ifdef IS_PYTHON_3
-    else if (PyObject_AsFileDescriptor (file) != -1)
-#else
-    else if (PyFile_Check (file))
-#endif
-    {
-        SDL_RWops *rw = RWopsFromPython (file);
-        if (!rw)
-            return NULL;
-
-        Py_BEGIN_ALLOW_THREADS;
-        _stat = SDL_SaveBMP_RW (((PySDLSurface*)surface)->surface, rw, 1);
-        Py_END_ALLOW_THREADS;
-    }
-    else
-    {
-#ifdef IS_PYTHON_3
-        PyErr_Clear (); /* Set by the PyObject_AsFileDescriptor() call */
-#endif
-        PyErr_SetString (PyExc_TypeError, "file must be a string or file");
+    rw = PyRWops_NewRW (file, &autoclose);
+    if (!rw)
         return NULL;
-    }
-
+    
+    Py_BEGIN_ALLOW_THREADS;
+    _stat = SDL_SaveBMP_RW (((PySDLSurface*)surface)->surface, rw, autoclose);
+    Py_END_ALLOW_THREADS;
+    
+    if (!autoclose)
+        PyRWops_Close (rw, autoclose);
+    
     if (_stat == -1)
     {
         PyErr_SetString (PyExc_PyGameError, SDL_GetError ());

src/sdl/keyboardmod.c

     int count, i;
     PyObject *dict, *key, *val;
     
-    ASSERT_VIDEO_INIT (NULL);
+    /*ASSERT_VIDEO_INIT (NULL);*/
     
     dict = PyDict_New ();
     if (!dict)
         return NULL;
-    
     SDL_PumpEvents ();
     array = SDL_GetKeyState (&count);
     
     {
         key = PyInt_FromLong (i);
         val = PyBool_FromLong (array[i]);
-        if (!PyDict_SetItem (dict, key, val))
+        if (PyDict_SetItem (dict, key, val) == -1)
         {
             Py_DECREF (key);
             Py_DECREF (val);
 static PyObject*
 _sdl_keygetmodstate (PyObject *self)
 {
-    ASSERT_VIDEO_INIT (NULL);
+    /*ASSERT_VIDEO_INIT (NULL);*/
     return PyLong_FromUnsignedLong (SDL_GetModState ());
 }
 
 _sdl_keysetmodstate (PyObject *self, PyObject *args)
 {
     SDLMod mod;
-    ASSERT_VIDEO_INIT (NULL);
+    /*ASSERT_VIDEO_INIT (NULL);*/
     
     if (!PyArg_ParseTuple (args, "i:set_mod_state", &mod))
         return NULL;
 {
     int key;
     
-    ASSERT_VIDEO_INIT (NULL);
+    /*ASSERT_VIDEO_INIT (NULL);*/
     
     if (!PyArg_ParseTuple (args, "i:get_key_name", &key))
         return NULL;
 
 /* RWops */
 #define PYGAME_SDLRWOPS_FIRSTSLOT 0
-#define PYGAME_SDLRWOPS_NUMSLOTS 4
+#define PYGAME_SDLRWOPS_NUMSLOTS 3
 #ifndef PYGAME_SDLRWOPS_INTERNAL
-#define RWopsFromPython                                                 \
-    (*(SDL_RWops*(*)(PyObject*))PyGameSDLRWops_C_API[PYGAME_SDLRWOPS_FIRSTSLOT])
-#define RWopsCheckPython                                                \
-    (*(int(*)(SDL_RWops*))PyGameSDLRWops_C_API[PYGAME_SDLRWOPS_FIRSTSLOT+1])
-#define RWopsFromPythonThreaded                                         \
-    (*(SDL_RWops*(*)(PyObject*))PyGameSDLRWops_C_API[PYGAME_SDLRWOPS_FIRSTSLOT+2])
-#define RWopsCheckPythonThreaded                                        \
-    (*(int(*)(SDL_RWops*))PyGameSDLRWops_C_API[PYGAME_SDLRWOPS_FIRSTSLOT+3])
+#define PyRWops_NewRO                                                 \
+    (*(SDL_RWops*(*)(PyObject*,int*))PyGameSDLRWops_C_API[PYGAME_SDLRWOPS_FIRSTSLOT])
+#define PyRWops_NewRW                                                 \
+    (*(SDL_RWops*(*)(PyObject*,int*))PyGameSDLRWops_C_API[PYGAME_SDLRWOPS_FIRSTSLOT+1])
+#define PyRWops_Close                                                 \
+    (*(void(*)(SDL_RWops*,int))PyGameSDLRWops_C_API[PYGAME_SDLRWOPS_FIRSTSLOT+2])
 #endif /* PYGAME_SDLRWOPS_INTERNAL */
 
 /**

src/sdl/rwopsmod.c

 
 typedef struct
 {
-    PyObject* read;
-    PyObject* write;
-    PyObject* seek;
-    PyObject* tell;
-    PyObject* close;
-#ifdef WITH_THREAD
-    PyThreadState* thread;
-#endif
-} _RWHelper;
+    PyObject *read;
+    PyObject *write;
+    PyObject *seek;
+    PyObject *tell;
+    PyObject *close;
+} _RWWrapper;
 
-static SDL_RWops* get_standard_rwop (PyObject* obj);
-static void fetch_object_methods (_RWHelper* helper, PyObject* obj);
-
-static int rw_seek (SDL_RWops* context, int offset, int whence);
-static int rw_read (SDL_RWops* context, void* ptr, int size, int maxnum);
-static int rw_write (SDL_RWops* context, const void* ptr, int size, int maxnum);
-static int rw_close (SDL_RWops* context);
-
-#ifdef WITH_THREAD
-static int rw_seek_th (SDL_RWops* context, int offset, int whence);
-static int rw_read_th (SDL_RWops* context, void* ptr, int size, int maxnum);
-static int rw_write_th (SDL_RWops* context, const void* ptr, int size,
-                        int maxnum);
-static int rw_close_th (SDL_RWops* context);
-#endif
-
-/* C API */
-static SDL_RWops* RWopsFromPython (PyObject* obj);
-static int RWopsCheckPython (SDL_RWops* rw);
-static SDL_RWops* RWopsFromPythonThreaded (PyObject* obj);
-static int RWopsCheckPythonThreaded (SDL_RWops* rw);
-
-static SDL_RWops*
-get_standard_rwop (PyObject* obj)
-{
-#ifdef IS_PYTHON_3
-    int fd;
-#endif
-    if (IsTextObj (obj))
-    {
-        int result;
-        char* name;
-        PyObject* tuple = PyTuple_New (1);
-        PyTuple_SET_ITEM (tuple, 0, obj);
-        Py_INCREF (obj);
-        if (!tuple)
-            return NULL;
-        result = PyArg_ParseTuple (tuple, "s", &name);
-        Py_DECREF (tuple);
-        if (!result)
-            return NULL;
-        /* TODO: allow wb ops! */
-        return SDL_RWFromFile (name, "rb");
-    }
-#ifdef IS_PYTHON_3
-    else if ((fd = PyObject_AsFileDescriptor (obj)) != -1)
-    {
-        FILE *fp = fdopen (fd, "rb"); /* TODO: is that safe? */
-        if (!fp)
-        {
-            PyErr_SetString (PyExc_IOError, "could not open file");
-            return NULL;
-        }
-        return SDL_RWFromFP (fp, 1);
-    }
-#else
-    else if (PyFile_Check(obj))
-        return SDL_RWFromFP (PyFile_AsFile (obj), 0);
-#endif
-    return NULL;
-}
+static void _bind_python_methods (_RWWrapper *wrapper, PyObject *obj);
+static int _pyobj_read (SDL_RWops *ops, void* ptr, int size, int num);
+static int _pyobj_seek (SDL_RWops *ops, int offset, int whence);
+static int _pyobj_write (SDL_RWops *ops, const void* ptr, int size, int num);
+static int _pyobj_close (SDL_RWops *ops);
 
 static void
-fetch_object_methods (_RWHelper* helper, PyObject* obj)
+_bind_python_methods (_RWWrapper *wrapper, PyObject *obj)
 {
-    helper->read = helper->write = helper->seek = helper->tell =
-        helper->close = NULL;
-
+    wrapper->read = NULL;
+    wrapper->write = NULL;
+    wrapper->seek = NULL;
+    wrapper->tell = NULL;
+    wrapper->close = NULL;
+    
     if (PyObject_HasAttrString (obj, "read"))
     {
-        helper->read = PyObject_GetAttrString (obj, "read");
-        if(helper->read && !PyCallable_Check (helper->read))
+        wrapper->read = PyObject_GetAttrString (obj, "read");
+        if (wrapper->read && !PyCallable_Check (wrapper->read))
         {
-            Py_DECREF (helper->read);
-            helper->read = NULL;
+            Py_DECREF (wrapper->read);
+            wrapper->read = NULL;
         }
     }
     if (PyObject_HasAttrString (obj, "write"))
     {
-        helper->write = PyObject_GetAttrString (obj, "write");
-        if (helper->write && !PyCallable_Check (helper->write))
+        wrapper->write = PyObject_GetAttrString (obj, "write");
+        if (wrapper->write&& !PyCallable_Check (wrapper->write))
         {
-            Py_DECREF (helper->write);
-            helper->write = NULL;
+            Py_DECREF (wrapper->write);
+            wrapper->write = NULL;
         }
     }
     if (PyObject_HasAttrString (obj, "seek"))
     {
-        helper->seek = PyObject_GetAttrString (obj, "seek");
-        if (helper->seek && !PyCallable_Check (helper->seek))
+        wrapper->seek = PyObject_GetAttrString (obj, "seek");
+        if (wrapper->seek && !PyCallable_Check (wrapper->seek))
         {
-            Py_DECREF (helper->seek);
-            helper->seek = NULL;
+            Py_DECREF (wrapper->seek);
+            wrapper->seek = NULL;
         }
     }
     if (PyObject_HasAttrString (obj, "tell"))
     {
-        helper->tell = PyObject_GetAttrString (obj, "tell");
-        if (helper->tell && !PyCallable_Check (helper->tell))
+        wrapper->tell = PyObject_GetAttrString (obj, "tell");
+        if (wrapper->tell && !PyCallable_Check (wrapper->tell))
         {
-            Py_DECREF (helper->tell);
-            helper->tell = NULL;
+            Py_DECREF (wrapper->tell);
+            wrapper->tell = NULL;
         }
     }
-    if(PyObject_HasAttrString(obj, "close"))
+    if (PyObject_HasAttrString (obj, "close"))
     {
-        helper->close = PyObject_GetAttrString (obj, "close");
-        if (helper->close && !PyCallable_Check (helper->close))
+        wrapper->close = PyObject_GetAttrString (obj, "close");
+        if (wrapper->close && !PyCallable_Check (wrapper->close))
         {
-            Py_DECREF (helper->close);
-            helper->close = NULL;
+            Py_DECREF (wrapper->close);
+            wrapper->close = NULL;
         }
     }
 }
 
 static int
-rw_seek (SDL_RWops* context, int offset, int whence)
+_pyobj_read (SDL_RWops *ops, void* ptr, int size, int maxnum)
 {
-    _RWHelper* helper = (_RWHelper*) context->hidden.unknown.data1;
+    _RWWrapper *wrapper = (_RWWrapper *) ops->hidden.unknown.data1;
+    PyObject *result;
+    int retval;
+    
+    if (!wrapper->read)
+        return -1;
+    result = PyObject_CallFunction (wrapper->read, "i", size * maxnum);
+    if (!result)
+        return -1;
+    if (!Bytes_Check (result))
+    {
+        Py_DECREF (result);
+        return -1;
+    }
+    retval = Bytes_GET_SIZE (result);
+    memcpy (ptr, Bytes_AS_STRING (result), (size_t) retval);
+    retval /= size;
+    
+    Py_DECREF (result);
+    return retval;
+}
+
+static int
+_pyobj_seek (SDL_RWops *ops, int offset, int whence)
+{
+    _RWWrapper *wrapper = (_RWWrapper *) ops->hidden.unknown.data1;
     PyObject* result;
     int retval;
 
-    if (!helper->seek || !helper->tell)
+    if (!wrapper->seek || !wrapper->tell)
         return -1;
 
     if (!(offset == 0 && whence == SEEK_CUR)) /*being called only for 'tell'*/
     {
-        result = PyObject_CallFunction (helper->seek, "ii", offset, whence);
+        result = PyObject_CallFunction (wrapper->seek, "ii", offset, whence);
         if (!result)
             return -1;
         Py_DECREF (result);
     }
 
-    result = PyObject_CallFunction (helper->tell, NULL);
+    result = PyObject_CallFunction (wrapper->tell, NULL);
     if (!result)
         return -1;
 
     retval = PyInt_AsLong (result);
     Py_DECREF (result);
-
     return retval;
 }
 
 static int
-rw_read (SDL_RWops* context, void* ptr, int size, int maxnum)
+_pyobj_write (SDL_RWops *ops, const void* ptr, int size, int num)
 {
-    _RWHelper* helper = (_RWHelper*) context->hidden.unknown.data1;
-    PyObject* result;
-    int retval;
+    _RWWrapper *wrapper = (_RWWrapper *) ops->hidden.unknown.data1;
+    PyObject *result;
 
-    if (!helper->read)
+    if (!wrapper->write)
         return -1;
 
-    result = PyObject_CallFunction (helper->read, "i", size * maxnum);
+    result = PyObject_CallFunction (wrapper->write, "s#", ptr, size * num);
     if (!result)
         return -1;
 
-    if (!Bytes_Check (result))
-    {
-        Py_DECREF (result);
-        return -1;
-    }
-
-    retval = Bytes_GET_SIZE (result);
-    memcpy (ptr, Bytes_AS_STRING (result), (size_t) retval);
-    retval /= size;
-
-    Py_DECREF (result);
-    return retval;
-}
-
-static int
-rw_write (SDL_RWops* context, const void* ptr, int size, int num)
-{
-    _RWHelper* helper = (_RWHelper*) context->hidden.unknown.data1;
-    PyObject* result;
-
-    if (!helper->write)
-        return -1;
-
-    result = PyObject_CallFunction (helper->write, "s#", ptr, size * num);
-    if(!result)
-        return -1;
-
     Py_DECREF (result);
     return num;
 }
 
 static int
-rw_close (SDL_RWops* context)
+_pyobj_close (SDL_RWops *ops)
 {
-    _RWHelper* helper = (_RWHelper*) context->hidden.unknown.data1;
-    PyObject* result;
+    _RWWrapper *wrapper = (_RWWrapper *) ops->hidden.unknown.data1;
+    PyObject *result;
     int retval = 0;
 
-    if (helper->close)
+    if (wrapper->close)
     {
-        result = PyObject_CallFunction (helper->close, NULL);
+        result = PyObject_CallFunction (wrapper->close, NULL);
         if (result)
             retval = -1;
         Py_XDECREF (result);
     }
 
-    Py_XDECREF (helper->seek);
-    Py_XDECREF (helper->tell);
-    Py_XDECREF (helper->write);
-    Py_XDECREF (helper->read);
-    Py_XDECREF (helper->close);
-    PyMem_Del (helper);
-    SDL_FreeRW (context);
+    Py_XDECREF (wrapper->seek);
+    Py_XDECREF (wrapper->tell);
+    Py_XDECREF (wrapper->write);
+    Py_XDECREF (wrapper->read);
+    Py_XDECREF (wrapper->close);
+    PyMem_Del (wrapper);
+    SDL_FreeRW (ops);
     return retval;
 }
 
-#ifdef WITH_THREAD
-static int
-rw_seek_th (SDL_RWops* context, int offset, int whence)
+/* C API */
+static SDL_RWops*
+PyRWops_NewRO (PyObject *obj, int *canautoclose)
 {
-    _RWHelper* helper = (_RWHelper*) context->hidden.unknown.data1;
-    PyObject* result;
-    int retval;
-    PyThreadState* oldstate;
-
-    if (!helper->seek || !helper->tell)
-        return -1;
-
-    PyEval_AcquireLock ();
-    oldstate = PyThreadState_Swap (helper->thread);
-
-    /* being seek'd, not just tell'd */
-    if (!(offset == 0 && whence == SEEK_CUR))
+    _RWWrapper *wrapper;
+    SDL_RWops *ops;
+    
+    if (!obj || !canautoclose)
     {
-        result = PyObject_CallFunction (helper->seek, "ii", offset, whence);
-        if(!result)
-        {
-            PyErr_Print();
-            retval = -1;
-            goto end;
-        }
-        Py_DECREF (result);
+        PyErr_SetString (PyExc_TypeError, "argument is NULL");
+        return NULL;
+    }
+    
+    /* If we have a text object, assume it is a file, which is automatically
+     * closed. */
+    if (IsTextObj (obj))
+    {
+        PyObject *tmp;
+        char *filename;
+        if (!UTF8FromObject (obj, &filename, &tmp))
+            return NULL;
+        Py_XDECREF (tmp);
+        *canautoclose = 1;
+        return SDL_RWFromFile ((const char *)filename, "rb");
     }
 
-    result = PyObject_CallFunction (helper->tell, NULL);
-    if (!result)
+    /* No text object, so its a buffer or something like that. Try to get the
+     * necessary information. */
+    ops = SDL_AllocRW ();
+    if (!ops)
+        return NULL;
+    wrapper = PyMem_New (_RWWrapper, 1);
+    if (!wrapper)
     {
-        PyErr_Print();
-        retval = -1;
-        goto end;
-    }
-
-    retval = PyInt_AsLong (result);
-    Py_DECREF (result);
-
-end:
-    PyThreadState_Swap (oldstate);
-    PyEval_ReleaseLock ();
-
-    return retval;
-}
-
-static int
-rw_read_th (SDL_RWops* context, void* ptr, int size, int maxnum)
-{
-    _RWHelper* helper = (_RWHelper*) context->hidden.unknown.data1;
-    PyObject* result;
-    int retval;
-    PyThreadState* oldstate;
-
-    if (!helper->read)
-        return -1;
-
-    PyEval_AcquireLock ();
-    oldstate = PyThreadState_Swap (helper->thread);
-
-    result = PyObject_CallFunction (helper->read, "i", size * maxnum);
-    if (!result)
-    {
-        PyErr_Print();
-        retval = -1;
-        goto end;
-    }
-
-    if (!Bytes_Check (result))
-    {
-        Py_DECREF (result);
-        PyErr_Print();
-        retval = -1;
-        goto end;
-    }
-
-    retval = Bytes_GET_SIZE (result);
-    memcpy (ptr, Bytes_AS_STRING (result), (size_t) retval);
-    retval /= size;
-
-    Py_DECREF (result);
-
-end:
-    PyThreadState_Swap (oldstate);
-    PyEval_ReleaseLock ();
-
-    return retval;
-}
-
-static int
-rw_write_th (SDL_RWops* context, const void* ptr, int size, int num)
-{
-    _RWHelper* helper = (_RWHelper*) context->hidden.unknown.data1;
-    PyObject* result;
-    int retval;
-    PyThreadState* oldstate;
-
-    if (!helper->write)
-        return -1;
-
-    PyEval_AcquireLock ();
-    oldstate = PyThreadState_Swap (helper->thread);
-
-    result = PyObject_CallFunction (helper->write, "s#", ptr, size * num);
-    if (!result)
-    {
-        PyErr_Print();
-        retval = -1;
-        goto end;
-    }
-
-    Py_DECREF (result);
-    retval = num;
-
-end:
-    PyThreadState_Swap (oldstate);
-    PyEval_ReleaseLock ();
-
-    return retval;
-}
-
-static int
-rw_close_th (SDL_RWops* context)
-{
-    _RWHelper* helper = (_RWHelper*) context->hidden.unknown.data1;
-    PyObject* result;
-    int retval = 0;
-    PyThreadState* oldstate;
-
-    PyEval_AcquireLock ();
-    oldstate = PyThreadState_Swap (helper->thread);
-
-    if (helper->close)
-    {
-        result = PyObject_CallFunction (helper->close, NULL);
-        if (!result)
-        {
-            PyErr_Print();
-            retval = -1;
-        }
-        Py_XDECREF (result);
-    }
-
-    Py_XDECREF (helper->seek);
-    Py_XDECREF (helper->tell);
-    Py_XDECREF (helper->write);
-    Py_XDECREF (helper->read);
-    Py_XDECREF (helper->close);
-
-    PyThreadState_Swap (oldstate);
-    PyThreadState_Clear (helper->thread);
-    PyThreadState_Delete (helper->thread);
-
-    PyMem_Del (helper);
-
-    PyEval_ReleaseLock ();
-
-    SDL_FreeRW (context);
-    return retval;
-}
-#endif
-
-/* C API */
-static SDL_RWops*
-RWopsFromPython (PyObject* obj)
-{
-    SDL_RWops* rw;
-    _RWHelper* helper;
-
-    if (!obj)
-    {
-        PyErr_SetString (PyExc_TypeError, "Invalid filetype object");
+        SDL_FreeRW (ops);
         return NULL;
     }
-    rw = get_standard_rwop (obj);
-    if (rw)
-        return rw;
-
-    helper = PyMem_New (_RWHelper, 1);
-    fetch_object_methods (helper, obj);
-
-    rw = SDL_AllocRW ();
-    rw->hidden.unknown.data1 = (void*) helper;
-    rw->seek = rw_seek;
-    rw->read = rw_read;
-    rw->write = rw_write;
-    rw->close = rw_close;
-
-    return rw;
-}
-
-static int
-RWopsCheckPython (SDL_RWops* rw)
-{
-    if (!rw)
-    {
-        PyErr_SetString (PyExc_TypeError, "rw must not be NULL");
-        return -1;
-    }
-    return rw->close == rw_close;
+    _bind_python_methods (wrapper, obj);
+    
+    ops->read = _pyobj_read;
+    ops->write = _pyobj_write;
+    ops->seek = _pyobj_seek;
+    ops->close = _pyobj_close;
+    ops->hidden.unknown.data1 = (void*) wrapper;
+    *canautoclose = 0;
+    return ops;
 }
 
 static SDL_RWops*
-RWopsFromPythonThreaded (PyObject* obj)
+PyRWops_NewRW (PyObject *obj, int *canautoclose)
 {
-    SDL_RWops* rw;
-    _RWHelper* helper;
-    PyInterpreterState* interp;
-    PyThreadState* thread;
-
-    if (!obj)
+    _RWWrapper *wrapper;
+    SDL_RWops *ops;
+    
+    if (!obj || !canautoclose)
     {
-        PyErr_SetString (PyExc_TypeError, "Invalid filetype object");
+        PyErr_SetString (PyExc_TypeError, "argument is NULL");
         return NULL;
     }
+    
+    /* If we have a text object, assume it is a file, which is automatically
+     * closed. */
+    if (IsTextObj (obj))
+    {
+        PyObject *tmp;
+        char *filename;
+        if (!UTF8FromObject (obj, &filename, &tmp))
+            return NULL;
+        Py_XDECREF (tmp);
+        *canautoclose = 1;
+        return SDL_RWFromFile ((const char *)filename, "wb");
+    }
 
-#ifndef WITH_THREAD
-    PyErr_SetString (PyExc_NotImplementedError,
-        "Python built without thread support");
-    return NULL;
-#else
-    helper = PyMem_New (_RWHelper, 1);
-    fetch_object_methods (helper, obj);
-
-    rw = SDL_AllocRW ();
-    rw->hidden.unknown.data1 = (void*) helper;
-    rw->seek = rw_seek_th;
-    rw->read = rw_read_th;
-    rw->write = rw_write_th;
-    rw->close = rw_close_th;
-
-    PyEval_InitThreads ();
-    thread = PyThreadState_Get ();
-    interp = thread->interp;
-    helper->thread = PyThreadState_New (interp);
-
-    return rw;
-#endif
+    /* No text object, so its a buffer or something like that. Try to get the
+     * necessary information. */
+    ops = SDL_AllocRW ();
+    if (!ops)
+        return NULL;
+    wrapper = PyMem_New (_RWWrapper, 1);
+    if (!wrapper)
+    {
+        SDL_FreeRW (ops);
+        return NULL;
+    }
+    _bind_python_methods (wrapper, obj);
+    ops->read = _pyobj_read;
+    ops->write = _pyobj_write;
+    ops->seek = _pyobj_seek;
+    ops->close = _pyobj_close;
+    ops->hidden.unknown.data1 = (void*) wrapper;
+    *canautoclose = 0;
+    return ops;
 }
 
-static int
-RWopsCheckPythonThreaded (SDL_RWops* rw)
+static void
+PyRWops_Close (SDL_RWops *ops, int canautoclose)
 {
-#ifdef WITH_THREAD
-    if (!rw)
+    /* internal _RWWrapper? */
+    if (ops->close == _pyobj_close)
     {
-        PyErr_SetString (PyExc_TypeError, "rw must not be NULL");
-        return -1;
+        if (!canautoclose) /* Do not close the underlying object. */
+        {
+            _RWWrapper *wrapper = (_RWWrapper *) ops->hidden.unknown.data1;
+            Py_DECREF (wrapper->close);
+            wrapper->close = NULL;
+        }
     }
-    return rw->close == rw_close_th;
-#else
-    return 0;
-#endif
+    SDL_RWclose (ops);
 }
 
 #ifdef IS_PYTHON_3
     if (!mod)
         goto fail;
 
-    c_api[PYGAME_SDLRWOPS_FIRSTSLOT+0] = RWopsFromPython;
-    c_api[PYGAME_SDLRWOPS_FIRSTSLOT+1] = RWopsCheckPython;
-    c_api[PYGAME_SDLRWOPS_FIRSTSLOT+2] = RWopsFromPythonThreaded;
-    c_api[PYGAME_SDLRWOPS_FIRSTSLOT+3] = RWopsCheckPythonThreaded;
-
+    c_api[PYGAME_SDLRWOPS_FIRSTSLOT] = PyRWops_NewRO;
+    c_api[PYGAME_SDLRWOPS_FIRSTSLOT+1] = PyRWops_NewRW;
+    c_api[PYGAME_SDLRWOPS_FIRSTSLOT+2] = PyRWops_Close;
+    
     c_api_obj = PyCObject_FromVoidPtr ((void *) c_api, NULL);
     if (c_api_obj)
         PyModule_AddObject (mod, PYGAME_SDLRWOPS_ENTRY, c_api_obj);    
 
+    if (import_pygame2_base () < 0)
+        goto fail;
+
     MODINIT_RETURN(mod);
 fail:
     Py_XDECREF (mod);

src/sdl/surface.c

 
     surface = ((PySDLSurface*)self)->surface;
 
+    /* TODO: full RWops support for all types! */
     if (IsTextObj (file))
     {
         PyObject *tmp;
 #endif
     {
         SDL_RWops* rw;
+        int autoclose;
         
         /* If the type is NULL, we assume TGA saving. */
         if (!type)
             type = "TGA";
 
-        if (!(rw = RWopsFromPython (file)))
+        rw = PyRWops_NewRW (file, &autoclose);
+        if (!rw)
             return NULL;
         Py_BEGIN_ALLOW_THREADS;
         retval = pyg_sdlsurface_save_rw (surface, rw, type);
         Py_END_ALLOW_THREADS;
+        
+        if (!autoclose)
+            PyRWops_Close (rw, autoclose);
     }
     else
     {

src/sdl/surface_save.c

         }
         else
         {
-            SDL_SetError ("unknown file type");
+            SDL_SetError ("unsupported file type for RWops saving");
             if (tmpsf)
                 SDL_FreeSurface (tmpsf);
             return 0;

src/sdlimage/imagemod.c

     char *filename, *type = NULL;
     SDL_Surface *surface = NULL;
     PyObject *sf, *file;
+    SDL_RWops *rw;
+    int autoclose;
     
     ASSERT_VIDEO_INIT (NULL);
     
     if (!PyArg_ParseTuple (args, "O|s:load", &file, &type))
         return NULL;
 
-    if (IsTextObj (file))
+    rw = PyRWops_NewRO (file, &autoclose);
+    if (!rw)
+        return -1;
+
+    if (type)
     {
-        PyObject *tmp;
-        if (!UTF8FromObject (file, &filename, &tmp))
-            return NULL;
-
-        if (type)
-        {
-            /* If the type's set, it has precedence over the filename. */
-            Py_BEGIN_ALLOW_THREADS;
-            surface = IMG_LoadTyped_RW (SDL_RWFromFile (filename, "rb"), 1,
-                type);
-            Py_END_ALLOW_THREADS;
-        }
-        else
-        {
-            Py_BEGIN_ALLOW_THREADS;
-            surface = IMG_Load (filename);
-            Py_END_ALLOW_THREADS;
-        }
-        Py_XDECREF (tmp);
-    }
-#ifdef IS_PYTHON_3
-    else if (PyObject_AsFileDescriptor (file) != -1)
-#else
-    else if (PyFile_Check (file))
-#endif
-    {
-        SDL_RWops *rw = RWopsFromPython (file);
-        if (!rw)
-            return NULL;
-
-        if (type)
-        {
-            Py_BEGIN_ALLOW_THREADS;
-            surface = IMG_LoadTyped_RW (rw, 1, type);
-            Py_END_ALLOW_THREADS;
-        }
-        else
-        {
-            Py_BEGIN_ALLOW_THREADS;
-            surface = IMG_Load_RW (rw, 1);
-            Py_END_ALLOW_THREADS;
-        }
+        /* If the type's set, it has precedence over the filename. */
+        Py_BEGIN_ALLOW_THREADS;
+        surface = IMG_LoadTyped_RW (rw, autoclose, type);
+        Py_END_ALLOW_THREADS;
     }
     else
     {
-#ifdef IS_PYTHON_3
-        PyErr_Clear (); /* Set by PyObject_AsFileDescriptor() */
-#endif
-        PyErr_SetString (PyExc_TypeError, "file must be a string or file");
-        return NULL;
+        Py_BEGIN_ALLOW_THREADS;
+        surface = IMG_Load_RW (rw, autoclose);
+        Py_END_ALLOW_THREADS;
     }
-
+    
+    if (!autoclose)
+        PyRWops_Close (rw, autoclose);
+    
     if (!surface)
     {
         PyErr_SetString (PyExc_PyGameError, IMG_GetError ());

src/sdlmixer/chunk.c

     char *filename;
     PyObject *file;
     Mix_Chunk *chunk;
+    SDL_RWops *rw;
+    int autoclose;
 
     ASSERT_MIXER_OPEN (-1);
     
     if (!PyArg_ParseTuple (args, "O", &file))
         return -1;
 
-    if (IsTextObj (file))
-    {
-        PyObject *tmp;
-        if (!UTF8FromObject (file, &filename, &tmp))
-            return -1;
+    rw = PyRWops_NewRO (file, &autoclose);
+    if (!rw)
+        return -1;
 
-        Py_BEGIN_ALLOW_THREADS;
-        chunk = Mix_LoadWAV (filename);
-        Py_END_ALLOW_THREADS;
-        Py_XDECREF (tmp);
-    }
-#ifdef IS_PYTHON_3
-    else if (PyObject_AsFileDescriptor (file) != -1)
-#else
-    else if (PyFile_Check (file))
-#endif
-    {
-        SDL_RWops *rw = RWopsFromPython (file);
-        if (!rw)
-            return -1;
-
-        Py_BEGIN_ALLOW_THREADS;
-        chunk = Mix_LoadWAV_RW (rw, 1);
-        Py_END_ALLOW_THREADS;
-    }
-    else
-    {
-#ifdef IS_PYTHON_3
-        PyErr_Clear (); /* Set by PyObject_AsFileDescriptor () */
-#endif
-        PyErr_SetString (PyExc_TypeError, "file must be string for file");
-        return -1;
-    }
-
-    if (!chunk)
-    {
-        PyErr_SetString (PyExc_PyGameError, Mix_GetError ());
-        return -1;
-    }
+    Py_BEGIN_ALLOW_THREADS;
+    chunk = Mix_LoadWAV_RW (rw, autoclose);
+    Py_END_ALLOW_THREADS;
+    
+    if (!autoclose)
+        PyRWops_Close (rw, autoclose);
     
     ((PyChunk*)self)->chunk = chunk;
     ((PyChunk*)self)->playchannel = -1;

src/sdlmixer/music.c

     PyObject *file;
     char *filename;
     Mix_Music *music;
+    SDL_RWops *rw;
+    int autoclose;
     
     ASSERT_MIXER_OPEN (-1);
     
     if (!PyArg_ParseTuple (args, "O", &file))
         return -1;
 
-    if (IsTextObj (file))
-    {
-        PyObject *tmp;
-        if (!UTF8FromObject (file, &filename, &tmp))
-            return -1;
+    rw = PyRWops_NewRO (file, &autoclose);
+    if (!rw)
+        return -1;
 
-        Py_BEGIN_ALLOW_THREADS;
-        music = Mix_LoadMUS (filename);
-        Py_END_ALLOW_THREADS;
-        Py_XDECREF (tmp);
-    }
-#ifdef IS_PYTHON_3
-    else if (PyObject_AsFileDescriptor (file) != -1)
-#else
-    else if (PyFile_Check (file))
-#endif
-    {
-        SDL_RWops *rw = RWopsFromPython (file);
-        if (!rw)
-            return -1;
+    Py_BEGIN_ALLOW_THREADS;
+    music = Mix_LoadMUS_RW (rw);
+    Py_END_ALLOW_THREADS;
 
-        Py_BEGIN_ALLOW_THREADS;
-        music = Mix_LoadMUS_RW (rw);
-        Py_END_ALLOW_THREADS;
-    }
-    else
-    {
-#ifdef IS_PYTHON_3
-        PyErr_Clear (); /* Set by PyObject_AsFileDescriptor(). */
-#endif
-        PyErr_SetString (PyExc_TypeError, "file must be a string or file");
-        return -1;
-    }
-
+    if (!autoclose)
+        PyRWops_Close (rw, autoclose);
+    
     if (!music)
     {
         PyErr_SetString (PyExc_PyGameError, Mix_GetError ());
         return -1;
     }
-    
+
     ((PyMusic*)self)->music = music;
     return 0;
 }

src/sdlttf/font.c

     PyObject *file;
     int ptsize, _index = 0;
     TTF_Font *font;
+    SDL_RWops *rw;
+    int autoclose;
 
     ASSERT_TTF_INIT (-1);
     if (!PyArg_ParseTuple (args, "Oi|i", &file, &ptsize, &_index))
         return -1;
     }
 
-    if (IsTextObj (file))
-    {
-        char *filename;
-        PyObject *tmp;
+    rw = PyRWops_NewRO (file, &autoclose);
+    if (!rw)
+        return -1;
 
-        if (!UTF8FromObject (file, &filename, &tmp))
-            return -1;
-
-        Py_BEGIN_ALLOW_THREADS;
-        if (_index == 0)
-            font = TTF_OpenFont (filename, ptsize);
-        else
-            font = TTF_OpenFontIndex (filename, ptsize, _index);
-        Py_END_ALLOW_THREADS;
-
-        Py_XDECREF (tmp);
-    }
-#ifdef IS_PYTHON_3
-    else if (PyObject_AsFileDescriptor (file) != -1)
-#else
-    else if (PyFile_Check (file))
-#endif
-    {
-        SDL_RWops *rw = RWopsFromPython (file);
-        if (!rw)
-            return -1;
-
-        Py_BEGIN_ALLOW_THREADS;
-        if (_index == 0)
-            font = TTF_OpenFontRW (rw, 1, ptsize);
-        else
-            font = TTF_OpenFontIndexRW (rw, 1, ptsize, _index);
-        Py_END_ALLOW_THREADS;
-    }
+    Py_BEGIN_ALLOW_THREADS;
+    if (_index == 0)
+        font = TTF_OpenFontRW (rw, autoclose, ptsize);
     else
-    {
-#ifdef IS_PYTHON_3
-        PyErr_Clear (); /* Set by PyObject_AsFileDescriptor() */
-#endif
-        PyErr_SetString (PyExc_TypeError, "file must be a string or file");
-        return -1;
-    }
-
+        font = TTF_OpenFontIndexRW (rw, autoclose, ptsize, _index);
+    Py_END_ALLOW_THREADS;
+    
+    if (!autoclose)
+        PyRWops_Close (rw, autoclose);
+    
     if (!font)
     {
         PyErr_SetString (PyExc_PyGameError, TTF_GetError ());

test/sdl_base_test.py

         # combination of the INIT_* constants.  In case an error occured,
         # False will be returned. The detailled error can be received using
         # pygame2.sdl.get_error().
-        self.assertEquals (base.init (constants.INIT_VIDEO), True)
+        self.assertEquals (base.init (constants.INIT_CDROM), True)
         self.assertEquals (base.init
-                           (constants.INIT_VIDEO | constants.INIT_AUDIO), True)
+                           (constants.INIT_CDROM | constants.INIT_AUDIO), True)
 
     def test_pygame2_sdl_base_init_subsystem(self):
 
         # Gets a bitwise OR'ed combination of the initialized SDL subsystems.
         # Returns a bitwise combination of the currently initialized SDL
         # subsystems.
-        base.init (constants.INIT_VIDEO)
-        v = base.was_init (constants.INIT_VIDEO) & constants.INIT_VIDEO
-        self.assert_ (v == constants.INIT_VIDEO)
+        base.init (constants.INIT_JOYSTICK)
+        v = base.was_init (constants.INIT_JOYSTICK) & constants.INIT_JOYSTICK
+        self.assert_ (v == constants.INIT_JOYSTICK)

test/sdl_keyboard_test.py

         # handling state.  By default unicode handling is enabled and for
         # keyboard events, the *unicode* member of the event will be filled
         # with the corresponding unicode character.
-        self.assert_ (keyboard.enable_unicode () == False)
-        self.assert_ (keyboard.enable_unicode (True) == False)
+        self.assert_ (keyboard.enable_unicode () == True)
+        self.assert_ (keyboard.enable_unicode (True) == True)
         self.assert_ (keyboard.enable_unicode (False) == True)
         self.assert_ (keyboard.enable_unicode (True) == False)
         self.assert_ (keyboard.enable_unicode (True) == True)
         keyboard.enable_repeat (7, 0)
         self.assert_ (keyboard.get_repeat () == (7, 0))
 
-    def todo_test_pygame2_sdl_keyboard_get_state(self):
+    def test_pygame2_sdl_keyboard_get_state(self):
 
         # __doc__ (as of 2009-05-13) for pygame2.sdl.keyboard.get_state:
 
         # dictionary with the current keyboard state. The keys of the
         # dictionary are the key constants, the boolean values of the
         # dictionary indicate, whether a certain key is pressed or not.
-
-        self.fail() 
+        self.assert_ (type (keyboard.get_state ()) == dict)
+        self.assert_ (constants.K_a in keyboard.get_state ().keys ())
+        self.assert_ (constants.K_b in keyboard.get_state ().keys ())
+        self.assert_ (constants.K_q in keyboard.get_state ().keys ())
+        self.assert_ (constants.K_KP4 in keyboard.get_state ().keys ())
 
     def todo_test_pygame2_sdl_keyboard_set_mod_state(self):