summaryrefslogtreecommitdiff
path: root/contrib/python
diff options
context:
space:
mode:
authorGary Scavone <gary@music.mcgill.ca>2011-04-13 00:50:38 +0000
committerStephen Sinclair <sinclair@music.mcgill.ca>2013-10-11 01:38:27 +0200
commit6faf4336eb5952b141e1c239d194f5cd70f0a885 (patch)
tree0138f26b95005b27ecc888e0c2dacf5f7ffe09b5 /contrib/python
parent24a98a1971301e582dc56ef2c6ac94c342b674dd (diff)
Updates for release 4.0.8, including new python binding, new teststops.cpp program, ALSA "default" flag, and various changes to stopping behavior (GS).
Diffstat (limited to 'contrib/python')
-rw-r--r--contrib/python/pyrtaudio/PyRtAudioTest.py70
-rw-r--r--contrib/python/pyrtaudio/readme57
-rw-r--r--contrib/python/pyrtaudio/rtaudiomodule.cpp605
-rw-r--r--contrib/python/pyrtaudio/setup.py58
4 files changed, 790 insertions, 0 deletions
diff --git a/contrib/python/pyrtaudio/PyRtAudioTest.py b/contrib/python/pyrtaudio/PyRtAudioTest.py
new file mode 100644
index 0000000..1966ce5
--- /dev/null
+++ b/contrib/python/pyrtaudio/PyRtAudioTest.py
@@ -0,0 +1,70 @@
+
+import rtaudio as rt
+
+from math import cos
+
+import struct
+
+
+class audio_generator:
+ def __init__(self):
+ self.idx = -1
+ self.freq = 440.
+ def __call__(self):
+ self.idx += 1
+ if self.idx%48000 == 0:
+ self.freq *= 2**(1/12.)
+ return 0.5*cos(2.*3.1416*self.freq*self.idx/48000.)
+
+
+class callback:
+ def __init__(self, gen):
+ self.gen = gen
+ self.i = 0
+ def __call__(self,playback, capture):
+ [struct.pack_into("f", playback, 4*o, self.gen()) for o in xrange(256)]
+ self.i = self.i + 256
+ if self.i > 48000*10:
+ print '.'
+ return 1
+
+dac = rt.RtAudio()
+
+n = dac.getDeviceCount()
+print 'Number of devices available: ', n
+
+for i in range(n):
+ try:
+ print dac.getDeviceInfo(i)
+ except rt.RtError as e:
+ print e
+
+
+print 'Default output device: ', dac.getDefaultOutputDevice()
+print 'Default input device: ', dac.getDefaultInputDevice()
+
+print 'is stream open: ', dac.isStreamOpen()
+print 'is stream running: ', dac.isStreamRunning()
+
+oParams = {'deviceId': 1, 'nChannels': 1, 'firstChannel': 0}
+iParams = {'deviceId': 1, 'nChannels': 1, 'firstChannel': 0}
+
+try:
+ dac.openStream(oParams,oParams,48000,256,callback(audio_generator()) )
+except rt.RtError as e:
+ print e
+else:
+ dac.startStream()
+
+ import time
+ print 'latency: ', dac.getStreamLatency()
+
+ while (dac.isStreamRunning()):
+ time.sleep(0.1)
+
+ print dac.getStreamTime()
+
+ dac.stopStream()
+ dac.abortStream()
+ dac.closeStream()
+
diff --git a/contrib/python/pyrtaudio/readme b/contrib/python/pyrtaudio/readme
new file mode 100644
index 0000000..56b868c
--- /dev/null
+++ b/contrib/python/pyrtaudio/readme
@@ -0,0 +1,57 @@
+PyRtAudio - a python wrapper around RtAudio that allows to perform audio i/o operations in real-time from the python language.
+
+By Antoine Lefebvre, 2011
+
+This software is in the development stage. Do not expect compatibility
+with future versions. Comments, suggestions, new features, bug fixes,
+etc. are welcome.
+
+
+This distribution of PyRtAudio contains the following:
+
+- rtaudiomodule.cpp: the python wrapper code
+- setup.py: a setup script use to compile and install PyRtAudio
+- examples: a single PyRtAudioTest.py script
+
+INSTALLATION
+
+The compilation and installation of the PyRtAudio module is handled by
+the python Distribution Utilities ("Distutils"). Provided that your
+system has a C++ compiler and is properly configure, the following
+command should be sufficient:
+
+>> python setup.py install
+
+Please refer to the distutils documentation for installation problems: http://docs.python.org/distutils/index.html
+
+LEGAL AND ETHICAL:
+
+The PyRtAudio license is the same as the RtAudio license:
+
+ PyRtAudio: a python wrapper around RtAudio
+ Copyright (c)2011 Antoine Lefebvre
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ asked to send the modifications to the original developer so that
+ they can be incorporated into the canonical version. This is,
+ however, not a binding provision of this license.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/contrib/python/pyrtaudio/rtaudiomodule.cpp b/contrib/python/pyrtaudio/rtaudiomodule.cpp
new file mode 100644
index 0000000..40a87e5
--- /dev/null
+++ b/contrib/python/pyrtaudio/rtaudiomodule.cpp
@@ -0,0 +1,605 @@
+/************************************************************************/
+/* PyRtAudio: a python wrapper around RtAudio
+ Copyright (c) 2011 Antoine Lefebvre
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ Any person wishing to distribute modifications to the Software is
+ asked to send the modifications to the original developer so that
+ they can be incorporated into the canonical version. This is,
+ however, not a binding provision of this license.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+/************************************************************************/
+
+// This software is in the development stage
+// Do not expect compatibility with future versions.
+// Comments, suggestions, new features, bug fixes, etc. are welcome
+
+#include <Python.h>
+
+#include "RtAudio.h"
+
+extern "C" {
+
+ typedef struct
+ {
+ PyObject_HEAD;
+ RtAudio *dac;
+ RtAudioFormat _format;
+ int _bufferSize;
+ unsigned int inputChannels;
+ PyObject *callback_func;
+ } PyRtAudio;
+
+ static PyObject *RtAudioError;
+
+ static int callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
+ double streamTime, RtAudioStreamStatus status, void *data )
+ {
+ PyRtAudio* self = (PyRtAudio*) data;
+
+ if (status == RTAUDIO_OUTPUT_UNDERFLOW)
+ printf("underflow.\n");
+
+ if (self == NULL) return -1;
+
+ float* in = (float *) inputBuffer;
+ float* out = (float *) outputBuffer;
+
+ PyObject *py_callback_func = self->callback_func;
+
+ int retval = 0;
+
+ if (py_callback_func) {
+ PyGILState_STATE gstate = PyGILState_Ensure();
+
+ PyObject* iBuffer = PyBuffer_FromMemory(in, sizeof(float) * self->inputChannels * nBufferFrames);
+ PyObject* oBuffer = PyBuffer_FromReadWriteMemory(out, sizeof(float) * nBufferFrames);
+ PyObject *arglist = Py_BuildValue("(O,O)", oBuffer, iBuffer);
+
+ if (arglist == NULL) {
+ printf("error.\n");
+ PyErr_Print();
+ PyGILState_Release(gstate);
+ return 2;
+ }
+
+ // Calling the callback
+ PyObject *result = PyEval_CallObject(py_callback_func, arglist);
+
+ if (PyErr_Occurred() != NULL) {
+ PyErr_Print();
+ }
+ else if PyInt_Check(result) {
+ retval = PyInt_AsLong(result);
+ }
+
+ Py_DECREF(arglist);
+ Py_DECREF(oBuffer);
+ Py_DECREF(iBuffer);
+ Py_XDECREF(result);
+
+ PyGILState_Release(gstate);
+ }
+
+ return retval;
+ }
+
+
+
+ static void RtAudio_dealloc(PyRtAudio *self)
+ {
+ printf("RtAudio_dealloc.\n");
+ if (self == NULL) return;
+
+ if (self->dac) {
+ self->dac->closeStream();
+ Py_CLEAR(self->callback_func);
+ delete self->dac;
+ }
+
+ self->ob_type->tp_free((PyObject *) self);
+ }
+
+
+ static PyObject* RtAudio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+ printf("RtAudio_new.\n");
+ PyRtAudio *self;
+ char *api = NULL;
+
+ if(!PyArg_ParseTuple(args, "|s", &api))
+ return NULL;
+
+ self = (PyRtAudio *) type->tp_alloc(type, 0);
+
+ if(self == NULL) return NULL;
+
+ self->dac = NULL;
+ self->callback_func = NULL;
+
+ try {
+ if (api == NULL)
+ self->dac = new RtAudio;
+ else if(!strcmp(api, "jack"))
+ self->dac = new RtAudio(RtAudio::UNIX_JACK);
+ else if(!strcmp(api, "alsa"))
+ self->dac = new RtAudio(RtAudio::LINUX_ALSA);
+ else if(!strcmp(api, "oss"))
+ self->dac = new RtAudio(RtAudio::LINUX_ALSA);
+ else if(!strcmp(api, "core"))
+ self->dac = new RtAudio(RtAudio::MACOSX_CORE);
+ else if(!strcmp(api, "asio"))
+ self->dac = new RtAudio(RtAudio::WINDOWS_ASIO);
+ else if(!strcmp(api, "directsound"))
+ self->dac = new RtAudio(RtAudio::WINDOWS_DS);
+ }
+ catch (RtError &error) {
+ PyErr_SetString(RtAudioError, error.getMessage().c_str());
+ Py_INCREF(RtAudioError);
+ return NULL;
+ }
+
+ self->dac->showWarnings(false);
+
+ //Py_XINCREF(self);
+ return (PyObject *) self;
+ }
+
+ static int RtAudio_init(PyRtAudio *self, PyObject *args, PyObject *kwds)
+ {
+ printf("RtAudio_init.\n");
+ //if (self == NULL) return 0;
+ return 0;
+ }
+
+ // This functions does not yet support all the features of the RtAudio::openStream method.
+ // Please send your patches if you improves this.
+ static PyObject* RtAudio_openStream(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL) return NULL;
+
+ if (self->dac == NULL) {
+ printf("the dac is null.\n");
+ Py_RETURN_NONE;
+ }
+
+ PyObject *oParamsObj;
+ PyObject *iParamsObj;
+ int fs;
+ unsigned int bf;
+ PyObject *pycallback;
+
+ if (!PyArg_ParseTuple(args, "OOiiO", &oParamsObj, &iParamsObj, &fs, &bf, &pycallback))
+ return NULL;
+
+ RtAudio::StreamParameters oParams;
+ oParams.deviceId = 1;
+ oParams.nChannels = 1;
+ oParams.firstChannel = 0;
+
+ if (PyDict_Check(oParamsObj)) {
+ if (PyDict_Contains(oParamsObj, PyString_FromString("deviceId"))) {
+ PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString("deviceId"));
+ oParams.deviceId = PyInt_AsLong(value);
+ }
+ if (PyDict_Contains(oParamsObj, PyString_FromString("nChannels"))) {
+ PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString("nChannels"));
+ oParams.nChannels = PyInt_AsLong(value);
+ }
+ if (PyDict_Contains(oParamsObj, PyString_FromString("firstChannel"))) {
+ PyObject *value = PyDict_GetItem(oParamsObj, PyString_FromString("firstChannel"));
+ oParams.firstChannel = PyInt_AsLong(value);
+ }
+ }
+ else {
+ printf("First argument must be a dictionary. Default values will be used.\n");
+ }
+
+ RtAudio::StreamParameters iParams;
+ iParams.deviceId = 1;
+ iParams.nChannels = 2;
+ iParams.firstChannel = 0;
+
+ if (PyDict_Check(iParamsObj)) {
+ if (PyDict_Contains(iParamsObj, PyString_FromString("deviceId"))) {
+ PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString("deviceId"));
+ iParams.deviceId = PyInt_AsLong(value);
+ }
+ if (PyDict_Contains(iParamsObj, PyString_FromString("nChannels"))) {
+ PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString("nChannels"));
+ iParams.nChannels = PyInt_AsLong(value);
+ }
+ if (PyDict_Contains(iParamsObj, PyString_FromString("firstChannel"))) {
+ PyObject *value = PyDict_GetItem(iParamsObj, PyString_FromString("firstChannel"));
+ iParams.firstChannel = PyInt_AsLong(value);
+ }
+ }
+ else {
+ printf("Second argument must be a dictionary. Default values will be used.\n");
+ }
+
+
+ if (!PyCallable_Check(pycallback)) {
+ PyErr_SetString(PyExc_TypeError, "Need a callable object!");
+ Py_XINCREF(PyExc_TypeError);
+ return NULL;
+ }
+
+ // sanity check the callback ?
+
+
+ Py_INCREF(pycallback); /* Add a reference to new callback */
+ self->callback_func = pycallback; /*Remember new callback */
+
+ // add support for other format
+ self->_format = RTAUDIO_FLOAT32;
+
+ // add support for other options
+ RtAudio::StreamOptions options;
+ options.flags = RTAUDIO_NONINTERLEAVED;
+
+ try {
+ if (self->dac->isStreamOpen())
+ self->dac->closeStream();
+ self->dac->openStream(&oParams, &iParams, self->_format, fs, &bf, &callback, self, &options);
+ }
+ catch ( RtError& error ) {
+ PyErr_SetString(RtAudioError, error.getMessage().c_str());
+ Py_INCREF(RtAudioError);
+ return NULL;
+ }
+
+ self->inputChannels = iParams.nChannels;
+
+ Py_RETURN_NONE;
+ }
+
+ static PyObject* RtAudio_closeStream(PyRtAudio *self, PyObject *args)
+ {
+ printf("RtAudio_closeStream.\n");
+ if (self == NULL || self->dac == NULL) return NULL;
+
+ try {
+ self->dac->closeStream();
+ Py_CLEAR(self->callback_func);
+ }
+ catch(RtError &error) {
+ PyErr_SetString(RtAudioError, error.getMessage().c_str());
+ Py_INCREF(RtAudioError);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+ }
+
+ static PyObject* RtAudio_startStream(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL || self->dac == NULL) return NULL;
+
+ try {
+ self->dac->startStream();
+ }
+ catch(RtError &error) {
+ PyErr_SetString(RtAudioError, error.getMessage().c_str());
+ Py_INCREF(RtAudioError);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+ }
+
+
+ static PyObject* RtAudio_stopStream(PyRtAudio *self, PyObject *args)
+ {
+ printf("RtAudio_stopStream.\n");
+ if (self == NULL || self->dac == NULL) return NULL;
+
+ try {
+ self->dac->stopStream();
+ }
+ catch(RtError &error) {
+ PyErr_SetString(RtAudioError, error.getMessage().c_str());
+ Py_INCREF(RtAudioError);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+ }
+
+ static PyObject* RtAudio_abortStream(PyRtAudio *self, PyObject *args)
+ {
+ printf("RtAudio_abortStream.\n");
+ if (self == NULL || self->dac == NULL) return NULL;
+
+ try {
+ self->dac->abortStream();
+ }
+ catch(RtError &error) {
+ PyErr_SetString(RtAudioError, error.getMessage().c_str());
+ Py_INCREF(RtAudioError);
+ return NULL;
+ }
+ Py_RETURN_NONE;
+ }
+
+ static PyObject* RtAudio_isStreamRunning(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL || self->dac == NULL) return NULL;
+
+ if (self->dac == NULL) {
+ Py_RETURN_FALSE;
+ }
+ if (self->dac->isStreamRunning())
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+ }
+
+ static PyObject* RtAudio_isStreamOpen(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL || self->dac == NULL) return NULL;
+
+ if (self->dac == NULL) {
+ Py_RETURN_FALSE;
+ }
+ if (self->dac->isStreamOpen())
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+
+ }
+
+ static PyObject* RtAudio_getDeviceCount(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL || self->dac == NULL) return NULL;
+
+ return PyInt_FromLong(self->dac->getDeviceCount());
+ }
+
+ static PyObject* RtAudio_getDeviceInfo(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL || self->dac == NULL) return NULL;
+
+ int device;
+ if (!PyArg_ParseTuple(args, "i", &device))
+ return NULL;
+
+ try {
+ RtAudio::DeviceInfo info = self->dac->getDeviceInfo(device);
+
+ PyObject* info_dict = PyDict_New();
+
+ if (info.probed) {
+ Py_INCREF(Py_True);
+ PyDict_SetItemString(info_dict, "probed", Py_True);
+ }
+ else {
+ Py_INCREF(Py_False);
+ PyDict_SetItemString(info_dict, "probed", Py_False);
+ }
+ PyObject* obj;
+
+ obj = PyString_FromString(info.name.c_str());
+ PyDict_SetItemString(info_dict, "name", obj);
+
+ obj = PyInt_FromLong(info.outputChannels);
+ PyDict_SetItemString(info_dict, "outputChannels", obj);
+
+ obj = PyInt_FromLong(info.inputChannels);
+ PyDict_SetItemString(info_dict, "inputChannels", obj);
+
+ obj = PyInt_FromLong(info.duplexChannels);
+ PyDict_SetItemString(info_dict, "duplexChannels", obj);
+
+ if (info.isDefaultOutput) {
+ Py_INCREF(Py_True);
+ PyDict_SetItemString(info_dict, "isDefaultOutput", Py_True);
+ }
+ else {
+ Py_INCREF(Py_False);
+ PyDict_SetItemString(info_dict, "isDefaultOutput", Py_False);
+ }
+
+ if (info.isDefaultInput) {
+ Py_INCREF(Py_True);
+ PyDict_SetItemString(info_dict, "isDefaultInput", Py_True);
+ }
+ else {
+ Py_INCREF(Py_False);
+ PyDict_SetItemString(info_dict, "isDefaultInput", Py_False);
+ }
+
+ return info_dict;
+
+ }
+ catch(RtError &error) {
+ PyErr_SetString(RtAudioError, error.getMessage().c_str());
+ Py_INCREF(RtAudioError);
+ return NULL;
+ }
+ }
+
+ static PyObject* RtAudio_getDefaultOutputDevice(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL || self->dac == NULL) return NULL;
+ return PyInt_FromLong(self->dac->getDefaultOutputDevice());
+ }
+
+ static PyObject* RtAudio_getDefaultInputDevice(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL || self->dac == NULL) return NULL;
+ return PyInt_FromLong(self->dac->getDefaultInputDevice());
+ }
+
+ static PyObject* RtAudio_getStreamTime(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL || self->dac == NULL) return NULL;
+ return PyFloat_FromDouble( self->dac->getStreamTime() );
+ }
+
+ static PyObject* RtAudio_getStreamLatency(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL || self->dac == NULL) return NULL;
+ return PyInt_FromLong( self->dac->getStreamLatency() );
+ }
+
+ static PyObject* RtAudio_getStreamSampleRate(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL || self->dac == NULL) return NULL;
+ return PyInt_FromLong( self->dac->getStreamSampleRate() );
+ }
+
+ static PyObject* RtAudio_showWarnings(PyRtAudio *self, PyObject *args)
+ {
+ if (self == NULL || self->dac == NULL) return NULL;
+
+ PyObject *obj;
+ if (!PyArg_ParseTuple(args, "O", &obj))
+ return NULL;
+
+ if (!PyBool_Check(obj))
+ return NULL;
+
+ if (obj == Py_True)
+ self->dac->showWarnings(true);
+ else if (obj == Py_False)
+ self->dac->showWarnings(false);
+ else {
+ printf("not true nor false\n");
+ }
+ Py_RETURN_NONE;
+ }
+
+
+ static PyMethodDef RtAudio_methods[] =
+ {
+ // TO BE DONE: getCurrentApi(void)
+ {"getDeviceCount", (PyCFunction) RtAudio_getDeviceCount, METH_NOARGS,
+ "A public function that queries for the number of audio devices available."},
+ {"getDeviceInfo", (PyCFunction) RtAudio_getDeviceInfo, METH_VARARGS,
+ "Return a dictionary with information for a specified device number."},
+ {"getDefaultOutputDevice", (PyCFunction) RtAudio_getDefaultOutputDevice, METH_NOARGS,
+ "A function that returns the index of the default output device."},
+ {"getDefaultInputDevice", (PyCFunction) RtAudio_getDefaultInputDevice, METH_NOARGS,
+ "A function that returns the index of the default input device."},
+ {"openStream", (PyCFunction) RtAudio_openStream, METH_VARARGS,
+ "A public method for opening a stream with the specified parameters."},
+ {"closeStream", (PyCFunction) RtAudio_closeStream, METH_NOARGS,
+ "A function that closes a stream and frees any associated stream memory. "},
+ {"startStream", (PyCFunction) RtAudio_startStream, METH_NOARGS,
+ "A function that starts a stream. "},
+ {"stopStream", (PyCFunction) RtAudio_stopStream, METH_NOARGS,
+ "Stop a stream, allowing any samples remaining in the output queue to be played. "},
+ {"abortStream", (PyCFunction) RtAudio_abortStream, METH_NOARGS,
+ "Stop a stream, discarding any samples remaining in the input/output queue."},
+ {"isStreamOpen", (PyCFunction) RtAudio_isStreamOpen, METH_NOARGS,
+ "Returns true if a stream is open and false if not."},
+ {"isStreamRunning", (PyCFunction) RtAudio_isStreamRunning, METH_NOARGS,
+ "Returns true if the stream is running and false if it is stopped or not open."},
+ {"getStreamTime", (PyCFunction) RtAudio_getStreamTime, METH_NOARGS,
+ "Returns the number of elapsed seconds since the stream was started."},
+ {"getStreamLatency", (PyCFunction) RtAudio_getStreamLatency, METH_NOARGS,
+ "Returns the internal stream latency in sample frames."},
+ {"getStreamSampleRate", (PyCFunction) RtAudio_getStreamSampleRate, METH_NOARGS,
+ "Returns actual sample rate in use by the stream."},
+ {"showWarnings", (PyCFunction) RtAudio_showWarnings, METH_VARARGS,
+ "Specify whether warning messages should be printed to stderr."},
+ // TO BE DONE: getCompiledApi (std::vector< RtAudio::Api > &apis) throw ()
+ {NULL}
+ };
+
+
+ static PyTypeObject RtAudio_type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "rtaudio.RtAudio", /*tp_name*/
+ sizeof(RtAudio), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ (destructor) RtAudio_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ "Audio input device", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ RtAudio_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)RtAudio_init, /* tp_init */
+ 0, /* tp_alloc */
+ RtAudio_new, /* tp_new */
+ 0, /* Low-level free-memory routine */
+ 0, /* For PyObject_IS_GC */
+ 0, // PyObject *tp_bases;
+ 0, // PyObject *tp_mro; /* method resolution order */
+ 0, //PyObject *tp_cache;
+ 0, //PyObject *tp_subclasses;
+ 0, //PyObject *tp_weaklist;
+ 0, //destructor tp_del;
+ //0, /* Type attribute cache version tag. Added in version 2.6 */
+ };
+
+
+
+#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
+#define PyMODINIT_FUNC void
+#endif
+ PyMODINIT_FUNC
+ initrtaudio(void)
+ {
+ PyEval_InitThreads();
+
+ if (PyType_Ready(&RtAudio_type) < 0)
+ return;
+
+ PyObject* module = Py_InitModule3("rtaudio", NULL, "RtAudio wrapper.");
+ if (module == NULL)
+ return;
+
+ Py_INCREF(&RtAudio_type);
+ PyModule_AddObject(module, "RtAudio", (PyObject *)&RtAudio_type);
+
+ RtAudioError = PyErr_NewException("rtaudio.RtError", NULL, NULL);
+ Py_INCREF(RtAudioError);
+ PyModule_AddObject(module, "RtError", RtAudioError);
+ }
+}
diff --git a/contrib/python/pyrtaudio/setup.py b/contrib/python/pyrtaudio/setup.py
new file mode 100644
index 0000000..6ad0d4a
--- /dev/null
+++ b/contrib/python/pyrtaudio/setup.py
@@ -0,0 +1,58 @@
+#!/bin/env python
+
+import os
+from distutils.core import setup, Extension
+
+if hasattr(os, 'uname'):
+ OSNAME = os.uname()[0]
+else:
+ OSNAME = 'Windows'
+
+
+define_macros = []
+libraries = []
+extra_link_args = []
+extra_compile_args = ['-I../../../']
+sources = ['rtaudiomodule.cpp', '../../../RtAudio.cpp']
+
+
+if OSNAME == 'Linux':
+ define_macros=[("__LINUX_ALSA__", ''),
+ ('__LINUX_JACK__', ''),
+ ('__LINUX_OSS__', '')]
+ libraries = ['asound', 'jack', 'pthread']
+
+elif OSNAME == 'Darwin':
+ define_macros = [('__MACOSX_CORE__', '')]
+ libraries = ['pthread', 'stdc++']
+ extra_link_args = ['-framework', 'CoreAudio']
+
+elif OSNAME == 'Windows':
+ define_macros = [('__WINDOWS_DS__', None),
+ ('__WINDOWS_ASIO__', None),
+ ('__LITTLE_ENDIAN__',None),
+ ('WIN32',None)]
+ libraries = ['winmm', 'dsound', 'Advapi32','Ole32','User32']
+ sources += ['../../../include/asio.cpp',
+ '../../../include/asiodrivers.cpp',
+ '../../../include/asiolist.cpp',
+ '../../../include/iasiothiscallresolver.cpp']
+ extra_compile_args.append('-I../../../include/')
+ extra_compile_args.append('-EHsc')
+
+
+
+audio = Extension('rtaudio',
+ sources=sources,
+ libraries=libraries,
+ define_macros=define_macros,
+ extra_compile_args = extra_compile_args,
+ extra_link_args = extra_link_args,
+ )
+
+
+setup(name = 'rtaudio',
+ version = '0.1',
+ description = 'Python RtAudio interface',
+ ext_modules = [audio])
+