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