Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/audaspace/Python/AUD_PyAPI.cpp')
-rw-r--r--intern/audaspace/Python/AUD_PyAPI.cpp2973
1 files changed, 2973 insertions, 0 deletions
diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp
new file mode 100644
index 00000000000..b0c55d5856e
--- /dev/null
+++ b/intern/audaspace/Python/AUD_PyAPI.cpp
@@ -0,0 +1,2973 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_PyAPI.h"
+#include "structmember.h"
+
+#include "AUD_I3DDevice.h"
+#include "AUD_NULLDevice.h"
+#include "AUD_DelayFactory.h"
+#include "AUD_DoubleFactory.h"
+#include "AUD_FaderFactory.h"
+#include "AUD_HighpassFactory.h"
+#include "AUD_LimiterFactory.h"
+#include "AUD_LoopFactory.h"
+#include "AUD_LowpassFactory.h"
+#include "AUD_PingPongFactory.h"
+#include "AUD_PitchFactory.h"
+#include "AUD_ReverseFactory.h"
+#include "AUD_SinusFactory.h"
+#include "AUD_FileFactory.h"
+#include "AUD_SquareFactory.h"
+#include "AUD_StreamBufferFactory.h"
+#include "AUD_SuperposeFactory.h"
+#include "AUD_VolumeFactory.h"
+#include "AUD_IIRFilterFactory.h"
+
+#ifdef WITH_SDL
+#include "AUD_SDLDevice.h"
+#endif
+
+#ifdef WITH_OPENAL
+#include "AUD_OpenALDevice.h"
+#endif
+
+#ifdef WITH_JACK
+#include "AUD_JackDevice.h"
+#endif
+
+// ====================================================================
+
+typedef enum
+{
+ AUD_DEVICE_NULL = 0,
+ AUD_DEVICE_OPENAL,
+ AUD_DEVICE_SDL,
+ AUD_DEVICE_JACK,
+ AUD_DEVICE_READ,
+} AUD_DeviceTypes;
+
+// ====================================================================
+
+#define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name)
+
+// ====================================================================
+
+static PyObject* AUDError;
+
+static const char* device_not_3d_error = "Device is not a 3D device!";
+
+// ====================================================================
+
+static void
+Factory_dealloc(Factory* self)
+{
+ if(self->factory)
+ delete self->factory;
+ Py_XDECREF(self->child_list);
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ Factory *self;
+
+ self = (Factory*)type->tp_alloc(type, 0);
+ if(self != NULL)
+ {
+ static const char *kwlist[] = {"filename", NULL};
+ const char* filename = NULL;
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Factory", const_cast<char**>(kwlist), &filename))
+ {
+ Py_DECREF(self);
+ return NULL;
+ }
+
+ try
+ {
+ self->factory = new AUD_FileFactory(filename);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Factory_sine_doc,
+ "sine(frequency, rate=44100)\n\n"
+ "Creates a sine factory which plays a sine wave.\n\n"
+ ":arg frequency: The frequency of the sine wave in Hz.\n"
+ ":type frequency: float\n"
+ ":arg rate: The sampling rate in Hz. It's recommended to set this "
+ "value to the playback device's samling rate to avoid resamping.\n"
+ ":type rate: int\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`");
+
+static PyObject *
+Factory_sine(PyTypeObject* type, PyObject* args)
+{
+ float frequency;
+ int rate = 44100;
+
+ if(!PyArg_ParseTuple(args, "f|i:sine", &frequency, &rate))
+ return NULL;
+
+ Factory *self;
+
+ self = (Factory*)type->tp_alloc(type, 0);
+ if(self != NULL)
+ {
+ try
+ {
+ self->factory = new AUD_SinusFactory(frequency, (AUD_SampleRate)rate);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Factory_file_doc,
+ "file(filename)\n\n"
+ "Creates a factory object of a sound file.\n\n"
+ ":arg filename: Path of the file.\n"
+ ":type filename: string\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`\n\n"
+ ".. warning:: If the file doesn't exist or can't be read you will "
+ "not get an exception immediately, but when you try to start "
+ "playback of that factory.");
+
+static PyObject *
+Factory_file(PyTypeObject* type, PyObject* args)
+{
+ const char* filename = NULL;
+
+ if(!PyArg_ParseTuple(args, "s:file", &filename))
+ return NULL;
+
+ Factory *self;
+
+ self = (Factory*)type->tp_alloc(type, 0);
+ if(self != NULL)
+ {
+ try
+ {
+ self->factory = new AUD_FileFactory(filename);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Factory_lowpass_doc,
+ "lowpass(frequency, Q=0.5)\n\n"
+ "Creates a second order lowpass filter based on the transfer "
+ "function H(s) = 1 / (s^2 + s/Q + 1)\n\n"
+ ":arg frequency: The cut off trequency of the lowpass.\n"
+ ":type frequency: float\n"
+ ":arg Q: Q factor of the lowpass.\n"
+ ":type Q: float\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`");
+
+static PyObject *
+Factory_lowpass(Factory* self, PyObject* args)
+{
+ float frequency;
+ float Q = 0.5;
+
+ if(!PyArg_ParseTuple(args, "f|f:lowpass", &frequency, &Q))
+ return NULL;
+
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_LowpassFactory(self->factory, frequency, Q);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_delay_doc,
+ "delay(time)\n\n"
+ "Delays by playing adding silence in front of the other factory's "
+ "data.\n\n"
+ ":arg time: How many seconds of silence should be added before "
+ "the factory.\n"
+ ":type time: float\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`");
+
+static PyObject *
+Factory_delay(Factory* self, PyObject* args)
+{
+ float delay;
+
+ if(!PyArg_ParseTuple(args, "f:delay", &delay))
+ return NULL;
+
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_DelayFactory(self->factory, delay);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_join_doc,
+ "join(factory)\n\n"
+ "Plays two factories in sequence.\n\n"
+ ":arg factory: The factory to play second.\n"
+ ":type factory: :class:`Factory`\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`\n\n"
+ ".. note:: The two factories have to have the same specifications "
+ "(channels and samplerate).");
+
+static PyObject *
+Factory_join(Factory* self, PyObject* object)
+{
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+
+ if(!PyObject_TypeCheck(object, type))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object has to be of type Factory!");
+ return NULL;
+ }
+
+ Factory *parent;
+ Factory *child = (Factory*)object;
+
+ parent = (Factory*)type->tp_alloc(type, 0);
+ if(parent != NULL)
+ {
+ parent->child_list = Py_BuildValue("(OO)", self, object);
+
+ try
+ {
+ parent->factory = new AUD_DoubleFactory(self->factory, child->factory);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_highpass_doc,
+ "highpass(frequency, Q=0.5)\n\n"
+ "Creates a second order highpass filter based on the transfer "
+ "function H(s) = s^2 / (s^2 + s/Q + 1)\n\n"
+ ":arg frequency: The cut off trequency of the highpass.\n"
+ ":type frequency: float\n"
+ ":arg Q: Q factor of the lowpass.\n"
+ ":type Q: float\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`");
+
+static PyObject *
+Factory_highpass(Factory* self, PyObject* args)
+{
+ float frequency;
+ float Q = 0.5;
+
+ if(!PyArg_ParseTuple(args, "f|f:highpass", &frequency, &Q))
+ return NULL;
+
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_HighpassFactory(self->factory, frequency, Q);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_limit_doc,
+ "limit(start, end)\n\n"
+ "Limits a factory within a specific start and end time.\n\n"
+ ":arg start: Start time in seconds.\n"
+ ":type start: float\n"
+ ":arg end: End time in seconds.\n"
+ ":type end: float\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`");
+
+static PyObject *
+Factory_limit(Factory* self, PyObject* args)
+{
+ float start, end;
+
+ if(!PyArg_ParseTuple(args, "ff:limit", &start, &end))
+ return NULL;
+
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_LimiterFactory(self->factory, start, end);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_pitch_doc,
+ "pitch(factor)\n\n"
+ "Changes the pitch of a factory with a specific factor.\n\n"
+ ":arg factor: The factor to change the pitch with.\n"
+ ":type factor: float\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`\n\n"
+ ".. note:: This is done by changing the sample rate of the "
+ "underlying factory, which has to be an integer, so the factor "
+ "value rounded and the factor may not be 100 % accurate.\n\n"
+ ".. note:: This is a filter function, you might consider using "
+ ":attr:`Handle.pitch` instead.");
+
+static PyObject *
+Factory_pitch(Factory* self, PyObject* args)
+{
+ float factor;
+
+ if(!PyArg_ParseTuple(args, "f:pitch", &factor))
+ return NULL;
+
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_PitchFactory(self->factory, factor);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_volume_doc,
+ "volume(volume)\n\n"
+ "Changes the volume of a factory.\n\n"
+ ":arg volume: The new volume..\n"
+ ":type volume: float\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`\n\n"
+ ".. note:: Should be in the range [0, 1] to avoid clipping.\n\n"
+ ".. note:: This is a filter function, you might consider using "
+ ":attr:`Handle.volume` instead.");
+
+static PyObject *
+Factory_volume(Factory* self, PyObject* args)
+{
+ float volume;
+
+ if(!PyArg_ParseTuple(args, "f:volume", &volume))
+ return NULL;
+
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_VolumeFactory(self->factory, volume);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_fadein_doc,
+ "fadein(start, length)\n\n"
+ "Fades a factory in by raising the volume linearly in the given "
+ "time interval.\n\n"
+ ":arg start: Time in seconds when the fading should start.\n"
+ ":type start: float\n"
+ ":arg length: Time in seconds how long the fading should last.\n"
+ ":type length: float\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`\n\n"
+ ".. note:: Before the fade starts it plays silence.");
+
+static PyObject *
+Factory_fadein(Factory* self, PyObject* args)
+{
+ float start, length;
+
+ if(!PyArg_ParseTuple(args, "ff:fadein", &start, &length))
+ return NULL;
+
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_IN, start, length);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_fadeout_doc,
+ "fadeout(start, length)\n\n"
+ "Fades a factory in by lowering the volume linearly in the given "
+ "time interval.\n\n"
+ ":arg start: Time in seconds when the fading should start.\n"
+ ":type start: float\n"
+ ":arg length: Time in seconds how long the fading should last.\n"
+ ":type length: float\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`\n\n"
+ ".. note:: After the fade this factory plays silence, so that "
+ "the length of the factory is not altered.");
+
+static PyObject *
+Factory_fadeout(Factory* self, PyObject* args)
+{
+ float start, length;
+
+ if(!PyArg_ParseTuple(args, "ff:fadeout", &start, &length))
+ return NULL;
+
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_OUT, start, length);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_loop_doc,
+ "loop(count)\n\n"
+ "Loops a factory.\n\n"
+ ":arg count: How often the factory should be looped. "
+ "Negative values mean endlessly.\n"
+ ":type count: integer\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`\n\n"
+ ".. note:: This is a filter function, you might consider using "
+ ":attr:`Handle.loop_count` instead.");
+
+static PyObject *
+Factory_loop(Factory* self, PyObject* args)
+{
+ int loop;
+
+ if(!PyArg_ParseTuple(args, "i:loop", &loop))
+ return NULL;
+
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_LoopFactory(self->factory, loop);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_mix_doc,
+ "mix(factory)\n\n"
+ "Mixes two factories.\n\n"
+ ":arg factory: The factory to mix over the other.\n"
+ ":type factory: :class:`Factory`\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`\n\n"
+ ".. note:: The two factories have to have the same specifications "
+ "(channels and samplerate).");
+
+static PyObject *
+Factory_mix(Factory* self, PyObject* object)
+{
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+
+ if(!PyObject_TypeCheck(object, type))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
+ return NULL;
+ }
+
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+ Factory *child = (Factory*)object;
+
+ if(parent != NULL)
+ {
+ parent->child_list = Py_BuildValue("(OO)", self, object);
+
+ try
+ {
+ parent->factory = new AUD_SuperposeFactory(self->factory, child->factory);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_pingpong_doc,
+ "pingpong()\n\n"
+ "Plays a factory forward and then backward.\n"
+ "This is like joining a factory with its reverse.\n\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`");
+
+static PyObject *
+Factory_pingpong(Factory* self)
+{
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_PingPongFactory(self->factory);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_reverse_doc,
+ "reverse()\n\n"
+ "Plays a factory reversed.\n\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`\n\n"
+ ".. note:: The factory has to have a finite length and has to be "
+ "seekable. It's recommended to use this only with factories with "
+ "fast and accurate seeking, which is not true for encoded audio "
+ "files, such ones should be buffered using :meth:`buffer` before "
+ "being played reversed.\n\n"
+ ".. warning:: If seeking is not accurate in the underlying factory "
+ "you'll likely hear skips/jumps/cracks.");
+
+static PyObject *
+Factory_reverse(Factory* self)
+{
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_ReverseFactory(self->factory);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_buffer_doc,
+ "buffer()\n\n"
+ "Buffers a factory into RAM.\n"
+ "This saves CPU usage needed for decoding and file access if the "
+ "underlying factory reads from a file on the harddisk, but it "
+ "consumes a lot of memory.\n\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`\n\n"
+ ".. note:: Only known-length factories can be buffered.\n\n"
+ ".. warning:: Raw PCM data needs a lot of space, only buffer "
+ "short factories.");
+
+static PyObject *
+Factory_buffer(Factory* self)
+{
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ try
+ {
+ parent->factory = new AUD_StreamBufferFactory(self->factory);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_square_doc,
+ "square(threshold = 0)\n\n"
+ "Makes a square wave out of an audio wave by setting all samples "
+ "with a amplitude >= threshold to 1, all <= -threshold to -1 and "
+ "all between to 0.\n\n"
+ ":arg threshold: Threshold value over which an amplitude counts "
+ "non-zero.\n"
+ ":type threshold: float\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`");
+
+static PyObject *
+Factory_square(Factory* self, PyObject* args)
+{
+ float threshold = 0;
+
+ if(!PyArg_ParseTuple(args, "|f:square", &threshold))
+ return NULL;
+
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_SquareFactory(self->factory, threshold);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Factory_filter_doc,
+ "filter(b, a = (1))\n\n"
+ "Filters a factory with the supplied IIR filter coefficients.\n"
+ "Without the second parameter you'll get a FIR filter.\n"
+ "If the first value of the a sequence is 0 it will be set to 1 "
+ "automatically.\n"
+ "If the first value of the a sequence is neither 0 nor 1, all "
+ "filter coefficients will be scaled by this value so that it is 1 "
+ "in the end, you don't have to scale yourself.\n\n"
+ ":arg b: The nominator filter coefficients.\n"
+ ":type b: sequence of float\n"
+ ":arg a: The denominator filter coefficients.\n"
+ ":type a: sequence of float\n"
+ ":return: The created :class:`Factory` object.\n"
+ ":rtype: :class:`Factory`");
+
+static PyObject *
+Factory_filter(Factory* self, PyObject* args)
+{
+ PyObject* py_b;
+ PyObject* py_a = NULL;
+
+ if(!PyArg_ParseTuple(args, "O|O:filter", &py_b, &py_a))
+ return NULL;
+
+ if(!PySequence_Check(py_b) || (py_a != NULL && !PySequence_Check(py_a)))
+ {
+ PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
+ return NULL;
+ }
+
+ if(!PySequence_Length(py_b) || (py_a != NULL && !PySequence_Length(py_a)))
+ {
+ PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
+ return NULL;
+ }
+
+ std::vector<float> a, b;
+ PyObject* py_value;
+ float value;
+ int result;
+
+ for(int i = 0; i < PySequence_Length(py_b); i++)
+ {
+ py_value = PySequence_GetItem(py_b, i);
+ result = PyArg_Parse(py_value, "f:filter", &value);
+ Py_DECREF(py_value);
+
+ if(!result)
+ return NULL;
+
+ b.push_back(value);
+ }
+
+ if(py_a)
+ {
+ for(int i = 0; i < PySequence_Length(py_a); i++)
+ {
+ py_value = PySequence_GetItem(py_a, i);
+ result = PyArg_Parse(py_value, "f:filter", &value);
+ Py_DECREF(py_value);
+
+ if(!result)
+ return NULL;
+
+ a.push_back(value);
+ }
+
+ if(a[0] == 0)
+ a[0] = 1;
+ }
+ else
+ a.push_back(1);
+
+ PyTypeObject* type = ((PyObject*)self)->ob_type;
+ Factory *parent = (Factory*)type->tp_alloc(type, 0);
+
+ if(parent != NULL)
+ {
+ Py_INCREF(self);
+ parent->child_list = (PyObject*)self;
+
+ try
+ {
+ parent->factory = new AUD_IIRFilterFactory(self->factory, b, a);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+static PyMethodDef Factory_methods[] = {
+ {"sine", (PyCFunction)Factory_sine, METH_VARARGS | METH_CLASS,
+ M_aud_Factory_sine_doc
+ },
+ {"file", (PyCFunction)Factory_file, METH_VARARGS | METH_CLASS,
+ M_aud_Factory_file_doc
+ },
+ {"lowpass", (PyCFunction)Factory_lowpass, METH_VARARGS,
+ M_aud_Factory_lowpass_doc
+ },
+ {"delay", (PyCFunction)Factory_delay, METH_VARARGS,
+ M_aud_Factory_delay_doc
+ },
+ {"join", (PyCFunction)Factory_join, METH_O,
+ M_aud_Factory_join_doc
+ },
+ {"highpass", (PyCFunction)Factory_highpass, METH_VARARGS,
+ M_aud_Factory_highpass_doc
+ },
+ {"limit", (PyCFunction)Factory_limit, METH_VARARGS,
+ M_aud_Factory_limit_doc
+ },
+ {"pitch", (PyCFunction)Factory_pitch, METH_VARARGS,
+ M_aud_Factory_pitch_doc
+ },
+ {"volume", (PyCFunction)Factory_volume, METH_VARARGS,
+ M_aud_Factory_volume_doc
+ },
+ {"fadein", (PyCFunction)Factory_fadein, METH_VARARGS,
+ M_aud_Factory_fadein_doc
+ },
+ {"fadeout", (PyCFunction)Factory_fadeout, METH_VARARGS,
+ M_aud_Factory_fadeout_doc
+ },
+ {"loop", (PyCFunction)Factory_loop, METH_VARARGS,
+ M_aud_Factory_loop_doc
+ },
+ {"mix", (PyCFunction)Factory_mix, METH_O,
+ M_aud_Factory_mix_doc
+ },
+ {"pingpong", (PyCFunction)Factory_pingpong, METH_NOARGS,
+ M_aud_Factory_pingpong_doc
+ },
+ {"reverse", (PyCFunction)Factory_reverse, METH_NOARGS,
+ M_aud_Factory_reverse_doc
+ },
+ {"buffer", (PyCFunction)Factory_buffer, METH_NOARGS,
+ M_aud_Factory_buffer_doc
+ },
+ {"square", (PyCFunction)Factory_square, METH_VARARGS,
+ M_aud_Factory_square_doc
+ },
+ {"filter", (PyCFunction)Factory_filter, METH_VARARGS,
+ M_aud_Factory_filter_doc
+ },
+ {NULL} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Factory_doc,
+ "Factory objects are immutable and represent a sound that can be "
+ "played simultaneously multiple times. They are called factories "
+ "because they create reader objects internally that are used for "
+ "playback.");
+
+static PyTypeObject FactoryType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "aud.Factory", /* tp_name */
+ sizeof(Factory), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Factory_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* 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, /* tp_flags */
+ M_aud_Factory_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Factory_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Factory_new, /* tp_new */
+};
+
+// ========== Handle ==================================================
+
+static void
+Handle_dealloc(Handle* self)
+{
+ Py_XDECREF(self->device);
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+PyDoc_STRVAR(M_aud_Handle_pause_doc,
+ "pause()\n\n"
+ "Pauses playback.\n\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool");
+
+static PyObject *
+Handle_pause(Handle *self)
+{
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ if(device->device->pause(self->handle))
+ {
+ Py_RETURN_TRUE;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+
+ Py_RETURN_FALSE;
+}
+
+PyDoc_STRVAR(M_aud_Handle_resume_doc,
+ "resume()\n\n"
+ "Resumes playback.\n\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool");
+
+static PyObject *
+Handle_resume(Handle *self)
+{
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ if(device->device->resume(self->handle))
+ {
+ Py_RETURN_TRUE;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+
+ Py_RETURN_FALSE;
+}
+
+PyDoc_STRVAR(M_aud_Handle_stop_doc,
+ "stop()\n\n"
+ "Stops playback.\n\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool\n\n"
+ ".. note:: This makes the handle invalid.");
+
+static PyObject *
+Handle_stop(Handle *self)
+{
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ if(device->device->stop(self->handle))
+ {
+ Py_RETURN_TRUE;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+
+ Py_RETURN_FALSE;
+}
+
+static PyMethodDef Handle_methods[] = {
+ {"pause", (PyCFunction)Handle_pause, METH_NOARGS,
+ M_aud_Handle_pause_doc
+ },
+ {"resume", (PyCFunction)Handle_resume, METH_NOARGS,
+ M_aud_Handle_resume_doc
+ },
+ {"stop", (PyCFunction)Handle_stop, METH_NOARGS,
+ M_aud_Handle_stop_doc
+ },
+ {NULL} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Handle_position_doc,
+ "The playback position of the sound in seconds.");
+
+static PyObject *
+Handle_get_position(Handle *self, void* nothing)
+{
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ return Py_BuildValue("f", device->device->getPosition(self->handle));
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_position(Handle *self, PyObject* args, void* nothing)
+{
+ float position;
+
+ if(!PyArg_Parse(args, "f:position", &position))
+ return -1;
+
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ if(device->device->seek(self->handle, position))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't seek the sound!");
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_keep_doc,
+ "Whether the sound should be kept paused in the device when its "
+ "end is reached.\n"
+ "This can be used to seek the sound to some position and start "
+ "playback again.\n\n"
+ ".. warning:: If this is set to true and you forget stopping this "
+ "equals a memory leak as the handle exists until the device is "
+ "destroyed.");
+
+static PyObject *
+Handle_get_keep(Handle *self, void* nothing)
+{
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ if(device->device->getKeep(self->handle))
+ {
+ Py_RETURN_TRUE;
+ }
+ else
+ {
+ Py_RETURN_FALSE;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_keep(Handle *self, PyObject* args, void* nothing)
+{
+ if(!PyBool_Check(args))
+ {
+ PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
+ return -1;
+ }
+
+ bool keep = args == Py_True;
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ if(device->device->setKeep(self->handle, keep))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set keep of the sound!");
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_status_doc,
+ "Whether the sound is playing, paused or stopped (=invalid).");
+
+static PyObject *
+Handle_get_status(Handle *self, void* nothing)
+{
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ return Py_BuildValue("i", device->device->getStatus(self->handle));
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Handle_volume_doc,
+ "The volume of the sound.");
+
+static PyObject *
+Handle_get_volume(Handle *self, void* nothing)
+{
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ return Py_BuildValue("f", device->device->getVolume(self->handle));
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_volume(Handle *self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:volume", &volume))
+ return -1;
+
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ if(device->device->setVolume(self->handle, volume))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the sound volume!");
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_pitch_doc,
+ "The pitch of the sound.");
+
+static PyObject *
+Handle_get_pitch(Handle *self, void* nothing)
+{
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ return Py_BuildValue("f", device->device->getPitch(self->handle));
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_pitch(Handle *self, PyObject* args, void* nothing)
+{
+ float pitch;
+
+ if(!PyArg_Parse(args, "f:pitch", &pitch))
+ return -1;
+
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ if(device->device->setPitch(self->handle, pitch))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the sound pitch!");
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_loop_count_doc,
+ "The (remaining) loop count of the sound. A negative value indicates infinity.");
+
+static PyObject *
+Handle_get_loop_count(Handle *self, void* nothing)
+{
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ return Py_BuildValue("i", device->device->getLoopCount(self->handle));
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_loop_count(Handle *self, PyObject* args, void* nothing)
+{
+ int loops;
+
+ if(!PyArg_Parse(args, "i:loop_count", &loops))
+ return -1;
+
+ Device* device = (Device*)self->device;
+
+ try
+ {
+ if(device->device->setLoopCount(self->handle, loops))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the loop count!");
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_location_doc,
+ "The source's location in 3D space, a 3D tuple of floats.");
+
+static PyObject *
+Handle_get_location(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ AUD_Vector3 v = device->getSourceLocation(self->handle);
+ return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return NULL;
+}
+
+static int
+Handle_set_location(Handle *self, PyObject* args, void* nothing)
+{
+ float x, y, z;
+
+ if(!PyArg_Parse(args, "(fff):location", &x, &y, &z))
+ return -1;
+
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ AUD_Vector3 location(x, y, z);
+ if(device->setSourceLocation(self->handle, location))
+ return 0;
+ PyErr_SetString(AUDError, "Location couldn't be set!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_velocity_doc,
+ "The source's velocity in 3D space, a 3D tuple of floats.");
+
+static PyObject *
+Handle_get_velocity(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ AUD_Vector3 v = device->getSourceVelocity(self->handle);
+ return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return NULL;
+}
+
+static int
+Handle_set_velocity(Handle *self, PyObject* args, void* nothing)
+{
+ float x, y, z;
+
+ if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z))
+ return -1;
+
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ AUD_Vector3 velocity(x, y, z);
+ if(device->setSourceVelocity(self->handle, velocity))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the velocity!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_orientation_doc,
+ "The source's orientation in 3D space as quaternion, a 4 float tuple.");
+
+static PyObject *
+Handle_get_orientation(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ AUD_Quaternion o = device->getSourceOrientation(self->handle);
+ return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return NULL;
+}
+
+static int
+Handle_set_orientation(Handle *self, PyObject* args, void* nothing)
+{
+ float w, x, y, z;
+
+ if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z))
+ return -1;
+
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ AUD_Quaternion orientation(w, x, y, z);
+ if(device->setSourceOrientation(self->handle, orientation))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the orientation!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_relative_doc,
+ "Whether the source's location, velocity and orientation is relative or absolute to the listener.");
+
+static PyObject *
+Handle_get_relative(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ if(device->isRelative(self->handle))
+ {
+ Py_RETURN_TRUE;
+ }
+ else
+ {
+ Py_RETURN_FALSE;
+ }
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return NULL;
+}
+
+static int
+Handle_set_relative(Handle *self, PyObject* args, void* nothing)
+{
+ if(!PyBool_Check(args))
+ {
+ PyErr_SetString(PyExc_TypeError, "Value is not a boolean!");
+ return -1;
+ }
+
+ bool relative = (args == Py_True);
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ if(device->setRelative(self->handle, relative))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the relativeness!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc,
+ "The minimum volume of the source.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+Handle_get_volume_minimum(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ return Py_BuildValue("f", device->getVolumeMinimum(self->handle));
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return NULL;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:volume_minimum", &volume))
+ return -1;
+
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ if(device->setVolumeMinimum(self->handle, volume))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the minimum volume!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc,
+ "The maximum volume of the source.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+Handle_get_volume_maximum(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ return Py_BuildValue("f", device->getVolumeMaximum(self->handle));
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return NULL;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:volume_maximum", &volume))
+ return -1;
+
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ if(device->setVolumeMaximum(self->handle, volume))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the maximum volume!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_distance_reference_doc,
+ "The reference distance of the source.\n"
+ "At this distance the volume will be exactly :attr:`volume`.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+Handle_get_distance_reference(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ return Py_BuildValue("f", device->getDistanceReference(self->handle));
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return NULL;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing)
+{
+ float distance;
+
+ if(!PyArg_Parse(args, "f:distance_reference", &distance))
+ return -1;
+
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ if(device->setDistanceReference(self->handle, distance))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the reference distance!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc,
+ "The maximum distance of the source.\n"
+ "If the listener is further away the source volume will be 0.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+Handle_get_distance_maximum(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ return Py_BuildValue("f", device->getDistanceMaximum(self->handle));
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return NULL;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing)
+{
+ float distance;
+
+ if(!PyArg_Parse(args, "f:distance_maximum", &distance))
+ return -1;
+
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ if(device->setDistanceMaximum(self->handle, distance))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the maximum distance!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_attenuation_doc,
+ "This factor is used for distance based attenuation of the "
+ "source.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+Handle_get_attenuation(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ return Py_BuildValue("f", device->getAttenuation(self->handle));
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return NULL;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_attenuation(Handle *self, PyObject* args, void* nothing)
+{
+ float factor;
+
+ if(!PyArg_Parse(args, "f:attenuation", &factor))
+ return -1;
+
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ if(device->setAttenuation(self->handle, factor))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the attenuation!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc,
+ "The opening angle of the inner cone of the source. If the cone "
+ "values of a source are set there are two (audible) cones with "
+ "the apex at the :attr:`location` of the source and with infinite "
+ "height, heading in the direction of the source's "
+ ":attr:`orientation`.\n"
+ "In the inner cone the volume is normal. Outside the outer cone "
+ "the volume will be :attr:`cone_volume_outer` and in the area "
+ "between the volume will be interpolated linearly.");
+
+static PyObject *
+Handle_get_cone_angle_inner(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ return Py_BuildValue("f", device->getConeAngleInner(self->handle));
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return NULL;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing)
+{
+ float angle;
+
+ if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
+ return -1;
+
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ if(device->setConeAngleInner(self->handle, angle))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the cone inner angle!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc,
+ "The opening angle of the outer cone of the source.\n\n"
+ ".. seealso:: :attr:`cone_angle_inner`");
+
+static PyObject *
+Handle_get_cone_angle_outer(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ return Py_BuildValue("f", device->getConeAngleOuter(self->handle));
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return NULL;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing)
+{
+ float angle;
+
+ if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
+ return -1;
+
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ if(device->setConeAngleOuter(self->handle, angle))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the cone outer angle!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc,
+ "The volume outside the outer cone of the source.\n\n"
+ ".. seealso:: :attr:`cone_angle_inner`");
+
+static PyObject *
+Handle_get_cone_volume_outer(Handle *self, void* nothing)
+{
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ return Py_BuildValue("f", device->getConeVolumeOuter(self->handle));
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return NULL;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
+ return -1;
+
+ Device* dev = (Device*)self->device;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
+ if(device)
+ {
+ if(device->setConeVolumeOuter(self->handle, volume))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the cone outer volume!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+static PyGetSetDef Handle_properties[] = {
+ {(char*)"position", (getter)Handle_get_position, (setter)Handle_set_position,
+ M_aud_Handle_position_doc, NULL },
+ {(char*)"keep", (getter)Handle_get_keep, (setter)Handle_set_keep,
+ M_aud_Handle_keep_doc, NULL },
+ {(char*)"status", (getter)Handle_get_status, NULL,
+ M_aud_Handle_status_doc, NULL },
+ {(char*)"volume", (getter)Handle_get_volume, (setter)Handle_set_volume,
+ M_aud_Handle_volume_doc, NULL },
+ {(char*)"pitch", (getter)Handle_get_pitch, (setter)Handle_set_pitch,
+ M_aud_Handle_pitch_doc, NULL },
+ {(char*)"loop_count", (getter)Handle_get_loop_count, (setter)Handle_set_loop_count,
+ M_aud_Handle_loop_count_doc, NULL },
+ {(char*)"location", (getter)Handle_get_location, (setter)Handle_set_location,
+ M_aud_Handle_location_doc, NULL },
+ {(char*)"velocity", (getter)Handle_get_velocity, (setter)Handle_set_velocity,
+ M_aud_Handle_velocity_doc, NULL },
+ {(char*)"orientation", (getter)Handle_get_orientation, (setter)Handle_set_orientation,
+ M_aud_Handle_orientation_doc, NULL },
+ {(char*)"relative", (getter)Handle_get_relative, (setter)Handle_set_relative,
+ M_aud_Handle_relative_doc, NULL },
+ {(char*)"volume_minimum", (getter)Handle_get_volume_minimum, (setter)Handle_set_volume_minimum,
+ M_aud_Handle_volume_minimum_doc, NULL },
+ {(char*)"volume_maximum", (getter)Handle_get_volume_maximum, (setter)Handle_set_volume_maximum,
+ M_aud_Handle_volume_maximum_doc, NULL },
+ {(char*)"distance_reference", (getter)Handle_get_distance_reference, (setter)Handle_set_distance_reference,
+ M_aud_Handle_distance_reference_doc, NULL },
+ {(char*)"distance_maximum", (getter)Handle_get_distance_maximum, (setter)Handle_set_distance_maximum,
+ M_aud_Handle_distance_maximum_doc, NULL },
+ {(char*)"attenuation", (getter)Handle_get_attenuation, (setter)Handle_set_attenuation,
+ M_aud_Handle_attenuation_doc, NULL },
+ {(char*)"cone_angle_inner", (getter)Handle_get_cone_angle_inner, (setter)Handle_set_cone_angle_inner,
+ M_aud_Handle_cone_angle_inner_doc, NULL },
+ {(char*)"cone_angle_outer", (getter)Handle_get_cone_angle_outer, (setter)Handle_set_cone_angle_outer,
+ M_aud_Handle_cone_angle_outer_doc, NULL },
+ {(char*)"cone_volume_outer", (getter)Handle_get_cone_volume_outer, (setter)Handle_set_cone_volume_outer,
+ M_aud_Handle_cone_volume_outer_doc, NULL },
+ {NULL} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Handle_doc,
+ "Handle objects are playback handles that can be used to control "
+ "playback of a sound. If a sound is played back multiple times "
+ "then there are as many handles.");
+
+static PyTypeObject HandleType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "aud.Handle", /* tp_name */
+ sizeof(Handle), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Handle_dealloc,/* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* 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, /* tp_flags */
+ M_aud_Handle_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Handle_methods, /* tp_methods */
+ 0, /* tp_members */
+ Handle_properties, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+// ========== Device ==================================================
+
+static void
+Device_dealloc(Device* self)
+{
+ if(self->device)
+ delete self->device;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ Device *self;
+
+ static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL};
+ int device;
+ int rate = AUD_RATE_44100;
+ int channels = AUD_CHANNELS_STEREO;
+ int format = AUD_FORMAT_FLOAT32;
+ int buffersize = AUD_DEFAULT_BUFFER_SIZE;
+ const char* name = "Audaspace";
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiis:Device", const_cast<char**>(kwlist),
+ &device, &rate, &channels, &format, &buffersize, &name))
+ return NULL;
+
+ if(buffersize < 128)
+ {
+ PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than 127!");
+ return NULL;
+ }
+
+ self = (Device*)type->tp_alloc(type, 0);
+ if(self != NULL)
+ {
+ AUD_DeviceSpecs specs;
+ specs.channels = (AUD_Channels)channels;
+ specs.format = (AUD_SampleFormat)format;
+ specs.rate = (AUD_SampleRate)rate;
+
+ self->device = NULL;
+
+ try
+ {
+ switch(device)
+ {
+ case AUD_DEVICE_NULL:
+ self->device = new AUD_NULLDevice();
+ break;
+ case AUD_DEVICE_OPENAL:
+#ifdef WITH_OPENAL
+ self->device = new AUD_OpenALDevice(specs, buffersize);
+#endif
+ break;
+ case AUD_DEVICE_SDL:
+#ifdef WITH_SDL
+ self->device = new AUD_SDLDevice(specs, buffersize);
+#endif
+ break;
+ case AUD_DEVICE_JACK:
+#ifdef WITH_JACK
+ self->device = new AUD_JackDevice(name, specs, buffersize);
+#endif
+ break;
+ case AUD_DEVICE_READ:
+ break;
+ }
+
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+
+ if(!self->device)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, "Unsupported device type!");
+ return NULL;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Device_play_doc,
+ "play(factory, keep=False)\n\n"
+ "Plays a factory.\n\n"
+ ":arg factory: The factory to play.\n"
+ ":type factory: :class:`Factory`\n"
+ ":arg keep: See :attr:`Handle.keep`.\n"
+ ":type keep: bool\n"
+ ":return: The playback handle with which playback can be "
+ "controlled with.\n"
+ ":rtype: :class:`Handle`");
+
+static PyObject *
+Device_play(Device *self, PyObject *args, PyObject *kwds)
+{
+ PyObject* object;
+ PyObject* keepo = NULL;
+
+ bool keep = false;
+
+ static const char *kwlist[] = {"factory", "keep", NULL};
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:play", const_cast<char**>(kwlist), &object, &keepo))
+ return NULL;
+
+ if(!PyObject_TypeCheck(object, &FactoryType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
+ return NULL;
+ }
+
+ if(keepo != NULL)
+ {
+ if(!PyBool_Check(keepo))
+ {
+ PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
+ return NULL;
+ }
+
+ keep = keepo == Py_True;
+ }
+
+ Factory* sound = (Factory*)object;
+ Handle *handle;
+
+ handle = (Handle*)HandleType.tp_alloc(&HandleType, 0);
+ if(handle != NULL)
+ {
+ handle->device = (PyObject*)self;
+ Py_INCREF(self);
+
+ try
+ {
+ handle->handle = self->device->play(sound->factory, keep);
+ }
+ catch(AUD_Exception& e)
+ {
+ Py_DECREF(handle);
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+ }
+
+ return (PyObject *)handle;
+}
+
+PyDoc_STRVAR(M_aud_Device_lock_doc,
+ "lock()\n\n"
+ "Locks the device so that it's guaranteed, that no samples are "
+ "read from the streams until :meth:`unlock` is called.\n"
+ "This is useful if you want to do start/stop/pause/resume some "
+ "sounds at the same time.\n\n"
+ ".. note:: The device has to be unlocked as often as locked to be "
+ "able to continue playback.\n\n"
+ ".. warning:: Make sure the time between locking and unlocking is "
+ "as short as possible to avoid clicks.");
+
+static PyObject *
+Device_lock(Device *self)
+{
+ try
+ {
+ self->device->lock();
+ Py_RETURN_NONE;
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Device_unlock_doc,
+ "unlock()\n\n"
+ "Unlocks the device after a lock call, see :meth:`lock` for "
+ "details.");
+
+static PyObject *
+Device_unlock(Device *self)
+{
+ try
+ {
+ self->device->unlock();
+ Py_RETURN_NONE;
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static PyMethodDef Device_methods[] = {
+ {"play", (PyCFunction)Device_play, METH_VARARGS | METH_KEYWORDS,
+ M_aud_Device_play_doc
+ },
+ {"lock", (PyCFunction)Device_lock, METH_NOARGS,
+ M_aud_Device_lock_doc
+ },
+ {"unlock", (PyCFunction)Device_unlock, METH_NOARGS,
+ M_aud_Device_unlock_doc
+ },
+ {NULL} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Device_rate_doc,
+ "The sampling rate of the device in Hz.");
+
+static PyObject *
+Device_get_rate(Device *self, void* nothing)
+{
+ try
+ {
+ AUD_DeviceSpecs specs = self->device->getSpecs();
+ return Py_BuildValue("i", specs.rate);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Device_format_doc,
+ "The native sample format of the device.");
+
+static PyObject *
+Device_get_format(Device *self, void* nothing)
+{
+ try
+ {
+ AUD_DeviceSpecs specs = self->device->getSpecs();
+ return Py_BuildValue("i", specs.format);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Device_channels_doc,
+ "The channel count of the device.");
+
+static PyObject *
+Device_get_channels(Device *self, void* nothing)
+{
+ try
+ {
+ AUD_DeviceSpecs specs = self->device->getSpecs();
+ return Py_BuildValue("i", specs.channels);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Device_volume_doc,
+ "The overall volume of the device.");
+
+static PyObject *
+Device_get_volume(Device *self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", self->device->getVolume());
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Device_set_volume(Device *self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:volume", &volume))
+ return -1;
+
+ try
+ {
+ self->device->setVolume(volume);
+ return 0;
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return -1;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Device_listener_location_doc,
+ "The listeners's location in 3D space, a 3D tuple of floats.");
+
+static PyObject *
+Device_get_listener_location(Device *self, void* nothing)
+{
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ AUD_Vector3 v = device->getListenerLocation();
+ return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return NULL;
+}
+
+static int
+Device_set_listener_location(Device *self, PyObject* args, void* nothing)
+{
+ float x, y, z;
+
+ if(!PyArg_Parse(args, "(fff):listener_location", &x, &y, &z))
+ return -1;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ AUD_Vector3 location(x, y, z);
+ device->setListenerLocation(location);
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Device_listener_velocity_doc,
+ "The listener's velocity in 3D space, a 3D tuple of floats.");
+
+static PyObject *
+Device_get_listener_velocity(Device *self, void* nothing)
+{
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ AUD_Vector3 v = device->getListenerVelocity();
+ return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return NULL;
+}
+
+static int
+Device_set_listener_velocity(Device *self, PyObject* args, void* nothing)
+{
+ float x, y, z;
+
+ if(!PyArg_Parse(args, "(fff):listener_velocity", &x, &y, &z))
+ return -1;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ AUD_Vector3 velocity(x, y, z);
+ device->setListenerVelocity(velocity);
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Device_listener_orientation_doc,
+ "The listener's orientation in 3D space as quaternion, a 4 float tuple.");
+
+static PyObject *
+Device_get_listener_orientation(Device *self, void* nothing)
+{
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ AUD_Quaternion o = device->getListenerOrientation();
+ return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return NULL;
+}
+
+static int
+Device_set_listener_orientation(Device *self, PyObject* args, void* nothing)
+{
+ float w, x, y, z;
+
+ if(!PyArg_Parse(args, "(ffff):listener_orientation", &w, &x, &y, &z))
+ return -1;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ AUD_Quaternion orientation(w, x, y, z);
+ device->setListenerOrientation(orientation);
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Device_speed_of_sound_doc,
+ "The speed of sound of the device.\n"
+ "The speed of sound in air is typically 343 m/s.");
+
+static PyObject *
+Device_get_speed_of_sound(Device *self, void* nothing)
+{
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ return Py_BuildValue("f", device->getSpeedOfSound());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return NULL;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing)
+{
+ float speed;
+
+ if(!PyArg_Parse(args, "f:speed_of_sound", &speed))
+ return -1;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ device->setSpeedOfSound(speed);
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Device_doppler_factor_doc,
+ "The doppler factor of the device.\n"
+ "This factor is a scaling factor for the velocity vectors in "
+ "doppler calculation. So a value bigger than 1 will exaggerate "
+ "the effect as it raises the velocity.");
+
+static PyObject *
+Device_get_doppler_factor(Device *self, void* nothing)
+{
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ return Py_BuildValue("f", device->getDopplerFactor());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return NULL;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Device_set_doppler_factor(Device *self, PyObject* args, void* nothing)
+{
+ float factor;
+
+ if(!PyArg_Parse(args, "f:doppler_factor", &factor))
+ return -1;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ device->setDopplerFactor(factor);
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Device_distance_model_doc,
+ "The distance model of the device.\n\n"
+ ".. seealso:: http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835864");
+
+static PyObject *
+Device_get_distance_model(Device *self, void* nothing)
+{
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ return Py_BuildValue("i", int(device->getDistanceModel()));
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return NULL;
+ }
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ return NULL;
+ }
+}
+
+static int
+Device_set_distance_model(Device *self, PyObject* args, void* nothing)
+{
+ int model;
+
+ if(!PyArg_Parse(args, "i:distance_model", &model))
+ return -1;
+
+ try
+ {
+ AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
+ if(device)
+ {
+ device->setDistanceModel(AUD_DistanceModel(model));
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(AUD_Exception& e)
+ {
+ PyErr_SetString(AUDError, e.str);
+ }
+
+ return -1;
+}
+
+static PyGetSetDef Device_properties[] = {
+ {(char*)"rate", (getter)Device_get_rate, NULL,
+ M_aud_Device_rate_doc, NULL },
+ {(char*)"format", (getter)Device_get_format, NULL,
+ M_aud_Device_format_doc, NULL },
+ {(char*)"channels", (getter)Device_get_channels, NULL,
+ M_aud_Device_channels_doc, NULL },
+ {(char*)"volume", (getter)Device_get_volume, (setter)Device_set_volume,
+ M_aud_Device_volume_doc, NULL },
+ {(char*)"listener_location", (getter)Device_get_listener_location, (setter)Device_set_listener_location,
+ M_aud_Device_listener_location_doc, NULL },
+ {(char*)"listener_velocity", (getter)Device_get_listener_velocity, (setter)Device_set_listener_velocity,
+ M_aud_Device_listener_velocity_doc, NULL },
+ {(char*)"listener_orientation", (getter)Device_get_listener_orientation, (setter)Device_set_listener_orientation,
+ M_aud_Device_listener_orientation_doc, NULL },
+ {(char*)"speed_of_sound", (getter)Device_get_speed_of_sound, (setter)Device_set_speed_of_sound,
+ M_aud_Device_speed_of_sound_doc, NULL },
+ {(char*)"doppler_factor", (getter)Device_get_doppler_factor, (setter)Device_set_doppler_factor,
+ M_aud_Device_doppler_factor_doc, NULL },
+ {(char*)"distance_model", (getter)Device_get_distance_model, (setter)Device_set_distance_model,
+ M_aud_Device_distance_model_doc, NULL },
+ {NULL} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Device_doc,
+ "Device objects represent an audio output backend like OpenAL or "
+ "SDL, but might also represent a file output or RAM buffer "
+ "output.");
+
+static PyTypeObject DeviceType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "aud.Device", /* tp_name */
+ sizeof(Device), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Device_dealloc,/* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* 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, /* tp_flags */
+ M_aud_Device_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Device_methods, /* tp_methods */
+ 0, /* tp_members */
+ Device_properties, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Device_new, /* tp_new */
+};
+
+PyObject *
+Device_empty()
+{
+ return DeviceType.tp_alloc(&DeviceType, 0);
+}
+
+// ====================================================================
+
+PyDoc_STRVAR(M_aud_doc,
+ "This module provides access to the audaspace audio library.");
+
+static struct PyModuleDef audmodule = {
+ PyModuleDef_HEAD_INIT,
+ "aud", /* name of module */
+ M_aud_doc, /* module documentation */
+ -1, /* size of per-interpreter state of the module,
+ or -1 if the module keeps state in global variables. */
+ NULL, NULL, NULL, NULL, NULL
+};
+
+PyMODINIT_FUNC
+PyInit_aud(void)
+{
+ PyObject* m;
+
+ if(PyType_Ready(&FactoryType) < 0)
+ return NULL;
+
+ if(PyType_Ready(&DeviceType) < 0)
+ return NULL;
+
+ if(PyType_Ready(&HandleType) < 0)
+ return NULL;
+
+ m = PyModule_Create(&audmodule);
+ if(m == NULL)
+ return NULL;
+
+ Py_INCREF(&FactoryType);
+ PyModule_AddObject(m, "Factory", (PyObject*)&FactoryType);
+
+ Py_INCREF(&DeviceType);
+ PyModule_AddObject(m, "Device", (PyObject*)&DeviceType);
+
+ Py_INCREF(&HandleType);
+ PyModule_AddObject(m, "Handle", (PyObject*)&HandleType);
+
+ AUDError = PyErr_NewException("aud.error", NULL, NULL);
+ Py_INCREF(AUDError);
+ PyModule_AddObject(m, "error", AUDError);
+
+ // device constants
+ PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_NULL);
+ PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_OPENAL);
+ PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_SDL);
+ PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_JACK);
+ //PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_READ);
+ // format constants
+ PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT32);
+ PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT64);
+ PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_INVALID);
+ PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S16);
+ PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S24);
+ PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S32);
+ PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_U8);
+ // status constants
+ PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_INVALID);
+ PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PAUSED);
+ PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PLAYING);
+ // distance model constants
+ PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT);
+ PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT_CLAMPED);
+ PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE);
+ PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE_CLAMPED);
+ PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR);
+ PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR_CLAMPED);
+ PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVALID);
+
+ return m;
+}