Commits

Anonymous committed 9e033a3

Added WITH_EXPERIMENTAL flag for experimental module builds.
Added context checks and proper device error handling to openal module.

Comments (0)

Files changed (13)

 PYTHON = python
+# Set this to 0 on releases.
+EXPERIMENTAL = 1
 top_srcdir = `pwd`
 SUBDIRS = \
 	$(top_srcdir)/config \
 	$(top_srcdir)/src/sdlmixer \
 	$(top_srcdir)/src/sdlttf
 
+
 all: clean build
 
 dist: clean docs
 
 build:
 	@echo "Running build..."
-	@$(PYTHON) setup.py build #-c mingw32
+	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) $(PYTHON) setup.py build #-c mingw32
 	@echo "Build finished, invoke 'make install' to install."
 
 clang: clean
 	@echo "Running build with Clang..."
-	@$(PYTHON) setup.py build -c clang
+	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) $(PYTHON) setup.py build -c clang
 	@echo "Build finished, invoke 'make install' to install."
 
 install:
 	@echo "Installing..."
-	@$(PYTHON) setup.py install 
+	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) $(PYTHON) setup.py install 
 
 clean:
 	@echo "Cleaning up in $(top_srcdir)/ ..."
 # purposes only!
 
 buildall: clean
-	@python2.4 setup.py build
-	@python2.5 setup.py build
-	@python2.6 setup.py build
-	@python3.1 setup.py build
+	@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
 
 buildallclang: clean
-	@python2.4 setup.py build -c clang
-	@python2.5 setup.py build -c clang
-	@python2.6 setup.py build -c clang
-	@python3.1 setup.py build -c clang
+	@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
 
 installall:
-	@python2.4 setup.py install
-	@python2.5 setup.py install
-	@python2.6 setup.py install
-	@python3.1 setup.py install
+	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.4 setup.py install
+	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.5 setup.py install
+	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python2.6 setup.py install
+	@WITH_EXPERIMENTAL=$(EXPERIMENTAL) python3.1 setup.py install
 
 testall:
 	@python2.4 test/run_tests.py
 environment variables are controlling, which components of pgreloaded
 should be build:
 
-WITH_SDL=[yes|no|1|True]        Example: make -DWITH_SDL=yes
+WITH_SDL=[yes|no|1|True]            Example: make -DWITH_SDL=yes
 
     Build and install the pygame2.sdl module. This wraps the SDL library
     and is required for any other SDL related module in pgreloaded.
 
-WITH_SDL_MIXER=[yes|no|1|True]  Example: make -DWITH_SDL_MIXER=no
+WITH_SDL_MIXER=[yes|no|1|True]      Example: make -DWITH_SDL_MIXER=no
 
     Build and install the pygame2.sdlmixer module. This wraps the
     SDL_mixer library. 
 
-WITH_SDL_IMAGE=[yes|no|1|True]  Example: make -DWITH_SDL_IMAGE=True
+WITH_SDL_IMAGE=[yes|no|1|True]      Example: make -DWITH_SDL_IMAGE=True
 
     Build and install the pygame2.sdlimage module. This wraps the
     SDL_image library.
 
-WITH_SDL_TTF=[yes|no|1|True]    Example: make -DWITH_SDL_TTF=True
+WITH_SDL_TTF=[yes|no|1|True]        Example: make -DWITH_SDL_TTF=True
 
     Build and install the pygame2.sdlttf module. This wraps the
     SDL_ttf library.
 
-WITH_SDL_GFX=[yes|no|1|True]    Example: make -DWITH_SDL_GFX=1
+WITH_SDL_GFX=[yes|no|1|True]        Example: make -DWITH_SDL_GFX=1
 
     Build and install the pygame2.sdlgfx module. This wraps the
     SDL_gfx library.
 
-WITH_PNG=[yes|no|1|True]        Example: make -DWITH_PNG=True
+WITH_PNG=[yes|no|1|True]            Example: make -DWITH_PNG=True
 
     Build with PNG format saving support for pygame2.sdl.
 
-WITH_JPEG=[yes|no|1|True]       Example: make -DWITH_JPEG=False
+WITH_JPEG=[yes|no|1|True]           Example: make -DWITH_JPEG=False
 
     Build with JPEG format saving support for pygame2.sdl.
 
-WITH_FREETYPE=[yes|no|1|True]   Example: make -DWITH_FREETYPE=False
+WITH_FREETYPE=[yes|no|1|True]       Example: make -DWITH_FREETYPE=False
     
     Build and install the pygame2.freetype module. This wraps the
     FreeType2 library.
 
-WITH_PORTMIDI=[yes|no|1|True]   Example: make -DWITH_PORTMIDI=False
+WITH_PORTMIDI=[yes|no|1|True]       Example: make -DWITH_PORTMIDI=False
     
     Build and install the pygame2.midi module. This wraps the
     portmidi library and gives access to the pygame2.midi module.
 
-WITH_OPENAL=[yes|no|1|True]   Example: make -DWITH_OPENAL=False
+WITH_OPENAL=[yes|no|1|True]         Example: make -DWITH_OPENAL=False
     
     Build and install the pygame2.openal module. This wraps the
     OpenAL library and gives access to the pygame2.openal module.
 
+WITH_EXPERIMENTAL=[yes|no|1|True]   Example: make -DWITH_EXPERIMENTAL=True
+
+    Build pygame2 modules, which are marked as experimental. Note that those
+    modules are likely to change a lot between updates, may cause instabilities
+    and can contain lots of bugs.
+    
 1.1 Dependencies
 ----------------
 Pygame2 is designed to run in as many environments as possible. As such,
 
 # OpenAL (module) support
 build['OPENAL'] = istrue (os.getenv ("WITH_OPENAL", True))
+
+# Experimental modules support
+build['EXPERIMENTAL'] = istrue (os.getenv ("WITH_EXPERIMENTAL", False))

config/config_modules.py

     dependencies = get_dependencies(buildsystem, cfg)
 
     for mod in modules:
-        mod.canbuild = True
+        mod.canbuild = (not mod.experimental) or \
+            (mod.experimental and cfg.build['EXPERIMENTAL'])
 
         # Pull in OS-specific dependencies.
         os_config.add_sys_deps (mod)
 
     make release
 
+.. note::
+
+  Set the *EXPERIMENTAL* variable to *0* within the Makefile before
+  starting the release build.
+
 This also will create a set of bundled docs to be distributed.
 
 Once all packages are built (see below) the revision control tree can be tagged
   WITH_OPENAL=[yes|no|1|True]             Example: make -DWITH_OPENAL=False
     
 Build and install the :mod:`pygame2.openal` module. This wraps the OpenAL
-library and gives access to the :mod:`pygame2.openal` module.
+library and gives access to the :mod:`pygame2.openal` module. ::
+
+  WITH_EXPERIMENTAL=[yes|no|1|True]       Example: make -DWITH_EXPERIMENTAL=True
+
+Build pygame2 modules, which are marked as experimental. Note that those
+modules are likely to change a lot between updates, may cause instabilities
+and can contain lots of bugs.
 .. cfunction:: int IsValidRect (PyObject *obj)
 
   Checks, if the passed object is a valid rectangle object. That is the
-  case if, the object is either a :ctype::`PyRect` or :ctype::`PyFRect`
+  case if, the object is either a :ctype:`PyRect` or :ctype:`PyFRect`
   instance or a 4-value sequence that carries two Sint16-compatible
   values two Uint16-compatible values in the order (Sint16, Sint16,
   Uint16, Uint16). This returns 1 on success and 0 on failure.
 
 class Module:
     def __init__ (self, name, sources=None, instheaders=[], docfile=None,
-                  depends=None, optional_dep=None):
+                  depends=None, optional_dep=None, experimental=False):
         """
             Initializes the Module object.
 
                         config.config_modules.DEPENDENCIES
             optional_dep - List of optional libraries with which this module
                            can be built.
+            experimental - Indicates, if the module is in an experimental state.
         """
 
         self.name = name
         self.cflags = []
         self.docfile = docfile
         self.canbuild = True
+        self.experimental = experimental
         nn = name.upper ().replace (".", "_")
         self.globaldefines = [("HAVE_PYGAME_" + nn, None)]
 
 
     Module ("openal.constants",
         sources = [ "src/openal/constantsmod.c" ],
-        depends = [ 'openal' ]),
+        depends = [ 'openal' ],
+        experimental = True),
     
     Module ("openal.base",
         sources = [ "src/openal/openalmod.c",
                     "src/openal/context.c",
                     "src/openal/device.c" ],
-        depends = [ 'openal' ]),
+        depends = [ 'openal' ],
+        experimental = True),
     ]
 
 if helpers.getversion() < (3, 0, 0):
 #include "openalmod.h"
 #include "pgopenal.h"
 
+#define CONTEXT_IS_CURRENT(x) \
+    (alcGetCurrentContext () == PyContext_AsContext (x))
+
+#define ASSERT_CONTEXT_IS_CURRENT(x,ret)                                \
+    if (alcGetCurrentContext () != PyContext_AsContext (x))             \
+    {                                                                   \
+        PyErr_SetString (PyExc_PyGameError, "Context is not current");  \
+        return (ret);                                                   \
+    }
 
 static int _context_init (PyObject *self, PyObject *args, PyObject *kwds);
 static void _context_dealloc (PyContext *self);
 static PyObject* _context_repr (PyObject *self);
 
+static PyObject* _context_createbuffers (PyObject *self, PyObject *args);
 static PyObject* _context_makecurrent (PyObject *self);
+static PyObject* _context_suspend (PyObject *self);
+static PyObject* _context_process (PyObject *self);
+static PyObject* _context_enable (PyObject *self, PyObject *args);
+static PyObject* _context_disable (PyObject *self, PyObject *args);
+static PyObject* _context_isenabled (PyObject *self, PyObject *args);
+
 static PyObject* _context_iscurrent (PyObject* self, void *closure);
+static PyObject* _context_getdevice (PyObject* self, void *closure);
 
 /**
  */
 static PyMethodDef _context_methods[] = {
-    { "make_current", (PyCFunction)_context_makecurrent, METH_NOARGS, "" },
+    { "make_current", (PyCFunction)_context_makecurrent, METH_NOARGS, NULL },
+    { "create_buffers", (PyCFunction) _context_createbuffers, METH_O, NULL },
+    { "suspend", (PyCFunction) _context_suspend, METH_NOARGS, NULL },
+    { "process", (PyCFunction) _context_process, METH_NOARGS, NULL },
+    { "enable", (PyCFunction) _context_enable, METH_O, "" },
+    { "disable", (PyCFunction) _context_disable, METH_O, "" },
+    { "is_enabled", (PyCFunction) _context_isenabled, METH_O, "" },
     { NULL, NULL, 0, NULL }
 };
 
  */
 static PyGetSetDef _context_getsets[] = {
     { "is_current", _context_iscurrent, NULL, NULL, NULL },
+    { "device", _context_getdevice, NULL, NULL, NULL },
     { NULL, NULL, NULL, NULL, NULL }
 };
 
             alcMakeContextCurrent (NULL);
         alcDestroyContext (self->context);
     }
+    Py_XDECREF (self->device);
+    self->device = NULL;
     self->context = NULL;
     ((PyObject*)self)->ob_type->tp_free ((PyObject *) self);
 }
         PyMem_Free (attrs);
     if (((PyContext*)self)->context == NULL)
     {
-        SetALErrorException (alGetError ());
+        SetALCErrorException (alcGetError (PyDevice_AsDevice (device)));
         return -1;
     }
+    Py_INCREF (device);
+    ((PyContext*)self)->device = device;
     return 0;
 }
 
 static PyObject*
 _context_iscurrent (PyObject* self, void *closure)
 {
-    return PyBool_FromLong
-        (alcGetCurrentContext () == PyContext_AsContext (self));
+    return PyBool_FromLong (CONTEXT_IS_CURRENT (self));
 }
 
+static PyObject*
+_context_getdevice (PyObject* self, void *closure)
+{
+    PyContext *ctxt = (PyContext*)self;
+    Py_INCREF (ctxt->device);
+    return ctxt->device;
+}
 
 /* Context methods */
 static PyObject*
     Py_RETURN_FALSE;
 }
 
+static PyObject*
+_context_createbuffers (PyObject *self, PyObject *args)
+{
+    unsigned int bufnum;
+    ALuint buffers;
+
+    ASSERT_CONTEXT_IS_CURRENT(self, NULL);
+
+    if (!UintFromObj (args, &bufnum))
+        return NULL;
+    CLEAR_ERROR_STATE ();
+
+    /* TODO: If there are already existing buffer, what should we do? */
+    alGenBuffers ((ALsizei)bufnum, &buffers);
+    if (SetALErrorException (alGetError ()))
+        return NULL;
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+_context_suspend (PyObject *self)
+{
+    alcSuspendContext (PyContext_AsContext (self));
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+_context_process (PyObject *self)
+{
+    alcProcessContext (PyContext_AsContext (self));
+    Py_RETURN_NONE;
+}
+
+
+static PyObject*
+_context_enable (PyObject *self, PyObject *args)
+{
+    ALenum val;
+
+    ASSERT_CONTEXT_IS_CURRENT(self, NULL);
+
+    if (!IntFromObj (args, (int*) &val))
+        return NULL;
+    CLEAR_ERROR_STATE ();
+    alEnable (val);
+    if (SetALErrorException (alGetError ()))
+        return NULL;
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+_context_disable (PyObject *self, PyObject *args)
+{
+    ALenum val;
+
+    ASSERT_CONTEXT_IS_CURRENT(self, NULL);
+
+    if (!IntFromObj (args, (int*) &val))
+        return NULL;
+    CLEAR_ERROR_STATE ();
+    alDisable (val);
+    if (SetALErrorException (alGetError ()))
+        return NULL;
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+_context_isenabled (PyObject *self, PyObject *args)
+{
+    ALenum val;
+    ALboolean ret;
+
+    ASSERT_CONTEXT_IS_CURRENT(self, NULL);
+
+    if (!IntFromObj (args, (int*) &val))
+        return NULL;
+    CLEAR_ERROR_STATE ();
+    ret = alIsEnabled (val);
+    if (SetALErrorException (alGetError ()))
+        return NULL;
+    if (ret == AL_TRUE)
+        Py_RETURN_TRUE;
+    Py_RETURN_FALSE;
+}
+
 void
 context_export_capi (void **capi)
 {
         ALC_DEVICE_SPECIFIER);
     if (!name)
     {
-        SetALErrorException (alGetError ());
+        SetALCErrorException (alcGetError (PyDevice_AsDevice (self)));
         return NULL;
     }
     return Text_FromUTF8 ((const char*)name);
     const ALCchar *devices = alcGetString (PyDevice_AsDevice (self),
         ALC_CAPTURE_DEVICE_SPECIFIER);
     
-    if (SetALErrorException (alGetError ()))
+    if (SetALCErrorException (alcGetError (PyDevice_AsDevice (self))))
         return NULL;
     list = PyList_New (0);
     dptr = devices;
     
     present = alcIsExtensionPresent (PyDevice_AsDevice (self),
         (const ALchar*)extname);
-    if (SetALErrorException (alGetError ()))
+    if (SetALCErrorException (alcGetError (PyDevice_AsDevice (self))))
         return NULL;
     if (present == ALC_FALSE)
         Py_RETURN_FALSE;
 static PyObject*
 _device_geterror (PyObject* self)
 {
-    ALenum error = alcGetError (PyDevice_AsDevice (self));
+    ALCenum error = alcGetError (PyDevice_AsDevice (self));
     switch (error)
     {
-    case AL_INVALID_ENUM:
+    case ALC_INVALID_ENUM:
         return Text_FromUTF8 ("invalid enumeration value");
-    case AL_INVALID_VALUE:
+    case ALC_INVALID_VALUE:
         return Text_FromUTF8 ("invalid value");
-    case AL_INVALID_OPERATION:
-        return Text_FromUTF8 ("invalid operation request");
-    case AL_OUT_OF_MEMORY:
+    case ALC_INVALID_DEVICE:
+        return Text_FromUTF8 ("invalid device");
+    case ALC_INVALID_CONTEXT:
+        return Text_FromUTF8 ("invalid context");
+    case ALC_OUT_OF_MEMORY:
         return Text_FromUTF8 ("insufficient memory");
     default:
         Py_RETURN_NONE;

src/openal/openalmod.c

 static PyObject* _openal_getdefaultoutputdevicename (PyObject *self);
 static PyObject* _openal_getdefaultcapturedevicename (PyObject *self);
 
+
 static PyMethodDef _openal_methods[] = {
     { "init", (PyCFunction)_openal_init, METH_NOARGS, ""/*DOC_BASE_INIT*/ },
     { "quit", (PyCFunction)_openal_quit, METH_NOARGS, ""/*DOC_BASE_QUIT*/ },
       (PyCFunction) _openal_getdefaultoutputdevicename, METH_NOARGS, ""},
     { "get_default_capture_device_name",
       (PyCFunction) _openal_getdefaultcapturedevicename, METH_NOARGS, ""},
-
+   
     { NULL, NULL, 0, NULL },
 };
 
 
     if (!devices)
     {
-        SetALErrorException (alGetError ());
+        SetALCErrorException (alcGetError (NULL));
         return NULL;
     }
 
     devices = alcGetString (NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
     if (!devices)
     {
-        SetALErrorException (alGetError ());
+        SetALCErrorException (alcGetError (NULL));
         return NULL;
     }
     list = PyList_New (0);
     name = alcGetString (NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
     if (name)
         return Text_FromUTF8 ((const char*)name);
-    SetALErrorException (alGetError ());
+    SetALCErrorException (alcGetError (NULL));
     return NULL;
 }
 
     name = alcGetString (NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
     if (name)
         return Text_FromUTF8 ((const char*)name);
-    SetALErrorException (alGetError ());
+    SetALCErrorException (alcGetError (NULL));
     return NULL;
 }
 
     }
 }
 
+int
+SetALCErrorException (ALCenum error)
+{
+    switch (error)
+    {
+    case ALC_INVALID_ENUM:
+        PyErr_SetString (PyExc_PyGameError, "invalid enumeration value");
+        return 1;
+    case ALC_INVALID_VALUE:
+        PyErr_SetString (PyExc_PyGameError, "invalid value");
+        return 1;
+    case ALC_OUT_OF_MEMORY:
+        PyErr_SetString (PyExc_PyGameError, "insufficient memory");
+        return 1;
+    case ALC_INVALID_DEVICE:
+        PyErr_SetString (PyExc_PyGameError, "invalid device");
+        return 1;
+    case ALC_INVALID_CONTEXT:
+        PyErr_SetString (PyExc_PyGameError, "invalid context");
+        return 1;
+    default:
+        return 0;
+    }
+}
+
 #ifdef IS_PYTHON_3
 PyMODINIT_FUNC PyInit_base (void)
 #else

src/openal/openalmod.h

 
 #if defined(IS_MSYS) || defined(IS_WIN32)
 #include <al.h>
+#include <alc.h>
 #else
 #include <AL/al.h>
+#include <AL/alc.h>
 #endif
 
 #include "pgcompat.h"
 #define PyContext_Check(x) (PyObject_TypeCheck (x, &PyContext_Type))
 
 int SetALErrorException (ALenum error);
+int SetALCErrorException (ALCenum error);
 #define CLEAR_ERROR_STATE() alGetError()
 
 void device_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 \
 {
     PyObject_HEAD
     ALCcontext *context;
+    PyObject   *device;
 } PyContext;
 #define PyContext_AsContext(x) (((PyContext*)x)->context)
 #define PYGAME_OPENALCONTEXT_FIRSTSLOT \