Blender V2.61 - r43446

AUD_PyAPI.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * Copyright 2009-2011 Jörg Hermann Müller
00005  *
00006  * This file is part of AudaSpace.
00007  *
00008  * Audaspace is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * AudaSpace is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with Audaspace; if not, write to the Free Software Foundation,
00020  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00021  *
00022  * ***** END GPL LICENSE BLOCK *****
00023  */
00024 
00030 #include "AUD_PyAPI.h"
00031 #include "structmember.h"
00032 
00033 #include "AUD_I3DDevice.h"
00034 #include "AUD_I3DHandle.h"
00035 #include "AUD_NULLDevice.h"
00036 #include "AUD_DelayFactory.h"
00037 #include "AUD_DoubleFactory.h"
00038 #include "AUD_FaderFactory.h"
00039 #include "AUD_HighpassFactory.h"
00040 #include "AUD_LimiterFactory.h"
00041 #include "AUD_LoopFactory.h"
00042 #include "AUD_LowpassFactory.h"
00043 #include "AUD_PingPongFactory.h"
00044 #include "AUD_PitchFactory.h"
00045 #include "AUD_ReverseFactory.h"
00046 #include "AUD_SinusFactory.h"
00047 #include "AUD_FileFactory.h"
00048 #include "AUD_SquareFactory.h"
00049 #include "AUD_StreamBufferFactory.h"
00050 #include "AUD_SuperposeFactory.h"
00051 #include "AUD_VolumeFactory.h"
00052 #include "AUD_IIRFilterFactory.h"
00053 
00054 #ifdef WITH_SDL
00055 #include "AUD_SDLDevice.h"
00056 #endif
00057 
00058 #ifdef WITH_OPENAL
00059 #include "AUD_OpenALDevice.h"
00060 #endif
00061 
00062 #ifdef WITH_JACK
00063 #include "AUD_JackDevice.h"
00064 #endif
00065 
00066 // ====================================================================
00067 
00068 typedef enum
00069 {
00070     AUD_DEVICE_NULL = 0,
00071     AUD_DEVICE_OPENAL,
00072     AUD_DEVICE_SDL,
00073     AUD_DEVICE_JACK,
00074     AUD_DEVICE_READ,
00075 } AUD_DeviceTypes;
00076 
00077 // ====================================================================
00078 
00079 #define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name)
00080 
00081 // ====================================================================
00082 
00083 static PyObject* AUDError;
00084 
00085 static const char* device_not_3d_error = "Device is not a 3D device!";
00086 
00087 // ====================================================================
00088 
00089 static void
00090 Factory_dealloc(Factory* self)
00091 {
00092     if(self->factory)
00093         delete reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory);
00094     Py_XDECREF(self->child_list);
00095     Py_TYPE(self)->tp_free((PyObject*)self);
00096 }
00097 
00098 static PyObject *
00099 Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
00100 {
00101     Factory *self;
00102 
00103     self = (Factory*)type->tp_alloc(type, 0);
00104     if(self != NULL)
00105     {
00106         static const char *kwlist[] = {"filename", NULL};
00107         const char* filename = NULL;
00108 
00109         if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Factory", const_cast<char**>(kwlist), &filename))
00110         {
00111             Py_DECREF(self);
00112             return NULL;
00113         }
00114 
00115         try
00116         {
00117             self->factory = new AUD_Reference<AUD_IFactory>(new AUD_FileFactory(filename));
00118         }
00119         catch(AUD_Exception& e)
00120         {
00121             Py_DECREF(self);
00122             PyErr_SetString(AUDError, e.str);
00123             return NULL;
00124         }
00125     }
00126 
00127     return (PyObject *)self;
00128 }
00129 
00130 PyDoc_STRVAR(M_aud_Factory_sine_doc,
00131              "sine(frequency, rate=44100)\n\n"
00132              "Creates a sine factory which plays a sine wave.\n\n"
00133              ":arg frequency: The frequency of the sine wave in Hz.\n"
00134              ":type frequency: float\n"
00135              ":arg rate: The sampling rate in Hz. It's recommended to set this "
00136              "value to the playback device's samling rate to avoid resamping.\n"
00137              ":type rate: int\n"
00138              ":return: The created :class:`Factory` object.\n"
00139              ":rtype: :class:`Factory`");
00140 
00141 static PyObject *
00142 Factory_sine(PyTypeObject* type, PyObject* args)
00143 {
00144     float frequency;
00145     double rate = 44100;
00146 
00147     if(!PyArg_ParseTuple(args, "f|d:sine", &frequency, &rate))
00148         return NULL;
00149 
00150     Factory *self;
00151 
00152     self = (Factory*)type->tp_alloc(type, 0);
00153     if(self != NULL)
00154     {
00155         try
00156         {
00157             self->factory = new AUD_Reference<AUD_IFactory>(new AUD_SinusFactory(frequency, (AUD_SampleRate)rate));
00158         }
00159         catch(AUD_Exception& e)
00160         {
00161             Py_DECREF(self);
00162             PyErr_SetString(AUDError, e.str);
00163             return NULL;
00164         }
00165     }
00166 
00167     return (PyObject *)self;
00168 }
00169 
00170 PyDoc_STRVAR(M_aud_Factory_file_doc,
00171              "file(filename)\n\n"
00172              "Creates a factory object of a sound file.\n\n"
00173              ":arg filename: Path of the file.\n"
00174              ":type filename: string\n"
00175              ":return: The created :class:`Factory` object.\n"
00176              ":rtype: :class:`Factory`\n\n"
00177              ".. warning:: If the file doesn't exist or can't be read you will "
00178              "not get an exception immediately, but when you try to start "
00179              "playback of that factory.");
00180 
00181 static PyObject *
00182 Factory_file(PyTypeObject* type, PyObject* args)
00183 {
00184     const char* filename = NULL;
00185 
00186     if(!PyArg_ParseTuple(args, "s:file", &filename))
00187         return NULL;
00188 
00189     Factory *self;
00190 
00191     self = (Factory*)type->tp_alloc(type, 0);
00192     if(self != NULL)
00193     {
00194         try
00195         {
00196             self->factory = new AUD_Reference<AUD_IFactory>(new AUD_FileFactory(filename));
00197         }
00198         catch(AUD_Exception& e)
00199         {
00200             Py_DECREF(self);
00201             PyErr_SetString(AUDError, e.str);
00202             return NULL;
00203         }
00204     }
00205 
00206     return (PyObject *)self;
00207 }
00208 
00209 PyDoc_STRVAR(M_aud_Factory_lowpass_doc,
00210              "lowpass(frequency, Q=0.5)\n\n"
00211              "Creates a second order lowpass filter based on the transfer "
00212              "function H(s) = 1 / (s^2 + s/Q + 1)\n\n"
00213              ":arg frequency: The cut off trequency of the lowpass.\n"
00214              ":type frequency: float\n"
00215              ":arg Q: Q factor of the lowpass.\n"
00216              ":type Q: float\n"
00217              ":return: The created :class:`Factory` object.\n"
00218              ":rtype: :class:`Factory`");
00219 
00220 static PyObject *
00221 Factory_lowpass(Factory* self, PyObject* args)
00222 {
00223     float frequency;
00224     float Q = 0.5;
00225 
00226     if(!PyArg_ParseTuple(args, "f|f:lowpass", &frequency, &Q))
00227         return NULL;
00228 
00229     PyTypeObject* type = Py_TYPE(self);
00230     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00231 
00232     if(parent != NULL)
00233     {
00234         Py_INCREF(self);
00235         parent->child_list = (PyObject*)self;
00236 
00237         try
00238         {
00239             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LowpassFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), frequency, Q));
00240         }
00241         catch(AUD_Exception& e)
00242         {
00243             Py_DECREF(parent);
00244             PyErr_SetString(AUDError, e.str);
00245             return NULL;
00246         }
00247     }
00248 
00249     return (PyObject *)parent;
00250 }
00251 
00252 PyDoc_STRVAR(M_aud_Factory_delay_doc,
00253              "delay(time)\n\n"
00254              "Delays by playing adding silence in front of the other factory's "
00255              "data.\n\n"
00256              ":arg time: How many seconds of silence should be added before "
00257              "the factory.\n"
00258              ":type time: float\n"
00259              ":return: The created :class:`Factory` object.\n"
00260              ":rtype: :class:`Factory`");
00261 
00262 static PyObject *
00263 Factory_delay(Factory* self, PyObject* args)
00264 {
00265     float delay;
00266 
00267     if(!PyArg_ParseTuple(args, "f:delay", &delay))
00268         return NULL;
00269 
00270     PyTypeObject* type = Py_TYPE(self);
00271     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00272 
00273     if(parent != NULL)
00274     {
00275         Py_INCREF(self);
00276         parent->child_list = (PyObject*)self;
00277 
00278         try
00279         {
00280             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_DelayFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), delay));
00281         }
00282         catch(AUD_Exception& e)
00283         {
00284             Py_DECREF(parent);
00285             PyErr_SetString(AUDError, e.str);
00286             return NULL;
00287         }
00288     }
00289 
00290     return (PyObject *)parent;
00291 }
00292 
00293 PyDoc_STRVAR(M_aud_Factory_join_doc,
00294              "join(factory)\n\n"
00295              "Plays two factories in sequence.\n\n"
00296              ":arg factory: The factory to play second.\n"
00297              ":type factory: :class:`Factory`\n"
00298              ":return: The created :class:`Factory` object.\n"
00299              ":rtype: :class:`Factory`\n\n"
00300              ".. note:: The two factories have to have the same specifications "
00301              "(channels and samplerate).");
00302 
00303 static PyObject *
00304 Factory_join(Factory* self, PyObject* object)
00305 {
00306     PyTypeObject* type = Py_TYPE(self);
00307 
00308     if(!PyObject_TypeCheck(object, type))
00309     {
00310         PyErr_SetString(PyExc_TypeError, "Object has to be of type Factory!");
00311         return NULL;
00312     }
00313 
00314     Factory *parent;
00315     Factory *child = (Factory*)object;
00316 
00317     parent = (Factory*)type->tp_alloc(type, 0);
00318     if(parent != NULL)
00319     {
00320         parent->child_list = Py_BuildValue("(OO)", self, object);
00321 
00322         try
00323         {
00324             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)));
00325         }
00326         catch(AUD_Exception& e)
00327         {
00328             Py_DECREF(parent);
00329             PyErr_SetString(AUDError, e.str);
00330             return NULL;
00331         }
00332     }
00333 
00334     return (PyObject *)parent;
00335 }
00336 
00337 PyDoc_STRVAR(M_aud_Factory_highpass_doc,
00338              "highpass(frequency, Q=0.5)\n\n"
00339              "Creates a second order highpass filter based on the transfer "
00340              "function H(s) = s^2 / (s^2 + s/Q + 1)\n\n"
00341              ":arg frequency: The cut off trequency of the highpass.\n"
00342              ":type frequency: float\n"
00343              ":arg Q: Q factor of the lowpass.\n"
00344              ":type Q: float\n"
00345              ":return: The created :class:`Factory` object.\n"
00346              ":rtype: :class:`Factory`");
00347 
00348 static PyObject *
00349 Factory_highpass(Factory* self, PyObject* args)
00350 {
00351     float frequency;
00352     float Q = 0.5;
00353 
00354     if(!PyArg_ParseTuple(args, "f|f:highpass", &frequency, &Q))
00355         return NULL;
00356 
00357     PyTypeObject* type = Py_TYPE(self);
00358     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00359 
00360     if(parent != NULL)
00361     {
00362         Py_INCREF(self);
00363         parent->child_list = (PyObject*)self;
00364 
00365         try
00366         {
00367             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_HighpassFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), frequency, Q));
00368         }
00369         catch(AUD_Exception& e)
00370         {
00371             Py_DECREF(parent);
00372             PyErr_SetString(AUDError, e.str);
00373             return NULL;
00374         }
00375     }
00376 
00377     return (PyObject *)parent;
00378 }
00379 
00380 PyDoc_STRVAR(M_aud_Factory_limit_doc,
00381              "limit(start, end)\n\n"
00382              "Limits a factory within a specific start and end time.\n\n"
00383              ":arg start: Start time in seconds.\n"
00384              ":type start: float\n"
00385              ":arg end: End time in seconds.\n"
00386              ":type end: float\n"
00387              ":return: The created :class:`Factory` object.\n"
00388              ":rtype: :class:`Factory`");
00389 
00390 static PyObject *
00391 Factory_limit(Factory* self, PyObject* args)
00392 {
00393     float start, end;
00394 
00395     if(!PyArg_ParseTuple(args, "ff:limit", &start, &end))
00396         return NULL;
00397 
00398     PyTypeObject* type = Py_TYPE(self);
00399     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00400 
00401     if(parent != NULL)
00402     {
00403         Py_INCREF(self);
00404         parent->child_list = (PyObject*)self;
00405 
00406         try
00407         {
00408             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LimiterFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), start, end));
00409         }
00410         catch(AUD_Exception& e)
00411         {
00412             Py_DECREF(parent);
00413             PyErr_SetString(AUDError, e.str);
00414             return NULL;
00415         }
00416     }
00417 
00418     return (PyObject *)parent;
00419 }
00420 
00421 PyDoc_STRVAR(M_aud_Factory_pitch_doc,
00422              "pitch(factor)\n\n"
00423              "Changes the pitch of a factory with a specific factor.\n\n"
00424              ":arg factor: The factor to change the pitch with.\n"
00425              ":type factor: float\n"
00426              ":return: The created :class:`Factory` object.\n"
00427              ":rtype: :class:`Factory`\n\n"
00428              ".. note:: This is done by changing the sample rate of the "
00429              "underlying factory, which has to be an integer, so the factor "
00430              "value rounded and the factor may not be 100 % accurate.\n\n"
00431              ".. note:: This is a filter function, you might consider using "
00432              ":attr:`Handle.pitch` instead.");
00433 
00434 static PyObject *
00435 Factory_pitch(Factory* self, PyObject* args)
00436 {
00437     float factor;
00438 
00439     if(!PyArg_ParseTuple(args, "f:pitch", &factor))
00440         return NULL;
00441 
00442     PyTypeObject* type = Py_TYPE(self);
00443     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00444 
00445     if(parent != NULL)
00446     {
00447         Py_INCREF(self);
00448         parent->child_list = (PyObject*)self;
00449 
00450         try
00451         {
00452             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_PitchFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), factor));
00453         }
00454         catch(AUD_Exception& e)
00455         {
00456             Py_DECREF(parent);
00457             PyErr_SetString(AUDError, e.str);
00458             return NULL;
00459         }
00460     }
00461 
00462     return (PyObject *)parent;
00463 }
00464 
00465 PyDoc_STRVAR(M_aud_Factory_volume_doc,
00466              "volume(volume)\n\n"
00467              "Changes the volume of a factory.\n\n"
00468              ":arg volume: The new volume..\n"
00469              ":type volume: float\n"
00470              ":return: The created :class:`Factory` object.\n"
00471              ":rtype: :class:`Factory`\n\n"
00472              ".. note:: Should be in the range [0, 1] to avoid clipping.\n\n"
00473              ".. note:: This is a filter function, you might consider using "
00474              ":attr:`Handle.volume` instead.");
00475 
00476 static PyObject *
00477 Factory_volume(Factory* self, PyObject* args)
00478 {
00479     float volume;
00480 
00481     if(!PyArg_ParseTuple(args, "f:volume", &volume))
00482         return NULL;
00483 
00484     PyTypeObject* type = Py_TYPE(self);
00485     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00486 
00487     if(parent != NULL)
00488     {
00489         Py_INCREF(self);
00490         parent->child_list = (PyObject*)self;
00491 
00492         try
00493         {
00494             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_VolumeFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), volume));
00495         }
00496         catch(AUD_Exception& e)
00497         {
00498             Py_DECREF(parent);
00499             PyErr_SetString(AUDError, e.str);
00500             return NULL;
00501         }
00502     }
00503 
00504     return (PyObject *)parent;
00505 }
00506 
00507 PyDoc_STRVAR(M_aud_Factory_fadein_doc,
00508              "fadein(start, length)\n\n"
00509              "Fades a factory in by raising the volume linearly in the given "
00510              "time interval.\n\n"
00511              ":arg start: Time in seconds when the fading should start.\n"
00512              ":type start: float\n"
00513              ":arg length: Time in seconds how long the fading should last.\n"
00514              ":type length: float\n"
00515              ":return: The created :class:`Factory` object.\n"
00516              ":rtype: :class:`Factory`\n\n"
00517              ".. note:: Before the fade starts it plays silence.");
00518 
00519 static PyObject *
00520 Factory_fadein(Factory* self, PyObject* args)
00521 {
00522     float start, length;
00523 
00524     if(!PyArg_ParseTuple(args, "ff:fadein", &start, &length))
00525         return NULL;
00526 
00527     PyTypeObject* type = Py_TYPE(self);
00528     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00529 
00530     if(parent != NULL)
00531     {
00532         Py_INCREF(self);
00533         parent->child_list = (PyObject*)self;
00534 
00535         try
00536         {
00537             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), AUD_FADE_IN, start, length));
00538         }
00539         catch(AUD_Exception& e)
00540         {
00541             Py_DECREF(parent);
00542             PyErr_SetString(AUDError, e.str);
00543             return NULL;
00544         }
00545     }
00546 
00547     return (PyObject *)parent;
00548 }
00549 
00550 PyDoc_STRVAR(M_aud_Factory_fadeout_doc,
00551              "fadeout(start, length)\n\n"
00552              "Fades a factory in by lowering the volume linearly in the given "
00553              "time interval.\n\n"
00554              ":arg start: Time in seconds when the fading should start.\n"
00555              ":type start: float\n"
00556              ":arg length: Time in seconds how long the fading should last.\n"
00557              ":type length: float\n"
00558              ":return: The created :class:`Factory` object.\n"
00559              ":rtype: :class:`Factory`\n\n"
00560              ".. note:: After the fade this factory plays silence, so that "
00561              "the length of the factory is not altered.");
00562 
00563 static PyObject *
00564 Factory_fadeout(Factory* self, PyObject* args)
00565 {
00566     float start, length;
00567 
00568     if(!PyArg_ParseTuple(args, "ff:fadeout", &start, &length))
00569         return NULL;
00570 
00571     PyTypeObject* type = Py_TYPE(self);
00572     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00573 
00574     if(parent != NULL)
00575     {
00576         Py_INCREF(self);
00577         parent->child_list = (PyObject*)self;
00578 
00579         try
00580         {
00581             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), AUD_FADE_OUT, start, length));
00582         }
00583         catch(AUD_Exception& e)
00584         {
00585             Py_DECREF(parent);
00586             PyErr_SetString(AUDError, e.str);
00587             return NULL;
00588         }
00589     }
00590 
00591     return (PyObject *)parent;
00592 }
00593 
00594 PyDoc_STRVAR(M_aud_Factory_loop_doc,
00595              "loop(count)\n\n"
00596              "Loops a factory.\n\n"
00597              ":arg count: How often the factory should be looped. "
00598              "Negative values mean endlessly.\n"
00599              ":type count: integer\n"
00600              ":return: The created :class:`Factory` object.\n"
00601              ":rtype: :class:`Factory`\n\n"
00602              ".. note:: This is a filter function, you might consider using "
00603              ":attr:`Handle.loop_count` instead.");
00604 
00605 static PyObject *
00606 Factory_loop(Factory* self, PyObject* args)
00607 {
00608     int loop;
00609 
00610     if(!PyArg_ParseTuple(args, "i:loop", &loop))
00611         return NULL;
00612 
00613     PyTypeObject* type = Py_TYPE(self);
00614     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00615 
00616     if(parent != NULL)
00617     {
00618         Py_INCREF(self);
00619         parent->child_list = (PyObject*)self;
00620 
00621         try
00622         {
00623             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LoopFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), loop));
00624         }
00625         catch(AUD_Exception& e)
00626         {
00627             Py_DECREF(parent);
00628             PyErr_SetString(AUDError, e.str);
00629             return NULL;
00630         }
00631     }
00632 
00633     return (PyObject *)parent;
00634 }
00635 
00636 PyDoc_STRVAR(M_aud_Factory_mix_doc,
00637              "mix(factory)\n\n"
00638              "Mixes two factories.\n\n"
00639              ":arg factory: The factory to mix over the other.\n"
00640              ":type factory: :class:`Factory`\n"
00641              ":return: The created :class:`Factory` object.\n"
00642              ":rtype: :class:`Factory`\n\n"
00643              ".. note:: The two factories have to have the same specifications "
00644              "(channels and samplerate).");
00645 
00646 static PyObject *
00647 Factory_mix(Factory* self, PyObject* object)
00648 {
00649     PyTypeObject* type = Py_TYPE(self);
00650 
00651     if(!PyObject_TypeCheck(object, type))
00652     {
00653         PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
00654         return NULL;
00655     }
00656 
00657     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00658     Factory *child = (Factory*)object;
00659 
00660     if(parent != NULL)
00661     {
00662         parent->child_list = Py_BuildValue("(OO)", self, object);
00663 
00664         try
00665         {
00666             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)));
00667         }
00668         catch(AUD_Exception& e)
00669         {
00670             Py_DECREF(parent);
00671             PyErr_SetString(AUDError, e.str);
00672             return NULL;
00673         }
00674     }
00675 
00676     return (PyObject *)parent;
00677 }
00678 
00679 PyDoc_STRVAR(M_aud_Factory_pingpong_doc,
00680              "pingpong()\n\n"
00681              "Plays a factory forward and then backward.\n"
00682              "This is like joining a factory with its reverse.\n\n"
00683              ":return: The created :class:`Factory` object.\n"
00684              ":rtype: :class:`Factory`");
00685 
00686 static PyObject *
00687 Factory_pingpong(Factory* self)
00688 {
00689     PyTypeObject* type = Py_TYPE(self);
00690     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00691 
00692     if(parent != NULL)
00693     {
00694         Py_INCREF(self);
00695         parent->child_list = (PyObject*)self;
00696 
00697         try
00698         {
00699             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_PingPongFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory)));
00700         }
00701         catch(AUD_Exception& e)
00702         {
00703             Py_DECREF(parent);
00704             PyErr_SetString(AUDError, e.str);
00705             return NULL;
00706         }
00707     }
00708 
00709     return (PyObject *)parent;
00710 }
00711 
00712 PyDoc_STRVAR(M_aud_Factory_reverse_doc,
00713              "reverse()\n\n"
00714              "Plays a factory reversed.\n\n"
00715              ":return: The created :class:`Factory` object.\n"
00716              ":rtype: :class:`Factory`\n\n"
00717              ".. note:: The factory has to have a finite length and has to be "
00718              "seekable. It's recommended to use this only with factories     with "
00719              "fast and accurate seeking, which is not true for encoded audio "
00720              "files, such ones should be buffered using :meth:`buffer` before "
00721              "being played reversed.\n\n"
00722              ".. warning:: If seeking is not accurate in the underlying factory "
00723              "you'll likely hear skips/jumps/cracks.");
00724 
00725 static PyObject *
00726 Factory_reverse(Factory* self)
00727 {
00728     PyTypeObject* type = Py_TYPE(self);
00729     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00730 
00731     if(parent != NULL)
00732     {
00733         Py_INCREF(self);
00734         parent->child_list = (PyObject*)self;
00735 
00736         try
00737         {
00738             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_ReverseFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory)));
00739         }
00740         catch(AUD_Exception& e)
00741         {
00742             Py_DECREF(parent);
00743             PyErr_SetString(AUDError, e.str);
00744             return NULL;
00745         }
00746     }
00747 
00748     return (PyObject *)parent;
00749 }
00750 
00751 PyDoc_STRVAR(M_aud_Factory_buffer_doc,
00752              "buffer()\n\n"
00753              "Buffers a factory into RAM.\n"
00754              "This saves CPU usage needed for decoding and file access if the "
00755              "underlying factory reads from a file on the harddisk, but it "
00756              "consumes a lot of memory.\n\n"
00757              ":return: The created :class:`Factory` object.\n"
00758              ":rtype: :class:`Factory`\n\n"
00759              ".. note:: Only known-length factories can be buffered.\n\n"
00760              ".. warning:: Raw PCM data needs a lot of space, only buffer "
00761              "short factories.");
00762 
00763 static PyObject *
00764 Factory_buffer(Factory* self)
00765 {
00766     PyTypeObject* type = Py_TYPE(self);
00767     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00768 
00769     if(parent != NULL)
00770     {
00771         try
00772         {
00773             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_StreamBufferFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory)));
00774         }
00775         catch(AUD_Exception& e)
00776         {
00777             Py_DECREF(parent);
00778             PyErr_SetString(AUDError, e.str);
00779             return NULL;
00780         }
00781     }
00782 
00783     return (PyObject *)parent;
00784 }
00785 
00786 PyDoc_STRVAR(M_aud_Factory_square_doc,
00787              "square(threshold = 0)\n\n"
00788              "Makes a square wave out of an audio wave by setting all samples "
00789              "with a amplitude >= threshold to 1, all <= -threshold to -1 and "
00790              "all between to 0.\n\n"
00791              ":arg threshold: Threshold value over which an amplitude counts "
00792              "non-zero.\n"
00793              ":type threshold: float\n"
00794              ":return: The created :class:`Factory` object.\n"
00795              ":rtype: :class:`Factory`");
00796 
00797 static PyObject *
00798 Factory_square(Factory* self, PyObject* args)
00799 {
00800     float threshold = 0;
00801 
00802     if(!PyArg_ParseTuple(args, "|f:square", &threshold))
00803         return NULL;
00804 
00805     PyTypeObject* type = Py_TYPE(self);
00806     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00807 
00808     if(parent != NULL)
00809     {
00810         Py_INCREF(self);
00811         parent->child_list = (PyObject*)self;
00812 
00813         try
00814         {
00815             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_SquareFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), threshold));
00816         }
00817         catch(AUD_Exception& e)
00818         {
00819             Py_DECREF(parent);
00820             PyErr_SetString(AUDError, e.str);
00821             return NULL;
00822         }
00823     }
00824 
00825     return (PyObject *)parent;
00826 }
00827 
00828 PyDoc_STRVAR(M_aud_Factory_filter_doc,
00829              "filter(b, a = (1))\n\n"
00830              "Filters a factory with the supplied IIR filter coefficients.\n"
00831              "Without the second parameter you'll get a FIR filter.\n"
00832              "If the first value of the a sequence is 0 it will be set to 1 "
00833              "automatically.\n"
00834              "If the first value of the a sequence is neither 0 nor 1, all "
00835              "filter coefficients will be scaled by this value so that it is 1 "
00836              "in the end, you don't have to scale yourself.\n\n"
00837              ":arg b: The nominator filter coefficients.\n"
00838              ":type b: sequence of float\n"
00839              ":arg a: The denominator filter coefficients.\n"
00840              ":type a: sequence of float\n"
00841              ":return: The created :class:`Factory` object.\n"
00842              ":rtype: :class:`Factory`");
00843 
00844 static PyObject *
00845 Factory_filter(Factory* self, PyObject* args)
00846 {
00847     PyObject* py_b;
00848     PyObject* py_a = NULL;
00849     Py_ssize_t py_a_len;
00850     Py_ssize_t py_b_len;
00851 
00852     if(!PyArg_ParseTuple(args, "O|O:filter", &py_b, &py_a))
00853         return NULL;
00854 
00855     if(!PySequence_Check(py_b) || (py_a != NULL && !PySequence_Check(py_a)))
00856     {
00857         PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
00858         return NULL;
00859     }
00860 
00861     py_a_len= py_a ? PySequence_Size(py_a) : 0;
00862     py_b_len= PySequence_Size(py_b);
00863 
00864     if(!py_b_len || ((py_a != NULL) && !py_b_len))
00865     {
00866         PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
00867         return NULL;
00868     }
00869 
00870     std::vector<float> a, b;
00871     PyObject* py_value;
00872     float value;
00873 
00874     for(Py_ssize_t i = 0; i < py_b_len; i++)
00875     {
00876         py_value = PySequence_GetItem(py_b, i);
00877         value= (float)PyFloat_AsDouble(py_value);
00878         Py_DECREF(py_value);
00879 
00880         if (value==-1.0f && PyErr_Occurred()) {
00881             return NULL;
00882         }
00883 
00884         b.push_back(value);
00885     }
00886 
00887     if(py_a)
00888     {
00889         for(Py_ssize_t i = 0; i < py_a_len; i++)
00890         {
00891             py_value = PySequence_GetItem(py_a, i);
00892             value= (float)PyFloat_AsDouble(py_value);
00893             Py_DECREF(py_value);
00894 
00895             if (value==-1.0f && PyErr_Occurred()) {
00896                 return NULL;
00897             }
00898 
00899             a.push_back(value);
00900         }
00901 
00902         if(a[0] == 0)
00903             a[0] = 1;
00904     }
00905     else
00906         a.push_back(1);
00907 
00908     PyTypeObject* type = Py_TYPE(self);
00909     Factory *parent = (Factory*)type->tp_alloc(type, 0);
00910 
00911     if(parent != NULL)
00912     {
00913         Py_INCREF(self);
00914         parent->child_list = (PyObject*)self;
00915 
00916         try
00917         {
00918             parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_IIRFilterFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), b, a));
00919         }
00920         catch(AUD_Exception& e)
00921         {
00922             Py_DECREF(parent);
00923             PyErr_SetString(AUDError, e.str);
00924             return NULL;
00925         }
00926     }
00927 
00928     return (PyObject *)parent;
00929 }
00930 
00931 static PyMethodDef Factory_methods[] = {
00932     {"sine", (PyCFunction)Factory_sine, METH_VARARGS | METH_CLASS,
00933      M_aud_Factory_sine_doc
00934     },
00935     {"file", (PyCFunction)Factory_file, METH_VARARGS | METH_CLASS,
00936      M_aud_Factory_file_doc
00937     },
00938     {"lowpass", (PyCFunction)Factory_lowpass, METH_VARARGS,
00939      M_aud_Factory_lowpass_doc
00940     },
00941     {"delay", (PyCFunction)Factory_delay, METH_VARARGS,
00942      M_aud_Factory_delay_doc
00943     },
00944     {"join", (PyCFunction)Factory_join, METH_O,
00945      M_aud_Factory_join_doc
00946     },
00947     {"highpass", (PyCFunction)Factory_highpass, METH_VARARGS,
00948      M_aud_Factory_highpass_doc
00949     },
00950     {"limit", (PyCFunction)Factory_limit, METH_VARARGS,
00951      M_aud_Factory_limit_doc
00952     },
00953     {"pitch", (PyCFunction)Factory_pitch, METH_VARARGS,
00954      M_aud_Factory_pitch_doc
00955     },
00956     {"volume", (PyCFunction)Factory_volume, METH_VARARGS,
00957      M_aud_Factory_volume_doc
00958     },
00959     {"fadein", (PyCFunction)Factory_fadein, METH_VARARGS,
00960      M_aud_Factory_fadein_doc
00961     },
00962     {"fadeout", (PyCFunction)Factory_fadeout, METH_VARARGS,
00963      M_aud_Factory_fadeout_doc
00964     },
00965     {"loop", (PyCFunction)Factory_loop, METH_VARARGS,
00966      M_aud_Factory_loop_doc
00967     },
00968     {"mix", (PyCFunction)Factory_mix, METH_O,
00969      M_aud_Factory_mix_doc
00970     },
00971     {"pingpong", (PyCFunction)Factory_pingpong, METH_NOARGS,
00972      M_aud_Factory_pingpong_doc
00973     },
00974     {"reverse", (PyCFunction)Factory_reverse, METH_NOARGS,
00975      M_aud_Factory_reverse_doc
00976     },
00977     {"buffer", (PyCFunction)Factory_buffer, METH_NOARGS,
00978      M_aud_Factory_buffer_doc
00979     },
00980     {"square", (PyCFunction)Factory_square, METH_VARARGS,
00981      M_aud_Factory_square_doc
00982     },
00983     {"filter", (PyCFunction)Factory_filter, METH_VARARGS,
00984      M_aud_Factory_filter_doc
00985     },
00986     {NULL}  /* Sentinel */
00987 };
00988 
00989 PyDoc_STRVAR(M_aud_Factory_doc,
00990              "Factory objects are immutable and represent a sound that can be "
00991              "played simultaneously multiple times. They are called factories "
00992              "because they create reader objects internally that are used for "
00993              "playback.");
00994 
00995 static PyTypeObject FactoryType = {
00996     PyVarObject_HEAD_INIT(NULL, 0)
00997     "aud.Factory",               /* tp_name */
00998     sizeof(Factory),             /* tp_basicsize */
00999     0,                         /* tp_itemsize */
01000     (destructor)Factory_dealloc, /* tp_dealloc */
01001     0,                         /* tp_print */
01002     0,                         /* tp_getattr */
01003     0,                         /* tp_setattr */
01004     0,                         /* tp_reserved */
01005     0,                         /* tp_repr */
01006     0,                         /* tp_as_number */
01007     0,                         /* tp_as_sequence */
01008     0,                         /* tp_as_mapping */
01009     0,                         /* tp_hash  */
01010     0,                         /* tp_call */
01011     0,                         /* tp_str */
01012     0,                         /* tp_getattro */
01013     0,                         /* tp_setattro */
01014     0,                         /* tp_as_buffer */
01015     Py_TPFLAGS_DEFAULT,        /* tp_flags */
01016     M_aud_Factory_doc,           /* tp_doc */
01017     0,                         /* tp_traverse */
01018     0,                         /* tp_clear */
01019     0,                         /* tp_richcompare */
01020     0,                         /* tp_weaklistoffset */
01021     0,                         /* tp_iter */
01022     0,                         /* tp_iternext */
01023     Factory_methods,             /* tp_methods */
01024     0,                         /* tp_members */
01025     0,                         /* tp_getset */
01026     0,                         /* tp_base */
01027     0,                         /* tp_dict */
01028     0,                         /* tp_descr_get */
01029     0,                         /* tp_descr_set */
01030     0,                         /* tp_dictoffset */
01031     0,                         /* tp_init */
01032     0,                         /* tp_alloc */
01033     Factory_new,                 /* tp_new */
01034 };
01035 
01036 // ========== Handle ==================================================
01037 
01038 static void
01039 Handle_dealloc(Handle* self)
01040 {
01041     if(self->handle)
01042         delete reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle);
01043     Py_TYPE(self)->tp_free((PyObject*)self);
01044 }
01045 
01046 PyDoc_STRVAR(M_aud_Handle_pause_doc,
01047              "pause()\n\n"
01048              "Pauses playback.\n\n"
01049              ":return: Whether the action succeeded.\n"
01050              ":rtype: bool");
01051 
01052 static PyObject *
01053 Handle_pause(Handle *self)
01054 {
01055     try
01056     {
01057         return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->pause());
01058     }
01059     catch(AUD_Exception& e)
01060     {
01061         PyErr_SetString(AUDError, e.str);
01062         return NULL;
01063     }
01064 }
01065 
01066 PyDoc_STRVAR(M_aud_Handle_resume_doc,
01067              "resume()\n\n"
01068              "Resumes playback.\n\n"
01069              ":return: Whether the action succeeded.\n"
01070              ":rtype: bool");
01071 
01072 static PyObject *
01073 Handle_resume(Handle *self)
01074 {
01075     try
01076     {
01077         return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->resume());
01078     }
01079     catch(AUD_Exception& e)
01080     {
01081         PyErr_SetString(AUDError, e.str);
01082         return NULL;
01083     }
01084 }
01085 
01086 PyDoc_STRVAR(M_aud_Handle_stop_doc,
01087              "stop()\n\n"
01088              "Stops playback.\n\n"
01089              ":return: Whether the action succeeded.\n"
01090              ":rtype: bool\n\n"
01091              ".. note:: This makes the handle invalid.");
01092 
01093 static PyObject *
01094 Handle_stop(Handle *self)
01095 {
01096     try
01097     {
01098         return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->stop());
01099     }
01100     catch(AUD_Exception& e)
01101     {
01102         PyErr_SetString(AUDError, e.str);
01103         return NULL;
01104     }
01105 }
01106 
01107 static PyMethodDef Handle_methods[] = {
01108     {"pause", (PyCFunction)Handle_pause, METH_NOARGS,
01109      M_aud_Handle_pause_doc
01110     },
01111     {"resume", (PyCFunction)Handle_resume, METH_NOARGS,
01112      M_aud_Handle_resume_doc
01113     },
01114     {"stop", (PyCFunction)Handle_stop, METH_NOARGS,
01115      M_aud_Handle_stop_doc
01116     },
01117     {NULL}  /* Sentinel */
01118 };
01119 
01120 PyDoc_STRVAR(M_aud_Handle_position_doc,
01121              "The playback position of the sound in seconds.");
01122 
01123 static PyObject *
01124 Handle_get_position(Handle *self, void* nothing)
01125 {
01126     try
01127     {
01128         return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getPosition());
01129     }
01130     catch(AUD_Exception& e)
01131     {
01132         PyErr_SetString(AUDError, e.str);
01133         return NULL;
01134     }
01135 }
01136 
01137 static int
01138 Handle_set_position(Handle *self, PyObject* args, void* nothing)
01139 {
01140     float position;
01141 
01142     if(!PyArg_Parse(args, "f:position", &position))
01143         return -1;
01144 
01145     try
01146     {
01147         if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->seek(position))
01148             return 0;
01149         PyErr_SetString(AUDError, "Couldn't seek the sound!");
01150     }
01151     catch(AUD_Exception& e)
01152     {
01153         PyErr_SetString(AUDError, e.str);
01154     }
01155 
01156     return -1;
01157 }
01158 
01159 PyDoc_STRVAR(M_aud_Handle_keep_doc,
01160              "Whether the sound should be kept paused in the device when its "
01161              "end is reached.\n"
01162              "This can be used to seek the sound to some position and start "
01163              "playback again.\n\n"
01164              ".. warning:: If this is set to true and you forget stopping this "
01165              "equals a memory leak as the handle exists until the device is "
01166              "destroyed.");
01167 
01168 static PyObject *
01169 Handle_get_keep(Handle *self, void* nothing)
01170 {
01171     try
01172     {
01173         return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getKeep());
01174     }
01175     catch(AUD_Exception& e)
01176     {
01177         PyErr_SetString(AUDError, e.str);
01178         return NULL;
01179     }
01180 }
01181 
01182 static int
01183 Handle_set_keep(Handle *self, PyObject* args, void* nothing)
01184 {
01185     if(!PyBool_Check(args))
01186     {
01187         PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
01188         return -1;
01189     }
01190 
01191     bool keep = args == Py_True;
01192 
01193     try
01194     {
01195         if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setKeep(keep))
01196             return 0;
01197         PyErr_SetString(AUDError, "Couldn't set keep of the sound!");
01198     }
01199     catch(AUD_Exception& e)
01200     {
01201         PyErr_SetString(AUDError, e.str);
01202     }
01203 
01204     return -1;
01205 }
01206 
01207 PyDoc_STRVAR(M_aud_Handle_status_doc,
01208              "Whether the sound is playing, paused or stopped (=invalid).");
01209 
01210 static PyObject *
01211 Handle_get_status(Handle *self, void* nothing)
01212 {
01213     try
01214     {
01215         return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getStatus());
01216     }
01217     catch(AUD_Exception& e)
01218     {
01219         PyErr_SetString(AUDError, e.str);
01220         return NULL;
01221     }
01222 }
01223 
01224 PyDoc_STRVAR(M_aud_Handle_volume_doc,
01225              "The volume of the sound.");
01226 
01227 static PyObject *
01228 Handle_get_volume(Handle *self, void* nothing)
01229 {
01230     try
01231     {
01232         return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getVolume());
01233     }
01234     catch(AUD_Exception& e)
01235     {
01236         PyErr_SetString(AUDError, e.str);
01237         return NULL;
01238     }
01239 }
01240 
01241 static int
01242 Handle_set_volume(Handle *self, PyObject* args, void* nothing)
01243 {
01244     float volume;
01245 
01246     if(!PyArg_Parse(args, "f:volume", &volume))
01247         return -1;
01248 
01249     try
01250     {
01251         if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setVolume(volume))
01252             return 0;
01253         PyErr_SetString(AUDError, "Couldn't set the sound volume!");
01254     }
01255     catch(AUD_Exception& e)
01256     {
01257         PyErr_SetString(AUDError, e.str);
01258     }
01259 
01260     return -1;
01261 }
01262 
01263 PyDoc_STRVAR(M_aud_Handle_pitch_doc,
01264              "The pitch of the sound.");
01265 
01266 static PyObject *
01267 Handle_get_pitch(Handle *self, void* nothing)
01268 {
01269     try
01270     {
01271         return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getPitch());
01272     }
01273     catch(AUD_Exception& e)
01274     {
01275         PyErr_SetString(AUDError, e.str);
01276         return NULL;
01277     }
01278 }
01279 
01280 static int
01281 Handle_set_pitch(Handle *self, PyObject* args, void* nothing)
01282 {
01283     float pitch;
01284 
01285     if(!PyArg_Parse(args, "f:pitch", &pitch))
01286         return -1;
01287 
01288     try
01289     {
01290         if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setPitch(pitch))
01291             return 0;
01292         PyErr_SetString(AUDError, "Couldn't set the sound pitch!");
01293     }
01294     catch(AUD_Exception& e)
01295     {
01296         PyErr_SetString(AUDError, e.str);
01297     }
01298 
01299     return -1;
01300 }
01301 
01302 PyDoc_STRVAR(M_aud_Handle_loop_count_doc,
01303              "The (remaining) loop count of the sound. A negative value indicates infinity.");
01304 
01305 static PyObject *
01306 Handle_get_loop_count(Handle *self, void* nothing)
01307 {
01308     try
01309     {
01310         return Py_BuildValue("i", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getLoopCount());
01311     }
01312     catch(AUD_Exception& e)
01313     {
01314         PyErr_SetString(AUDError, e.str);
01315         return NULL;
01316     }
01317 }
01318 
01319 static int
01320 Handle_set_loop_count(Handle *self, PyObject* args, void* nothing)
01321 {
01322     int loops;
01323 
01324     if(!PyArg_Parse(args, "i:loop_count", &loops))
01325         return -1;
01326 
01327     try
01328     {
01329         if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setLoopCount(loops))
01330             return 0;
01331         PyErr_SetString(AUDError, "Couldn't set the loop count!");
01332     }
01333     catch(AUD_Exception& e)
01334     {
01335         PyErr_SetString(AUDError, e.str);
01336     }
01337 
01338     return -1;
01339 }
01340 
01341 PyDoc_STRVAR(M_aud_Handle_location_doc,
01342              "The source's location in 3D space, a 3D tuple of floats.");
01343 
01344 static PyObject *
01345 Handle_get_location(Handle *self, void* nothing)
01346 {
01347     try
01348     {
01349         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01350         if(handle)
01351         {
01352             AUD_Vector3 v = handle->getSourceLocation();
01353             return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
01354         }
01355         else
01356         {
01357             PyErr_SetString(AUDError, device_not_3d_error);
01358         }
01359     }
01360     catch(AUD_Exception& e)
01361     {
01362         PyErr_SetString(AUDError, e.str);
01363     }
01364 
01365     return NULL;
01366 }
01367 
01368 static int
01369 Handle_set_location(Handle *self, PyObject* args, void* nothing)
01370 {
01371     float x, y, z;
01372 
01373     if(!PyArg_Parse(args, "(fff):location", &x, &y, &z))
01374         return -1;
01375 
01376     try
01377     {
01378         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01379         if(handle)
01380         {
01381             AUD_Vector3 location(x, y, z);
01382             if(handle->setSourceLocation(location))
01383                 return 0;
01384             PyErr_SetString(AUDError, "Location couldn't be set!");
01385         }
01386         else
01387             PyErr_SetString(AUDError, device_not_3d_error);
01388     }
01389     catch(AUD_Exception& e)
01390     {
01391         PyErr_SetString(AUDError, e.str);
01392     }
01393 
01394     return -1;
01395 }
01396 
01397 PyDoc_STRVAR(M_aud_Handle_velocity_doc,
01398              "The source's velocity in 3D space, a 3D tuple of floats.");
01399 
01400 static PyObject *
01401 Handle_get_velocity(Handle *self, void* nothing)
01402 {
01403     try
01404     {
01405         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01406         if(handle)
01407         {
01408             AUD_Vector3 v = handle->getSourceVelocity();
01409             return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
01410         }
01411         else
01412         {
01413             PyErr_SetString(AUDError, device_not_3d_error);
01414         }
01415     }
01416     catch(AUD_Exception& e)
01417     {
01418         PyErr_SetString(AUDError, e.str);
01419     }
01420 
01421     return NULL;
01422 }
01423 
01424 static int
01425 Handle_set_velocity(Handle *self, PyObject* args, void* nothing)
01426 {
01427     float x, y, z;
01428 
01429     if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z))
01430         return -1;
01431 
01432     try
01433     {
01434         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01435         if(handle)
01436         {
01437             AUD_Vector3 velocity(x, y, z);
01438             if(handle->setSourceVelocity(velocity))
01439                 return 0;
01440             PyErr_SetString(AUDError, "Couldn't set the velocity!");
01441         }
01442         else
01443             PyErr_SetString(AUDError, device_not_3d_error);
01444     }
01445     catch(AUD_Exception& e)
01446     {
01447         PyErr_SetString(AUDError, e.str);
01448     }
01449 
01450     return -1;
01451 }
01452 
01453 PyDoc_STRVAR(M_aud_Handle_orientation_doc,
01454              "The source's orientation in 3D space as quaternion, a 4 float tuple.");
01455 
01456 static PyObject *
01457 Handle_get_orientation(Handle *self, void* nothing)
01458 {
01459     try
01460     {
01461         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01462         if(handle)
01463         {
01464             AUD_Quaternion o = handle->getSourceOrientation();
01465             return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
01466         }
01467         else
01468         {
01469             PyErr_SetString(AUDError, device_not_3d_error);
01470         }
01471     }
01472     catch(AUD_Exception& e)
01473     {
01474         PyErr_SetString(AUDError, e.str);
01475     }
01476 
01477     return NULL;
01478 }
01479 
01480 static int
01481 Handle_set_orientation(Handle *self, PyObject* args, void* nothing)
01482 {
01483     float w, x, y, z;
01484 
01485     if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z))
01486         return -1;
01487 
01488     try
01489     {
01490         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01491         if(handle)
01492         {
01493             AUD_Quaternion orientation(w, x, y, z);
01494             if(handle->setSourceOrientation(orientation))
01495                 return 0;
01496             PyErr_SetString(AUDError, "Couldn't set the orientation!");
01497         }
01498         else
01499             PyErr_SetString(AUDError, device_not_3d_error);
01500     }
01501     catch(AUD_Exception& e)
01502     {
01503         PyErr_SetString(AUDError, e.str);
01504     }
01505 
01506     return -1;
01507 }
01508 
01509 PyDoc_STRVAR(M_aud_Handle_relative_doc,
01510              "Whether the source's location, velocity and orientation is relative or absolute to the listener.");
01511 
01512 static PyObject *
01513 Handle_get_relative(Handle *self, void* nothing)
01514 {
01515     try
01516     {
01517         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01518         if(handle)
01519         {
01520             return PyBool_FromLong((long)handle->isRelative());
01521         }
01522         else
01523         {
01524             PyErr_SetString(AUDError, device_not_3d_error);
01525         }
01526     }
01527     catch(AUD_Exception& e)
01528     {
01529         PyErr_SetString(AUDError, e.str);
01530     }
01531 
01532     return NULL;
01533 }
01534 
01535 static int
01536 Handle_set_relative(Handle *self, PyObject* args, void* nothing)
01537 {
01538     if(!PyBool_Check(args))
01539     {
01540         PyErr_SetString(PyExc_TypeError, "Value is not a boolean!");
01541         return -1;
01542     }
01543 
01544     bool relative = (args == Py_True);
01545 
01546     try
01547     {
01548         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01549         if(handle)
01550         {
01551             if(handle->setRelative(relative))
01552                 return 0;
01553             PyErr_SetString(AUDError, "Couldn't set the relativeness!");
01554         }
01555         else
01556             PyErr_SetString(AUDError, device_not_3d_error);
01557     }
01558     catch(AUD_Exception& e)
01559     {
01560         PyErr_SetString(AUDError, e.str);
01561     }
01562 
01563     return -1;
01564 }
01565 
01566 PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc,
01567              "The minimum volume of the source.\n\n"
01568              ".. seealso:: :attr:`Device.distance_model`");
01569 
01570 static PyObject *
01571 Handle_get_volume_minimum(Handle *self, void* nothing)
01572 {
01573     try
01574     {
01575         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01576         if(handle)
01577         {
01578             return Py_BuildValue("f", handle->getVolumeMinimum());
01579         }
01580         else
01581         {
01582             PyErr_SetString(AUDError, device_not_3d_error);
01583             return NULL;
01584         }
01585     }
01586     catch(AUD_Exception& e)
01587     {
01588         PyErr_SetString(AUDError, e.str);
01589         return NULL;
01590     }
01591 }
01592 
01593 static int
01594 Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing)
01595 {
01596     float volume;
01597 
01598     if(!PyArg_Parse(args, "f:volume_minimum", &volume))
01599         return -1;
01600 
01601     try
01602     {
01603         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01604         if(handle)
01605         {
01606             if(handle->setVolumeMinimum(volume))
01607                 return 0;
01608             PyErr_SetString(AUDError, "Couldn't set the minimum volume!");
01609         }
01610         else
01611             PyErr_SetString(AUDError, device_not_3d_error);
01612     }
01613     catch(AUD_Exception& e)
01614     {
01615         PyErr_SetString(AUDError, e.str);
01616     }
01617 
01618     return -1;
01619 }
01620 
01621 PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc,
01622              "The maximum volume of the source.\n\n"
01623              ".. seealso:: :attr:`Device.distance_model`");
01624 
01625 static PyObject *
01626 Handle_get_volume_maximum(Handle *self, void* nothing)
01627 {
01628     try
01629     {
01630         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01631         if(handle)
01632         {
01633             return Py_BuildValue("f", handle->getVolumeMaximum());
01634         }
01635         else
01636         {
01637             PyErr_SetString(AUDError, device_not_3d_error);
01638             return NULL;
01639         }
01640     }
01641     catch(AUD_Exception& e)
01642     {
01643         PyErr_SetString(AUDError, e.str);
01644         return NULL;
01645     }
01646 }
01647 
01648 static int
01649 Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing)
01650 {
01651     float volume;
01652 
01653     if(!PyArg_Parse(args, "f:volume_maximum", &volume))
01654         return -1;
01655 
01656     try
01657     {
01658         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01659         if(handle)
01660         {
01661             if(handle->setVolumeMaximum(volume))
01662                 return 0;
01663             PyErr_SetString(AUDError, "Couldn't set the maximum volume!");
01664         }
01665         else
01666             PyErr_SetString(AUDError, device_not_3d_error);
01667     }
01668     catch(AUD_Exception& e)
01669     {
01670         PyErr_SetString(AUDError, e.str);
01671     }
01672 
01673     return -1;
01674 }
01675 
01676 PyDoc_STRVAR(M_aud_Handle_distance_reference_doc,
01677              "The reference distance of the source.\n"
01678              "At this distance the volume will be exactly :attr:`volume`.\n\n"
01679              ".. seealso:: :attr:`Device.distance_model`");
01680 
01681 static PyObject *
01682 Handle_get_distance_reference(Handle *self, void* nothing)
01683 {
01684     try
01685     {
01686         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01687         if(handle)
01688         {
01689             return Py_BuildValue("f", handle->getDistanceReference());
01690         }
01691         else
01692         {
01693             PyErr_SetString(AUDError, device_not_3d_error);
01694             return NULL;
01695         }
01696     }
01697     catch(AUD_Exception& e)
01698     {
01699         PyErr_SetString(AUDError, e.str);
01700         return NULL;
01701     }
01702 }
01703 
01704 static int
01705 Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing)
01706 {
01707     float distance;
01708 
01709     if(!PyArg_Parse(args, "f:distance_reference", &distance))
01710         return -1;
01711 
01712     try
01713     {
01714         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01715         if(handle)
01716         {
01717             if(handle->setDistanceReference(distance))
01718                 return 0;
01719             PyErr_SetString(AUDError, "Couldn't set the reference distance!");
01720         }
01721         else
01722             PyErr_SetString(AUDError, device_not_3d_error);
01723     }
01724     catch(AUD_Exception& e)
01725     {
01726         PyErr_SetString(AUDError, e.str);
01727     }
01728 
01729     return -1;
01730 }
01731 
01732 PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc,
01733              "The maximum distance of the source.\n"
01734              "If the listener is further away the source volume will be 0.\n\n"
01735              ".. seealso:: :attr:`Device.distance_model`");
01736 
01737 static PyObject *
01738 Handle_get_distance_maximum(Handle *self, void* nothing)
01739 {
01740     try
01741     {
01742         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01743         if(handle)
01744         {
01745             return Py_BuildValue("f", handle->getDistanceMaximum());
01746         }
01747         else
01748         {
01749             PyErr_SetString(AUDError, device_not_3d_error);
01750             return NULL;
01751         }
01752     }
01753     catch(AUD_Exception& e)
01754     {
01755         PyErr_SetString(AUDError, e.str);
01756         return NULL;
01757     }
01758 }
01759 
01760 static int
01761 Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing)
01762 {
01763     float distance;
01764 
01765     if(!PyArg_Parse(args, "f:distance_maximum", &distance))
01766         return -1;
01767 
01768     try
01769     {
01770         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01771         if(handle)
01772         {
01773             if(handle->setDistanceMaximum(distance))
01774                 return 0;
01775             PyErr_SetString(AUDError, "Couldn't set the maximum distance!");
01776         }
01777         else
01778             PyErr_SetString(AUDError, device_not_3d_error);
01779     }
01780     catch(AUD_Exception& e)
01781     {
01782         PyErr_SetString(AUDError, e.str);
01783     }
01784 
01785     return -1;
01786 }
01787 
01788 PyDoc_STRVAR(M_aud_Handle_attenuation_doc,
01789              "This factor is used for distance based attenuation of the "
01790              "source.\n\n"
01791              ".. seealso:: :attr:`Device.distance_model`");
01792 
01793 static PyObject *
01794 Handle_get_attenuation(Handle *self, void* nothing)
01795 {
01796     try
01797     {
01798         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01799         if(handle)
01800         {
01801             return Py_BuildValue("f", handle->getAttenuation());
01802         }
01803         else
01804         {
01805             PyErr_SetString(AUDError, device_not_3d_error);
01806             return NULL;
01807         }
01808     }
01809     catch(AUD_Exception& e)
01810     {
01811         PyErr_SetString(AUDError, e.str);
01812         return NULL;
01813     }
01814 }
01815 
01816 static int
01817 Handle_set_attenuation(Handle *self, PyObject* args, void* nothing)
01818 {
01819     float factor;
01820 
01821     if(!PyArg_Parse(args, "f:attenuation", &factor))
01822         return -1;
01823 
01824     try
01825     {
01826         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01827         if(handle)
01828         {
01829             if(handle->setAttenuation(factor))
01830                 return 0;
01831             PyErr_SetString(AUDError, "Couldn't set the attenuation!");
01832         }
01833         else
01834             PyErr_SetString(AUDError, device_not_3d_error);
01835     }
01836     catch(AUD_Exception& e)
01837     {
01838         PyErr_SetString(AUDError, e.str);
01839     }
01840 
01841     return -1;
01842 }
01843 
01844 PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc,
01845              "The opening angle of the inner cone of the source. If the cone "
01846              "values of a source are set there are two (audible) cones with "
01847              "the apex at the :attr:`location` of the source and with infinite "
01848              "height, heading in the direction of the source's "
01849              ":attr:`orientation`.\n"
01850              "In the inner cone the volume is normal. Outside the outer cone "
01851              "the volume will be :attr:`cone_volume_outer` and in the area "
01852              "between the volume will be interpolated linearly.");
01853 
01854 static PyObject *
01855 Handle_get_cone_angle_inner(Handle *self, void* nothing)
01856 {
01857     try
01858     {
01859         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01860         if(handle)
01861         {
01862             return Py_BuildValue("f", handle->getConeAngleInner());
01863         }
01864         else
01865         {
01866             PyErr_SetString(AUDError, device_not_3d_error);
01867             return NULL;
01868         }
01869     }
01870     catch(AUD_Exception& e)
01871     {
01872         PyErr_SetString(AUDError, e.str);
01873         return NULL;
01874     }
01875 }
01876 
01877 static int
01878 Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing)
01879 {
01880     float angle;
01881 
01882     if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
01883         return -1;
01884 
01885     try
01886     {
01887         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01888         if(handle)
01889         {
01890             if(handle->setConeAngleInner(angle))
01891                 return 0;
01892             PyErr_SetString(AUDError, "Couldn't set the cone inner angle!");
01893         }
01894         else
01895             PyErr_SetString(AUDError, device_not_3d_error);
01896     }
01897     catch(AUD_Exception& e)
01898     {
01899         PyErr_SetString(AUDError, e.str);
01900     }
01901 
01902     return -1;
01903 }
01904 
01905 PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc,
01906              "The opening angle of the outer cone of the source.\n\n"
01907              ".. seealso:: :attr:`cone_angle_inner`");
01908 
01909 static PyObject *
01910 Handle_get_cone_angle_outer(Handle *self, void* nothing)
01911 {
01912     try
01913     {
01914         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01915         if(handle)
01916         {
01917             return Py_BuildValue("f", handle->getConeAngleOuter());
01918         }
01919         else
01920         {
01921             PyErr_SetString(AUDError, device_not_3d_error);
01922             return NULL;
01923         }
01924     }
01925     catch(AUD_Exception& e)
01926     {
01927         PyErr_SetString(AUDError, e.str);
01928         return NULL;
01929     }
01930 }
01931 
01932 static int
01933 Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing)
01934 {
01935     float angle;
01936 
01937     if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
01938         return -1;
01939 
01940     try
01941     {
01942         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01943         if(handle)
01944         {
01945             if(handle->setConeAngleOuter(angle))
01946                 return 0;
01947             PyErr_SetString(AUDError, "Couldn't set the cone outer angle!");
01948         }
01949         else
01950             PyErr_SetString(AUDError, device_not_3d_error);
01951     }
01952     catch(AUD_Exception& e)
01953     {
01954         PyErr_SetString(AUDError, e.str);
01955     }
01956 
01957     return -1;
01958 }
01959 
01960 PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc,
01961              "The volume outside the outer cone of the source.\n\n"
01962              ".. seealso:: :attr:`cone_angle_inner`");
01963 
01964 static PyObject *
01965 Handle_get_cone_volume_outer(Handle *self, void* nothing)
01966 {
01967     try
01968     {
01969         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01970         if(handle)
01971         {
01972             return Py_BuildValue("f", handle->getConeVolumeOuter());
01973         }
01974         else
01975         {
01976             PyErr_SetString(AUDError, device_not_3d_error);
01977             return NULL;
01978         }
01979     }
01980     catch(AUD_Exception& e)
01981     {
01982         PyErr_SetString(AUDError, e.str);
01983         return NULL;
01984     }
01985 }
01986 
01987 static int
01988 Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing)
01989 {
01990     float volume;
01991 
01992     if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
01993         return -1;
01994 
01995     try
01996     {
01997         AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
01998         if(handle)
01999         {
02000             if(handle->setConeVolumeOuter(volume))
02001                 return 0;
02002             PyErr_SetString(AUDError, "Couldn't set the cone outer volume!");
02003         }
02004         else
02005             PyErr_SetString(AUDError, device_not_3d_error);
02006     }
02007     catch(AUD_Exception& e)
02008     {
02009         PyErr_SetString(AUDError, e.str);
02010     }
02011 
02012     return -1;
02013 }
02014 
02015 static PyGetSetDef Handle_properties[] = {
02016     {(char*)"position", (getter)Handle_get_position, (setter)Handle_set_position,
02017      M_aud_Handle_position_doc, NULL },
02018     {(char*)"keep", (getter)Handle_get_keep, (setter)Handle_set_keep,
02019      M_aud_Handle_keep_doc, NULL },
02020     {(char*)"status", (getter)Handle_get_status, NULL,
02021      M_aud_Handle_status_doc, NULL },
02022     {(char*)"volume", (getter)Handle_get_volume, (setter)Handle_set_volume,
02023      M_aud_Handle_volume_doc, NULL },
02024     {(char*)"pitch", (getter)Handle_get_pitch, (setter)Handle_set_pitch,
02025      M_aud_Handle_pitch_doc, NULL },
02026     {(char*)"loop_count", (getter)Handle_get_loop_count, (setter)Handle_set_loop_count,
02027      M_aud_Handle_loop_count_doc, NULL },
02028     {(char*)"location", (getter)Handle_get_location, (setter)Handle_set_location,
02029      M_aud_Handle_location_doc, NULL },
02030     {(char*)"velocity", (getter)Handle_get_velocity, (setter)Handle_set_velocity,
02031      M_aud_Handle_velocity_doc, NULL },
02032     {(char*)"orientation", (getter)Handle_get_orientation, (setter)Handle_set_orientation,
02033      M_aud_Handle_orientation_doc, NULL },
02034     {(char*)"relative", (getter)Handle_get_relative, (setter)Handle_set_relative,
02035      M_aud_Handle_relative_doc, NULL },
02036     {(char*)"volume_minimum", (getter)Handle_get_volume_minimum, (setter)Handle_set_volume_minimum,
02037      M_aud_Handle_volume_minimum_doc, NULL },
02038     {(char*)"volume_maximum", (getter)Handle_get_volume_maximum, (setter)Handle_set_volume_maximum,
02039      M_aud_Handle_volume_maximum_doc, NULL },
02040     {(char*)"distance_reference", (getter)Handle_get_distance_reference, (setter)Handle_set_distance_reference,
02041      M_aud_Handle_distance_reference_doc, NULL },
02042     {(char*)"distance_maximum", (getter)Handle_get_distance_maximum, (setter)Handle_set_distance_maximum,
02043      M_aud_Handle_distance_maximum_doc, NULL },
02044     {(char*)"attenuation", (getter)Handle_get_attenuation, (setter)Handle_set_attenuation,
02045      M_aud_Handle_attenuation_doc, NULL },
02046     {(char*)"cone_angle_inner", (getter)Handle_get_cone_angle_inner, (setter)Handle_set_cone_angle_inner,
02047      M_aud_Handle_cone_angle_inner_doc, NULL },
02048     {(char*)"cone_angle_outer", (getter)Handle_get_cone_angle_outer, (setter)Handle_set_cone_angle_outer,
02049      M_aud_Handle_cone_angle_outer_doc, NULL },
02050     {(char*)"cone_volume_outer", (getter)Handle_get_cone_volume_outer, (setter)Handle_set_cone_volume_outer,
02051      M_aud_Handle_cone_volume_outer_doc, NULL },
02052     {NULL}  /* Sentinel */
02053 };
02054 
02055 PyDoc_STRVAR(M_aud_Handle_doc,
02056              "Handle objects are playback handles that can be used to control "
02057              "playback of a sound. If a sound is played back multiple times "
02058              "then there are as many handles.");
02059 
02060 static PyTypeObject HandleType = {
02061     PyVarObject_HEAD_INIT(NULL, 0)
02062     "aud.Handle",              /* tp_name */
02063     sizeof(Handle),            /* tp_basicsize */
02064     0,                         /* tp_itemsize */
02065     (destructor)Handle_dealloc,/* tp_dealloc */
02066     0,                         /* tp_print */
02067     0,                         /* tp_getattr */
02068     0,                         /* tp_setattr */
02069     0,                         /* tp_reserved */
02070     0,                         /* tp_repr */
02071     0,                         /* tp_as_number */
02072     0,                         /* tp_as_sequence */
02073     0,                         /* tp_as_mapping */
02074     0,                         /* tp_hash  */
02075     0,                         /* tp_call */
02076     0,                         /* tp_str */
02077     0,                         /* tp_getattro */
02078     0,                         /* tp_setattro */
02079     0,                         /* tp_as_buffer */
02080     Py_TPFLAGS_DEFAULT,        /* tp_flags */
02081     M_aud_Handle_doc,          /* tp_doc */
02082     0,                         /* tp_traverse */
02083     0,                         /* tp_clear */
02084     0,                         /* tp_richcompare */
02085     0,                         /* tp_weaklistoffset */
02086     0,                         /* tp_iter */
02087     0,                         /* tp_iternext */
02088     Handle_methods,            /* tp_methods */
02089     0,                         /* tp_members */
02090     Handle_properties,         /* tp_getset */
02091     0,                         /* tp_base */
02092     0,                         /* tp_dict */
02093     0,                         /* tp_descr_get */
02094     0,                         /* tp_descr_set */
02095     0,                         /* tp_dictoffset */
02096     0,                         /* tp_init */
02097     0,                         /* tp_alloc */
02098     0,                         /* tp_new */
02099 };
02100 
02101 // ========== Device ==================================================
02102 
02103 static void
02104 Device_dealloc(Device* self)
02105 {
02106     if(self->device)
02107         delete reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device);
02108     Py_TYPE(self)->tp_free((PyObject*)self);
02109 }
02110 
02111 static PyObject *
02112 Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
02113 {
02114     Device *self;
02115 
02116     static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL};
02117     int device;
02118     double rate = AUD_RATE_44100;
02119     int channels = AUD_CHANNELS_STEREO;
02120     int format = AUD_FORMAT_FLOAT32;
02121     int buffersize = AUD_DEFAULT_BUFFER_SIZE;
02122     const char* name = "Audaspace";
02123 
02124     if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|diiis:Device", const_cast<char**>(kwlist),
02125                                     &device, &rate, &channels, &format, &buffersize, &name))
02126         return NULL;
02127 
02128     if(buffersize < 128)
02129     {
02130         PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than 127!");
02131         return NULL;
02132     }
02133 
02134     self = (Device*)type->tp_alloc(type, 0);
02135     if(self != NULL)
02136     {
02137         AUD_DeviceSpecs specs;
02138         specs.channels = (AUD_Channels)channels;
02139         specs.format = (AUD_SampleFormat)format;
02140         specs.rate = (AUD_SampleRate)rate;
02141 
02142         self->device = NULL;
02143 
02144         try
02145         {
02146             switch(device)
02147             {
02148             case AUD_DEVICE_NULL:
02149                 (void)specs; /* quiet warning when others disabled */
02150                 self->device = new AUD_Reference<AUD_IDevice>(new AUD_NULLDevice());
02151                 break;
02152             case AUD_DEVICE_OPENAL:
02153 #ifdef WITH_OPENAL
02154                 self->device = new AUD_Reference<AUD_IDevice>(new AUD_OpenALDevice(specs, buffersize));
02155 #endif
02156                 break;
02157             case AUD_DEVICE_SDL:
02158 #ifdef WITH_SDL
02159                 self->device = new AUD_Reference<AUD_IDevice>(new AUD_SDLDevice(specs, buffersize));
02160 #endif
02161                 break;
02162             case AUD_DEVICE_JACK:
02163 #ifdef WITH_JACK
02164                 self->device = new AUD_Reference<AUD_IDevice>(new AUD_JackDevice(name, specs, buffersize));
02165 #endif
02166                 break;
02167             case AUD_DEVICE_READ:
02168                 break;
02169             }
02170 
02171         }
02172         catch(AUD_Exception& e)
02173         {
02174             Py_DECREF(self);
02175             PyErr_SetString(AUDError, e.str);
02176             return NULL;
02177         }
02178 
02179         if(!self->device)
02180         {
02181             Py_DECREF(self);
02182             PyErr_SetString(AUDError, "Unsupported device type!");
02183             return NULL;
02184         }
02185     }
02186 
02187     return (PyObject *)self;
02188 }
02189 
02190 PyDoc_STRVAR(M_aud_Device_play_doc,
02191              "play(factory, keep=False)\n\n"
02192              "Plays a factory.\n\n"
02193              ":arg factory: The factory to play.\n"
02194              ":type factory: :class:`Factory`\n"
02195              ":arg keep: See :attr:`Handle.keep`.\n"
02196              ":type keep: bool\n"
02197              ":return: The playback handle with which playback can be "
02198              "controlled with.\n"
02199              ":rtype: :class:`Handle`");
02200 
02201 static PyObject *
02202 Device_play(Device *self, PyObject *args, PyObject *kwds)
02203 {
02204     PyObject* object;
02205     PyObject* keepo = NULL;
02206 
02207     bool keep = false;
02208 
02209     static const char *kwlist[] = {"factory", "keep", NULL};
02210 
02211     if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:play", const_cast<char**>(kwlist), &object, &keepo))
02212         return NULL;
02213 
02214     if(!PyObject_TypeCheck(object, &FactoryType))
02215     {
02216         PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
02217         return NULL;
02218     }
02219 
02220     if(keepo != NULL)
02221     {
02222         if(!PyBool_Check(keepo))
02223         {
02224             PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
02225             return NULL;
02226         }
02227 
02228         keep = keepo == Py_True;
02229     }
02230 
02231     Factory* sound = (Factory*)object;
02232     Handle *handle;
02233 
02234     handle = (Handle*)HandleType.tp_alloc(&HandleType, 0);
02235     if(handle != NULL)
02236     {
02237         try
02238         {
02239             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));
02240         }
02241         catch(AUD_Exception& e)
02242         {
02243             Py_DECREF(handle);
02244             PyErr_SetString(AUDError, e.str);
02245             return NULL;
02246         }
02247     }
02248 
02249     return (PyObject *)handle;
02250 }
02251 
02252 PyDoc_STRVAR(M_aud_Device_stopAll_doc,
02253              "stopAll()\n\n"
02254              "Stops all playing and paused sounds.");
02255 
02256 static PyObject *
02257 Device_stopAll(Device *self)
02258 {
02259     try
02260     {
02261         (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->stopAll();
02262         Py_RETURN_NONE;
02263     }
02264     catch(AUD_Exception& e)
02265     {
02266         PyErr_SetString(AUDError, e.str);
02267         return NULL;
02268     }
02269 }
02270 
02271 PyDoc_STRVAR(M_aud_Device_lock_doc,
02272              "lock()\n\n"
02273              "Locks the device so that it's guaranteed, that no samples are "
02274              "read from the streams until :meth:`unlock` is called.\n"
02275              "This is useful if you want to do start/stop/pause/resume some "
02276              "sounds at the same time.\n\n"
02277              ".. note:: The device has to be unlocked as often as locked to be "
02278              "able to continue playback.\n\n"
02279              ".. warning:: Make sure the time between locking and unlocking is "
02280              "as short as possible to avoid clicks.");
02281 
02282 static PyObject *
02283 Device_lock(Device *self)
02284 {
02285     try
02286     {
02287         (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->lock();
02288         Py_RETURN_NONE;
02289     }
02290     catch(AUD_Exception& e)
02291     {
02292         PyErr_SetString(AUDError, e.str);
02293         return NULL;
02294     }
02295 }
02296 
02297 PyDoc_STRVAR(M_aud_Device_unlock_doc,
02298              "unlock()\n\n"
02299              "Unlocks the device after a lock call, see :meth:`lock` for "
02300              "details.");
02301 
02302 static PyObject *
02303 Device_unlock(Device *self)
02304 {
02305     try
02306     {
02307         (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->unlock();
02308         Py_RETURN_NONE;
02309     }
02310     catch(AUD_Exception& e)
02311     {
02312         PyErr_SetString(AUDError, e.str);
02313         return NULL;
02314     }
02315 }
02316 
02317 static PyMethodDef Device_methods[] = {
02318     {"play", (PyCFunction)Device_play, METH_VARARGS | METH_KEYWORDS,
02319      M_aud_Device_play_doc
02320     },
02321     {"stopAll", (PyCFunction)Device_stopAll, METH_NOARGS,
02322      M_aud_Device_stopAll_doc
02323     },
02324     {"lock", (PyCFunction)Device_lock, METH_NOARGS,
02325      M_aud_Device_lock_doc
02326     },
02327     {"unlock", (PyCFunction)Device_unlock, METH_NOARGS,
02328      M_aud_Device_unlock_doc
02329     },
02330     {NULL}  /* Sentinel */
02331 };
02332 
02333 PyDoc_STRVAR(M_aud_Device_rate_doc,
02334              "The sampling rate of the device in Hz.");
02335 
02336 static PyObject *
02337 Device_get_rate(Device *self, void* nothing)
02338 {
02339     try
02340     {
02341         AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs();
02342         return Py_BuildValue("d", specs.rate);
02343     }
02344     catch(AUD_Exception& e)
02345     {
02346         PyErr_SetString(AUDError, e.str);
02347         return NULL;
02348     }
02349 }
02350 
02351 PyDoc_STRVAR(M_aud_Device_format_doc,
02352              "The native sample format of the device.");
02353 
02354 static PyObject *
02355 Device_get_format(Device *self, void* nothing)
02356 {
02357     try
02358     {
02359         AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs();
02360         return Py_BuildValue("i", specs.format);
02361     }
02362     catch(AUD_Exception& e)
02363     {
02364         PyErr_SetString(AUDError, e.str);
02365         return NULL;
02366     }
02367 }
02368 
02369 PyDoc_STRVAR(M_aud_Device_channels_doc,
02370              "The channel count of the device.");
02371 
02372 static PyObject *
02373 Device_get_channels(Device *self, void* nothing)
02374 {
02375     try
02376     {
02377         AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs();
02378         return Py_BuildValue("i", specs.channels);
02379     }
02380     catch(AUD_Exception& e)
02381     {
02382         PyErr_SetString(AUDError, e.str);
02383         return NULL;
02384     }
02385 }
02386 
02387 PyDoc_STRVAR(M_aud_Device_volume_doc,
02388              "The overall volume of the device.");
02389 
02390 static PyObject *
02391 Device_get_volume(Device *self, void* nothing)
02392 {
02393     try
02394     {
02395         return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getVolume());
02396     }
02397     catch(AUD_Exception& e)
02398     {
02399         PyErr_SetString(AUDError, e.str);
02400         return NULL;
02401     }
02402 }
02403 
02404 static int
02405 Device_set_volume(Device *self, PyObject* args, void* nothing)
02406 {
02407     float volume;
02408 
02409     if(!PyArg_Parse(args, "f:volume", &volume))
02410         return -1;
02411 
02412     try
02413     {
02414         (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->setVolume(volume);
02415         return 0;
02416     }
02417     catch(AUD_Exception& e)
02418     {
02419         PyErr_SetString(AUDError, e.str);
02420         return -1;
02421     }
02422 }
02423 
02424 PyDoc_STRVAR(M_aud_Device_listener_location_doc,
02425              "The listeners's location in 3D space, a 3D tuple of floats.");
02426 
02427 static PyObject *
02428 Device_get_listener_location(Device *self, void* nothing)
02429 {
02430     try
02431     {
02432         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02433         if(device)
02434         {
02435             AUD_Vector3 v = device->getListenerLocation();
02436             return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
02437         }
02438         else
02439         {
02440             PyErr_SetString(AUDError, device_not_3d_error);
02441         }
02442     }
02443     catch(AUD_Exception& e)
02444     {
02445         PyErr_SetString(AUDError, e.str);
02446     }
02447 
02448     return NULL;
02449 }
02450 
02451 static int
02452 Device_set_listener_location(Device *self, PyObject* args, void* nothing)
02453 {
02454     float x, y, z;
02455 
02456     if(!PyArg_Parse(args, "(fff):listener_location", &x, &y, &z))
02457         return -1;
02458 
02459     try
02460     {
02461         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02462         if(device)
02463         {
02464             AUD_Vector3 location(x, y, z);
02465             device->setListenerLocation(location);
02466             return 0;
02467         }
02468         else
02469             PyErr_SetString(AUDError, device_not_3d_error);
02470     }
02471     catch(AUD_Exception& e)
02472     {
02473         PyErr_SetString(AUDError, e.str);
02474     }
02475 
02476     return -1;
02477 }
02478 
02479 PyDoc_STRVAR(M_aud_Device_listener_velocity_doc,
02480              "The listener's velocity in 3D space, a 3D tuple of floats.");
02481 
02482 static PyObject *
02483 Device_get_listener_velocity(Device *self, void* nothing)
02484 {
02485     try
02486     {
02487         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02488         if(device)
02489         {
02490             AUD_Vector3 v = device->getListenerVelocity();
02491             return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
02492         }
02493         else
02494         {
02495             PyErr_SetString(AUDError, device_not_3d_error);
02496         }
02497     }
02498     catch(AUD_Exception& e)
02499     {
02500         PyErr_SetString(AUDError, e.str);
02501     }
02502 
02503     return NULL;
02504 }
02505 
02506 static int
02507 Device_set_listener_velocity(Device *self, PyObject* args, void* nothing)
02508 {
02509     float x, y, z;
02510 
02511     if(!PyArg_Parse(args, "(fff):listener_velocity", &x, &y, &z))
02512         return -1;
02513 
02514     try
02515     {
02516         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02517         if(device)
02518         {
02519             AUD_Vector3 velocity(x, y, z);
02520             device->setListenerVelocity(velocity);
02521             return 0;
02522         }
02523         else
02524             PyErr_SetString(AUDError, device_not_3d_error);
02525     }
02526     catch(AUD_Exception& e)
02527     {
02528         PyErr_SetString(AUDError, e.str);
02529     }
02530 
02531     return -1;
02532 }
02533 
02534 PyDoc_STRVAR(M_aud_Device_listener_orientation_doc,
02535              "The listener's orientation in 3D space as quaternion, a 4 float tuple.");
02536 
02537 static PyObject *
02538 Device_get_listener_orientation(Device *self, void* nothing)
02539 {
02540     try
02541     {
02542         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02543         if(device)
02544         {
02545             AUD_Quaternion o = device->getListenerOrientation();
02546             return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
02547         }
02548         else
02549         {
02550             PyErr_SetString(AUDError, device_not_3d_error);
02551         }
02552     }
02553     catch(AUD_Exception& e)
02554     {
02555         PyErr_SetString(AUDError, e.str);
02556     }
02557 
02558     return NULL;
02559 }
02560 
02561 static int
02562 Device_set_listener_orientation(Device *self, PyObject* args, void* nothing)
02563 {
02564     float w, x, y, z;
02565 
02566     if(!PyArg_Parse(args, "(ffff):listener_orientation", &w, &x, &y, &z))
02567         return -1;
02568 
02569     try
02570     {
02571         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02572         if(device)
02573         {
02574             AUD_Quaternion orientation(w, x, y, z);
02575             device->setListenerOrientation(orientation);
02576             return 0;
02577         }
02578         else
02579             PyErr_SetString(AUDError, device_not_3d_error);
02580     }
02581     catch(AUD_Exception& e)
02582     {
02583         PyErr_SetString(AUDError, e.str);
02584     }
02585 
02586     return -1;
02587 }
02588 
02589 PyDoc_STRVAR(M_aud_Device_speed_of_sound_doc,
02590              "The speed of sound of the device.\n"
02591              "The speed of sound in air is typically 343 m/s.");
02592 
02593 static PyObject *
02594 Device_get_speed_of_sound(Device *self, void* nothing)
02595 {
02596     try
02597     {
02598         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02599         if(device)
02600         {
02601             return Py_BuildValue("f", device->getSpeedOfSound());
02602         }
02603         else
02604         {
02605             PyErr_SetString(AUDError, device_not_3d_error);
02606             return NULL;
02607         }
02608     }
02609     catch(AUD_Exception& e)
02610     {
02611         PyErr_SetString(AUDError, e.str);
02612         return NULL;
02613     }
02614 }
02615 
02616 static int
02617 Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing)
02618 {
02619     float speed;
02620 
02621     if(!PyArg_Parse(args, "f:speed_of_sound", &speed))
02622         return -1;
02623 
02624     try
02625     {
02626         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02627         if(device)
02628         {
02629             device->setSpeedOfSound(speed);
02630             return 0;
02631         }
02632         else
02633             PyErr_SetString(AUDError, device_not_3d_error);
02634     }
02635     catch(AUD_Exception& e)
02636     {
02637         PyErr_SetString(AUDError, e.str);
02638     }
02639 
02640     return -1;
02641 }
02642 
02643 PyDoc_STRVAR(M_aud_Device_doppler_factor_doc,
02644              "The doppler factor of the device.\n"
02645              "This factor is a scaling factor for the velocity vectors in "
02646              "doppler calculation. So a value bigger than 1 will exaggerate "
02647              "the effect as it raises the velocity.");
02648 
02649 static PyObject *
02650 Device_get_doppler_factor(Device *self, void* nothing)
02651 {
02652     try
02653     {
02654         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02655         if(device)
02656         {
02657             return Py_BuildValue("f", device->getDopplerFactor());
02658         }
02659         else
02660         {
02661             PyErr_SetString(AUDError, device_not_3d_error);
02662             return NULL;
02663         }
02664     }
02665     catch(AUD_Exception& e)
02666     {
02667         PyErr_SetString(AUDError, e.str);
02668         return NULL;
02669     }
02670 }
02671 
02672 static int
02673 Device_set_doppler_factor(Device *self, PyObject* args, void* nothing)
02674 {
02675     float factor;
02676 
02677     if(!PyArg_Parse(args, "f:doppler_factor", &factor))
02678         return -1;
02679 
02680     try
02681     {
02682         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02683         if(device)
02684         {
02685             device->setDopplerFactor(factor);
02686             return 0;
02687         }
02688         else
02689             PyErr_SetString(AUDError, device_not_3d_error);
02690     }
02691     catch(AUD_Exception& e)
02692     {
02693         PyErr_SetString(AUDError, e.str);
02694     }
02695 
02696     return -1;
02697 }
02698 
02699 PyDoc_STRVAR(M_aud_Device_distance_model_doc,
02700              "The distance model of the device.\n\n"
02701              ".. seealso:: http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835864");
02702 
02703 static PyObject *
02704 Device_get_distance_model(Device *self, void* nothing)
02705 {
02706     try
02707     {
02708         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02709         if(device)
02710         {
02711             return Py_BuildValue("i", int(device->getDistanceModel()));
02712         }
02713         else
02714         {
02715             PyErr_SetString(AUDError, device_not_3d_error);
02716             return NULL;
02717         }
02718     }
02719     catch(AUD_Exception& e)
02720     {
02721         PyErr_SetString(AUDError, e.str);
02722         return NULL;
02723     }
02724 }
02725 
02726 static int
02727 Device_set_distance_model(Device *self, PyObject* args, void* nothing)
02728 {
02729     int model;
02730 
02731     if(!PyArg_Parse(args, "i:distance_model", &model))
02732         return -1;
02733 
02734     try
02735     {
02736         AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get());
02737         if(device)
02738         {
02739             device->setDistanceModel(AUD_DistanceModel(model));
02740             return 0;
02741         }
02742         else
02743             PyErr_SetString(AUDError, device_not_3d_error);
02744     }
02745     catch(AUD_Exception& e)
02746     {
02747         PyErr_SetString(AUDError, e.str);
02748     }
02749 
02750     return -1;
02751 }
02752 
02753 static PyGetSetDef Device_properties[] = {
02754     {(char*)"rate", (getter)Device_get_rate, NULL,
02755      M_aud_Device_rate_doc, NULL },
02756     {(char*)"format", (getter)Device_get_format, NULL,
02757      M_aud_Device_format_doc, NULL },
02758     {(char*)"channels", (getter)Device_get_channels, NULL,
02759      M_aud_Device_channels_doc, NULL },
02760     {(char*)"volume", (getter)Device_get_volume, (setter)Device_set_volume,
02761      M_aud_Device_volume_doc, NULL },
02762     {(char*)"listener_location", (getter)Device_get_listener_location, (setter)Device_set_listener_location,
02763      M_aud_Device_listener_location_doc, NULL },
02764     {(char*)"listener_velocity", (getter)Device_get_listener_velocity, (setter)Device_set_listener_velocity,
02765      M_aud_Device_listener_velocity_doc, NULL },
02766     {(char*)"listener_orientation", (getter)Device_get_listener_orientation, (setter)Device_set_listener_orientation,
02767      M_aud_Device_listener_orientation_doc, NULL },
02768     {(char*)"speed_of_sound", (getter)Device_get_speed_of_sound, (setter)Device_set_speed_of_sound,
02769      M_aud_Device_speed_of_sound_doc, NULL },
02770     {(char*)"doppler_factor", (getter)Device_get_doppler_factor, (setter)Device_set_doppler_factor,
02771      M_aud_Device_doppler_factor_doc, NULL },
02772     {(char*)"distance_model", (getter)Device_get_distance_model, (setter)Device_set_distance_model,
02773      M_aud_Device_distance_model_doc, NULL },
02774     {NULL}  /* Sentinel */
02775 };
02776 
02777 PyDoc_STRVAR(M_aud_Device_doc,
02778              "Device objects represent an audio output backend like OpenAL or "
02779              "SDL, but might also represent a file output or RAM buffer "
02780              "output.");
02781 
02782 static PyTypeObject DeviceType = {
02783     PyVarObject_HEAD_INIT(NULL, 0)
02784     "aud.Device",              /* tp_name */
02785     sizeof(Device),            /* tp_basicsize */
02786     0,                         /* tp_itemsize */
02787     (destructor)Device_dealloc,/* tp_dealloc */
02788     0,                         /* tp_print */
02789     0,                         /* tp_getattr */
02790     0,                         /* tp_setattr */
02791     0,                         /* tp_reserved */
02792     0,                         /* tp_repr */
02793     0,                         /* tp_as_number */
02794     0,                         /* tp_as_sequence */
02795     0,                         /* tp_as_mapping */
02796     0,                         /* tp_hash  */
02797     0,                         /* tp_call */
02798     0,                         /* tp_str */
02799     0,                         /* tp_getattro */
02800     0,                         /* tp_setattro */
02801     0,                         /* tp_as_buffer */
02802     Py_TPFLAGS_DEFAULT,        /* tp_flags */
02803     M_aud_Device_doc,          /* tp_doc */
02804     0,                         /* tp_traverse */
02805     0,                         /* tp_clear */
02806     0,                         /* tp_richcompare */
02807     0,                         /* tp_weaklistoffset */
02808     0,                         /* tp_iter */
02809     0,                         /* tp_iternext */
02810     Device_methods,            /* tp_methods */
02811     0,                         /* tp_members */
02812     Device_properties,         /* tp_getset */
02813     0,                         /* tp_base */
02814     0,                         /* tp_dict */
02815     0,                         /* tp_descr_get */
02816     0,                         /* tp_descr_set */
02817     0,                         /* tp_dictoffset */
02818     0,                         /* tp_init */
02819     0,                         /* tp_alloc */
02820     Device_new,                /* tp_new */
02821 };
02822 
02823 PyObject *
02824 Device_empty()
02825 {
02826     return DeviceType.tp_alloc(&DeviceType, 0);
02827 }
02828 
02829 PyObject *
02830 Factory_empty()
02831 {
02832     return FactoryType.tp_alloc(&FactoryType, 0);
02833 }
02834 
02835 Factory*
02836 checkFactory(PyObject* factory)
02837 {
02838     if(!PyObject_TypeCheck(factory, &FactoryType))
02839     {
02840         PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
02841         return NULL;
02842     }
02843 
02844     return (Factory*)factory;
02845 }
02846 
02847 
02848 // ====================================================================
02849 
02850 PyDoc_STRVAR(M_aud_doc,
02851              "This module provides access to the audaspace audio library.");
02852 
02853 static struct PyModuleDef audmodule = {
02854     PyModuleDef_HEAD_INIT,
02855     "aud",     /* name of module */
02856     M_aud_doc, /* module documentation */
02857     -1,        /* size of per-interpreter state of the module,
02858                   or -1 if the module keeps state in global variables. */
02859    NULL, NULL, NULL, NULL, NULL
02860 };
02861 
02862 PyMODINIT_FUNC
02863 PyInit_aud(void)
02864 {
02865     PyObject* m;
02866 
02867     if(PyType_Ready(&FactoryType) < 0)
02868         return NULL;
02869 
02870     if(PyType_Ready(&DeviceType) < 0)
02871         return NULL;
02872 
02873     if(PyType_Ready(&HandleType) < 0)
02874         return NULL;
02875 
02876     m = PyModule_Create(&audmodule);
02877     if(m == NULL)
02878         return NULL;
02879 
02880     Py_INCREF(&FactoryType);
02881     PyModule_AddObject(m, "Factory", (PyObject*)&FactoryType);
02882 
02883     Py_INCREF(&DeviceType);
02884     PyModule_AddObject(m, "Device", (PyObject*)&DeviceType);
02885 
02886     Py_INCREF(&HandleType);
02887     PyModule_AddObject(m, "Handle", (PyObject*)&HandleType);
02888 
02889     AUDError = PyErr_NewException("aud.error", NULL, NULL);
02890     Py_INCREF(AUDError);
02891     PyModule_AddObject(m, "error", AUDError);
02892 
02893     // device constants
02894     PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_NULL);
02895     PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_OPENAL);
02896     PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_SDL);
02897     PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_JACK);
02898     //PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_READ);
02899     // format constants
02900     PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT32);
02901     PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT64);
02902     PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_INVALID);
02903     PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S16);
02904     PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S24);
02905     PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S32);
02906     PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_U8);
02907     // status constants
02908     PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_INVALID);
02909     PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PAUSED);
02910     PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PLAYING);
02911     // distance model constants
02912     PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT);
02913     PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT_CLAMPED);
02914     PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE);
02915     PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE_CLAMPED);
02916     PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR);
02917     PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR_CLAMPED);
02918     PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVALID);
02919 
02920     return m;
02921 }