patch [#24576] aud.Handle.status return bool
[blender-staging.git] / intern / audaspace / Python / AUD_PyAPI.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN LGPL LICENSE BLOCK *****
5  *
6  * Copyright 2009 Jörg Hermann Müller
7  *
8  * This file is part of AudaSpace.
9  *
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.
14  *
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.
19  *
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/>.
22  *
23  * ***** END LGPL LICENSE BLOCK *****
24  */
25
26 #include "AUD_PyAPI.h"
27 #include "structmember.h"
28
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"
48
49 #ifdef WITH_SDL
50 #include "AUD_SDLDevice.h"
51 #endif
52
53 #ifdef WITH_OPENAL
54 #include "AUD_OpenALDevice.h"
55 #endif
56
57 #ifdef WITH_JACK
58 #include "AUD_JackDevice.h"
59 #endif
60
61 // ====================================================================
62
63 typedef enum
64 {
65         AUD_DEVICE_NULL = 0,
66         AUD_DEVICE_OPENAL,
67         AUD_DEVICE_SDL,
68         AUD_DEVICE_JACK,
69         AUD_DEVICE_READ,
70 } AUD_DeviceTypes;
71
72 // ====================================================================
73
74 #define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name)
75
76 // ====================================================================
77
78 static PyObject* AUDError;
79
80 static const char* device_not_3d_error = "Device is not a 3D device!";
81
82 // ====================================================================
83
84 static void
85 Factory_dealloc(Factory* self)
86 {
87         if(self->factory)
88                 delete self->factory;
89         Py_XDECREF(self->child_list);
90         Py_TYPE(self)->tp_free((PyObject*)self);
91 }
92
93 static PyObject *
94 Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
95 {
96         Factory *self;
97
98         self = (Factory*)type->tp_alloc(type, 0);
99         if(self != NULL)
100         {
101                 static const char *kwlist[] = {"filename", NULL};
102                 const char* filename = NULL;
103
104                 if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Factory", const_cast<char**>(kwlist), &filename))
105                 {
106                         Py_DECREF(self);
107                         return NULL;
108                 }
109
110                 try
111                 {
112                         self->factory = new AUD_FileFactory(filename);
113                 }
114                 catch(AUD_Exception& e)
115                 {
116                         Py_DECREF(self);
117                         PyErr_SetString(AUDError, e.str);
118                         return NULL;
119                 }
120         }
121
122         return (PyObject *)self;
123 }
124
125 PyDoc_STRVAR(M_aud_Factory_sine_doc,
126                          "sine(frequency, rate=44100)\n\n"
127                          "Creates a sine factory which plays a sine wave.\n\n"
128                          ":arg frequency: The frequency of the sine wave in Hz.\n"
129                          ":type frequency: float\n"
130                          ":arg rate: The sampling rate in Hz. It's recommended to set this "
131                          "value to the playback device's samling rate to avoid resamping.\n"
132                          ":type rate: int\n"
133                          ":return: The created :class:`Factory` object.\n"
134                          ":rtype: :class:`Factory`");
135
136 static PyObject *
137 Factory_sine(PyTypeObject* type, PyObject* args)
138 {
139         float frequency;
140         int rate = 44100;
141
142         if(!PyArg_ParseTuple(args, "f|i:sine", &frequency, &rate))
143                 return NULL;
144
145         Factory *self;
146
147         self = (Factory*)type->tp_alloc(type, 0);
148         if(self != NULL)
149         {
150                 try
151                 {
152                         self->factory = new AUD_SinusFactory(frequency, (AUD_SampleRate)rate);
153                 }
154                 catch(AUD_Exception& e)
155                 {
156                         Py_DECREF(self);
157                         PyErr_SetString(AUDError, e.str);
158                         return NULL;
159                 }
160         }
161
162         return (PyObject *)self;
163 }
164
165 PyDoc_STRVAR(M_aud_Factory_file_doc,
166                          "file(filename)\n\n"
167                          "Creates a factory object of a sound file.\n\n"
168                          ":arg filename: Path of the file.\n"
169                          ":type filename: string\n"
170                          ":return: The created :class:`Factory` object.\n"
171                          ":rtype: :class:`Factory`\n\n"
172                          ".. warning:: If the file doesn't exist or can't be read you will "
173                          "not get an exception immediately, but when you try to start "
174                          "playback of that factory.");
175
176 static PyObject *
177 Factory_file(PyTypeObject* type, PyObject* args)
178 {
179         const char* filename = NULL;
180
181         if(!PyArg_ParseTuple(args, "s:file", &filename))
182                 return NULL;
183
184         Factory *self;
185
186         self = (Factory*)type->tp_alloc(type, 0);
187         if(self != NULL)
188         {
189                 try
190                 {
191                         self->factory = new AUD_FileFactory(filename);
192                 }
193                 catch(AUD_Exception& e)
194                 {
195                         Py_DECREF(self);
196                         PyErr_SetString(AUDError, e.str);
197                         return NULL;
198                 }
199         }
200
201         return (PyObject *)self;
202 }
203
204 PyDoc_STRVAR(M_aud_Factory_lowpass_doc,
205                          "lowpass(frequency, Q=0.5)\n\n"
206                          "Creates a second order lowpass filter based on the transfer "
207                          "function H(s) = 1 / (s^2 + s/Q + 1)\n\n"
208                          ":arg frequency: The cut off trequency of the lowpass.\n"
209                          ":type frequency: float\n"
210                          ":arg Q: Q factor of the lowpass.\n"
211                          ":type Q: float\n"
212                          ":return: The created :class:`Factory` object.\n"
213                          ":rtype: :class:`Factory`");
214
215 static PyObject *
216 Factory_lowpass(Factory* self, PyObject* args)
217 {
218         float frequency;
219         float Q = 0.5;
220
221         if(!PyArg_ParseTuple(args, "f|f:lowpass", &frequency, &Q))
222                 return NULL;
223
224         PyTypeObject* type = ((PyObject*)self)->ob_type;
225         Factory *parent = (Factory*)type->tp_alloc(type, 0);
226
227         if(parent != NULL)
228         {
229                 Py_INCREF(self);
230                 parent->child_list = (PyObject*)self;
231
232                 try
233                 {
234                         parent->factory = new AUD_LowpassFactory(self->factory, frequency, Q);
235                 }
236                 catch(AUD_Exception& e)
237                 {
238                         Py_DECREF(parent);
239                         PyErr_SetString(AUDError, e.str);
240                         return NULL;
241                 }
242         }
243
244         return (PyObject *)parent;
245 }
246
247 PyDoc_STRVAR(M_aud_Factory_delay_doc,
248                          "delay(time)\n\n"
249                          "Delays by playing adding silence in front of the other factory's "
250                          "data.\n\n"
251                          ":arg time: How many seconds of silence should be added before "
252                          "the factory.\n"
253                          ":type time: float\n"
254                          ":return: The created :class:`Factory` object.\n"
255                          ":rtype: :class:`Factory`");
256
257 static PyObject *
258 Factory_delay(Factory* self, PyObject* args)
259 {
260         float delay;
261
262         if(!PyArg_ParseTuple(args, "f:delay", &delay))
263                 return NULL;
264
265         PyTypeObject* type = ((PyObject*)self)->ob_type;
266         Factory *parent = (Factory*)type->tp_alloc(type, 0);
267
268         if(parent != NULL)
269         {
270                 Py_INCREF(self);
271                 parent->child_list = (PyObject*)self;
272
273                 try
274                 {
275                         parent->factory = new AUD_DelayFactory(self->factory, delay);
276                 }
277                 catch(AUD_Exception& e)
278                 {
279                         Py_DECREF(parent);
280                         PyErr_SetString(AUDError, e.str);
281                         return NULL;
282                 }
283         }
284
285         return (PyObject *)parent;
286 }
287
288 PyDoc_STRVAR(M_aud_Factory_join_doc,
289                          "join(factory)\n\n"
290                          "Plays two factories in sequence.\n\n"
291                          ":arg factory: The factory to play second.\n"
292                          ":type factory: :class:`Factory`\n"
293                          ":return: The created :class:`Factory` object.\n"
294                          ":rtype: :class:`Factory`\n\n"
295                          ".. note:: The two factories have to have the same specifications "
296                          "(channels and samplerate).");
297
298 static PyObject *
299 Factory_join(Factory* self, PyObject* object)
300 {
301         PyTypeObject* type = ((PyObject*)self)->ob_type;
302
303         if(!PyObject_TypeCheck(object, type))
304         {
305                 PyErr_SetString(PyExc_TypeError, "Object has to be of type Factory!");
306                 return NULL;
307         }
308
309         Factory *parent;
310         Factory *child = (Factory*)object;
311
312         parent = (Factory*)type->tp_alloc(type, 0);
313         if(parent != NULL)
314         {
315                 parent->child_list = Py_BuildValue("(OO)", self, object);
316
317                 try
318                 {
319                         parent->factory = new AUD_DoubleFactory(self->factory, child->factory);
320                 }
321                 catch(AUD_Exception& e)
322                 {
323                         Py_DECREF(parent);
324                         PyErr_SetString(AUDError, e.str);
325                         return NULL;
326                 }
327         }
328
329         return (PyObject *)parent;
330 }
331
332 PyDoc_STRVAR(M_aud_Factory_highpass_doc,
333                          "highpass(frequency, Q=0.5)\n\n"
334                          "Creates a second order highpass filter based on the transfer "
335                          "function H(s) = s^2 / (s^2 + s/Q + 1)\n\n"
336                          ":arg frequency: The cut off trequency of the highpass.\n"
337                          ":type frequency: float\n"
338                          ":arg Q: Q factor of the lowpass.\n"
339                          ":type Q: float\n"
340                          ":return: The created :class:`Factory` object.\n"
341                          ":rtype: :class:`Factory`");
342
343 static PyObject *
344 Factory_highpass(Factory* self, PyObject* args)
345 {
346         float frequency;
347         float Q = 0.5;
348
349         if(!PyArg_ParseTuple(args, "f|f:highpass", &frequency, &Q))
350                 return NULL;
351
352         PyTypeObject* type = ((PyObject*)self)->ob_type;
353         Factory *parent = (Factory*)type->tp_alloc(type, 0);
354
355         if(parent != NULL)
356         {
357                 Py_INCREF(self);
358                 parent->child_list = (PyObject*)self;
359
360                 try
361                 {
362                         parent->factory = new AUD_HighpassFactory(self->factory, frequency, Q);
363                 }
364                 catch(AUD_Exception& e)
365                 {
366                         Py_DECREF(parent);
367                         PyErr_SetString(AUDError, e.str);
368                         return NULL;
369                 }
370         }
371
372         return (PyObject *)parent;
373 }
374
375 PyDoc_STRVAR(M_aud_Factory_limit_doc,
376                          "limit(start, end)\n\n"
377                          "Limits a factory within a specific start and end time.\n\n"
378                          ":arg start: Start time in seconds.\n"
379                          ":type start: float\n"
380                          ":arg end: End time in seconds.\n"
381                          ":type end: float\n"
382                          ":return: The created :class:`Factory` object.\n"
383                          ":rtype: :class:`Factory`");
384
385 static PyObject *
386 Factory_limit(Factory* self, PyObject* args)
387 {
388         float start, end;
389
390         if(!PyArg_ParseTuple(args, "ff:limit", &start, &end))
391                 return NULL;
392
393         PyTypeObject* type = ((PyObject*)self)->ob_type;
394         Factory *parent = (Factory*)type->tp_alloc(type, 0);
395
396         if(parent != NULL)
397         {
398                 Py_INCREF(self);
399                 parent->child_list = (PyObject*)self;
400
401                 try
402                 {
403                         parent->factory = new AUD_LimiterFactory(self->factory, start, end);
404                 }
405                 catch(AUD_Exception& e)
406                 {
407                         Py_DECREF(parent);
408                         PyErr_SetString(AUDError, e.str);
409                         return NULL;
410                 }
411         }
412
413         return (PyObject *)parent;
414 }
415
416 PyDoc_STRVAR(M_aud_Factory_pitch_doc,
417                          "pitch(factor)\n\n"
418                          "Changes the pitch of a factory with a specific factor.\n\n"
419                          ":arg factor: The factor to change the pitch with.\n"
420                          ":type factor: float\n"
421                          ":return: The created :class:`Factory` object.\n"
422                          ":rtype: :class:`Factory`\n\n"
423                          ".. note:: This is done by changing the sample rate of the "
424                          "underlying factory, which has to be an integer, so the factor "
425                          "value rounded and the factor may not be 100 % accurate.\n\n"
426                          ".. note:: This is a filter function, you might consider using "
427                          ":attr:`Handle.pitch` instead.");
428
429 static PyObject *
430 Factory_pitch(Factory* self, PyObject* args)
431 {
432         float factor;
433
434         if(!PyArg_ParseTuple(args, "f:pitch", &factor))
435                 return NULL;
436
437         PyTypeObject* type = ((PyObject*)self)->ob_type;
438         Factory *parent = (Factory*)type->tp_alloc(type, 0);
439
440         if(parent != NULL)
441         {
442                 Py_INCREF(self);
443                 parent->child_list = (PyObject*)self;
444
445                 try
446                 {
447                         parent->factory = new AUD_PitchFactory(self->factory, factor);
448                 }
449                 catch(AUD_Exception& e)
450                 {
451                         Py_DECREF(parent);
452                         PyErr_SetString(AUDError, e.str);
453                         return NULL;
454                 }
455         }
456
457         return (PyObject *)parent;
458 }
459
460 PyDoc_STRVAR(M_aud_Factory_volume_doc,
461                          "volume(volume)\n\n"
462                          "Changes the volume of a factory.\n\n"
463                          ":arg volume: The new volume..\n"
464                          ":type volume: float\n"
465                          ":return: The created :class:`Factory` object.\n"
466                          ":rtype: :class:`Factory`\n\n"
467                          ".. note:: Should be in the range [0, 1] to avoid clipping.\n\n"
468                          ".. note:: This is a filter function, you might consider using "
469                          ":attr:`Handle.volume` instead.");
470
471 static PyObject *
472 Factory_volume(Factory* self, PyObject* args)
473 {
474         float volume;
475
476         if(!PyArg_ParseTuple(args, "f:volume", &volume))
477                 return NULL;
478
479         PyTypeObject* type = ((PyObject*)self)->ob_type;
480         Factory *parent = (Factory*)type->tp_alloc(type, 0);
481
482         if(parent != NULL)
483         {
484                 Py_INCREF(self);
485                 parent->child_list = (PyObject*)self;
486
487                 try
488                 {
489                         parent->factory = new AUD_VolumeFactory(self->factory, volume);
490                 }
491                 catch(AUD_Exception& e)
492                 {
493                         Py_DECREF(parent);
494                         PyErr_SetString(AUDError, e.str);
495                         return NULL;
496                 }
497         }
498
499         return (PyObject *)parent;
500 }
501
502 PyDoc_STRVAR(M_aud_Factory_fadein_doc,
503                          "fadein(start, length)\n\n"
504                          "Fades a factory in by raising the volume linearly in the given "
505                          "time interval.\n\n"
506                          ":arg start: Time in seconds when the fading should start.\n"
507                          ":type start: float\n"
508                          ":arg length: Time in seconds how long the fading should last.\n"
509                          ":type length: float\n"
510                          ":return: The created :class:`Factory` object.\n"
511                          ":rtype: :class:`Factory`\n\n"
512                          ".. note:: Before the fade starts it plays silence.");
513
514 static PyObject *
515 Factory_fadein(Factory* self, PyObject* args)
516 {
517         float start, length;
518
519         if(!PyArg_ParseTuple(args, "ff:fadein", &start, &length))
520                 return NULL;
521
522         PyTypeObject* type = ((PyObject*)self)->ob_type;
523         Factory *parent = (Factory*)type->tp_alloc(type, 0);
524
525         if(parent != NULL)
526         {
527                 Py_INCREF(self);
528                 parent->child_list = (PyObject*)self;
529
530                 try
531                 {
532                         parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_IN, start, length);
533                 }
534                 catch(AUD_Exception& e)
535                 {
536                         Py_DECREF(parent);
537                         PyErr_SetString(AUDError, e.str);
538                         return NULL;
539                 }
540         }
541
542         return (PyObject *)parent;
543 }
544
545 PyDoc_STRVAR(M_aud_Factory_fadeout_doc,
546                          "fadeout(start, length)\n\n"
547                          "Fades a factory in by lowering the volume linearly in the given "
548                          "time interval.\n\n"
549                          ":arg start: Time in seconds when the fading should start.\n"
550                          ":type start: float\n"
551                          ":arg length: Time in seconds how long the fading should last.\n"
552                          ":type length: float\n"
553                          ":return: The created :class:`Factory` object.\n"
554                          ":rtype: :class:`Factory`\n\n"
555                          ".. note:: After the fade this factory plays silence, so that "
556                          "the length of the factory is not altered.");
557
558 static PyObject *
559 Factory_fadeout(Factory* self, PyObject* args)
560 {
561         float start, length;
562
563         if(!PyArg_ParseTuple(args, "ff:fadeout", &start, &length))
564                 return NULL;
565
566         PyTypeObject* type = ((PyObject*)self)->ob_type;
567         Factory *parent = (Factory*)type->tp_alloc(type, 0);
568
569         if(parent != NULL)
570         {
571                 Py_INCREF(self);
572                 parent->child_list = (PyObject*)self;
573
574                 try
575                 {
576                         parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_OUT, start, length);
577                 }
578                 catch(AUD_Exception& e)
579                 {
580                         Py_DECREF(parent);
581                         PyErr_SetString(AUDError, e.str);
582                         return NULL;
583                 }
584         }
585
586         return (PyObject *)parent;
587 }
588
589 PyDoc_STRVAR(M_aud_Factory_loop_doc,
590                          "loop(count)\n\n"
591                          "Loops a factory.\n\n"
592                          ":arg count: How often the factory should be looped. "
593                          "Negative values mean endlessly.\n"
594                          ":type count: integer\n"
595                          ":return: The created :class:`Factory` object.\n"
596                          ":rtype: :class:`Factory`\n\n"
597                          ".. note:: This is a filter function, you might consider using "
598                          ":attr:`Handle.loop_count` instead.");
599
600 static PyObject *
601 Factory_loop(Factory* self, PyObject* args)
602 {
603         int loop;
604
605         if(!PyArg_ParseTuple(args, "i:loop", &loop))
606                 return NULL;
607
608         PyTypeObject* type = ((PyObject*)self)->ob_type;
609         Factory *parent = (Factory*)type->tp_alloc(type, 0);
610
611         if(parent != NULL)
612         {
613                 Py_INCREF(self);
614                 parent->child_list = (PyObject*)self;
615
616                 try
617                 {
618                         parent->factory = new AUD_LoopFactory(self->factory, loop);
619                 }
620                 catch(AUD_Exception& e)
621                 {
622                         Py_DECREF(parent);
623                         PyErr_SetString(AUDError, e.str);
624                         return NULL;
625                 }
626         }
627
628         return (PyObject *)parent;
629 }
630
631 PyDoc_STRVAR(M_aud_Factory_mix_doc,
632                          "mix(factory)\n\n"
633                          "Mixes two factories.\n\n"
634                          ":arg factory: The factory to mix over the other.\n"
635                          ":type factory: :class:`Factory`\n"
636                          ":return: The created :class:`Factory` object.\n"
637                          ":rtype: :class:`Factory`\n\n"
638                          ".. note:: The two factories have to have the same specifications "
639                          "(channels and samplerate).");
640
641 static PyObject *
642 Factory_mix(Factory* self, PyObject* object)
643 {
644         PyTypeObject* type = ((PyObject*)self)->ob_type;
645
646         if(!PyObject_TypeCheck(object, type))
647         {
648                 PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
649                 return NULL;
650         }
651
652         Factory *parent = (Factory*)type->tp_alloc(type, 0);
653         Factory *child = (Factory*)object;
654
655         if(parent != NULL)
656         {
657                 parent->child_list = Py_BuildValue("(OO)", self, object);
658
659                 try
660                 {
661                         parent->factory = new AUD_SuperposeFactory(self->factory, child->factory);
662                 }
663                 catch(AUD_Exception& e)
664                 {
665                         Py_DECREF(parent);
666                         PyErr_SetString(AUDError, e.str);
667                         return NULL;
668                 }
669         }
670
671         return (PyObject *)parent;
672 }
673
674 PyDoc_STRVAR(M_aud_Factory_pingpong_doc,
675                          "pingpong()\n\n"
676                          "Plays a factory forward and then backward.\n"
677                          "This is like joining a factory with its reverse.\n\n"
678                          ":return: The created :class:`Factory` object.\n"
679                          ":rtype: :class:`Factory`");
680
681 static PyObject *
682 Factory_pingpong(Factory* self)
683 {
684         PyTypeObject* type = ((PyObject*)self)->ob_type;
685         Factory *parent = (Factory*)type->tp_alloc(type, 0);
686
687         if(parent != NULL)
688         {
689                 Py_INCREF(self);
690                 parent->child_list = (PyObject*)self;
691
692                 try
693                 {
694                         parent->factory = new AUD_PingPongFactory(self->factory);
695                 }
696                 catch(AUD_Exception& e)
697                 {
698                         Py_DECREF(parent);
699                         PyErr_SetString(AUDError, e.str);
700                         return NULL;
701                 }
702         }
703
704         return (PyObject *)parent;
705 }
706
707 PyDoc_STRVAR(M_aud_Factory_reverse_doc,
708                          "reverse()\n\n"
709                          "Plays a factory reversed.\n\n"
710                          ":return: The created :class:`Factory` object.\n"
711                          ":rtype: :class:`Factory`\n\n"
712                          ".. note:: The factory has to have a finite length and has to be "
713                          "seekable. It's recommended to use this only with factories     with "
714                          "fast and accurate seeking, which is not true for encoded audio "
715                          "files, such ones should be buffered using :meth:`buffer` before "
716                          "being played reversed.\n\n"
717                          ".. warning:: If seeking is not accurate in the underlying factory "
718                          "you'll likely hear skips/jumps/cracks.");
719
720 static PyObject *
721 Factory_reverse(Factory* self)
722 {
723         PyTypeObject* type = ((PyObject*)self)->ob_type;
724         Factory *parent = (Factory*)type->tp_alloc(type, 0);
725
726         if(parent != NULL)
727         {
728                 Py_INCREF(self);
729                 parent->child_list = (PyObject*)self;
730
731                 try
732                 {
733                         parent->factory = new AUD_ReverseFactory(self->factory);
734                 }
735                 catch(AUD_Exception& e)
736                 {
737                         Py_DECREF(parent);
738                         PyErr_SetString(AUDError, e.str);
739                         return NULL;
740                 }
741         }
742
743         return (PyObject *)parent;
744 }
745
746 PyDoc_STRVAR(M_aud_Factory_buffer_doc,
747                          "buffer()\n\n"
748                          "Buffers a factory into RAM.\n"
749                          "This saves CPU usage needed for decoding and file access if the "
750                          "underlying factory reads from a file on the harddisk, but it "
751                          "consumes a lot of memory.\n\n"
752                          ":return: The created :class:`Factory` object.\n"
753                          ":rtype: :class:`Factory`\n\n"
754                          ".. note:: Only known-length factories can be buffered.\n\n"
755                          ".. warning:: Raw PCM data needs a lot of space, only buffer "
756                          "short factories.");
757
758 static PyObject *
759 Factory_buffer(Factory* self)
760 {
761         PyTypeObject* type = ((PyObject*)self)->ob_type;
762         Factory *parent = (Factory*)type->tp_alloc(type, 0);
763
764         if(parent != NULL)
765         {
766                 try
767                 {
768                         parent->factory = new AUD_StreamBufferFactory(self->factory);
769                 }
770                 catch(AUD_Exception& e)
771                 {
772                         Py_DECREF(parent);
773                         PyErr_SetString(AUDError, e.str);
774                         return NULL;
775                 }
776         }
777
778         return (PyObject *)parent;
779 }
780
781 PyDoc_STRVAR(M_aud_Factory_square_doc,
782                          "square(threshold = 0)\n\n"
783                          "Makes a square wave out of an audio wave by setting all samples "
784                          "with a amplitude >= threshold to 1, all <= -threshold to -1 and "
785                          "all between to 0.\n\n"
786                          ":arg threshold: Threshold value over which an amplitude counts "
787                          "non-zero.\n"
788                          ":type threshold: float\n"
789                          ":return: The created :class:`Factory` object.\n"
790                          ":rtype: :class:`Factory`");
791
792 static PyObject *
793 Factory_square(Factory* self, PyObject* args)
794 {
795         float threshold = 0;
796
797         if(!PyArg_ParseTuple(args, "|f:square", &threshold))
798                 return NULL;
799
800         PyTypeObject* type = ((PyObject*)self)->ob_type;
801         Factory *parent = (Factory*)type->tp_alloc(type, 0);
802
803         if(parent != NULL)
804         {
805                 Py_INCREF(self);
806                 parent->child_list = (PyObject*)self;
807
808                 try
809                 {
810                         parent->factory = new AUD_SquareFactory(self->factory, threshold);
811                 }
812                 catch(AUD_Exception& e)
813                 {
814                         Py_DECREF(parent);
815                         PyErr_SetString(AUDError, e.str);
816                         return NULL;
817                 }
818         }
819
820         return (PyObject *)parent;
821 }
822
823 PyDoc_STRVAR(M_aud_Factory_filter_doc,
824                          "filter(b, a = (1))\n\n"
825                          "Filters a factory with the supplied IIR filter coefficients.\n"
826                          "Without the second parameter you'll get a FIR filter.\n"
827                          "If the first value of the a sequence is 0 it will be set to 1 "
828                          "automatically.\n"
829                          "If the first value of the a sequence is neither 0 nor 1, all "
830                          "filter coefficients will be scaled by this value so that it is 1 "
831                          "in the end, you don't have to scale yourself.\n\n"
832                          ":arg b: The nominator filter coefficients.\n"
833                          ":type b: sequence of float\n"
834                          ":arg a: The denominator filter coefficients.\n"
835                          ":type a: sequence of float\n"
836                          ":return: The created :class:`Factory` object.\n"
837                          ":rtype: :class:`Factory`");
838
839 static PyObject *
840 Factory_filter(Factory* self, PyObject* args)
841 {
842         PyObject* py_b;
843         PyObject* py_a = NULL;
844
845         if(!PyArg_ParseTuple(args, "O|O:filter", &py_b, &py_a))
846                 return NULL;
847
848         if(!PySequence_Check(py_b) || (py_a != NULL && !PySequence_Check(py_a)))
849         {
850                 PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
851                 return NULL;
852         }
853
854         if(!PySequence_Length(py_b) || (py_a != NULL && !PySequence_Length(py_a)))
855         {
856                 PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
857                 return NULL;
858         }
859
860         std::vector<float> a, b;
861         PyObject* py_value;
862         float value;
863         int result;
864
865         for(int i = 0; i < PySequence_Length(py_b); i++)
866         {
867                 py_value = PySequence_GetItem(py_b, i);
868                 result = PyArg_Parse(py_value, "f:filter", &value);
869                 Py_DECREF(py_value);
870
871                 if(!result)
872                         return NULL;
873
874                 b.push_back(value);
875         }
876
877         if(py_a)
878         {
879                 for(int i = 0; i < PySequence_Length(py_a); i++)
880                 {
881                         py_value = PySequence_GetItem(py_a, i);
882                         result = PyArg_Parse(py_value, "f:filter", &value);
883                         Py_DECREF(py_value);
884
885                         if(!result)
886                                 return NULL;
887
888                         a.push_back(value);
889                 }
890
891                 if(a[0] == 0)
892                         a[0] = 1;
893         }
894         else
895                 a.push_back(1);
896
897         PyTypeObject* type = ((PyObject*)self)->ob_type;
898         Factory *parent = (Factory*)type->tp_alloc(type, 0);
899
900         if(parent != NULL)
901         {
902                 Py_INCREF(self);
903                 parent->child_list = (PyObject*)self;
904
905                 try
906                 {
907                         parent->factory = new AUD_IIRFilterFactory(self->factory, b, a);
908                 }
909                 catch(AUD_Exception& e)
910                 {
911                         Py_DECREF(parent);
912                         PyErr_SetString(AUDError, e.str);
913                         return NULL;
914                 }
915         }
916
917         return (PyObject *)parent;
918 }
919
920 static PyMethodDef Factory_methods[] = {
921         {"sine", (PyCFunction)Factory_sine, METH_VARARGS | METH_CLASS,
922          M_aud_Factory_sine_doc
923         },
924         {"file", (PyCFunction)Factory_file, METH_VARARGS | METH_CLASS,
925          M_aud_Factory_file_doc
926         },
927         {"lowpass", (PyCFunction)Factory_lowpass, METH_VARARGS,
928          M_aud_Factory_lowpass_doc
929         },
930         {"delay", (PyCFunction)Factory_delay, METH_VARARGS,
931          M_aud_Factory_delay_doc
932         },
933         {"join", (PyCFunction)Factory_join, METH_O,
934          M_aud_Factory_join_doc
935         },
936         {"highpass", (PyCFunction)Factory_highpass, METH_VARARGS,
937          M_aud_Factory_highpass_doc
938         },
939         {"limit", (PyCFunction)Factory_limit, METH_VARARGS,
940          M_aud_Factory_limit_doc
941         },
942         {"pitch", (PyCFunction)Factory_pitch, METH_VARARGS,
943          M_aud_Factory_pitch_doc
944         },
945         {"volume", (PyCFunction)Factory_volume, METH_VARARGS,
946          M_aud_Factory_volume_doc
947         },
948         {"fadein", (PyCFunction)Factory_fadein, METH_VARARGS,
949          M_aud_Factory_fadein_doc
950         },
951         {"fadeout", (PyCFunction)Factory_fadeout, METH_VARARGS,
952          M_aud_Factory_fadeout_doc
953         },
954         {"loop", (PyCFunction)Factory_loop, METH_VARARGS,
955          M_aud_Factory_loop_doc
956         },
957         {"mix", (PyCFunction)Factory_mix, METH_O,
958          M_aud_Factory_mix_doc
959         },
960         {"pingpong", (PyCFunction)Factory_pingpong, METH_NOARGS,
961          M_aud_Factory_pingpong_doc
962         },
963         {"reverse", (PyCFunction)Factory_reverse, METH_NOARGS,
964          M_aud_Factory_reverse_doc
965         },
966         {"buffer", (PyCFunction)Factory_buffer, METH_NOARGS,
967          M_aud_Factory_buffer_doc
968         },
969         {"square", (PyCFunction)Factory_square, METH_VARARGS,
970          M_aud_Factory_square_doc
971         },
972         {"filter", (PyCFunction)Factory_filter, METH_VARARGS,
973          M_aud_Factory_filter_doc
974         },
975         {NULL}  /* Sentinel */
976 };
977
978 PyDoc_STRVAR(M_aud_Factory_doc,
979                          "Factory objects are immutable and represent a sound that can be "
980                          "played simultaneously multiple times. They are called factories "
981                          "because they create reader objects internally that are used for "
982                          "playback.");
983
984 static PyTypeObject FactoryType = {
985         PyVarObject_HEAD_INIT(NULL, 0)
986         "aud.Factory",               /* tp_name */
987         sizeof(Factory),             /* tp_basicsize */
988         0,                         /* tp_itemsize */
989         (destructor)Factory_dealloc, /* tp_dealloc */
990         0,                         /* tp_print */
991         0,                         /* tp_getattr */
992         0,                         /* tp_setattr */
993         0,                         /* tp_reserved */
994         0,                         /* tp_repr */
995         0,                         /* tp_as_number */
996         0,                         /* tp_as_sequence */
997         0,                         /* tp_as_mapping */
998         0,                         /* tp_hash  */
999         0,                         /* tp_call */
1000         0,                         /* tp_str */
1001         0,                         /* tp_getattro */
1002         0,                         /* tp_setattro */
1003         0,                         /* tp_as_buffer */
1004         Py_TPFLAGS_DEFAULT,        /* tp_flags */
1005         M_aud_Factory_doc,           /* tp_doc */
1006         0,                                 /* tp_traverse */
1007         0,                                 /* tp_clear */
1008         0,                                 /* tp_richcompare */
1009         0,                                 /* tp_weaklistoffset */
1010         0,                                 /* tp_iter */
1011         0,                                 /* tp_iternext */
1012         Factory_methods,             /* tp_methods */
1013         0,                         /* tp_members */
1014         0,                         /* tp_getset */
1015         0,                         /* tp_base */
1016         0,                         /* tp_dict */
1017         0,                         /* tp_descr_get */
1018         0,                         /* tp_descr_set */
1019         0,                         /* tp_dictoffset */
1020         0,                         /* tp_init */
1021         0,                         /* tp_alloc */
1022         Factory_new,                 /* tp_new */
1023 };
1024
1025 // ========== Handle ==================================================
1026
1027 static void
1028 Handle_dealloc(Handle* self)
1029 {
1030         Py_XDECREF(self->device);
1031         Py_TYPE(self)->tp_free((PyObject*)self);
1032 }
1033
1034 PyDoc_STRVAR(M_aud_Handle_pause_doc,
1035                          "pause()\n\n"
1036                          "Pauses playback.\n\n"
1037                          ":return: Whether the action succeeded.\n"
1038                          ":rtype: bool");
1039
1040 static PyObject *
1041 Handle_pause(Handle *self)
1042 {
1043         Device* device = (Device*)self->device;
1044
1045         try
1046         {
1047                 return PyBool_FromLong((long)device->device->pause(self->handle));
1048         }
1049         catch(AUD_Exception& e)
1050         {
1051                 PyErr_SetString(AUDError, e.str);
1052                 return NULL;
1053         }
1054 }
1055
1056 PyDoc_STRVAR(M_aud_Handle_resume_doc,
1057                          "resume()\n\n"
1058                          "Resumes playback.\n\n"
1059                          ":return: Whether the action succeeded.\n"
1060                          ":rtype: bool");
1061
1062 static PyObject *
1063 Handle_resume(Handle *self)
1064 {
1065         Device* device = (Device*)self->device;
1066
1067         try
1068         {
1069                 return PyBool_FromLong((long)device->device->resume(self->handle));
1070         }
1071         catch(AUD_Exception& e)
1072         {
1073                 PyErr_SetString(AUDError, e.str);
1074                 return NULL;
1075         }
1076 }
1077
1078 PyDoc_STRVAR(M_aud_Handle_stop_doc,
1079                          "stop()\n\n"
1080                          "Stops playback.\n\n"
1081                          ":return: Whether the action succeeded.\n"
1082                          ":rtype: bool\n\n"
1083                          ".. note:: This makes the handle invalid.");
1084
1085 static PyObject *
1086 Handle_stop(Handle *self)
1087 {
1088         Device* device = (Device*)self->device;
1089
1090         try
1091         {
1092                 return PyBool_FromLong((long)device->device->stop(self->handle));
1093         }
1094         catch(AUD_Exception& e)
1095         {
1096                 PyErr_SetString(AUDError, e.str);
1097                 return NULL;
1098         }
1099 }
1100
1101 static PyMethodDef Handle_methods[] = {
1102         {"pause", (PyCFunction)Handle_pause, METH_NOARGS,
1103          M_aud_Handle_pause_doc
1104         },
1105         {"resume", (PyCFunction)Handle_resume, METH_NOARGS,
1106          M_aud_Handle_resume_doc
1107         },
1108         {"stop", (PyCFunction)Handle_stop, METH_NOARGS,
1109          M_aud_Handle_stop_doc
1110         },
1111         {NULL}  /* Sentinel */
1112 };
1113
1114 PyDoc_STRVAR(M_aud_Handle_position_doc,
1115                          "The playback position of the sound in seconds.");
1116
1117 static PyObject *
1118 Handle_get_position(Handle *self, void* nothing)
1119 {
1120         Device* device = (Device*)self->device;
1121
1122         try
1123         {
1124                 return Py_BuildValue("f", device->device->getPosition(self->handle));
1125         }
1126         catch(AUD_Exception& e)
1127         {
1128                 PyErr_SetString(AUDError, e.str);
1129                 return NULL;
1130         }
1131 }
1132
1133 static int
1134 Handle_set_position(Handle *self, PyObject* args, void* nothing)
1135 {
1136         float position;
1137
1138         if(!PyArg_Parse(args, "f:position", &position))
1139                 return -1;
1140
1141         Device* device = (Device*)self->device;
1142
1143         try
1144         {
1145                 if(device->device->seek(self->handle, position))
1146                         return 0;
1147                 PyErr_SetString(AUDError, "Couldn't seek the sound!");
1148         }
1149         catch(AUD_Exception& e)
1150         {
1151                 PyErr_SetString(AUDError, e.str);
1152         }
1153
1154         return -1;
1155 }
1156
1157 PyDoc_STRVAR(M_aud_Handle_keep_doc,
1158                          "Whether the sound should be kept paused in the device when its "
1159                          "end is reached.\n"
1160                          "This can be used to seek the sound to some position and start "
1161                          "playback again.\n\n"
1162                          ".. warning:: If this is set to true and you forget stopping this "
1163                          "equals a memory leak as the handle exists until the device is "
1164                          "destroyed.");
1165
1166 static PyObject *
1167 Handle_get_keep(Handle *self, void* nothing)
1168 {
1169         Device* device = (Device*)self->device;
1170
1171         try
1172         {
1173                 return PyBool_FromLong((long)device->device->getKeep(self->handle));
1174         }
1175         catch(AUD_Exception& e)
1176         {
1177                 PyErr_SetString(AUDError, e.str);
1178                 return NULL;
1179         }
1180 }
1181
1182 static int
1183 Handle_set_keep(Handle *self, PyObject* args, void* nothing)
1184 {
1185         if(!PyBool_Check(args))
1186         {
1187                 PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
1188                 return -1;
1189         }
1190
1191         bool keep = args == Py_True;
1192         Device* device = (Device*)self->device;
1193
1194         try
1195         {
1196                 if(device->device->setKeep(self->handle, keep))
1197                         return 0;
1198                 PyErr_SetString(AUDError, "Couldn't set keep of the sound!");
1199         }
1200         catch(AUD_Exception& e)
1201         {
1202                 PyErr_SetString(AUDError, e.str);
1203         }
1204
1205         return -1;
1206 }
1207
1208 PyDoc_STRVAR(M_aud_Handle_status_doc,
1209                          "Whether the sound is playing, paused or stopped (=invalid).");
1210
1211 static PyObject *
1212 Handle_get_status(Handle *self, void* nothing)
1213 {
1214         Device* device = (Device*)self->device;
1215
1216         try
1217         {
1218                 return PyBool_FromLong((long)device->device->getStatus(self->handle));
1219         }
1220         catch(AUD_Exception& e)
1221         {
1222                 PyErr_SetString(AUDError, e.str);
1223                 return NULL;
1224         }
1225 }
1226
1227 PyDoc_STRVAR(M_aud_Handle_volume_doc,
1228                          "The volume of the sound.");
1229
1230 static PyObject *
1231 Handle_get_volume(Handle *self, void* nothing)
1232 {
1233         Device* device = (Device*)self->device;
1234
1235         try
1236         {
1237                 return Py_BuildValue("f", device->device->getVolume(self->handle));
1238         }
1239         catch(AUD_Exception& e)
1240         {
1241                 PyErr_SetString(AUDError, e.str);
1242                 return NULL;
1243         }
1244 }
1245
1246 static int
1247 Handle_set_volume(Handle *self, PyObject* args, void* nothing)
1248 {
1249         float volume;
1250
1251         if(!PyArg_Parse(args, "f:volume", &volume))
1252                 return -1;
1253
1254         Device* device = (Device*)self->device;
1255
1256         try
1257         {
1258                 if(device->device->setVolume(self->handle, volume))
1259                         return 0;
1260                 PyErr_SetString(AUDError, "Couldn't set the sound volume!");
1261         }
1262         catch(AUD_Exception& e)
1263         {
1264                 PyErr_SetString(AUDError, e.str);
1265         }
1266
1267         return -1;
1268 }
1269
1270 PyDoc_STRVAR(M_aud_Handle_pitch_doc,
1271                          "The pitch of the sound.");
1272
1273 static PyObject *
1274 Handle_get_pitch(Handle *self, void* nothing)
1275 {
1276         Device* device = (Device*)self->device;
1277
1278         try
1279         {
1280                 return Py_BuildValue("f", device->device->getPitch(self->handle));
1281         }
1282         catch(AUD_Exception& e)
1283         {
1284                 PyErr_SetString(AUDError, e.str);
1285                 return NULL;
1286         }
1287 }
1288
1289 static int
1290 Handle_set_pitch(Handle *self, PyObject* args, void* nothing)
1291 {
1292         float pitch;
1293
1294         if(!PyArg_Parse(args, "f:pitch", &pitch))
1295                 return -1;
1296
1297         Device* device = (Device*)self->device;
1298
1299         try
1300         {
1301                 if(device->device->setPitch(self->handle, pitch))
1302                         return 0;
1303                 PyErr_SetString(AUDError, "Couldn't set the sound pitch!");
1304         }
1305         catch(AUD_Exception& e)
1306         {
1307                 PyErr_SetString(AUDError, e.str);
1308         }
1309
1310         return -1;
1311 }
1312
1313 PyDoc_STRVAR(M_aud_Handle_loop_count_doc,
1314                          "The (remaining) loop count of the sound. A negative value indicates infinity.");
1315
1316 static PyObject *
1317 Handle_get_loop_count(Handle *self, void* nothing)
1318 {
1319         Device* device = (Device*)self->device;
1320
1321         try
1322         {
1323                 return Py_BuildValue("i", device->device->getLoopCount(self->handle));
1324         }
1325         catch(AUD_Exception& e)
1326         {
1327                 PyErr_SetString(AUDError, e.str);
1328                 return NULL;
1329         }
1330 }
1331
1332 static int
1333 Handle_set_loop_count(Handle *self, PyObject* args, void* nothing)
1334 {
1335         int loops;
1336
1337         if(!PyArg_Parse(args, "i:loop_count", &loops))
1338                 return -1;
1339
1340         Device* device = (Device*)self->device;
1341
1342         try
1343         {
1344                 if(device->device->setLoopCount(self->handle, loops))
1345                         return 0;
1346                 PyErr_SetString(AUDError, "Couldn't set the loop count!");
1347         }
1348         catch(AUD_Exception& e)
1349         {
1350                 PyErr_SetString(AUDError, e.str);
1351         }
1352
1353         return -1;
1354 }
1355
1356 PyDoc_STRVAR(M_aud_Handle_location_doc,
1357                          "The source's location in 3D space, a 3D tuple of floats.");
1358
1359 static PyObject *
1360 Handle_get_location(Handle *self, void* nothing)
1361 {
1362         Device* dev = (Device*)self->device;
1363
1364         try
1365         {
1366                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1367                 if(device)
1368                 {
1369                         AUD_Vector3 v = device->getSourceLocation(self->handle);
1370                         return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
1371                 }
1372                 else
1373                 {
1374                         PyErr_SetString(AUDError, device_not_3d_error);
1375                 }
1376         }
1377         catch(AUD_Exception& e)
1378         {
1379                 PyErr_SetString(AUDError, e.str);
1380         }
1381
1382         return NULL;
1383 }
1384
1385 static int
1386 Handle_set_location(Handle *self, PyObject* args, void* nothing)
1387 {
1388         float x, y, z;
1389
1390         if(!PyArg_Parse(args, "(fff):location", &x, &y, &z))
1391                 return -1;
1392
1393         Device* dev = (Device*)self->device;
1394
1395         try
1396         {
1397                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1398                 if(device)
1399                 {
1400                         AUD_Vector3 location(x, y, z);
1401                         if(device->setSourceLocation(self->handle, location))
1402                                 return 0;
1403                         PyErr_SetString(AUDError, "Location couldn't be set!");
1404                 }
1405                 else
1406                         PyErr_SetString(AUDError, device_not_3d_error);
1407         }
1408         catch(AUD_Exception& e)
1409         {
1410                 PyErr_SetString(AUDError, e.str);
1411         }
1412
1413         return -1;
1414 }
1415
1416 PyDoc_STRVAR(M_aud_Handle_velocity_doc,
1417                          "The source's velocity in 3D space, a 3D tuple of floats.");
1418
1419 static PyObject *
1420 Handle_get_velocity(Handle *self, void* nothing)
1421 {
1422         Device* dev = (Device*)self->device;
1423
1424         try
1425         {
1426                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1427                 if(device)
1428                 {
1429                         AUD_Vector3 v = device->getSourceVelocity(self->handle);
1430                         return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
1431                 }
1432                 else
1433                 {
1434                         PyErr_SetString(AUDError, device_not_3d_error);
1435                 }
1436         }
1437         catch(AUD_Exception& e)
1438         {
1439                 PyErr_SetString(AUDError, e.str);
1440         }
1441
1442         return NULL;
1443 }
1444
1445 static int
1446 Handle_set_velocity(Handle *self, PyObject* args, void* nothing)
1447 {
1448         float x, y, z;
1449
1450         if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z))
1451                 return -1;
1452
1453         Device* dev = (Device*)self->device;
1454
1455         try
1456         {
1457                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1458                 if(device)
1459                 {
1460                         AUD_Vector3 velocity(x, y, z);
1461                         if(device->setSourceVelocity(self->handle, velocity))
1462                                 return 0;
1463                         PyErr_SetString(AUDError, "Couldn't set the velocity!");
1464                 }
1465                 else
1466                         PyErr_SetString(AUDError, device_not_3d_error);
1467         }
1468         catch(AUD_Exception& e)
1469         {
1470                 PyErr_SetString(AUDError, e.str);
1471         }
1472
1473         return -1;
1474 }
1475
1476 PyDoc_STRVAR(M_aud_Handle_orientation_doc,
1477                          "The source's orientation in 3D space as quaternion, a 4 float tuple.");
1478
1479 static PyObject *
1480 Handle_get_orientation(Handle *self, void* nothing)
1481 {
1482         Device* dev = (Device*)self->device;
1483
1484         try
1485         {
1486                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1487                 if(device)
1488                 {
1489                         AUD_Quaternion o = device->getSourceOrientation(self->handle);
1490                         return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
1491                 }
1492                 else
1493                 {
1494                         PyErr_SetString(AUDError, device_not_3d_error);
1495                 }
1496         }
1497         catch(AUD_Exception& e)
1498         {
1499                 PyErr_SetString(AUDError, e.str);
1500         }
1501
1502         return NULL;
1503 }
1504
1505 static int
1506 Handle_set_orientation(Handle *self, PyObject* args, void* nothing)
1507 {
1508         float w, x, y, z;
1509
1510         if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z))
1511                 return -1;
1512
1513         Device* dev = (Device*)self->device;
1514
1515         try
1516         {
1517                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1518                 if(device)
1519                 {
1520                         AUD_Quaternion orientation(w, x, y, z);
1521                         if(device->setSourceOrientation(self->handle, orientation))
1522                                 return 0;
1523                         PyErr_SetString(AUDError, "Couldn't set the orientation!");
1524                 }
1525                 else
1526                         PyErr_SetString(AUDError, device_not_3d_error);
1527         }
1528         catch(AUD_Exception& e)
1529         {
1530                 PyErr_SetString(AUDError, e.str);
1531         }
1532
1533         return -1;
1534 }
1535
1536 PyDoc_STRVAR(M_aud_Handle_relative_doc,
1537                          "Whether the source's location, velocity and orientation is relative or absolute to the listener.");
1538
1539 static PyObject *
1540 Handle_get_relative(Handle *self, void* nothing)
1541 {
1542         Device* dev = (Device*)self->device;
1543
1544         try
1545         {
1546                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1547                 if(device)
1548                 {
1549                         return PyBool_FromLong((long)device->isRelative(self->handle));
1550                 }
1551                 else
1552                 {
1553                         PyErr_SetString(AUDError, device_not_3d_error);
1554                 }
1555         }
1556         catch(AUD_Exception& e)
1557         {
1558                 PyErr_SetString(AUDError, e.str);
1559         }
1560
1561         return NULL;
1562 }
1563
1564 static int
1565 Handle_set_relative(Handle *self, PyObject* args, void* nothing)
1566 {
1567         if(!PyBool_Check(args))
1568         {
1569                 PyErr_SetString(PyExc_TypeError, "Value is not a boolean!");
1570                 return -1;
1571         }
1572
1573         bool relative = (args == Py_True);
1574         Device* dev = (Device*)self->device;
1575
1576         try
1577         {
1578                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1579                 if(device)
1580                 {
1581                         if(device->setRelative(self->handle, relative))
1582                                 return 0;
1583                         PyErr_SetString(AUDError, "Couldn't set the relativeness!");
1584                 }
1585                 else
1586                         PyErr_SetString(AUDError, device_not_3d_error);
1587         }
1588         catch(AUD_Exception& e)
1589         {
1590                 PyErr_SetString(AUDError, e.str);
1591         }
1592
1593         return -1;
1594 }
1595
1596 PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc,
1597                          "The minimum volume of the source.\n\n"
1598                          ".. seealso:: :attr:`Device.distance_model`");
1599
1600 static PyObject *
1601 Handle_get_volume_minimum(Handle *self, void* nothing)
1602 {
1603         Device* dev = (Device*)self->device;
1604
1605         try
1606         {
1607                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1608                 if(device)
1609                 {
1610                         return Py_BuildValue("f", device->getVolumeMinimum(self->handle));
1611                 }
1612                 else
1613                 {
1614                         PyErr_SetString(AUDError, device_not_3d_error);
1615                         return NULL;
1616                 }
1617         }
1618         catch(AUD_Exception& e)
1619         {
1620                 PyErr_SetString(AUDError, e.str);
1621                 return NULL;
1622         }
1623 }
1624
1625 static int
1626 Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing)
1627 {
1628         float volume;
1629
1630         if(!PyArg_Parse(args, "f:volume_minimum", &volume))
1631                 return -1;
1632
1633         Device* dev = (Device*)self->device;
1634
1635         try
1636         {
1637                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1638                 if(device)
1639                 {
1640                         if(device->setVolumeMinimum(self->handle, volume))
1641                                 return 0;
1642                         PyErr_SetString(AUDError, "Couldn't set the minimum volume!");
1643                 }
1644                 else
1645                         PyErr_SetString(AUDError, device_not_3d_error);
1646         }
1647         catch(AUD_Exception& e)
1648         {
1649                 PyErr_SetString(AUDError, e.str);
1650         }
1651
1652         return -1;
1653 }
1654
1655 PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc,
1656                          "The maximum volume of the source.\n\n"
1657                          ".. seealso:: :attr:`Device.distance_model`");
1658
1659 static PyObject *
1660 Handle_get_volume_maximum(Handle *self, void* nothing)
1661 {
1662         Device* dev = (Device*)self->device;
1663
1664         try
1665         {
1666                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1667                 if(device)
1668                 {
1669                         return Py_BuildValue("f", device->getVolumeMaximum(self->handle));
1670                 }
1671                 else
1672                 {
1673                         PyErr_SetString(AUDError, device_not_3d_error);
1674                         return NULL;
1675                 }
1676         }
1677         catch(AUD_Exception& e)
1678         {
1679                 PyErr_SetString(AUDError, e.str);
1680                 return NULL;
1681         }
1682 }
1683
1684 static int
1685 Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing)
1686 {
1687         float volume;
1688
1689         if(!PyArg_Parse(args, "f:volume_maximum", &volume))
1690                 return -1;
1691
1692         Device* dev = (Device*)self->device;
1693
1694         try
1695         {
1696                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1697                 if(device)
1698                 {
1699                         if(device->setVolumeMaximum(self->handle, volume))
1700                                 return 0;
1701                         PyErr_SetString(AUDError, "Couldn't set the maximum volume!");
1702                 }
1703                 else
1704                         PyErr_SetString(AUDError, device_not_3d_error);
1705         }
1706         catch(AUD_Exception& e)
1707         {
1708                 PyErr_SetString(AUDError, e.str);
1709         }
1710
1711         return -1;
1712 }
1713
1714 PyDoc_STRVAR(M_aud_Handle_distance_reference_doc,
1715                          "The reference distance of the source.\n"
1716                          "At this distance the volume will be exactly :attr:`volume`.\n\n"
1717                          ".. seealso:: :attr:`Device.distance_model`");
1718
1719 static PyObject *
1720 Handle_get_distance_reference(Handle *self, void* nothing)
1721 {
1722         Device* dev = (Device*)self->device;
1723
1724         try
1725         {
1726                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1727                 if(device)
1728                 {
1729                         return Py_BuildValue("f", device->getDistanceReference(self->handle));
1730                 }
1731                 else
1732                 {
1733                         PyErr_SetString(AUDError, device_not_3d_error);
1734                         return NULL;
1735                 }
1736         }
1737         catch(AUD_Exception& e)
1738         {
1739                 PyErr_SetString(AUDError, e.str);
1740                 return NULL;
1741         }
1742 }
1743
1744 static int
1745 Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing)
1746 {
1747         float distance;
1748
1749         if(!PyArg_Parse(args, "f:distance_reference", &distance))
1750                 return -1;
1751
1752         Device* dev = (Device*)self->device;
1753
1754         try
1755         {
1756                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1757                 if(device)
1758                 {
1759                         if(device->setDistanceReference(self->handle, distance))
1760                                 return 0;
1761                         PyErr_SetString(AUDError, "Couldn't set the reference distance!");
1762                 }
1763                 else
1764                         PyErr_SetString(AUDError, device_not_3d_error);
1765         }
1766         catch(AUD_Exception& e)
1767         {
1768                 PyErr_SetString(AUDError, e.str);
1769         }
1770
1771         return -1;
1772 }
1773
1774 PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc,
1775                          "The maximum distance of the source.\n"
1776                          "If the listener is further away the source volume will be 0.\n\n"
1777                          ".. seealso:: :attr:`Device.distance_model`");
1778
1779 static PyObject *
1780 Handle_get_distance_maximum(Handle *self, void* nothing)
1781 {
1782         Device* dev = (Device*)self->device;
1783
1784         try
1785         {
1786                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1787                 if(device)
1788                 {
1789                         return Py_BuildValue("f", device->getDistanceMaximum(self->handle));
1790                 }
1791                 else
1792                 {
1793                         PyErr_SetString(AUDError, device_not_3d_error);
1794                         return NULL;
1795                 }
1796         }
1797         catch(AUD_Exception& e)
1798         {
1799                 PyErr_SetString(AUDError, e.str);
1800                 return NULL;
1801         }
1802 }
1803
1804 static int
1805 Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing)
1806 {
1807         float distance;
1808
1809         if(!PyArg_Parse(args, "f:distance_maximum", &distance))
1810                 return -1;
1811
1812         Device* dev = (Device*)self->device;
1813
1814         try
1815         {
1816                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1817                 if(device)
1818                 {
1819                         if(device->setDistanceMaximum(self->handle, distance))
1820                                 return 0;
1821                         PyErr_SetString(AUDError, "Couldn't set the maximum distance!");
1822                 }
1823                 else
1824                         PyErr_SetString(AUDError, device_not_3d_error);
1825         }
1826         catch(AUD_Exception& e)
1827         {
1828                 PyErr_SetString(AUDError, e.str);
1829         }
1830
1831         return -1;
1832 }
1833
1834 PyDoc_STRVAR(M_aud_Handle_attenuation_doc,
1835                          "This factor is used for distance based attenuation of the "
1836                          "source.\n\n"
1837                          ".. seealso:: :attr:`Device.distance_model`");
1838
1839 static PyObject *
1840 Handle_get_attenuation(Handle *self, void* nothing)
1841 {
1842         Device* dev = (Device*)self->device;
1843
1844         try
1845         {
1846                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1847                 if(device)
1848                 {
1849                         return Py_BuildValue("f", device->getAttenuation(self->handle));
1850                 }
1851                 else
1852                 {
1853                         PyErr_SetString(AUDError, device_not_3d_error);
1854                         return NULL;
1855                 }
1856         }
1857         catch(AUD_Exception& e)
1858         {
1859                 PyErr_SetString(AUDError, e.str);
1860                 return NULL;
1861         }
1862 }
1863
1864 static int
1865 Handle_set_attenuation(Handle *self, PyObject* args, void* nothing)
1866 {
1867         float factor;
1868
1869         if(!PyArg_Parse(args, "f:attenuation", &factor))
1870                 return -1;
1871
1872         Device* dev = (Device*)self->device;
1873
1874         try
1875         {
1876                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1877                 if(device)
1878                 {
1879                         if(device->setAttenuation(self->handle, factor))
1880                                 return 0;
1881                         PyErr_SetString(AUDError, "Couldn't set the attenuation!");
1882                 }
1883                 else
1884                         PyErr_SetString(AUDError, device_not_3d_error);
1885         }
1886         catch(AUD_Exception& e)
1887         {
1888                 PyErr_SetString(AUDError, e.str);
1889         }
1890
1891         return -1;
1892 }
1893
1894 PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc,
1895                          "The opening angle of the inner cone of the source. If the cone "
1896                          "values of a source are set there are two (audible) cones with "
1897                          "the apex at the :attr:`location` of the source and with infinite "
1898                          "height, heading in the direction of the source's "
1899                          ":attr:`orientation`.\n"
1900                          "In the inner cone the volume is normal. Outside the outer cone "
1901                          "the volume will be :attr:`cone_volume_outer` and in the area "
1902                          "between the volume will be interpolated linearly.");
1903
1904 static PyObject *
1905 Handle_get_cone_angle_inner(Handle *self, void* nothing)
1906 {
1907         Device* dev = (Device*)self->device;
1908
1909         try
1910         {
1911                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1912                 if(device)
1913                 {
1914                         return Py_BuildValue("f", device->getConeAngleInner(self->handle));
1915                 }
1916                 else
1917                 {
1918                         PyErr_SetString(AUDError, device_not_3d_error);
1919                         return NULL;
1920                 }
1921         }
1922         catch(AUD_Exception& e)
1923         {
1924                 PyErr_SetString(AUDError, e.str);
1925                 return NULL;
1926         }
1927 }
1928
1929 static int
1930 Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing)
1931 {
1932         float angle;
1933
1934         if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
1935                 return -1;
1936
1937         Device* dev = (Device*)self->device;
1938
1939         try
1940         {
1941                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1942                 if(device)
1943                 {
1944                         if(device->setConeAngleInner(self->handle, angle))
1945                                 return 0;
1946                         PyErr_SetString(AUDError, "Couldn't set the cone inner angle!");
1947                 }
1948                 else
1949                         PyErr_SetString(AUDError, device_not_3d_error);
1950         }
1951         catch(AUD_Exception& e)
1952         {
1953                 PyErr_SetString(AUDError, e.str);
1954         }
1955
1956         return -1;
1957 }
1958
1959 PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc,
1960                          "The opening angle of the outer cone of the source.\n\n"
1961                          ".. seealso:: :attr:`cone_angle_inner`");
1962
1963 static PyObject *
1964 Handle_get_cone_angle_outer(Handle *self, void* nothing)
1965 {
1966         Device* dev = (Device*)self->device;
1967
1968         try
1969         {
1970                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1971                 if(device)
1972                 {
1973                         return Py_BuildValue("f", device->getConeAngleOuter(self->handle));
1974                 }
1975                 else
1976                 {
1977                         PyErr_SetString(AUDError, device_not_3d_error);
1978                         return NULL;
1979                 }
1980         }
1981         catch(AUD_Exception& e)
1982         {
1983                 PyErr_SetString(AUDError, e.str);
1984                 return NULL;
1985         }
1986 }
1987
1988 static int
1989 Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing)
1990 {
1991         float angle;
1992
1993         if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
1994                 return -1;
1995
1996         Device* dev = (Device*)self->device;
1997
1998         try
1999         {
2000                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2001                 if(device)
2002                 {
2003                         if(device->setConeAngleOuter(self->handle, angle))
2004                                 return 0;
2005                         PyErr_SetString(AUDError, "Couldn't set the cone outer angle!");
2006                 }
2007                 else
2008                         PyErr_SetString(AUDError, device_not_3d_error);
2009         }
2010         catch(AUD_Exception& e)
2011         {
2012                 PyErr_SetString(AUDError, e.str);
2013         }
2014
2015         return -1;
2016 }
2017
2018 PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc,
2019                          "The volume outside the outer cone of the source.\n\n"
2020                          ".. seealso:: :attr:`cone_angle_inner`");
2021
2022 static PyObject *
2023 Handle_get_cone_volume_outer(Handle *self, void* nothing)
2024 {
2025         Device* dev = (Device*)self->device;
2026
2027         try
2028         {
2029                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2030                 if(device)
2031                 {
2032                         return Py_BuildValue("f", device->getConeVolumeOuter(self->handle));
2033                 }
2034                 else
2035                 {
2036                         PyErr_SetString(AUDError, device_not_3d_error);
2037                         return NULL;
2038                 }
2039         }
2040         catch(AUD_Exception& e)
2041         {
2042                 PyErr_SetString(AUDError, e.str);
2043                 return NULL;
2044         }
2045 }
2046
2047 static int
2048 Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing)
2049 {
2050         float volume;
2051
2052         if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
2053                 return -1;
2054
2055         Device* dev = (Device*)self->device;
2056
2057         try
2058         {
2059                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2060                 if(device)
2061                 {
2062                         if(device->setConeVolumeOuter(self->handle, volume))
2063                                 return 0;
2064                         PyErr_SetString(AUDError, "Couldn't set the cone outer volume!");
2065                 }
2066                 else
2067                         PyErr_SetString(AUDError, device_not_3d_error);
2068         }
2069         catch(AUD_Exception& e)
2070         {
2071                 PyErr_SetString(AUDError, e.str);
2072         }
2073
2074         return -1;
2075 }
2076
2077 static PyGetSetDef Handle_properties[] = {
2078         {(char*)"position", (getter)Handle_get_position, (setter)Handle_set_position,
2079          M_aud_Handle_position_doc, NULL },
2080         {(char*)"keep", (getter)Handle_get_keep, (setter)Handle_set_keep,
2081          M_aud_Handle_keep_doc, NULL },
2082         {(char*)"status", (getter)Handle_get_status, NULL,
2083          M_aud_Handle_status_doc, NULL },
2084         {(char*)"volume", (getter)Handle_get_volume, (setter)Handle_set_volume,
2085          M_aud_Handle_volume_doc, NULL },
2086         {(char*)"pitch", (getter)Handle_get_pitch, (setter)Handle_set_pitch,
2087          M_aud_Handle_pitch_doc, NULL },
2088         {(char*)"loop_count", (getter)Handle_get_loop_count, (setter)Handle_set_loop_count,
2089          M_aud_Handle_loop_count_doc, NULL },
2090         {(char*)"location", (getter)Handle_get_location, (setter)Handle_set_location,
2091          M_aud_Handle_location_doc, NULL },
2092         {(char*)"velocity", (getter)Handle_get_velocity, (setter)Handle_set_velocity,
2093          M_aud_Handle_velocity_doc, NULL },
2094         {(char*)"orientation", (getter)Handle_get_orientation, (setter)Handle_set_orientation,
2095          M_aud_Handle_orientation_doc, NULL },
2096         {(char*)"relative", (getter)Handle_get_relative, (setter)Handle_set_relative,
2097          M_aud_Handle_relative_doc, NULL },
2098         {(char*)"volume_minimum", (getter)Handle_get_volume_minimum, (setter)Handle_set_volume_minimum,
2099          M_aud_Handle_volume_minimum_doc, NULL },
2100         {(char*)"volume_maximum", (getter)Handle_get_volume_maximum, (setter)Handle_set_volume_maximum,
2101          M_aud_Handle_volume_maximum_doc, NULL },
2102         {(char*)"distance_reference", (getter)Handle_get_distance_reference, (setter)Handle_set_distance_reference,
2103          M_aud_Handle_distance_reference_doc, NULL },
2104         {(char*)"distance_maximum", (getter)Handle_get_distance_maximum, (setter)Handle_set_distance_maximum,
2105          M_aud_Handle_distance_maximum_doc, NULL },
2106         {(char*)"attenuation", (getter)Handle_get_attenuation, (setter)Handle_set_attenuation,
2107          M_aud_Handle_attenuation_doc, NULL },
2108         {(char*)"cone_angle_inner", (getter)Handle_get_cone_angle_inner, (setter)Handle_set_cone_angle_inner,
2109          M_aud_Handle_cone_angle_inner_doc, NULL },
2110         {(char*)"cone_angle_outer", (getter)Handle_get_cone_angle_outer, (setter)Handle_set_cone_angle_outer,
2111          M_aud_Handle_cone_angle_outer_doc, NULL },
2112         {(char*)"cone_volume_outer", (getter)Handle_get_cone_volume_outer, (setter)Handle_set_cone_volume_outer,
2113          M_aud_Handle_cone_volume_outer_doc, NULL },
2114         {NULL}  /* Sentinel */
2115 };
2116
2117 PyDoc_STRVAR(M_aud_Handle_doc,
2118                          "Handle objects are playback handles that can be used to control "
2119                          "playback of a sound. If a sound is played back multiple times "
2120                          "then there are as many handles.");
2121
2122 static PyTypeObject HandleType = {
2123         PyVarObject_HEAD_INIT(NULL, 0)
2124         "aud.Handle",              /* tp_name */
2125         sizeof(Handle),            /* tp_basicsize */
2126         0,                         /* tp_itemsize */
2127         (destructor)Handle_dealloc,/* tp_dealloc */
2128         0,                         /* tp_print */
2129         0,                         /* tp_getattr */
2130         0,                         /* tp_setattr */
2131         0,                         /* tp_reserved */
2132         0,                         /* tp_repr */
2133         0,                         /* tp_as_number */
2134         0,                         /* tp_as_sequence */
2135         0,                         /* tp_as_mapping */
2136         0,                         /* tp_hash  */
2137         0,                         /* tp_call */
2138         0,                         /* tp_str */
2139         0,                         /* tp_getattro */
2140         0,                         /* tp_setattro */
2141         0,                         /* tp_as_buffer */
2142         Py_TPFLAGS_DEFAULT,        /* tp_flags */
2143         M_aud_Handle_doc,          /* tp_doc */
2144         0,                                 /* tp_traverse */
2145         0,                                 /* tp_clear */
2146         0,                                 /* tp_richcompare */
2147         0,                                 /* tp_weaklistoffset */
2148         0,                                 /* tp_iter */
2149         0,                                 /* tp_iternext */
2150         Handle_methods,            /* tp_methods */
2151         0,                         /* tp_members */
2152         Handle_properties,         /* tp_getset */
2153         0,                         /* tp_base */
2154         0,                         /* tp_dict */
2155         0,                         /* tp_descr_get */
2156         0,                         /* tp_descr_set */
2157         0,                         /* tp_dictoffset */
2158         0,                         /* tp_init */
2159         0,                         /* tp_alloc */
2160         0,                         /* tp_new */
2161 };
2162
2163 // ========== Device ==================================================
2164
2165 static void
2166 Device_dealloc(Device* self)
2167 {
2168         if(self->device)
2169                 delete self->device;
2170         Py_TYPE(self)->tp_free((PyObject*)self);
2171 }
2172
2173 static PyObject *
2174 Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2175 {
2176         Device *self;
2177
2178         static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL};
2179         int device;
2180         int rate = AUD_RATE_44100;
2181         int channels = AUD_CHANNELS_STEREO;
2182         int format = AUD_FORMAT_FLOAT32;
2183         int buffersize = AUD_DEFAULT_BUFFER_SIZE;
2184         const char* name = "Audaspace";
2185
2186         if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiis:Device", const_cast<char**>(kwlist),
2187                                                                         &device, &rate, &channels, &format, &buffersize, &name))
2188                 return NULL;
2189
2190         if(buffersize < 128)
2191         {
2192                 PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than 127!");
2193                 return NULL;
2194         }
2195
2196         self = (Device*)type->tp_alloc(type, 0);
2197         if(self != NULL)
2198         {
2199                 AUD_DeviceSpecs specs;
2200                 specs.channels = (AUD_Channels)channels;
2201                 specs.format = (AUD_SampleFormat)format;
2202                 specs.rate = (AUD_SampleRate)rate;
2203
2204                 self->device = NULL;
2205
2206                 try
2207                 {
2208                         switch(device)
2209                         {
2210                         case AUD_DEVICE_NULL:
2211                                 self->device = new AUD_NULLDevice();
2212                                 break;
2213                         case AUD_DEVICE_OPENAL:
2214 #ifdef WITH_OPENAL
2215                                 self->device = new AUD_OpenALDevice(specs, buffersize);
2216 #endif
2217                                 break;
2218                         case AUD_DEVICE_SDL:
2219 #ifdef WITH_SDL
2220                                 self->device = new AUD_SDLDevice(specs, buffersize);
2221 #endif
2222                                 break;
2223                         case AUD_DEVICE_JACK:
2224 #ifdef WITH_JACK
2225                                 self->device = new AUD_JackDevice(name, specs, buffersize);
2226 #endif
2227                                 break;
2228                         case AUD_DEVICE_READ:
2229                                 break;
2230                         }
2231
2232                 }
2233                 catch(AUD_Exception& e)
2234                 {
2235                         Py_DECREF(self);
2236                         PyErr_SetString(AUDError, e.str);
2237                         return NULL;
2238                 }
2239
2240                 if(!self->device)
2241                 {
2242                         Py_DECREF(self);
2243                         PyErr_SetString(AUDError, "Unsupported device type!");
2244                         return NULL;
2245                 }
2246         }
2247
2248         return (PyObject *)self;
2249 }
2250
2251 PyDoc_STRVAR(M_aud_Device_play_doc,
2252                          "play(factory, keep=False)\n\n"
2253                          "Plays a factory.\n\n"
2254                          ":arg factory: The factory to play.\n"
2255                          ":type factory: :class:`Factory`\n"
2256                          ":arg keep: See :attr:`Handle.keep`.\n"
2257                          ":type keep: bool\n"
2258                          ":return: The playback handle with which playback can be "
2259                          "controlled with.\n"
2260                          ":rtype: :class:`Handle`");
2261
2262 static PyObject *
2263 Device_play(Device *self, PyObject *args, PyObject *kwds)
2264 {
2265         PyObject* object;
2266         PyObject* keepo = NULL;
2267
2268         bool keep = false;
2269
2270         static const char *kwlist[] = {"factory", "keep", NULL};
2271
2272         if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:play", const_cast<char**>(kwlist), &object, &keepo))
2273                 return NULL;
2274
2275         if(!PyObject_TypeCheck(object, &FactoryType))
2276         {
2277                 PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
2278                 return NULL;
2279         }
2280
2281         if(keepo != NULL)
2282         {
2283                 if(!PyBool_Check(keepo))
2284                 {
2285                         PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
2286                         return NULL;
2287                 }
2288
2289                 keep = keepo == Py_True;
2290         }
2291
2292         Factory* sound = (Factory*)object;
2293         Handle *handle;
2294
2295         handle = (Handle*)HandleType.tp_alloc(&HandleType, 0);
2296         if(handle != NULL)
2297         {
2298                 handle->device = (PyObject*)self;
2299                 Py_INCREF(self);
2300
2301                 try
2302                 {
2303                         handle->handle = self->device->play(sound->factory, keep);
2304                 }
2305                 catch(AUD_Exception& e)
2306                 {
2307                         Py_DECREF(handle);
2308                         PyErr_SetString(AUDError, e.str);
2309                         return NULL;
2310                 }
2311         }
2312
2313         return (PyObject *)handle;
2314 }
2315
2316 PyDoc_STRVAR(M_aud_Device_lock_doc,
2317                          "lock()\n\n"
2318                          "Locks the device so that it's guaranteed, that no samples are "
2319                          "read from the streams until :meth:`unlock` is called.\n"
2320                          "This is useful if you want to do start/stop/pause/resume some "
2321                          "sounds at the same time.\n\n"
2322                          ".. note:: The device has to be unlocked as often as locked to be "
2323                          "able to continue playback.\n\n"
2324                          ".. warning:: Make sure the time between locking and unlocking is "
2325                          "as short as possible to avoid clicks.");
2326
2327 static PyObject *
2328 Device_lock(Device *self)
2329 {
2330         try
2331         {
2332                 self->device->lock();
2333                 Py_RETURN_NONE;
2334         }
2335         catch(AUD_Exception& e)
2336         {
2337                 PyErr_SetString(AUDError, e.str);
2338                 return NULL;
2339         }
2340 }
2341
2342 PyDoc_STRVAR(M_aud_Device_unlock_doc,
2343                          "unlock()\n\n"
2344                          "Unlocks the device after a lock call, see :meth:`lock` for "
2345                          "details.");
2346
2347 static PyObject *
2348 Device_unlock(Device *self)
2349 {
2350         try
2351         {
2352                 self->device->unlock();
2353                 Py_RETURN_NONE;
2354         }
2355         catch(AUD_Exception& e)
2356         {
2357                 PyErr_SetString(AUDError, e.str);
2358                 return NULL;
2359         }
2360 }
2361
2362 static PyMethodDef Device_methods[] = {
2363         {"play", (PyCFunction)Device_play, METH_VARARGS | METH_KEYWORDS,
2364          M_aud_Device_play_doc
2365         },
2366         {"lock", (PyCFunction)Device_lock, METH_NOARGS,
2367          M_aud_Device_lock_doc
2368         },
2369         {"unlock", (PyCFunction)Device_unlock, METH_NOARGS,
2370          M_aud_Device_unlock_doc
2371         },
2372         {NULL}  /* Sentinel */
2373 };
2374
2375 PyDoc_STRVAR(M_aud_Device_rate_doc,
2376                          "The sampling rate of the device in Hz.");
2377
2378 static PyObject *
2379 Device_get_rate(Device *self, void* nothing)
2380 {
2381         try
2382         {
2383                 AUD_DeviceSpecs specs = self->device->getSpecs();
2384                 return Py_BuildValue("i", specs.rate);
2385         }
2386         catch(AUD_Exception& e)
2387         {
2388                 PyErr_SetString(AUDError, e.str);
2389                 return NULL;
2390         }
2391 }
2392
2393 PyDoc_STRVAR(M_aud_Device_format_doc,
2394                          "The native sample format of the device.");
2395
2396 static PyObject *
2397 Device_get_format(Device *self, void* nothing)
2398 {
2399         try
2400         {
2401                 AUD_DeviceSpecs specs = self->device->getSpecs();
2402                 return Py_BuildValue("i", specs.format);
2403         }
2404         catch(AUD_Exception& e)
2405         {
2406                 PyErr_SetString(AUDError, e.str);
2407                 return NULL;
2408         }
2409 }
2410
2411 PyDoc_STRVAR(M_aud_Device_channels_doc,
2412                          "The channel count of the device.");
2413
2414 static PyObject *
2415 Device_get_channels(Device *self, void* nothing)
2416 {
2417         try
2418         {
2419                 AUD_DeviceSpecs specs = self->device->getSpecs();
2420                 return Py_BuildValue("i", specs.channels);
2421         }
2422         catch(AUD_Exception& e)
2423         {
2424                 PyErr_SetString(AUDError, e.str);
2425                 return NULL;
2426         }
2427 }
2428
2429 PyDoc_STRVAR(M_aud_Device_volume_doc,
2430                          "The overall volume of the device.");
2431
2432 static PyObject *
2433 Device_get_volume(Device *self, void* nothing)
2434 {
2435         try
2436         {
2437                 return Py_BuildValue("f", self->device->getVolume());
2438         }
2439         catch(AUD_Exception& e)
2440         {
2441                 PyErr_SetString(AUDError, e.str);
2442                 return NULL;
2443         }
2444 }
2445
2446 static int
2447 Device_set_volume(Device *self, PyObject* args, void* nothing)
2448 {
2449         float volume;
2450
2451         if(!PyArg_Parse(args, "f:volume", &volume))
2452                 return -1;
2453
2454         try
2455         {
2456                 self->device->setVolume(volume);
2457                 return 0;
2458         }
2459         catch(AUD_Exception& e)
2460         {
2461                 PyErr_SetString(AUDError, e.str);
2462                 return -1;
2463         }
2464 }
2465
2466 PyDoc_STRVAR(M_aud_Device_listener_location_doc,
2467                          "The listeners's location in 3D space, a 3D tuple of floats.");
2468
2469 static PyObject *
2470 Device_get_listener_location(Device *self, void* nothing)
2471 {
2472         try
2473         {
2474                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2475                 if(device)
2476                 {
2477                         AUD_Vector3 v = device->getListenerLocation();
2478                         return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
2479                 }
2480                 else
2481                 {
2482                         PyErr_SetString(AUDError, device_not_3d_error);
2483                 }
2484         }
2485         catch(AUD_Exception& e)
2486         {
2487                 PyErr_SetString(AUDError, e.str);
2488         }
2489
2490         return NULL;
2491 }
2492
2493 static int
2494 Device_set_listener_location(Device *self, PyObject* args, void* nothing)
2495 {
2496         float x, y, z;
2497
2498         if(!PyArg_Parse(args, "(fff):listener_location", &x, &y, &z))
2499                 return -1;
2500
2501         try
2502         {
2503                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2504                 if(device)
2505                 {
2506                         AUD_Vector3 location(x, y, z);
2507                         device->setListenerLocation(location);
2508                         return 0;
2509                 }
2510                 else
2511                         PyErr_SetString(AUDError, device_not_3d_error);
2512         }
2513         catch(AUD_Exception& e)
2514         {
2515                 PyErr_SetString(AUDError, e.str);
2516         }
2517
2518         return -1;
2519 }
2520
2521 PyDoc_STRVAR(M_aud_Device_listener_velocity_doc,
2522                          "The listener's velocity in 3D space, a 3D tuple of floats.");
2523
2524 static PyObject *
2525 Device_get_listener_velocity(Device *self, void* nothing)
2526 {
2527         try
2528         {
2529                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2530                 if(device)
2531                 {
2532                         AUD_Vector3 v = device->getListenerVelocity();
2533                         return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
2534                 }
2535                 else
2536                 {
2537                         PyErr_SetString(AUDError, device_not_3d_error);
2538                 }
2539         }
2540         catch(AUD_Exception& e)
2541         {
2542                 PyErr_SetString(AUDError, e.str);
2543         }
2544
2545         return NULL;
2546 }
2547
2548 static int
2549 Device_set_listener_velocity(Device *self, PyObject* args, void* nothing)
2550 {
2551         float x, y, z;
2552
2553         if(!PyArg_Parse(args, "(fff):listener_velocity", &x, &y, &z))
2554                 return -1;
2555
2556         try
2557         {
2558                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2559                 if(device)
2560                 {
2561                         AUD_Vector3 velocity(x, y, z);
2562                         device->setListenerVelocity(velocity);
2563                         return 0;
2564                 }
2565                 else
2566                         PyErr_SetString(AUDError, device_not_3d_error);
2567         }
2568         catch(AUD_Exception& e)
2569         {
2570                 PyErr_SetString(AUDError, e.str);
2571         }
2572
2573         return -1;
2574 }
2575
2576 PyDoc_STRVAR(M_aud_Device_listener_orientation_doc,
2577                          "The listener's orientation in 3D space as quaternion, a 4 float tuple.");
2578
2579 static PyObject *
2580 Device_get_listener_orientation(Device *self, void* nothing)
2581 {
2582         try
2583         {
2584                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2585                 if(device)
2586                 {
2587                         AUD_Quaternion o = device->getListenerOrientation();
2588                         return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
2589                 }
2590                 else
2591                 {
2592                         PyErr_SetString(AUDError, device_not_3d_error);
2593                 }
2594         }
2595         catch(AUD_Exception& e)
2596         {
2597                 PyErr_SetString(AUDError, e.str);
2598         }
2599
2600         return NULL;
2601 }
2602
2603 static int
2604 Device_set_listener_orientation(Device *self, PyObject* args, void* nothing)
2605 {
2606         float w, x, y, z;
2607
2608         if(!PyArg_Parse(args, "(ffff):listener_orientation", &w, &x, &y, &z))
2609                 return -1;
2610
2611         try
2612         {
2613                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2614                 if(device)
2615                 {
2616                         AUD_Quaternion orientation(w, x, y, z);
2617                         device->setListenerOrientation(orientation);
2618                         return 0;
2619                 }
2620                 else
2621                         PyErr_SetString(AUDError, device_not_3d_error);
2622         }
2623         catch(AUD_Exception& e)
2624         {
2625                 PyErr_SetString(AUDError, e.str);
2626         }
2627
2628         return -1;
2629 }
2630
2631 PyDoc_STRVAR(M_aud_Device_speed_of_sound_doc,
2632                          "The speed of sound of the device.\n"
2633                          "The speed of sound in air is typically 343 m/s.");
2634
2635 static PyObject *
2636 Device_get_speed_of_sound(Device *self, void* nothing)
2637 {
2638         try
2639         {
2640                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2641                 if(device)
2642                 {
2643                         return Py_BuildValue("f", device->getSpeedOfSound());
2644                 }
2645                 else
2646                 {
2647                         PyErr_SetString(AUDError, device_not_3d_error);
2648                         return NULL;
2649                 }
2650         }
2651         catch(AUD_Exception& e)
2652         {
2653                 PyErr_SetString(AUDError, e.str);
2654                 return NULL;
2655         }
2656 }
2657
2658 static int
2659 Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing)
2660 {
2661         float speed;
2662
2663         if(!PyArg_Parse(args, "f:speed_of_sound", &speed))
2664                 return -1;
2665
2666         try
2667         {
2668                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2669                 if(device)
2670                 {
2671                         device->setSpeedOfSound(speed);
2672                         return 0;
2673                 }
2674                 else
2675                         PyErr_SetString(AUDError, device_not_3d_error);
2676         }
2677         catch(AUD_Exception& e)
2678         {
2679                 PyErr_SetString(AUDError, e.str);
2680         }
2681
2682         return -1;
2683 }
2684
2685 PyDoc_STRVAR(M_aud_Device_doppler_factor_doc,
2686                          "The doppler factor of the device.\n"
2687                          "This factor is a scaling factor for the velocity vectors in "
2688                          "doppler calculation. So a value bigger than 1 will exaggerate "
2689                          "the effect as it raises the velocity.");
2690
2691 static PyObject *
2692 Device_get_doppler_factor(Device *self, void* nothing)
2693 {
2694         try
2695         {
2696                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2697                 if(device)
2698                 {
2699                         return Py_BuildValue("f", device->getDopplerFactor());
2700                 }
2701                 else
2702                 {
2703                         PyErr_SetString(AUDError, device_not_3d_error);
2704                         return NULL;
2705                 }
2706         }
2707         catch(AUD_Exception& e)
2708         {
2709                 PyErr_SetString(AUDError, e.str);
2710                 return NULL;
2711         }
2712 }
2713
2714 static int
2715 Device_set_doppler_factor(Device *self, PyObject* args, void* nothing)
2716 {
2717         float factor;
2718
2719         if(!PyArg_Parse(args, "f:doppler_factor", &factor))
2720                 return -1;
2721
2722         try
2723         {
2724                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2725                 if(device)
2726                 {
2727                         device->setDopplerFactor(factor);
2728                         return 0;
2729                 }
2730                 else
2731                         PyErr_SetString(AUDError, device_not_3d_error);
2732         }
2733         catch(AUD_Exception& e)
2734         {
2735                 PyErr_SetString(AUDError, e.str);
2736         }
2737
2738         return -1;
2739 }
2740
2741 PyDoc_STRVAR(M_aud_Device_distance_model_doc,
2742                          "The distance model of the device.\n\n"
2743                          ".. seealso:: http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835864");
2744
2745 static PyObject *
2746 Device_get_distance_model(Device *self, void* nothing)
2747 {
2748         try
2749         {
2750                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2751                 if(device)
2752                 {
2753                         return Py_BuildValue("i", int(device->getDistanceModel()));
2754                 }
2755                 else
2756                 {
2757                         PyErr_SetString(AUDError, device_not_3d_error);
2758                         return NULL;
2759                 }
2760         }
2761         catch(AUD_Exception& e)
2762         {
2763                 PyErr_SetString(AUDError, e.str);
2764                 return NULL;
2765         }
2766 }
2767
2768 static int
2769 Device_set_distance_model(Device *self, PyObject* args, void* nothing)
2770 {
2771         int model;
2772
2773         if(!PyArg_Parse(args, "i:distance_model", &model))
2774                 return -1;
2775
2776         try
2777         {
2778                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2779                 if(device)
2780                 {
2781                         device->setDistanceModel(AUD_DistanceModel(model));
2782                         return 0;
2783                 }
2784                 else
2785                         PyErr_SetString(AUDError, device_not_3d_error);
2786         }
2787         catch(AUD_Exception& e)
2788         {
2789                 PyErr_SetString(AUDError, e.str);
2790         }
2791
2792         return -1;
2793 }
2794
2795 static PyGetSetDef Device_properties[] = {
2796         {(char*)"rate", (getter)Device_get_rate, NULL,
2797          M_aud_Device_rate_doc, NULL },
2798         {(char*)"format", (getter)Device_get_format, NULL,
2799          M_aud_Device_format_doc, NULL },
2800         {(char*)"channels", (getter)Device_get_channels, NULL,
2801          M_aud_Device_channels_doc, NULL },
2802         {(char*)"volume", (getter)Device_get_volume, (setter)Device_set_volume,
2803          M_aud_Device_volume_doc, NULL },
2804         {(char*)"listener_location", (getter)Device_get_listener_location, (setter)Device_set_listener_location,
2805          M_aud_Device_listener_location_doc, NULL },
2806         {(char*)"listener_velocity", (getter)Device_get_listener_velocity, (setter)Device_set_listener_velocity,
2807          M_aud_Device_listener_velocity_doc, NULL },
2808         {(char*)"listener_orientation", (getter)Device_get_listener_orientation, (setter)Device_set_listener_orientation,
2809          M_aud_Device_listener_orientation_doc, NULL },
2810         {(char*)"speed_of_sound", (getter)Device_get_speed_of_sound, (setter)Device_set_speed_of_sound,
2811          M_aud_Device_speed_of_sound_doc, NULL },
2812         {(char*)"doppler_factor", (getter)Device_get_doppler_factor, (setter)Device_set_doppler_factor,
2813          M_aud_Device_doppler_factor_doc, NULL },
2814         {(char*)"distance_model", (getter)Device_get_distance_model, (setter)Device_set_distance_model,
2815          M_aud_Device_distance_model_doc, NULL },
2816         {NULL}  /* Sentinel */
2817 };
2818
2819 PyDoc_STRVAR(M_aud_Device_doc,
2820                          "Device objects represent an audio output backend like OpenAL or "
2821                          "SDL, but might also represent a file output or RAM buffer "
2822                          "output.");
2823
2824 static PyTypeObject DeviceType = {
2825         PyVarObject_HEAD_INIT(NULL, 0)
2826         "aud.Device",              /* tp_name */
2827         sizeof(Device),            /* tp_basicsize */
2828         0,                         /* tp_itemsize */
2829         (destructor)Device_dealloc,/* tp_dealloc */
2830         0,                         /* tp_print */
2831         0,                         /* tp_getattr */
2832         0,                         /* tp_setattr */
2833         0,                         /* tp_reserved */
2834         0,                         /* tp_repr */
2835         0,                         /* tp_as_number */
2836         0,                         /* tp_as_sequence */
2837         0,                         /* tp_as_mapping */
2838         0,                         /* tp_hash  */
2839         0,                         /* tp_call */
2840         0,                         /* tp_str */
2841         0,                         /* tp_getattro */
2842         0,                         /* tp_setattro */
2843         0,                         /* tp_as_buffer */
2844         Py_TPFLAGS_DEFAULT,        /* tp_flags */
2845         M_aud_Device_doc,          /* tp_doc */
2846         0,                                 /* tp_traverse */
2847         0,                                 /* tp_clear */
2848         0,                                 /* tp_richcompare */
2849         0,                                 /* tp_weaklistoffset */
2850         0,                                 /* tp_iter */
2851         0,                                 /* tp_iternext */
2852         Device_methods,            /* tp_methods */
2853         0,                         /* tp_members */
2854         Device_properties,         /* tp_getset */
2855         0,                         /* tp_base */
2856         0,                         /* tp_dict */
2857         0,                         /* tp_descr_get */
2858         0,                         /* tp_descr_set */
2859         0,                         /* tp_dictoffset */
2860         0,                         /* tp_init */
2861         0,                         /* tp_alloc */
2862         Device_new,                /* tp_new */
2863 };
2864
2865 PyObject *
2866 Device_empty()
2867 {
2868         return DeviceType.tp_alloc(&DeviceType, 0);
2869 }
2870
2871 // ====================================================================
2872
2873 PyDoc_STRVAR(M_aud_doc,
2874                          "This module provides access to the audaspace audio library.");
2875
2876 static struct PyModuleDef audmodule = {
2877         PyModuleDef_HEAD_INIT,
2878         "aud",     /* name of module */
2879         M_aud_doc, /* module documentation */
2880         -1,        /* size of per-interpreter state of the module,
2881                                   or -1 if the module keeps state in global variables. */
2882    NULL, NULL, NULL, NULL, NULL
2883 };
2884
2885 PyMODINIT_FUNC
2886 PyInit_aud(void)
2887 {
2888         PyObject* m;
2889
2890         if(PyType_Ready(&FactoryType) < 0)
2891                 return NULL;
2892
2893         if(PyType_Ready(&DeviceType) < 0)
2894                 return NULL;
2895
2896         if(PyType_Ready(&HandleType) < 0)
2897                 return NULL;
2898
2899         m = PyModule_Create(&audmodule);
2900         if(m == NULL)
2901                 return NULL;
2902
2903         Py_INCREF(&FactoryType);
2904         PyModule_AddObject(m, "Factory", (PyObject*)&FactoryType);
2905
2906         Py_INCREF(&DeviceType);
2907         PyModule_AddObject(m, "Device", (PyObject*)&DeviceType);
2908
2909         Py_INCREF(&HandleType);
2910         PyModule_AddObject(m, "Handle", (PyObject*)&HandleType);
2911
2912         AUDError = PyErr_NewException("aud.error", NULL, NULL);
2913         Py_INCREF(AUDError);
2914         PyModule_AddObject(m, "error", AUDError);
2915
2916         // device constants
2917         PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_NULL);
2918         PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_OPENAL);
2919         PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_SDL);
2920         PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_JACK);
2921         //PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_READ);
2922         // format constants
2923         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT32);
2924         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT64);
2925         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_INVALID);
2926         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S16);
2927         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S24);
2928         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S32);
2929         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_U8);
2930         // status constants
2931         PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_INVALID);
2932         PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PAUSED);
2933         PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PLAYING);
2934         // distance model constants
2935         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT);
2936         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT_CLAMPED);
2937         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE);
2938         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE_CLAMPED);
2939         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR);
2940         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR_CLAMPED);
2941         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVALID);
2942
2943         return m;
2944 }