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"
64 // ====================================================================
75 // ====================================================================
77 #define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name)
79 // ====================================================================
81 static PyObject* AUDError;
83 static const char* device_not_3d_error = "Device is not a 3D device!";
85 // ====================================================================
88 Factory_dealloc(Factory* self)
92 Py_XDECREF(self->child_list);
93 Py_TYPE(self)->tp_free((PyObject*)self);
97 Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
101 self = (Factory*)type->tp_alloc(type, 0);
104 static const char *kwlist[] = {"filename", NULL};
105 const char* filename = NULL;
107 if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Factory", const_cast<char**>(kwlist), &filename))
115 self->factory = new AUD_FileFactory(filename);
117 catch(AUD_Exception& e)
120 PyErr_SetString(AUDError, e.str);
125 return (PyObject *)self;
128 PyDoc_STRVAR(M_aud_Factory_sine_doc,
129 "sine(frequency, rate=44100)\n\n"
130 "Creates a sine factory which plays a sine wave.\n\n"
131 ":arg frequency: The frequency of the sine wave in Hz.\n"
132 ":type frequency: float\n"
133 ":arg rate: The sampling rate in Hz. It's recommended to set this "
134 "value to the playback device's samling rate to avoid resamping.\n"
136 ":return: The created :class:`Factory` object.\n"
137 ":rtype: :class:`Factory`");
140 Factory_sine(PyTypeObject* type, PyObject* args)
145 if(!PyArg_ParseTuple(args, "f|i:sine", &frequency, &rate))
150 self = (Factory*)type->tp_alloc(type, 0);
155 self->factory = new AUD_SinusFactory(frequency, (AUD_SampleRate)rate);
157 catch(AUD_Exception& e)
160 PyErr_SetString(AUDError, e.str);
165 return (PyObject *)self;
168 PyDoc_STRVAR(M_aud_Factory_file_doc,
170 "Creates a factory object of a sound file.\n\n"
171 ":arg filename: Path of the file.\n"
172 ":type filename: string\n"
173 ":return: The created :class:`Factory` object.\n"
174 ":rtype: :class:`Factory`\n\n"
175 ".. warning:: If the file doesn't exist or can't be read you will "
176 "not get an exception immediately, but when you try to start "
177 "playback of that factory.");
180 Factory_file(PyTypeObject* type, PyObject* args)
182 const char* filename = NULL;
184 if(!PyArg_ParseTuple(args, "s:file", &filename))
189 self = (Factory*)type->tp_alloc(type, 0);
194 self->factory = new AUD_FileFactory(filename);
196 catch(AUD_Exception& e)
199 PyErr_SetString(AUDError, e.str);
204 return (PyObject *)self;
207 PyDoc_STRVAR(M_aud_Factory_lowpass_doc,
208 "lowpass(frequency, Q=0.5)\n\n"
209 "Creates a second order lowpass filter based on the transfer "
210 "function H(s) = 1 / (s^2 + s/Q + 1)\n\n"
211 ":arg frequency: The cut off trequency of the lowpass.\n"
212 ":type frequency: float\n"
213 ":arg Q: Q factor of the lowpass.\n"
215 ":return: The created :class:`Factory` object.\n"
216 ":rtype: :class:`Factory`");
219 Factory_lowpass(Factory* self, PyObject* args)
224 if(!PyArg_ParseTuple(args, "f|f:lowpass", &frequency, &Q))
227 PyTypeObject* type = ((PyObject*)self)->ob_type;
228 Factory *parent = (Factory*)type->tp_alloc(type, 0);
233 parent->child_list = (PyObject*)self;
237 parent->factory = new AUD_LowpassFactory(self->factory, frequency, Q);
239 catch(AUD_Exception& e)
242 PyErr_SetString(AUDError, e.str);
247 return (PyObject *)parent;
250 PyDoc_STRVAR(M_aud_Factory_delay_doc,
252 "Delays by playing adding silence in front of the other factory's "
254 ":arg time: How many seconds of silence should be added before "
256 ":type time: float\n"
257 ":return: The created :class:`Factory` object.\n"
258 ":rtype: :class:`Factory`");
261 Factory_delay(Factory* self, PyObject* args)
265 if(!PyArg_ParseTuple(args, "f:delay", &delay))
268 PyTypeObject* type = ((PyObject*)self)->ob_type;
269 Factory *parent = (Factory*)type->tp_alloc(type, 0);
274 parent->child_list = (PyObject*)self;
278 parent->factory = new AUD_DelayFactory(self->factory, delay);
280 catch(AUD_Exception& e)
283 PyErr_SetString(AUDError, e.str);
288 return (PyObject *)parent;
291 PyDoc_STRVAR(M_aud_Factory_join_doc,
293 "Plays two factories in sequence.\n\n"
294 ":arg factory: The factory to play second.\n"
295 ":type factory: :class:`Factory`\n"
296 ":return: The created :class:`Factory` object.\n"
297 ":rtype: :class:`Factory`\n\n"
298 ".. note:: The two factories have to have the same specifications "
299 "(channels and samplerate).");
302 Factory_join(Factory* self, PyObject* object)
304 PyTypeObject* type = ((PyObject*)self)->ob_type;
306 if(!PyObject_TypeCheck(object, type))
308 PyErr_SetString(PyExc_TypeError, "Object has to be of type Factory!");
313 Factory *child = (Factory*)object;
315 parent = (Factory*)type->tp_alloc(type, 0);
318 parent->child_list = Py_BuildValue("(OO)", self, object);
322 parent->factory = new AUD_DoubleFactory(self->factory, child->factory);
324 catch(AUD_Exception& e)
327 PyErr_SetString(AUDError, e.str);
332 return (PyObject *)parent;
335 PyDoc_STRVAR(M_aud_Factory_highpass_doc,
336 "highpass(frequency, Q=0.5)\n\n"
337 "Creates a second order highpass filter based on the transfer "
338 "function H(s) = s^2 / (s^2 + s/Q + 1)\n\n"
339 ":arg frequency: The cut off trequency of the highpass.\n"
340 ":type frequency: float\n"
341 ":arg Q: Q factor of the lowpass.\n"
343 ":return: The created :class:`Factory` object.\n"
344 ":rtype: :class:`Factory`");
347 Factory_highpass(Factory* self, PyObject* args)
352 if(!PyArg_ParseTuple(args, "f|f:highpass", &frequency, &Q))
355 PyTypeObject* type = ((PyObject*)self)->ob_type;
356 Factory *parent = (Factory*)type->tp_alloc(type, 0);
361 parent->child_list = (PyObject*)self;
365 parent->factory = new AUD_HighpassFactory(self->factory, frequency, Q);
367 catch(AUD_Exception& e)
370 PyErr_SetString(AUDError, e.str);
375 return (PyObject *)parent;
378 PyDoc_STRVAR(M_aud_Factory_limit_doc,
379 "limit(start, end)\n\n"
380 "Limits a factory within a specific start and end time.\n\n"
381 ":arg start: Start time in seconds.\n"
382 ":type start: float\n"
383 ":arg end: End time in seconds.\n"
385 ":return: The created :class:`Factory` object.\n"
386 ":rtype: :class:`Factory`");
389 Factory_limit(Factory* self, PyObject* args)
393 if(!PyArg_ParseTuple(args, "ff:limit", &start, &end))
396 PyTypeObject* type = ((PyObject*)self)->ob_type;
397 Factory *parent = (Factory*)type->tp_alloc(type, 0);
402 parent->child_list = (PyObject*)self;
406 parent->factory = new AUD_LimiterFactory(self->factory, start, end);
408 catch(AUD_Exception& e)
411 PyErr_SetString(AUDError, e.str);
416 return (PyObject *)parent;
419 PyDoc_STRVAR(M_aud_Factory_pitch_doc,
421 "Changes the pitch of a factory with a specific factor.\n\n"
422 ":arg factor: The factor to change the pitch with.\n"
423 ":type factor: float\n"
424 ":return: The created :class:`Factory` object.\n"
425 ":rtype: :class:`Factory`\n\n"
426 ".. note:: This is done by changing the sample rate of the "
427 "underlying factory, which has to be an integer, so the factor "
428 "value rounded and the factor may not be 100 % accurate.\n\n"
429 ".. note:: This is a filter function, you might consider using "
430 ":attr:`Handle.pitch` instead.");
433 Factory_pitch(Factory* self, PyObject* args)
437 if(!PyArg_ParseTuple(args, "f:pitch", &factor))
440 PyTypeObject* type = ((PyObject*)self)->ob_type;
441 Factory *parent = (Factory*)type->tp_alloc(type, 0);
446 parent->child_list = (PyObject*)self;
450 parent->factory = new AUD_PitchFactory(self->factory, factor);
452 catch(AUD_Exception& e)
455 PyErr_SetString(AUDError, e.str);
460 return (PyObject *)parent;
463 PyDoc_STRVAR(M_aud_Factory_volume_doc,
465 "Changes the volume of a factory.\n\n"
466 ":arg volume: The new volume..\n"
467 ":type volume: float\n"
468 ":return: The created :class:`Factory` object.\n"
469 ":rtype: :class:`Factory`\n\n"
470 ".. note:: Should be in the range [0, 1] to avoid clipping.\n\n"
471 ".. note:: This is a filter function, you might consider using "
472 ":attr:`Handle.volume` instead.");
475 Factory_volume(Factory* self, PyObject* args)
479 if(!PyArg_ParseTuple(args, "f:volume", &volume))
482 PyTypeObject* type = ((PyObject*)self)->ob_type;
483 Factory *parent = (Factory*)type->tp_alloc(type, 0);
488 parent->child_list = (PyObject*)self;
492 parent->factory = new AUD_VolumeFactory(self->factory, volume);
494 catch(AUD_Exception& e)
497 PyErr_SetString(AUDError, e.str);
502 return (PyObject *)parent;
505 PyDoc_STRVAR(M_aud_Factory_fadein_doc,
506 "fadein(start, length)\n\n"
507 "Fades a factory in by raising the volume linearly in the given "
509 ":arg start: Time in seconds when the fading should start.\n"
510 ":type start: float\n"
511 ":arg length: Time in seconds how long the fading should last.\n"
512 ":type length: float\n"
513 ":return: The created :class:`Factory` object.\n"
514 ":rtype: :class:`Factory`\n\n"
515 ".. note:: Before the fade starts it plays silence.");
518 Factory_fadein(Factory* self, PyObject* args)
522 if(!PyArg_ParseTuple(args, "ff:fadein", &start, &length))
525 PyTypeObject* type = ((PyObject*)self)->ob_type;
526 Factory *parent = (Factory*)type->tp_alloc(type, 0);
531 parent->child_list = (PyObject*)self;
535 parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_IN, start, length);
537 catch(AUD_Exception& e)
540 PyErr_SetString(AUDError, e.str);
545 return (PyObject *)parent;
548 PyDoc_STRVAR(M_aud_Factory_fadeout_doc,
549 "fadeout(start, length)\n\n"
550 "Fades a factory in by lowering the volume linearly in the given "
552 ":arg start: Time in seconds when the fading should start.\n"
553 ":type start: float\n"
554 ":arg length: Time in seconds how long the fading should last.\n"
555 ":type length: float\n"
556 ":return: The created :class:`Factory` object.\n"
557 ":rtype: :class:`Factory`\n\n"
558 ".. note:: After the fade this factory plays silence, so that "
559 "the length of the factory is not altered.");
562 Factory_fadeout(Factory* self, PyObject* args)
566 if(!PyArg_ParseTuple(args, "ff:fadeout", &start, &length))
569 PyTypeObject* type = ((PyObject*)self)->ob_type;
570 Factory *parent = (Factory*)type->tp_alloc(type, 0);
575 parent->child_list = (PyObject*)self;
579 parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_OUT, start, length);
581 catch(AUD_Exception& e)
584 PyErr_SetString(AUDError, e.str);
589 return (PyObject *)parent;
592 PyDoc_STRVAR(M_aud_Factory_loop_doc,
594 "Loops a factory.\n\n"
595 ":arg count: How often the factory should be looped. "
596 "Negative values mean endlessly.\n"
597 ":type count: integer\n"
598 ":return: The created :class:`Factory` object.\n"
599 ":rtype: :class:`Factory`\n\n"
600 ".. note:: This is a filter function, you might consider using "
601 ":attr:`Handle.loop_count` instead.");
604 Factory_loop(Factory* self, PyObject* args)
608 if(!PyArg_ParseTuple(args, "i:loop", &loop))
611 PyTypeObject* type = ((PyObject*)self)->ob_type;
612 Factory *parent = (Factory*)type->tp_alloc(type, 0);
617 parent->child_list = (PyObject*)self;
621 parent->factory = new AUD_LoopFactory(self->factory, loop);
623 catch(AUD_Exception& e)
626 PyErr_SetString(AUDError, e.str);
631 return (PyObject *)parent;
634 PyDoc_STRVAR(M_aud_Factory_mix_doc,
636 "Mixes two factories.\n\n"
637 ":arg factory: The factory to mix over the other.\n"
638 ":type factory: :class:`Factory`\n"
639 ":return: The created :class:`Factory` object.\n"
640 ":rtype: :class:`Factory`\n\n"
641 ".. note:: The two factories have to have the same specifications "
642 "(channels and samplerate).");
645 Factory_mix(Factory* self, PyObject* object)
647 PyTypeObject* type = ((PyObject*)self)->ob_type;
649 if(!PyObject_TypeCheck(object, type))
651 PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
655 Factory *parent = (Factory*)type->tp_alloc(type, 0);
656 Factory *child = (Factory*)object;
660 parent->child_list = Py_BuildValue("(OO)", self, object);
664 parent->factory = new AUD_SuperposeFactory(self->factory, child->factory);
666 catch(AUD_Exception& e)
669 PyErr_SetString(AUDError, e.str);
674 return (PyObject *)parent;
677 PyDoc_STRVAR(M_aud_Factory_pingpong_doc,
679 "Plays a factory forward and then backward.\n"
680 "This is like joining a factory with its reverse.\n\n"
681 ":return: The created :class:`Factory` object.\n"
682 ":rtype: :class:`Factory`");
685 Factory_pingpong(Factory* self)
687 PyTypeObject* type = ((PyObject*)self)->ob_type;
688 Factory *parent = (Factory*)type->tp_alloc(type, 0);
693 parent->child_list = (PyObject*)self;
697 parent->factory = new AUD_PingPongFactory(self->factory);
699 catch(AUD_Exception& e)
702 PyErr_SetString(AUDError, e.str);
707 return (PyObject *)parent;
710 PyDoc_STRVAR(M_aud_Factory_reverse_doc,
712 "Plays a factory reversed.\n\n"
713 ":return: The created :class:`Factory` object.\n"
714 ":rtype: :class:`Factory`\n\n"
715 ".. note:: The factory has to have a finite length and has to be "
716 "seekable. It's recommended to use this only with factories with "
717 "fast and accurate seeking, which is not true for encoded audio "
718 "files, such ones should be buffered using :meth:`buffer` before "
719 "being played reversed.\n\n"
720 ".. warning:: If seeking is not accurate in the underlying factory "
721 "you'll likely hear skips/jumps/cracks.");
724 Factory_reverse(Factory* self)
726 PyTypeObject* type = ((PyObject*)self)->ob_type;
727 Factory *parent = (Factory*)type->tp_alloc(type, 0);
732 parent->child_list = (PyObject*)self;
736 parent->factory = new AUD_ReverseFactory(self->factory);
738 catch(AUD_Exception& e)
741 PyErr_SetString(AUDError, e.str);
746 return (PyObject *)parent;
749 PyDoc_STRVAR(M_aud_Factory_buffer_doc,
751 "Buffers a factory into RAM.\n"
752 "This saves CPU usage needed for decoding and file access if the "
753 "underlying factory reads from a file on the harddisk, but it "
754 "consumes a lot of memory.\n\n"
755 ":return: The created :class:`Factory` object.\n"
756 ":rtype: :class:`Factory`\n\n"
757 ".. note:: Only known-length factories can be buffered.\n\n"
758 ".. warning:: Raw PCM data needs a lot of space, only buffer "
762 Factory_buffer(Factory* self)
764 PyTypeObject* type = ((PyObject*)self)->ob_type;
765 Factory *parent = (Factory*)type->tp_alloc(type, 0);
771 parent->factory = new AUD_StreamBufferFactory(self->factory);
773 catch(AUD_Exception& e)
776 PyErr_SetString(AUDError, e.str);
781 return (PyObject *)parent;
784 PyDoc_STRVAR(M_aud_Factory_square_doc,
785 "square(threshold = 0)\n\n"
786 "Makes a square wave out of an audio wave by setting all samples "
787 "with a amplitude >= threshold to 1, all <= -threshold to -1 and "
788 "all between to 0.\n\n"
789 ":arg threshold: Threshold value over which an amplitude counts "
791 ":type threshold: float\n"
792 ":return: The created :class:`Factory` object.\n"
793 ":rtype: :class:`Factory`");
796 Factory_square(Factory* self, PyObject* args)
800 if(!PyArg_ParseTuple(args, "|f:square", &threshold))
803 PyTypeObject* type = ((PyObject*)self)->ob_type;
804 Factory *parent = (Factory*)type->tp_alloc(type, 0);
809 parent->child_list = (PyObject*)self;
813 parent->factory = new AUD_SquareFactory(self->factory, threshold);
815 catch(AUD_Exception& e)
818 PyErr_SetString(AUDError, e.str);
823 return (PyObject *)parent;
826 PyDoc_STRVAR(M_aud_Factory_filter_doc,
827 "filter(b, a = (1))\n\n"
828 "Filters a factory with the supplied IIR filter coefficients.\n"
829 "Without the second parameter you'll get a FIR filter.\n"
830 "If the first value of the a sequence is 0 it will be set to 1 "
832 "If the first value of the a sequence is neither 0 nor 1, all "
833 "filter coefficients will be scaled by this value so that it is 1 "
834 "in the end, you don't have to scale yourself.\n\n"
835 ":arg b: The nominator filter coefficients.\n"
836 ":type b: sequence of float\n"
837 ":arg a: The denominator filter coefficients.\n"
838 ":type a: sequence of float\n"
839 ":return: The created :class:`Factory` object.\n"
840 ":rtype: :class:`Factory`");
843 Factory_filter(Factory* self, PyObject* args)
846 PyObject* py_a = NULL;
848 if(!PyArg_ParseTuple(args, "O|O:filter", &py_b, &py_a))
851 if(!PySequence_Check(py_b) || (py_a != NULL && !PySequence_Check(py_a)))
853 PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
857 if(!PySequence_Length(py_b) || (py_a != NULL && !PySequence_Length(py_a)))
859 PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
863 std::vector<float> a, b;
868 for(int i = 0; i < PySequence_Length(py_b); i++)
870 py_value = PySequence_GetItem(py_b, i);
871 result = PyArg_Parse(py_value, "f:filter", &value);
882 for(int i = 0; i < PySequence_Length(py_a); i++)
884 py_value = PySequence_GetItem(py_a, i);
885 result = PyArg_Parse(py_value, "f:filter", &value);
900 PyTypeObject* type = ((PyObject*)self)->ob_type;
901 Factory *parent = (Factory*)type->tp_alloc(type, 0);
906 parent->child_list = (PyObject*)self;
910 parent->factory = new AUD_IIRFilterFactory(self->factory, b, a);
912 catch(AUD_Exception& e)
915 PyErr_SetString(AUDError, e.str);
920 return (PyObject *)parent;
923 static PyMethodDef Factory_methods[] = {
924 {"sine", (PyCFunction)Factory_sine, METH_VARARGS | METH_CLASS,
925 M_aud_Factory_sine_doc
927 {"file", (PyCFunction)Factory_file, METH_VARARGS | METH_CLASS,
928 M_aud_Factory_file_doc
930 {"lowpass", (PyCFunction)Factory_lowpass, METH_VARARGS,
931 M_aud_Factory_lowpass_doc
933 {"delay", (PyCFunction)Factory_delay, METH_VARARGS,
934 M_aud_Factory_delay_doc
936 {"join", (PyCFunction)Factory_join, METH_O,
937 M_aud_Factory_join_doc
939 {"highpass", (PyCFunction)Factory_highpass, METH_VARARGS,
940 M_aud_Factory_highpass_doc
942 {"limit", (PyCFunction)Factory_limit, METH_VARARGS,
943 M_aud_Factory_limit_doc
945 {"pitch", (PyCFunction)Factory_pitch, METH_VARARGS,
946 M_aud_Factory_pitch_doc
948 {"volume", (PyCFunction)Factory_volume, METH_VARARGS,
949 M_aud_Factory_volume_doc
951 {"fadein", (PyCFunction)Factory_fadein, METH_VARARGS,
952 M_aud_Factory_fadein_doc
954 {"fadeout", (PyCFunction)Factory_fadeout, METH_VARARGS,
955 M_aud_Factory_fadeout_doc
957 {"loop", (PyCFunction)Factory_loop, METH_VARARGS,
958 M_aud_Factory_loop_doc
960 {"mix", (PyCFunction)Factory_mix, METH_O,
961 M_aud_Factory_mix_doc
963 {"pingpong", (PyCFunction)Factory_pingpong, METH_NOARGS,
964 M_aud_Factory_pingpong_doc
966 {"reverse", (PyCFunction)Factory_reverse, METH_NOARGS,
967 M_aud_Factory_reverse_doc
969 {"buffer", (PyCFunction)Factory_buffer, METH_NOARGS,
970 M_aud_Factory_buffer_doc
972 {"square", (PyCFunction)Factory_square, METH_VARARGS,
973 M_aud_Factory_square_doc
975 {"filter", (PyCFunction)Factory_filter, METH_VARARGS,
976 M_aud_Factory_filter_doc
978 {NULL} /* Sentinel */
981 PyDoc_STRVAR(M_aud_Factory_doc,
982 "Factory objects are immutable and represent a sound that can be "
983 "played simultaneously multiple times. They are called factories "
984 "because they create reader objects internally that are used for "
987 static PyTypeObject FactoryType = {
988 PyVarObject_HEAD_INIT(NULL, 0)
989 "aud.Factory", /* tp_name */
990 sizeof(Factory), /* tp_basicsize */
992 (destructor)Factory_dealloc, /* tp_dealloc */
998 0, /* tp_as_number */
999 0, /* tp_as_sequence */
1000 0, /* tp_as_mapping */
1004 0, /* tp_getattro */
1005 0, /* tp_setattro */
1006 0, /* tp_as_buffer */
1007 Py_TPFLAGS_DEFAULT, /* tp_flags */
1008 M_aud_Factory_doc, /* tp_doc */
1009 0, /* tp_traverse */
1011 0, /* tp_richcompare */
1012 0, /* tp_weaklistoffset */
1014 0, /* tp_iternext */
1015 Factory_methods, /* tp_methods */
1020 0, /* tp_descr_get */
1021 0, /* tp_descr_set */
1022 0, /* tp_dictoffset */
1025 Factory_new, /* tp_new */
1028 // ========== Handle ==================================================
1031 Handle_dealloc(Handle* self)
1033 Py_XDECREF(self->device);
1034 Py_TYPE(self)->tp_free((PyObject*)self);
1037 PyDoc_STRVAR(M_aud_Handle_pause_doc,
1039 "Pauses playback.\n\n"
1040 ":return: Whether the action succeeded.\n"
1044 Handle_pause(Handle *self)
1046 Device* device = (Device*)self->device;
1050 if(device->device->pause(self->handle))
1055 catch(AUD_Exception& e)
1057 PyErr_SetString(AUDError, e.str);
1064 PyDoc_STRVAR(M_aud_Handle_resume_doc,
1066 "Resumes playback.\n\n"
1067 ":return: Whether the action succeeded.\n"
1071 Handle_resume(Handle *self)
1073 Device* device = (Device*)self->device;
1077 if(device->device->resume(self->handle))
1082 catch(AUD_Exception& e)
1084 PyErr_SetString(AUDError, e.str);
1091 PyDoc_STRVAR(M_aud_Handle_stop_doc,
1093 "Stops playback.\n\n"
1094 ":return: Whether the action succeeded.\n"
1096 ".. note:: This makes the handle invalid.");
1099 Handle_stop(Handle *self)
1101 Device* device = (Device*)self->device;
1105 if(device->device->stop(self->handle))
1110 catch(AUD_Exception& e)
1112 PyErr_SetString(AUDError, e.str);
1119 static PyMethodDef Handle_methods[] = {
1120 {"pause", (PyCFunction)Handle_pause, METH_NOARGS,
1121 M_aud_Handle_pause_doc
1123 {"resume", (PyCFunction)Handle_resume, METH_NOARGS,
1124 M_aud_Handle_resume_doc
1126 {"stop", (PyCFunction)Handle_stop, METH_NOARGS,
1127 M_aud_Handle_stop_doc
1129 {NULL} /* Sentinel */
1132 PyDoc_STRVAR(M_aud_Handle_position_doc,
1133 "The playback position of the sound in seconds.");
1136 Handle_get_position(Handle *self, void* nothing)
1138 Device* device = (Device*)self->device;
1142 return Py_BuildValue("f", device->device->getPosition(self->handle));
1144 catch(AUD_Exception& e)
1146 PyErr_SetString(AUDError, e.str);
1152 Handle_set_position(Handle *self, PyObject* args, void* nothing)
1156 if(!PyArg_Parse(args, "f:position", &position))
1159 Device* device = (Device*)self->device;
1163 if(device->device->seek(self->handle, position))
1165 PyErr_SetString(AUDError, "Couldn't seek the sound!");
1167 catch(AUD_Exception& e)
1169 PyErr_SetString(AUDError, e.str);
1175 PyDoc_STRVAR(M_aud_Handle_keep_doc,
1176 "Whether the sound should be kept paused in the device when its "
1178 "This can be used to seek the sound to some position and start "
1179 "playback again.\n\n"
1180 ".. warning:: If this is set to true and you forget stopping this "
1181 "equals a memory leak as the handle exists until the device is "
1185 Handle_get_keep(Handle *self, void* nothing)
1187 Device* device = (Device*)self->device;
1191 if(device->device->getKeep(self->handle))
1200 catch(AUD_Exception& e)
1202 PyErr_SetString(AUDError, e.str);
1208 Handle_set_keep(Handle *self, PyObject* args, void* nothing)
1210 if(!PyBool_Check(args))
1212 PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
1216 bool keep = args == Py_True;
1217 Device* device = (Device*)self->device;
1221 if(device->device->setKeep(self->handle, keep))
1223 PyErr_SetString(AUDError, "Couldn't set keep of the sound!");
1225 catch(AUD_Exception& e)
1227 PyErr_SetString(AUDError, e.str);
1233 PyDoc_STRVAR(M_aud_Handle_status_doc,
1234 "Whether the sound is playing, paused or stopped (=invalid).");
1237 Handle_get_status(Handle *self, void* nothing)
1239 Device* device = (Device*)self->device;
1243 return Py_BuildValue("i", device->device->getStatus(self->handle));
1245 catch(AUD_Exception& e)
1247 PyErr_SetString(AUDError, e.str);
1252 PyDoc_STRVAR(M_aud_Handle_volume_doc,
1253 "The volume of the sound.");
1256 Handle_get_volume(Handle *self, void* nothing)
1258 Device* device = (Device*)self->device;
1262 return Py_BuildValue("f", device->device->getVolume(self->handle));
1264 catch(AUD_Exception& e)
1266 PyErr_SetString(AUDError, e.str);
1272 Handle_set_volume(Handle *self, PyObject* args, void* nothing)
1276 if(!PyArg_Parse(args, "f:volume", &volume))
1279 Device* device = (Device*)self->device;
1283 if(device->device->setVolume(self->handle, volume))
1285 PyErr_SetString(AUDError, "Couldn't set the sound volume!");
1287 catch(AUD_Exception& e)
1289 PyErr_SetString(AUDError, e.str);
1295 PyDoc_STRVAR(M_aud_Handle_pitch_doc,
1296 "The pitch of the sound.");
1299 Handle_get_pitch(Handle *self, void* nothing)
1301 Device* device = (Device*)self->device;
1305 return Py_BuildValue("f", device->device->getPitch(self->handle));
1307 catch(AUD_Exception& e)
1309 PyErr_SetString(AUDError, e.str);
1315 Handle_set_pitch(Handle *self, PyObject* args, void* nothing)
1319 if(!PyArg_Parse(args, "f:pitch", &pitch))
1322 Device* device = (Device*)self->device;
1326 if(device->device->setPitch(self->handle, pitch))
1328 PyErr_SetString(AUDError, "Couldn't set the sound pitch!");
1330 catch(AUD_Exception& e)
1332 PyErr_SetString(AUDError, e.str);
1338 PyDoc_STRVAR(M_aud_Handle_loop_count_doc,
1339 "The (remaining) loop count of the sound. A negative value indicates infinity.");
1342 Handle_get_loop_count(Handle *self, void* nothing)
1344 Device* device = (Device*)self->device;
1348 return Py_BuildValue("i", device->device->getLoopCount(self->handle));
1350 catch(AUD_Exception& e)
1352 PyErr_SetString(AUDError, e.str);
1358 Handle_set_loop_count(Handle *self, PyObject* args, void* nothing)
1362 if(!PyArg_Parse(args, "i:loop_count", &loops))
1365 Device* device = (Device*)self->device;
1369 if(device->device->setLoopCount(self->handle, loops))
1371 PyErr_SetString(AUDError, "Couldn't set the loop count!");
1373 catch(AUD_Exception& e)
1375 PyErr_SetString(AUDError, e.str);
1381 PyDoc_STRVAR(M_aud_Handle_location_doc,
1382 "The source's location in 3D space, a 3D tuple of floats.");
1385 Handle_get_location(Handle *self, void* nothing)
1387 Device* dev = (Device*)self->device;
1391 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1394 AUD_Vector3 v = device->getSourceLocation(self->handle);
1395 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
1399 PyErr_SetString(AUDError, device_not_3d_error);
1402 catch(AUD_Exception& e)
1404 PyErr_SetString(AUDError, e.str);
1411 Handle_set_location(Handle *self, PyObject* args, void* nothing)
1415 if(!PyArg_Parse(args, "(fff):location", &x, &y, &z))
1418 Device* dev = (Device*)self->device;
1422 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1425 AUD_Vector3 location(x, y, z);
1426 if(device->setSourceLocation(self->handle, location))
1428 PyErr_SetString(AUDError, "Location couldn't be set!");
1431 PyErr_SetString(AUDError, device_not_3d_error);
1433 catch(AUD_Exception& e)
1435 PyErr_SetString(AUDError, e.str);
1441 PyDoc_STRVAR(M_aud_Handle_velocity_doc,
1442 "The source's velocity in 3D space, a 3D tuple of floats.");
1445 Handle_get_velocity(Handle *self, void* nothing)
1447 Device* dev = (Device*)self->device;
1451 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1454 AUD_Vector3 v = device->getSourceVelocity(self->handle);
1455 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
1459 PyErr_SetString(AUDError, device_not_3d_error);
1462 catch(AUD_Exception& e)
1464 PyErr_SetString(AUDError, e.str);
1471 Handle_set_velocity(Handle *self, PyObject* args, void* nothing)
1475 if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z))
1478 Device* dev = (Device*)self->device;
1482 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1485 AUD_Vector3 velocity(x, y, z);
1486 if(device->setSourceVelocity(self->handle, velocity))
1488 PyErr_SetString(AUDError, "Couldn't set the velocity!");
1491 PyErr_SetString(AUDError, device_not_3d_error);
1493 catch(AUD_Exception& e)
1495 PyErr_SetString(AUDError, e.str);
1501 PyDoc_STRVAR(M_aud_Handle_orientation_doc,
1502 "The source's orientation in 3D space as quaternion, a 4 float tuple.");
1505 Handle_get_orientation(Handle *self, void* nothing)
1507 Device* dev = (Device*)self->device;
1511 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1514 AUD_Quaternion o = device->getSourceOrientation(self->handle);
1515 return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
1519 PyErr_SetString(AUDError, device_not_3d_error);
1522 catch(AUD_Exception& e)
1524 PyErr_SetString(AUDError, e.str);
1531 Handle_set_orientation(Handle *self, PyObject* args, void* nothing)
1535 if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z))
1538 Device* dev = (Device*)self->device;
1542 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1545 AUD_Quaternion orientation(w, x, y, z);
1546 if(device->setSourceOrientation(self->handle, orientation))
1548 PyErr_SetString(AUDError, "Couldn't set the orientation!");
1551 PyErr_SetString(AUDError, device_not_3d_error);
1553 catch(AUD_Exception& e)
1555 PyErr_SetString(AUDError, e.str);
1561 PyDoc_STRVAR(M_aud_Handle_relative_doc,
1562 "Whether the source's location, velocity and orientation is relative or absolute to the listener.");
1565 Handle_get_relative(Handle *self, void* nothing)
1567 Device* dev = (Device*)self->device;
1571 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1574 if(device->isRelative(self->handle))
1585 PyErr_SetString(AUDError, device_not_3d_error);
1588 catch(AUD_Exception& e)
1590 PyErr_SetString(AUDError, e.str);
1597 Handle_set_relative(Handle *self, PyObject* args, void* nothing)
1599 if(!PyBool_Check(args))
1601 PyErr_SetString(PyExc_TypeError, "Value is not a boolean!");
1605 bool relative = (args == Py_True);
1606 Device* dev = (Device*)self->device;
1610 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1613 if(device->setRelative(self->handle, relative))
1615 PyErr_SetString(AUDError, "Couldn't set the relativeness!");
1618 PyErr_SetString(AUDError, device_not_3d_error);
1620 catch(AUD_Exception& e)
1622 PyErr_SetString(AUDError, e.str);
1628 PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc,
1629 "The minimum volume of the source.\n\n"
1630 ".. seealso:: :attr:`Device.distance_model`");
1633 Handle_get_volume_minimum(Handle *self, void* nothing)
1635 Device* dev = (Device*)self->device;
1639 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1642 return Py_BuildValue("f", device->getVolumeMinimum(self->handle));
1646 PyErr_SetString(AUDError, device_not_3d_error);
1650 catch(AUD_Exception& e)
1652 PyErr_SetString(AUDError, e.str);
1658 Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing)
1662 if(!PyArg_Parse(args, "f:volume_minimum", &volume))
1665 Device* dev = (Device*)self->device;
1669 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1672 if(device->setVolumeMinimum(self->handle, volume))
1674 PyErr_SetString(AUDError, "Couldn't set the minimum volume!");
1677 PyErr_SetString(AUDError, device_not_3d_error);
1679 catch(AUD_Exception& e)
1681 PyErr_SetString(AUDError, e.str);
1687 PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc,
1688 "The maximum volume of the source.\n\n"
1689 ".. seealso:: :attr:`Device.distance_model`");
1692 Handle_get_volume_maximum(Handle *self, void* nothing)
1694 Device* dev = (Device*)self->device;
1698 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1701 return Py_BuildValue("f", device->getVolumeMaximum(self->handle));
1705 PyErr_SetString(AUDError, device_not_3d_error);
1709 catch(AUD_Exception& e)
1711 PyErr_SetString(AUDError, e.str);
1717 Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing)
1721 if(!PyArg_Parse(args, "f:volume_maximum", &volume))
1724 Device* dev = (Device*)self->device;
1728 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1731 if(device->setVolumeMaximum(self->handle, volume))
1733 PyErr_SetString(AUDError, "Couldn't set the maximum volume!");
1736 PyErr_SetString(AUDError, device_not_3d_error);
1738 catch(AUD_Exception& e)
1740 PyErr_SetString(AUDError, e.str);
1746 PyDoc_STRVAR(M_aud_Handle_distance_reference_doc,
1747 "The reference distance of the source.\n"
1748 "At this distance the volume will be exactly :attr:`volume`.\n\n"
1749 ".. seealso:: :attr:`Device.distance_model`");
1752 Handle_get_distance_reference(Handle *self, void* nothing)
1754 Device* dev = (Device*)self->device;
1758 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1761 return Py_BuildValue("f", device->getDistanceReference(self->handle));
1765 PyErr_SetString(AUDError, device_not_3d_error);
1769 catch(AUD_Exception& e)
1771 PyErr_SetString(AUDError, e.str);
1777 Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing)
1781 if(!PyArg_Parse(args, "f:distance_reference", &distance))
1784 Device* dev = (Device*)self->device;
1788 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1791 if(device->setDistanceReference(self->handle, distance))
1793 PyErr_SetString(AUDError, "Couldn't set the reference distance!");
1796 PyErr_SetString(AUDError, device_not_3d_error);
1798 catch(AUD_Exception& e)
1800 PyErr_SetString(AUDError, e.str);
1806 PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc,
1807 "The maximum distance of the source.\n"
1808 "If the listener is further away the source volume will be 0.\n\n"
1809 ".. seealso:: :attr:`Device.distance_model`");
1812 Handle_get_distance_maximum(Handle *self, void* nothing)
1814 Device* dev = (Device*)self->device;
1818 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1821 return Py_BuildValue("f", device->getDistanceMaximum(self->handle));
1825 PyErr_SetString(AUDError, device_not_3d_error);
1829 catch(AUD_Exception& e)
1831 PyErr_SetString(AUDError, e.str);
1837 Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing)
1841 if(!PyArg_Parse(args, "f:distance_maximum", &distance))
1844 Device* dev = (Device*)self->device;
1848 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1851 if(device->setDistanceMaximum(self->handle, distance))
1853 PyErr_SetString(AUDError, "Couldn't set the maximum distance!");
1856 PyErr_SetString(AUDError, device_not_3d_error);
1858 catch(AUD_Exception& e)
1860 PyErr_SetString(AUDError, e.str);
1866 PyDoc_STRVAR(M_aud_Handle_attenuation_doc,
1867 "This factor is used for distance based attenuation of the "
1869 ".. seealso:: :attr:`Device.distance_model`");
1872 Handle_get_attenuation(Handle *self, void* nothing)
1874 Device* dev = (Device*)self->device;
1878 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1881 return Py_BuildValue("f", device->getAttenuation(self->handle));
1885 PyErr_SetString(AUDError, device_not_3d_error);
1889 catch(AUD_Exception& e)
1891 PyErr_SetString(AUDError, e.str);
1897 Handle_set_attenuation(Handle *self, PyObject* args, void* nothing)
1901 if(!PyArg_Parse(args, "f:attenuation", &factor))
1904 Device* dev = (Device*)self->device;
1908 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1911 if(device->setAttenuation(self->handle, factor))
1913 PyErr_SetString(AUDError, "Couldn't set the attenuation!");
1916 PyErr_SetString(AUDError, device_not_3d_error);
1918 catch(AUD_Exception& e)
1920 PyErr_SetString(AUDError, e.str);
1926 PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc,
1927 "The opening angle of the inner cone of the source. If the cone "
1928 "values of a source are set there are two (audible) cones with "
1929 "the apex at the :attr:`location` of the source and with infinite "
1930 "height, heading in the direction of the source's "
1931 ":attr:`orientation`.\n"
1932 "In the inner cone the volume is normal. Outside the outer cone "
1933 "the volume will be :attr:`cone_volume_outer` and in the area "
1934 "between the volume will be interpolated linearly.");
1937 Handle_get_cone_angle_inner(Handle *self, void* nothing)
1939 Device* dev = (Device*)self->device;
1943 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1946 return Py_BuildValue("f", device->getConeAngleInner(self->handle));
1950 PyErr_SetString(AUDError, device_not_3d_error);
1954 catch(AUD_Exception& e)
1956 PyErr_SetString(AUDError, e.str);
1962 Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing)
1966 if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
1969 Device* dev = (Device*)self->device;
1973 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1976 if(device->setConeAngleInner(self->handle, angle))
1978 PyErr_SetString(AUDError, "Couldn't set the cone inner angle!");
1981 PyErr_SetString(AUDError, device_not_3d_error);
1983 catch(AUD_Exception& e)
1985 PyErr_SetString(AUDError, e.str);
1991 PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc,
1992 "The opening angle of the outer cone of the source.\n\n"
1993 ".. seealso:: :attr:`cone_angle_inner`");
1996 Handle_get_cone_angle_outer(Handle *self, void* nothing)
1998 Device* dev = (Device*)self->device;
2002 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2005 return Py_BuildValue("f", device->getConeAngleOuter(self->handle));
2009 PyErr_SetString(AUDError, device_not_3d_error);
2013 catch(AUD_Exception& e)
2015 PyErr_SetString(AUDError, e.str);
2021 Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing)
2025 if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
2028 Device* dev = (Device*)self->device;
2032 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2035 if(device->setConeAngleOuter(self->handle, angle))
2037 PyErr_SetString(AUDError, "Couldn't set the cone outer angle!");
2040 PyErr_SetString(AUDError, device_not_3d_error);
2042 catch(AUD_Exception& e)
2044 PyErr_SetString(AUDError, e.str);
2050 PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc,
2051 "The volume outside the outer cone of the source.\n\n"
2052 ".. seealso:: :attr:`cone_angle_inner`");
2055 Handle_get_cone_volume_outer(Handle *self, void* nothing)
2057 Device* dev = (Device*)self->device;
2061 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2064 return Py_BuildValue("f", device->getConeVolumeOuter(self->handle));
2068 PyErr_SetString(AUDError, device_not_3d_error);
2072 catch(AUD_Exception& e)
2074 PyErr_SetString(AUDError, e.str);
2080 Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing)
2084 if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
2087 Device* dev = (Device*)self->device;
2091 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2094 if(device->setConeVolumeOuter(self->handle, volume))
2096 PyErr_SetString(AUDError, "Couldn't set the cone outer volume!");
2099 PyErr_SetString(AUDError, device_not_3d_error);
2101 catch(AUD_Exception& e)
2103 PyErr_SetString(AUDError, e.str);
2109 static PyGetSetDef Handle_properties[] = {
2110 {(char*)"position", (getter)Handle_get_position, (setter)Handle_set_position,
2111 M_aud_Handle_position_doc, NULL },
2112 {(char*)"keep", (getter)Handle_get_keep, (setter)Handle_set_keep,
2113 M_aud_Handle_keep_doc, NULL },
2114 {(char*)"status", (getter)Handle_get_status, NULL,
2115 M_aud_Handle_status_doc, NULL },
2116 {(char*)"volume", (getter)Handle_get_volume, (setter)Handle_set_volume,
2117 M_aud_Handle_volume_doc, NULL },
2118 {(char*)"pitch", (getter)Handle_get_pitch, (setter)Handle_set_pitch,
2119 M_aud_Handle_pitch_doc, NULL },
2120 {(char*)"loop_count", (getter)Handle_get_loop_count, (setter)Handle_set_loop_count,
2121 M_aud_Handle_loop_count_doc, NULL },
2122 {(char*)"location", (getter)Handle_get_location, (setter)Handle_set_location,
2123 M_aud_Handle_location_doc, NULL },
2124 {(char*)"velocity", (getter)Handle_get_velocity, (setter)Handle_set_velocity,
2125 M_aud_Handle_velocity_doc, NULL },
2126 {(char*)"orientation", (getter)Handle_get_orientation, (setter)Handle_set_orientation,
2127 M_aud_Handle_orientation_doc, NULL },
2128 {(char*)"relative", (getter)Handle_get_relative, (setter)Handle_set_relative,
2129 M_aud_Handle_relative_doc, NULL },
2130 {(char*)"volume_minimum", (getter)Handle_get_volume_minimum, (setter)Handle_set_volume_minimum,
2131 M_aud_Handle_volume_minimum_doc, NULL },
2132 {(char*)"volume_maximum", (getter)Handle_get_volume_maximum, (setter)Handle_set_volume_maximum,
2133 M_aud_Handle_volume_maximum_doc, NULL },
2134 {(char*)"distance_reference", (getter)Handle_get_distance_reference, (setter)Handle_set_distance_reference,
2135 M_aud_Handle_distance_reference_doc, NULL },
2136 {(char*)"distance_maximum", (getter)Handle_get_distance_maximum, (setter)Handle_set_distance_maximum,
2137 M_aud_Handle_distance_maximum_doc, NULL },
2138 {(char*)"attenuation", (getter)Handle_get_attenuation, (setter)Handle_set_attenuation,
2139 M_aud_Handle_attenuation_doc, NULL },
2140 {(char*)"cone_angle_inner", (getter)Handle_get_cone_angle_inner, (setter)Handle_set_cone_angle_inner,
2141 M_aud_Handle_cone_angle_inner_doc, NULL },
2142 {(char*)"cone_angle_outer", (getter)Handle_get_cone_angle_outer, (setter)Handle_set_cone_angle_outer,
2143 M_aud_Handle_cone_angle_outer_doc, NULL },
2144 {(char*)"cone_volume_outer", (getter)Handle_get_cone_volume_outer, (setter)Handle_set_cone_volume_outer,
2145 M_aud_Handle_cone_volume_outer_doc, NULL },
2146 {NULL} /* Sentinel */
2149 PyDoc_STRVAR(M_aud_Handle_doc,
2150 "Handle objects are playback handles that can be used to control "
2151 "playback of a sound. If a sound is played back multiple times "
2152 "then there are as many handles.");
2154 static PyTypeObject HandleType = {
2155 PyVarObject_HEAD_INIT(NULL, 0)
2156 "aud.Handle", /* tp_name */
2157 sizeof(Handle), /* tp_basicsize */
2158 0, /* tp_itemsize */
2159 (destructor)Handle_dealloc,/* tp_dealloc */
2163 0, /* tp_reserved */
2165 0, /* tp_as_number */
2166 0, /* tp_as_sequence */
2167 0, /* tp_as_mapping */
2171 0, /* tp_getattro */
2172 0, /* tp_setattro */
2173 0, /* tp_as_buffer */
2174 Py_TPFLAGS_DEFAULT, /* tp_flags */
2175 M_aud_Handle_doc, /* tp_doc */
2176 0, /* tp_traverse */
2178 0, /* tp_richcompare */
2179 0, /* tp_weaklistoffset */
2181 0, /* tp_iternext */
2182 Handle_methods, /* tp_methods */
2184 Handle_properties, /* tp_getset */
2187 0, /* tp_descr_get */
2188 0, /* tp_descr_set */
2189 0, /* tp_dictoffset */
2195 // ========== Device ==================================================
2198 Device_dealloc(Device* self)
2201 delete self->device;
2202 Py_TYPE(self)->tp_free((PyObject*)self);
2206 Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2210 static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL};
2212 int rate = AUD_RATE_44100;
2213 int channels = AUD_CHANNELS_STEREO;
2214 int format = AUD_FORMAT_FLOAT32;
2215 int buffersize = AUD_DEFAULT_BUFFER_SIZE;
2216 const char* name = "Audaspace";
2218 if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiis:Device", const_cast<char**>(kwlist),
2219 &device, &rate, &channels, &format, &buffersize, &name))
2222 if(buffersize < 128)
2224 PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than 127!");
2228 self = (Device*)type->tp_alloc(type, 0);
2231 AUD_DeviceSpecs specs;
2232 specs.channels = (AUD_Channels)channels;
2233 specs.format = (AUD_SampleFormat)format;
2234 specs.rate = (AUD_SampleRate)rate;
2236 self->device = NULL;
2242 case AUD_DEVICE_NULL:
2243 self->device = new AUD_NULLDevice();
2245 case AUD_DEVICE_OPENAL:
2247 self->device = new AUD_OpenALDevice(specs, buffersize);
2250 case AUD_DEVICE_SDL:
2252 self->device = new AUD_SDLDevice(specs, buffersize);
2255 case AUD_DEVICE_JACK:
2257 self->device = new AUD_JackDevice(name, specs, buffersize);
2260 case AUD_DEVICE_READ:
2265 catch(AUD_Exception& e)
2268 PyErr_SetString(AUDError, e.str);
2275 PyErr_SetString(AUDError, "Unsupported device type!");
2280 return (PyObject *)self;
2283 PyDoc_STRVAR(M_aud_Device_play_doc,
2284 "play(factory, keep=False)\n\n"
2285 "Plays a factory.\n\n"
2286 ":arg factory: The factory to play.\n"
2287 ":type factory: :class:`Factory`\n"
2288 ":arg keep: See :attr:`Handle.keep`.\n"
2289 ":type keep: bool\n"
2290 ":return: The playback handle with which playback can be "
2291 "controlled with.\n"
2292 ":rtype: :class:`Handle`");
2295 Device_play(Device *self, PyObject *args, PyObject *kwds)
2298 PyObject* keepo = NULL;
2302 static const char *kwlist[] = {"factory", "keep", NULL};
2304 if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:play", const_cast<char**>(kwlist), &object, &keepo))
2307 if(!PyObject_TypeCheck(object, &FactoryType))
2309 PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
2315 if(!PyBool_Check(keepo))
2317 PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
2321 keep = keepo == Py_True;
2324 Factory* sound = (Factory*)object;
2327 handle = (Handle*)HandleType.tp_alloc(&HandleType, 0);
2330 handle->device = (PyObject*)self;
2335 handle->handle = self->device->play(sound->factory, keep);
2337 catch(AUD_Exception& e)
2340 PyErr_SetString(AUDError, e.str);
2345 return (PyObject *)handle;
2348 PyDoc_STRVAR(M_aud_Device_lock_doc,
2350 "Locks the device so that it's guaranteed, that no samples are "
2351 "read from the streams until :meth:`unlock` is called.\n"
2352 "This is useful if you want to do start/stop/pause/resume some "
2353 "sounds at the same time.\n\n"
2354 ".. note:: The device has to be unlocked as often as locked to be "
2355 "able to continue playback.\n\n"
2356 ".. warning:: Make sure the time between locking and unlocking is "
2357 "as short as possible to avoid clicks.");
2360 Device_lock(Device *self)
2364 self->device->lock();
2367 catch(AUD_Exception& e)
2369 PyErr_SetString(AUDError, e.str);
2374 PyDoc_STRVAR(M_aud_Device_unlock_doc,
2376 "Unlocks the device after a lock call, see :meth:`lock` for "
2380 Device_unlock(Device *self)
2384 self->device->unlock();
2387 catch(AUD_Exception& e)
2389 PyErr_SetString(AUDError, e.str);
2394 static PyMethodDef Device_methods[] = {
2395 {"play", (PyCFunction)Device_play, METH_VARARGS | METH_KEYWORDS,
2396 M_aud_Device_play_doc
2398 {"lock", (PyCFunction)Device_lock, METH_NOARGS,
2399 M_aud_Device_lock_doc
2401 {"unlock", (PyCFunction)Device_unlock, METH_NOARGS,
2402 M_aud_Device_unlock_doc
2404 {NULL} /* Sentinel */
2407 PyDoc_STRVAR(M_aud_Device_rate_doc,
2408 "The sampling rate of the device in Hz.");
2411 Device_get_rate(Device *self, void* nothing)
2415 AUD_DeviceSpecs specs = self->device->getSpecs();
2416 return Py_BuildValue("i", specs.rate);
2418 catch(AUD_Exception& e)
2420 PyErr_SetString(AUDError, e.str);
2425 PyDoc_STRVAR(M_aud_Device_format_doc,
2426 "The native sample format of the device.");
2429 Device_get_format(Device *self, void* nothing)
2433 AUD_DeviceSpecs specs = self->device->getSpecs();
2434 return Py_BuildValue("i", specs.format);
2436 catch(AUD_Exception& e)
2438 PyErr_SetString(AUDError, e.str);
2443 PyDoc_STRVAR(M_aud_Device_channels_doc,
2444 "The channel count of the device.");
2447 Device_get_channels(Device *self, void* nothing)
2451 AUD_DeviceSpecs specs = self->device->getSpecs();
2452 return Py_BuildValue("i", specs.channels);
2454 catch(AUD_Exception& e)
2456 PyErr_SetString(AUDError, e.str);
2461 PyDoc_STRVAR(M_aud_Device_volume_doc,
2462 "The overall volume of the device.");
2465 Device_get_volume(Device *self, void* nothing)
2469 return Py_BuildValue("f", self->device->getVolume());
2471 catch(AUD_Exception& e)
2473 PyErr_SetString(AUDError, e.str);
2479 Device_set_volume(Device *self, PyObject* args, void* nothing)
2483 if(!PyArg_Parse(args, "f:volume", &volume))
2488 self->device->setVolume(volume);
2491 catch(AUD_Exception& e)
2493 PyErr_SetString(AUDError, e.str);
2498 PyDoc_STRVAR(M_aud_Device_listener_location_doc,
2499 "The listeners's location in 3D space, a 3D tuple of floats.");
2502 Device_get_listener_location(Device *self, void* nothing)
2506 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2509 AUD_Vector3 v = device->getListenerLocation();
2510 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
2514 PyErr_SetString(AUDError, device_not_3d_error);
2517 catch(AUD_Exception& e)
2519 PyErr_SetString(AUDError, e.str);
2526 Device_set_listener_location(Device *self, PyObject* args, void* nothing)
2530 if(!PyArg_Parse(args, "(fff):listener_location", &x, &y, &z))
2535 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2538 AUD_Vector3 location(x, y, z);
2539 device->setListenerLocation(location);
2543 PyErr_SetString(AUDError, device_not_3d_error);
2545 catch(AUD_Exception& e)
2547 PyErr_SetString(AUDError, e.str);
2553 PyDoc_STRVAR(M_aud_Device_listener_velocity_doc,
2554 "The listener's velocity in 3D space, a 3D tuple of floats.");
2557 Device_get_listener_velocity(Device *self, void* nothing)
2561 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2564 AUD_Vector3 v = device->getListenerVelocity();
2565 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
2569 PyErr_SetString(AUDError, device_not_3d_error);
2572 catch(AUD_Exception& e)
2574 PyErr_SetString(AUDError, e.str);
2581 Device_set_listener_velocity(Device *self, PyObject* args, void* nothing)
2585 if(!PyArg_Parse(args, "(fff):listener_velocity", &x, &y, &z))
2590 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2593 AUD_Vector3 velocity(x, y, z);
2594 device->setListenerVelocity(velocity);
2598 PyErr_SetString(AUDError, device_not_3d_error);
2600 catch(AUD_Exception& e)
2602 PyErr_SetString(AUDError, e.str);
2608 PyDoc_STRVAR(M_aud_Device_listener_orientation_doc,
2609 "The listener's orientation in 3D space as quaternion, a 4 float tuple.");
2612 Device_get_listener_orientation(Device *self, void* nothing)
2616 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2619 AUD_Quaternion o = device->getListenerOrientation();
2620 return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
2624 PyErr_SetString(AUDError, device_not_3d_error);
2627 catch(AUD_Exception& e)
2629 PyErr_SetString(AUDError, e.str);
2636 Device_set_listener_orientation(Device *self, PyObject* args, void* nothing)
2640 if(!PyArg_Parse(args, "(ffff):listener_orientation", &w, &x, &y, &z))
2645 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2648 AUD_Quaternion orientation(w, x, y, z);
2649 device->setListenerOrientation(orientation);
2653 PyErr_SetString(AUDError, device_not_3d_error);
2655 catch(AUD_Exception& e)
2657 PyErr_SetString(AUDError, e.str);
2663 PyDoc_STRVAR(M_aud_Device_speed_of_sound_doc,
2664 "The speed of sound of the device.\n"
2665 "The speed of sound in air is typically 343 m/s.");
2668 Device_get_speed_of_sound(Device *self, void* nothing)
2672 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2675 return Py_BuildValue("f", device->getSpeedOfSound());
2679 PyErr_SetString(AUDError, device_not_3d_error);
2683 catch(AUD_Exception& e)
2685 PyErr_SetString(AUDError, e.str);
2691 Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing)
2695 if(!PyArg_Parse(args, "f:speed_of_sound", &speed))
2700 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2703 device->setSpeedOfSound(speed);
2707 PyErr_SetString(AUDError, device_not_3d_error);
2709 catch(AUD_Exception& e)
2711 PyErr_SetString(AUDError, e.str);
2717 PyDoc_STRVAR(M_aud_Device_doppler_factor_doc,
2718 "The doppler factor of the device.\n"
2719 "This factor is a scaling factor for the velocity vectors in "
2720 "doppler calculation. So a value bigger than 1 will exaggerate "
2721 "the effect as it raises the velocity.");
2724 Device_get_doppler_factor(Device *self, void* nothing)
2728 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2731 return Py_BuildValue("f", device->getDopplerFactor());
2735 PyErr_SetString(AUDError, device_not_3d_error);
2739 catch(AUD_Exception& e)
2741 PyErr_SetString(AUDError, e.str);
2747 Device_set_doppler_factor(Device *self, PyObject* args, void* nothing)
2751 if(!PyArg_Parse(args, "f:doppler_factor", &factor))
2756 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2759 device->setDopplerFactor(factor);
2763 PyErr_SetString(AUDError, device_not_3d_error);
2765 catch(AUD_Exception& e)
2767 PyErr_SetString(AUDError, e.str);
2773 PyDoc_STRVAR(M_aud_Device_distance_model_doc,
2774 "The distance model of the device.\n\n"
2775 ".. seealso:: http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835864");
2778 Device_get_distance_model(Device *self, void* nothing)
2782 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2785 return Py_BuildValue("i", int(device->getDistanceModel()));
2789 PyErr_SetString(AUDError, device_not_3d_error);
2793 catch(AUD_Exception& e)
2795 PyErr_SetString(AUDError, e.str);
2801 Device_set_distance_model(Device *self, PyObject* args, void* nothing)
2805 if(!PyArg_Parse(args, "i:distance_model", &model))
2810 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2813 device->setDistanceModel(AUD_DistanceModel(model));
2817 PyErr_SetString(AUDError, device_not_3d_error);
2819 catch(AUD_Exception& e)
2821 PyErr_SetString(AUDError, e.str);
2827 static PyGetSetDef Device_properties[] = {
2828 {(char*)"rate", (getter)Device_get_rate, NULL,
2829 M_aud_Device_rate_doc, NULL },
2830 {(char*)"format", (getter)Device_get_format, NULL,
2831 M_aud_Device_format_doc, NULL },
2832 {(char*)"channels", (getter)Device_get_channels, NULL,
2833 M_aud_Device_channels_doc, NULL },
2834 {(char*)"volume", (getter)Device_get_volume, (setter)Device_set_volume,
2835 M_aud_Device_volume_doc, NULL },
2836 {(char*)"listener_location", (getter)Device_get_listener_location, (setter)Device_set_listener_location,
2837 M_aud_Device_listener_location_doc, NULL },
2838 {(char*)"listener_velocity", (getter)Device_get_listener_velocity, (setter)Device_set_listener_velocity,
2839 M_aud_Device_listener_velocity_doc, NULL },
2840 {(char*)"listener_orientation", (getter)Device_get_listener_orientation, (setter)Device_set_listener_orientation,
2841 M_aud_Device_listener_orientation_doc, NULL },
2842 {(char*)"speed_of_sound", (getter)Device_get_speed_of_sound, (setter)Device_set_speed_of_sound,
2843 M_aud_Device_speed_of_sound_doc, NULL },
2844 {(char*)"doppler_factor", (getter)Device_get_doppler_factor, (setter)Device_set_doppler_factor,
2845 M_aud_Device_doppler_factor_doc, NULL },
2846 {(char*)"distance_model", (getter)Device_get_distance_model, (setter)Device_set_distance_model,
2847 M_aud_Device_distance_model_doc, NULL },
2848 {NULL} /* Sentinel */
2851 PyDoc_STRVAR(M_aud_Device_doc,
2852 "Device objects represent an audio output backend like OpenAL or "
2853 "SDL, but might also represent a file output or RAM buffer "
2856 static PyTypeObject DeviceType = {
2857 PyVarObject_HEAD_INIT(NULL, 0)
2858 "aud.Device", /* tp_name */
2859 sizeof(Device), /* tp_basicsize */
2860 0, /* tp_itemsize */
2861 (destructor)Device_dealloc,/* tp_dealloc */
2865 0, /* tp_reserved */
2867 0, /* tp_as_number */
2868 0, /* tp_as_sequence */
2869 0, /* tp_as_mapping */
2873 0, /* tp_getattro */
2874 0, /* tp_setattro */
2875 0, /* tp_as_buffer */
2876 Py_TPFLAGS_DEFAULT, /* tp_flags */
2877 M_aud_Device_doc, /* tp_doc */
2878 0, /* tp_traverse */
2880 0, /* tp_richcompare */
2881 0, /* tp_weaklistoffset */
2883 0, /* tp_iternext */
2884 Device_methods, /* tp_methods */
2886 Device_properties, /* tp_getset */
2889 0, /* tp_descr_get */
2890 0, /* tp_descr_set */
2891 0, /* tp_dictoffset */
2894 Device_new, /* tp_new */
2900 return DeviceType.tp_alloc(&DeviceType, 0);
2903 // ====================================================================
2905 PyDoc_STRVAR(M_aud_doc,
2906 "This module provides access to the audaspace audio library.");
2908 static struct PyModuleDef audmodule = {
2909 PyModuleDef_HEAD_INIT,
2910 "aud", /* name of module */
2911 M_aud_doc, /* module documentation */
2912 -1, /* size of per-interpreter state of the module,
2913 or -1 if the module keeps state in global variables. */
2914 NULL, NULL, NULL, NULL, NULL
2922 if(PyType_Ready(&FactoryType) < 0)
2925 if(PyType_Ready(&DeviceType) < 0)
2928 if(PyType_Ready(&HandleType) < 0)
2931 m = PyModule_Create(&audmodule);
2935 Py_INCREF(&FactoryType);
2936 PyModule_AddObject(m, "Factory", (PyObject*)&FactoryType);
2938 Py_INCREF(&DeviceType);
2939 PyModule_AddObject(m, "Device", (PyObject*)&DeviceType);
2941 Py_INCREF(&HandleType);
2942 PyModule_AddObject(m, "Handle", (PyObject*)&HandleType);
2944 AUDError = PyErr_NewException("aud.error", NULL, NULL);
2945 Py_INCREF(AUDError);
2946 PyModule_AddObject(m, "error", AUDError);
2949 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_NULL);
2950 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_OPENAL);
2951 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_SDL);
2952 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_JACK);
2953 //PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_READ);
2955 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT32);
2956 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT64);
2957 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_INVALID);
2958 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S16);
2959 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S24);
2960 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S32);
2961 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_U8);
2963 PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_INVALID);
2964 PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PAUSED);
2965 PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PLAYING);
2966 // distance model constants
2967 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT);
2968 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT_CLAMPED);
2969 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE);
2970 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE_CLAMPED);
2971 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR);
2972 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR_CLAMPED);
2973 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVALID);