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])\n\n"
130 "Creates a sine sound 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.\n"
135 ":return: The created :class:`Factory` object.\n"
136 ":rtype: :class:`Factory`");
139 Factory_sine(PyTypeObject* type, PyObject* args)
144 if(!PyArg_ParseTuple(args, "f|i:sine", &frequency, &rate))
149 self = (Factory*)type->tp_alloc(type, 0);
154 self->factory = new AUD_SinusFactory(frequency, (AUD_SampleRate)rate);
156 catch(AUD_Exception& e)
159 PyErr_SetString(AUDError, e.str);
164 return (PyObject *)self;
167 PyDoc_STRVAR(M_aud_Factory_file_doc,
169 "Creates a sound object of a sound file.\n\n"
170 ":arg filename: Path of the file.\n"
171 ":type filename: string\n"
172 ":return: The created :class:`Factory` object.\n"
173 ":rtype: :class:`Factory`");
176 Factory_file(PyTypeObject* type, PyObject* args)
178 const char* filename = NULL;
180 if(!PyArg_ParseTuple(args, "s:file", &filename))
185 self = (Factory*)type->tp_alloc(type, 0);
190 self->factory = new AUD_FileFactory(filename);
192 catch(AUD_Exception& e)
195 PyErr_SetString(AUDError, e.str);
200 return (PyObject *)self;
203 PyDoc_STRVAR(M_aud_Factory_lowpass_doc,
204 "lowpass(frequency[, Q])\n\n"
205 "Creates a second order lowpass filter.\n\n"
206 ":arg frequency: The cut off trequency of the lowpass.\n"
207 ":type frequency: float\n"
208 ":arg Q: Q factor of the lowpass.\n"
210 ":return: The created :class:`Factory` object.\n"
211 ":rtype: :class:`Factory`");
214 Factory_lowpass(Factory* self, PyObject* args)
219 if(!PyArg_ParseTuple(args, "f|f:lowpass", &frequency, &Q))
222 PyTypeObject* type = ((PyObject*)self)->ob_type;
223 Factory *parent = (Factory*)type->tp_alloc(type, 0);
228 parent->child_list = (PyObject*)self;
232 parent->factory = new AUD_LowpassFactory(self->factory, frequency, Q);
234 catch(AUD_Exception& e)
237 PyErr_SetString(AUDError, e.str);
242 return (PyObject *)parent;
245 PyDoc_STRVAR(M_aud_Factory_delay_doc,
247 "Delays a sound by playing silence before the sound starts.\n\n"
248 ":arg time: How many seconds of silence should be added before the sound.\n"
249 ":type time: float\n"
250 ":return: The created :class:`Factory` object.\n"
251 ":rtype: :class:`Factory`");
254 Factory_delay(Factory* self, PyObject* args)
258 if(!PyArg_ParseTuple(args, "f:delay", &delay))
261 PyTypeObject* type = ((PyObject*)self)->ob_type;
262 Factory *parent = (Factory*)type->tp_alloc(type, 0);
267 parent->child_list = (PyObject*)self;
271 parent->factory = new AUD_DelayFactory(self->factory, delay);
273 catch(AUD_Exception& e)
276 PyErr_SetString(AUDError, e.str);
281 return (PyObject *)parent;
284 PyDoc_STRVAR(M_aud_Factory_join_doc,
286 "Plays two sounds in sequence.\n\n"
287 ":arg sound: The sound to play second.\n"
288 ":type sound: :class:`Factory`\n"
289 ":return: The created :class:`Factory` object.\n"
290 ":rtype: :class:`Factory`\n\n"
291 ".. note:: The two sounds have to have the same specifications "
292 "(channels and samplerate).");
295 Factory_join(Factory* self, PyObject* object)
297 PyTypeObject* type = ((PyObject*)self)->ob_type;
299 if(!PyObject_TypeCheck(object, type))
301 PyErr_SetString(PyExc_TypeError, "Object has to be of type Factory!");
306 Factory *child = (Factory*)object;
308 parent = (Factory*)type->tp_alloc(type, 0);
311 parent->child_list = Py_BuildValue("(OO)", self, object);
315 parent->factory = new AUD_DoubleFactory(self->factory, child->factory);
317 catch(AUD_Exception& e)
320 PyErr_SetString(AUDError, e.str);
325 return (PyObject *)parent;
328 PyDoc_STRVAR(M_aud_Factory_highpass_doc,
329 "highpass(frequency[, Q])\n\n"
330 "Creates a second order highpass filter.\n\n"
331 ":arg frequency: The cut off trequency of the highpass.\n"
332 ":type frequency: float\n"
333 ":arg Q: Q factor of the lowpass.\n"
335 ":return: The created :class:`Factory` object.\n"
336 ":rtype: :class:`Factory`");
339 Factory_highpass(Factory* self, PyObject* args)
344 if(!PyArg_ParseTuple(args, "f|f:highpass", &frequency, &Q))
347 PyTypeObject* type = ((PyObject*)self)->ob_type;
348 Factory *parent = (Factory*)type->tp_alloc(type, 0);
353 parent->child_list = (PyObject*)self;
357 parent->factory = new AUD_HighpassFactory(self->factory, frequency, Q);
359 catch(AUD_Exception& e)
362 PyErr_SetString(AUDError, e.str);
367 return (PyObject *)parent;
370 PyDoc_STRVAR(M_aud_Factory_limit_doc,
371 "limit(start, end)\n\n"
372 "Limits a sound within a specific start and end time.\n\n"
373 ":arg start: Start time in seconds.\n"
374 ":type start: float\n"
375 ":arg end: End time in seconds.\n"
377 ":return: The created :class:`Factory` object.\n"
378 ":rtype: :class:`Factory`");
381 Factory_limit(Factory* self, PyObject* args)
385 if(!PyArg_ParseTuple(args, "ff:limit", &start, &end))
388 PyTypeObject* type = ((PyObject*)self)->ob_type;
389 Factory *parent = (Factory*)type->tp_alloc(type, 0);
394 parent->child_list = (PyObject*)self;
398 parent->factory = new AUD_LimiterFactory(self->factory, start, end);
400 catch(AUD_Exception& e)
403 PyErr_SetString(AUDError, e.str);
408 return (PyObject *)parent;
411 PyDoc_STRVAR(M_aud_Factory_pitch_doc,
413 "Changes the pitch of a sound with a specific factor.\n\n"
414 ":arg factor: The factor to change the pitch with.\n"
415 ":type factor: float\n"
416 ":return: The created :class:`Factory` object.\n"
417 ":rtype: :class:`Factory`\n\n"
418 ".. note:: This is done by changing the sample rate of the "
419 "underlying sound, which has to be an integer, so the factor "
420 "value rounded and the factor may not be 100 % accurate.\n\n"
421 ".. note:: This is a filter function, you might consider using "
422 "Handle.pitch instead.");
425 Factory_pitch(Factory* self, PyObject* args)
429 if(!PyArg_ParseTuple(args, "f:pitch", &factor))
432 PyTypeObject* type = ((PyObject*)self)->ob_type;
433 Factory *parent = (Factory*)type->tp_alloc(type, 0);
438 parent->child_list = (PyObject*)self;
442 parent->factory = new AUD_PitchFactory(self->factory, factor);
444 catch(AUD_Exception& e)
447 PyErr_SetString(AUDError, e.str);
452 return (PyObject *)parent;
455 PyDoc_STRVAR(M_aud_Factory_volume_doc,
457 "Changes the volume of a sound.\n\n"
458 ":arg volume: The new volume..\n"
459 ":type volume: float\n"
460 ":return: The created :class:`Factory` object.\n"
461 ":rtype: :class:`Factory`\n\n"
462 ".. note:: Should be in the range [0, 1] to avoid clipping.\n\n"
463 ".. note:: This is a filter function, you might consider using "
464 "Handle.volume instead.");
467 Factory_volume(Factory* self, PyObject* args)
471 if(!PyArg_ParseTuple(args, "f:volume", &volume))
474 PyTypeObject* type = ((PyObject*)self)->ob_type;
475 Factory *parent = (Factory*)type->tp_alloc(type, 0);
480 parent->child_list = (PyObject*)self;
484 parent->factory = new AUD_VolumeFactory(self->factory, volume);
486 catch(AUD_Exception& e)
489 PyErr_SetString(AUDError, e.str);
494 return (PyObject *)parent;
497 PyDoc_STRVAR(M_aud_Factory_fadein_doc,
498 "fadein(start, length)\n\n"
499 "Fades a sound in.\n\n"
500 ":arg start: Time in seconds when the fading should start.\n"
501 ":type start: float\n"
502 ":arg length: Time in seconds how long the fading should last.\n"
503 ":type length: float\n"
504 ":return: The created :class:`Factory` object.\n"
505 ":rtype: :class:`Factory`");
508 Factory_fadein(Factory* self, PyObject* args)
512 if(!PyArg_ParseTuple(args, "ff:fadein", &start, &length))
515 PyTypeObject* type = ((PyObject*)self)->ob_type;
516 Factory *parent = (Factory*)type->tp_alloc(type, 0);
521 parent->child_list = (PyObject*)self;
525 parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_IN, start, length);
527 catch(AUD_Exception& e)
530 PyErr_SetString(AUDError, e.str);
535 return (PyObject *)parent;
538 PyDoc_STRVAR(M_aud_Factory_fadeout_doc,
539 "fadeout(start, length)\n\n"
540 "Fades a sound out.\n\n"
541 ":arg start: Time in seconds when the fading should start.\n"
542 ":type start: float\n"
543 ":arg length: Time in seconds how long the fading should last.\n"
544 ":type length: float\n"
545 ":return: The created :class:`Factory` object.\n"
546 ":rtype: :class:`Factory`");
549 Factory_fadeout(Factory* self, PyObject* args)
553 if(!PyArg_ParseTuple(args, "ff:fadeout", &start, &length))
556 PyTypeObject* type = ((PyObject*)self)->ob_type;
557 Factory *parent = (Factory*)type->tp_alloc(type, 0);
562 parent->child_list = (PyObject*)self;
566 parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_OUT, start, length);
568 catch(AUD_Exception& e)
571 PyErr_SetString(AUDError, e.str);
576 return (PyObject *)parent;
579 PyDoc_STRVAR(M_aud_Factory_loop_doc,
582 ":arg count: How often the sound should be looped. "
583 "Negative values mean endlessly.\n"
584 ":type count: integer\n"
585 ":return: The created :class:`Factory` object.\n"
586 ":rtype: :class:`Factory`");
589 Factory_loop(Factory* self, PyObject* args)
593 if(!PyArg_ParseTuple(args, "i:loop", &loop))
596 PyTypeObject* type = ((PyObject*)self)->ob_type;
597 Factory *parent = (Factory*)type->tp_alloc(type, 0);
602 parent->child_list = (PyObject*)self;
606 parent->factory = new AUD_LoopFactory(self->factory, loop);
608 catch(AUD_Exception& e)
611 PyErr_SetString(AUDError, e.str);
616 return (PyObject *)parent;
619 PyDoc_STRVAR(M_aud_Factory_mix_doc,
621 "Mixes two sounds.\n\n"
622 ":arg sound: The sound to mix over the other.\n"
623 ":type sound: :class:`Factory`\n"
624 ":return: The created :class:`Factory` object.\n"
625 ":rtype: :class:`Factory`\n\n"
626 ".. note:: The two sounds have to have the same specifications "
627 "(channels and samplerate).");
630 Factory_mix(Factory* self, PyObject* object)
632 PyTypeObject* type = ((PyObject*)self)->ob_type;
634 if(!PyObject_TypeCheck(object, type))
636 PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
640 Factory *parent = (Factory*)type->tp_alloc(type, 0);
641 Factory *child = (Factory*)object;
645 parent->child_list = Py_BuildValue("(OO)", self, object);
649 parent->factory = new AUD_SuperposeFactory(self->factory, child->factory);
651 catch(AUD_Exception& e)
654 PyErr_SetString(AUDError, e.str);
659 return (PyObject *)parent;
662 PyDoc_STRVAR(M_aud_Factory_pingpong_doc,
664 "Plays a sound forward and then backward.\n\n"
665 ":return: The created :class:`Factory` object.\n"
666 ":rtype: :class:`Factory`");
669 Factory_pingpong(Factory* self)
671 PyTypeObject* type = ((PyObject*)self)->ob_type;
672 Factory *parent = (Factory*)type->tp_alloc(type, 0);
677 parent->child_list = (PyObject*)self;
681 parent->factory = new AUD_PingPongFactory(self->factory);
683 catch(AUD_Exception& e)
686 PyErr_SetString(AUDError, e.str);
691 return (PyObject *)parent;
694 PyDoc_STRVAR(M_aud_Factory_reverse_doc,
696 "Plays a sound reversed.\n\n"
697 ":return: The created :class:`Factory` object.\n"
698 ":rtype: :class:`Factory`\n\n"
699 ".. note:: The sound has have a finite length and be seekable. "
700 "It's recommended to buffer sounds that should be played reversed.");
703 Factory_reverse(Factory* self)
705 PyTypeObject* type = ((PyObject*)self)->ob_type;
706 Factory *parent = (Factory*)type->tp_alloc(type, 0);
711 parent->child_list = (PyObject*)self;
715 parent->factory = new AUD_ReverseFactory(self->factory);
717 catch(AUD_Exception& e)
720 PyErr_SetString(AUDError, e.str);
725 return (PyObject *)parent;
728 PyDoc_STRVAR(M_aud_Factory_buffer_doc,
730 "Buffers a sound into RAM.\n\n"
731 ":return: The created :class:`Factory` object.\n"
732 ":rtype: :class:`Factory`\n\n"
733 ".. note:: Raw PCM data needs a lot of space, only buffer short sounds.");
736 Factory_buffer(Factory* self)
738 PyTypeObject* type = ((PyObject*)self)->ob_type;
739 Factory *parent = (Factory*)type->tp_alloc(type, 0);
745 parent->factory = new AUD_StreamBufferFactory(self->factory);
747 catch(AUD_Exception& e)
750 PyErr_SetString(AUDError, e.str);
755 return (PyObject *)parent;
758 PyDoc_STRVAR(M_aud_Factory_square_doc,
759 "squre([threshold = 0])\n\n"
760 "Makes a square wave out of an audio wave.\n\n"
761 ":arg threshold: Threshold value over which an amplitude counts non-zero.\n"
762 ":type threshold: float\n"
763 ":return: The created :class:`Factory` object.\n"
764 ":rtype: :class:`Factory`");
767 Factory_square(Factory* self, PyObject* args)
771 if(!PyArg_ParseTuple(args, "|f:square", &threshold))
774 PyTypeObject* type = ((PyObject*)self)->ob_type;
775 Factory *parent = (Factory*)type->tp_alloc(type, 0);
780 parent->child_list = (PyObject*)self;
784 parent->factory = new AUD_SquareFactory(self->factory, threshold);
786 catch(AUD_Exception& e)
789 PyErr_SetString(AUDError, e.str);
794 return (PyObject *)parent;
797 PyDoc_STRVAR(M_aud_Factory_filter_doc,
798 "filter(b[, a = (1)])\n\n"
799 "Filters a sound with the supplied IIR filter coefficients.\n\n"
800 ":arg b: The nominator filter coefficients.\n"
801 ":type b: sequence of float\n"
802 ":arg a: The denominator filter coefficients.\n"
803 ":type a: sequence of float\n"
804 ":return: The created :class:`Factory` object.\n"
805 ":rtype: :class:`Factory`");
808 Factory_filter(Factory* self, PyObject* args)
811 PyObject* py_a = NULL;
813 if(!PyArg_ParseTuple(args, "O|O:filter", &py_b, &py_a))
816 if(!PySequence_Check(py_b) || (py_a != NULL && !PySequence_Check(py_a)))
818 PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
822 if(!PySequence_Length(py_b) || (py_a != NULL && !PySequence_Length(py_a)))
824 PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
828 std::vector<float> a, b;
833 for(int i = 0; i < PySequence_Length(py_b); i++)
835 py_value = PySequence_GetItem(py_b, i);
836 result = PyArg_Parse(py_value, "f:filter", &value);
847 for(int i = 0; i < PySequence_Length(py_a); i++)
849 py_value = PySequence_GetItem(py_a, i);
850 result = PyArg_Parse(py_value, "f:filter", &value);
865 PyTypeObject* type = ((PyObject*)self)->ob_type;
866 Factory *parent = (Factory*)type->tp_alloc(type, 0);
871 parent->child_list = (PyObject*)self;
875 parent->factory = new AUD_IIRFilterFactory(self->factory, b, a);
877 catch(AUD_Exception& e)
880 PyErr_SetString(AUDError, e.str);
885 return (PyObject *)parent;
888 static PyMethodDef Factory_methods[] = {
889 {"sine", (PyCFunction)Factory_sine, METH_VARARGS | METH_CLASS,
890 M_aud_Factory_sine_doc
892 {"file", (PyCFunction)Factory_file, METH_VARARGS | METH_CLASS,
893 M_aud_Factory_file_doc
895 {"lowpass", (PyCFunction)Factory_lowpass, METH_VARARGS,
896 M_aud_Factory_lowpass_doc
898 {"delay", (PyCFunction)Factory_delay, METH_VARARGS,
899 M_aud_Factory_delay_doc
901 {"join", (PyCFunction)Factory_join, METH_O,
902 M_aud_Factory_join_doc
904 {"highpass", (PyCFunction)Factory_highpass, METH_VARARGS,
905 M_aud_Factory_highpass_doc
907 {"limit", (PyCFunction)Factory_limit, METH_VARARGS,
908 M_aud_Factory_limit_doc
910 {"pitch", (PyCFunction)Factory_pitch, METH_VARARGS,
911 M_aud_Factory_pitch_doc
913 {"volume", (PyCFunction)Factory_volume, METH_VARARGS,
914 M_aud_Factory_volume_doc
916 {"fadein", (PyCFunction)Factory_fadein, METH_VARARGS,
917 M_aud_Factory_fadein_doc
919 {"fadeout", (PyCFunction)Factory_fadeout, METH_VARARGS,
920 M_aud_Factory_fadeout_doc
922 {"loop", (PyCFunction)Factory_loop, METH_VARARGS,
923 M_aud_Factory_loop_doc
925 {"mix", (PyCFunction)Factory_mix, METH_O,
926 M_aud_Factory_mix_doc
928 {"pingpong", (PyCFunction)Factory_pingpong, METH_NOARGS,
929 M_aud_Factory_pingpong_doc
931 {"reverse", (PyCFunction)Factory_reverse, METH_NOARGS,
932 M_aud_Factory_reverse_doc
934 {"buffer", (PyCFunction)Factory_buffer, METH_NOARGS,
935 M_aud_Factory_buffer_doc
937 {"square", (PyCFunction)Factory_square, METH_VARARGS,
938 M_aud_Factory_square_doc
940 {"filter", (PyCFunction)Factory_filter, METH_VARARGS,
941 M_aud_Factory_filter_doc
943 {NULL} /* Sentinel */
946 PyDoc_STRVAR(M_aud_Factory_doc,
947 "Factory objects are immutable and represent a sound that can be "
948 "played simultaneously multiple times.");
950 static PyTypeObject FactoryType = {
951 PyVarObject_HEAD_INIT(NULL, 0)
952 "aud.Factory", /* tp_name */
953 sizeof(Factory), /* tp_basicsize */
955 (destructor)Factory_dealloc, /* tp_dealloc */
961 0, /* tp_as_number */
962 0, /* tp_as_sequence */
963 0, /* tp_as_mapping */
969 0, /* tp_as_buffer */
970 Py_TPFLAGS_DEFAULT, /* tp_flags */
971 M_aud_Factory_doc, /* tp_doc */
974 0, /* tp_richcompare */
975 0, /* tp_weaklistoffset */
978 Factory_methods, /* tp_methods */
983 0, /* tp_descr_get */
984 0, /* tp_descr_set */
985 0, /* tp_dictoffset */
988 Factory_new, /* tp_new */
991 // ========== Handle ==================================================
994 Handle_dealloc(Handle* self)
996 Py_XDECREF(self->device);
997 Py_TYPE(self)->tp_free((PyObject*)self);
1000 PyDoc_STRVAR(M_aud_Handle_pause_doc,
1002 "Pauses playback.\n\n"
1003 ":return: Whether the action succeeded.\n"
1007 Handle_pause(Handle *self)
1009 Device* device = (Device*)self->device;
1013 if(device->device->pause(self->handle))
1018 catch(AUD_Exception& e)
1020 PyErr_SetString(AUDError, e.str);
1027 PyDoc_STRVAR(M_aud_Handle_resume_doc,
1029 "Resumes playback.\n\n"
1030 ":return: Whether the action succeeded.\n"
1034 Handle_resume(Handle *self)
1036 Device* device = (Device*)self->device;
1040 if(device->device->resume(self->handle))
1045 catch(AUD_Exception& e)
1047 PyErr_SetString(AUDError, e.str);
1054 PyDoc_STRVAR(M_aud_Handle_stop_doc,
1056 "Stops playback.\n\n"
1057 ":return: Whether the action succeeded.\n"
1061 Handle_stop(Handle *self)
1063 Device* device = (Device*)self->device;
1067 if(device->device->stop(self->handle))
1072 catch(AUD_Exception& e)
1074 PyErr_SetString(AUDError, e.str);
1081 static PyMethodDef Handle_methods[] = {
1082 {"pause", (PyCFunction)Handle_pause, METH_NOARGS,
1083 M_aud_Handle_pause_doc
1085 {"resume", (PyCFunction)Handle_resume, METH_NOARGS,
1086 M_aud_Handle_resume_doc
1088 {"stop", (PyCFunction)Handle_stop, METH_NOARGS,
1089 M_aud_Handle_stop_doc
1091 {NULL} /* Sentinel */
1094 PyDoc_STRVAR(M_aud_Handle_position_doc,
1095 "The playback position of the sound.");
1098 Handle_get_position(Handle *self, void* nothing)
1100 Device* device = (Device*)self->device;
1104 return Py_BuildValue("f", device->device->getPosition(self->handle));
1106 catch(AUD_Exception& e)
1108 PyErr_SetString(AUDError, e.str);
1114 Handle_set_position(Handle *self, PyObject* args, void* nothing)
1118 if(!PyArg_Parse(args, "f:position", &position))
1121 Device* device = (Device*)self->device;
1125 if(device->device->seek(self->handle, position))
1127 PyErr_SetString(AUDError, "Couldn't seek the sound!");
1129 catch(AUD_Exception& e)
1131 PyErr_SetString(AUDError, e.str);
1137 PyDoc_STRVAR(M_aud_Handle_keep_doc,
1138 "Whether the sound should be kept paused in the device when its end is reached.");
1141 Handle_get_keep(Handle *self, void* nothing)
1143 Device* device = (Device*)self->device;
1147 if(device->device->getKeep(self->handle))
1156 catch(AUD_Exception& e)
1158 PyErr_SetString(AUDError, e.str);
1164 Handle_set_keep(Handle *self, PyObject* args, void* nothing)
1166 if(!PyBool_Check(args))
1168 PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
1172 bool keep = args == Py_True;
1173 Device* device = (Device*)self->device;
1177 if(device->device->setKeep(self->handle, keep))
1179 PyErr_SetString(AUDError, "Couldn't set keep of the sound!");
1181 catch(AUD_Exception& e)
1183 PyErr_SetString(AUDError, e.str);
1189 PyDoc_STRVAR(M_aud_Handle_status_doc,
1190 "Whether the sound is playing, paused or stopped.");
1193 Handle_get_status(Handle *self, void* nothing)
1195 Device* device = (Device*)self->device;
1199 return Py_BuildValue("i", device->device->getStatus(self->handle));
1201 catch(AUD_Exception& e)
1203 PyErr_SetString(AUDError, e.str);
1208 PyDoc_STRVAR(M_aud_Handle_volume_doc,
1209 "The volume of the sound.");
1212 Handle_get_volume(Handle *self, void* nothing)
1214 Device* device = (Device*)self->device;
1218 return Py_BuildValue("f", device->device->getVolume(self->handle));
1220 catch(AUD_Exception& e)
1222 PyErr_SetString(AUDError, e.str);
1228 Handle_set_volume(Handle *self, PyObject* args, void* nothing)
1232 if(!PyArg_Parse(args, "f:volume", &volume))
1235 Device* device = (Device*)self->device;
1239 if(device->device->setVolume(self->handle, volume))
1241 PyErr_SetString(AUDError, "Couldn't set the sound volume!");
1243 catch(AUD_Exception& e)
1245 PyErr_SetString(AUDError, e.str);
1251 PyDoc_STRVAR(M_aud_Handle_pitch_doc,
1252 "The pitch of the sound.");
1255 Handle_get_pitch(Handle *self, void* nothing)
1257 Device* device = (Device*)self->device;
1261 return Py_BuildValue("f", device->device->getPitch(self->handle));
1263 catch(AUD_Exception& e)
1265 PyErr_SetString(AUDError, e.str);
1271 Handle_set_pitch(Handle *self, PyObject* args, void* nothing)
1275 if(!PyArg_Parse(args, "f:pitch", &pitch))
1278 Device* device = (Device*)self->device;
1282 if(device->device->setPitch(self->handle, pitch))
1284 PyErr_SetString(AUDError, "Couldn't set the sound pitch!");
1286 catch(AUD_Exception& e)
1288 PyErr_SetString(AUDError, e.str);
1294 PyDoc_STRVAR(M_aud_Handle_loop_count_doc,
1295 "The (remaining) loop count of the sound. A negative value indicates infinity.");
1298 Handle_get_loop_count(Handle *self, void* nothing)
1300 Device* device = (Device*)self->device;
1304 return Py_BuildValue("i", device->device->getLoopCount(self->handle));
1306 catch(AUD_Exception& e)
1308 PyErr_SetString(AUDError, e.str);
1314 Handle_set_loop_count(Handle *self, PyObject* args, void* nothing)
1318 if(!PyArg_Parse(args, "i:loop_count", &loops))
1321 Device* device = (Device*)self->device;
1325 if(device->device->setLoopCount(self->handle, loops))
1327 PyErr_SetString(AUDError, "Couldn't set the loop count!");
1329 catch(AUD_Exception& e)
1331 PyErr_SetString(AUDError, e.str);
1337 PyDoc_STRVAR(M_aud_Handle_location_doc,
1338 "The source's location in 3D space, a 3D tuple of floats.");
1341 Handle_get_location(Handle *self, void* nothing)
1343 Device* dev = (Device*)self->device;
1347 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1350 AUD_Vector3 v = device->getSourceLocation(self->handle);
1351 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
1355 PyErr_SetString(AUDError, device_not_3d_error);
1358 catch(AUD_Exception& e)
1360 PyErr_SetString(AUDError, e.str);
1367 Handle_set_location(Handle *self, PyObject* args, void* nothing)
1371 if(!PyArg_Parse(args, "(fff):location", &x, &y, &z))
1374 Device* dev = (Device*)self->device;
1378 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1381 AUD_Vector3 location(x, y, z);
1382 if(device->setSourceLocation(self->handle, location))
1384 PyErr_SetString(AUDError, "Location couldn't be set!");
1387 PyErr_SetString(AUDError, device_not_3d_error);
1389 catch(AUD_Exception& e)
1391 PyErr_SetString(AUDError, e.str);
1397 PyDoc_STRVAR(M_aud_Handle_velocity_doc,
1398 "The source's velocity in 3D space, a 3D tuple of floats.");
1401 Handle_get_velocity(Handle *self, void* nothing)
1403 Device* dev = (Device*)self->device;
1407 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1410 AUD_Vector3 v = device->getSourceVelocity(self->handle);
1411 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
1415 PyErr_SetString(AUDError, device_not_3d_error);
1418 catch(AUD_Exception& e)
1420 PyErr_SetString(AUDError, e.str);
1427 Handle_set_velocity(Handle *self, PyObject* args, void* nothing)
1431 if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z))
1434 Device* dev = (Device*)self->device;
1438 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1441 AUD_Vector3 velocity(x, y, z);
1442 if(device->setSourceVelocity(self->handle, velocity))
1444 PyErr_SetString(AUDError, "Couldn't set the velocity!");
1447 PyErr_SetString(AUDError, device_not_3d_error);
1449 catch(AUD_Exception& e)
1451 PyErr_SetString(AUDError, e.str);
1457 PyDoc_STRVAR(M_aud_Handle_orientation_doc,
1458 "The source's orientation in 3D space as quaternion, a 4 float tuple.");
1461 Handle_get_orientation(Handle *self, void* nothing)
1463 Device* dev = (Device*)self->device;
1467 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1470 AUD_Quaternion o = device->getSourceOrientation(self->handle);
1471 return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
1475 PyErr_SetString(AUDError, device_not_3d_error);
1478 catch(AUD_Exception& e)
1480 PyErr_SetString(AUDError, e.str);
1487 Handle_set_orientation(Handle *self, PyObject* args, void* nothing)
1491 if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z))
1494 Device* dev = (Device*)self->device;
1498 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1501 AUD_Quaternion orientation(w, x, y, z);
1502 if(device->setSourceOrientation(self->handle, orientation))
1504 PyErr_SetString(AUDError, "Couldn't set the orientation!");
1507 PyErr_SetString(AUDError, device_not_3d_error);
1509 catch(AUD_Exception& e)
1511 PyErr_SetString(AUDError, e.str);
1517 PyDoc_STRVAR(M_aud_Handle_relative_doc,
1518 "Whether the source's location, velocity and orientation is relative or absolute to the listener.");
1521 Handle_get_relative(Handle *self, void* nothing)
1523 Device* dev = (Device*)self->device;
1527 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1530 if(device->isRelative(self->handle))
1541 PyErr_SetString(AUDError, device_not_3d_error);
1544 catch(AUD_Exception& e)
1546 PyErr_SetString(AUDError, e.str);
1553 Handle_set_relative(Handle *self, PyObject* args, void* nothing)
1555 if(!PyBool_Check(args))
1557 PyErr_SetString(PyExc_TypeError, "Value is not a boolean!");
1561 bool relative = (args == Py_True);
1562 Device* dev = (Device*)self->device;
1566 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1569 if(device->setRelative(self->handle, relative))
1571 PyErr_SetString(AUDError, "Couldn't set the relativeness!");
1574 PyErr_SetString(AUDError, device_not_3d_error);
1576 catch(AUD_Exception& e)
1578 PyErr_SetString(AUDError, e.str);
1584 PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc,
1585 "The minimum volume of the source.");
1588 Handle_get_volume_minimum(Handle *self, void* nothing)
1590 Device* dev = (Device*)self->device;
1594 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1597 return Py_BuildValue("f", device->getVolumeMinimum(self->handle));
1601 PyErr_SetString(AUDError, device_not_3d_error);
1605 catch(AUD_Exception& e)
1607 PyErr_SetString(AUDError, e.str);
1613 Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing)
1617 if(!PyArg_Parse(args, "f:volume_minimum", &volume))
1620 Device* dev = (Device*)self->device;
1624 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1627 if(device->setVolumeMinimum(self->handle, volume))
1629 PyErr_SetString(AUDError, "Couldn't set the minimum volume!");
1632 PyErr_SetString(AUDError, device_not_3d_error);
1634 catch(AUD_Exception& e)
1636 PyErr_SetString(AUDError, e.str);
1642 PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc,
1643 "The maximum volume of the source.");
1646 Handle_get_volume_maximum(Handle *self, void* nothing)
1648 Device* dev = (Device*)self->device;
1652 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1655 return Py_BuildValue("f", device->getVolumeMaximum(self->handle));
1659 PyErr_SetString(AUDError, device_not_3d_error);
1663 catch(AUD_Exception& e)
1665 PyErr_SetString(AUDError, e.str);
1671 Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing)
1675 if(!PyArg_Parse(args, "f:volume_maximum", &volume))
1678 Device* dev = (Device*)self->device;
1682 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1685 if(device->setVolumeMaximum(self->handle, volume))
1687 PyErr_SetString(AUDError, "Couldn't set the maximum volume!");
1690 PyErr_SetString(AUDError, device_not_3d_error);
1692 catch(AUD_Exception& e)
1694 PyErr_SetString(AUDError, e.str);
1700 PyDoc_STRVAR(M_aud_Handle_distance_reference_doc,
1701 "The reference distance of the source.");
1704 Handle_get_distance_reference(Handle *self, void* nothing)
1706 Device* dev = (Device*)self->device;
1710 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1713 return Py_BuildValue("f", device->getDistanceReference(self->handle));
1717 PyErr_SetString(AUDError, device_not_3d_error);
1721 catch(AUD_Exception& e)
1723 PyErr_SetString(AUDError, e.str);
1729 Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing)
1733 if(!PyArg_Parse(args, "f:distance_reference", &distance))
1736 Device* dev = (Device*)self->device;
1740 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1743 if(device->setDistanceReference(self->handle, distance))
1745 PyErr_SetString(AUDError, "Couldn't set the reference distance!");
1748 PyErr_SetString(AUDError, device_not_3d_error);
1750 catch(AUD_Exception& e)
1752 PyErr_SetString(AUDError, e.str);
1758 PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc,
1759 "The maximum distance of the source.");
1762 Handle_get_distance_maximum(Handle *self, void* nothing)
1764 Device* dev = (Device*)self->device;
1768 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1771 return Py_BuildValue("f", device->getDistanceMaximum(self->handle));
1775 PyErr_SetString(AUDError, device_not_3d_error);
1779 catch(AUD_Exception& e)
1781 PyErr_SetString(AUDError, e.str);
1787 Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing)
1791 if(!PyArg_Parse(args, "f:distance_maximum", &distance))
1794 Device* dev = (Device*)self->device;
1798 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1801 if(device->setDistanceMaximum(self->handle, distance))
1803 PyErr_SetString(AUDError, "Couldn't set the maximum distance!");
1806 PyErr_SetString(AUDError, device_not_3d_error);
1808 catch(AUD_Exception& e)
1810 PyErr_SetString(AUDError, e.str);
1816 PyDoc_STRVAR(M_aud_Handle_attenuation_doc,
1817 "The attenuation of the source.");
1820 Handle_get_attenuation(Handle *self, void* nothing)
1822 Device* dev = (Device*)self->device;
1826 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1829 return Py_BuildValue("f", device->getAttenuation(self->handle));
1833 PyErr_SetString(AUDError, device_not_3d_error);
1837 catch(AUD_Exception& e)
1839 PyErr_SetString(AUDError, e.str);
1845 Handle_set_attenuation(Handle *self, PyObject* args, void* nothing)
1849 if(!PyArg_Parse(args, "f:attenuation", &factor))
1852 Device* dev = (Device*)self->device;
1856 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1859 if(device->setAttenuation(self->handle, factor))
1861 PyErr_SetString(AUDError, "Couldn't set the attenuation!");
1864 PyErr_SetString(AUDError, device_not_3d_error);
1866 catch(AUD_Exception& e)
1868 PyErr_SetString(AUDError, e.str);
1874 PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc,
1875 "The cone inner angle of the source.");
1878 Handle_get_cone_angle_inner(Handle *self, void* nothing)
1880 Device* dev = (Device*)self->device;
1884 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1887 return Py_BuildValue("f", device->getConeAngleInner(self->handle));
1891 PyErr_SetString(AUDError, device_not_3d_error);
1895 catch(AUD_Exception& e)
1897 PyErr_SetString(AUDError, e.str);
1903 Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing)
1907 if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
1910 Device* dev = (Device*)self->device;
1914 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1917 if(device->setConeAngleInner(self->handle, angle))
1919 PyErr_SetString(AUDError, "Couldn't set the cone inner angle!");
1922 PyErr_SetString(AUDError, device_not_3d_error);
1924 catch(AUD_Exception& e)
1926 PyErr_SetString(AUDError, e.str);
1932 PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc,
1933 "The cone outer angle of the source.");
1936 Handle_get_cone_angle_outer(Handle *self, void* nothing)
1938 Device* dev = (Device*)self->device;
1942 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1945 return Py_BuildValue("f", device->getConeAngleOuter(self->handle));
1949 PyErr_SetString(AUDError, device_not_3d_error);
1953 catch(AUD_Exception& e)
1955 PyErr_SetString(AUDError, e.str);
1961 Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing)
1965 if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
1968 Device* dev = (Device*)self->device;
1972 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1975 if(device->setConeAngleOuter(self->handle, angle))
1977 PyErr_SetString(AUDError, "Couldn't set the cone outer angle!");
1980 PyErr_SetString(AUDError, device_not_3d_error);
1982 catch(AUD_Exception& e)
1984 PyErr_SetString(AUDError, e.str);
1990 PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc,
1991 "The cone outer volume of the source.");
1994 Handle_get_cone_volume_outer(Handle *self, void* nothing)
1996 Device* dev = (Device*)self->device;
2000 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2003 return Py_BuildValue("f", device->getConeVolumeOuter(self->handle));
2007 PyErr_SetString(AUDError, device_not_3d_error);
2011 catch(AUD_Exception& e)
2013 PyErr_SetString(AUDError, e.str);
2019 Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing)
2023 if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
2026 Device* dev = (Device*)self->device;
2030 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2033 if(device->setConeVolumeOuter(self->handle, volume))
2035 PyErr_SetString(AUDError, "Couldn't set the cone outer volume!");
2038 PyErr_SetString(AUDError, device_not_3d_error);
2040 catch(AUD_Exception& e)
2042 PyErr_SetString(AUDError, e.str);
2048 static PyGetSetDef Handle_properties[] = {
2049 {(char*)"position", (getter)Handle_get_position, (setter)Handle_set_position,
2050 M_aud_Handle_position_doc, NULL },
2051 {(char*)"keep", (getter)Handle_get_keep, (setter)Handle_set_keep,
2052 M_aud_Handle_keep_doc, NULL },
2053 {(char*)"status", (getter)Handle_get_status, NULL,
2054 M_aud_Handle_status_doc, NULL },
2055 {(char*)"volume", (getter)Handle_get_volume, (setter)Handle_set_volume,
2056 M_aud_Handle_volume_doc, NULL },
2057 {(char*)"pitch", (getter)Handle_get_pitch, (setter)Handle_set_pitch,
2058 M_aud_Handle_pitch_doc, NULL },
2059 {(char*)"loop_count", (getter)Handle_get_loop_count, (setter)Handle_set_loop_count,
2060 M_aud_Handle_loop_count_doc, NULL },
2061 {(char*)"location", (getter)Handle_get_location, (setter)Handle_set_location,
2062 M_aud_Handle_location_doc, NULL },
2063 {(char*)"velocity", (getter)Handle_get_velocity, (setter)Handle_set_velocity,
2064 M_aud_Handle_velocity_doc, NULL },
2065 {(char*)"orientation", (getter)Handle_get_orientation, (setter)Handle_set_orientation,
2066 M_aud_Handle_orientation_doc, NULL },
2067 {(char*)"relative", (getter)Handle_get_relative, (setter)Handle_set_relative,
2068 M_aud_Handle_relative_doc, NULL },
2069 {(char*)"volume_minimum", (getter)Handle_get_volume_minimum, (setter)Handle_set_volume_minimum,
2070 M_aud_Handle_volume_minimum_doc, NULL },
2071 {(char*)"volume_maximum", (getter)Handle_get_volume_maximum, (setter)Handle_set_volume_maximum,
2072 M_aud_Handle_volume_maximum_doc, NULL },
2073 {(char*)"distance_reference", (getter)Handle_get_distance_reference, (setter)Handle_set_distance_reference,
2074 M_aud_Handle_distance_reference_doc, NULL },
2075 {(char*)"distance_maximum", (getter)Handle_get_distance_maximum, (setter)Handle_set_distance_maximum,
2076 M_aud_Handle_distance_maximum_doc, NULL },
2077 {(char*)"attenuation", (getter)Handle_get_attenuation, (setter)Handle_set_attenuation,
2078 M_aud_Handle_attenuation_doc, NULL },
2079 {(char*)"cone_angle_inner", (getter)Handle_get_cone_angle_inner, (setter)Handle_set_cone_angle_inner,
2080 M_aud_Handle_cone_angle_inner_doc, NULL },
2081 {(char*)"cone_angle_outer", (getter)Handle_get_cone_angle_outer, (setter)Handle_set_cone_angle_outer,
2082 M_aud_Handle_cone_angle_outer_doc, NULL },
2083 {(char*)"cone_volume_outer", (getter)Handle_get_cone_volume_outer, (setter)Handle_set_cone_volume_outer,
2084 M_aud_Handle_cone_volume_outer_doc, NULL },
2085 {NULL} /* Sentinel */
2088 PyDoc_STRVAR(M_aud_Handle_doc,
2089 "Handle objects are playback handles that can be used to control "
2090 "playback of a sound. If a sound is played back multiple times "
2091 "then there are as many handles.");
2093 static PyTypeObject HandleType = {
2094 PyVarObject_HEAD_INIT(NULL, 0)
2095 "aud.Handle", /* tp_name */
2096 sizeof(Handle), /* tp_basicsize */
2097 0, /* tp_itemsize */
2098 (destructor)Handle_dealloc,/* tp_dealloc */
2102 0, /* tp_reserved */
2104 0, /* tp_as_number */
2105 0, /* tp_as_sequence */
2106 0, /* tp_as_mapping */
2110 0, /* tp_getattro */
2111 0, /* tp_setattro */
2112 0, /* tp_as_buffer */
2113 Py_TPFLAGS_DEFAULT, /* tp_flags */
2114 M_aud_Handle_doc, /* tp_doc */
2115 0, /* tp_traverse */
2117 0, /* tp_richcompare */
2118 0, /* tp_weaklistoffset */
2120 0, /* tp_iternext */
2121 Handle_methods, /* tp_methods */
2123 Handle_properties, /* tp_getset */
2126 0, /* tp_descr_get */
2127 0, /* tp_descr_set */
2128 0, /* tp_dictoffset */
2134 // ========== Device ==================================================
2137 Device_dealloc(Device* self)
2140 delete self->device;
2141 Py_TYPE(self)->tp_free((PyObject*)self);
2145 Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2149 static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL};
2151 int rate = AUD_RATE_44100;
2152 int channels = AUD_CHANNELS_STEREO;
2153 int format = AUD_FORMAT_FLOAT32;
2154 int buffersize = AUD_DEFAULT_BUFFER_SIZE;
2155 const char* name = "Audaspace";
2157 if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiis:Device", const_cast<char**>(kwlist),
2158 &device, &rate, &channels, &format, &buffersize, &name))
2161 if(buffersize < 128)
2163 PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than 127!");
2167 self = (Device*)type->tp_alloc(type, 0);
2170 AUD_DeviceSpecs specs;
2171 specs.channels = (AUD_Channels)channels;
2172 specs.format = (AUD_SampleFormat)format;
2173 specs.rate = (AUD_SampleRate)rate;
2175 self->device = NULL;
2181 case AUD_DEVICE_NULL:
2182 self->device = new AUD_NULLDevice();
2184 case AUD_DEVICE_OPENAL:
2186 self->device = new AUD_OpenALDevice(specs, buffersize);
2189 case AUD_DEVICE_SDL:
2191 self->device = new AUD_SDLDevice(specs, buffersize);
2194 case AUD_DEVICE_JACK:
2196 self->device = new AUD_JackDevice(name, specs, buffersize);
2199 case AUD_DEVICE_READ:
2204 catch(AUD_Exception& e)
2207 PyErr_SetString(AUDError, e.str);
2214 PyErr_SetString(AUDError, "Unsupported device type!");
2219 return (PyObject *)self;
2222 PyDoc_STRVAR(M_aud_Device_play_doc,
2223 "play(sound[, keep])\n\n"
2224 "Plays a sound.\n\n"
2225 ":arg sound: The sound to play.\n"
2226 ":type sound: :class:`Factory`\n"
2227 ":arg keep: Whether the sound should be kept paused in the device when its end is reached.\n"
2228 ":type keep: bool\n"
2229 ":return: The playback handle.\n"
2230 ":rtype: :class:`Handle`");
2233 Device_play(Device *self, PyObject *args, PyObject *kwds)
2236 PyObject* keepo = NULL;
2240 static const char *kwlist[] = {"sound", "keep", NULL};
2242 if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:play", const_cast<char**>(kwlist), &object, &keepo))
2245 if(!PyObject_TypeCheck(object, &FactoryType))
2247 PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
2253 if(!PyBool_Check(keepo))
2255 PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
2259 keep = keepo == Py_True;
2262 Factory* sound = (Factory*)object;
2265 handle = (Handle*)HandleType.tp_alloc(&HandleType, 0);
2268 handle->device = (PyObject*)self;
2273 handle->handle = self->device->play(sound->factory, keep);
2275 catch(AUD_Exception& e)
2278 PyErr_SetString(AUDError, e.str);
2283 return (PyObject *)handle;
2286 PyDoc_STRVAR(M_aud_Device_lock_doc,
2288 "Locks the device so that it's guaranteed, that no samples are "
2289 "read from the streams until the unlock is called. The device has "
2290 "to be unlocked as often as locked to be able to continue "
2291 "playback. Make sure the time between locking and unlocking is as "
2292 "short as possible to avoid clicks.");
2295 Device_lock(Device *self)
2299 self->device->lock();
2302 catch(AUD_Exception& e)
2304 PyErr_SetString(AUDError, e.str);
2309 PyDoc_STRVAR(M_aud_Device_unlock_doc,
2311 "Unlocks the device after a lock call, see lock() for details.");
2314 Device_unlock(Device *self)
2318 self->device->unlock();
2321 catch(AUD_Exception& e)
2323 PyErr_SetString(AUDError, e.str);
2328 static PyMethodDef Device_methods[] = {
2329 {"play", (PyCFunction)Device_play, METH_VARARGS | METH_KEYWORDS,
2330 M_aud_Device_play_doc
2332 {"lock", (PyCFunction)Device_lock, METH_NOARGS,
2333 M_aud_Device_lock_doc
2335 {"unlock", (PyCFunction)Device_unlock, METH_NOARGS,
2336 M_aud_Device_unlock_doc
2338 {NULL} /* Sentinel */
2341 PyDoc_STRVAR(M_aud_Device_rate_doc,
2342 "The sampling rate of the device in Hz.");
2345 Device_get_rate(Device *self, void* nothing)
2349 AUD_DeviceSpecs specs = self->device->getSpecs();
2350 return Py_BuildValue("i", specs.rate);
2352 catch(AUD_Exception& e)
2354 PyErr_SetString(AUDError, e.str);
2359 PyDoc_STRVAR(M_aud_Device_format_doc,
2360 "The native sample format of the device.");
2363 Device_get_format(Device *self, void* nothing)
2367 AUD_DeviceSpecs specs = self->device->getSpecs();
2368 return Py_BuildValue("i", specs.format);
2370 catch(AUD_Exception& e)
2372 PyErr_SetString(AUDError, e.str);
2377 PyDoc_STRVAR(M_aud_Device_channels_doc,
2378 "The channel count of the device.");
2381 Device_get_channels(Device *self, void* nothing)
2385 AUD_DeviceSpecs specs = self->device->getSpecs();
2386 return Py_BuildValue("i", specs.channels);
2388 catch(AUD_Exception& e)
2390 PyErr_SetString(AUDError, e.str);
2395 PyDoc_STRVAR(M_aud_Device_volume_doc,
2396 "The overall volume of the device.");
2399 Device_get_volume(Device *self, void* nothing)
2403 return Py_BuildValue("f", self->device->getVolume());
2405 catch(AUD_Exception& e)
2407 PyErr_SetString(AUDError, e.str);
2413 Device_set_volume(Device *self, PyObject* args, void* nothing)
2417 if(!PyArg_Parse(args, "f:volume", &volume))
2422 self->device->setVolume(volume);
2425 catch(AUD_Exception& e)
2427 PyErr_SetString(AUDError, e.str);
2432 PyDoc_STRVAR(M_aud_Device_listener_location_doc,
2433 "The listeners's location in 3D space, a 3D tuple of floats.");
2436 Device_get_listener_location(Device *self, void* nothing)
2440 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2443 AUD_Vector3 v = device->getListenerLocation();
2444 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
2448 PyErr_SetString(AUDError, device_not_3d_error);
2451 catch(AUD_Exception& e)
2453 PyErr_SetString(AUDError, e.str);
2460 Device_set_listener_location(Device *self, PyObject* args, void* nothing)
2464 if(!PyArg_Parse(args, "(fff):listener_location", &x, &y, &z))
2469 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2472 AUD_Vector3 location(x, y, z);
2473 device->setListenerLocation(location);
2477 PyErr_SetString(AUDError, device_not_3d_error);
2479 catch(AUD_Exception& e)
2481 PyErr_SetString(AUDError, e.str);
2487 PyDoc_STRVAR(M_aud_Device_listener_velocity_doc,
2488 "The listener's velocity in 3D space, a 3D tuple of floats.");
2491 Device_get_listener_velocity(Device *self, void* nothing)
2495 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2498 AUD_Vector3 v = device->getListenerVelocity();
2499 return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
2503 PyErr_SetString(AUDError, device_not_3d_error);
2506 catch(AUD_Exception& e)
2508 PyErr_SetString(AUDError, e.str);
2515 Device_set_listener_velocity(Device *self, PyObject* args, void* nothing)
2519 if(!PyArg_Parse(args, "(fff):listener_velocity", &x, &y, &z))
2524 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2527 AUD_Vector3 velocity(x, y, z);
2528 device->setListenerVelocity(velocity);
2532 PyErr_SetString(AUDError, device_not_3d_error);
2534 catch(AUD_Exception& e)
2536 PyErr_SetString(AUDError, e.str);
2542 PyDoc_STRVAR(M_aud_Device_listener_orientation_doc,
2543 "The listener's orientation in 3D space as quaternion, a 4 float tuple.");
2546 Device_get_listener_orientation(Device *self, void* nothing)
2550 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2553 AUD_Quaternion o = device->getListenerOrientation();
2554 return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
2558 PyErr_SetString(AUDError, device_not_3d_error);
2561 catch(AUD_Exception& e)
2563 PyErr_SetString(AUDError, e.str);
2570 Device_set_listener_orientation(Device *self, PyObject* args, void* nothing)
2574 if(!PyArg_Parse(args, "(ffff):listener_orientation", &w, &x, &y, &z))
2579 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2582 AUD_Quaternion orientation(w, x, y, z);
2583 device->setListenerOrientation(orientation);
2587 PyErr_SetString(AUDError, device_not_3d_error);
2589 catch(AUD_Exception& e)
2591 PyErr_SetString(AUDError, e.str);
2597 PyDoc_STRVAR(M_aud_Device_speed_of_sound_doc,
2598 "The speed of sound of the device.");
2601 Device_get_speed_of_sound(Device *self, void* nothing)
2605 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2608 return Py_BuildValue("f", device->getSpeedOfSound());
2612 PyErr_SetString(AUDError, device_not_3d_error);
2616 catch(AUD_Exception& e)
2618 PyErr_SetString(AUDError, e.str);
2624 Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing)
2628 if(!PyArg_Parse(args, "f:speed_of_sound", &speed))
2633 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2636 device->setSpeedOfSound(speed);
2640 PyErr_SetString(AUDError, device_not_3d_error);
2642 catch(AUD_Exception& e)
2644 PyErr_SetString(AUDError, e.str);
2650 PyDoc_STRVAR(M_aud_Device_doppler_factor_doc,
2651 "The doppler factor of the device.");
2654 Device_get_doppler_factor(Device *self, void* nothing)
2658 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2661 return Py_BuildValue("f", device->getDopplerFactor());
2665 PyErr_SetString(AUDError, device_not_3d_error);
2669 catch(AUD_Exception& e)
2671 PyErr_SetString(AUDError, e.str);
2677 Device_set_doppler_factor(Device *self, PyObject* args, void* nothing)
2681 if(!PyArg_Parse(args, "f:doppler_factor", &factor))
2686 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2689 device->setDopplerFactor(factor);
2693 PyErr_SetString(AUDError, device_not_3d_error);
2695 catch(AUD_Exception& e)
2697 PyErr_SetString(AUDError, e.str);
2703 PyDoc_STRVAR(M_aud_Device_distance_model_doc,
2704 "The distance model of the device.");
2707 Device_get_distance_model(Device *self, void* nothing)
2711 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2714 return Py_BuildValue("i", int(device->getDistanceModel()));
2718 PyErr_SetString(AUDError, device_not_3d_error);
2722 catch(AUD_Exception& e)
2724 PyErr_SetString(AUDError, e.str);
2730 Device_set_distance_model(Device *self, PyObject* args, void* nothing)
2734 if(!PyArg_Parse(args, "i:distance_model", &model))
2739 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2742 device->setDistanceModel(AUD_DistanceModel(model));
2746 PyErr_SetString(AUDError, device_not_3d_error);
2748 catch(AUD_Exception& e)
2750 PyErr_SetString(AUDError, e.str);
2756 static PyGetSetDef Device_properties[] = {
2757 {(char*)"rate", (getter)Device_get_rate, NULL,
2758 M_aud_Device_rate_doc, NULL },
2759 {(char*)"format", (getter)Device_get_format, NULL,
2760 M_aud_Device_format_doc, NULL },
2761 {(char*)"channels", (getter)Device_get_channels, NULL,
2762 M_aud_Device_channels_doc, NULL },
2763 {(char*)"volume", (getter)Device_get_volume, (setter)Device_set_volume,
2764 M_aud_Device_volume_doc, NULL },
2765 {(char*)"listener_location", (getter)Device_get_listener_location, (setter)Device_set_listener_location,
2766 M_aud_Device_listener_location_doc, NULL },
2767 {(char*)"listener_velocity", (getter)Device_get_listener_velocity, (setter)Device_set_listener_velocity,
2768 M_aud_Device_listener_velocity_doc, NULL },
2769 {(char*)"listener_orientation", (getter)Device_get_listener_orientation, (setter)Device_set_listener_orientation,
2770 M_aud_Device_listener_orientation_doc, NULL },
2771 {(char*)"speed_of_sound", (getter)Device_get_speed_of_sound, (setter)Device_set_speed_of_sound,
2772 M_aud_Device_speed_of_sound_doc, NULL },
2773 {(char*)"doppler_factor", (getter)Device_get_doppler_factor, (setter)Device_set_doppler_factor,
2774 M_aud_Device_doppler_factor_doc, NULL },
2775 {(char*)"distance_model", (getter)Device_get_distance_model, (setter)Device_set_distance_model,
2776 M_aud_Device_distance_model_doc, NULL },
2777 {NULL} /* Sentinel */
2780 PyDoc_STRVAR(M_aud_Device_doc,
2781 "Device objects represent an audio output backend like OpenAL or "
2782 "SDL, but might also represent a file output or RAM buffer "
2785 static PyTypeObject DeviceType = {
2786 PyVarObject_HEAD_INIT(NULL, 0)
2787 "aud.Device", /* tp_name */
2788 sizeof(Device), /* tp_basicsize */
2789 0, /* tp_itemsize */
2790 (destructor)Device_dealloc,/* tp_dealloc */
2794 0, /* tp_reserved */
2796 0, /* tp_as_number */
2797 0, /* tp_as_sequence */
2798 0, /* tp_as_mapping */
2802 0, /* tp_getattro */
2803 0, /* tp_setattro */
2804 0, /* tp_as_buffer */
2805 Py_TPFLAGS_DEFAULT, /* tp_flags */
2806 M_aud_Device_doc, /* tp_doc */
2807 0, /* tp_traverse */
2809 0, /* tp_richcompare */
2810 0, /* tp_weaklistoffset */
2812 0, /* tp_iternext */
2813 Device_methods, /* tp_methods */
2815 Device_properties, /* tp_getset */
2818 0, /* tp_descr_get */
2819 0, /* tp_descr_set */
2820 0, /* tp_dictoffset */
2823 Device_new, /* tp_new */
2829 return DeviceType.tp_alloc(&DeviceType, 0);
2832 // ====================================================================
2834 PyDoc_STRVAR(M_aud_doc,
2835 "This module provides access to the audaspace audio library.");
2837 static struct PyModuleDef audmodule = {
2838 PyModuleDef_HEAD_INIT,
2839 "aud", /* name of module */
2840 M_aud_doc, /* module documentation */
2841 -1, /* size of per-interpreter state of the module,
2842 or -1 if the module keeps state in global variables. */
2843 NULL, NULL, NULL, NULL, NULL
2851 if(PyType_Ready(&FactoryType) < 0)
2854 if(PyType_Ready(&DeviceType) < 0)
2857 if(PyType_Ready(&HandleType) < 0)
2860 m = PyModule_Create(&audmodule);
2864 Py_INCREF(&FactoryType);
2865 PyModule_AddObject(m, "Factory", (PyObject*)&FactoryType);
2867 Py_INCREF(&DeviceType);
2868 PyModule_AddObject(m, "Device", (PyObject*)&DeviceType);
2870 Py_INCREF(&HandleType);
2871 PyModule_AddObject(m, "Handle", (PyObject*)&HandleType);
2873 AUDError = PyErr_NewException("aud.error", NULL, NULL);
2874 Py_INCREF(AUDError);
2875 PyModule_AddObject(m, "error", AUDError);
2878 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_NULL);
2879 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_OPENAL);
2880 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_SDL);
2881 PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_JACK);
2882 //PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_READ);
2884 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT32);
2885 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT64);
2886 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_INVALID);
2887 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S16);
2888 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S24);
2889 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S32);
2890 PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_U8);
2892 PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_INVALID);
2893 PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PAUSED);
2894 PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PLAYING);
2895 // distance model constants
2896 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT);
2897 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT_CLAMPED);
2898 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE);
2899 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE_CLAMPED);
2900 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR);
2901 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR_CLAMPED);
2902 PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVALID);