1 /************************************************************************/
2 /*  PyRtAudio: a python wrapper around RtAudio
3     Copyright (c) 2011 Antoine Lefebvre
4 
5     Permission is hereby granted, free of charge, to any person
6     obtaining a copy of this software and associated documentation files
7     (the "Software"), to deal in the Software without restriction,
8     including without limitation the rights to use, copy, modify, merge,
9     publish, distribute, sublicense, and/or sell copies of the Software,
10     and to permit persons to whom the Software is furnished to do so,
11     subject to the following conditions:
12 
13     The above copyright notice and this permission notice shall be
14     included in all copies or substantial portions of the Software.
15 
16     Any person wishing to distribute modifications to the Software is
17     asked to send the modifications to the original developer so that
18     they can be incorporated into the canonical version.  This is,
19     however, not a binding provision of this license.
20 
21     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
25     ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
26     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 */
29 /************************************************************************/
30 
31 // This software is in the development stage
32 // Do not expect compatibility with future versions.
33 // Comments, suggestions, new features, bug fixes, etc. are welcome
34 
35 #include <Python.h>
36 
37 #include "RtAudio.h"
38 
39 extern "C" {
40 
41     typedef struct
42     {
43         PyObject_HEAD
44 #if PY_MAJOR_VERSION < 3
45         void *padding; // python 2.7 seems to set dac to bad value
46                        // after print_function, causing a crash, no
47                        // idea why, but this fixes it.
48 #endif
49         RtAudio *dac;
50         RtAudioFormat _format;
51         int _bufferSize;
52         unsigned int inputChannels;
53         PyObject *callback_func;
54     } PyRtAudio;
55 
56     static PyObject *RtAudioErrorException;
57 
callback(void * outputBuffer,void * inputBuffer,unsigned int nBufferFrames,double streamTime,RtAudioStreamStatus status,void * data)58     static int callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
59         double streamTime, RtAudioStreamStatus status, void *data )
60     {
61         PyRtAudio* self = (PyRtAudio*) data;
62 
63         if (status == RTAUDIO_OUTPUT_UNDERFLOW)
64             printf("underflow.\n");
65 
66         if (self == NULL) return -1;
67 
68         float* in = (float *) inputBuffer;
69         float* out = (float *) outputBuffer;
70 
71         PyObject *py_callback_func = self->callback_func;
72 
73         int retval = 0;
74 
75         if (py_callback_func) {
76             PyGILState_STATE gstate = PyGILState_Ensure();
77 
78 #if PY_MAJOR_VERSION >= 3
79             PyObject* iBuffer = PyMemoryView_FromMemory((char*)in, sizeof(float) * self->inputChannels * nBufferFrames, PyBUF_READ);
80             PyObject* oBuffer = PyMemoryView_FromMemory((char*)out, sizeof(float) * nBufferFrames, PyBUF_WRITE);
81 #else
82             PyObject* iBuffer = PyBuffer_FromMemory(in, sizeof(float) * self->inputChannels * nBufferFrames);
83             PyObject* oBuffer = PyBuffer_FromReadWriteMemory(out, sizeof(float) * nBufferFrames);
84 #endif
85             PyObject *arglist =  Py_BuildValue("(O,O)", oBuffer, iBuffer);
86 
87             if (arglist == NULL) {
88                 printf("error.\n");
89                 PyErr_Print();
90                 PyGILState_Release(gstate);
91                 return 2;
92             }
93 
94             // Calling the callback
95             PyObject *result = PyEval_CallObject(py_callback_func, arglist);
96 
97             if (PyErr_Occurred() != NULL) {
98                 PyErr_Print();
99             }
100 #if PY_MAJOR_VERSION >= 3
101             else if (result == NULL)
102               retval = 0;
103             else if (PyLong_Check(result)) {
104               retval = PyLong_AsLong(result);
105             }
106 #else
107             else if (PyInt_Check(result)) {
108               retval = PyInt_AsLong(result);
109             }
110 #endif
111 
112             Py_DECREF(arglist);
113             Py_DECREF(oBuffer);
114             Py_DECREF(iBuffer);
115             Py_XDECREF(result);
116 
117             PyGILState_Release(gstate);
118         }
119 
120         return retval;
121     }
122 
123 
124 
RtAudio_dealloc(PyRtAudio * self)125     static void RtAudio_dealloc(PyRtAudio *self)
126     {
127         printf("RtAudio_dealloc.\n");
128         if (self == NULL) return;
129 
130         if (self->dac) {
131             self->dac->closeStream();
132             Py_CLEAR(self->callback_func);
133             delete self->dac;
134         }
135 
136         Py_TYPE(self)->tp_free((PyObject *) self);
137     }
138 
139 
RtAudio_new(PyTypeObject * type,PyObject * args,PyObject * kwds)140     static PyObject* RtAudio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
141     {
142         printf("RtAudio_new.\n");
143         PyRtAudio *self;
144         char *api = NULL;
145 
146         if(!PyArg_ParseTuple(args, "|s", &api))
147             return NULL;
148 
149         self = (PyRtAudio *) type->tp_alloc(type, 0);
150 
151         if(self == NULL) return NULL;
152 
153         self->dac = NULL;
154         self->callback_func = NULL;
155 
156         try {
157             if (api == NULL)
158                 self->dac = new RtAudio;
159             else if(!strcmp(api, "jack"))
160                 self->dac = new RtAudio(RtAudio::UNIX_JACK);
161             else if(!strcmp(api, "alsa"))
162                 self->dac = new RtAudio(RtAudio::LINUX_ALSA);
163             else if(!strcmp(api, "oss"))
164                 self->dac = new RtAudio(RtAudio::LINUX_ALSA);
165             else if(!strcmp(api, "core"))
166                 self->dac = new RtAudio(RtAudio::MACOSX_CORE);
167             else if(!strcmp(api, "asio"))
168                 self->dac = new RtAudio(RtAudio::WINDOWS_ASIO);
169             else if(!strcmp(api, "directsound"))
170                 self->dac = new RtAudio(RtAudio::WINDOWS_DS);
171         }
172         catch (RtAudioError &error) {
173             PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
174             Py_INCREF(RtAudioErrorException);
175             return NULL;
176         }
177 
178         self->dac->showWarnings(false);
179 
180         //Py_XINCREF(self);
181         return (PyObject *) self;
182     }
183 
RtAudio_init(PyRtAudio * self,PyObject * args,PyObject * kwds)184     static int RtAudio_init(PyRtAudio *self, PyObject *args, PyObject *kwds)
185     {
186         printf("RtAudio_init.\n");
187         //if (self == NULL) return 0;
188         return 0;
189     }
190 
191     // This functions does not yet support all the features of the RtAudio::openStream method.
192     // Please send your patches if you improves this.
RtAudio_openStream(PyRtAudio * self,PyObject * args)193     static PyObject* RtAudio_openStream(PyRtAudio *self, PyObject *args)
194     {
195         if (self == NULL) return NULL;
196 
197         if (self->dac == NULL) {
198             printf("the dac is null.\n");
199             Py_RETURN_NONE;
200         }
201 
202         PyObject *oParamsObj;
203         PyObject *iParamsObj;
204         int fs;
205         unsigned int bf;
206         PyObject *pycallback;
207 
208         if (!PyArg_ParseTuple(args, "OOiiO", &oParamsObj, &iParamsObj, &fs, &bf, &pycallback))
209             return NULL;
210 
211         RtAudio::StreamParameters oParams;
212         oParams.deviceId = 1;
213         oParams.nChannels = 1;
214         oParams.firstChannel = 0;
215 
216         if (PyDict_Check(oParamsObj)) {
217 #if PY_MAJOR_VERSION >= 3
218             if (PyDict_Contains(oParamsObj, PyUnicode_FromString("deviceId"))) {
219                 PyObject *value = PyDict_GetItem(oParamsObj, PyUnicode_FromString("deviceId"));
220                 oParams.deviceId = PyLong_AsLong(value);
221             }
222             if (PyDict_Contains(oParamsObj, PyUnicode_FromString("nChannels"))) {
223                 PyObject *value = PyDict_GetItem(oParamsObj, PyUnicode_FromString("nChannels"));
224                 oParams.nChannels = PyLong_AsLong(value);
225             }
226             if (PyDict_Contains(oParamsObj, PyUnicode_FromString("firstChannel"))) {
227                 PyObject *value = PyDict_GetItem(oParamsObj, PyUnicode_FromString("firstChannel"));
228                 oParams.firstChannel = PyLong_AsLong(value);
229             }
230 #else
231             if (PyDict_Contains(oParamsObj, PyString_FromString("deviceId"))) {
232                 PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString("deviceId"));
233                 oParams.deviceId = PyInt_AsLong(value);
234             }
235             if (PyDict_Contains(oParamsObj, PyString_FromString("nChannels"))) {
236                 PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString("nChannels"));
237                 oParams.nChannels = PyInt_AsLong(value);
238             }
239             if (PyDict_Contains(oParamsObj, PyString_FromString("firstChannel"))) {
240                 PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString("firstChannel"));
241                 oParams.firstChannel = PyInt_AsLong(value);
242             }
243 #endif
244         }
245         else {
246             printf("First argument must be a dictionary. Default values will be used.\n");
247         }
248 
249         RtAudio::StreamParameters iParams;
250         iParams.deviceId = 1;
251         iParams.nChannels = 2;
252         iParams.firstChannel = 0;
253 
254         if (PyDict_Check(iParamsObj)) {
255 #if PY_MAJOR_VERSION >= 3
256             if (PyDict_Contains(iParamsObj, PyUnicode_FromString("deviceId"))) {
257                 PyObject *value = PyDict_GetItem(iParamsObj, PyUnicode_FromString("deviceId"));
258                 iParams.deviceId = PyLong_AsLong(value);
259             }
260             if (PyDict_Contains(iParamsObj, PyUnicode_FromString("nChannels"))) {
261                 PyObject *value = PyDict_GetItem(iParamsObj, PyUnicode_FromString("nChannels"));
262                 iParams.nChannels = PyLong_AsLong(value);
263             }
264             if (PyDict_Contains(iParamsObj, PyUnicode_FromString("firstChannel"))) {
265                 PyObject *value = PyDict_GetItem(iParamsObj, PyUnicode_FromString("firstChannel"));
266                 iParams.firstChannel = PyLong_AsLong(value);
267             }
268 #else
269             if (PyDict_Contains(iParamsObj, PyString_FromString("deviceId"))) {
270                 PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString("deviceId"));
271                 iParams.deviceId = PyInt_AsLong(value);
272             }
273             if (PyDict_Contains(iParamsObj, PyString_FromString("nChannels"))) {
274                 PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString("nChannels"));
275                 iParams.nChannels = PyInt_AsLong(value);
276             }
277             if (PyDict_Contains(iParamsObj, PyString_FromString("firstChannel"))) {
278                 PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString("firstChannel"));
279                 iParams.firstChannel = PyInt_AsLong(value);
280             }
281 #endif
282         }
283         else {
284             printf("Second argument must be a dictionary. Default values will be used.\n");
285         }
286 
287 
288         if (!PyCallable_Check(pycallback)) {
289             PyErr_SetString(PyExc_TypeError, "Need a callable object!");
290             Py_XINCREF(PyExc_TypeError);
291             return NULL;
292         }
293 
294         // sanity check the callback ?
295 
296 
297         Py_INCREF(pycallback);         /* Add a reference to new callback */
298         self->callback_func = pycallback; /*Remember new callback */
299 
300         // add support for other format
301         self->_format = RTAUDIO_FLOAT32;
302 
303         // add support for other options
304         RtAudio::StreamOptions options;
305         options.flags = RTAUDIO_NONINTERLEAVED;
306 
307         try {
308             if (self->dac->isStreamOpen())
309                 self->dac->closeStream();
310             self->dac->openStream(&oParams, &iParams, self->_format, fs, &bf, &callback, self, &options);
311         }
312         catch ( RtAudioError& error ) {
313             PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
314             Py_INCREF(RtAudioErrorException);
315             return NULL;
316         }
317 
318         self->inputChannels = iParams.nChannels;
319 
320         Py_RETURN_NONE;
321     }
322 
RtAudio_closeStream(PyRtAudio * self,PyObject * args)323     static PyObject* RtAudio_closeStream(PyRtAudio *self, PyObject *args)
324     {
325         printf("RtAudio_closeStream.\n");
326         if (self == NULL || self->dac == NULL) return NULL;
327 
328         try {
329             self->dac->closeStream();
330             Py_CLEAR(self->callback_func);
331         }
332         catch(RtAudioError &error) {
333             PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
334             Py_INCREF(RtAudioErrorException);
335             return NULL;
336         }
337 
338         Py_RETURN_NONE;
339     }
340 
RtAudio_startStream(PyRtAudio * self,PyObject * args)341     static PyObject* RtAudio_startStream(PyRtAudio *self, PyObject *args)
342     {
343         if (self == NULL || self->dac == NULL) return NULL;
344 
345         try {
346             self->dac->startStream();
347         }
348         catch(RtAudioError &error) {
349             PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
350             Py_INCREF(RtAudioErrorException);
351             return NULL;
352         }
353 
354         Py_RETURN_NONE;
355     }
356 
357 
RtAudio_stopStream(PyRtAudio * self,PyObject * args)358     static PyObject* RtAudio_stopStream(PyRtAudio *self, PyObject *args)
359     {
360         printf("RtAudio_stopStream.\n");
361         if (self == NULL || self->dac == NULL) return NULL;
362 
363         try {
364             self->dac->stopStream();
365         }
366         catch(RtAudioError &error) {
367             PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
368             Py_INCREF(RtAudioErrorException);
369             return NULL;
370         }
371 
372         Py_RETURN_NONE;
373     }
374 
RtAudio_abortStream(PyRtAudio * self,PyObject * args)375     static PyObject* RtAudio_abortStream(PyRtAudio *self, PyObject *args)
376     {
377         printf("RtAudio_abortStream.\n");
378         if (self == NULL || self->dac == NULL) return NULL;
379 
380         try {
381             self->dac->abortStream();
382         }
383         catch(RtAudioError &error) {
384             PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
385             Py_INCREF(RtAudioErrorException);
386             return NULL;
387         }
388         Py_RETURN_NONE;
389     }
390 
RtAudio_isStreamRunning(PyRtAudio * self,PyObject * args)391     static PyObject* RtAudio_isStreamRunning(PyRtAudio *self, PyObject *args)
392     {
393        if (self == NULL || self->dac == NULL) return NULL;
394 
395        if (self->dac == NULL) {
396             Py_RETURN_FALSE;
397         }
398         if (self->dac->isStreamRunning())
399             Py_RETURN_TRUE;
400         else
401             Py_RETURN_FALSE;
402     }
403 
RtAudio_isStreamOpen(PyRtAudio * self,PyObject * args)404     static PyObject* RtAudio_isStreamOpen(PyRtAudio *self, PyObject *args)
405     {
406         if (self == NULL || self->dac == NULL) return NULL;
407 
408         if (self->dac == NULL) {
409             Py_RETURN_FALSE;
410         }
411         if (self->dac->isStreamOpen())
412             Py_RETURN_TRUE;
413         else
414             Py_RETURN_FALSE;
415 
416     }
417 
RtAudio_getDeviceCount(PyRtAudio * self,PyObject * args)418     static PyObject* RtAudio_getDeviceCount(PyRtAudio *self, PyObject *args)
419     {
420         if (self == NULL || self->dac == NULL) return NULL;
421 
422 #if PY_MAJOR_VERSION >= 3
423         return PyLong_FromLong(self->dac->getDeviceCount());
424 #else
425         return PyInt_FromLong(self->dac->getDeviceCount());
426 #endif
427     }
428 
RtAudio_getDeviceInfo(PyRtAudio * self,PyObject * args)429     static PyObject* RtAudio_getDeviceInfo(PyRtAudio *self, PyObject *args)
430     {
431         if (self == NULL || self->dac == NULL) return NULL;
432 
433         int device;
434         if (!PyArg_ParseTuple(args, "i", &device))
435             return NULL;
436 
437         try {
438             RtAudio::DeviceInfo info = self->dac->getDeviceInfo(device);
439 
440             PyObject* info_dict = PyDict_New();
441 
442             if (info.probed) {
443                 Py_INCREF(Py_True);
444                 PyDict_SetItemString(info_dict, "probed", Py_True);
445             }
446             else {
447                 Py_INCREF(Py_False);
448                 PyDict_SetItemString(info_dict, "probed", Py_False);
449             }
450             PyObject* obj;
451 
452 #if PY_MAJOR_VERSION >= 3
453             obj = PyUnicode_FromString(info.name.c_str());
454             PyDict_SetItemString(info_dict, "name", obj);
455 
456             obj = PyLong_FromLong(info.outputChannels);
457             PyDict_SetItemString(info_dict, "outputChannels", obj);
458 
459             obj = PyLong_FromLong(info.inputChannels);
460             PyDict_SetItemString(info_dict, "inputChannels", obj);
461 
462             obj = PyLong_FromLong(info.duplexChannels);
463             PyDict_SetItemString(info_dict, "duplexChannels", obj);
464 #else
465             obj = PyString_FromString(info.name.c_str());
466             PyDict_SetItemString(info_dict, "name", obj);
467 
468             obj = PyInt_FromLong(info.outputChannels);
469             PyDict_SetItemString(info_dict, "outputChannels", obj);
470 
471             obj = PyInt_FromLong(info.inputChannels);
472             PyDict_SetItemString(info_dict, "inputChannels", obj);
473 
474             obj = PyInt_FromLong(info.duplexChannels);
475             PyDict_SetItemString(info_dict, "duplexChannels", obj);
476 #endif
477 
478             if (info.isDefaultOutput) {
479                 Py_INCREF(Py_True);
480                 PyDict_SetItemString(info_dict, "isDefaultOutput", Py_True);
481             }
482             else {
483                 Py_INCREF(Py_False);
484                 PyDict_SetItemString(info_dict, "isDefaultOutput", Py_False);
485             }
486 
487             if (info.isDefaultInput) {
488                 Py_INCREF(Py_True);
489                 PyDict_SetItemString(info_dict, "isDefaultInput", Py_True);
490             }
491             else {
492                 Py_INCREF(Py_False);
493                 PyDict_SetItemString(info_dict, "isDefaultInput", Py_False);
494             }
495 
496             return info_dict;
497 
498         }
499         catch(RtAudioError &error) {
500             PyErr_SetString(RtAudioErrorException, error.getMessage().c_str());
501             Py_INCREF(RtAudioErrorException);
502             return NULL;
503         }
504     }
505 
RtAudio_getDefaultOutputDevice(PyRtAudio * self,PyObject * args)506     static PyObject* RtAudio_getDefaultOutputDevice(PyRtAudio *self, PyObject *args)
507     {
508         if (self == NULL || self->dac == NULL) return NULL;
509 #if PY_MAJOR_VERSION >= 3
510         return PyLong_FromLong(self->dac->getDefaultOutputDevice());
511 #else
512         return PyInt_FromLong(self->dac->getDefaultOutputDevice());
513 #endif
514     }
515 
RtAudio_getDefaultInputDevice(PyRtAudio * self,PyObject * args)516     static PyObject* RtAudio_getDefaultInputDevice(PyRtAudio *self, PyObject *args)
517     {
518         if (self == NULL || self->dac == NULL) return NULL;
519 #if PY_MAJOR_VERSION >= 3
520         return PyLong_FromLong(self->dac->getDefaultInputDevice());
521 #else
522         return PyInt_FromLong(self->dac->getDefaultInputDevice());
523 #endif
524     }
525 
RtAudio_getStreamTime(PyRtAudio * self,PyObject * args)526     static PyObject* RtAudio_getStreamTime(PyRtAudio *self, PyObject *args)
527     {
528         if (self == NULL || self->dac == NULL) return NULL;
529         return PyFloat_FromDouble( self->dac->getStreamTime() );
530     }
531 
RtAudio_getStreamLatency(PyRtAudio * self,PyObject * args)532     static PyObject* RtAudio_getStreamLatency(PyRtAudio *self, PyObject *args)
533     {
534         if (self == NULL || self->dac == NULL) return NULL;
535 #if PY_MAJOR_VERSION >= 3
536         return PyLong_FromLong( self->dac->getStreamLatency() );
537 #else
538         return PyInt_FromLong( self->dac->getStreamLatency() );
539 #endif
540     }
541 
RtAudio_getStreamSampleRate(PyRtAudio * self,PyObject * args)542     static PyObject* RtAudio_getStreamSampleRate(PyRtAudio *self, PyObject *args)
543     {
544         if (self == NULL || self->dac == NULL) return NULL;
545 #if PY_MAJOR_VERSION >= 3
546         return PyLong_FromLong( self->dac->getStreamSampleRate() );
547 #else
548         return PyInt_FromLong( self->dac->getStreamSampleRate() );
549 #endif
550     }
551 
RtAudio_showWarnings(PyRtAudio * self,PyObject * args)552     static PyObject* RtAudio_showWarnings(PyRtAudio *self, PyObject *args)
553     {
554         if (self == NULL || self->dac == NULL) return NULL;
555 
556         PyObject *obj;
557         if (!PyArg_ParseTuple(args, "O", &obj))
558             return NULL;
559 
560         if (!PyBool_Check(obj))
561             return NULL;
562 
563         if (obj == Py_True)
564             self->dac->showWarnings(true);
565         else if (obj == Py_False)
566             self->dac->showWarnings(false);
567         else {
568             printf("not true nor false\n");
569         }
570         Py_RETURN_NONE;
571     }
572 
573 
574     static PyMethodDef RtAudio_methods[] =
575     {
576         // TO BE DONE: getCurrentApi(void)
577         {"getDeviceCount", (PyCFunction) RtAudio_getDeviceCount, METH_NOARGS,
578         "A public function that queries for the number of audio devices available."},
579         {"getDeviceInfo", (PyCFunction) RtAudio_getDeviceInfo, METH_VARARGS,
580         "Return a dictionary with information for a specified device number."},
581         {"getDefaultOutputDevice", (PyCFunction) RtAudio_getDefaultOutputDevice, METH_NOARGS,
582         "A function that returns the index of the default output device."},
583         {"getDefaultInputDevice", (PyCFunction) RtAudio_getDefaultInputDevice, METH_NOARGS,
584         "A function that returns the index of the default input device."},
585         {"openStream", (PyCFunction) RtAudio_openStream, METH_VARARGS,
586         "A public method for opening a stream with the specified parameters."},
587         {"closeStream", (PyCFunction) RtAudio_closeStream, METH_NOARGS,
588         "A function that closes a stream and frees any associated stream memory. "},
589         {"startStream", (PyCFunction) RtAudio_startStream, METH_NOARGS,
590         "A function that starts a stream. "},
591         {"stopStream", (PyCFunction) RtAudio_stopStream, METH_NOARGS,
592         "Stop a stream, allowing any samples remaining in the output queue to be played. "},
593         {"abortStream", (PyCFunction) RtAudio_abortStream, METH_NOARGS,
594         "Stop a stream, discarding any samples remaining in the input/output queue."},
595         {"isStreamOpen", (PyCFunction) RtAudio_isStreamOpen, METH_NOARGS,
596         "Returns true if a stream is open and false if not."},
597         {"isStreamRunning", (PyCFunction) RtAudio_isStreamRunning, METH_NOARGS,
598         "Returns true if the stream is running and false if it is stopped or not open."},
599         {"getStreamTime", (PyCFunction) RtAudio_getStreamTime, METH_NOARGS,
600         "Returns the number of elapsed seconds since the stream was started."},
601         {"getStreamLatency", (PyCFunction) RtAudio_getStreamLatency, METH_NOARGS,
602         "Returns the internal stream latency in sample frames."},
603         {"getStreamSampleRate", (PyCFunction) RtAudio_getStreamSampleRate, METH_NOARGS,
604         "Returns actual sample rate in use by the stream."},
605         {"showWarnings", (PyCFunction) RtAudio_showWarnings, METH_VARARGS,
606         "Specify whether warning messages should be printed to stderr."},
607         // TO BE DONE: getCompiledApi (std::vector< RtAudio::Api > &apis) throw ()
608         {NULL}
609     };
610 
611     static PyTypeObject RtAudio_type = {
612         PyVarObject_HEAD_INIT(NULL, 0)
613         "rtaudio.RtAudio",             /*tp_name*/
614         sizeof(RtAudio), /*tp_basicsize*/
615         0,                         /*tp_itemsize*/
616         (destructor) RtAudio_dealloc,                         /*tp_dealloc*/
617         0,                         /*tp_print*/
618         0,                         /*tp_getattr*/
619         0,                         /*tp_setattr*/
620         0,                         /*tp_compare*/
621         0,                         /*tp_repr*/
622         0,                         /*tp_as_number*/
623         0,                         /*tp_as_sequence*/
624         0,                         /*tp_as_mapping*/
625         0,                         /*tp_hash */
626         0,                         /*tp_call*/
627         0,                         /*tp_str*/
628         0,                         /*tp_getattro*/
629         0,                         /*tp_setattro*/
630         0,                         /*tp_as_buffer*/
631         Py_TPFLAGS_DEFAULT,        /*tp_flags*/
632         "Audio input device",           /* tp_doc */
633         0,               /* tp_traverse */
634         0,               /* tp_clear */
635         0,               /* tp_richcompare */
636         0,               /* tp_weaklistoffset */
637         0,               /* tp_iter */
638         0,               /* tp_iternext */
639         RtAudio_methods,             /* tp_methods */
640         0,              /* tp_members */
641         0,                         /* tp_getset */
642         0,                         /* tp_base */
643         0,                         /* tp_dict */
644         0,                         /* tp_descr_get */
645         0,                         /* tp_descr_set */
646         0,                         /* tp_dictoffset */
647         (initproc)RtAudio_init,      /* tp_init */
648         0,                         /* tp_alloc */
649         RtAudio_new,                 /* tp_new */
650         0, /* Low-level free-memory routine */
651 	    0, /* For PyObject_IS_GC */
652 	    0, // PyObject *tp_bases;
653 	    0, // PyObject *tp_mro; /* method resolution order */
654 	    0, //PyObject *tp_cache;
655 	    0, //PyObject *tp_subclasses;
656 	    0, //PyObject *tp_weaklist;
657 	    0, //destructor tp_del;
658         //0,	/* Type attribute cache version tag. Added in version 2.6 */
659     };
660 
661 #if PY_MAJOR_VERSION >= 3
662     static PyModuleDef RtAudio_module = {
663         PyModuleDef_HEAD_INIT,
664         "RtAudio",
665         "RtAudio wrapper.",
666     };
667 #endif
668 
669 #ifndef PyMODINIT_FUNC	/* declarations for DLL import/export */
670 #define PyMODINIT_FUNC void
671 #endif
672     PyMODINIT_FUNC
673 #if PY_MAJOR_VERSION >= 3
PyInit_rtaudio(void)674     PyInit_rtaudio(void)
675 #else
676     initrtaudio(void)
677 #endif
678     {
679         if (!PyEval_ThreadsInitialized())
680             PyEval_InitThreads();
681 
682         if (PyType_Ready(&RtAudio_type) < 0)
683 #if PY_MAJOR_VERSION >= 3
684             return NULL;
685 #else
686             return;
687 #endif
688 
689 #if PY_MAJOR_VERSION >= 3
690         PyObject* module = PyModule_Create(&RtAudio_module);
691         if (module == NULL)
692             return NULL;
693 #else
694         PyObject* module = Py_InitModule3("rtaudio", NULL, "RtAudio wrapper.");
695         if (module == NULL)
696             return;
697 #endif
698 
699         Py_INCREF(&RtAudio_type);
700         PyModule_AddObject(module, "RtAudio", (PyObject *)&RtAudio_type);
701 
702         RtAudioErrorException = PyErr_NewException("rtaudio.RtError", NULL, NULL);
703         Py_INCREF(RtAudioErrorException);
704         PyModule_AddObject(module, "RtError", RtAudioErrorException);
705 #if PY_MAJOR_VERSION >= 3
706         return module;
707 #else
708         return;
709 #endif
710     }
711 }
712