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