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