4 * ***** BEGIN LGPL LICENSE BLOCK *****
6 * Copyright 2009 Jörg Hermann Müller
8 * This file is part of AudaSpace.
10 * AudaSpace is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
15 * AudaSpace is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
23 * ***** END LGPL LICENSE BLOCK *****
26 #include "AUD_PyAPI.h"
27 #include "structmember.h"
29 #include "AUD_I3DDevice.h"
30 #include "AUD_NULLDevice.h"
31 #include "AUD_DelayFactory.h"
32 #include "AUD_DoubleFactory.h"
33 #include "AUD_FaderFactory.h"
34 #include "AUD_HighpassFactory.h"
35 #include "AUD_LimiterFactory.h"
36 #include "AUD_LoopFactory.h"
37 #include "AUD_LowpassFactory.h"
38 #include "AUD_PingPongFactory.h"
39 #include "AUD_PitchFactory.h"
40 #include "AUD_ReverseFactory.h"
41 #include "AUD_SinusFactory.h"
42 #include "AUD_FileFactory.h"
43 #include "AUD_SquareFactory.h"
44 #include "AUD_StreamBufferFactory.h"
45 #include "AUD_SuperposeFactory.h"
46 #include "AUD_VolumeFactory.h"
47 #include "AUD_IIRFilterFactory.h"
50 #include "AUD_SDLDevice.h"
54 #include "AUD_OpenALDevice.h"
58 #include "AUD_JackDevice.h"
61 // ====================================================================
72 // ====================================================================
74 #define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name)
76 // ====================================================================
78 static PyObject* AUDError;
80 static const char* device_not_3d_error = "Device is not a 3D device!";
82 // ====================================================================
85 Factory_dealloc(Factory* self)
89 Py_XDECREF(self->child_list);
90 Py_TYPE(self)->tp_free((PyObject*)self);
94 Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
98 self = (Factory*)type->tp_alloc(type, 0);
101 static const char *kwlist[] = {"filename", NULL};
102 const char* filename = NULL;
104 if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Factory", const_cast<char**>(kwlist), &filename))
112 self->factory = new AUD_FileFactory(filename);
114 catch(AUD_Exception& e)
117 PyErr_SetString(AUDError, e.str);
122 return (PyObject *)self;
125 PyDoc_STRVAR(M_aud_Factory_sine_doc,
126 "sine(frequency, rate=44100)\n\n"
127 "Creates a sine factory which plays a sine wave.\n\n"
128 ":arg frequency: The frequency of the sine wave in Hz.\n"
129 ":type frequency: float\n"
130 ":arg rate: The sampling rate in Hz. It's recommended to set this "
131 "value to the playback device's samling rate to avoid resamping.\n"
133 ":return: The created :class:`Factory` object.\n"
134 ":rtype: :class:`Factory`");
137 Factory_sine(PyTypeObject* type, PyObject* args)
142 if(!PyArg_ParseTuple(args, "f|i:sine", &frequency, &rate))
147 self = (Factory*)type->tp_alloc(type, 0);
152 self->factory = new AUD_SinusFactory(frequency, (AUD_SampleRate)rate);
154 catch(AUD_Exception& e)
157 PyErr_SetString(AUDError, e.str);
162 return (PyObject *)self;
165 PyDoc_STRVAR(M_aud_Factory_file_doc,
167 "Creates a factory object of a sound file.\n\n"
168 ":arg filename: Path of the file.\n"
169 ":type filename: string\n"
170 ":return: The created :class:`Factory` object.\n"
171 ":rtype: :class:`Factory`\n\n"
172 ".. warning:: If the file doesn't exist or can't be read you will "
173 "not get an exception immediately, but when you try to start "
174 "playback of that factory.");
177 Factory_file(PyTypeObject* type, PyObject* args)
179 const char* filename = NULL;
181 if(!PyArg_ParseTuple(args, "s:file", &filename))
186 self = (Factory*)type->tp_alloc(type, 0);
191 self->factory = new AUD_FileFactory(filename);
193 catch(AUD_Exception& e)
196 PyErr_SetString(AUDError, e.str);
201 return (PyObject *)self;
204 PyDoc_STRVAR(M_aud_Factory_lowpass_doc,
205 "lowpass(frequency, Q=0.5)\n\n"
206 "Creates a second order lowpass filter based on the transfer "
207 "function H(s) = 1 / (s^2 + s/Q + 1)\n\n"
208 ":arg frequency: The cut off trequency of the lowpass.\n"
209 ":type frequency: float\n"
210 ":arg Q: Q factor of the lowpass.\n"
212 ":return: The created :class:`Factory` object.\n"
213 ":rtype: :class:`Factory`");
216 Factory_lowpass(Factory* self, PyObject* args)
221 if(!PyArg_ParseTuple(args, "f|f:lowpass", &frequency, &Q))
224 PyTypeObject* type = ((PyObject*)self)->ob_type;
225 Factory *parent = (Factory*)type->tp_alloc(type, 0);
230 parent->child_list = (PyObject*)self;
234 parent->factory = new AUD_LowpassFactory(self->factory, frequency, Q);
236 catch(AUD_Exception& e)
239 PyErr_SetString(AUDError, e.str);
244 return (PyObject *)parent;
247 PyDoc_STRVAR(M_aud_Factory_delay_doc,
249 "Delays by playing adding silence in front of the other factory's "
251 ":arg time: How many seconds of silence should be added before "
253 ":type time: float\n"
254 ":return: The created :class:`Factory` object.\n"
255 ":rtype: :class:`Factory`");
258 Factory_delay(Factory* self, PyObject* args)
262 if(!PyArg_ParseTuple(args, "f:delay", &delay))
265 PyTypeObject* type = ((PyObject*)self)->ob_type;
266 Factory *parent = (Factory*)type->tp_alloc(type, 0);
271 parent->child_list = (PyObject*)self;
275 parent->factory = new AUD_DelayFactory(self->factory, delay);
277 catch(AUD_Exception& e)
280 PyErr_SetString(AUDError, e.str);
285 return (PyObject *)parent;
288 PyDoc_STRVAR(M_aud_Factory_join_doc,
290 "Plays two factories in sequence.\n\n"
291 ":arg factory: The factory to play second.\n"
292 ":type factory: :class:`Factory`\n"
293 ":return: The created :class:`Factory` object.\n"
294 ":rtype: :class:`Factory`\n\n"
295 ".. note:: The two factories have to have the same specifications "
296 "(channels and samplerate).");
299 Factory_join(Factory* self, PyObject* object)
301 PyTypeObject* type = ((PyObject*)self)->ob_type;
303 if(!PyObject_TypeCheck(object, type))
305 PyErr_SetString(PyExc_TypeError, "Object has to be of type Factory!");
310 Factory *child = (Factory*)object;
312 parent = (Factory*)type->tp_alloc(type, 0);
315 parent->child_list = Py_BuildValue("(OO)", self, object);
319 parent->factory = new AUD_DoubleFactory(self->factory, child->factory);
321 catch(AUD_Exception& e)
324 PyErr_SetString(AUDError, e.str);
329 return (PyObject *)parent;
332 PyDoc_STRVAR(M_aud_Factory_highpass_doc,
333 "highpass(frequency, Q=0.5)\n\n"
334 "Creates a second order highpass filter based on the transfer "
335 "function H(s) = s^2 / (s^2 + s/Q + 1)\n\n"
336 ":arg frequency: The cut off trequency of the highpass.\n"
337 ":type frequency: float\n"
338 ":arg Q: Q factor of the lowpass.\n"
340 ":return: The created :class:`Factory` object.\n"
341 ":rtype: :class:`Factory`");
344 Factory_highpass(Factory* self, PyObject* args)
349 if(!PyArg_ParseTuple(args, "f|f:highpass", &frequency, &Q))
352 PyTypeObject* type = ((PyObject*)self)->ob_type;
353 Factory *parent = (Factory*)type->tp_alloc(type, 0);
358 parent->child_list = (PyObject*)self;
362 parent->factory = new AUD_HighpassFactory(self->factory, frequency, Q);
364 catch(AUD_Exception& e)
367 PyErr_SetString(AUDError, e.str);
372 return (PyObject *)parent;
375 PyDoc_STRVAR(M_aud_Factory_limit_doc,
376 "limit(start, end)\n\n"
377 "Limits a factory within a specific start and end time.\n\n"
378 ":arg start: Start time in seconds.\n"
379 ":type start: float\n"
380 ":arg end: End time in seconds.\n"
382 ":return: The created :class:`Factory` object.\n"
383 ":rtype: :class:`Factory`");
386 Factory_limit(Factory* self, PyObject* args)
390 if(!PyArg_ParseTuple(args, "ff:limit", &start, &end))
393 PyTypeObject* type = ((PyObject*)self)->ob_type;
394 Factory *parent = (Factory*)type->tp_alloc(type, 0);
399 parent->child_list = (PyObject*)self;
403 parent->factory = new AUD_LimiterFactory(self->factory, start, end);
405 catch(AUD_Exception& e)
408 PyErr_SetString(AUDError, e.str);
413 return (PyObject *)parent;
416 PyDoc_STRVAR(M_aud_Factory_pitch_doc,
418 "Changes the pitch of a factory with a specific factor.\n\n"
419 ":arg factor: The factor to change the pitch with.\n"
420 ":type factor: float\n"
421 ":return: The created :class:`Factory` object.\n"
422 ":rtype: :class:`Factory`\n\n"
423 ".. note:: This is done by changing the sample rate of the "
424 "underlying factory, which has to be an integer, so the factor "
425 "value rounded and the factor may not be 100 % accurate.\n\n"
426 ".. note:: This is a filter function, you might consider using "
427 ":attr:`Handle.pitch` instead.");
430 Factory_pitch(Factory* self, PyObject* args)
434 if(!PyArg_ParseTuple(args, "f:pitch", &factor))
437 PyTypeObject* type = ((PyObject*)self)->ob_type;
438 Factory *parent = (Factory*)type->tp_alloc(type, 0);
443 parent->child_list = (PyObject*)self;
447 parent->factory = new AUD_PitchFactory(self->factory, factor);
449 catch(AUD_Exception& e)
452 PyErr_SetString(AUDError, e.str);
457 return (PyObject *)parent;
460 PyDoc_STRVAR(M_aud_Factory_volume_doc,
462 "Changes the volume of a factory.\n\n"
463 ":arg volume: The new volume..\n"
464 ":type volume: float\n"
465 ":return: The created :class:`Factory` object.\n"
466 ":rtype: :class:`Factory`\n\n"
467 ".. note:: Should be in the range [0, 1] to avoid clipping.\n\n"
468 ".. note:: This is a filter function, you might consider using "
469 ":attr:`Handle.volume` instead.");
472 Factory_volume(Factory* self, PyObject* args)
476 if(!PyArg_ParseTuple(args, "f:volume", &volume))
479 PyTypeObject* type = ((PyObject*)self)->ob_type;
480 Factory *parent = (Factory*)type->tp_alloc(type, 0);
485 parent->child_list = (PyObject*)self;
489 parent->factory = new AUD_VolumeFactory(self->factory, volume);
491 catch(AUD_Exception& e)
494 PyErr_SetString(AUDError, e.str);
499 return (PyObject *)parent;
502 PyDoc_STRVAR(M_aud_Factory_fadein_doc,
503 "fadein(start, length)\n\n"
504 "Fades a factory in by raising the volume linearly in the given "
506 ":arg start: Time in seconds when the fading should start.\n"
507 ":type start: float\n"
508 ":arg length: Time in seconds how long the fading should last.\n"
509 ":type length: float\n"
510 ":return: The created :class:`Factory` object.\n"
511 ":rtype: :class:`Factory`\n\n"
512 ".. note:: Before the fade starts it plays silence.");
515 Factory_fadein(Factory* self, PyObject* args)
519 if(!PyArg_ParseTuple(args, "ff:fadein", &start, &length))
522 PyTypeObject* type = ((PyObject*)self)->ob_type;
523 Factory *parent = (Factory*)type->tp_alloc(type, 0);
528 parent->child_list = (PyObject*)self;
532 parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_IN, start, length);
534 catch(AUD_Exception& e)
537 PyErr_SetString(AUDError, e.str);
542 return (PyObject *)parent;
545 PyDoc_STRVAR(M_aud_Factory_fadeout_doc,
546 "fadeout(start, length)\n\n"
547 "Fades a factory in by lowering the volume linearly in the given "
549 ":arg start: Time in seconds when the fading should start.\n"
550 ":type start: float\n"
551 ":arg length: Time in seconds how long the fading should last.\n"
552 ":type length: float\n"
553 ":return: The created :class:`Factory` object.\n"
554 ":rtype: :class:`Factory`\n\n"
555 ".. note:: After the fade this factory plays silence, so that "
556 "the length of the factory is not altered.");
559 Factory_fadeout(Factory* self, PyObject* args)
563 if(!PyArg_ParseTuple(args, "ff:fadeout", &start, &length))
566 PyTypeObject* type = ((PyObject*)self)->ob_type;
567 Factory *parent = (Factory*)type->tp_alloc(type, 0);
572 parent->child_list = (PyObject*)self;
576 parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_OUT, start, length);
578 catch(AUD_Exception& e)
581 PyErr_SetString(AUDError, e.str);
586 return (PyObject *)parent;
589 PyDoc_STRVAR(M_aud_Factory_loop_doc,
591 "Loops a factory.\n\n"
592 ":arg count: How often the factory should be looped. "
593 "Negative values mean endlessly.\n"
594 ":type count: integer\n"
595 ":return: The created :class:`Factory` object.\n"
596 ":rtype: :class:`Factory`\n\n"
597 ".. note:: This is a filter function, you might consider using "
598 ":attr:`Handle.loop_count` instead.");
601 Factory_loop(Factory* self, PyObject* args)
605 if(!PyArg_ParseTuple(args, "i:loop", &loop))
608 PyTypeObject* type = ((PyObject*)self)->ob_type;
609 Factory *parent = (Factory*)type->tp_alloc(type, 0);
614 parent->child_list = (PyObject*)self;
618 parent->factory = new AUD_LoopFactory(self->factory, loop);
620 catch(AUD_Exception& e)
623 PyErr_SetString(AUDError, e.str);
628 return (PyObject *)parent;
631 PyDoc_STRVAR(M_aud_Factory_mix_doc,
633 "Mixes two factories.\n\n"
634 ":arg factory: The factory to mix over the other.\n"
635 ":type factory: :class:`Factory`\n"
636 ":return: The created :class:`Factory` object.\n"
637 ":rtype: :class:`Factory`\n\n"
638 ".. note:: The two factories have to have the same specifications "
639 "(channels and samplerate).");
642 Factory_mix(Factory* self, PyObject* object)
644 PyTypeObject* type = ((PyObject*)self)->ob_type;
646 if(!PyObject_TypeCheck(object, type))
648 PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
652 Factory *parent = (Factory*)type->tp_alloc(type, 0);
653 Factory *child = (Factory*)object;
657 parent->child_list = Py_BuildValue("(OO)", self, object);
661 parent->factory = new AUD_SuperposeFactory(self->factory, child->factory);
663 catch(AUD_Exception& e)
666 PyErr_SetString(AUDError, e.str);
671 return (PyObject *)parent;
674 PyDoc_STRVAR(M_aud_Factory_pingpong_doc,
676 "Plays a factory forward and then backward.\n"
677 "This is like joining a factory with its reverse.\n\n"
678 ":return: The created :class:`Factory` object.\n"
679 ":rtype: :class:`Factory`");
682 Factory_pingpong(Factory* self)
684 PyTypeObject* type = ((PyObject*)self)->ob_type;
685 Factory *parent = (Factory*)type->tp_alloc(type, 0);
690 parent->child_list = (PyObject*)self;
694 parent->factory = new AUD_PingPongFactory(self->factory);
696 catch(AUD_Exception& e)
699 PyErr_SetString(AUDError, e.str);
704 return (PyObject *)parent;
707 PyDoc_STRVAR(M_aud_Factory_reverse_doc,
709 "Plays a factory reversed.\n\n"
710 ":return: The created :class:`Factory` object.\n"
711 ":rtype: :class:`Factory`\n\n"
712 ".. note:: The factory has to have a finite length and has to be "
713 "seekable. It's recommended to use this only with factories with "
714 "fast and accurate seeking, which is not true for encoded audio "
715 "files, such ones should be buffered using :meth:`buffer` before "
716 "being played reversed.\n\n"
717 ".. warning:: If seeking is not accurate in the underlying factory "
718 "you'll likely hear skips/jumps/cracks.");
721 Factory_reverse(Factory* self)
723 PyTypeObject* type = ((PyObject*)self)->ob_type;
724 Factory *parent = (Factory*)type->tp_alloc(type, 0);
729 parent->child_list = (PyObject*)self;
733 parent->factory = new AUD_ReverseFactory(self->factory);
735 catch(AUD_Exception& e)
738 PyErr_SetString(AUDError, e.str);
743 return (PyObject *)parent;
746 PyDoc_STRVAR(M_aud_Factory_buffer_doc,
748 "Buffers a factory into RAM.\n"
749 "This saves CPU usage needed for decoding and file access if the "
750 "underlying factory reads from a file on the harddisk, but it "
751 "consumes a lot of memory.\n\n"
752 ":return: The created :class:`Factory` object.\n"
753 ":rtype: :class:`Factory`\n\n"
754 ".. note:: Only known-length factories can be buffered.\n\n"
755 ".. warning:: Raw PCM data needs a lot of space, only buffer "
759 Factory_buffer(Factory* self)
761 PyTypeObject* type = ((PyObject*)self)->ob_type;
762 Factory *parent = (Factory*)type->tp_alloc(type, 0);
768 parent->factory = new AUD_StreamBufferFactory(self->factory);
770 catch(AUD_Exception& e)
773 PyErr_SetString(AUDError, e.str);
778 return (PyObject *)parent;
781 PyDoc_STRVAR(M_aud_Factory_square_doc,
782 "square(threshold = 0)\n\n"
783 "Makes a square wave out of an audio wave by setting all samples "
784 "with a amplitude >= threshold to 1, all <= -threshold to -1 and "
785 "all between to 0.\n\n"
786 ":arg threshold: Threshold value over which an amplitude counts "
788 ":type threshold: float\n"
789 ":return: The created :class:`Factory` object.\n"
790 ":rtype: :class:`Factory`");
793 Factory_square(Factory* self, PyObject* args)
797 if(!PyArg_ParseTuple(args, "|f:square", &threshold))
800 PyTypeObject* type = ((PyObject*)self)->ob_type;
801 Factory *parent = (Factory*)type->tp_alloc(type, 0);
806 parent->child_list = (PyObject*)self;
810 parent->factory = new AUD_SquareFactory(self->factory, threshold);
812 catch(AUD_Exception& e)
815 PyErr_SetString(AUDError, e.str);
820 return (PyObject *)parent;
823 PyDoc_STRVAR(M_aud_Factory_filter_doc,
824 "filter(b, a = (1))\n\n"
825 "Filters a factory with the supplied IIR filter coefficients.\n"
826 "Without the second parameter you'll get a FIR filter.\n"
827 "If the first value of the a sequence is 0 it will be set to 1 "
829 "If the first value of the a sequence is neither 0 nor 1, all "
830 "filter coefficients will be scaled by this value so that it is 1 "
831 "in the end, you don't have to scale yourself.\n\n"
832 ":arg b: The nominator filter coefficients.\n"
833 ":type b: sequence of float\n"
834 ":arg a: The denominator filter coefficients.\n"
835 ":type a: sequence of float\n"
836 ":return: The created :class:`Factory` object.\n"
837 ":rtype: :class:`Factory`");
840 Factory_filter(Factory* self, PyObject* args)
843 PyObject* py_a = NULL;
845 if(!PyArg_ParseTuple(args, "O|O:filter", &py_b, &py_a))
848 if(!PySequence_Check(py_b) || (py_a != NULL && !PySequence_Check(py_a)))
850 PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
854 if(!PySequence_Length(py_b) || (py_a != NULL && !PySequence_Length(py_a)))
856 PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
860 std::vector<float> a, b;
865 for(int i = 0; i < PySequence_Length(py_b); i++)
867 py_value = PySequence_GetItem(py_b, i);
868 result = PyArg_Parse(py_value, "f:filter", &value);
879 for(int i = 0; i < PySequence_Length(py_a); i++)
881 py_value = PySequence_GetItem(py_a, i);
882 result = PyArg_Parse(py_value, "f:filter", &value);
897 PyTypeObject* type = ((PyObject*)self)->ob_type;
898 Factory *parent = (Factory*)type->tp_alloc(type, 0);
903 parent->child_list = (PyObject*)self;
907 parent->factory = new AUD_IIRFilterFactory(self->factory, b, a);
909 catch(AUD_Exception& e)
912 PyErr_SetString(AUDError, e.str);
917 return (PyObject *)parent;
920 static PyMethodDef Factory_methods[] = {
921 {"sine", (PyCFunction)Factory_sine, METH_VARARGS | METH_CLASS,
922 M_aud_Factory_sine_doc
924 {"file", (PyCFunction)Factory_file, METH_VARARGS | METH_CLASS,
925 M_aud_Factory_file_doc
927 {"lowpass", (PyCFunction)Factory_lowpass, METH_VARARGS,
928 M_aud_Factory_lowpass_doc
930 {"delay", (PyCFunction)Factory_delay, METH_VARARGS,
931 M_aud_Factory_delay_doc
933 {"join", (PyCFunction)Factory_join, METH_O,
934 M_aud_Factory_join_doc
936 {"highpass", (PyCFunction)Factory_highpass, METH_VARARGS,
937 M_aud_Factory_highpass_doc
939 {"limit", (PyCFunction)Factory_limit, METH_VARARGS,
940 M_aud_Factory_limit_doc
942 {"pitch", (PyCFunction)Factory_pitch, METH_VARARGS,
943 M_aud_Factory_pitch_doc
945 {"volume", (PyCFunction)Factory_volume, METH_VARARGS,
946 M_aud_Factory_volume_doc
948 {"fadein", (PyCFunction)Factory_fadein, METH_VARARGS,
949 M_aud_Factory_fadein_doc
951 {"fadeout", (PyCFunction)Factory_fadeout, METH_VARARGS,
952 M_aud_Factory_fadeout_doc
954 {"loop", (PyCFunction)Factory_loop, METH_VARARGS,
955 M_aud_Factory_loop_doc
957 {"mix", (PyCFunction)Factory_mix, METH_O,
958 M_aud_Factory_mix_doc
960 {"pingpong", (PyCFunction)Factory_pingpong, METH_NOARGS,
961 M_aud_Factory_pingpong_doc
963 {"reverse", (PyCFunction)Factory_reverse, METH_NOARGS,
964 M_aud_Factory_reverse_doc
966 {"buffer", (PyCFunction)Factory_buffer, METH_NOARGS,
967 M_aud_Factory_buffer_doc
969 {"square", (PyCFunction)Factory_square, METH_VARARGS,
970 M_aud_Factory_square_doc
972 {"filter", (PyCFunction)Factory_filter, METH_VARARGS,
973 M_aud_Factory_filter_doc
975 {NULL} /* Sentinel */
978 PyDoc_STRVAR(M_aud_Factory_doc,
979 "Factory objects are immutable and represent a sound that can be "
980 "played simultaneously multiple times. They are called factories "
981 "because they create reader objects internally that are used for "
984 static PyTypeObject FactoryType = {
985 PyVarObject_HEAD_INIT(NULL, 0)
986 "aud.Factory", /* tp_name */
987 sizeof(Factory), /* tp_basicsize */
989 (destructor)Factory_dealloc, /* tp_dealloc */
995 0, /* tp_as_number */
996 0, /* tp_as_sequence */
997 0, /* tp_as_mapping */
1001 0, /* tp_getattro */
1002 0, /* tp_setattro */
1003 0, /* tp_as_buffer */
1004 Py_TPFLAGS_DEFAULT, /* tp_flags */
1005 M_aud_Factory_doc, /* tp_doc */
1006 0, /* tp_traverse */
1008 0, /* tp_richcompare */
1009 0, /* tp_weaklistoffset */
1011 0, /* tp_iternext */
1012 Factory_methods, /* tp_methods */
1017 0, /* tp_descr_get */
1018 0, /* tp_descr_set */
1019 0, /* tp_dictoffset */
1022 Factory_new, /* tp_new */
1025 // ========== Handle ==================================================
1028 Handle_dealloc(Handle* self)
1030 Py_XDECREF(self->device);
1031 Py_TYPE(self)->tp_free((PyObject*)self);
1034 PyDoc_STRVAR(M_aud_Handle_pause_doc,
1036 "Pauses playback.\n\n"
1037 ":return: Whether the action succeeded.\n"
1041 Handle_pause(Handle *self)
1043 Device* device = (Device*)self->device;
1047 return PyBool_FromLong((long)device->device->pause(self->handle));
1049 catch(AUD_Exception& e)
1051 PyErr_SetString(AUDError, e.str);
1056 PyDoc_STRVAR(M_aud_Handle_resume_doc,
1058 "Resumes playback.\n\n"
1059 ":return: Whether the action succeeded.\n"
1063 Handle_resume(Handle *self)
1065 Device* device = (Device*)self->device;
1069 return PyBool_FromLong((long)device->device->resume(self->handle));
1071 catch(AUD_Exception& e)
1073 PyErr_SetString(AUDError, e.str);
1078 PyDoc_STRVAR(M_aud_Handle_stop_doc,
1080 "Stops playback.\n\n"
1081 ":return: Whether the action succeeded.\n"
1083 ".. note:: This makes the handle invalid.");
1086 Handle_stop(Handle *self)
1088 Device* device = (Device*)self->device;
1092 return PyBool_FromLong((long)device->device->stop(self->handle));
1094 catch(AUD_Exception& e)
1096 PyErr_SetString(AUDError, e.str);
1101 static PyMethodDef Handle_methods[] = {
1102 {"pause", (PyCFunction)Handle_pause, METH_NOARGS,
1103 M_aud_Handle_pause_doc
1105 {"resume", (PyCFunction)Handle_resume, METH_NOARGS,
1106 M_aud_Handle_resume_doc
1108 {"stop", (PyCFunction)Handle_stop, METH_NOARGS,
1109 M_aud_Handle_stop_doc
1111 {NULL} /* Sentinel */
1114 PyDoc_STRVAR(M_aud_Handle_position_doc,
1115 "The playback position of the sound in seconds.");
1118 Handle_get_position(Handle *self, void* nothing)
1120 Device* device = (Device*)self->device;
1124 return Py_BuildValue("f", device->device->getPosition(self->handle));
1126 catch(AUD_Exception& e)
1128 PyErr_SetString(AUDError, e.str);
1134 Handle_set_position(Handle *self, PyObject* args, void* nothing)
1138 if(!PyArg_Parse(args, "f:position", &position))
1141 Device* device = (Device*)self->device;
1145 if(device->device->seek(self->handle, position))
1147 PyErr_SetString(AUDError, "Couldn't seek the sound!");
1149 catch(AUD_Exception& e)
1151 PyErr_SetString(AUDError, e.str);
1157 PyDoc_STRVAR(M_aud_Handle_keep_doc,
1158 "Whether the sound should be kept paused in the device when its "
1160 "This can be used to seek the sound to some position and start "
1161 "playback again.\n\n"
1162 ".. warning:: If this is set to true and you forget stopping this "
1163 "equals a memory leak as the handle exists until the device is "
1167 Handle_get_keep(Handle *self, void* nothing)
1169 Device* device = (Device*)self->device;
1173 return PyBool_FromLong((long)device->device->getKeep(self->handle));
1175 catch(AUD_Exception& e)
1177 PyErr_SetString(AUDError, e.str);
1183 Handle_set_keep(Handle *self, PyObject* args, void* nothing)
1185 if(!PyBool_Check(args))
1187 PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
1191 bool keep = args == Py_True;
1192 Device* device = (Device*)self->device;
1196 if(device->device->setKeep(self->handle, keep))
1198 PyErr_SetString(AUDError, "Couldn't set keep of the sound!");
1200 catch(AUD_Exception& e)
1202 PyErr_SetString(AUDError, e.str);
1208 PyDoc_STRVAR(M_aud_Handle_status_doc,
1209 "Whether the sound is playing, paused or stopped (=invalid).");
1212 Handle_get_status(Handle *self, void* nothing)
1214 Device* device = (Device*)self->device;
1218 return PyBool_FromLong((long)device->device->getStatus(self->handle));
1220 catch(AUD_Exception& e)
1222 PyErr_SetString(AUDError, e.str);
1227 PyDoc_STRVAR(M_aud_Handle_volume_doc,
1228 "The volume of the sound.");
1231 Handle_get_volume(Handle *self, void* nothing)
1233 Device* device = (Device*)self->device;
1237 return Py_BuildValue("f", device->device->getVolume(self->handle));
1239 catch(AUD_Exception& e)
1241 PyErr_SetString(AUDError, e.str);
1247 Handle_set_volume(Handle *self, PyObject* args, void* nothing)
1251 if(!PyArg_Parse(args, "f:volume", &volume))
1254 Device* device = (Device*)self->device;
1258 if(device->device->setVolume(self->handle, volume))
1260 PyErr_SetString(AUDError, "Couldn't set the sound volume!");
1262 catch(AUD_Exception& e)
1264 PyErr_SetString(AUDError, e.str);
1270 PyDoc_STRVAR(M_aud_Handle_pitch_doc,
1271 "The pitch of the sound.");
1274 Handle_get_pitch(Handle *self, void* nothing)
1276 Device* device = (Device*)self->device;
1280 return Py_BuildValue("f", device->device->getPitch(self->handle));
1282 catch(AUD_Exception& e)
1284 PyErr_SetString(AUDError, e.str);
1290 Handle_set_pitch(Handle *self, PyObject* args, void* nothing)
1294 if(!PyArg_Parse(args, "f:pitch", &pitch))
1297 Device* device = (Device*)self->device;
1301 if(device->device->setPitch(self->handle, pitch))
1303 PyErr_SetString(AUDError, "Couldn't set the sound pitch!");
1305 catch(AUD_Exception& e)
1307 PyErr_SetString(AUDError, e.str);
1313 PyDoc_STRVAR(M_aud_Handle_loop_count_doc,
1314 "The (remaining) loop count of the sound. A negative value indicates infinity.");
1317 Handle_get_loop_count(Handle *self, void* nothing)
1319 Device* device = (Device*)self->device;
1323 return Py_BuildValue("i", device->device->getLoopCount(self->handle));
1325 catch(AUD_Exception& e)
1327 PyErr_SetString(AUDError, e.str);
1333 Handle_set_loop_count(Handle *self, PyObject* args, void* nothing)
1337 if(!PyArg_Parse(args, "i:loop_count", &loops))
1340 Device* device = (Device*)self->device;
1344 if(device->device->setLoopCount(self->handle, loops))
1346 PyErr_SetString(AUDError, "Couldn't set the loop count!");
1348 catch(AUD_Exception& e)
1350 PyErr_SetString(AUDError, e.str);
1356 PyDoc_STRVAR(M_aud_Handle_location_doc,
1357 "The source's location in 3D space, a 3D tuple of floats.");
1360 Handle_get_location(Handle *self, void* nothing)
1362 Device* dev = (Device*)self->device;
1366 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1369 AUD_Vector3 v = device->getSourceLocation(self->handle);
1370 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
1374 PyErr_SetString(AUDError, device_not_3d_error);
1377 catch(AUD_Exception& e)
1379 PyErr_SetString(AUDError, e.str);
1386 Handle_set_location(Handle *self, PyObject* args, void* nothing)
1390 if(!PyArg_Parse(args, "(fff):location", &x, &y, &z))
1393 Device* dev = (Device*)self->device;
1397 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1400 AUD_Vector3 location(x, y, z);
1401 if(device->setSourceLocation(self->handle, location))
1403 PyErr_SetString(AUDError, "Location couldn't be set!");
1406 PyErr_SetString(AUDError, device_not_3d_error);
1408 catch(AUD_Exception& e)
1410 PyErr_SetString(AUDError, e.str);
1416 PyDoc_STRVAR(M_aud_Handle_velocity_doc,
1417 "The source's velocity in 3D space, a 3D tuple of floats.");
1420 Handle_get_velocity(Handle *self, void* nothing)
1422 Device* dev = (Device*)self->device;
1426 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1429 AUD_Vector3 v = device->getSourceVelocity(self->handle);
1430 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
1434 PyErr_SetString(AUDError, device_not_3d_error);
1437 catch(AUD_Exception& e)
1439 PyErr_SetString(AUDError, e.str);
1446 Handle_set_velocity(Handle *self, PyObject* args, void* nothing)
1450 if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z))
1453 Device* dev = (Device*)self->device;
1457 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1460 AUD_Vector3 velocity(x, y, z);
1461 if(device->setSourceVelocity(self->handle, velocity))
1463 PyErr_SetString(AUDError, "Couldn't set the velocity!");
1466 PyErr_SetString(AUDError, device_not_3d_error);
1468 catch(AUD_Exception& e)
1470 PyErr_SetString(AUDError, e.str);
1476 PyDoc_STRVAR(M_aud_Handle_orientation_doc,
1477 "The source's orientation in 3D space as quaternion, a 4 float tuple.");
1480 Handle_get_orientation(Handle *self, void* nothing)
1482 Device* dev = (Device*)self->device;
1486 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1489 AUD_Quaternion o = device->getSourceOrientation(self->handle);
1490 return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
1494 PyErr_SetString(AUDError, device_not_3d_error);
1497 catch(AUD_Exception& e)
1499 PyErr_SetString(AUDError, e.str);
1506 Handle_set_orientation(Handle *self, PyObject* args, void* nothing)
1510 if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z))
1513 Device* dev = (Device*)self->device;
1517 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1520 AUD_Quaternion orientation(w, x, y, z);
1521 if(device->setSourceOrientation(self->handle, orientation))
1523 PyErr_SetString(AUDError, "Couldn't set the orientation!");
1526 PyErr_SetString(AUDError, device_not_3d_error);
1528 catch(AUD_Exception& e)
1530 PyErr_SetString(AUDError, e.str);
1536 PyDoc_STRVAR(M_aud_Handle_relative_doc,
1537 "Whether the source's location, velocity and orientation is relative or absolute to the listener.");
1540 Handle_get_relative(Handle *self, void* nothing)
1542 Device* dev = (Device*)self->device;
1546 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1549 return PyBool_FromLong((long)device->isRelative(self->handle));
1553 PyErr_SetString(AUDError, device_not_3d_error);
1556 catch(AUD_Exception& e)
1558 PyErr_SetString(AUDError, e.str);
1565 Handle_set_relative(Handle *self, PyObject* args, void* nothing)
1567 if(!PyBool_Check(args))
1569 PyErr_SetString(PyExc_TypeError, "Value is not a boolean!");
1573 bool relative = (args == Py_True);
1574 Device* dev = (Device*)self->device;
1578 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1581 if(device->setRelative(self->handle, relative))
1583 PyErr_SetString(AUDError, "Couldn't set the relativeness!");
1586 PyErr_SetString(AUDError, device_not_3d_error);
1588 catch(AUD_Exception& e)
1590 PyErr_SetString(AUDError, e.str);
1596 PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc,
1597 "The minimum volume of the source.\n\n"
1598 ".. seealso:: :attr:`Device.distance_model`");
1601 Handle_get_volume_minimum(Handle *self, void* nothing)
1603 Device* dev = (Device*)self->device;
1607 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1610 return Py_BuildValue("f", device->getVolumeMinimum(self->handle));
1614 PyErr_SetString(AUDError, device_not_3d_error);
1618 catch(AUD_Exception& e)
1620 PyErr_SetString(AUDError, e.str);
1626 Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing)
1630 if(!PyArg_Parse(args, "f:volume_minimum", &volume))
1633 Device* dev = (Device*)self->device;
1637 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1640 if(device->setVolumeMinimum(self->handle, volume))
1642 PyErr_SetString(AUDError, "Couldn't set the minimum volume!");
1645 PyErr_SetString(AUDError, device_not_3d_error);
1647 catch(AUD_Exception& e)
1649 PyErr_SetString(AUDError, e.str);
1655 PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc,
1656 "The maximum volume of the source.\n\n"
1657 ".. seealso:: :attr:`Device.distance_model`");
1660 Handle_get_volume_maximum(Handle *self, void* nothing)
1662 Device* dev = (Device*)self->device;
1666 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1669 return Py_BuildValue("f", device->getVolumeMaximum(self->handle));
1673 PyErr_SetString(AUDError, device_not_3d_error);
1677 catch(AUD_Exception& e)
1679 PyErr_SetString(AUDError, e.str);
1685 Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing)
1689 if(!PyArg_Parse(args, "f:volume_maximum", &volume))
1692 Device* dev = (Device*)self->device;
1696 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1699 if(device->setVolumeMaximum(self->handle, volume))
1701 PyErr_SetString(AUDError, "Couldn't set the maximum volume!");
1704 PyErr_SetString(AUDError, device_not_3d_error);
1706 catch(AUD_Exception& e)
1708 PyErr_SetString(AUDError, e.str);
1714 PyDoc_STRVAR(M_aud_Handle_distance_reference_doc,
1715 "The reference distance of the source.\n"
1716 "At this distance the volume will be exactly :attr:`volume`.\n\n"
1717 ".. seealso:: :attr:`Device.distance_model`");
1720 Handle_get_distance_reference(Handle *self, void* nothing)
1722 Device* dev = (Device*)self->device;
1726 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1729 return Py_BuildValue("f", device->getDistanceReference(self->handle));
1733 PyErr_SetString(AUDError, device_not_3d_error);
1737 catch(AUD_Exception& e)
1739 PyErr_SetString(AUDError, e.str);
1745 Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing)
1749 if(!PyArg_Parse(args, "f:distance_reference", &distance))
1752 Device* dev = (Device*)self->device;
1756 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1759 if(device->setDistanceReference(self->handle, distance))
1761 PyErr_SetString(AUDError, "Couldn't set the reference distance!");
1764 PyErr_SetString(AUDError, device_not_3d_error);
1766 catch(AUD_Exception& e)
1768 PyErr_SetString(AUDError, e.str);
1774 PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc,
1775 "The maximum distance of the source.\n"
1776 "If the listener is further away the source volume will be 0.\n\n"
1777 ".. seealso:: :attr:`Device.distance_model`");
1780 Handle_get_distance_maximum(Handle *self, void* nothing)
1782 Device* dev = (Device*)self->device;
1786 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1789 return Py_BuildValue("f", device->getDistanceMaximum(self->handle));
1793 PyErr_SetString(AUDError, device_not_3d_error);
1797 catch(AUD_Exception& e)
1799 PyErr_SetString(AUDError, e.str);
1805 Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing)
1809 if(!PyArg_Parse(args, "f:distance_maximum", &distance))
1812 Device* dev = (Device*)self->device;
1816 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1819 if(device->setDistanceMaximum(self->handle, distance))
1821 PyErr_SetString(AUDError, "Couldn't set the maximum distance!");
1824 PyErr_SetString(AUDError, device_not_3d_error);
1826 catch(AUD_Exception& e)
1828 PyErr_SetString(AUDError, e.str);
1834 PyDoc_STRVAR(M_aud_Handle_attenuation_doc,
1835 "This factor is used for distance based attenuation of the "
1837 ".. seealso:: :attr:`Device.distance_model`");
1840 Handle_get_attenuation(Handle *self, void* nothing)
1842 Device* dev = (Device*)self->device;
1846 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1849 return Py_BuildValue("f", device->getAttenuation(self->handle));
1853 PyErr_SetString(AUDError, device_not_3d_error);
1857 catch(AUD_Exception& e)
1859 PyErr_SetString(AUDError, e.str);
1865 Handle_set_attenuation(Handle *self, PyObject* args, void* nothing)
1869 if(!PyArg_Parse(args, "f:attenuation", &factor))
1872 Device* dev = (Device*)self->device;
1876 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1879 if(device->setAttenuation(self->handle, factor))
1881 PyErr_SetString(AUDError, "Couldn't set the attenuation!");
1884 PyErr_SetString(AUDError, device_not_3d_error);
1886 catch(AUD_Exception& e)
1888 PyErr_SetString(AUDError, e.str);
1894 PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc,
1895 "The opening angle of the inner cone of the source. If the cone "
1896 "values of a source are set there are two (audible) cones with "
1897 "the apex at the :attr:`location` of the source and with infinite "
1898 "height, heading in the direction of the source's "
1899 ":attr:`orientation`.\n"
1900 "In the inner cone the volume is normal. Outside the outer cone "
1901 "the volume will be :attr:`cone_volume_outer` and in the area "
1902 "between the volume will be interpolated linearly.");
1905 Handle_get_cone_angle_inner(Handle *self, void* nothing)
1907 Device* dev = (Device*)self->device;
1911 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1914 return Py_BuildValue("f", device->getConeAngleInner(self->handle));
1918 PyErr_SetString(AUDError, device_not_3d_error);
1922 catch(AUD_Exception& e)
1924 PyErr_SetString(AUDError, e.str);
1930 Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing)
1934 if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
1937 Device* dev = (Device*)self->device;
1941 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1944 if(device->setConeAngleInner(self->handle, angle))
1946 PyErr_SetString(AUDError, "Couldn't set the cone inner angle!");
1949 PyErr_SetString(AUDError, device_not_3d_error);
1951 catch(AUD_Exception& e)
1953 PyErr_SetString(AUDError, e.str);
1959 PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc,
1960 "The opening angle of the outer cone of the source.\n\n"
1961 ".. seealso:: :attr:`cone_angle_inner`");
1964 Handle_get_cone_angle_outer(Handle *self, void* nothing)
1966 Device* dev = (Device*)self->device;
1970 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1973 return Py_BuildValue("f", device->getConeAngleOuter(self->handle));
1977 PyErr_SetString(AUDError, device_not_3d_error);
1981 catch(AUD_Exception& e)
1983 PyErr_SetString(AUDError, e.str);
1989 Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing)
1993 if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
1996 Device* dev = (Device*)self->device;
2000 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2003 if(device->setConeAngleOuter(self->handle, angle))
2005 PyErr_SetString(AUDError, "Couldn't set the cone outer angle!");
2008 PyErr_SetString(AUDError, device_not_3d_error);
2010 catch(AUD_Exception& e)
2012 PyErr_SetString(AUDError, e.str);
2018 PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc,
2019 "The volume outside the outer cone of the source.\n\n"
2020 ".. seealso:: :attr:`cone_angle_inner`");
2023 Handle_get_cone_volume_outer(Handle *self, void* nothing)
2025 Device* dev = (Device*)self->device;
2029 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2032 return Py_BuildValue("f", device->getConeVolumeOuter(self->handle));
2036 PyErr_SetString(AUDError, device_not_3d_error);
2040 catch(AUD_Exception& e)
2042 PyErr_SetString(AUDError, e.str);
2048 Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing)
2052 if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
2055 Device* dev = (Device*)self->device;
2059 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2062 if(device->setConeVolumeOuter(self->handle, volume))
2064 PyErr_SetString(AUDError, "Couldn't set the cone outer volume!");
2067 PyErr_SetString(AUDError, device_not_3d_error);
2069 catch(AUD_Exception& e)
2071 PyErr_SetString(AUDError, e.str);
2077 static PyGetSetDef Handle_properties[] = {
2078 {(char*)"position", (getter)Handle_get_position, (setter)Handle_set_position,
2079 M_aud_Handle_position_doc, NULL },
2080 {(char*)"keep", (getter)Handle_get_keep, (setter)Handle_set_keep,
2081 M_aud_Handle_keep_doc, NULL },
2082 {(char*)"status", (getter)Handle_get_status, NULL,
2083 M_aud_Handle_status_doc, NULL },
2084 {(char*)"volume", (getter)Handle_get_volume, (setter)Handle_set_volume,
2085 M_aud_Handle_volume_doc, NULL },
2086 {(char*)"pitch", (getter)Handle_get_pitch, (setter)Handle_set_pitch,
2087 M_aud_Handle_pitch_doc, NULL },
2088 {(char*)"loop_count", (getter)Handle_get_loop_count, (setter)Handle_set_loop_count,
2089 M_aud_Handle_loop_count_doc, NULL },
2090 {(char*)"location", (getter)Handle_get_location, (setter)Handle_set_location,
2091 M_aud_Handle_location_doc, NULL },
2092 {(char*)"velocity", (getter)Handle_get_velocity, (setter)Handle_set_velocity,
2093 M_aud_Handle_velocity_doc, NULL },
2094 {(char*)"orientation", (getter)Handle_get_orientation, (setter)Handle_set_orientation,
2095 M_aud_Handle_orientation_doc, NULL },
2096 {(char*)"relative", (getter)Handle_get_relative, (setter)Handle_set_relative,
2097 M_aud_Handle_relative_doc, NULL },
2098 {(char*)"volume_minimum", (getter)Handle_get_volume_minimum, (setter)Handle_set_volume_minimum,
2099 M_aud_Handle_volume_minimum_doc, NULL },
2100 {(char*)"volume_maximum", (getter)Handle_get_volume_maximum, (setter)Handle_set_volume_maximum,
2101 M_aud_Handle_volume_maximum_doc, NULL },
2102 {(char*)"distance_reference", (getter)Handle_get_distance_reference, (setter)Handle_set_distance_reference,
2103 M_aud_Handle_distance_reference_doc, NULL },
2104 {(char*)"distance_maximum", (getter)Handle_get_distance_maximum, (setter)Handle_set_distance_maximum,
2105 M_aud_Handle_distance_maximum_doc, NULL },
2106 {(char*)"attenuation", (getter)Handle_get_attenuation, (setter)Handle_set_attenuation,
2107 M_aud_Handle_attenuation_doc, NULL },
2108 {(char*)"cone_angle_inner", (getter)Handle_get_cone_angle_inner, (setter)Handle_set_cone_angle_inner,
2109 M_aud_Handle_cone_angle_inner_doc, NULL },
2110 {(char*)"cone_angle_outer", (getter)Handle_get_cone_angle_outer, (setter)Handle_set_cone_angle_outer,
2111 M_aud_Handle_cone_angle_outer_doc, NULL },
2112 {(char*)"cone_volume_outer", (getter)Handle_get_cone_volume_outer, (setter)Handle_set_cone_volume_outer,
2113 M_aud_Handle_cone_volume_outer_doc, NULL },
2114 {NULL} /* Sentinel */
2117 PyDoc_STRVAR(M_aud_Handle_doc,
2118 "Handle objects are playback handles that can be used to control "
2119 "playback of a sound. If a sound is played back multiple times "
2120 "then there are as many handles.");
2122 static PyTypeObject HandleType = {
2123 PyVarObject_HEAD_INIT(NULL, 0)
2124 "aud.Handle", /* tp_name */
2125 sizeof(Handle), /* tp_basicsize */
2126 0, /* tp_itemsize */
2127 (destructor)Handle_dealloc,/* tp_dealloc */
2131 0, /* tp_reserved */
2133 0, /* tp_as_number */
2134 0, /* tp_as_sequence */
2135 0, /* tp_as_mapping */
2139 0, /* tp_getattro */
2140 0, /* tp_setattro */
2141 0, /* tp_as_buffer */
2142 Py_TPFLAGS_DEFAULT, /* tp_flags */
2143 M_aud_Handle_doc, /* tp_doc */
2144 0, /* tp_traverse */
2146 0, /* tp_richcompare */
2147 0, /* tp_weaklistoffset */
2149 0, /* tp_iternext */
2150 Handle_methods, /* tp_methods */
2152 Handle_properties, /* tp_getset */
2155 0, /* tp_descr_get */
2156 0, /* tp_descr_set */
2157 0, /* tp_dictoffset */
2163 // ========== Device ==================================================
2166 Device_dealloc(Device* self)
2169 delete self->device;
2170 Py_TYPE(self)->tp_free((PyObject*)self);
2174 Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2178 static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL};
2180 int rate = AUD_RATE_44100;
2181 int channels = AUD_CHANNELS_STEREO;
2182 int format = AUD_FORMAT_FLOAT32;
2183 int buffersize = AUD_DEFAULT_BUFFER_SIZE;
2184 const char* name = "Audaspace";
2186 if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiis:Device", const_cast<char**>(kwlist),
2187 &device, &rate, &channels, &format, &buffersize, &name))
2190 if(buffersize < 128)
2192 PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than 127!");
2196 self = (Device*)type->tp_alloc(type, 0);
2199 AUD_DeviceSpecs specs;
2200 specs.channels = (AUD_Channels)channels;
2201 specs.format = (AUD_SampleFormat)format;
2202 specs.rate = (AUD_SampleRate)rate;
2204 self->device = NULL;
2210 case AUD_DEVICE_NULL:
2211 self->device = new AUD_NULLDevice();
2213 case AUD_DEVICE_OPENAL:
2215 self->device = new AUD_OpenALDevice(specs, buffersize);
2218 case AUD_DEVICE_SDL:
2220 self->device = new AUD_SDLDevice(specs, buffersize);
2223 case AUD_DEVICE_JACK:
2225 self->device = new AUD_JackDevice(name, specs, buffersize);
2228 case AUD_DEVICE_READ:
2233 catch(AUD_Exception& e)
2236 PyErr_SetString(AUDError, e.str);
2243 PyErr_SetString(AUDError, "Unsupported device type!");
2248 return (PyObject *)self;
2251 PyDoc_STRVAR(M_aud_Device_play_doc,
2252 "play(factory, keep=False)\n\n"
2253 "Plays a factory.\n\n"
2254 ":arg factory: The factory to play.\n"
2255 ":type factory: :class:`Factory`\n"
2256 ":arg keep: See :attr:`Handle.keep`.\n"
2257 ":type keep: bool\n"
2258 ":return: The playback handle with which playback can be "
2259 "controlled with.\n"
2260 ":rtype: :class:`Handle`");
2263 Device_play(Device *self, PyObject *args, PyObject *kwds)
2266 PyObject* keepo = NULL;
2270 static const char *kwlist[] = {"factory", "keep", NULL};
2272 if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:play", const_cast<char**>(kwlist), &object, &keepo))
2275 if(!PyObject_TypeCheck(object, &FactoryType))
2277 PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
2283 if(!PyBool_Check(keepo))
2285 PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
2289 keep = keepo == Py_True;
2292 Factory* sound = (Factory*)object;
2295 handle = (Handle*)HandleType.tp_alloc(&HandleType, 0);
2298 handle->device = (PyObject*)self;
2303 handle->handle = self->device->play(sound->factory, keep);
2305 catch(AUD_Exception& e)
2308 PyErr_SetString(AUDError, e.str);
2313 return (PyObject *)handle;
2316 PyDoc_STRVAR(M_aud_Device_lock_doc,
2318 "Locks the device so that it's guaranteed, that no samples are "
2319 "read from the streams until :meth:`unlock` is called.\n"
2320 "This is useful if you want to do start/stop/pause/resume some "
2321 "sounds at the same time.\n\n"
2322 ".. note:: The device has to be unlocked as often as locked to be "
2323 "able to continue playback.\n\n"
2324 ".. warning:: Make sure the time between locking and unlocking is "
2325 "as short as possible to avoid clicks.");
2328 Device_lock(Device *self)
2332 self->device->lock();
2335 catch(AUD_Exception& e)
2337 PyErr_SetString(AUDError, e.str);
2342 PyDoc_STRVAR(M_aud_Device_unlock_doc,
2344 "Unlocks the device after a lock call, see :meth:`lock` for "
2348 Device_unlock(Device *self)
2352 self->device->unlock();
2355 catch(AUD_Exception& e)
2357 PyErr_SetString(AUDError, e.str);
2362 static PyMethodDef Device_methods[] = {
2363 {"play", (PyCFunction)Device_play, METH_VARARGS | METH_KEYWORDS,
2364 M_aud_Device_play_doc
2366 {"lock", (PyCFunction)Device_lock, METH_NOARGS,
2367 M_aud_Device_lock_doc
2369 {"unlock", (PyCFunction)Device_unlock, METH_NOARGS,
2370 M_aud_Device_unlock_doc
2372 {NULL} /* Sentinel */
2375 PyDoc_STRVAR(M_aud_Device_rate_doc,
2376 "The sampling rate of the device in Hz.");
2379 Device_get_rate(Device *self, void* nothing)
2383 AUD_DeviceSpecs specs = self->device->getSpecs();
2384 return Py_BuildValue("i", specs.rate);
2386 catch(AUD_Exception& e)
2388 PyErr_SetString(AUDError, e.str);
2393 PyDoc_STRVAR(M_aud_Device_format_doc,
2394 "The native sample format of the device.");
2397 Device_get_format(Device *self, void* nothing)
2401 AUD_DeviceSpecs specs = self->device->getSpecs();
2402 return Py_BuildValue("i", specs.format);
2404 catch(AUD_Exception& e)
2406 PyErr_SetString(AUDError, e.str);
2411 PyDoc_STRVAR(M_aud_Device_channels_doc,
2412 "The channel count of the device.");
2415 Device_get_channels(Device *self, void* nothing)
2419 AUD_DeviceSpecs specs = self->device->getSpecs();
2420 return Py_BuildValue("i", specs.channels);
2422 catch(AUD_Exception& e)
2424 PyErr_SetString(AUDError, e.str);
2429 PyDoc_STRVAR(M_aud_Device_volume_doc,
2430 "The overall volume of the device.");
2433 Device_get_volume(Device *self, void* nothing)
2437 return Py_BuildValue("f", self->device->getVolume());
2439 catch(AUD_Exception& e)
2441 PyErr_SetString(AUDError, e.str);
2447 Device_set_volume(Device *self, PyObject* args, void* nothing)
2451 if(!PyArg_Parse(args, "f:volume", &volume))
2456 self->device->setVolume(volume);
2459 catch(AUD_Exception& e)
2461 PyErr_SetString(AUDError, e.str);
2466 PyDoc_STRVAR(M_aud_Device_listener_location_doc,
2467 "The listeners's location in 3D space, a 3D tuple of floats.");
2470 Device_get_listener_location(Device *self, void* nothing)
2474 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2477 AUD_Vector3 v = device->getListenerLocation();
2478 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
2482 PyErr_SetString(AUDError, device_not_3d_error);
2485 catch(AUD_Exception& e)
2487 PyErr_SetString(AUDError, e.str);
2494 Device_set_listener_location(Device *self, PyObject* args, void* nothing)
2498 if(!PyArg_Parse(args, "(fff):listener_location", &x, &y, &z))
2503 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2506 AUD_Vector3 location(x, y, z);
2507 device->setListenerLocation(location);
2511 PyErr_SetString(AUDError, device_not_3d_error);
2513 catch(AUD_Exception& e)
2515 PyErr_SetString(AUDError, e.str);
2521 PyDoc_STRVAR(M_aud_Device_listener_velocity_doc,
2522 "The listener's velocity in 3D space, a 3D tuple of floats.");
2525 Device_get_listener_velocity(Device *self, void* nothing)
2529 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2532 AUD_Vector3 v = device->getListenerVelocity();
2533 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
2537 PyErr_SetString(AUDError, device_not_3d_error);
2540 catch(AUD_Exception& e)
2542 PyErr_SetString(AUDError, e.str);
2549 Device_set_listener_velocity(Device *self, PyObject* args, void* nothing)
2553 if(!PyArg_Parse(args, "(fff):listener_velocity", &x, &y, &z))
2558 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2561 AUD_Vector3 velocity(x, y, z);
2562 device->setListenerVelocity(velocity);
2566 PyErr_SetString(AUDError, device_not_3d_error);
2568 catch(AUD_Exception& e)
2570 PyErr_SetString(AUDError, e.str);
2576 PyDoc_STRVAR(M_aud_Device_listener_orientation_doc,
2577 "The listener's orientation in 3D space as quaternion, a 4 float tuple.");
2580 Device_get_listener_orientation(Device *self, void* nothing)
2584 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2587 AUD_Quaternion o = device->getListenerOrientation();
2588 return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
2592 PyErr_SetString(AUDError, device_not_3d_error);
2595 catch(AUD_Exception& e)
2597 PyErr_SetString(AUDError, e.str);
2604 Device_set_listener_orientation(Device *self, PyObject* args, void* nothing)
2608 if(!PyArg_Parse(args, "(ffff):listener_orientation", &w, &x, &y, &z))
2613 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2616 AUD_Quaternion orientation(w, x, y, z);
2617 device->setListenerOrientation(orientation);
2621 PyErr_SetString(AUDError, device_not_3d_error);
2623 catch(AUD_Exception& e)
2625 PyErr_SetString(AUDError, e.str);
2631 PyDoc_STRVAR(M_aud_Device_speed_of_sound_doc,
2632 "The speed of sound of the device.\n"
2633 "The speed of sound in air is typically 343 m/s.");
2636 Device_get_speed_of_sound(Device *self, void* nothing)
2640 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2643 return Py_BuildValue("f", device->getSpeedOfSound());
2647 PyErr_SetString(AUDError, device_not_3d_error);
2651 catch(AUD_Exception& e)
2653 PyErr_SetString(AUDError, e.str);
2659 Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing)
2663 if(!PyArg_Parse(args, "f:speed_of_sound", &speed))
2668 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2671 device->setSpeedOfSound(speed);
2675 PyErr_SetString(AUDError, device_not_3d_error);
2677 catch(AUD_Exception& e)
2679 PyErr_SetString(AUDError, e.str);
2685 PyDoc_STRVAR(M_aud_Device_doppler_factor_doc,
2686 "The doppler factor of the device.\n"
2687 "This factor is a scaling factor for the velocity vectors in "
2688 "doppler calculation. So a value bigger than 1 will exaggerate "
2689 "the effect as it raises the velocity.");
2692 Device_get_doppler_factor(Device *self, void* nothing)
2696 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2699 return Py_BuildValue("f", device->getDopplerFactor());
2703 PyErr_SetString(AUDError, device_not_3d_error);
2707 catch(AUD_Exception& e)
2709 PyErr_SetString(AUDError, e.str);
2715 Device_set_doppler_factor(Device *self, PyObject* args, void* nothing)
2719 if(!PyArg_Parse(args, "f:doppler_factor", &factor))
2724 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2727 device->setDopplerFactor(factor);
2731 PyErr_SetString(AUDError, device_not_3d_error);
2733 catch(AUD_Exception& e)
2735 PyErr_SetString(AUDError, e.str);
2741 PyDoc_STRVAR(M_aud_Device_distance_model_doc,
2742 "The distance model of the device.\n\n"
2743 ".. seealso:: http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835864");
2746 Device_get_distance_model(Device *self, void* nothing)
2750 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2753 return Py_BuildValue("i", int(device->getDistanceModel()));
2757 PyErr_SetString(AUDError, device_not_3d_error);
2761 catch(AUD_Exception& e)
2763 PyErr_SetString(AUDError, e.str);
2769 Device_set_distance_model(Device *self, PyObject* args, void* nothing)
2773 if(!PyArg_Parse(args, "i:distance_model", &model))
2778 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2781 device->setDistanceModel(AUD_DistanceModel(model));
2785 PyErr_SetString(AUDError, device_not_3d_error);
2787 catch(AUD_Exception& e)
2789 PyErr_SetString(AUDError, e.str);
2795 static PyGetSetDef Device_properties[] = {
2796 {(char*)"rate", (getter)Device_get_rate, NULL,
2797 M_aud_Device_rate_doc, NULL },
2798 {(char*)"format", (getter)Device_get_format, NULL,
2799 M_aud_Device_format_doc, NULL },
2800 {(char*)"channels", (getter)Device_get_channels, NULL,
2801 M_aud_Device_channels_doc, NULL },
2802 {(char*)"volume", (getter)Device_get_volume, (setter)Device_set_volume,
2803 M_aud_Device_volume_doc, NULL },
2804 {(char*)"listener_location", (getter)Device_get_listener_location, (setter)Device_set_listener_location,
2805 M_aud_Device_listener_location_doc, NULL },
2806 {(char*)"listener_velocity", (getter)Device_get_listener_velocity, (setter)Device_set_listener_velocity,
2807 M_aud_Device_listener_velocity_doc, NULL },
2808 {(char*)"listener_orientation", (getter)Device_get_listener_orientation, (setter)Device_set_listener_orientation,
2809 M_aud_Device_listener_orientation_doc, NULL },
2810 {(char*)"speed_of_sound", (getter)Device_get_speed_of_sound, (setter)Device_set_speed_of_sound,
2811 M_aud_Device_speed_of_sound_doc, NULL },
2812 {(char*)"doppler_factor", (getter)Device_get_doppler_factor, (setter)Device_set_doppler_factor,
2813 M_aud_Device_doppler_factor_doc, NULL },
2814 {(char*)"distance_model", (getter)Device_get_distance_model, (setter)Device_set_distance_model,
2815 M_aud_Device_distance_model_doc, NULL },
2816 {NULL} /* Sentinel */
2819 PyDoc_STRVAR(M_aud_Device_doc,
2820 "Device objects represent an audio output backend like OpenAL or "
2821 "SDL, but might also represent a file output or RAM buffer "
2824 static PyTypeObject DeviceType = {
2825 PyVarObject_HEAD_INIT(NULL, 0)
2826 "aud.Device", /* tp_name */
2827 sizeof(Device), /* tp_basicsize */
2828 0, /* tp_itemsize */
2829 (destructor)Device_dealloc,/* tp_dealloc */
2833 0, /* tp_reserved */
2835 0, /* tp_as_number */
2836 0, /* tp_as_sequence */
2837 0, /* tp_as_mapping */
2841 0, /* tp_getattro */
2842 0, /* tp_setattro */
2843 0, /* tp_as_buffer */
2844 Py_TPFLAGS_DEFAULT, /* tp_flags */
2845 M_aud_Device_doc, /* tp_doc */
2846 0, /* tp_traverse */
2848 0, /* tp_richcompare */
2849 0, /* tp_weaklistoffset */
2851 0, /* tp_iternext */
2852 Device_methods, /* tp_methods */
2854 Device_properties, /* tp_getset */
2857 0, /* tp_descr_get */
2858 0, /* tp_descr_set */
2859 0, /* tp_dictoffset */
2862 Device_new, /* tp_new */
2868 return DeviceType.tp_alloc(&DeviceType, 0);
2871 // ====================================================================
2873 PyDoc_STRVAR(M_aud_doc,
2874 "This module provides access to the audaspace audio library.");
2876 static struct PyModuleDef audmodule = {
2877 PyModuleDef_HEAD_INIT,
2878 "aud", /* name of module */
2879 M_aud_doc, /* module documentation */
2880 -1, /* size of per-interpreter state of the module,
2881 or -1 if the module keeps state in global variables. */
2882 NULL, NULL, NULL, NULL, NULL
2890 if(PyType_Ready(&FactoryType) < 0)
2893 if(PyType_Ready(&DeviceType) < 0)
2896 if(PyType_Ready(&HandleType) < 0)
2899 m = PyModule_Create(&audmodule);
2903 Py_INCREF(&FactoryType);
2904 PyModule_AddObject(m, "Factory", (PyObject*)&FactoryType);
2906 Py_INCREF(&DeviceType);
2907 PyModule_AddObject(m, "Device", (PyObject*)&DeviceType);
2909 Py_INCREF(&HandleType);
2910 PyModule_AddObject(m, "Handle", (PyObject*)&HandleType);
2912 AUDError = PyErr_NewException("aud.error", NULL, NULL);
2913 Py_INCREF(AUDError);
2914 PyModule_AddObject(m, "error", AUDError);
2917 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_NULL);
2918 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_OPENAL);
2919 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_SDL);
2920 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_JACK);
2921 //PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_READ);
2923 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT32);
2924 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT64);
2925 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_INVALID);
2926 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S16);
2927 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S24);
2928 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S32);
2929 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_U8);
2931 PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_INVALID);
2932 PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PAUSED);
2933 PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PLAYING);
2934 // distance model constants
2935 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT);
2936 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT_CLAMPED);
2937 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE);
2938 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE_CLAMPED);
2939 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR);
2940 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR_CLAMPED);
2941 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVALID);