Anonymous avatar Anonymous committed 84e9391

Added basic openal.CaptureDevice implementation.
Fixed threading issues in openal device handling.
Improved msys environment detection and make targets.
Fixed memory leaks in openal.Buffers and openal.Sources.

Comments (0)

Files changed (14)

 PYTHON = python
+COMPILER = ''
 # Set this to 0 on releases.
 EXPERIMENTAL = 1
 top_srcdir = `pwd`
 	$(top_srcdir)/src/sdlmixer \
 	$(top_srcdir)/src/sdlttf
 
-
 all: clean build
 
 dist: clean docs
 	@$(PYTHON) setup.py bdist
 
 build:
-	@echo "Running build..."
-	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) $(PYTHON) setup.py build #-c mingw32
+	@if test -n $(COMPILER); then \
+        echo "Running build with $(COMPILER)..."; \
+		WITH_EXPERIMENTAL=$(EXPERIMENTAL) $(PYTHON) setup.py build -c $(COMPILER); \
+	else \
+        echo "Running build"; \
+		WITH_EXPERIMENTAL=$(EXPERIMENTAL) $(PYTHON) setup.py build; \
+	fi
 	@echo "Build finished, invoke 'make install' to install."
 
-clang: clean
-	@echo "Running build with Clang..."
-	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) $(PYTHON) setup.py build -c clang
-	@echo "Build finished, invoke 'make install' to install."
+clang: COMPILER = clang
+clang: all
+
+msys: COMPILER = mingw32
+msys: all
 
 install:
 	@echo "Installing..."
 # purposes only!
 
 buildall: clean
-	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.4 setup.py build
-	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.5 setup.py build
-	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.6 setup.py build
-	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python3.1 setup.py build
+	@if test -n $(COMPILER); then \
+		WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.4 setup.py build -c $(COMPILER); \
+		WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.5 setup.py build -c $(COMPILER); \
+		WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.6 setup.py build -c $(COMPILER); \
+		WITH_EXPERIMENTAL=$(EXPERIMENTAL) python3.1 setup.py build -c $(COMPILER); \
+	else \
+		WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.4 setup.py build; \
+		WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.5 setup.py build; \
+		WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.6 setup.py build; \
+		WITH_EXPERIMENTAL=$(EXPERIMENTAL) python3.1 setup.py build; \
+	fi
 
-buildallclang: clean
-	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.4 setup.py build -c clang
-	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.5 setup.py build -c clang
-	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.6 setup.py build -c clang
-	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python3.1 setup.py build -c clang
+buildallclang: COMPILER = clang
+buildallclang: buildall
 
 installall:
 	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.4 setup.py install
    has)?
 
 * openal: check integrity and references for sources, buffers and listeners.
+* openal: check for locking issues on closing a CaptureDevice.
 
 Things to ADD:
 ==============
 def is_msys():
     """Return true if the execution environment is MSYS"""
     
-    try:
-        return os.environ['OSTYPE'] == 'msys'
-    except KeyError:
-        return 0
+    if 'OSTYPE' in os.environ:
+        if os.environ['OSTYPE'] == 'msys':
+            return True
+    if 'MSYSCON' in os.environ:
+        return True
+    return False

doc/src/sdlwm.xml

     <call>set_icon (surface[, mask]) -> None</call>
     <desc>
       Sets the window manager icon to be used by the window.
-      
-      .. todo::
-        
-         Not fully implemented.
     </desc>
   </func>
   <func name="toggle_fullscreen">
                     "src/openal/sources.c",
                     "src/openal/listener.c",
                     "src/openal/context.c",
+                    "src/openal/capturedevice.c",
                     "src/openal/device.c" ],
         depends = [ 'openal' ],
         experimental = True),

src/openal/buffers.c

             switched = 1;
         }
         alDeleteBuffers (self->count, self->buffers);
+        PyMem_Free (self->buffers);
         if (switched)
             alcMakeContextCurrent (ctxt);
     }
         return NULL;
     }
 
-    if (!PyArg_ParseTuple (args, "lls", &bufnum, &param, &type))
+    if (!PyArg_ParseTuple (args, "lls:get_prop", &bufnum, &param, &type))
     {
         PyErr_Clear ();
-        if (!PyArg_ParseTuple (args, "ll|si", &bufnum, &param, &type, &size))
+        if (!PyArg_ParseTuple (args, "ll|si:get_prop", &bufnum, &param, &type,
+            &size))
             return NULL;
         if (size <= 0)
         {
     if (SetALErrorException (alGetError ()))
     {
         Py_DECREF (buffers);
+        PyMem_Free (buf);
         return NULL;
     }
 
     ((PyBuffers*)buffers)->buffers = buf;
-
-    
     return buffers;
 }
 

src/openal/capturedevice.c

+/*
+  pygame - Python Game Library
+  Copyright (C) 2010 Marcus von Appen
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Library General Public
+  License as published by the Free Software Foundation; either
+  version 2 of the License, or (at your option) any later version.
+
+  This library 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
+  Library General Public License for more details.
+
+  You should have received a copy of the GNU Library General Public
+  License along with this library; if not, write to the Free
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+#define PYGAME_OPENALCAPTUREDEVICE_INTERNAL
+
+#include "openalmod.h"
+#include "pgopenal.h"
+
+static PyObject* _capturedevice_new (PyTypeObject *type, PyObject *args,
+    PyObject *kwds);
+static int _capturedevice_init (PyObject *self, PyObject *args, PyObject *kwds);
+static void _capturedevice_dealloc (PyCaptureDevice *self);
+static PyObject* _capturedevice_repr (PyObject *self);
+
+static PyObject* _capturedevice_start (PyObject* self);
+static PyObject* _capturedevice_stop (PyObject* self);
+
+static PyObject* _capturedevice_getsize (PyObject *self, void *closure);
+
+/**
+ */
+static PyMethodDef _capturedevice_methods[] = {
+    { "start", (PyCFunction)_capturedevice_start, METH_NOARGS, NULL },
+    { "stop", (PyCFunction)_capturedevice_start, METH_NOARGS, NULL },
+    { NULL, NULL, 0, NULL }
+};
+
+/**
+ */
+static PyGetSetDef _capturedevice_getsets[] = {
+    { "size", _capturedevice_getsize, NULL, NULL, NULL },
+    { NULL, NULL, NULL, NULL, NULL }
+};
+
+/**
+ */
+PyTypeObject PyCaptureDevice_Type =
+{
+    TYPE_HEAD(NULL, 0)
+    "base.CaptureDevice",       /* tp_name */
+    sizeof (PyCaptureDevice),   /* tp_basicsize */
+    0,                          /* tp_itemsize */
+    (destructor) _capturedevice_dealloc, /* tp_dealloc */
+    0,                          /* tp_print */
+    0,                          /* tp_getattr */
+    0,                          /* tp_setattr */
+    0,                          /* tp_compare */
+    (reprfunc)_capturedevice_repr,     /* tp_repr */
+    0,                          /* tp_as_number */
+    0,                          /* tp_as_sequence */
+    0,                          /* tp_as_mapping */
+    0,                          /* tp_hash */
+    0,                          /* tp_call */
+    0,                          /* tp_str */
+    0,                          /* tp_getattro */
+    0,                          /* tp_setattro */
+    0,                          /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+    0/*DOC_BASE_DEVICE*/,
+    0,                          /* tp_traverse */
+    0,                          /* tp_clear */
+    0,                          /* tp_richcompare */
+    0,                          /* tp_weaklistoffset */
+    0,                          /* tp_iter */
+    0,                          /* tp_iternext */
+    _capturedevice_methods,     /* tp_methods */
+    0,                          /* tp_members */
+    _capturedevice_getsets,     /* tp_getset */
+    0,                          /* tp_base */
+    0,                          /* tp_dict */
+    0,                          /* tp_descr_get */
+    0,                          /* tp_descr_set */
+    0,                          /* tp_dictoffset */
+    (initproc) _capturedevice_init,    /* tp_init */
+    0,                          /* tp_alloc */
+    _capturedevice_new,         /* tp_new */
+    0,                          /* tp_free */
+    0,                          /* tp_is_gc */
+    0,                          /* tp_bases */
+    0,                          /* tp_mro */
+    0,                          /* tp_cache */
+    0,                          /* tp_subclasses */
+    0,                          /* tp_weaklist */
+    0,                          /* tp_del */
+#if PY_VERSION_HEX >= 0x02060000
+    0                           /* tp_version_tag */
+#endif
+};
+
+static PyObject*
+_capturedevice_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PyCaptureDevice *device = (PyCaptureDevice *)type->tp_alloc (type, 0);
+    if (!device)
+        return NULL;
+    device->size = 0;
+    device->device.device = NULL;
+    return (PyObject*) device;
+}
+
+static void
+_capturedevice_dealloc (PyCaptureDevice *self)
+{
+    if (self->device.device)
+    {
+        Py_BEGIN_ALLOW_THREADS;
+        alcCaptureCloseDevice (self->device.device);
+        Py_END_ALLOW_THREADS;
+    }
+    self->device.device = NULL;
+    ((PyObject*)self)->ob_type->tp_free ((PyObject *) self);
+}
+
+static int
+_capturedevice_init (PyObject *self, PyObject *args, PyObject *kwds)
+{
+    char *name = NULL;
+    ALCdevice *device = NULL;
+    long bufsize, freq, format;
+    
+    if (!PyArg_ParseTuple (args, "slll", &name, &freq, &format, &bufsize))
+    {
+        PyErr_Clear ();
+        if (!PyArg_ParseTuple (args, "lll", &freq, &format, &bufsize))
+            return -1;
+    }
+
+    if (bufsize <= 0)
+    {
+        PyErr_SetString (PyExc_ValueError,
+            "bufsize must not be smaller than 1");
+        return -1;
+    }
+
+    Py_BEGIN_ALLOW_THREADS;
+    device = alcCaptureOpenDevice ((const ALCchar*)name, (ALCuint) freq,
+        (ALCenum)format, (ALCsizei) bufsize);
+    Py_END_ALLOW_THREADS;
+    if (!device)
+    {
+        SetALErrorException (alGetError ());
+        return -1;
+    }
+    ((PyCaptureDevice*)self)->device.device = device;
+    return 0;
+}
+
+static PyObject*
+_capturedevice_repr (PyObject *self)
+{
+    PyObject *retval;
+    const ALCchar *name = alcGetString (PyCaptureDevice_AsDevice (self),
+        ALC_CAPTURE_DEVICE_SPECIFIER);
+    /* CaptureDevice('') == 17 */
+    size_t len = strlen ((const char*) name) + 18;
+    char *str = malloc (len);
+    if (!str)
+        return NULL;
+
+    snprintf (str, len, "CaptureDevice('%s')", (const char*) name);
+    retval = Text_FromUTF8 (str);
+    free (str);
+    return retval;
+}
+
+/* CaptureDevice getters/setters */
+static PyObject*
+_capturedevice_getsize (PyObject *self, void *closure)
+{
+    return PyInt_FromLong ((long) ((PyCaptureDevice*)self)->size);
+}
+
+/* CaptureDevice methods */
+static PyObject*
+_capturedevice_start (PyObject* self)
+{
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+_capturedevice_stop (PyObject* self)
+{
+    Py_RETURN_NONE;
+}
+
+/* C API */
+PyObject*
+PyCaptureDevice_New (const char* name, ALCuint frequency, ALCenum format,
+    ALCsizei bufsize)
+{
+    ALCdevice *dev;
+    PyObject *device = PyCaptureDevice_Type.tp_new (&PyCaptureDevice_Type,
+        NULL, NULL);
+
+    if (!device)
+        return NULL;
+
+    dev = alcCaptureOpenDevice (name, frequency, format, bufsize);
+    if (!dev)
+    {
+        SetALErrorException (alGetError ());
+        Py_DECREF (device);
+        return NULL;
+    }
+    ((PyCaptureDevice*)device)->device.device = dev;
+    return device;
+}
+
+void
+capturedevice_export_capi (void **capi)
+{
+    capi[PYGAME_OPENALDEVICE_FIRSTSLOT] = &PyCaptureDevice_Type;
+    capi[PYGAME_OPENALDEVICE_FIRSTSLOT+1] = (void *)PyCaptureDevice_New;
+}

src/openal/device.c

 _device_dealloc (PyDevice *self)
 {
     if (self->device)
+    {
+        Py_BEGIN_ALLOW_THREADS;
         alcCloseDevice (self->device);
+        Py_END_ALLOW_THREADS;
+    }
     self->device = NULL;
     ((PyObject*)self)->ob_type->tp_free ((PyObject *) self);
 }
     if (!PyArg_ParseTuple (args, "|s", &name))
         return -1;
     
+    Py_BEGIN_ALLOW_THREADS;
     device = alcOpenDevice (name);
+    Py_END_ALLOW_THREADS;
     if (!device)
     {
         SetALErrorException (alGetError ());

src/openal/listener.c

         return NULL;
     }
 
-    if (!PyArg_ParseTuple (args, "ls", &param, &type))
+    if (!PyArg_ParseTuple (args, "ls:get_prop", &param, &type))
     {
         PyErr_Clear ();
-        if (!PyArg_ParseTuple (args, "l|si", &param, &type, &size))
+        if (!PyArg_ParseTuple (args, "l|si:get_prop", &param, &type, &size))
             return NULL;
         if (size <= 0)
         {

src/openal/openalmod.c

     PyDevice_Type.tp_new = PyType_GenericNew;
     if (PyType_Ready (&PyDevice_Type) < 0)
         goto fail;
+    PyCaptureDevice_Type.tp_base = &PyDevice_Type;
+    if (PyType_Ready (&PyCaptureDevice_Type) < 0)
+        goto fail;
     PyContext_Type.tp_new = PyType_GenericNew;
     if (PyType_Ready (&PyContext_Type) < 0)
         goto fail;
         goto fail;
     
     ADD_OBJ_OR_FAIL (mod, "Device", PyDevice_Type, fail);
+    ADD_OBJ_OR_FAIL (mod, "CaptureDevice", PyCaptureDevice_Type, fail);
     ADD_OBJ_OR_FAIL (mod, "Context", PyContext_Type, fail);
     ADD_OBJ_OR_FAIL (mod, "Buffers", PyBuffers_Type, fail);
     ADD_OBJ_OR_FAIL (mod, "Sources", PySources_Type, fail);
     ADD_OBJ_OR_FAIL (mod, "Listener", PyListener_Type, fail);
 
     device_export_capi (c_api);
+    capturedevice_export_capi (c_api);
     context_export_capi (c_api);
     buffers_export_capi (c_api);
     sources_export_capi (c_api);

src/openal/openalmod.h

 
 #define PYGAME_OPENAL_INTERNAL
 #define PYGAME_OPENALDEVICE_INTERNAL
+#define PYGAME_OPENALCAPTUREDEVICE_INTERNAL
 #define PYGAME_OPENALCONTEXT_INTERNAL
 #define PYGAME_OPENALBUFFERS_INTERNAL
 #define PYGAME_OPENALSOURCES_INTERNAL
 #define PyDevice_Check(x) (PyObject_TypeCheck (x, &PyDevice_Type))
 PyObject* PyDevice_New (const char *name);
 
+extern PyTypeObject PyCaptureDevice_Type;
+#define PyCaptureDevice_Check(x) (PyObject_TypeCheck (x, &PyCaptureDevice_Type))
+PyObject* PyCaptureDevice_New (const char* name, ALCuint frequency,
+    ALCenum format, ALCsizei bufsize);
+
 extern PyTypeObject PyContext_Type;
 #define PyContext_Check(x) (PyObject_TypeCheck (x, &PyContext_Type))
 
 #define CLEAR_ERROR_STATE() alGetError()
 
 void device_export_capi (void **capi);
+void capturedevice_export_capi (void **capi);
 void context_export_capi (void **capi);
 void buffers_export_capi (void **capi);
 void sources_export_capi (void **capi);

src/openal/pgopenal.h

 {
     PyObject_HEAD
     ALCdevice *device;
-    ALuint    *buffers;
-    int        bufsize;
 } PyDevice;
 #define PyDevice_AsDevice(x) (((PyDevice*)x)->device)
 #define PYGAME_OPENALDEVICE_FIRSTSLOT                   \
 
 typedef struct
 {
+    PyDevice device;
+    ALCsizei size;
+} PyCaptureDevice;
+#define PyCaptureDevice_AsDevice(x) (((PyCaptureDevice*)x)->device.device)
+#define PYGAME_OPENALCAPTUREDEVICE_FIRSTSLOT                   \
+    (PYGAME_OPENALDEVICE_FIRSTSLOT + PYGAME_OPENALDEVICE_NUMSLOTS)
+#define PYGAME_OPENALCAPTUREDEVICE_NUMSLOTS 2
+#ifndef PYGAME_OPENALCAPTUREDEVICE_INTERNAL
+#define PyCaptureDevice_Type                                            \
+    (*(PyTypeObject*)PyGameOpenAL_C_API[PYGAME_OPENALCAPTUREDEVICE_FIRSTSLOT+0])
+#define PyCaptureDevice_Check(x)                                        \
+    (PyObject_TypeCheck(x,                                              \
+        (PyTypeObject*)PyGameOpenAL_C_API[PYGAME_OPENALCAPTUREDEVICE_FIRSTSLOT+0]))
+#define PyCaptureDevice_New                                             \
+    (*(PyObject*(*)(const char*,ALCuint,ALCenum,ALCsizei))PyGameOpenAL_C_API[PYGAME_OPENALCAPTUREDEVICE_FIRSTSLOT+1])
+#endif /* PYGAME_OPENALCAPTUREDEVICE_INTERNAL */
+
+typedef struct
+{
     PyObject_HEAD
     ALCcontext *context;
     PyObject   *device;
         return (ret);                                                   \
     }
 #define PYGAME_OPENALCONTEXT_FIRSTSLOT                                  \
-    (PYGAME_OPENALDEVICE_FIRSTSLOT + PYGAME_OPENALDEVICE_NUMSLOTS)
+    (PYGAME_OPENALCAPTUREDEVICE_FIRSTSLOT + PYGAME_OPENALCAPTUREDEVICE_NUMSLOTS)
 #define PYGAME_OPENALCONTEXT_NUMSLOTS 1
 #ifndef PYGAME_OPENALCONTEXT_INTERNAL
 #define PyContext_Type                                                  \

src/openal/sources.c

 static PyObject* _sources_pause (PyObject *self, PyObject *args);
 static PyObject* _sources_stop (PyObject *self, PyObject *args);
 static PyObject* _sources_rewind (PyObject *self, PyObject *args);
+static PyObject* _sources_queuebuffers (PyObject *self, PyObject *args);
+static PyObject* _sources_unqueuebuffers (PyObject *self, PyObject *args);
 
 static PyObject* _sources_getcount (PyObject* self, void *closure);
 static PyObject* _sources_getsources (PyObject* self, void *closure);
     { "pause", _sources_pause, METH_O, NULL },
     { "stop", _sources_stop, METH_O, NULL },
     { "rewind", _sources_rewind, METH_O, NULL },
+    { "queue_buffers", _sources_queuebuffers, METH_VARARGS, NULL },
+    { "unqueue_buffers", _sources_unqueuebuffers, METH_VARARGS, NULL },
     { NULL, NULL, 0, NULL }
 };
 
             switched = 1;
         }
         alDeleteSources (self->count, self->sources);
+        PyMem_Free (self->sources);
         if (switched)
             alcMakeContextCurrent (ctxt);
     }
         return NULL;
     }
 
-    if (!PyArg_ParseTuple (args, "lls", &bufnum, &param, &type))
+    if (!PyArg_ParseTuple (args, "lls:get_prop", &bufnum, &param, &type))
     {
         PyErr_Clear ();
-        if (!PyArg_ParseTuple (args, "ll|si", &bufnum, &param, &type, &size))
+        if (!PyArg_ParseTuple (args, "ll|si:get_prop", &bufnum, &param, &type,
+            &size))
             return NULL;
         if (size <= 0)
         {
     return _sources_action (self, args, REWIND);
 }
 
+static PyObject*
+_sources_queuebuffers (PyObject *self, PyObject *args)
+{
+    PyObject *buffers;
+    long bufnum;
+    
+    if (!CONTEXT_IS_CURRENT (((PySources*)self)->context))
+    {
+        PyErr_SetString (PyExc_PyGameError, "source context is not current");
+        return NULL;
+    }
+    
+    if (!PyArg_ParseTuple (args, "lO:queue_buffers", &bufnum, &buffers))
+        return NULL;
+    
+    if (bufnum < 0 || bufnum > ((PySources*)self)->count)
+    {
+        PyErr_SetString (PyExc_ValueError, "source index out of range");
+        return NULL;
+    }
+    if (!PyBuffers_Check (buffers))
+    {
+        PyErr_SetString (PyExc_TypeError, "argument must be a Buffers object");
+        return NULL;
+    }
+    
+    CLEAR_ERROR_STATE ();
+    alSourceQueueBuffers ((ALuint) bufnum, ((PyBuffers*)buffers)->count,
+        PyBuffers_AsBuffers(buffers));
+    if (SetALErrorException (alGetError ()))
+        return NULL;
+    
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+_sources_unqueuebuffers (PyObject *self, PyObject *args)
+{
+    PyObject *buffers;
+    long bufnum;
+    
+    if (!CONTEXT_IS_CURRENT (((PySources*)self)->context))
+    {
+        PyErr_SetString (PyExc_PyGameError, "source context is not current");
+        return NULL;
+    }
+    
+    if (!PyArg_ParseTuple (args, "lO:unqueue_buffers", &bufnum, &buffers))
+        return NULL;
+    
+    if (bufnum < 0 || bufnum > ((PySources*)self)->count)
+    {
+        PyErr_SetString (PyExc_ValueError, "source index out of range");
+        return NULL;
+    }
+    if (!PyBuffers_Check (buffers))
+    {
+        PyErr_SetString (PyExc_TypeError, "argument must be a Buffers object");
+        return NULL;
+    }
+    
+    CLEAR_ERROR_STATE ();
+    alSourceUnqueueBuffers ((ALuint) bufnum, ((PyBuffers*)buffers)->count,
+        PyBuffers_AsBuffers(buffers));
+    if (SetALErrorException (alGetError ()))
+        return NULL;
+    
+    Py_RETURN_NONE;
+}
 /* C API */
 PyObject*
 PySources_New (PyObject *context, ALsizei count)
     if (SetALErrorException (alGetError ()))
     {
         Py_DECREF (sources);
+        PyMem_Free (buf);
         return NULL;
     }
 
 {
     PyObject *surface;
     PyObject *mask = NULL;
-    SDL_Surface *sfmask = NULL;
+    Uint8 *maskbuf = NULL;
+    Py_ssize_t masklen = 0;
+    SDL_Surface *sdlsurface;
 
     ASSERT_VIDEO_INIT(NULL);
 
         PyErr_SetString (PyExc_TypeError, "surface must be a Surface");
         return NULL;
     }
-
+    sdlsurface = PySDLSurface_AsSDLSurface (surface);
+    
     if (mask)
     {
-        PyErr_SetString (PyExc_NotImplementedError,
-            "icon masks are not supported yet");
+        int w;
+        if (PyObject_AsReadBuffer (mask, (const void**)&maskbuf,
+            &masklen) == -1)
+            return -1;
+        w = (int) round ((masklen * 1.f) / sdlsurface->h);
+        if ((w * 8) != sdlsurface->w)
+        {
+            PyErr_SetString (PyExc_ValueError,
+                "mask buffer does not match size");
+            return NULL;
+        }
     }
-    /* TODO: support the mask */
-    SDL_WM_SetIcon (((PySDLSurface*)surface)->surface, NULL);
+    SDL_WM_SetIcon (((PySDLSurface*)surface)->surface, maskbuf);
     Py_RETURN_NONE;
 }
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.