Audaspace:
[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                 if(device->device->pause(self->handle))
1048                 {
1049                         Py_RETURN_TRUE;
1050                 }
1051         }
1052         catch(AUD_Exception& e)
1053         {
1054                 PyErr_SetString(AUDError, e.str);
1055                 return NULL;
1056         }
1057
1058         Py_RETURN_FALSE;
1059 }
1060
1061 PyDoc_STRVAR(M_aud_Handle_resume_doc,
1062                          "resume()\n\n"
1063                          "Resumes playback.\n\n"
1064                          ":return: Whether the action succeeded.\n"
1065                          ":rtype: bool");
1066
1067 static PyObject *
1068 Handle_resume(Handle *self)
1069 {
1070         Device* device = (Device*)self->device;
1071
1072         try
1073         {
1074                 if(device->device->resume(self->handle))
1075                 {
1076                         Py_RETURN_TRUE;
1077                 }
1078         }
1079         catch(AUD_Exception& e)
1080         {
1081                 PyErr_SetString(AUDError, e.str);
1082                 return NULL;
1083         }
1084
1085         Py_RETURN_FALSE;
1086 }
1087
1088 PyDoc_STRVAR(M_aud_Handle_stop_doc,
1089                          "stop()\n\n"
1090                          "Stops playback.\n\n"
1091                          ":return: Whether the action succeeded.\n"
1092                          ":rtype: bool\n\n"
1093                          ".. note:: This makes the handle invalid.");
1094
1095 static PyObject *
1096 Handle_stop(Handle *self)
1097 {
1098         Device* device = (Device*)self->device;
1099
1100         try
1101         {
1102                 if(device->device->stop(self->handle))
1103                 {
1104                         Py_RETURN_TRUE;
1105                 }
1106         }
1107         catch(AUD_Exception& e)
1108         {
1109                 PyErr_SetString(AUDError, e.str);
1110                 return NULL;
1111         }
1112
1113         Py_RETURN_FALSE;
1114 }
1115
1116 static PyMethodDef Handle_methods[] = {
1117         {"pause", (PyCFunction)Handle_pause, METH_NOARGS,
1118          M_aud_Handle_pause_doc
1119         },
1120         {"resume", (PyCFunction)Handle_resume, METH_NOARGS,
1121          M_aud_Handle_resume_doc
1122         },
1123         {"stop", (PyCFunction)Handle_stop, METH_NOARGS,
1124          M_aud_Handle_stop_doc
1125         },
1126         {NULL}  /* Sentinel */
1127 };
1128
1129 PyDoc_STRVAR(M_aud_Handle_position_doc,
1130                          "The playback position of the sound in seconds.");
1131
1132 static PyObject *
1133 Handle_get_position(Handle *self, void* nothing)
1134 {
1135         Device* device = (Device*)self->device;
1136
1137         try
1138         {
1139                 return Py_BuildValue("f", device->device->getPosition(self->handle));
1140         }
1141         catch(AUD_Exception& e)
1142         {
1143                 PyErr_SetString(AUDError, e.str);
1144                 return NULL;
1145         }
1146 }
1147
1148 static int
1149 Handle_set_position(Handle *self, PyObject* args, void* nothing)
1150 {
1151         float position;
1152
1153         if(!PyArg_Parse(args, "f:position", &position))
1154                 return -1;
1155
1156         Device* device = (Device*)self->device;
1157
1158         try
1159         {
1160                 if(device->device->seek(self->handle, position))
1161                         return 0;
1162                 PyErr_SetString(AUDError, "Couldn't seek the sound!");
1163         }
1164         catch(AUD_Exception& e)
1165         {
1166                 PyErr_SetString(AUDError, e.str);
1167         }
1168
1169         return -1;
1170 }
1171
1172 PyDoc_STRVAR(M_aud_Handle_keep_doc,
1173                          "Whether the sound should be kept paused in the device when its "
1174                          "end is reached.\n"
1175                          "This can be used to seek the sound to some position and start "
1176                          "playback again.\n\n"
1177                          ".. warning:: If this is set to true and you forget stopping this "
1178                          "equals a memory leak as the handle exists until the device is "
1179                          "destroyed.");
1180
1181 static PyObject *
1182 Handle_get_keep(Handle *self, void* nothing)
1183 {
1184         Device* device = (Device*)self->device;
1185
1186         try
1187         {
1188                 if(device->device->getKeep(self->handle))
1189                 {
1190                         Py_RETURN_TRUE;
1191                 }
1192                 else
1193                 {
1194                         Py_RETURN_FALSE;
1195                 }
1196         }
1197         catch(AUD_Exception& e)
1198         {
1199                 PyErr_SetString(AUDError, e.str);
1200                 return NULL;
1201         }
1202 }
1203
1204 static int
1205 Handle_set_keep(Handle *self, PyObject* args, void* nothing)
1206 {
1207         if(!PyBool_Check(args))
1208         {
1209                 PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
1210                 return -1;
1211         }
1212
1213         bool keep = args == Py_True;
1214         Device* device = (Device*)self->device;
1215
1216         try
1217         {
1218                 if(device->device->setKeep(self->handle, keep))
1219                         return 0;
1220                 PyErr_SetString(AUDError, "Couldn't set keep of the sound!");
1221         }
1222         catch(AUD_Exception& e)
1223         {
1224                 PyErr_SetString(AUDError, e.str);
1225         }
1226
1227         return -1;
1228 }
1229
1230 PyDoc_STRVAR(M_aud_Handle_status_doc,
1231                          "Whether the sound is playing, paused or stopped (=invalid).");
1232
1233 static PyObject *
1234 Handle_get_status(Handle *self, void* nothing)
1235 {
1236         Device* device = (Device*)self->device;
1237
1238         try
1239         {
1240                 return Py_BuildValue("i", device->device->getStatus(self->handle));
1241         }
1242         catch(AUD_Exception& e)
1243         {
1244                 PyErr_SetString(AUDError, e.str);
1245                 return NULL;
1246         }
1247 }
1248
1249 PyDoc_STRVAR(M_aud_Handle_volume_doc,
1250                          "The volume of the sound.");
1251
1252 static PyObject *
1253 Handle_get_volume(Handle *self, void* nothing)
1254 {
1255         Device* device = (Device*)self->device;
1256
1257         try
1258         {
1259                 return Py_BuildValue("f", device->device->getVolume(self->handle));
1260         }
1261         catch(AUD_Exception& e)
1262         {
1263                 PyErr_SetString(AUDError, e.str);
1264                 return NULL;
1265         }
1266 }
1267
1268 static int
1269 Handle_set_volume(Handle *self, PyObject* args, void* nothing)
1270 {
1271         float volume;
1272
1273         if(!PyArg_Parse(args, "f:volume", &volume))
1274                 return -1;
1275
1276         Device* device = (Device*)self->device;
1277
1278         try
1279         {
1280                 if(device->device->setVolume(self->handle, volume))
1281                         return 0;
1282                 PyErr_SetString(AUDError, "Couldn't set the sound volume!");
1283         }
1284         catch(AUD_Exception& e)
1285         {
1286                 PyErr_SetString(AUDError, e.str);
1287         }
1288
1289         return -1;
1290 }
1291
1292 PyDoc_STRVAR(M_aud_Handle_pitch_doc,
1293                          "The pitch of the sound.");
1294
1295 static PyObject *
1296 Handle_get_pitch(Handle *self, void* nothing)
1297 {
1298         Device* device = (Device*)self->device;
1299
1300         try
1301         {
1302                 return Py_BuildValue("f", device->device->getPitch(self->handle));
1303         }
1304         catch(AUD_Exception& e)
1305         {
1306                 PyErr_SetString(AUDError, e.str);
1307                 return NULL;
1308         }
1309 }
1310
1311 static int
1312 Handle_set_pitch(Handle *self, PyObject* args, void* nothing)
1313 {
1314         float pitch;
1315
1316         if(!PyArg_Parse(args, "f:pitch", &pitch))
1317                 return -1;
1318
1319         Device* device = (Device*)self->device;
1320
1321         try
1322         {
1323                 if(device->device->setPitch(self->handle, pitch))
1324                         return 0;
1325                 PyErr_SetString(AUDError, "Couldn't set the sound pitch!");
1326         }
1327         catch(AUD_Exception& e)
1328         {
1329                 PyErr_SetString(AUDError, e.str);
1330         }
1331
1332         return -1;
1333 }
1334
1335 PyDoc_STRVAR(M_aud_Handle_loop_count_doc,
1336                          "The (remaining) loop count of the sound. A negative value indicates infinity.");
1337
1338 static PyObject *
1339 Handle_get_loop_count(Handle *self, void* nothing)
1340 {
1341         Device* device = (Device*)self->device;
1342
1343         try
1344         {
1345                 return Py_BuildValue("i", device->device->getLoopCount(self->handle));
1346         }
1347         catch(AUD_Exception& e)
1348         {
1349                 PyErr_SetString(AUDError, e.str);
1350                 return NULL;
1351         }
1352 }
1353
1354 static int
1355 Handle_set_loop_count(Handle *self, PyObject* args, void* nothing)
1356 {
1357         int loops;
1358
1359         if(!PyArg_Parse(args, "i:loop_count", &loops))
1360                 return -1;
1361
1362         Device* device = (Device*)self->device;
1363
1364         try
1365         {
1366                 if(device->device->setLoopCount(self->handle, loops))
1367                         return 0;
1368                 PyErr_SetString(AUDError, "Couldn't set the loop count!");
1369         }
1370         catch(AUD_Exception& e)
1371         {
1372                 PyErr_SetString(AUDError, e.str);
1373         }
1374
1375         return -1;
1376 }
1377
1378 PyDoc_STRVAR(M_aud_Handle_location_doc,
1379                          "The source's location in 3D space, a 3D tuple of floats.");
1380
1381 static PyObject *
1382 Handle_get_location(Handle *self, void* nothing)
1383 {
1384         Device* dev = (Device*)self->device;
1385
1386         try
1387         {
1388                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1389                 if(device)
1390                 {
1391                         AUD_Vector3 v = device->getSourceLocation(self->handle);
1392                         return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
1393                 }
1394                 else
1395                 {
1396                         PyErr_SetString(AUDError, device_not_3d_error);
1397                 }
1398         }
1399         catch(AUD_Exception& e)
1400         {
1401                 PyErr_SetString(AUDError, e.str);
1402         }
1403
1404         return NULL;
1405 }
1406
1407 static int
1408 Handle_set_location(Handle *self, PyObject* args, void* nothing)
1409 {
1410         float x, y, z;
1411
1412         if(!PyArg_Parse(args, "(fff):location", &x, &y, &z))
1413                 return -1;
1414
1415         Device* dev = (Device*)self->device;
1416
1417         try
1418         {
1419                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1420                 if(device)
1421                 {
1422                         AUD_Vector3 location(x, y, z);
1423                         if(device->setSourceLocation(self->handle, location))
1424                                 return 0;
1425                         PyErr_SetString(AUDError, "Location couldn't be set!");
1426                 }
1427                 else
1428                         PyErr_SetString(AUDError, device_not_3d_error);
1429         }
1430         catch(AUD_Exception& e)
1431         {
1432                 PyErr_SetString(AUDError, e.str);
1433         }
1434
1435         return -1;
1436 }
1437
1438 PyDoc_STRVAR(M_aud_Handle_velocity_doc,
1439                          "The source's velocity in 3D space, a 3D tuple of floats.");
1440
1441 static PyObject *
1442 Handle_get_velocity(Handle *self, void* nothing)
1443 {
1444         Device* dev = (Device*)self->device;
1445
1446         try
1447         {
1448                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1449                 if(device)
1450                 {
1451                         AUD_Vector3 v = device->getSourceVelocity(self->handle);
1452                         return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
1453                 }
1454                 else
1455                 {
1456                         PyErr_SetString(AUDError, device_not_3d_error);
1457                 }
1458         }
1459         catch(AUD_Exception& e)
1460         {
1461                 PyErr_SetString(AUDError, e.str);
1462         }
1463
1464         return NULL;
1465 }
1466
1467 static int
1468 Handle_set_velocity(Handle *self, PyObject* args, void* nothing)
1469 {
1470         float x, y, z;
1471
1472         if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z))
1473                 return -1;
1474
1475         Device* dev = (Device*)self->device;
1476
1477         try
1478         {
1479                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1480                 if(device)
1481                 {
1482                         AUD_Vector3 velocity(x, y, z);
1483                         if(device->setSourceVelocity(self->handle, velocity))
1484                                 return 0;
1485                         PyErr_SetString(AUDError, "Couldn't set the velocity!");
1486                 }
1487                 else
1488                         PyErr_SetString(AUDError, device_not_3d_error);
1489         }
1490         catch(AUD_Exception& e)
1491         {
1492                 PyErr_SetString(AUDError, e.str);
1493         }
1494
1495         return -1;
1496 }
1497
1498 PyDoc_STRVAR(M_aud_Handle_orientation_doc,
1499                          "The source's orientation in 3D space as quaternion, a 4 float tuple.");
1500
1501 static PyObject *
1502 Handle_get_orientation(Handle *self, void* nothing)
1503 {
1504         Device* dev = (Device*)self->device;
1505
1506         try
1507         {
1508                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1509                 if(device)
1510                 {
1511                         AUD_Quaternion o = device->getSourceOrientation(self->handle);
1512                         return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
1513                 }
1514                 else
1515                 {
1516                         PyErr_SetString(AUDError, device_not_3d_error);
1517                 }
1518         }
1519         catch(AUD_Exception& e)
1520         {
1521                 PyErr_SetString(AUDError, e.str);
1522         }
1523
1524         return NULL;
1525 }
1526
1527 static int
1528 Handle_set_orientation(Handle *self, PyObject* args, void* nothing)
1529 {
1530         float w, x, y, z;
1531
1532         if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z))
1533                 return -1;
1534
1535         Device* dev = (Device*)self->device;
1536
1537         try
1538         {
1539                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1540                 if(device)
1541                 {
1542                         AUD_Quaternion orientation(w, x, y, z);
1543                         if(device->setSourceOrientation(self->handle, orientation))
1544                                 return 0;
1545                         PyErr_SetString(AUDError, "Couldn't set the orientation!");
1546                 }
1547                 else
1548                         PyErr_SetString(AUDError, device_not_3d_error);
1549         }
1550         catch(AUD_Exception& e)
1551         {
1552                 PyErr_SetString(AUDError, e.str);
1553         }
1554
1555         return -1;
1556 }
1557
1558 PyDoc_STRVAR(M_aud_Handle_relative_doc,
1559                          "Whether the source's location, velocity and orientation is relative or absolute to the listener.");
1560
1561 static PyObject *
1562 Handle_get_relative(Handle *self, void* nothing)
1563 {
1564         Device* dev = (Device*)self->device;
1565
1566         try
1567         {
1568                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1569                 if(device)
1570                 {
1571                         if(device->isRelative(self->handle))
1572                         {
1573                                 Py_RETURN_TRUE;
1574                         }
1575                         else
1576                         {
1577                                 Py_RETURN_FALSE;
1578                         }
1579                 }
1580                 else
1581                 {
1582                         PyErr_SetString(AUDError, device_not_3d_error);
1583                 }
1584         }
1585         catch(AUD_Exception& e)
1586         {
1587                 PyErr_SetString(AUDError, e.str);
1588         }
1589
1590         return NULL;
1591 }
1592
1593 static int
1594 Handle_set_relative(Handle *self, PyObject* args, void* nothing)
1595 {
1596         if(!PyBool_Check(args))
1597         {
1598                 PyErr_SetString(PyExc_TypeError, "Value is not a boolean!");
1599                 return -1;
1600         }
1601
1602         bool relative = (args == Py_True);
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                         if(device->setRelative(self->handle, relative))
1611                                 return 0;
1612                         PyErr_SetString(AUDError, "Couldn't set the relativeness!");
1613                 }
1614                 else
1615                         PyErr_SetString(AUDError, device_not_3d_error);
1616         }
1617         catch(AUD_Exception& e)
1618         {
1619                 PyErr_SetString(AUDError, e.str);
1620         }
1621
1622         return -1;
1623 }
1624
1625 PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc,
1626                          "The minimum volume of the source.\n\n"
1627                          ".. seealso:: :attr:`Device.distance_model`");
1628
1629 static PyObject *
1630 Handle_get_volume_minimum(Handle *self, void* nothing)
1631 {
1632         Device* dev = (Device*)self->device;
1633
1634         try
1635         {
1636                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1637                 if(device)
1638                 {
1639                         return Py_BuildValue("f", device->getVolumeMinimum(self->handle));
1640                 }
1641                 else
1642                 {
1643                         PyErr_SetString(AUDError, device_not_3d_error);
1644                         return NULL;
1645                 }
1646         }
1647         catch(AUD_Exception& e)
1648         {
1649                 PyErr_SetString(AUDError, e.str);
1650                 return NULL;
1651         }
1652 }
1653
1654 static int
1655 Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing)
1656 {
1657         float volume;
1658
1659         if(!PyArg_Parse(args, "f:volume_minimum", &volume))
1660                 return -1;
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                         if(device->setVolumeMinimum(self->handle, volume))
1670                                 return 0;
1671                         PyErr_SetString(AUDError, "Couldn't set the minimum volume!");
1672                 }
1673                 else
1674                         PyErr_SetString(AUDError, device_not_3d_error);
1675         }
1676         catch(AUD_Exception& e)
1677         {
1678                 PyErr_SetString(AUDError, e.str);
1679         }
1680
1681         return -1;
1682 }
1683
1684 PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc,
1685                          "The maximum volume of the source.\n\n"
1686                          ".. seealso:: :attr:`Device.distance_model`");
1687
1688 static PyObject *
1689 Handle_get_volume_maximum(Handle *self, void* nothing)
1690 {
1691         Device* dev = (Device*)self->device;
1692
1693         try
1694         {
1695                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1696                 if(device)
1697                 {
1698                         return Py_BuildValue("f", device->getVolumeMaximum(self->handle));
1699                 }
1700                 else
1701                 {
1702                         PyErr_SetString(AUDError, device_not_3d_error);
1703                         return NULL;
1704                 }
1705         }
1706         catch(AUD_Exception& e)
1707         {
1708                 PyErr_SetString(AUDError, e.str);
1709                 return NULL;
1710         }
1711 }
1712
1713 static int
1714 Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing)
1715 {
1716         float volume;
1717
1718         if(!PyArg_Parse(args, "f:volume_maximum", &volume))
1719                 return -1;
1720
1721         Device* dev = (Device*)self->device;
1722
1723         try
1724         {
1725                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1726                 if(device)
1727                 {
1728                         if(device->setVolumeMaximum(self->handle, volume))
1729                                 return 0;
1730                         PyErr_SetString(AUDError, "Couldn't set the maximum volume!");
1731                 }
1732                 else
1733                         PyErr_SetString(AUDError, device_not_3d_error);
1734         }
1735         catch(AUD_Exception& e)
1736         {
1737                 PyErr_SetString(AUDError, e.str);
1738         }
1739
1740         return -1;
1741 }
1742
1743 PyDoc_STRVAR(M_aud_Handle_distance_reference_doc,
1744                          "The reference distance of the source.\n"
1745                          "At this distance the volume will be exactly :attr:`volume`.\n\n"
1746                          ".. seealso:: :attr:`Device.distance_model`");
1747
1748 static PyObject *
1749 Handle_get_distance_reference(Handle *self, void* nothing)
1750 {
1751         Device* dev = (Device*)self->device;
1752
1753         try
1754         {
1755                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1756                 if(device)
1757                 {
1758                         return Py_BuildValue("f", device->getDistanceReference(self->handle));
1759                 }
1760                 else
1761                 {
1762                         PyErr_SetString(AUDError, device_not_3d_error);
1763                         return NULL;
1764                 }
1765         }
1766         catch(AUD_Exception& e)
1767         {
1768                 PyErr_SetString(AUDError, e.str);
1769                 return NULL;
1770         }
1771 }
1772
1773 static int
1774 Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing)
1775 {
1776         float distance;
1777
1778         if(!PyArg_Parse(args, "f:distance_reference", &distance))
1779                 return -1;
1780
1781         Device* dev = (Device*)self->device;
1782
1783         try
1784         {
1785                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1786                 if(device)
1787                 {
1788                         if(device->setDistanceReference(self->handle, distance))
1789                                 return 0;
1790                         PyErr_SetString(AUDError, "Couldn't set the reference distance!");
1791                 }
1792                 else
1793                         PyErr_SetString(AUDError, device_not_3d_error);
1794         }
1795         catch(AUD_Exception& e)
1796         {
1797                 PyErr_SetString(AUDError, e.str);
1798         }
1799
1800         return -1;
1801 }
1802
1803 PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc,
1804                          "The maximum distance of the source.\n"
1805                          "If the listener is further away the source volume will be 0.\n\n"
1806                          ".. seealso:: :attr:`Device.distance_model`");
1807
1808 static PyObject *
1809 Handle_get_distance_maximum(Handle *self, void* nothing)
1810 {
1811         Device* dev = (Device*)self->device;
1812
1813         try
1814         {
1815                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1816                 if(device)
1817                 {
1818                         return Py_BuildValue("f", device->getDistanceMaximum(self->handle));
1819                 }
1820                 else
1821                 {
1822                         PyErr_SetString(AUDError, device_not_3d_error);
1823                         return NULL;
1824                 }
1825         }
1826         catch(AUD_Exception& e)
1827         {
1828                 PyErr_SetString(AUDError, e.str);
1829                 return NULL;
1830         }
1831 }
1832
1833 static int
1834 Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing)
1835 {
1836         float distance;
1837
1838         if(!PyArg_Parse(args, "f:distance_maximum", &distance))
1839                 return -1;
1840
1841         Device* dev = (Device*)self->device;
1842
1843         try
1844         {
1845                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1846                 if(device)
1847                 {
1848                         if(device->setDistanceMaximum(self->handle, distance))
1849                                 return 0;
1850                         PyErr_SetString(AUDError, "Couldn't set the maximum distance!");
1851                 }
1852                 else
1853                         PyErr_SetString(AUDError, device_not_3d_error);
1854         }
1855         catch(AUD_Exception& e)
1856         {
1857                 PyErr_SetString(AUDError, e.str);
1858         }
1859
1860         return -1;
1861 }
1862
1863 PyDoc_STRVAR(M_aud_Handle_attenuation_doc,
1864                          "This factor is used for distance based attenuation of the "
1865                          "source.\n\n"
1866                          ".. seealso:: :attr:`Device.distance_model`");
1867
1868 static PyObject *
1869 Handle_get_attenuation(Handle *self, void* nothing)
1870 {
1871         Device* dev = (Device*)self->device;
1872
1873         try
1874         {
1875                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1876                 if(device)
1877                 {
1878                         return Py_BuildValue("f", device->getAttenuation(self->handle));
1879                 }
1880                 else
1881                 {
1882                         PyErr_SetString(AUDError, device_not_3d_error);
1883                         return NULL;
1884                 }
1885         }
1886         catch(AUD_Exception& e)
1887         {
1888                 PyErr_SetString(AUDError, e.str);
1889                 return NULL;
1890         }
1891 }
1892
1893 static int
1894 Handle_set_attenuation(Handle *self, PyObject* args, void* nothing)
1895 {
1896         float factor;
1897
1898         if(!PyArg_Parse(args, "f:attenuation", &factor))
1899                 return -1;
1900
1901         Device* dev = (Device*)self->device;
1902
1903         try
1904         {
1905                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1906                 if(device)
1907                 {
1908                         if(device->setAttenuation(self->handle, factor))
1909                                 return 0;
1910                         PyErr_SetString(AUDError, "Couldn't set the attenuation!");
1911                 }
1912                 else
1913                         PyErr_SetString(AUDError, device_not_3d_error);
1914         }
1915         catch(AUD_Exception& e)
1916         {
1917                 PyErr_SetString(AUDError, e.str);
1918         }
1919
1920         return -1;
1921 }
1922
1923 PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc,
1924                          "The opening angle of the inner cone of the source. If the cone "
1925                          "values of a source are set there are two (audible) cones with "
1926                          "the apex at the :attr:`location` of the source and with infinite "
1927                          "height, heading in the direction of the source's "
1928                          ":attr:`orientation`.\n"
1929                          "In the inner cone the volume is normal. Outside the outer cone "
1930                          "the volume will be :attr:`cone_volume_outer` and in the area "
1931                          "between the volume will be interpolated linearly.");
1932
1933 static PyObject *
1934 Handle_get_cone_angle_inner(Handle *self, void* nothing)
1935 {
1936         Device* dev = (Device*)self->device;
1937
1938         try
1939         {
1940                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
1941                 if(device)
1942                 {
1943                         return Py_BuildValue("f", device->getConeAngleInner(self->handle));
1944                 }
1945                 else
1946                 {
1947                         PyErr_SetString(AUDError, device_not_3d_error);
1948                         return NULL;
1949                 }
1950         }
1951         catch(AUD_Exception& e)
1952         {
1953                 PyErr_SetString(AUDError, e.str);
1954                 return NULL;
1955         }
1956 }
1957
1958 static int
1959 Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing)
1960 {
1961         float angle;
1962
1963         if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
1964                 return -1;
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                         if(device->setConeAngleInner(self->handle, angle))
1974                                 return 0;
1975                         PyErr_SetString(AUDError, "Couldn't set the cone inner angle!");
1976                 }
1977                 else
1978                         PyErr_SetString(AUDError, device_not_3d_error);
1979         }
1980         catch(AUD_Exception& e)
1981         {
1982                 PyErr_SetString(AUDError, e.str);
1983         }
1984
1985         return -1;
1986 }
1987
1988 PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc,
1989                          "The opening angle of the outer cone of the source.\n\n"
1990                          ".. seealso:: :attr:`cone_angle_inner`");
1991
1992 static PyObject *
1993 Handle_get_cone_angle_outer(Handle *self, void* nothing)
1994 {
1995         Device* dev = (Device*)self->device;
1996
1997         try
1998         {
1999                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2000                 if(device)
2001                 {
2002                         return Py_BuildValue("f", device->getConeAngleOuter(self->handle));
2003                 }
2004                 else
2005                 {
2006                         PyErr_SetString(AUDError, device_not_3d_error);
2007                         return NULL;
2008                 }
2009         }
2010         catch(AUD_Exception& e)
2011         {
2012                 PyErr_SetString(AUDError, e.str);
2013                 return NULL;
2014         }
2015 }
2016
2017 static int
2018 Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing)
2019 {
2020         float angle;
2021
2022         if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
2023                 return -1;
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                         if(device->setConeAngleOuter(self->handle, angle))
2033                                 return 0;
2034                         PyErr_SetString(AUDError, "Couldn't set the cone outer angle!");
2035                 }
2036                 else
2037                         PyErr_SetString(AUDError, device_not_3d_error);
2038         }
2039         catch(AUD_Exception& e)
2040         {
2041                 PyErr_SetString(AUDError, e.str);
2042         }
2043
2044         return -1;
2045 }
2046
2047 PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc,
2048                          "The volume outside the outer cone of the source.\n\n"
2049                          ".. seealso:: :attr:`cone_angle_inner`");
2050
2051 static PyObject *
2052 Handle_get_cone_volume_outer(Handle *self, void* nothing)
2053 {
2054         Device* dev = (Device*)self->device;
2055
2056         try
2057         {
2058                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2059                 if(device)
2060                 {
2061                         return Py_BuildValue("f", device->getConeVolumeOuter(self->handle));
2062                 }
2063                 else
2064                 {
2065                         PyErr_SetString(AUDError, device_not_3d_error);
2066                         return NULL;
2067                 }
2068         }
2069         catch(AUD_Exception& e)
2070         {
2071                 PyErr_SetString(AUDError, e.str);
2072                 return NULL;
2073         }
2074 }
2075
2076 static int
2077 Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing)
2078 {
2079         float volume;
2080
2081         if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
2082                 return -1;
2083
2084         Device* dev = (Device*)self->device;
2085
2086         try
2087         {
2088                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
2089                 if(device)
2090                 {
2091                         if(device->setConeVolumeOuter(self->handle, volume))
2092                                 return 0;
2093                         PyErr_SetString(AUDError, "Couldn't set the cone outer volume!");
2094                 }
2095                 else
2096                         PyErr_SetString(AUDError, device_not_3d_error);
2097         }
2098         catch(AUD_Exception& e)
2099         {
2100                 PyErr_SetString(AUDError, e.str);
2101         }
2102
2103         return -1;
2104 }
2105
2106 static PyGetSetDef Handle_properties[] = {
2107         {(char*)"position", (getter)Handle_get_position, (setter)Handle_set_position,
2108          M_aud_Handle_position_doc, NULL },
2109         {(char*)"keep", (getter)Handle_get_keep, (setter)Handle_set_keep,
2110          M_aud_Handle_keep_doc, NULL },
2111         {(char*)"status", (getter)Handle_get_status, NULL,
2112          M_aud_Handle_status_doc, NULL },
2113         {(char*)"volume", (getter)Handle_get_volume, (setter)Handle_set_volume,
2114          M_aud_Handle_volume_doc, NULL },
2115         {(char*)"pitch", (getter)Handle_get_pitch, (setter)Handle_set_pitch,
2116          M_aud_Handle_pitch_doc, NULL },
2117         {(char*)"loop_count", (getter)Handle_get_loop_count, (setter)Handle_set_loop_count,
2118          M_aud_Handle_loop_count_doc, NULL },
2119         {(char*)"location", (getter)Handle_get_location, (setter)Handle_set_location,
2120          M_aud_Handle_location_doc, NULL },
2121         {(char*)"velocity", (getter)Handle_get_velocity, (setter)Handle_set_velocity,
2122          M_aud_Handle_velocity_doc, NULL },
2123         {(char*)"orientation", (getter)Handle_get_orientation, (setter)Handle_set_orientation,
2124          M_aud_Handle_orientation_doc, NULL },
2125         {(char*)"relative", (getter)Handle_get_relative, (setter)Handle_set_relative,
2126          M_aud_Handle_relative_doc, NULL },
2127         {(char*)"volume_minimum", (getter)Handle_get_volume_minimum, (setter)Handle_set_volume_minimum,
2128          M_aud_Handle_volume_minimum_doc, NULL },
2129         {(char*)"volume_maximum", (getter)Handle_get_volume_maximum, (setter)Handle_set_volume_maximum,
2130          M_aud_Handle_volume_maximum_doc, NULL },
2131         {(char*)"distance_reference", (getter)Handle_get_distance_reference, (setter)Handle_set_distance_reference,
2132          M_aud_Handle_distance_reference_doc, NULL },
2133         {(char*)"distance_maximum", (getter)Handle_get_distance_maximum, (setter)Handle_set_distance_maximum,
2134          M_aud_Handle_distance_maximum_doc, NULL },
2135         {(char*)"attenuation", (getter)Handle_get_attenuation, (setter)Handle_set_attenuation,
2136          M_aud_Handle_attenuation_doc, NULL },
2137         {(char*)"cone_angle_inner", (getter)Handle_get_cone_angle_inner, (setter)Handle_set_cone_angle_inner,
2138          M_aud_Handle_cone_angle_inner_doc, NULL },
2139         {(char*)"cone_angle_outer", (getter)Handle_get_cone_angle_outer, (setter)Handle_set_cone_angle_outer,
2140          M_aud_Handle_cone_angle_outer_doc, NULL },
2141         {(char*)"cone_volume_outer", (getter)Handle_get_cone_volume_outer, (setter)Handle_set_cone_volume_outer,
2142          M_aud_Handle_cone_volume_outer_doc, NULL },
2143         {NULL}  /* Sentinel */
2144 };
2145
2146 PyDoc_STRVAR(M_aud_Handle_doc,
2147                          "Handle objects are playback handles that can be used to control "
2148                          "playback of a sound. If a sound is played back multiple times "
2149                          "then there are as many handles.");
2150
2151 static PyTypeObject HandleType = {
2152         PyVarObject_HEAD_INIT(NULL, 0)
2153         "aud.Handle",              /* tp_name */
2154         sizeof(Handle),            /* tp_basicsize */
2155         0,                         /* tp_itemsize */
2156         (destructor)Handle_dealloc,/* tp_dealloc */
2157         0,                         /* tp_print */
2158         0,                         /* tp_getattr */
2159         0,                         /* tp_setattr */
2160         0,                         /* tp_reserved */
2161         0,                         /* tp_repr */
2162         0,                         /* tp_as_number */
2163         0,                         /* tp_as_sequence */
2164         0,                         /* tp_as_mapping */
2165         0,                         /* tp_hash  */
2166         0,                         /* tp_call */
2167         0,                         /* tp_str */
2168         0,                         /* tp_getattro */
2169         0,                         /* tp_setattro */
2170         0,                         /* tp_as_buffer */
2171         Py_TPFLAGS_DEFAULT,        /* tp_flags */
2172         M_aud_Handle_doc,          /* tp_doc */
2173         0,                                 /* tp_traverse */
2174         0,                                 /* tp_clear */
2175         0,                                 /* tp_richcompare */
2176         0,                                 /* tp_weaklistoffset */
2177         0,                                 /* tp_iter */
2178         0,                                 /* tp_iternext */
2179         Handle_methods,            /* tp_methods */
2180         0,                         /* tp_members */
2181         Handle_properties,         /* tp_getset */
2182         0,                         /* tp_base */
2183         0,                         /* tp_dict */
2184         0,                         /* tp_descr_get */
2185         0,                         /* tp_descr_set */
2186         0,                         /* tp_dictoffset */
2187         0,                         /* tp_init */
2188         0,                         /* tp_alloc */
2189         0,                         /* tp_new */
2190 };
2191
2192 // ========== Device ==================================================
2193
2194 static void
2195 Device_dealloc(Device* self)
2196 {
2197         if(self->device)
2198                 delete self->device;
2199         Py_TYPE(self)->tp_free((PyObject*)self);
2200 }
2201
2202 static PyObject *
2203 Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2204 {
2205         Device *self;
2206
2207         static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL};
2208         int device;
2209         int rate = AUD_RATE_44100;
2210         int channels = AUD_CHANNELS_STEREO;
2211         int format = AUD_FORMAT_FLOAT32;
2212         int buffersize = AUD_DEFAULT_BUFFER_SIZE;
2213         const char* name = "Audaspace";
2214
2215         if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiis:Device", const_cast<char**>(kwlist),
2216                                                                         &device, &rate, &channels, &format, &buffersize, &name))
2217                 return NULL;
2218
2219         if(buffersize < 128)
2220         {
2221                 PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than 127!");
2222                 return NULL;
2223         }
2224
2225         self = (Device*)type->tp_alloc(type, 0);
2226         if(self != NULL)
2227         {
2228                 AUD_DeviceSpecs specs;
2229                 specs.channels = (AUD_Channels)channels;
2230                 specs.format = (AUD_SampleFormat)format;
2231                 specs.rate = (AUD_SampleRate)rate;
2232
2233                 self->device = NULL;
2234
2235                 try
2236                 {
2237                         switch(device)
2238                         {
2239                         case AUD_DEVICE_NULL:
2240                                 self->device = new AUD_NULLDevice();
2241                                 break;
2242                         case AUD_DEVICE_OPENAL:
2243 #ifdef WITH_OPENAL
2244                                 self->device = new AUD_OpenALDevice(specs, buffersize);
2245 #endif
2246                                 break;
2247                         case AUD_DEVICE_SDL:
2248 #ifdef WITH_SDL
2249                                 self->device = new AUD_SDLDevice(specs, buffersize);
2250 #endif
2251                                 break;
2252                         case AUD_DEVICE_JACK:
2253 #ifdef WITH_JACK
2254                                 self->device = new AUD_JackDevice(name, specs, buffersize);
2255 #endif
2256                                 break;
2257                         case AUD_DEVICE_READ:
2258                                 break;
2259                         }
2260
2261                 }
2262                 catch(AUD_Exception& e)
2263                 {
2264                         Py_DECREF(self);
2265                         PyErr_SetString(AUDError, e.str);
2266                         return NULL;
2267                 }
2268
2269                 if(!self->device)
2270                 {
2271                         Py_DECREF(self);
2272                         PyErr_SetString(AUDError, "Unsupported device type!");
2273                         return NULL;
2274                 }
2275         }
2276
2277         return (PyObject *)self;
2278 }
2279
2280 PyDoc_STRVAR(M_aud_Device_play_doc,
2281                          "play(factory, keep=False)\n\n"
2282                          "Plays a factory.\n\n"
2283                          ":arg factory: The factory to play.\n"
2284                          ":type factory: :class:`Factory`\n"
2285                          ":arg keep: See :attr:`Handle.keep`.\n"
2286                          ":type keep: bool\n"
2287                          ":return: The playback handle with which playback can be "
2288                          "controlled with.\n"
2289                          ":rtype: :class:`Handle`");
2290
2291 static PyObject *
2292 Device_play(Device *self, PyObject *args, PyObject *kwds)
2293 {
2294         PyObject* object;
2295         PyObject* keepo = NULL;
2296
2297         bool keep = false;
2298
2299         static const char *kwlist[] = {"factory", "keep", NULL};
2300
2301         if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:play", const_cast<char**>(kwlist), &object, &keepo))
2302                 return NULL;
2303
2304         if(!PyObject_TypeCheck(object, &FactoryType))
2305         {
2306                 PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
2307                 return NULL;
2308         }
2309
2310         if(keepo != NULL)
2311         {
2312                 if(!PyBool_Check(keepo))
2313                 {
2314                         PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
2315                         return NULL;
2316                 }
2317
2318                 keep = keepo == Py_True;
2319         }
2320
2321         Factory* sound = (Factory*)object;
2322         Handle *handle;
2323
2324         handle = (Handle*)HandleType.tp_alloc(&HandleType, 0);
2325         if(handle != NULL)
2326         {
2327                 handle->device = (PyObject*)self;
2328                 Py_INCREF(self);
2329
2330                 try
2331                 {
2332                         handle->handle = self->device->play(sound->factory, keep);
2333                 }
2334                 catch(AUD_Exception& e)
2335                 {
2336                         Py_DECREF(handle);
2337                         PyErr_SetString(AUDError, e.str);
2338                         return NULL;
2339                 }
2340         }
2341
2342         return (PyObject *)handle;
2343 }
2344
2345 PyDoc_STRVAR(M_aud_Device_lock_doc,
2346                          "lock()\n\n"
2347                          "Locks the device so that it's guaranteed, that no samples are "
2348                          "read from the streams until :meth:`unlock` is called.\n"
2349                          "This is useful if you want to do start/stop/pause/resume some "
2350                          "sounds at the same time.\n\n"
2351                          ".. note:: The device has to be unlocked as often as locked to be "
2352                          "able to continue playback.\n\n"
2353                          ".. warning:: Make sure the time between locking and unlocking is "
2354                          "as short as possible to avoid clicks.");
2355
2356 static PyObject *
2357 Device_lock(Device *self)
2358 {
2359         try
2360         {
2361                 self->device->lock();
2362                 Py_RETURN_NONE;
2363         }
2364         catch(AUD_Exception& e)
2365         {
2366                 PyErr_SetString(AUDError, e.str);
2367                 return NULL;
2368         }
2369 }
2370
2371 PyDoc_STRVAR(M_aud_Device_unlock_doc,
2372                          "unlock()\n\n"
2373                          "Unlocks the device after a lock call, see :meth:`lock` for "
2374                          "details.");
2375
2376 static PyObject *
2377 Device_unlock(Device *self)
2378 {
2379         try
2380         {
2381                 self->device->unlock();
2382                 Py_RETURN_NONE;
2383         }
2384         catch(AUD_Exception& e)
2385         {
2386                 PyErr_SetString(AUDError, e.str);
2387                 return NULL;
2388         }
2389 }
2390
2391 static PyMethodDef Device_methods[] = {
2392         {"play", (PyCFunction)Device_play, METH_VARARGS | METH_KEYWORDS,
2393          M_aud_Device_play_doc
2394         },
2395         {"lock", (PyCFunction)Device_lock, METH_NOARGS,
2396          M_aud_Device_lock_doc
2397         },
2398         {"unlock", (PyCFunction)Device_unlock, METH_NOARGS,
2399          M_aud_Device_unlock_doc
2400         },
2401         {NULL}  /* Sentinel */
2402 };
2403
2404 PyDoc_STRVAR(M_aud_Device_rate_doc,
2405                          "The sampling rate of the device in Hz.");
2406
2407 static PyObject *
2408 Device_get_rate(Device *self, void* nothing)
2409 {
2410         try
2411         {
2412                 AUD_DeviceSpecs specs = self->device->getSpecs();
2413                 return Py_BuildValue("i", specs.rate);
2414         }
2415         catch(AUD_Exception& e)
2416         {
2417                 PyErr_SetString(AUDError, e.str);
2418                 return NULL;
2419         }
2420 }
2421
2422 PyDoc_STRVAR(M_aud_Device_format_doc,
2423                          "The native sample format of the device.");
2424
2425 static PyObject *
2426 Device_get_format(Device *self, void* nothing)
2427 {
2428         try
2429         {
2430                 AUD_DeviceSpecs specs = self->device->getSpecs();
2431                 return Py_BuildValue("i", specs.format);
2432         }
2433         catch(AUD_Exception& e)
2434         {
2435                 PyErr_SetString(AUDError, e.str);
2436                 return NULL;
2437         }
2438 }
2439
2440 PyDoc_STRVAR(M_aud_Device_channels_doc,
2441                          "The channel count of the device.");
2442
2443 static PyObject *
2444 Device_get_channels(Device *self, void* nothing)
2445 {
2446         try
2447         {
2448                 AUD_DeviceSpecs specs = self->device->getSpecs();
2449                 return Py_BuildValue("i", specs.channels);
2450         }
2451         catch(AUD_Exception& e)
2452         {
2453                 PyErr_SetString(AUDError, e.str);
2454                 return NULL;
2455         }
2456 }
2457
2458 PyDoc_STRVAR(M_aud_Device_volume_doc,
2459                          "The overall volume of the device.");
2460
2461 static PyObject *
2462 Device_get_volume(Device *self, void* nothing)
2463 {
2464         try
2465         {
2466                 return Py_BuildValue("f", self->device->getVolume());
2467         }
2468         catch(AUD_Exception& e)
2469         {
2470                 PyErr_SetString(AUDError, e.str);
2471                 return NULL;
2472         }
2473 }
2474
2475 static int
2476 Device_set_volume(Device *self, PyObject* args, void* nothing)
2477 {
2478         float volume;
2479
2480         if(!PyArg_Parse(args, "f:volume", &volume))
2481                 return -1;
2482
2483         try
2484         {
2485                 self->device->setVolume(volume);
2486                 return 0;
2487         }
2488         catch(AUD_Exception& e)
2489         {
2490                 PyErr_SetString(AUDError, e.str);
2491                 return -1;
2492         }
2493 }
2494
2495 PyDoc_STRVAR(M_aud_Device_listener_location_doc,
2496                          "The listeners's location in 3D space, a 3D tuple of floats.");
2497
2498 static PyObject *
2499 Device_get_listener_location(Device *self, void* nothing)
2500 {
2501         try
2502         {
2503                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2504                 if(device)
2505                 {
2506                         AUD_Vector3 v = device->getListenerLocation();
2507                         return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
2508                 }
2509                 else
2510                 {
2511                         PyErr_SetString(AUDError, device_not_3d_error);
2512                 }
2513         }
2514         catch(AUD_Exception& e)
2515         {
2516                 PyErr_SetString(AUDError, e.str);
2517         }
2518
2519         return NULL;
2520 }
2521
2522 static int
2523 Device_set_listener_location(Device *self, PyObject* args, void* nothing)
2524 {
2525         float x, y, z;
2526
2527         if(!PyArg_Parse(args, "(fff):listener_location", &x, &y, &z))
2528                 return -1;
2529
2530         try
2531         {
2532                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2533                 if(device)
2534                 {
2535                         AUD_Vector3 location(x, y, z);
2536                         device->setListenerLocation(location);
2537                         return 0;
2538                 }
2539                 else
2540                         PyErr_SetString(AUDError, device_not_3d_error);
2541         }
2542         catch(AUD_Exception& e)
2543         {
2544                 PyErr_SetString(AUDError, e.str);
2545         }
2546
2547         return -1;
2548 }
2549
2550 PyDoc_STRVAR(M_aud_Device_listener_velocity_doc,
2551                          "The listener's velocity in 3D space, a 3D tuple of floats.");
2552
2553 static PyObject *
2554 Device_get_listener_velocity(Device *self, void* nothing)
2555 {
2556         try
2557         {
2558                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2559                 if(device)
2560                 {
2561                         AUD_Vector3 v = device->getListenerVelocity();
2562                         return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
2563                 }
2564                 else
2565                 {
2566                         PyErr_SetString(AUDError, device_not_3d_error);
2567                 }
2568         }
2569         catch(AUD_Exception& e)
2570         {
2571                 PyErr_SetString(AUDError, e.str);
2572         }
2573
2574         return NULL;
2575 }
2576
2577 static int
2578 Device_set_listener_velocity(Device *self, PyObject* args, void* nothing)
2579 {
2580         float x, y, z;
2581
2582         if(!PyArg_Parse(args, "(fff):listener_velocity", &x, &y, &z))
2583                 return -1;
2584
2585         try
2586         {
2587                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2588                 if(device)
2589                 {
2590                         AUD_Vector3 velocity(x, y, z);
2591                         device->setListenerVelocity(velocity);
2592                         return 0;
2593                 }
2594                 else
2595                         PyErr_SetString(AUDError, device_not_3d_error);
2596         }
2597         catch(AUD_Exception& e)
2598         {
2599                 PyErr_SetString(AUDError, e.str);
2600         }
2601
2602         return -1;
2603 }
2604
2605 PyDoc_STRVAR(M_aud_Device_listener_orientation_doc,
2606                          "The listener's orientation in 3D space as quaternion, a 4 float tuple.");
2607
2608 static PyObject *
2609 Device_get_listener_orientation(Device *self, void* nothing)
2610 {
2611         try
2612         {
2613                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2614                 if(device)
2615                 {
2616                         AUD_Quaternion o = device->getListenerOrientation();
2617                         return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
2618                 }
2619                 else
2620                 {
2621                         PyErr_SetString(AUDError, device_not_3d_error);
2622                 }
2623         }
2624         catch(AUD_Exception& e)
2625         {
2626                 PyErr_SetString(AUDError, e.str);
2627         }
2628
2629         return NULL;
2630 }
2631
2632 static int
2633 Device_set_listener_orientation(Device *self, PyObject* args, void* nothing)
2634 {
2635         float w, x, y, z;
2636
2637         if(!PyArg_Parse(args, "(ffff):listener_orientation", &w, &x, &y, &z))
2638                 return -1;
2639
2640         try
2641         {
2642                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2643                 if(device)
2644                 {
2645                         AUD_Quaternion orientation(w, x, y, z);
2646                         device->setListenerOrientation(orientation);
2647                         return 0;
2648                 }
2649                 else
2650                         PyErr_SetString(AUDError, device_not_3d_error);
2651         }
2652         catch(AUD_Exception& e)
2653         {
2654                 PyErr_SetString(AUDError, e.str);
2655         }
2656
2657         return -1;
2658 }
2659
2660 PyDoc_STRVAR(M_aud_Device_speed_of_sound_doc,
2661                          "The speed of sound of the device.\n"
2662                          "The speed of sound in air is typically 343 m/s.");
2663
2664 static PyObject *
2665 Device_get_speed_of_sound(Device *self, void* nothing)
2666 {
2667         try
2668         {
2669                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2670                 if(device)
2671                 {
2672                         return Py_BuildValue("f", device->getSpeedOfSound());
2673                 }
2674                 else
2675                 {
2676                         PyErr_SetString(AUDError, device_not_3d_error);
2677                         return NULL;
2678                 }
2679         }
2680         catch(AUD_Exception& e)
2681         {
2682                 PyErr_SetString(AUDError, e.str);
2683                 return NULL;
2684         }
2685 }
2686
2687 static int
2688 Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing)
2689 {
2690         float speed;
2691
2692         if(!PyArg_Parse(args, "f:speed_of_sound", &speed))
2693                 return -1;
2694
2695         try
2696         {
2697                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2698                 if(device)
2699                 {
2700                         device->setSpeedOfSound(speed);
2701                         return 0;
2702                 }
2703                 else
2704                         PyErr_SetString(AUDError, device_not_3d_error);
2705         }
2706         catch(AUD_Exception& e)
2707         {
2708                 PyErr_SetString(AUDError, e.str);
2709         }
2710
2711         return -1;
2712 }
2713
2714 PyDoc_STRVAR(M_aud_Device_doppler_factor_doc,
2715                          "The doppler factor of the device.\n"
2716                          "This factor is a scaling factor for the velocity vectors in "
2717                          "doppler calculation. So a value bigger than 1 will exaggerate "
2718                          "the effect as it raises the velocity.");
2719
2720 static PyObject *
2721 Device_get_doppler_factor(Device *self, void* nothing)
2722 {
2723         try
2724         {
2725                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2726                 if(device)
2727                 {
2728                         return Py_BuildValue("f", device->getDopplerFactor());
2729                 }
2730                 else
2731                 {
2732                         PyErr_SetString(AUDError, device_not_3d_error);
2733                         return NULL;
2734                 }
2735         }
2736         catch(AUD_Exception& e)
2737         {
2738                 PyErr_SetString(AUDError, e.str);
2739                 return NULL;
2740         }
2741 }
2742
2743 static int
2744 Device_set_doppler_factor(Device *self, PyObject* args, void* nothing)
2745 {
2746         float factor;
2747
2748         if(!PyArg_Parse(args, "f:doppler_factor", &factor))
2749                 return -1;
2750
2751         try
2752         {
2753                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2754                 if(device)
2755                 {
2756                         device->setDopplerFactor(factor);
2757                         return 0;
2758                 }
2759                 else
2760                         PyErr_SetString(AUDError, device_not_3d_error);
2761         }
2762         catch(AUD_Exception& e)
2763         {
2764                 PyErr_SetString(AUDError, e.str);
2765         }
2766
2767         return -1;
2768 }
2769
2770 PyDoc_STRVAR(M_aud_Device_distance_model_doc,
2771                          "The distance model of the device.\n\n"
2772                          ".. seealso:: http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835864");
2773
2774 static PyObject *
2775 Device_get_distance_model(Device *self, void* nothing)
2776 {
2777         try
2778         {
2779                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2780                 if(device)
2781                 {
2782                         return Py_BuildValue("i", int(device->getDistanceModel()));
2783                 }
2784                 else
2785                 {
2786                         PyErr_SetString(AUDError, device_not_3d_error);
2787                         return NULL;
2788                 }
2789         }
2790         catch(AUD_Exception& e)
2791         {
2792                 PyErr_SetString(AUDError, e.str);
2793                 return NULL;
2794         }
2795 }
2796
2797 static int
2798 Device_set_distance_model(Device *self, PyObject* args, void* nothing)
2799 {
2800         int model;
2801
2802         if(!PyArg_Parse(args, "i:distance_model", &model))
2803                 return -1;
2804
2805         try
2806         {
2807                 AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
2808                 if(device)
2809                 {
2810                         device->setDistanceModel(AUD_DistanceModel(model));
2811                         return 0;
2812                 }
2813                 else
2814                         PyErr_SetString(AUDError, device_not_3d_error);
2815         }
2816         catch(AUD_Exception& e)
2817         {
2818                 PyErr_SetString(AUDError, e.str);
2819         }
2820
2821         return -1;
2822 }
2823
2824 static PyGetSetDef Device_properties[] = {
2825         {(char*)"rate", (getter)Device_get_rate, NULL,
2826          M_aud_Device_rate_doc, NULL },
2827         {(char*)"format", (getter)Device_get_format, NULL,
2828          M_aud_Device_format_doc, NULL },
2829         {(char*)"channels", (getter)Device_get_channels, NULL,
2830          M_aud_Device_channels_doc, NULL },
2831         {(char*)"volume", (getter)Device_get_volume, (setter)Device_set_volume,
2832          M_aud_Device_volume_doc, NULL },
2833         {(char*)"listener_location", (getter)Device_get_listener_location, (setter)Device_set_listener_location,
2834          M_aud_Device_listener_location_doc, NULL },
2835         {(char*)"listener_velocity", (getter)Device_get_listener_velocity, (setter)Device_set_listener_velocity,
2836          M_aud_Device_listener_velocity_doc, NULL },
2837         {(char*)"listener_orientation", (getter)Device_get_listener_orientation, (setter)Device_set_listener_orientation,
2838          M_aud_Device_listener_orientation_doc, NULL },
2839         {(char*)"speed_of_sound", (getter)Device_get_speed_of_sound, (setter)Device_set_speed_of_sound,
2840          M_aud_Device_speed_of_sound_doc, NULL },
2841         {(char*)"doppler_factor", (getter)Device_get_doppler_factor, (setter)Device_set_doppler_factor,
2842          M_aud_Device_doppler_factor_doc, NULL },
2843         {(char*)"distance_model", (getter)Device_get_distance_model, (setter)Device_set_distance_model,
2844          M_aud_Device_distance_model_doc, NULL },
2845         {NULL}  /* Sentinel */
2846 };
2847
2848 PyDoc_STRVAR(M_aud_Device_doc,
2849                          "Device objects represent an audio output backend like OpenAL or "
2850                          "SDL, but might also represent a file output or RAM buffer "
2851                          "output.");
2852
2853 static PyTypeObject DeviceType = {
2854         PyVarObject_HEAD_INIT(NULL, 0)
2855         "aud.Device",              /* tp_name */
2856         sizeof(Device),            /* tp_basicsize */
2857         0,                         /* tp_itemsize */
2858         (destructor)Device_dealloc,/* tp_dealloc */
2859         0,                         /* tp_print */
2860         0,                         /* tp_getattr */
2861         0,                         /* tp_setattr */
2862         0,                         /* tp_reserved */
2863         0,                         /* tp_repr */
2864         0,                         /* tp_as_number */
2865         0,                         /* tp_as_sequence */
2866         0,                         /* tp_as_mapping */
2867         0,                         /* tp_hash  */
2868         0,                         /* tp_call */
2869         0,                         /* tp_str */
2870         0,                         /* tp_getattro */
2871         0,                         /* tp_setattro */
2872         0,                         /* tp_as_buffer */
2873         Py_TPFLAGS_DEFAULT,        /* tp_flags */
2874         M_aud_Device_doc,          /* tp_doc */
2875         0,                                 /* tp_traverse */
2876         0,                                 /* tp_clear */
2877         0,                                 /* tp_richcompare */
2878         0,                                 /* tp_weaklistoffset */
2879         0,                                 /* tp_iter */
2880         0,                                 /* tp_iternext */
2881         Device_methods,            /* tp_methods */
2882         0,                         /* tp_members */
2883         Device_properties,         /* tp_getset */
2884         0,                         /* tp_base */
2885         0,                         /* tp_dict */
2886         0,                         /* tp_descr_get */
2887         0,                         /* tp_descr_set */
2888         0,                         /* tp_dictoffset */
2889         0,                         /* tp_init */
2890         0,                         /* tp_alloc */
2891         Device_new,                /* tp_new */
2892 };
2893
2894 PyObject *
2895 Device_empty()
2896 {
2897         return DeviceType.tp_alloc(&DeviceType, 0);
2898 }
2899
2900 // ====================================================================
2901
2902 PyDoc_STRVAR(M_aud_doc,
2903                          "This module provides access to the audaspace audio library.");
2904
2905 static struct PyModuleDef audmodule = {
2906         PyModuleDef_HEAD_INIT,
2907         "aud",     /* name of module */
2908         M_aud_doc, /* module documentation */
2909         -1,        /* size of per-interpreter state of the module,
2910                                   or -1 if the module keeps state in global variables. */
2911    NULL, NULL, NULL, NULL, NULL
2912 };
2913
2914 PyMODINIT_FUNC
2915 PyInit_aud(void)
2916 {
2917         PyObject* m;
2918
2919         if(PyType_Ready(&FactoryType) < 0)
2920                 return NULL;
2921
2922         if(PyType_Ready(&DeviceType) < 0)
2923                 return NULL;
2924
2925         if(PyType_Ready(&HandleType) < 0)
2926                 return NULL;
2927
2928         m = PyModule_Create(&audmodule);
2929         if(m == NULL)
2930                 return NULL;
2931
2932         Py_INCREF(&FactoryType);
2933         PyModule_AddObject(m, "Factory", (PyObject*)&FactoryType);
2934
2935         Py_INCREF(&DeviceType);
2936         PyModule_AddObject(m, "Device", (PyObject*)&DeviceType);
2937
2938         Py_INCREF(&HandleType);
2939         PyModule_AddObject(m, "Handle", (PyObject*)&HandleType);
2940
2941         AUDError = PyErr_NewException("aud.error", NULL, NULL);
2942         Py_INCREF(AUDError);
2943         PyModule_AddObject(m, "error", AUDError);
2944
2945         // device constants
2946         PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_NULL);
2947         PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_OPENAL);
2948         PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_SDL);
2949         PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_JACK);
2950         //PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_READ);
2951         // format constants
2952         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT32);
2953         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT64);
2954         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_INVALID);
2955         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S16);
2956         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S24);
2957         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S32);
2958         PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_U8);
2959         // status constants
2960         PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_INVALID);
2961         PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PAUSED);
2962         PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PLAYING);
2963         // distance model constants
2964         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT);
2965         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT_CLAMPED);
2966         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE);
2967         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE_CLAMPED);
2968         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR);
2969         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR_CLAMPED);
2970         PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVALID);
2971
2972         return m;
2973 }