diff options
| author | Gary Scavone <gary@music.mcgill.ca> | 2011-04-13 00:50:38 +0000 |
|---|---|---|
| committer | Stephen Sinclair <sinclair@music.mcgill.ca> | 2013-10-11 01:38:27 +0200 |
| commit | 6faf4336eb5952b141e1c239d194f5cd70f0a885 (patch) | |
| tree | 0138f26b95005b27ecc888e0c2dacf5f7ffe09b5 /contrib/python | |
| parent | 24a98a1971301e582dc56ef2c6ac94c342b674dd (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.py | 70 | ||||
| -rw-r--r-- | contrib/python/pyrtaudio/readme | 57 | ||||
| -rw-r--r-- | contrib/python/pyrtaudio/rtaudiomodule.cpp | 605 | ||||
| -rw-r--r-- | contrib/python/pyrtaudio/setup.py | 58 |
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]) + |
