Commits

Anonymous committed 240dc49

Added pygame2.openal wrapper module skeleton.
Improved pygame2.resources doc strings and added it to the documentation.
Added pygam2.math C API documentation.
Fixed height calculation for text rendering in pygame2.freetype.

Comments (0)

Files changed (22)

 
     Build with JPEG format saving support for pygame2.sdl.
 
-WITH_FREETYPE=[yes|no|1|True]   Example: make -WITH_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 -WITH_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
+    
+    Build and install the pygame2.openal module. This wraps the
+    OpenAL library and gives access to the pygame2.openal module.
+
 1.1 Dependencies
 ----------------
 Pygame2 is designed to run in as many environments as possible. As such,
 installation. Additionally other libraries are needed, if you want to
 enable certain features of Pygame2.
 
-* Python 2.4, 2.5, 2.6, 3.0, 3.1 supported   (http://www.python.org)
+* Python 2.4, 2.5, 2.6, 3.1 supported   (http://www.python.org)
 
 [Optional dependencies]
 * SDL >= 1.2.10             (http://www.libsdl.org)
 * freetype: brush up docs and examples
 * freetype: description/markup language for rendering text (like e.g. pango
    has)?
-* freetype: fix returned height and surface height for fonts!
 
 Things to ADD:
 ==============
 * (re)add tests
 * add examples
 * reorganise and add camera module
-* add math module
 * add movie module
 * subsurfaces via surface[x:y,a:b]? Brought up by ctgPi via IRC
 
 
 # midi (module) support
 build['PORTMIDI'] = istrue (os.getenv ("WITH_PORTMIDI", True))
+
+# OpenAL (module) support
+build['OPENAL'] = istrue (os.getenv ("WITH_OPENAL", True))

config/config_modules.py

             config_program='freetype-config'),
         
         'portmidi' : dep(['portmidi.h'], 'portmidi'),
-    }
+        
+        'openal' : dep(['al.h'], 'openal',
+            config_program='openal-config',
+            pkgconfig_name='openal')
+        }
 
     OS_MODULES[buildsystem].update_sys_deps (DEPENDENCIES)
 

config/config_msys.py

         libraries.update (_hunt_libs ("freetype", dirs))
     if cfg.build['PORTMIDI']:
         libraries.update (_hunt_libs ("portmidi", dirs))
+    if cfg.build['OPENAL']:
+        libraries.update (_hunt_libs ("openal", dirs))
 
     return [ k.replace ("/", os.sep) for k in libraries.keys() ]
 

config/config_win.py

     deps["user32"].nocheck = True
     deps["gdi32"] = Dependency ([], 'gdi32')
     deps["gdi32"].nocheck = True
+    deps["openal"].libs = [ "OpenAL32" ]
 
 def add_sys_deps (module):
     if module.name.startswith("sdl"):
         libraries.update (_hunt_libs ("freetype", dirs))
     if cfg.build['PORTMIDI']:
         libraries.update (_hunt_libs ("portmidi", dirs))
+    if cfg.build['OPENAL']:
+        libraries.update (_hunt_libs ("openal", dirs))
 
     return libraries.keys ()
 
     ('png', r'(lib){0,1}png(1[23])(-0){0,1}\.dll$', ['z']),
     ('z', r'zlib1\.dll$', []),
     ('portmidi', r'portmidi\.dll$', []),
+    ('openal', r'OpenAL32\.dll$', []),
 ]
 
 # regexs: Maps name to DLL file name regex.

doc/BuildDarwin.txt

 Make sure, you have at least one of the following Python versions installed:
 
 * Python 2.5 (bundled with Mac OS X)
-* Python 2.4, 2.6, 3.0, 3.1 (http://www.python.org)
+* Python 2.4, 2.6, 3.1 (http://www.python.org)
 
 These versions must be installed as Frameworks: Mac OS 10.5 already
 comes with Python 2.5 installed as a framework; be careful when

doc/BuildMinGW.txt

 
 Make sure, you have at least one of the following Python versions installed:
 
-* Python 2.4, 2.5, 2.6, 3.0, 3.1 (http://www.python.org)
+* Python 2.4, 2.5, 2.6, 3.1 (http://www.python.org)
 
 To build anything, you will have to download the following additional source
 packages:

doc/BuildUnix.txt

 
 Make sure, you have at least one of the following Python versions installed:
 
-* Python 2.4, 2.5, 2.6, 3.0, 3.1 (http://www.python.org)
+* Python 2.4, 2.5, 2.6, 3.1 (http://www.python.org)
 
 To build anything, you will have to download the following additional source
 packages:
 Make sure, you have at least one of the following Python versions
 installed:
 
-* Python 2.4, 2.5, 2.6, 3.0, 3.1 (http://www.python.org)
+* Python 2.4, 2.5, 2.6, 3.1 (http://www.python.org)
 
 To build anything, you will have to download the following additional
 packages:
   WITH_FREETYPE=[yes|no|1|True]           Example: make -DWITH_FREETYPE=False
 
 Build and install the :mod:`pygame2.freetype` module. This wraps the
-FreeType2 library.
+FreeType2 library. ::
 
   WITH_PORTMIDI=[yes|no|1|True]           Example: make -DWITH_PORTMIDI=False
 
 Build and install the :mod:`pygame2.pypm` and :mod:`pygame2.midi` modules. This
 wraps the portmidi library and gives access to the :mod:`pygame2.midi` module.
+
+  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.
   capi/base.rst
   capi/freetype.rst
   capi/mask.rst
+  capi/math.rst
   capi/sdlbase.rst
   capi/sdlcdrom.rst
   capi/sdlevent.rst

doc/capi/math.rst

+============
+pygame2.math
+============
+The :mod:`pygame2.math` C API contains various objects and functions for
+math and vector operations.
+
+Import
+------
+Include headers::
+
+  pygame2/pgmath.h
+
+.. cfunction:: int import_pygame2_math (void)
+
+  Imports the :mod:`pygame2.math` module. This returns 0 on success and
+  -1 on failure.
+
+Macros
+------
+.. data:: VEC_EPSILON
+
+  .. todo::
+    Detailled description about the eps usage.
+
+Functions
+---------
+.. cfunction:: double* VectorCoordsFromObj (PyObject *obj, Py_ssize_t *size)
+
+  Tries to retrieve as many double values as possible from the passed *obj.
+  If *obj* is a :ctype:`PyVector`, a copy of all its elements is returned.
+  Otherwise the method treats *obj* as a sequence of float values. The total
+  amount of doubles returned will be stored in *size*. The caller has to free
+  the return value using :cfunc:`PyMem_Free`. This returns 1 on success and 0
+  on failure.
+
+PyVector
+--------
+.. ctype:: PyVector
+.. ctype:: PyVector_Type
+
+The PyVector object is a generic vector implementation, which can deal with
+any dimension size. Specialized (and in some terms faster) implementations
+for 2 and 3 dimensions can be found in the :ctype:`PyVector2` and
+:ctype:`PyVector3` implementations.
+
+Members
+^^^^^^^
+.. cmember:: double* PyVector.coords
+
+  The vector coordinates. It holds up to *dim* values.
+  
+.. cmember:: Py_ssize_t PyVector.dim;
+
+  The number of dimensions (coordinate values), the PyVector can hold.
+
+.. cmember:: double PyVector.epsilon
+
+  .. todo::
+    Detailled description about the eps usage.
+
+Functions
+^^^^^^^^^
+.. cfunction:: int PyVector_Check (PyObject *obj)
+
+  Returns true, if the argument is a :ctype:`PyVector` or a subclass of
+  :ctype:`PyVector`.
+
+.. cfunction:: PyObject* PyVector_New (Py_ssize_t dims)
+
+  Creates a new :ctype:`PyVector` object with the given number of dimensions.
+  On failure, this returns NULL.
+
+.. cfunction:: PyObject* PyVector_NewFromSeq (PyObject *obj)
+
+  Creates a new :ctype:`PyVector` object from the passed *obj*. *obj is treated
+  as a sequence of float values (or :ctype:`PyVector`). On failure, this
+  returns NULL.
+
+.. cfunction:: PyVector_NewSpecialized (Py_ssize_t dims)
+
+  This behaves like :cfunc:`PyVector_New`, but creates specialized
+  :ctype:`PyVector2` or :ctype:`PyVector3` instances for a *dims* value of 2 or
+  3. On failure, this returns NULL.
+
+PyVector2
+---------
+.. ctype:: PyVector2
+.. ctype:: PyVector2_Type
+
+A specialized :ctype:`PyVector` class limited to two dimensions.
+
+Members
+^^^^^^^
+.. cmember:: PyVector PyVector2.vector
+
+  The parent :ctype:`PyVector` class the PyVector2 inherits from.
+
+Functions
+^^^^^^^^^
+.. cfunction:: int PyVector2_Check (PyObject *obj)
+
+  Returns true, if the argument is a :ctype:`PyVector2` or a subclass of
+  :ctype:`PyVector2`.
+
+.. cfunction:: PyObject* PyVector2_New (double x, double y)
+
+  Creates a new :ctype:`PyVector2` object with the specified *x* and *y*
+  coordinates. On failure, this returns NULL.
+
+PyVector3
+---------
+.. ctype:: PyVector3
+.. ctype:: PyVector3_Type
+
+A specialized :ctype:`PyVector` class limited to three dimensions.
+
+Members
+^^^^^^^
+.. cmember:: PyVector PyVector3.vector
+
+  The parent :ctype:`PyVector` class the PyVector3 inherits from.
+
+Functions
+^^^^^^^^^
+.. cfunction:: int PyVector3_Check (PyObject *obj)
+
+  Returns true, if the argument is a :ctype:`PyVector3` or a subclass of
+  :ctype:`PyVector3`.
+
+.. cfunction:: PyObject* PyVector3_New (double x, double y, double z)
+
+  Creates a new :ctype:`PyVector3` object with the specified *x*, *y* and *z*
+  coordinates. On failure, this returns NULL.

doc/src/modules.rst

    pygame2_math.rst
    pygame2_mask.rst
    pygame2_midi.rst
+   pygame2_resources.rst
    pygame2_sdl.rst
    pygame2_sdl_audio.rst
    pygame2_sdl_cdrom.rst

doc/src/resources.xml

+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE module SYSTEM "api.dtd">
+
+<module name="pygame2.resources">
+  <short>Resource management methods.</short>
+  <desc>
+    Resource management methods.
+  </desc>
+  
+  <class name="Resources">
+    <constructor>Resources () -> Resources</constructor>
+    <desc>Creates a new resource container instance.
+    
+      The Resources class manages a set of file resources and eases accessing
+      them by using relative paths, scanning archives automatically and so on.
+    </desc>
+    <method name="add">
+      <call>add (filename) -> None</call>
+      <desc>Adds a file to the Resources container.
+
+        Depending on the file type (determined by the file suffix or name),
+        the file will be automatically scanned (if it is an archive) or
+        checked for availability (if it is a stream/network resource).
+      </desc>
+    </method>
+    <method name="add_archive">
+      <call>add_archive (self, filename, typehint='zip') -> None</call>
+      <desc>Adds an archive file to the Resources container.
+
+        This will scan the passed archive and add its contents to the list
+        of available resources.
+      </desc>
+    </method>
+    <method name="add_file">
+      <call>add_file (self, filename) -> None</call>
+      <desc>Adds a file to the Resources container.
+
+        This will only add the passed file and do not scan an archive or check
+        a stream for availability.
+      </desc>
+    </method>
+    <method name="get">
+      <call>get (filename) -> StringIO</call>
+      <desc>Gets a specific file from the Resources.
+
+        Raises a KeyError, if *filename* could not be found.
+      </desc>
+    </method>
+    <method name="get_filelike">
+      <call>get_filelike (filename) -> file or StringIO</call>
+      <desc>
+        Like get(), but tries to return the original file handle, if possible.
+
+        If the passed *filename* is only available within an archive, a
+        StringIO instance will be returned.
+
+        Raises a KeyError, if *filename* could not be found.
+      </desc>
+    </method>
+    <method name="get_path">
+      <call>get_path (filename) -> str</call>
+      <desc>Gets the path of the passed filename.
+
+        If *filename* is only available within an archive, a string in the form
+        'filename@archivename' will be returned.
+
+        Raises a KeyError, if *filename* could not be found.
+      </desc>
+    </method>
+    <method name="scan">
+      <call>scan (path) -> None</call>
+      <desc>Scans a path and adds all found files to the Resource container.
+
+        Scans a path and adds all found files to the Resource container. If a
+        file is a supported (ZIP or TAR) archive, its contents will be indexed
+        and added automatically.
+
+        *excludepattern* can be a regular expression to skip files, which match
+        the pattern.
+      </desc>
+    </method>
+  </class>
+
+  <func name="open_tarfile">
+    <call>open_tarfile (archive, filename, dir=None, type=None) -> StringIO</call>
+    <desc>Opens and reads a certain file from a TAR archive.
+
+      Opens and reads a certain file from a TAR archive. The result is returned
+      as StringIO stream. *filename* can be a relative or absolute path within
+      the ZIP archive. The optional *dir* argument can be used to supply a
+      relative directory path, under which *filename* will be tried to retrieved.
+
+      *type* is used to supply additional compression information, in case the
+      system cannot determine the compression type itself, and can be either
+      'gz' for gzip compression or 'bz2' for bzip2 compression.
+
+      .. note::
+
+        If *type* is supplied, the compreesion mode will be enforced for opening
+        and reading.
+
+      If the *filename* could not be found or an error occured on reading it,
+      None will be returned.
+
+      Raises a TypeError, if *archive* is not a valid TAR archive or if *type*
+      is not a valid value of ('gz', 'bz2').
+    </desc>
+  </func>
+  <func name="open_url">
+    <call>open_url (filename, basepath=None) -> file</call>
+    <desc>Opens and reads a certain file from a web or remote location.
+
+      Opens and reads a certain file from a web or remote location. This function
+      utilizes the urllib2 module, which means that it is restricted to the types
+      of remote locations supported by urllib2.
+
+      *basepath* can be used to supply an additional location prefix.
+    </desc>
+  </func>
+  <func name="open_zipfile">
+    <call>open_zipfile (archive, filename, dir=None) -> StringIO</call>
+    <desc>Opens and reads a certain file from a ZIP archive.
+
+      Opens and reads a certain file from a ZIP archive. The result is returned
+      as StringIO stream. *filename* can be a relative or absolute path within
+      the ZIP archive. The optional *dir* argument can be used to supply a
+      relative directory path, under which *filename* will be tried to retrieved.
+
+      If the *filename* could not be found or an error occured on reading it,
+      None will be returned.
+
+      Raises a TypeError, if *archive* is not a valid ZIP archive.
+    </desc>
+  </func>
+</module>
+
 
 def open_zipfile (archive, filename, dir=None):
     """open_zipfile (archive, filename, dir=None) -> StringIO
+    
+    Opens and reads a certain file from a ZIP archive.
+    
+    Opens and reads a certain file from a ZIP archive. The result is returned
+    as StringIO stream. *filename* can be a relative or absolute path within
+    the ZIP archive. The optional *dir* argument can be used to supply a
+    relative directory path, under which *filename* will be tried to retrieved.
+    
+    If the *filename* could not be found or an error occured on reading it,
+    None will be returned.
+    
+    Raises a TypeError, if *archive* is not a valid ZIP archive.
     """
     data = None
     opened = False
 
 def open_tarfile (archive, filename, dir=None, type=None):
     """open_tarfile (archive, filename, dir=None, type=None) -> StringIO
+    
+    Opens and reads a certain file from a TAR archive.
+    
+    Opens and reads a certain file from a TAR archive. The result is returned
+    as StringIO stream. *filename* can be a relative or absolute path within
+    the ZIP archive. The optional *dir* argument can be used to supply a
+    relative directory path, under which *filename* will be tried to retrieved.
+
+    *type* is used to supply additional compression information, in case the
+    system cannot determine the compression type itself, and can be either
+    'gz' for gzip compression or 'bz2' for bzip2 compression.
+    
+    Note:
+      
+      If *type* is supplied, the compreesion mode will be enforced for opening
+      and reading.
+    
+    If the *filename* could not be found or an error occured on reading it,
+    None will be returned.
+    
+    Raises a TypeError, if *archive* is not a valid TAR archive or if *type*
+    is not a valid value of ('gz', 'bz2').
     """
     data = None
     opened = False
     return data
     
 def open_url (filename, basepath=None):
-    """open_url (filename) -> file
+    """open_url (filename, basepath=None) -> file
+    
+    Opens and reads a certain file from a web or remote location.
+    
+    Opens and reads a certain file from a web or remote location. This function
+    utilizes the urllib2 module, which means that it is restricted to the types
+    of remote locations supported by urllib2.
+    
+    *basepath* can be used to supply an additional location prefix.
     """
     url = filename
     if basepath:
             self.scan (path, excludepattern)
 
     def _scanzip (self, filename):
-        """
+        """_scanzip (filename) -> None
+        
+        Scans the passed ZIP archive and indexes all the files contained by it.
         """
         if not zipfile.is_zipfile (filename):
             raise TypeError ("file '%s' is not a valid ZIP archive" % filename)
         zip.close ()
     
     def _scantar (self, filename, type=None):
-        """
+        """_scantar (filename, type=None) -> None
+        
+        Scans the passed TAR archive and indexes all the files contained by it.
         """
         if not tarfile.is_tarfile (filename):
             raise TypeError ("file '%s' is not a valid TAR archive" % filename)
             raise ValueError ("unsupported archive type")
 
     def get (self, filename):
-        """get (filename) -> file
+        """get (filename) -> StringIO
        
-        Gets the specified file from the Resources.
+        Gets a specific file from the Resources.
+        
+        Raises a KeyError, if *filename* could not be found.
         """
         archive, type, pathname = self.files[filename]
         if archive:
         return data
     
     def get_filelike (self, filename):
-        """get_filelike (filename) -> file
+        """get_filelike (filename) -> file or StringIO
         
         Like get(), but tries to return the original file handle, if possible.
+        
+        If the passed *filename* is only available within an archive, a
+        StringIO instance will be returned.
+        
+        Raises a KeyError, if *filename* could not be found.
         """
         archive, type, pathname = self.files[filename]
         if archive:
     
     def get_path (self, filename):
         """get_path (filename) -> str
+        
+        Gets the path of the passed filename.
+        
+        If *filename* is only available within an archive, a string in the form
+        'filename@archivename' will be returned.
+        
+        Raises a KeyError, if *filename* could not be found.
         """
         archive, type, pathname = self.files[filename]
         if archive:
 
     def scan (self, path, excludepattern=None):
         """scan (path) -> None
+        
+        Scans a path and adds all found files to the Resource container.
+        
+        Scans a path and adds all found files to the Resource container. If a
+        file is a supported (ZIP or TAR) archive, its contents will be indexed
+        and added automatically.
+        
+        *excludepattern* can be a regular expression to skip files, which match
+        the pattern.
         """
         match = None
         if excludepattern:
         instheaders = ["src/math/pgmath.h"],
         docfile = "mathbase.xml"),
 
+    Module ("openal.constants",
+        sources = [ "src/openal/constantsmod.c" ],
+        depends = [ 'openal' ]),
+    
+    Module ("openal.base",
+        sources = [ "src/openal/basemod.c" ],
+        depends = [ 'openal' ]),
     ]
 
 if helpers.getversion() < (3, 0, 0):

src/freetype/ft_text.c

 
     FT_Fixed    y_scale;
     FT_Fixed    bold_str = 0;
+    FT_Fixed    addh = 0, bearing = 0;
 
     FontText    *ftext = NULL;
     FontGlyph   *glyph = NULL;
     ftext->text_size.x = ftext->text_size.y = 0;
     ftext->baseline_offset.x = ftext->baseline_offset.y = 0;
     ftext->underline_pos = ftext->underline_size = 0;
-
+    
     y_scale = face->size->metrics.y_scale;
 
     /* fill it with the glyphs */
          */
         if (glyph->baseline > ftext->baseline_offset.y)
             ftext->baseline_offset.y = glyph->baseline;
-
+        
         if (glyph->size.x > ftext->glyph_size.x)
             ftext->glyph_size.x = glyph->size.x;
-
+        
         if (glyph->size.y > ftext->glyph_size.y)
             ftext->glyph_size.y = glyph->size.y;
 
+        /* We have to add the bearing below the baseline, so that the
+         * displacement along the baseline is correctly measured */
+        addh = glyph->size.y - (glyph->size.y - glyph->baseline);
+        if (bearing < addh)
+            bearing = addh;
+            
         *glyph_array++ = glyph;
     }
+    
+    ftext->glyph_size.y += bearing;
 
     if (render->style & FT_STYLE_UNDERLINE &&
         (render->render_flags & FT_RFLAG_VERTICAL) == 0 &&

src/openal/basemod.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_OPENALBASE_INTERNAL
+
+#include <AL.h>
+#include "pgbase.h"
+#include "pgopenal.h"
+/*#include "openalbase_doc.h"*/
+
+static PyObject* _openal_init (PyObject *self);
+static PyObject* _openal_quit (PyObject *self);
+
+static PyMethodDef _openal_methods[] = {
+    { "init", (PyCFunction)_openal_init, METH_NOARGS, ""/*DOC_BASE_INIT*/ },
+    { "quit", (PyCFunction)_openal_quit, METH_NOARGS, ""/*DOC_BASE_QUIT*/ },
+    { NULL, NULL, 0, NULL },
+};
+
+static PyObject*
+_openal_init (PyObject *self)
+{
+    Py_RETURN_NONE;
+}
+
+static PyObject*
+_openal_quit (PyObject *self)
+{
+    Py_RETURN_NONE;
+}
+
+#ifdef IS_PYTHON_3
+PyMODINIT_FUNC PyInit_base (void)
+#else
+PyMODINIT_FUNC initbase (void)
+#endif
+{
+    PyObject *mod;
+
+#ifdef IS_PYTHON_3
+    static struct PyModuleDef _module = {
+        PyModuleDef_HEAD_INIT,
+        "base",
+        ""/*DOC_BASE*/,
+        -1,
+        _image_methods,
+        NULL, NULL, NULL, NULL
+    };
+    mod = PyModule_Create (&_module);
+#else
+    mod = Py_InitModule3 ("base", _openal_methods, ""/*DOC_BASE*/);
+#endif
+    if (!mod)
+        goto fail;
+        
+    PyModule_AddObject (mod, "Device", (PyObject *) &PyDevice_Type);
+    
+    if (import_pygame2_base () < 0)
+        goto fail;
+    MODINIT_RETURN(mod);
+fail:
+    Py_XDECREF (mod);
+    MODINIT_RETURN (NULL);
+}

src/openal/constantsmod.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_OPENALCONSTANTS_INTERNAL
+
+#include <al.h>
+#include <alc.h>
+#include <alext.h>
+#include "pgopenal.h"
+
+/* macros used to create each constant */
+#define DEC_CONST(x)  PyModule_AddIntConstant(module, #x, (int) x)
+
+#ifdef IS_PYTHON_3
+PyMODINIT_FUNC PyInit_constants (void)
+#else
+PyMODINIT_FUNC initconstants (void)
+#endif
+{
+    PyObject *module;
+
+#ifdef IS_PYTHON_3
+    static struct PyModuleDef _module = {
+        PyModuleDef_HEAD_INIT,
+        "constants",
+        "Pygame OpenAL constants",
+        -1,
+        NULL,
+        NULL, NULL, NULL, NULL
+    };
+    module = PyModule_Create (&_module);
+#else
+    module = Py_InitModule3 ("constants", NULL, "Pygame OpenAL constants");
+#endif
+    if (!module)
+        goto fail;
+
+    DEC_CONST(AL_INVALID);
+    DEC_CONST(AL_ILLEGAL_ENUM);
+    DEC_CONST(AL_ILLEGAL_COMMAND);
+    
+    DEC_CONST(AL_NONE);
+    DEC_CONST(AL_FALSE);
+    DEC_CONST(AL_TRUE);
+    
+    DEC_CONST(AL_SOURCE_RELATIVE);
+    DEC_CONST(AL_CONE_INNER_ANGLE);
+    DEC_CONST(AL_CONE_OUTER_ANGLE);
+    DEC_CONST(AL_PITCH);
+    DEC_CONST(AL_POSITION);
+    DEC_CONST(AL_DIRECTION);
+    DEC_CONST(AL_VELOCITY);
+    DEC_CONST(AL_LOOPING);
+    DEC_CONST(AL_BUFFER);
+    DEC_CONST(AL_GAIN);
+    DEC_CONST(AL_MIN_GAIN);
+    DEC_CONST(AL_MAX_GAIN);
+    DEC_CONST(AL_ORIENTATION);
+    
+    DEC_CONST(AL_SOURCE_STATE);
+    DEC_CONST(AL_INITIAL);
+    DEC_CONST(AL_PLAYING);
+    DEC_CONST(AL_PAUSED);
+    DEC_CONST(AL_STOPPED);
+    
+    DEC_CONST(AL_BUFFERS_QUEUED);
+    DEC_CONST(AL_BUFFERS_PROCESSED);
+    
+    DEC_CONST(AL_SEC_OFFSET);
+    DEC_CONST(AL_SAMPLE_OFFSET);
+    DEC_CONST(AL_BYTE_OFFSET);
+    
+    DEC_CONST(AL_SOURCE_TYPE);
+    DEC_CONST(AL_STATIC);
+    DEC_CONST(AL_STREAMING);
+    DEC_CONST(AL_UNDETERMINED);
+    
+    DEC_CONST(AL_FORMAT_MONO8);
+    DEC_CONST(AL_FORMAT_MONO16);
+    DEC_CONST(AL_FORMAT_STEREO8);
+    DEC_CONST(AL_FORMAT_STEREO16);
+    
+    DEC_CONST(AL_REFERENCE_DISTANCE);
+    DEC_CONST(AL_ROLLOFF_FACTOR);
+    DEC_CONST(AL_CONE_OUTER_GAIN);
+    DEC_CONST(AL_MAX_DISTANCE);
+    
+    DEC_CONST(AL_FREQUENCY);
+    DEC_CONST(AL_BITS);
+    DEC_CONST(AL_CHANNELS);
+    DEC_CONST(AL_SIZE);
+    
+    DEC_CONST(AL_UNUSED);
+    DEC_CONST(AL_PENDING);
+    DEC_CONST(AL_PROCESSED);
+    
+    DEC_CONST(AL_NO_ERROR);
+    DEC_CONST(AL_INVALID_NAME);
+    DEC_CONST(AL_INVALID_ENUM);
+    DEC_CONST(AL_INVALID_VALUE);
+    DEC_CONST(AL_INVALID_OPERATION);
+    DEC_CONST(AL_OUT_OF_MEMORY);
+    
+    DEC_CONST(AL_VENDOR);
+    DEC_CONST(AL_VERSION);
+    DEC_CONST(AL_RENDERER);
+    DEC_CONST(AL_EXTENSIONS);
+    
+    DEC_CONST(AL_DOPPLER_FACTOR);
+    DEC_CONST(AL_DOPPLER_VELOCITY);
+    
+    DEC_CONST(AL_SPEED_OF_SOUND);
+    
+    DEC_CONST(AL_DISTANCE_MODEL);
+    DEC_CONST(AL_INVERSE_DISTANCE);
+    DEC_CONST(AL_INVERSE_DISTANCE_CLAMPED);
+    DEC_CONST(AL_LINEAR_DISTANCE);
+    DEC_CONST(AL_LINEAR_DISTANCE_CLAMPED);
+    DEC_CONST(AL_EXPONENT_DISTANCE);
+    DEC_CONST(AL_EXPONENT_DISTANCE_CLAMPED);
+
+    /* ALC constants */
+    DEC_CONST(ALC_INVALID);
+    DEC_CONST(ALC_FALSE);
+    DEC_CONST(ALC_TRUE);
+    DEC_CONST(ALC_FREQUENCY);
+    DEC_CONST(ALC_REFRESH);
+    DEC_CONST(ALC_SYNC);
+    
+    DEC_CONST(ALC_MONO_SOURCES);
+    DEC_CONST(ALC_STEREO_SOURCES);
+    
+    DEC_CONST(ALC_NO_ERROR);
+    DEC_CONST(ALC_INVALID_DEVICE);
+    DEC_CONST(ALC_INVALID_CONTEXT);
+    DEC_CONST(ALC_INVALID_ENUM);
+    DEC_CONST(ALC_INVALID_VALUE);
+    DEC_CONST(ALC_OUT_OF_MEMORY);
+    
+    DEC_CONST(ALC_DEFAULT_DEVICE_SPECIFIER);
+    DEC_CONST(ALC_DEVICE_SPECIFIER);
+    DEC_CONST(ALC_EXTENSIONS);
+    
+    DEC_CONST(ALC_MAJOR_VERSION);
+    DEC_CONST(ALC_MINOR_VERSION);
+    
+    DEC_CONST(ALC_ATTRIBUTES_SIZE);
+    DEC_CONST(ALC_ALL_ATTRIBUTES);
+    
+    DEC_CONST(ALC_CAPTURE_DEVICE_SPECIFIER);
+    DEC_CONST(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
+    DEC_CONST(ALC_CAPTURE_SAMPLES);
+    
+    /* AL/ALC extensions */
+    DEC_CONST(AL_FORMAT_IMA_ADPCM_MONO16_EXT);
+    DEC_CONST(AL_FORMAT_IMA_ADPCM_STEREO16_EXT);
+    
+    DEC_CONST(AL_FORMAT_WAVE_EXT);
+    
+    DEC_CONST(AL_FORMAT_VORBIS_EXT);
+    
+    DEC_CONST(AL_FORMAT_QUAD8_LOKI);
+    DEC_CONST(AL_FORMAT_QUAD16_LOKI);
+    
+    DEC_CONST(AL_FORMAT_MONO_FLOAT32);
+    DEC_CONST(AL_FORMAT_STEREO_FLOAT32);
+    
+    DEC_CONST(AL_FORMAT_MONO_DOUBLE_EXT);
+    DEC_CONST(AL_FORMAT_STEREO_DOUBLE_EXT);
+    
+    DEC_CONST(ALC_CHAN_MAIN_LOKI);
+    DEC_CONST(ALC_CHAN_PCM_LOKI);
+    DEC_CONST(ALC_CHAN_CD_LOKI);
+    
+    DEC_CONST(ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
+    DEC_CONST(ALC_ALL_DEVICES_SPECIFIER);
+    
+    DEC_CONST(AL_FORMAT_QUAD8);
+    DEC_CONST(AL_FORMAT_QUAD16);
+    DEC_CONST(AL_FORMAT_QUAD32);
+    DEC_CONST(AL_FORMAT_REAR8);
+    DEC_CONST(AL_FORMAT_REAR16);
+    DEC_CONST(AL_FORMAT_REAR32);
+    DEC_CONST(AL_FORMAT_51CHN8);
+    DEC_CONST(AL_FORMAT_51CHN16);
+    DEC_CONST(AL_FORMAT_51CHN32);
+    DEC_CONST(AL_FORMAT_61CHN8);
+    DEC_CONST(AL_FORMAT_61CHN16);
+    DEC_CONST(AL_FORMAT_61CHN32);
+    DEC_CONST(AL_FORMAT_71CHN8);
+    DEC_CONST(AL_FORMAT_71CHN16);
+    DEC_CONST(AL_FORMAT_71CHN32);
+    
+    DEC_CONST(AL_FORMAT_MONO_IMA4);
+    DEC_CONST(AL_FORMAT_STEREO_IMA4);
+    
+    DEC_CONST(AL_BYTE_RW_OFFSETS_EXT);
+    DEC_CONST(AL_SAMPLE_RW_OFFSETS_EXT);
+    DEC_CONST(AL_SEC_RW_OFFSETS_EXT);
+    
+    DEC_CONST(AL_SAMPLE_SOURCE_EXT);
+    DEC_CONST(AL_SAMPLE_SINK_EXT);
+    DEC_CONST(AL_READ_ONLY_EXT);
+    DEC_CONST(AL_WRITE_ONLY_EXT);
+    DEC_CONST(AL_READ_WRITE_EXT);
+    DEC_CONST(AL_STREAM_WRITE_EXT);
+    DEC_CONST(AL_STREAM_READ_EXT);
+    DEC_CONST(AL_STREAM_COPY_EXT);
+    DEC_CONST(AL_STATIC_WRITE_EXT);
+    DEC_CONST(AL_STATIC_READ_EXT);
+    DEC_CONST(AL_STATIC_COPY_EXT);
+    DEC_CONST(AL_DYNAMIC_WRITE_EXT);
+    DEC_CONST(AL_DYNAMIC_READ_EXT);
+    DEC_CONST(AL_DYNAMIC_COPY_EXT);
+    
+    DEC_CONST(ALC_CONNECTED);
+    
+    DEC_CONST(AL_SOURCE_DISTANCE_MODEL);
+    
+    MODINIT_RETURN(module);
+fail:
+    Py_XDECREF (module);
+    MODINIT_RETURN (NULL);
+}

src/openal/pgopenal.h

+/*
+  pygame - Python Game Library
+
+  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
+
+*/
+#ifndef _PYGAME_OPENAL_H_
+#define _PYGAME_OPENAL_H_
+
+#include "pgcompat.h"
+#include "pgdefines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PYGAME_OPENAL_FIRSTSLOT 0
+#define PYGAME_OPENAL_NUMSLOTS 0
+#ifndef PYGAME_OPENAL_INTERNAL
+#endif /* PYGAME_OPENAL_INTERNAL */
+
+/**
+ * C API export.
+ */
+#ifdef PYGAME_INTERNAL
+void **PyGameOpenAL_C_API;
+#else
+static void **PyGameOpenAL_C_API;
+#endif
+
+#define PYGAME_OPENAL_SLOTS (PYGAME_OPENAL_FIRSTSLOT + PYGAME_OPENAL_NUMSLOTS)
+#define PYGAME_OPENAL_ENTRY "_PYGAME_OPENAL_CAPI"
+
+static int
+import_pygame2_openal (void)
+{
+    PyObject *_module = PyImport_ImportModule ("pygame2.openal");
+    if (_module != NULL)
+    {
+        PyObject *_capi = PyObject_GetAttrString(_module, PYGAME_OPENAL_ENTRY);
+        if (!PyCObject_Check (_capi))
+        {
+            Py_DECREF (_module);
+            return -1;
+        }
+        PyGameOpenAL_C_API = (void**) PyCObject_AsVoidPtr (_capi);
+        Py_DECREF (_capi);
+        return 0;
+    }
+    return -1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PYGAME_OPENAL_H_ */