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