├── .gitignore ├── MANIFEST.in ├── test ├── play_wave.py ├── wire_callback.py ├── wire_full.py ├── record.py ├── play_wave_callback.py ├── wire_half.py ├── play_wave_macosx_channelmap.py ├── error.py └── system_info.py ├── sphinx ├── index.rst ├── examples.rst └── conf.py ├── Makefile ├── README ├── CHANGELOG ├── INSTALL ├── src ├── _portaudiomodule.h ├── pyaudio.py └── _portaudiomodule.c └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | src/PyAudio.egg-info 3 | build/ 4 | dist/ 5 | docs/ 6 | MANIFEST 7 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include src/*.c src/*.h src/*.py 2 | include Makefile CHANGELOG INSTALL MANIFEST.in 3 | recursive-include test *.py *.c 4 | graft docs 5 | graft sphinx 6 | -------------------------------------------------------------------------------- /test/play_wave.py: -------------------------------------------------------------------------------- 1 | """PyAudio Example: Play a wave file.""" 2 | 3 | import pyaudio 4 | import wave 5 | import sys 6 | 7 | CHUNK = 1024 8 | 9 | if len(sys.argv) < 2: 10 | print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0]) 11 | sys.exit(-1) 12 | 13 | wf = wave.open(sys.argv[1], 'rb') 14 | 15 | # instantiate PyAudio (1) 16 | p = pyaudio.PyAudio() 17 | 18 | # open stream (2) 19 | stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), 20 | channels=wf.getnchannels(), 21 | rate=wf.getframerate(), 22 | output=True) 23 | 24 | # read data 25 | data = wf.readframes(CHUNK) 26 | 27 | # play stream (3) 28 | while data != '': 29 | stream.write(data) 30 | data = wf.readframes(CHUNK) 31 | 32 | # stop stream (4) 33 | stream.stop_stream() 34 | stream.close() 35 | 36 | # close PyAudio (5) 37 | p.terminate() 38 | -------------------------------------------------------------------------------- /test/wire_callback.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyAudio Example: Make a wire between input and output (i.e., record a 3 | few samples and play them back immediately). 4 | 5 | This is the callback (non-blocking) version. 6 | """ 7 | 8 | import pyaudio 9 | import time 10 | import sys 11 | 12 | WIDTH = 2 13 | CHANNELS = 2 14 | RATE = 44100 15 | 16 | if sys.platform == 'darwin': 17 | CHANNELS = 1 18 | 19 | p = pyaudio.PyAudio() 20 | 21 | def callback(in_data, frame_count, time_info, status): 22 | return (in_data, pyaudio.paContinue) 23 | 24 | stream = p.open(format=p.get_format_from_width(WIDTH), 25 | channels=CHANNELS, 26 | rate=RATE, 27 | input=True, 28 | output=True, 29 | stream_callback=callback) 30 | 31 | stream.start_stream() 32 | 33 | while stream.is_active(): 34 | time.sleep(0.1) 35 | 36 | stream.stop_stream() 37 | stream.close() 38 | 39 | p.terminate() 40 | -------------------------------------------------------------------------------- /test/wire_full.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyAudio Example: Make a wire between input and output (i.e., record a 3 | few samples and play them back immediately). 4 | 5 | This is the full duplex version. 6 | """ 7 | 8 | import pyaudio 9 | import sys 10 | 11 | CHUNK = 1024 12 | WIDTH = 2 13 | CHANNELS = 2 14 | RATE = 44100 15 | RECORD_SECONDS = 5 16 | 17 | if sys.platform == 'darwin': 18 | CHANNELS = 1 19 | 20 | p = pyaudio.PyAudio() 21 | 22 | stream = p.open(format=p.get_format_from_width(WIDTH), 23 | channels=CHANNELS, 24 | rate=RATE, 25 | input=True, 26 | output=True, 27 | frames_per_buffer=CHUNK) 28 | 29 | print("* recording") 30 | 31 | for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)): 32 | data = stream.read(CHUNK) 33 | stream.write(data, CHUNK) 34 | 35 | print("* done") 36 | 37 | stream.stop_stream() 38 | stream.close() 39 | 40 | p.terminate() 41 | -------------------------------------------------------------------------------- /sphinx/index.rst: -------------------------------------------------------------------------------- 1 | PyAudio Documentation 2 | ===================== 3 | 4 | .. contents:: 5 | 6 | ------------ 7 | Introduction 8 | ------------ 9 | 10 | .. automodule:: pyaudio 11 | :members: 12 | :special-members: 13 | :exclude-members: PyAudio, Stream, PaMacCoreStreamInfo 14 | 15 | Details 16 | ------- 17 | 18 | ------------- 19 | Class PyAudio 20 | ------------- 21 | 22 | .. autoclass:: pyaudio.PyAudio 23 | :members: 24 | :special-members: 25 | 26 | ------------ 27 | Class Stream 28 | ------------ 29 | 30 | .. autoclass:: pyaudio.Stream 31 | :members: 32 | :special-members: 33 | 34 | ----------------- 35 | Platform Specific 36 | ----------------- 37 | 38 | .. only:: pamac 39 | 40 | Class PaMacCoreStreamInfo 41 | ------------------------- 42 | 43 | .. autoclass:: pyaudio.PaMacCoreStreamInfo 44 | :members: 45 | :special-members: 46 | 47 | 48 | Indices and tables 49 | ================== 50 | 51 | * :ref:`genindex` 52 | * :ref:`search` 53 | -------------------------------------------------------------------------------- /test/record.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyAudio example: Record a few seconds of audio and save to a WAVE 3 | file. 4 | """ 5 | 6 | import pyaudio 7 | import wave 8 | import sys 9 | 10 | CHUNK = 1024 11 | FORMAT = pyaudio.paInt16 12 | CHANNELS = 2 13 | RATE = 44100 14 | RECORD_SECONDS = 5 15 | WAVE_OUTPUT_FILENAME = "output.wav" 16 | 17 | if sys.platform == 'darwin': 18 | CHANNELS = 1 19 | 20 | p = pyaudio.PyAudio() 21 | 22 | stream = p.open(format=FORMAT, 23 | channels=CHANNELS, 24 | rate=RATE, 25 | input=True, 26 | frames_per_buffer=CHUNK) 27 | 28 | print("* recording") 29 | 30 | frames = [] 31 | 32 | for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)): 33 | data = stream.read(CHUNK) 34 | frames.append(data) 35 | 36 | print("* done recording") 37 | 38 | stream.stop_stream() 39 | stream.close() 40 | p.terminate() 41 | 42 | wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb') 43 | wf.setnchannels(CHANNELS) 44 | wf.setsampwidth(p.get_sample_size(FORMAT)) 45 | wf.setframerate(RATE) 46 | wf.writeframes(b''.join(frames)) 47 | wf.close() 48 | -------------------------------------------------------------------------------- /test/play_wave_callback.py: -------------------------------------------------------------------------------- 1 | """PyAudio Example: Play a wave file (callback version).""" 2 | 3 | import pyaudio 4 | import wave 5 | import time 6 | import sys 7 | 8 | if len(sys.argv) < 2: 9 | print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0]) 10 | sys.exit(-1) 11 | 12 | wf = wave.open(sys.argv[1], 'rb') 13 | 14 | # instantiate PyAudio (1) 15 | p = pyaudio.PyAudio() 16 | 17 | # define callback (2) 18 | def callback(in_data, frame_count, time_info, status): 19 | data = wf.readframes(frame_count) 20 | return (data, pyaudio.paContinue) 21 | 22 | # open stream using callback (3) 23 | stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), 24 | channels=wf.getnchannels(), 25 | rate=wf.getframerate(), 26 | output=True, 27 | stream_callback=callback) 28 | 29 | # start the stream (4) 30 | stream.start_stream() 31 | 32 | # wait for stream to finish (5) 33 | while stream.is_active(): 34 | time.sleep(0.1) 35 | 36 | # stop stream (6) 37 | stream.stop_stream() 38 | stream.close() 39 | wf.close() 40 | 41 | # close PyAudio (7) 42 | p.terminate() 43 | -------------------------------------------------------------------------------- /test/wire_half.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyAudio Example: Make a wire between input and output (i.e., record a 3 | few samples and play them back immediately). 4 | 5 | This is the half duplex version. 6 | """ 7 | 8 | import pyaudio 9 | import sys 10 | 11 | CHUNK = 1024 12 | WIDTH = 2 13 | CHANNELS = 2 14 | RATE = 44100 15 | RECORD_SECONDS = 5 16 | 17 | if sys.platform == 'darwin': 18 | CHANNELS = 1 19 | 20 | p = pyaudio.PyAudio() 21 | 22 | # Open input stream using default device: 23 | stream_input = p.open(format=p.get_format_from_width(WIDTH), 24 | channels=CHANNELS, 25 | rate=RATE, 26 | input=True, 27 | frames_per_buffer=CHUNK) 28 | 29 | # Open out stream using default device: 30 | stream_output = p.open(format=p.get_format_from_width(WIDTH), 31 | channels=CHANNELS, 32 | rate=RATE, 33 | output=True, 34 | frames_per_buffer=CHUNK) 35 | 36 | print("* recording") 37 | 38 | for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)): 39 | data = stream_input.read(CHUNK) 40 | stream_output.write(data, CHUNK) 41 | 42 | print("* done") 43 | 44 | stream_input.stop_stream() 45 | stream_output.stop_stream() 46 | stream_input.close() 47 | stream_output.close() 48 | p.terminate() 49 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This is the PyAudio distribution makefile. 2 | 3 | .PHONY: docs clean build 4 | 5 | VERSION := 0.2.8 6 | PYTHON ?= python 7 | BUILD_ARGS ?= 8 | SPHINX ?= sphinx-build 9 | DOCS_OUTPUT=docs/ 10 | PYTHON_BUILD_DIR:=$(shell $(PYTHON) -c "import distutils.util; import sys; print(distutils.util.get_platform() + '-' + sys.version[0:3])") 11 | BUILD_DIR:=lib.$(PYTHON_BUILD_DIR) 12 | BUILD_STAMP:=$(BUILD_DIR)/build 13 | SRCFILES := src/*.c src/*.h src/*.py 14 | EXAMPLES := test/*.py 15 | 16 | what: 17 | @echo "make targets:" 18 | @echo 19 | @echo " tarball : build source tarball" 20 | @echo " docs : generate documentation (requires sphinx)" 21 | @echo " clean : remove build files" 22 | @echo 23 | @echo "To build pyaudio, run:" 24 | @echo 25 | @echo " python setup.py install" 26 | 27 | clean: 28 | @rm -rf build dist MANIFEST $(DOCS_OUTPUT) src/*.pyc 29 | 30 | ###################################################################### 31 | # Documentation 32 | ###################################################################### 33 | 34 | build: build/$(BUILD_STAMP) 35 | 36 | build/$(BUILD_STAMP): $(SRCFILES) 37 | $(PYTHON) setup.py build $(BUILD_ARGS) 38 | touch $@ 39 | 40 | docs: build 41 | PYTHONPATH=build/$(BUILD_DIR) $(SPHINX) -b html sphinx/ $(DOCS_OUTPUT) 42 | 43 | ###################################################################### 44 | # Source Tarball 45 | ###################################################################### 46 | tarball: docs $(SRCFILES) $(EXAMPLES) MANIFEST.in 47 | @$(PYTHON) setup.py sdist 48 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ====================================================================== 2 | PyAudio v0.2.8: Python Bindings for PortAudio. 3 | ====================================================================== 4 | 5 | See: http://people.csail.mit.edu/hubert/pyaudio/ 6 | 7 | PyAudio provides Python bindings for PortAudio v19, the cross-platform 8 | audio I/O library. Using PyAudio, you can easily use Python to play 9 | and record audio on a variety of platforms. 10 | 11 | See INSTALL for compilation hints. 12 | 13 | ====================================================================== 14 | 15 | PyAudio : Python Bindings for PortAudio. 16 | 17 | Copyright (c) 2006-2014 Hubert Pham 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining 20 | a copy of this software and associated documentation files (the 21 | "Software"), to deal in the Software without restriction, including 22 | without limitation the rights to use, copy, modify, merge, publish, 23 | distribute, sublicense, and/or sell copies of the Software, and to 24 | permit persons to whom the Software is furnished to do so, subject to 25 | the following conditions: 26 | 27 | The above copyright notice and this permission notice shall be 28 | included in all copies or substantial portions of the Software. 29 | 30 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 31 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 32 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 33 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 34 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 35 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 36 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 37 | 38 | ====================================================================== 39 | 40 | -------------------------------------------------------------------------------- /test/play_wave_macosx_channelmap.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyAudio Example: Mac OS X-only: Play a wave file with channel maps. 3 | """ 4 | 5 | import pyaudio 6 | import wave 7 | import sys 8 | 9 | chunk = 1024 10 | 11 | PyAudio = pyaudio.PyAudio 12 | 13 | if len(sys.argv) < 2: 14 | print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0]) 15 | sys.exit(-1) 16 | 17 | wf = wave.open(sys.argv[1], 'rb') 18 | 19 | p = PyAudio() 20 | 21 | # standard L-R stereo 22 | # channel_map = (0, 1) 23 | 24 | # reverse: R-L stereo 25 | # channel_map = (1, 0) 26 | 27 | # no audio 28 | # channel_map = (-1, -1) 29 | 30 | # left channel audio --> left speaker; no right channel 31 | # channel_map = (0, -1) 32 | 33 | # right channel audio --> right speaker; no left channel 34 | # channel_map = (-1, 1) 35 | 36 | # left channel audio --> right speaker 37 | # channel_map = (-1, 0) 38 | 39 | # right channel audio --> left speaker 40 | channel_map = (1, -1) 41 | # etc... 42 | 43 | try: 44 | stream_info = pyaudio.PaMacCoreStreamInfo( 45 | flags=pyaudio.PaMacCoreStreamInfo.paMacCorePlayNice, # default 46 | channel_map=channel_map) 47 | except AttributeError: 48 | print("Sorry, couldn't find PaMacCoreStreamInfo. Make sure that " 49 | "you're running on Mac OS X.") 50 | sys.exit(-1) 51 | 52 | print("Stream Info Flags:", stream_info.get_flags()) 53 | print("Stream Info Channel Map:", stream_info.get_channel_map()) 54 | 55 | # open stream 56 | stream = p.open( 57 | format=p.get_format_from_width(wf.getsampwidth()), 58 | channels=wf.getnchannels(), 59 | rate=wf.getframerate(), 60 | output=True, 61 | output_host_api_specific_stream_info=stream_info) 62 | 63 | # read data 64 | data = wf.readframes(chunk) 65 | 66 | # play stream 67 | while data != '': 68 | stream.write(data) 69 | data = wf.readframes(chunk) 70 | 71 | stream.stop_stream() 72 | stream.close() 73 | 74 | p.terminate() 75 | -------------------------------------------------------------------------------- /sphinx/examples.rst: -------------------------------------------------------------------------------- 1 | Example: Blocking Mode Audio I/O 2 | -------------------------------- 3 | 4 | .. literalinclude:: ../test/play_wave.py 5 | 6 | To use PyAudio, first instantiate PyAudio using 7 | :py:func:`pyaudio.PyAudio` (1), which sets up the portaudio system. 8 | 9 | To record or play audio, open a stream on the desired device with the 10 | desired audio parameters using :py:func:`pyaudio.PyAudio.open` 11 | (2). This sets up a :py:class:`pyaudio.Stream` to play or record 12 | audio. 13 | 14 | Play audio by writing audio data to the stream using 15 | :py:func:`pyaudio.Stream.write`, or read audio data from the stream 16 | using :py:func:`pyaudio.Stream.read`. (3) 17 | 18 | Note that in "blocking mode", each :py:func:`pyaudio.Stream.write` or 19 | :py:func:`pyaudio.Stream.read` blocks until all the given/requested 20 | frames have been played/recorded. Alternatively, to generate audio 21 | data on the fly or immediately process recorded audio data, use the 22 | "callback mode" outlined below. 23 | 24 | Use :py:func:`pyaudio.Stream.stop_stream` to pause playing/recording, 25 | and :py:func:`pyaudio.Stream.close` to terminate the stream. (4) 26 | 27 | Finally, terminate the portaudio session using 28 | :py:func:`pyaudio.PyAudio.terminate` (5) 29 | 30 | Example: Callback Mode Audio I/O 31 | -------------------------------- 32 | 33 | .. literalinclude:: ../test/play_wave_callback.py 34 | 35 | In callback mode, PyAudio will call a specified callback function (2) 36 | whenever it needs new audio data (to play) and/or when there is new 37 | (recorded) audio data available. Note that PyAudio calls the callback 38 | function in a separate thread. The function has the following 39 | signature ``callback(, , , 40 | )`` and must return a tuple containing ``frame_count`` 41 | frames of audio data and a flag signifying whether there are more 42 | frames to play/record. 43 | 44 | Start processing the audio stream using 45 | :py:func:`pyaudio.Stream.start_stream` (4), which will call the 46 | callback function repeatedly until that function returns 47 | :py:data:`pyaudio.paComplete`. 48 | 49 | To keep the stream active, the main thread must not terminate, e.g., 50 | by sleeping (5). 51 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 2014-02-16 Hubert Pham 2 | 3 | PyAudio 0.2.8 4 | 5 | - Device names: support non-UTF8 encoded device names. 6 | 7 | get_device_info_by_index() now attempts to decode the device name 8 | using a few known encodings (defaults to UTF-8 and CP1252). If 9 | those fail, PyAudio passes the raw bytes for the device name. 10 | Previously, PyAudio assumed a UTF-8 encoding, which is not always 11 | true. 12 | 13 | - Callback-mode: fix deadlock on some platforms when calling 14 | pa.stop_stream. 15 | 16 | Thanks to Jason Roehm for this patch! 17 | 18 | 2012-10-20 Hubert Pham 19 | 20 | PyAudio 0.2.7 21 | 22 | - Callback-mode: support callables. 23 | 24 | Thanks to John Luebs and Bastian Bechtold for this patch. 25 | 26 | - Update documentation to use Sphinx. 27 | 28 | Thanks again to Bastian Bechtold for his incredible contribution! 29 | 30 | 31 | 2012-09-01 Hubert Pham 32 | 33 | PyAudio 0.2.6 34 | 35 | - Added support for Python 3. As of this update, PyAudio is 36 | compatible with Python 2.6, Python 2.7, and Python 3.2. 37 | 38 | Many thanks to Bastian Bechtold and Bob Jamison for their patches! 39 | 40 | - Fixed a bug in which a list could be modified during iteration. 41 | 42 | Many thanks to Danilo J. S. Bellini for reporting this error! 43 | 44 | - Fixed a memory bug involving Mac OS X channel maps. 45 | 46 | 47 | 2012-09-01 Hubert Pham 48 | 49 | PyAudio 0.2.5 50 | 51 | - Added support for callback (non-blocking) operation. 52 | 53 | Many thanks to Bastian Bechtold for his initial contribution and 54 | his generous help towards releasing this feature. Callback mode 55 | would not have happened without Bastian's help! 56 | 57 | 58 | 2010-08-12 Hubert Pham 59 | 60 | PyAudio 0.2.4 61 | 62 | - Maintenance release: updated directory structure and packaging. 63 | 64 | 65 | 2008-10-29 Hubert Pham 66 | 67 | PyAudio 0.2.3 68 | 69 | - Release the GIL during blocking PortAudio I/O calls. 70 | 71 | - Fixed Python argument parsing to use a long for PaSampleFormat 72 | (rather than int). 73 | 74 | Thanks to many who have pointed out these two issues and sent 75 | patches. 76 | 77 | - pyaudio.PyAudio.is_format_supported() now throws a ValueError 78 | exception if the specified format is not supported for any reason 79 | (or returns True if the format is supported). 80 | 81 | Prior, the method would return False if and only if the specified 82 | sample rate was unsupported. is_format_supported() now will always 83 | return True or throw an exception. 84 | 85 | 86 | 2008-03-06 Hubert Pham 87 | 88 | PyAudio 0.2.0 89 | 90 | - Added PaMacCoreStreamInfo for Mac OS X Host API Specific Stream Info 91 | (e.g., for channel maps). 92 | 93 | - Added packaging files for building binaries. 94 | 95 | 96 | 2008-02-12 Justin Mazzola Paluska 97 | 98 | - Initial version of debian packaging. 99 | 100 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | ====================================================================== 2 | PyAudio Compilation Hints 3 | ====================================================================== 4 | 5 | Here are some hints for compiling PortAudio and PyAudio on various 6 | platforms: 7 | 8 | * General UNIX Guide: (GNU/Linux, Mac OS X, Cygwin) 9 | * Microsoft Windows (native) 10 | 11 | Generally speaking, you must first install the PortAudio v19 library 12 | before building PyAudio. 13 | 14 | 15 | ---------------------------------------------------------------------- 16 | General UNIX Guide (GNU/Linux, Mac OS X, Cygwin) 17 | ---------------------------------------------------------------------- 18 | 19 | 1. Build and install PortAudio, i.e.: 20 | 21 | % ./configure 22 | % make 23 | % make install # you may need to be root 24 | 25 | (Or better yet, use your package manager to install PortAudio v19) 26 | 27 | 2. Extract PyAudio; to build and install, run: 28 | 29 | % python setup.py install 30 | 31 | 32 | ---------------------------------------------------------------------- 33 | Microsoft Windows 34 | ---------------------------------------------------------------------- 35 | 36 | If you are targeting native Win32 Python, you will need either 37 | Microsoft Visual Studio or MinGW (via Cygwin). Here are compilation 38 | hints for using MinGW under the Cygwin build environment. 39 | 40 | Note: I've only tested this under Cygwin's build environment. Your 41 | mileage may vary in other environments (i.e., compiling PortAudio with 42 | MinGW's compiler and environment). 43 | 44 | (If you have instructions for building PyAudio using Visual Studio, 45 | I'd love to hear about it.) 46 | 47 | 1. Download PortAudio to ./portaudio-v19 in this directory 48 | and build. When running configure, be sure to use ``-mno-cygwin`` 49 | (under cygwin) to generate native Win32 binaries: 50 | 51 | % cd ./portaudio-v19 52 | % CFLAGS="-mno-cygwin" LDFLAGS="-mno-cygwin" ./configure 53 | % make 54 | % cd .. 55 | 56 | 2. To build PyAudio, run (from this directory): 57 | 58 | % python setup.py build --static-link -cmingw32 59 | 60 | Be sure to invoke the native Win32 python rather than cygwin's 61 | python. The --static-link option statically links in the PortAudio 62 | library to the PyAudio module, which is probably the best way to go 63 | on Windows. 64 | 65 | From: http://boodebr.org/main/python/build-windows-extensions 66 | 67 | Update: 2008-09-10 68 | 69 | Recent versions of Cygwin binutils have version numbers that are 70 | breaking the version number parsing, resulting in errors like: 71 | ValueError: invalid version number '2.18.50.20080625' 72 | 73 | To fix this, edit distutils/version.py. At line 100, replace: 74 | 75 | version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', 76 | re.VERBOSE) 77 | 78 | with 79 | 80 | version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? (\. (\d+))?$', 81 | re.VERBOSE) 82 | 83 | 3. To install PyAudio: 84 | 85 | % python setup.py install --skip-build 86 | 87 | The --skip-build option prevents Python from searching your system 88 | for Visual Studio and the .NET framework. 89 | -------------------------------------------------------------------------------- /src/_portaudiomodule.h: -------------------------------------------------------------------------------- 1 | /** 2 | * PyAudio : Python Bindings for PortAudio. 3 | * 4 | * PyAudio : API Header File 5 | * 6 | * Copyright (c) 2006-2012 Hubert Pham 7 | * 8 | * Permission is hereby granted, free of charge, to any person 9 | * obtaining a copy of this software and associated documentation 10 | * files (the "Software"), to deal in the Software without 11 | * restriction, including without limitation the rights to use, copy, 12 | * modify, merge, publish, distribute, sublicense, and/or sell copies 13 | * of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 23 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 24 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifndef __PAMODULE_H__ 30 | #define __PAMODULE_H__ 31 | 32 | /* version */ 33 | static PyObject * 34 | pa_get_version(PyObject *self, PyObject *args); 35 | 36 | static PyObject * 37 | pa_get_version_text(PyObject *self, PyObject *args); 38 | 39 | /* framework init */ 40 | static PyObject * 41 | pa_initialize(PyObject *self, PyObject *args); 42 | 43 | static PyObject * 44 | pa_terminate(PyObject *self, PyObject *args); 45 | 46 | /* host api */ 47 | static PyObject * 48 | pa_get_host_api_count(PyObject *self, PyObject *args); 49 | 50 | static PyObject * 51 | pa_get_default_host_api(PyObject *self, PyObject *args); 52 | 53 | static PyObject * 54 | pa_host_api_type_id_to_host_api_index(PyObject *self, PyObject *args); 55 | 56 | static PyObject * 57 | pa_host_api_device_index_to_device_index(PyObject *self, PyObject *args); 58 | 59 | static PyObject * 60 | pa_get_host_api_info(PyObject *self, PyObject *args); 61 | 62 | /* device api */ 63 | static PyObject * 64 | pa_get_device_count(PyObject *self, PyObject *args); 65 | 66 | static PyObject * 67 | pa_get_default_input_device(PyObject *self, PyObject *args); 68 | 69 | static PyObject * 70 | pa_get_default_output_device(PyObject *self, PyObject *args); 71 | 72 | static PyObject * 73 | pa_get_device_info(PyObject *self, PyObject *args); 74 | 75 | /* stream open/close */ 76 | 77 | static PyObject * 78 | pa_open(PyObject *self, PyObject *args, PyObject *kwargs); 79 | 80 | static PyObject * 81 | pa_close(PyObject *self, PyObject *args); 82 | 83 | static PyObject * 84 | pa_get_sample_size(PyObject *self, PyObject *args); 85 | 86 | static PyObject * 87 | pa_is_format_supported(PyObject *self, PyObject *args, 88 | PyObject *kwargs); 89 | 90 | /* stream start/stop/info */ 91 | 92 | static PyObject * 93 | pa_start_stream(PyObject *self, PyObject *args); 94 | 95 | static PyObject * 96 | pa_stop_stream(PyObject *self, PyObject *args); 97 | 98 | static PyObject * 99 | pa_abort_stream(PyObject *self, PyObject *args); 100 | 101 | static PyObject * 102 | pa_is_stream_stopped(PyObject *self, PyObject *args); 103 | 104 | static PyObject * 105 | pa_is_stream_active(PyObject *self, PyObject *args); 106 | 107 | static PyObject * 108 | pa_get_stream_time(PyObject *self, PyObject *args); 109 | 110 | static PyObject * 111 | pa_get_stream_cpu_load(PyObject *self, PyObject *args); 112 | 113 | /* stream write/read */ 114 | 115 | static PyObject * 116 | pa_write_stream(PyObject *self, PyObject *args); 117 | 118 | static PyObject * 119 | pa_read_stream(PyObject *self, PyObject *args); 120 | 121 | static PyObject * 122 | pa_get_stream_write_available(PyObject *self, PyObject *args); 123 | 124 | static PyObject * 125 | pa_get_stream_read_available(PyObject *self, PyObject *args); 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /test/error.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyAudio Example: Test for a variety of error conditions. This example 3 | demonstrates exception handling with PyAudio. 4 | """ 5 | 6 | import pyaudio 7 | 8 | p = pyaudio.PyAudio() 9 | 10 | # get invalid sample size 11 | try: 12 | p.get_sample_size(10) 13 | except ValueError as e: 14 | assert e.args[1] == pyaudio.paSampleFormatNotSupported 15 | print("OK: %s" % e.args[0]) 16 | else: 17 | assert False, "sample size" 18 | 19 | # get format from invalid width 20 | try: 21 | p.get_format_from_width(8) 22 | except ValueError as e: 23 | print("OK: invalid format from width") 24 | else: 25 | assert False, "invalid format" 26 | 27 | # try to get an invalid device 28 | try: 29 | p.get_host_api_info_by_type(-1) 30 | except IOError as e: 31 | assert e.args[1] == pyaudio.paHostApiNotFound 32 | print("OK: %s" % e.args[0]) 33 | else: 34 | assert False, "invalid host type" 35 | 36 | # try to get host api info by index 37 | try: 38 | p.get_host_api_info_by_index(-1) 39 | except IOError as e: 40 | assert e.args[1] == pyaudio.paInvalidHostApi 41 | print("OK: %s" % e.args[0]) 42 | else: 43 | assert False, "invalid host api index" 44 | 45 | # try good host api device index 46 | try: 47 | p.get_device_info_by_host_api_device_index(0, -1) 48 | except IOError as e: 49 | assert ((e.args[1] == pyaudio.paInvalidDevice) or \ 50 | (e.args[1] == pyaudio.paInvalidHostApi)) 51 | print("OK: %s" % e.args[0]) 52 | else: 53 | assert False, "device info by host api device idnex" 54 | 55 | 56 | # try bad host api and good device index 57 | try: 58 | p.get_device_info_by_host_api_device_index(-1, 0) 59 | except IOError as e: 60 | assert ((e.args[1] == pyaudio.paInvalidDevice) or \ 61 | (e.args[1] == pyaudio.paInvalidHostApi)) 62 | print("OK: %s" % e.args[0]) 63 | else: 64 | assert False, "device info by host api device idnex" 65 | 66 | 67 | # bad device index 68 | try: 69 | p.get_device_info_by_index(-1) 70 | except IOError as e: 71 | assert e.args[1] == pyaudio.paInvalidDevice 72 | print("OK: %s" % e.args[0]) 73 | else: 74 | assert False, "bad device index" 75 | 76 | ### now for some real work ### 77 | 78 | stream = p.open(channels = 1, 79 | rate = 44100, 80 | format = pyaudio.paInt16, 81 | input = True, 82 | start = False) 83 | 84 | # (note that we didn't start the stream!) 85 | 86 | try: 87 | data = stream.read(2) 88 | except IOError as e: 89 | print("OK: %s" % e.args[0]) 90 | assert e.args[1] == pyaudio.paStreamIsStopped, e.args[1] 91 | else: 92 | assert False, "Should have caused exception" 93 | 94 | stream.start_stream() 95 | 96 | # try to write to the input stream 97 | try: 98 | stream.write('foobar') 99 | except IOError as e: 100 | assert e.args[1] == pyaudio.paCanNotWriteToAnInputOnlyStream 101 | print("OK: %s" % e.args[0]) 102 | else: 103 | assert False, "write to input stream" 104 | 105 | # read some negative data 106 | try: 107 | data = stream.read(-1) 108 | except ValueError as e: 109 | print("OK: Invalid frames") 110 | else: 111 | assert False, "invalid frames" 112 | 113 | # read some real data 114 | try: 115 | data = stream.read(2) 116 | except IOError as e: 117 | # some slower machines might overflow 118 | assert e.args[1] == pyaudio.paInputOverflowed, e 119 | print("OK: %s" % e.args[0]) 120 | else: 121 | print("OK: got %d bytes of data" % len(data)) 122 | 123 | # close the stream; nothing should work with 124 | # this stream afterwards 125 | 126 | stream.close() 127 | 128 | # query for properties 129 | try: 130 | stream.get_input_latency() 131 | except IOError as e: 132 | assert e.args[1] == pyaudio.paBadStreamPtr 133 | print("OK: %s" % e.args[0]) 134 | else: 135 | assert False, "closed stream" 136 | 137 | # read some data again 138 | try: 139 | stream.read(10) 140 | except IOError as e: 141 | assert e.args[1] == pyaudio.paBadStreamPtr 142 | print("OK: %s" % e.args[0]) 143 | else: 144 | assert False, "closed stream" 145 | 146 | # get invalid stream capabilities 147 | try: 148 | p.is_format_supported(8000, -1, 1, pyaudio.paInt16) 149 | except ValueError as e: 150 | assert e.args[1] == pyaudio.paInvalidDevice 151 | print("OK: %s" % e.args[0]) 152 | else: 153 | assert False, "invalid device" 154 | 155 | # get invalid stream capabilities 156 | try: 157 | p.is_format_supported(8000, 0, -1, pyaudio.paInt16) 158 | except ValueError as e: 159 | assert e.args[1] == pyaudio.paInvalidChannelCount 160 | print("OK: %s" % e.args[0]) 161 | else: 162 | assert False, "invalid number of channels" 163 | 164 | p.terminate() 165 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyAudio v0.2.8: Python Bindings for PortAudio. 3 | 4 | Copyright (c) 2006-2014 Hubert Pham 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files (the 8 | "Software"), to deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY 18 | OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 22 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 23 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 26 | USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | """ 28 | 29 | from distutils.core import setup, Extension 30 | import sys 31 | import os 32 | 33 | __version__ = "0.2.8" 34 | 35 | # Note: distutils will try to locate and link dynamically 36 | # against portaudio. 37 | # 38 | # You probably don't want to statically link in the PortAudio 39 | # library unless you're building on Microsoft Windows. 40 | # 41 | # In any case, if you would rather statically link in libportaudio, 42 | # run: 43 | # 44 | # % python setup.py build --static-link 45 | # 46 | # Be sure to specify the location of the libportaudio.a in 47 | # the `extra_link_args' variable below. 48 | 49 | STATIC_LINKING = False 50 | 51 | if "--static-link" in sys.argv: 52 | STATIC_LINKING = True 53 | sys.argv.remove("--static-link") 54 | 55 | portaudio_path = os.environ.get("PORTAUDIO_PATH", "./portaudio-v19") 56 | mac_sysroot_path = os.environ.get("SYSROOT_PATH", None) 57 | 58 | pyaudio_module_sources = ['src/_portaudiomodule.c'] 59 | 60 | include_dirs = [] 61 | external_libraries = [] 62 | extra_compile_args = [] 63 | extra_link_args = [] 64 | scripts = [] 65 | defines = [] 66 | 67 | if STATIC_LINKING: 68 | extra_link_args = [ 69 | os.path.join(portaudio_path, 'lib/.libs/libportaudio.a') 70 | ] 71 | include_dirs = [os.path.join(portaudio_path, 'include/')] 72 | else: 73 | # dynamic linking 74 | external_libraries = ['portaudio'] 75 | extra_link_args = [] 76 | 77 | if sys.platform == 'darwin': 78 | defines += [('MACOSX', '1')] 79 | 80 | if mac_sysroot_path: 81 | extra_compile_args += ["-isysroot", mac_sysroot_path] 82 | extra_link_args += ["-isysroot", mac_sysroot_path] 83 | 84 | if STATIC_LINKING: 85 | 86 | # platform specific configuration 87 | if sys.platform == 'darwin': 88 | extra_link_args += ['-framework', 'CoreAudio', 89 | '-framework', 'AudioToolbox', 90 | '-framework', 'AudioUnit', 91 | '-framework', 'Carbon'] 92 | 93 | elif sys.platform == 'cygwin': 94 | external_libraries += ['winmm'] 95 | extra_link_args += ['-lwinmm'] 96 | 97 | elif sys.platform == 'win32': 98 | # i.e., Win32 Python with mingw32 99 | # run: python setup.py build -cmingw32 100 | external_libraries += ['winmm'] 101 | extra_link_args += ['-lwinmm'] 102 | 103 | elif sys.platform == 'linux2': 104 | extra_link_args += ['-lrt', '-lm', '-lpthread'] 105 | 106 | # Since you're insisting on linking statically against 107 | # PortAudio on GNU/Linux, be sure to link in whatever sound 108 | # backend you used in portaudio (e.g., ALSA, JACK, etc...) 109 | 110 | # I'll start you off with ALSA, since that's the most common 111 | # today. If you need JACK support, add it here. 112 | 113 | extra_link_args += ['-lasound', '-ljack'] 114 | 115 | 116 | pyaudio = Extension('_portaudio', 117 | sources=pyaudio_module_sources, 118 | include_dirs=include_dirs, 119 | define_macros=defines, 120 | libraries=external_libraries, 121 | extra_compile_args=extra_compile_args, 122 | extra_link_args=extra_link_args) 123 | 124 | setup(name = 'PyAudio', 125 | version = __version__, 126 | author = "Hubert Pham", 127 | url = "http://people.csail.mit.edu/hubert/pyaudio/", 128 | description = 'PortAudio Python Bindings', 129 | long_description = __doc__.lstrip(), 130 | scripts = scripts, 131 | py_modules = ['pyaudio'], 132 | package_dir = {'': 'src'}, 133 | ext_modules = [pyaudio]) 134 | -------------------------------------------------------------------------------- /test/system_info.py: -------------------------------------------------------------------------------- 1 | """ 2 | PyAudio Example: 3 | 4 | Query and print PortAudio HostAPIs, Devices, and their 5 | support rates. 6 | """ 7 | 8 | import pyaudio 9 | 10 | standard_sample_rates = [8000.0, 9600.0, 11025.0, 12000.0, 11 | 16000.0, 22050.0, 24000.0, 32000.0, 12 | 44100.0, 48000.0, 88200.0, 96000.0, 13 | 192000.0] 14 | 15 | p = pyaudio.PyAudio() 16 | max_apis = p.get_host_api_count() 17 | max_devs = p.get_device_count() 18 | 19 | print("\nPortAudio System Info:\n======================") 20 | print("Version: %d" % pyaudio.get_portaudio_version()) 21 | print("Version Text: %s" % pyaudio.get_portaudio_version_text()) 22 | print("Number of Host APIs: %d" % max_apis) 23 | print("Number of Devices : %d" % max_devs) 24 | 25 | print("\nHost APIs:\n==========") 26 | 27 | for i in range(max_apis): 28 | apiinfo = p.get_host_api_info_by_index(i) 29 | for k in list(apiinfo.items()): 30 | print("%s: %s" % k) 31 | print("--------------------------") 32 | 33 | print("\nDevices:\n========") 34 | 35 | for i in range(max_devs): 36 | devinfo = p.get_device_info_by_index(i) 37 | 38 | # print out device parameters 39 | for k in list(devinfo.items()): 40 | name, value = k 41 | 42 | # if host API, then get friendly name 43 | 44 | if name == 'hostApi': 45 | value = str(value) + \ 46 | " (%s)" % p.get_host_api_info_by_index(k[1])['name'] 47 | 48 | # Crashing? See http://stackoverflow.com/a/5146914 49 | print("\t%s: %s" % (name, value)) 50 | 51 | # print out supported format rates 52 | 53 | input_supported_rates = [] 54 | output_supported_rates = [] 55 | full_duplex_rates = [] 56 | 57 | for f in standard_sample_rates: 58 | 59 | if devinfo['maxInputChannels'] > 0: 60 | try: 61 | if p.is_format_supported( 62 | f, 63 | input_device = devinfo['index'], 64 | input_channels = devinfo['maxInputChannels'], 65 | input_format = pyaudio.paInt16): 66 | input_supported_rates.append(f) 67 | except ValueError: 68 | pass 69 | 70 | if devinfo['maxOutputChannels'] > 0: 71 | try: 72 | if p.is_format_supported( 73 | f, 74 | output_device = devinfo['index'], 75 | output_channels = devinfo['maxOutputChannels'], 76 | output_format = pyaudio.paInt16): 77 | output_supported_rates.append(f) 78 | except ValueError: 79 | pass 80 | 81 | if (devinfo['maxInputChannels'] > 0) and \ 82 | (devinfo['maxOutputChannels'] > 0): 83 | try: 84 | if p.is_format_supported( 85 | f, 86 | input_device = devinfo['index'], 87 | input_channels = devinfo['maxInputChannels'], 88 | input_format = pyaudio.paInt16, 89 | output_device = devinfo['index'], 90 | output_channels = devinfo['maxOutputChannels'], 91 | output_format = pyaudio.paInt16): 92 | full_duplex_rates.append(f) 93 | except ValueError: 94 | pass 95 | 96 | if len(input_supported_rates): 97 | print("\tInput rates: %s" % input_supported_rates) 98 | if len(output_supported_rates): 99 | print("\tOutput rates: %s" % output_supported_rates) 100 | if len(full_duplex_rates): 101 | print("\tFull duplex: %s" % full_duplex_rates) 102 | 103 | print("\t--------------------------------") 104 | 105 | print("\nDefault Devices:\n================") 106 | try: 107 | def_index = p.get_default_input_device_info()['index'] 108 | print("Default Input Device : %s" % def_index) 109 | devinfo = p.get_device_info_by_index(def_index) 110 | for k in list(devinfo.items()): 111 | name, value = k 112 | if name == 'hostApi': 113 | value = str(value) + \ 114 | " (%s)" % p.get_host_api_info_by_index(k[1])['name'] 115 | print("\t%s: %s" % (name, value)) 116 | print("\t--------------------------------") 117 | except IOError as e: 118 | print("No Input devices: %s" % e[0]) 119 | 120 | try: 121 | def_index = p.get_default_output_device_info()['index'] 122 | print("Default Output Device: %s" % def_index) 123 | devinfo = p.get_device_info_by_index(def_index) 124 | for k in list(devinfo.items()): 125 | name, value = k 126 | if name == 'hostApi': 127 | value = str(value) + \ 128 | " (%s)" % p.get_host_api_info_by_index(k[1])['name'] 129 | print("\t%s: %s" % (name, value)) 130 | print("\t--------------------------------") 131 | except IOError as e: 132 | print("No Output devices: %s" % e[0]) 133 | 134 | p.terminate() 135 | -------------------------------------------------------------------------------- /sphinx/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # PyAudio documentation build configuration file, created by 5 | # sphinx-quickstart on Wed Aug 29 08:37:41 2012. 6 | # 7 | # This file is execfile()d with the current directory set to its containing dir. 8 | # 9 | # Note that not all possible configuration values are present in this 10 | # autogenerated file. 11 | # 12 | # All configuration values have a default; values that are commented out 13 | # serve to show the default. 14 | 15 | import sys, os 16 | 17 | # If extensions (or modules to document with autodoc) are in another directory, 18 | # add these directories to sys.path here. If the directory is relative to the 19 | # documentation root, use os.path.abspath to make it absolute, like shown here. 20 | #sys.path.insert(0, os.path.abspath('.')) 21 | 22 | # -- General configuration ----------------------------------------------------- 23 | 24 | # If your documentation needs a minimal Sphinx version, state it here. 25 | #needs_sphinx = '1.0' 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be extensions 28 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 29 | extensions = ['sphinx.ext.autodoc'] 30 | 31 | # Add any paths that contain templates here, relative to this directory. 32 | templates_path = ['_templates'] 33 | 34 | # The suffix of source filenames. 35 | source_suffix = '.rst' 36 | 37 | # The encoding of source files. 38 | #source_encoding = 'utf-8-sig' 39 | 40 | # The master toctree document. 41 | master_doc = 'index' 42 | 43 | # General information about the project. 44 | project = 'PyAudio' 45 | copyright = '2014, Hubert Pham' 46 | 47 | # The version info for the project you're documenting, acts as replacement for 48 | # |version| and |release|, also used in various other places throughout the 49 | # built documents. 50 | # 51 | # The short X.Y version. 52 | version = '0.2.8' 53 | # The full version, including alpha/beta/rc tags. 54 | release = '0.2.8' 55 | 56 | # The language for content autogenerated by Sphinx. Refer to documentation 57 | # for a list of supported languages. 58 | #language = None 59 | 60 | # There are two options for replacing |today|: either, you set today to some 61 | # non-false value, then it is used: 62 | #today = '' 63 | # Else, today_fmt is used as the format for a strftime call. 64 | #today_fmt = '%B %d, %Y' 65 | 66 | # List of patterns, relative to source directory, that match files and 67 | # directories to ignore when looking for source files. 68 | exclude_patterns = ['_build'] 69 | 70 | # The reST default role (used for this markup: `text`) to use for all documents. 71 | #default_role = None 72 | 73 | # If true, '()' will be appended to :func: etc. cross-reference text. 74 | #add_function_parentheses = True 75 | 76 | # If true, the current module name will be prepended to all description 77 | # unit titles (such as .. function::). 78 | #add_module_names = True 79 | 80 | # If true, sectionauthor and moduleauthor directives will be shown in the 81 | # output. They are ignored by default. 82 | #show_authors = False 83 | 84 | # The name of the Pygments (syntax highlighting) style to use. 85 | pygments_style = 'sphinx' 86 | 87 | # A list of ignored prefixes for module index sorting. 88 | #modindex_common_prefix = [] 89 | 90 | 91 | # -- Options for HTML output --------------------------------------------------- 92 | 93 | # The theme to use for HTML and HTML Help pages. See the documentation for 94 | # a list of builtin themes. 95 | html_theme = 'nature' 96 | 97 | # Theme options are theme-specific and customize the look and feel of a theme 98 | # further. For a list of options available for each theme, see the 99 | # documentation. 100 | html_theme_options = { 101 | "nosidebar": True 102 | } 103 | 104 | # Add any paths that contain custom themes here, relative to this directory. 105 | #html_theme_path = [] 106 | 107 | # The name for this set of Sphinx documents. If None, it defaults to 108 | # " v documentation". 109 | #html_title = None 110 | 111 | # A shorter title for the navigation bar. Default is the same as html_title. 112 | #html_short_title = None 113 | 114 | # The name of an image file (relative to this directory) to place at the top 115 | # of the sidebar. 116 | #html_logo = None 117 | 118 | # The name of an image file (within the static path) to use as favicon of the 119 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 120 | # pixels large. 121 | #html_favicon = None 122 | 123 | # Add any paths that contain custom static files (such as style sheets) here, 124 | # relative to this directory. They are copied after the builtin static files, 125 | # so a file named "default.css" will overwrite the builtin "default.css". 126 | #html_static_path = ['_static'] 127 | 128 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 129 | # using the given strftime format. 130 | #html_last_updated_fmt = '%b %d, %Y' 131 | 132 | # If true, SmartyPants will be used to convert quotes and dashes to 133 | # typographically correct entities. 134 | #html_use_smartypants = True 135 | 136 | # Custom sidebar templates, maps document names to template names. 137 | #html_sidebars = {} 138 | 139 | # Additional templates that should be rendered to pages, maps page names to 140 | # template names. 141 | #html_additional_pages = {} 142 | 143 | # If false, no module index is generated. 144 | #html_domain_indices = True 145 | 146 | # If false, no index is generated. 147 | #html_use_index = True 148 | 149 | # If true, the index is split into individual pages for each letter. 150 | #html_split_index = False 151 | 152 | # If true, links to the reST sources are added to the pages. 153 | #html_show_sourcelink = True 154 | 155 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 156 | #html_show_sphinx = True 157 | 158 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 159 | #html_show_copyright = True 160 | 161 | # If true, an OpenSearch description file will be output, and all pages will 162 | # contain a tag referring to it. The value of this option must be the 163 | # base URL from which the finished HTML is served. 164 | #html_use_opensearch = '' 165 | 166 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 167 | #html_file_suffix = None 168 | 169 | # Output file base name for HTML help builder. 170 | htmlhelp_basename = 'PyAudiodoc' 171 | 172 | 173 | # -- Options for LaTeX output -------------------------------------------------- 174 | 175 | latex_elements = { 176 | # The paper size ('letterpaper' or 'a4paper'). 177 | #'papersize': 'letterpaper', 178 | 179 | # The font size ('10pt', '11pt' or '12pt'). 180 | #'pointsize': '10pt', 181 | 182 | # Additional stuff for the LaTeX preamble. 183 | #'preamble': '', 184 | } 185 | 186 | # Grouping the document tree into LaTeX files. List of tuples 187 | # (source start file, target name, title, author, documentclass [howto/manual]). 188 | latex_documents = [ 189 | ('index', 'PyAudio.tex', 'PyAudio Documentation', 190 | 'Hubert Pham', 'manual'), 191 | ] 192 | 193 | # The name of an image file (relative to this directory) to place at the top of 194 | # the title page. 195 | #latex_logo = None 196 | 197 | # For "manual" documents, if this is true, then toplevel headings are parts, 198 | # not chapters. 199 | #latex_use_parts = False 200 | 201 | # If true, show page references after internal links. 202 | #latex_show_pagerefs = False 203 | 204 | # If true, show URL addresses after external links. 205 | #latex_show_urls = False 206 | 207 | # Documents to append as an appendix to all manuals. 208 | #latex_appendices = [] 209 | 210 | # If false, no module index is generated. 211 | #latex_domain_indices = True 212 | 213 | 214 | # -- Options for manual page output -------------------------------------------- 215 | 216 | # One entry per manual page. List of tuples 217 | # (source start file, name, description, authors, manual section). 218 | man_pages = [ 219 | ('index', 'pyaudio', 'PyAudio Documentation', 220 | ['Hubert Pham'], 1) 221 | ] 222 | 223 | # If true, show URL addresses after external links. 224 | #man_show_urls = False 225 | 226 | 227 | # -- Options for Texinfo output ------------------------------------------------ 228 | 229 | # Grouping the document tree into Texinfo files. List of tuples 230 | # (source start file, target name, title, author, 231 | # dir menu entry, description, category) 232 | texinfo_documents = [ 233 | ('index', 'PyAudio', 'PyAudio Documentation', 234 | 'Hubert Pham', 'PyAudio', 'One line description of project.', 235 | 'Miscellaneous'), 236 | ] 237 | 238 | # Documents to append as an appendix to all manuals. 239 | #texinfo_appendices = [] 240 | 241 | # If false, no module index is generated. 242 | #texinfo_domain_indices = True 243 | 244 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 245 | #texinfo_show_urls = 'footnote' 246 | 247 | try: 248 | from _portaudio import paMacCoreStreamInfo 249 | except ImportError: 250 | pass 251 | else: 252 | tags.add('pamac') 253 | -------------------------------------------------------------------------------- /src/pyaudio.py: -------------------------------------------------------------------------------- 1 | # PyAudio : Python Bindings for PortAudio. 2 | 3 | # Copyright (c) 2006-2012 Hubert Pham 4 | 5 | # Permission is hereby granted, free of charge, to any person obtaining 6 | # a copy of this software and associated documentation files (the 7 | # "Software"), to deal in the Software without restriction, including 8 | # without limitation the rights to use, copy, modify, merge, publish, 9 | # distribute, sublicense, and/or sell copies of the Software, and to 10 | # permit persons to whom the Software is furnished to do so, subject to 11 | # 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 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | 25 | """ 26 | PyAudio provides Python bindings for PortAudio, the cross-platform 27 | audio I/O library. With PyAudio, you can easily use Python to play and 28 | record audio on a variety of platforms. PyAudio is inspired by: 29 | 30 | * pyPortAudio/fastaudio: Python bindings for PortAudio v18 API. 31 | * tkSnack: cross-platform sound toolkit for Tcl/Tk and Python. 32 | 33 | .. include:: ../sphinx/examples.rst 34 | 35 | Overview 36 | -------- 37 | 38 | **Classes** 39 | :py:class:`PyAudio`, :py:class:`Stream` 40 | 41 | .. only:: pamac 42 | 43 | **Host Specific Classes** 44 | :py:class:`PaMacCoreStreamInfo` 45 | 46 | **Stream Conversion Convenience Functions** 47 | :py:func:`get_sample_size`, :py:func:`get_format_from_width` 48 | 49 | **PortAudio version** 50 | :py:func:`get_portaudio_version`, :py:func:`get_portaudio_version_text` 51 | 52 | .. |PaSampleFormat| replace:: :ref:`PortAudio Sample Format ` 53 | .. _PaSampleFormat: 54 | 55 | **Portaudio Sample Formats** 56 | :py:data:`paFloat32`, :py:data:`paInt32`, :py:data:`paInt24`, 57 | :py:data:`paInt16`, :py:data:`paInt8`, :py:data:`paUInt8`, 58 | :py:data:`paCustomFormat` 59 | 60 | .. |PaHostAPI| replace:: :ref:`PortAudio Host API ` 61 | .. _PaHostAPI: 62 | 63 | **PortAudio Host APIs** 64 | :py:data:`paInDevelopment`, :py:data:`paDirectSound`, :py:data:`paMME`, 65 | :py:data:`paASIO`, :py:data:`paSoundManager`, :py:data:`paCoreAudio`, 66 | :py:data:`paOSS`, :py:data:`paALSA`, :py:data:`paAL`, :py:data:`paBeOS`, 67 | :py:data:`paWDMKS`, :py:data:`paJACK`, :py:data:`paWASAPI`, 68 | :py:data:`paNoDevice` 69 | 70 | .. |PaErrorCode| replace:: :ref:`PortAudio Error Code ` 71 | .. _PaErrorCode: 72 | 73 | **PortAudio Error Codes** 74 | :py:data:`paNoError`, :py:data:`paNotInitialized`, 75 | :py:data:`paUnanticipatedHostError`, :py:data:`paInvalidChannelCount`, 76 | :py:data:`paInvalidSampleRate`, :py:data:`paInvalidDevice`, 77 | :py:data:`paInvalidFlag`, :py:data:`paSampleFormatNotSupported`, 78 | :py:data:`paBadIODeviceCombination`, :py:data:`paInsufficientMemory`, 79 | :py:data:`paBufferTooBig`, :py:data:`paBufferTooSmall`, 80 | :py:data:`paNullCallback`, :py:data:`paBadStreamPtr`, 81 | :py:data:`paTimedOut`, :py:data:`paInternalError`, 82 | :py:data:`paDeviceUnavailable`, 83 | :py:data:`paIncompatibleHostApiSpecificStreamInfo`, 84 | :py:data:`paStreamIsStopped`, :py:data:`paStreamIsNotStopped`, 85 | :py:data:`paInputOverflowed`, :py:data:`paOutputUnderflowed`, 86 | :py:data:`paHostApiNotFound`, :py:data:`paInvalidHostApi`, 87 | :py:data:`paCanNotReadFromACallbackStream`, 88 | :py:data:`paCanNotWriteToACallbackStream`, 89 | :py:data:`paCanNotReadFromAnOutputOnlyStream`, 90 | :py:data:`paCanNotWriteToAnInputOnlyStream`, 91 | :py:data:`paIncompatibleStreamHostApi` 92 | 93 | .. |PaCallbackReturnCodes| replace:: :ref:`PortAudio Callback Return Code ` 94 | .. _PaCallbackReturnCodes: 95 | 96 | **PortAudio Callback Return Codes** 97 | :py:data:`paContinue`, :py:data:`paComplete`, :py:data:`paAbort` 98 | 99 | .. |PaCallbackFlags| replace:: :ref:`PortAutio Callback Flag ` 100 | .. _PaCallbackFlags: 101 | 102 | **PortAudio Callback Flags** 103 | :py:data:`paInputUnderflow`, :py:data:`paInputOverflow`, 104 | :py:data:`paOutputUnderflow`, :py:data:`paOutputOverflow`, 105 | :py:data:`paPrimingOutput` 106 | """ 107 | 108 | __author__ = "Hubert Pham" 109 | __version__ = "0.2.8.1" 110 | __docformat__ = "restructuredtext en" 111 | 112 | import sys 113 | 114 | # attempt to import PortAudio 115 | try: 116 | import _portaudio as pa 117 | except ImportError: 118 | print("Please build and install the PortAudio Python " + 119 | "bindings first.") 120 | sys.exit(-1) 121 | 122 | ############################################################ 123 | # GLOBALS 124 | ############################################################ 125 | 126 | ##### PaSampleFormat Sample Formats ##### 127 | 128 | paFloat32 = pa.paFloat32 #: 32 bit float 129 | paInt32 = pa.paInt32 #: 32 bit int 130 | paInt24 = pa.paInt24 #: 24 bit int 131 | paInt16 = pa.paInt16 #: 16 bit int 132 | paInt8 = pa.paInt8 #: 8 bit int 133 | paUInt8 = pa.paUInt8 #: 8 bit unsigned int 134 | paCustomFormat = pa.paCustomFormat #: a custom data format 135 | 136 | ###### HostAPI TypeId ##### 137 | 138 | paInDevelopment = pa.paInDevelopment #: Still in development 139 | paDirectSound = pa.paDirectSound #: DirectSound (Windows only) 140 | paMME = pa.paMME #: Multimedia Extension (Windows only) 141 | paASIO = pa.paASIO #: Steinberg Audio Stream Input/Output 142 | paSoundManager = pa.paSoundManager #: SoundManager (OSX only) 143 | paCoreAudio = pa.paCoreAudio #: CoreAudio (OSX only) 144 | paOSS = pa.paOSS #: Open Sound System (Linux only) 145 | paALSA = pa.paALSA #: Advanced Linux Sound Architecture (Linux only) 146 | paAL = pa.paAL #: Open Audio Library 147 | paBeOS = pa.paBeOS #: BeOS Sound System 148 | paWDMKS = pa.paWDMKS #: Windows Driver Model (Windows only) 149 | paJACK = pa.paJACK #: JACK Audio Connection Kit 150 | paWASAPI = pa.paWASAPI #: Windows Vista Audio stack architecture 151 | paNoDevice = pa.paNoDevice #: Not actually an audio device 152 | 153 | ###### portaudio error codes ##### 154 | 155 | paNoError = pa.paNoError 156 | paNotInitialized = pa.paNotInitialized 157 | paUnanticipatedHostError = pa.paUnanticipatedHostError 158 | paInvalidChannelCount = pa.paInvalidChannelCount 159 | paInvalidSampleRate = pa.paInvalidSampleRate 160 | paInvalidDevice = pa.paInvalidDevice 161 | paInvalidFlag = pa.paInvalidFlag 162 | paSampleFormatNotSupported = pa.paSampleFormatNotSupported 163 | paBadIODeviceCombination = pa.paBadIODeviceCombination 164 | paInsufficientMemory = pa.paInsufficientMemory 165 | paBufferTooBig = pa.paBufferTooBig 166 | paBufferTooSmall = pa.paBufferTooSmall 167 | paNullCallback = pa.paNullCallback 168 | paBadStreamPtr = pa.paBadStreamPtr 169 | paTimedOut = pa.paTimedOut 170 | paInternalError = pa.paInternalError 171 | paDeviceUnavailable = pa.paDeviceUnavailable 172 | paIncompatibleHostApiSpecificStreamInfo = pa.paIncompatibleHostApiSpecificStreamInfo 173 | paStreamIsStopped = pa.paStreamIsStopped 174 | paStreamIsNotStopped = pa.paStreamIsNotStopped 175 | paInputOverflowed = pa.paInputOverflowed 176 | paOutputUnderflowed = pa.paOutputUnderflowed 177 | paHostApiNotFound = pa.paHostApiNotFound 178 | paInvalidHostApi = pa.paInvalidHostApi 179 | paCanNotReadFromACallbackStream = pa.paCanNotReadFromACallbackStream 180 | paCanNotWriteToACallbackStream = pa.paCanNotWriteToACallbackStream 181 | paCanNotReadFromAnOutputOnlyStream = pa.paCanNotReadFromAnOutputOnlyStream 182 | paCanNotWriteToAnInputOnlyStream = pa.paCanNotWriteToAnInputOnlyStream 183 | paIncompatibleStreamHostApi = pa.paIncompatibleStreamHostApi 184 | 185 | ###### portaudio callback return codes ###### 186 | 187 | paContinue = pa.paContinue #: There is more audio data to come 188 | paComplete = pa.paComplete #: This was the last block of audio data 189 | paAbort = pa.paAbort #: An error ocurred, stop playback/recording 190 | 191 | ###### portaudio callback flags ###### 192 | 193 | paInputUnderflow = pa.paInputUnderflow #: Buffer underflow in input 194 | paInputOverflow = pa.paInputOverflow #: Buffer overflow in input 195 | paOutputUnderflow = pa.paOutputUnderflow #: Buffer underflow in output 196 | paOutputOverflow = pa.paOutputOverflow #: Buffer overflow in output 197 | paPrimingOutput = pa.paPrimingOutput #: Just priming, not playing yet 198 | 199 | ############################################################ 200 | # Convenience Functions 201 | ############################################################ 202 | 203 | def get_sample_size(format): 204 | """ 205 | Returns the size (in bytes) for the specified 206 | sample *format*. 207 | 208 | :param format: A |PaSampleFormat| constant. 209 | :raises ValueError: on invalid specified `format`. 210 | :rtype: integer 211 | """ 212 | 213 | return pa.get_sample_size(format) 214 | 215 | def get_format_from_width(width, unsigned=True): 216 | """ 217 | Returns a PortAudio format constant for the specified *width*. 218 | 219 | :param width: The desired sample width in bytes (1, 2, 3, or 4) 220 | :param unsigned: For 1 byte width, specifies signed or unsigned format. 221 | 222 | :raises ValueError: when invalid *width* 223 | :rtype: A |PaSampleFormat| constant 224 | """ 225 | 226 | if width == 1: 227 | if unsigned: 228 | return paUInt8 229 | else: 230 | return paInt8 231 | elif width == 2: 232 | return paInt16 233 | elif width == 3: 234 | return paInt24 235 | elif width == 4: 236 | return paFloat32 237 | else: 238 | raise ValueError("Invalid width: %d" % width) 239 | 240 | 241 | ############################################################ 242 | # Versioning 243 | ############################################################ 244 | 245 | def get_portaudio_version(): 246 | """ 247 | Returns portaudio version. 248 | 249 | :rtype: string 250 | """ 251 | 252 | return pa.get_version() 253 | 254 | def get_portaudio_version_text(): 255 | """ 256 | Returns PortAudio version as a text string. 257 | 258 | :rtype: string 259 | """ 260 | 261 | return pa.get_version_text() 262 | 263 | ############################################################ 264 | # Wrapper around _portaudio Stream (Internal) 265 | ############################################################ 266 | 267 | # Note: See PyAudio class below for main export. 268 | 269 | class Stream: 270 | """ 271 | PortAudio Stream Wrapper. Use :py:func:`PyAudio.open` to make a new 272 | :py:class:`Stream`. 273 | 274 | **Opening and Closing** 275 | :py:func:`__init__`, :py:func:`close` 276 | 277 | **Stream Info** 278 | :py:func:`get_input_latency`, :py:func:`get_output_latency`, 279 | :py:func:`get_time`, :py:func:`get_cpu_load` 280 | 281 | **Stream Management** 282 | :py:func:`start_stream`, :py:func:`stop_stream`, :py:func:`is_active`, 283 | :py:func:`is_stopped` 284 | 285 | **Input Output** 286 | :py:func:`write`, :py:func:`read`, :py:func:`get_read_available`, 287 | :py:func:`get_write_available` 288 | """ 289 | 290 | def __init__(self, 291 | PA_manager, 292 | rate, 293 | channels, 294 | format, 295 | input=False, 296 | output=False, 297 | input_device_index=None, 298 | output_device_index=None, 299 | frames_per_buffer=1024, 300 | start=True, 301 | input_host_api_specific_stream_info=None, 302 | output_host_api_specific_stream_info=None, 303 | stream_callback=None): 304 | """ 305 | Initialize a stream; this should be called by 306 | :py:func:`PyAudio.open`. A stream can either be input, output, 307 | or both. 308 | 309 | :param PA_manager: A reference to the managing :py:class:`PyAudio` 310 | instance 311 | :param rate: Sampling rate 312 | :param channels: Number of channels 313 | :param format: Sampling size and format. See |PaSampleFormat|. 314 | :param input: Specifies whether this is an input stream. 315 | Defaults to ``False``. 316 | :param output: Specifies whether this is an output stream. 317 | Defaults to ``False``. 318 | :param input_device_index: Index of Input Device to use. 319 | Unspecified (or ``None``) uses default device. 320 | Ignored if `input` is ``False``. 321 | :param output_device_index: 322 | Index of Output Device to use. 323 | Unspecified (or ``None``) uses the default device. 324 | Ignored if `output` is ``False``. 325 | :param frames_per_buffer: Specifies the number of frames per buffer. 326 | :param start: Start the stream running immediately. 327 | Defaults to ``True``. In general, there is no reason to set 328 | this to ``False``. 329 | :param input_host_api_specific_stream_info: Specifies a host API 330 | specific stream information data structure for input. 331 | 332 | .. only:: pamac 333 | 334 | See :py:class:`PaMacCoreStreamInfo`. 335 | 336 | :param output_host_api_specific_stream_info: Specifies a host API 337 | specific stream information data structure for output. 338 | 339 | .. only:: pamac 340 | 341 | See :py:class:`PaMacCoreStreamInfo`. 342 | 343 | :param stream_callback: Specifies a callback function for 344 | *non-blocking* (callback) operation. Default is 345 | ``None``, which indicates *blocking* operation (i.e., 346 | :py:func:`Stream.read` and :py:func:`Stream.write`). To use 347 | non-blocking operation, specify a callback that conforms 348 | to the following signature: 349 | 350 | .. code-block:: python 351 | 352 | callback(in_data, # recorded data if input=True; else None 353 | frame_count, # number of frames 354 | time_info, # dictionary 355 | status_flags) # PaCallbackFlags 356 | 357 | ``time_info`` is a dictionary with the following keys: 358 | ``input_buffer_adc_time``, ``current_time``, and 359 | ``output_buffer_dac_time``; see the PortAudio 360 | documentation for their meanings. ``status_flags`` is one 361 | of |PaCallbackFlags|. 362 | 363 | The callback must return a tuple: 364 | 365 | .. code-block:: python 366 | 367 | (out_data, flag) 368 | 369 | ``out_data`` is a byte array whose length should be the 370 | (``frame_count * channels * bytes-per-channel``) if 371 | ``output=True`` or ``None`` if ``output=False``. ``flag`` 372 | must be either :py:data:`paContinue`, :py:data:`paComplete` or 373 | :py:data:`paAbort` (one of |PaCallbackReturnCodes|). 374 | When ``output=True`` and ``out_data`` does not contain at 375 | least ``frame_count`` frames, :py:data:`paComplete` is 376 | assumed for ``flag``. 377 | 378 | **Note:** ``stream_callback`` is called in a separate 379 | thread (from the main thread). Exceptions that occur in 380 | the ``stream_callback`` will: 381 | 382 | 1. print a traceback on standard error to aid debugging, 383 | 2. queue the exception to be thrown (at some point) in 384 | the main thread, and 385 | 3. return `paAbort` to PortAudio to stop the stream. 386 | 387 | **Note:** Do not call :py:func:`Stream.read` or 388 | :py:func:`Stream.write` if using non-blocking operation. 389 | 390 | **See:** PortAudio's callback signature for additional 391 | details: http://portaudio.com/docs/v19-doxydocs/portaudio_8h.html#a8a60fb2a5ec9cbade3f54a9c978e2710 392 | 393 | :raise ValueError: Neither input nor output are set True. 394 | """ 395 | 396 | # no stupidity allowed 397 | if not (input or output): 398 | raise ValueError("Must specify an input or output " + "stream.") 399 | 400 | # remember parent 401 | self._parent = PA_manager 402 | 403 | # remember if we are an: input, output (or both) 404 | self._is_input = input 405 | self._is_output = output 406 | 407 | # are we running? 408 | self._is_running = start 409 | 410 | # remember some parameters 411 | self._rate = rate 412 | self._channels = channels 413 | self._format = format 414 | self._frames_per_buffer = frames_per_buffer 415 | 416 | arguments = { 417 | 'rate' : rate, 418 | 'channels' : channels, 419 | 'format' : format, 420 | 'input' : input, 421 | 'output' : output, 422 | 'input_device_index' : input_device_index, 423 | 'output_device_index' : output_device_index, 424 | 'frames_per_buffer' : frames_per_buffer} 425 | 426 | if input_host_api_specific_stream_info: 427 | _l = input_host_api_specific_stream_info 428 | arguments[ 429 | 'input_host_api_specific_stream_info' 430 | ] = _l._get_host_api_stream_object() 431 | 432 | if output_host_api_specific_stream_info: 433 | _l = output_host_api_specific_stream_info 434 | arguments[ 435 | 'output_host_api_specific_stream_info' 436 | ] = _l._get_host_api_stream_object() 437 | 438 | if stream_callback: 439 | arguments['stream_callback'] = stream_callback 440 | 441 | # calling pa.open returns a stream object 442 | self._stream = pa.open(**arguments) 443 | 444 | self._input_latency = self._stream.inputLatency 445 | self._output_latency = self._stream.outputLatency 446 | 447 | if self._is_running: 448 | pa.start_stream(self._stream) 449 | 450 | def close(self): 451 | """ Close the stream """ 452 | 453 | pa.close(self._stream) 454 | 455 | self._is_running = False 456 | 457 | self._parent._remove_stream(self) 458 | 459 | 460 | ############################################################ 461 | # Stream Info 462 | ############################################################ 463 | 464 | def get_input_latency(self): 465 | """ 466 | Return the input latency. 467 | 468 | :rtype: float 469 | """ 470 | 471 | return self._stream.inputLatency 472 | 473 | def get_output_latency(self): 474 | """ 475 | Return the input latency. 476 | 477 | :rtype: float 478 | """ 479 | 480 | return self._stream.outputLatency 481 | 482 | def get_time(self): 483 | """ 484 | Return stream time. 485 | 486 | :rtype: float 487 | """ 488 | 489 | return pa.get_stream_time(self._stream) 490 | 491 | def get_cpu_load(self): 492 | """ 493 | Return the CPU load. This is always 0.0 for the 494 | blocking API. 495 | 496 | :rtype: float 497 | """ 498 | 499 | return pa.get_stream_cpu_load(self._stream) 500 | 501 | 502 | ############################################################ 503 | # Stream Management 504 | ############################################################ 505 | 506 | def start_stream(self): 507 | """ Start the stream. """ 508 | 509 | if self._is_running: 510 | return 511 | 512 | pa.start_stream(self._stream) 513 | self._is_running = True 514 | 515 | def stop_stream(self): 516 | """ 517 | Stop the stream. Once the stream is stopped, one may not call 518 | write or read. Call :py:func:`start_stream` to resume the 519 | stream. 520 | """ 521 | 522 | if not self._is_running: 523 | return 524 | 525 | pa.stop_stream(self._stream) 526 | self._is_running = False 527 | 528 | def is_active(self): 529 | """ 530 | Returns whether the stream is active. 531 | 532 | :rtype: bool 533 | """ 534 | 535 | return pa.is_stream_active(self._stream) 536 | 537 | def is_stopped(self): 538 | """ 539 | Returns whether the stream is stopped. 540 | 541 | :rtype: bool 542 | """ 543 | 544 | return pa.is_stream_stopped(self._stream) 545 | 546 | 547 | ############################################################ 548 | # Reading/Writing 549 | ############################################################ 550 | 551 | def write(self, frames, num_frames=None, 552 | exception_on_underflow=False): 553 | 554 | """ 555 | Write samples to the stream. Do not call when using 556 | *non-blocking* mode. 557 | 558 | :param frames: 559 | The frames of data. 560 | :param num_frames: 561 | The number of frames to write. 562 | Defaults to None, in which this value will be 563 | automatically computed. 564 | :param exception_on_underflow: 565 | Specifies whether an exception should be thrown 566 | (or silently ignored) on buffer underflow. Defaults 567 | to False for improved performance, especially on 568 | slower platforms. 569 | 570 | :raises IOError: if the stream is not an output stream 571 | or if the write operation was unsuccessful. 572 | 573 | :rtype: `None` 574 | """ 575 | 576 | if not self._is_output: 577 | raise IOError("Not output stream", 578 | paCanNotWriteToAnInputOnlyStream) 579 | 580 | if num_frames == None: 581 | # determine how many frames to read 582 | width = get_sample_size(self._format) 583 | num_frames = int(len(frames) / (self._channels * width)) 584 | #print len(frames), self._channels, self._width, num_frames 585 | 586 | pa.write_stream(self._stream, frames, num_frames, 587 | exception_on_underflow) 588 | 589 | 590 | def read(self, num_frames, should_warn=False): 591 | """ 592 | Read samples from the stream. Do not call when using 593 | *non-blocking* mode. 594 | 595 | :param num_frames: 596 | The number of frames to read. 597 | :param should_warn: 598 | Specifies whether a warning should be written to stderr (or silently 599 | ignored) on buffer overflow. Defaults to False. 600 | 601 | :raises IOError: if stream is not an input stream 602 | or if the read operation was unsuccessful. 603 | 604 | :rtype: string 605 | """ 606 | 607 | if not self._is_input: 608 | raise IOError("Not input stream", 609 | paCanNotReadFromAnOutputOnlyStream) 610 | 611 | return pa.read_stream(self._stream, num_frames, should_warn) 612 | 613 | def get_read_available(self): 614 | """ 615 | Return the number of frames that can be read without waiting. 616 | 617 | :rtype: integer 618 | """ 619 | 620 | return pa.get_stream_read_available(self._stream) 621 | 622 | 623 | def get_write_available(self): 624 | """ 625 | Return the number of frames that can be written without 626 | waiting. 627 | 628 | :rtype: integer 629 | 630 | """ 631 | 632 | return pa.get_stream_write_available(self._stream) 633 | 634 | 635 | 636 | ############################################################ 637 | # Main Export 638 | ############################################################ 639 | 640 | class PyAudio: 641 | 642 | """ 643 | Python interface to PortAudio. Provides methods to: 644 | - initialize and terminate PortAudio 645 | - open and close streams 646 | - query and inspect the available PortAudio Host APIs 647 | - query and inspect the available PortAudio audio 648 | devices 649 | 650 | Use this class to open and close streams. 651 | 652 | **Stream Management** 653 | :py:func:`open`, :py:func:`close` 654 | 655 | **Host API** 656 | :py:func:`get_host_api_count`, :py:func:`get_default_host_api_info`, 657 | :py:func:`get_host_api_info_by_type`, 658 | :py:func:`get_host_api_info_by_index`, 659 | :py:func:`get_device_info_by_host_api_device_index` 660 | 661 | **Device API** 662 | :py:func:`get_device_count`, :py:func:`is_format_supported`, 663 | :py:func:`get_default_input_device_info`, 664 | :py:func:`get_default_output_device_info`, 665 | :py:func:`get_device_info_by_index` 666 | 667 | **Stream Format Conversion** 668 | :py:func:`get_sample_size`, :py:func:`get_format_from_width` 669 | 670 | **Details** 671 | """ 672 | 673 | ############################################################ 674 | # Initialization and Termination 675 | ############################################################ 676 | 677 | def __init__(self): 678 | """Initialize PortAudio.""" 679 | 680 | pa.initialize() 681 | self._streams = set() 682 | 683 | def terminate(self): 684 | """ 685 | Terminate PortAudio. 686 | 687 | :attention: Be sure to call this method for every instance of 688 | this object to release PortAudio resources. 689 | """ 690 | 691 | for stream in self._streams.copy(): 692 | stream.close() 693 | 694 | self._streams = set() 695 | 696 | pa.terminate() 697 | 698 | 699 | ############################################################ 700 | # Stream Format 701 | ############################################################ 702 | 703 | def get_sample_size(self, format): 704 | """ 705 | Returns the size (in bytes) for the specified 706 | sample `format` (a |PaSampleFormat| constant). 707 | 708 | :param format: A |PaSampleFormat| constant. 709 | :raises ValueError: Invalid specified `format`. 710 | :rtype: integer 711 | """ 712 | 713 | return pa.get_sample_size(format) 714 | 715 | def get_format_from_width(self, width, unsigned=True): 716 | """ 717 | Returns a PortAudio format constant for the specified `width`. 718 | 719 | :param width: The desired sample width in bytes (1, 2, 3, or 4) 720 | :param unsigned: For 1 byte width, specifies signed or unsigned format. 721 | 722 | :raises ValueError: for invalid `width` 723 | :rtype: A |PaSampleFormat| constant. 724 | """ 725 | 726 | if width == 1: 727 | if unsigned: 728 | return paUInt8 729 | else: 730 | return paInt8 731 | elif width == 2: 732 | return paInt16 733 | elif width == 3: 734 | return paInt24 735 | elif width == 4: 736 | return paFloat32 737 | else: 738 | raise ValueError("Invalid width: %d" % width) 739 | 740 | 741 | ############################################################ 742 | # Stream Factory 743 | ############################################################ 744 | 745 | def open(self, *args, **kwargs): 746 | """ 747 | Open a new stream. See constructor for 748 | :py:func:`Stream.__init__` for parameter details. 749 | 750 | :returns: A new :py:class:`Stream` 751 | """ 752 | 753 | stream = Stream(self, *args, **kwargs) 754 | self._streams.add(stream) 755 | return stream 756 | 757 | def close(self, stream): 758 | """ 759 | Close a stream. Typically use :py:func:`Stream.close` instead. 760 | 761 | :param stream: An instance of the :py:class:`Stream` object. 762 | :raises ValueError: if stream does not exist. 763 | """ 764 | 765 | if stream not in self._streams: 766 | raise ValueError("Stream `%s' not found" % str(stream)) 767 | 768 | stream.close() 769 | 770 | def _remove_stream(self, stream): 771 | """ 772 | Internal method. Removes a stream. 773 | 774 | :param stream: An instance of the :py:class:`Stream` object. 775 | """ 776 | 777 | if stream in self._streams: 778 | self._streams.remove(stream) 779 | 780 | 781 | ############################################################ 782 | # Host API Inspection 783 | ############################################################ 784 | 785 | def get_host_api_count(self): 786 | """ 787 | Return the number of available PortAudio Host APIs. 788 | 789 | :rtype: integer 790 | """ 791 | 792 | return pa.get_host_api_count() 793 | 794 | def get_default_host_api_info(self): 795 | """ 796 | Return a dictionary containing the default Host API 797 | parameters. The keys of the dictionary mirror the data fields 798 | of PortAudio's ``PaHostApiInfo`` structure. 799 | 800 | :raises IOError: if no default input device is available 801 | :rtype: dict 802 | """ 803 | 804 | defaultHostApiIndex = pa.get_default_host_api() 805 | return self.get_host_api_info_by_index(defaultHostApiIndex) 806 | 807 | def get_host_api_info_by_type(self, host_api_type): 808 | """ 809 | Return a dictionary containing the Host API parameters for the 810 | host API specified by the `host_api_type`. The keys of the 811 | dictionary mirror the data fields of PortAudio's ``PaHostApiInfo`` 812 | structure. 813 | 814 | :param host_api_type: The desired |PaHostAPI| 815 | :raises IOError: for invalid `host_api_type` 816 | :rtype: dict 817 | """ 818 | 819 | index = pa.host_api_type_id_to_host_api_index(host_api_type) 820 | return self.get_host_api_info_by_index(index) 821 | 822 | def get_host_api_info_by_index(self, host_api_index): 823 | """ 824 | Return a dictionary containing the Host API parameters for the 825 | host API specified by the `host_api_index`. The keys of the 826 | dictionary mirror the data fields of PortAudio's ``PaHostApiInfo`` 827 | structure. 828 | 829 | :param host_api_index: The host api index 830 | :raises IOError: for invalid `host_api_index` 831 | :rtype: dict 832 | """ 833 | 834 | return self._make_host_api_dictionary( 835 | host_api_index, 836 | pa.get_host_api_info(host_api_index) 837 | ) 838 | 839 | def get_device_info_by_host_api_device_index(self, 840 | host_api_index, 841 | host_api_device_index): 842 | """ 843 | Return a dictionary containing the Device parameters for a 844 | given Host API's n'th device. The keys of the dictionary 845 | mirror the data fields of PortAudio's ``PaDeviceInfo`` structure. 846 | 847 | :param host_api_index: The Host API index number 848 | :param host_api_device_index: The n'th device of the host API 849 | :raises IOError: for invalid indices 850 | :rtype: dict 851 | """ 852 | 853 | long_method_name = pa.host_api_device_index_to_device_index 854 | device_index = long_method_name(host_api_index, 855 | host_api_device_index) 856 | return self.get_device_info_by_index(device_index) 857 | 858 | def _make_host_api_dictionary(self, index, host_api_struct): 859 | """ 860 | Internal method to create Host API dictionary that mirrors 861 | PortAudio's ``PaHostApiInfo`` structure. 862 | 863 | :rtype: dict 864 | """ 865 | 866 | return {'index' : index, 867 | 'structVersion' : host_api_struct.structVersion, 868 | 'type' : host_api_struct.type, 869 | 'name' : host_api_struct.name, 870 | 'deviceCount' : host_api_struct.deviceCount, 871 | 'defaultInputDevice' : host_api_struct.defaultInputDevice, 872 | 'defaultOutputDevice' : host_api_struct.defaultOutputDevice} 873 | 874 | 875 | ############################################################ 876 | # Device Inspection 877 | ############################################################ 878 | 879 | def get_device_count(self): 880 | """ 881 | Return the number of PortAudio Host APIs. 882 | 883 | :rtype: integer 884 | """ 885 | 886 | return pa.get_device_count() 887 | 888 | def is_format_supported(self, rate, 889 | input_device=None, 890 | input_channels=None, 891 | input_format=None, 892 | output_device=None, 893 | output_channels=None, 894 | output_format=None): 895 | """ 896 | Check to see if specified device configuration 897 | is supported. Returns True if the configuration 898 | is supported; throws a ValueError exception otherwise. 899 | 900 | :param rate: 901 | Specifies the desired rate (in Hz) 902 | :param input_device: 903 | The input device index. Specify ``None`` (default) for 904 | half-duplex output-only streams. 905 | :param input_channels: 906 | The desired number of input channels. Ignored if 907 | `input_device` is not specified (or ``None``). 908 | :param input_format: 909 | PortAudio sample format constant defined 910 | in this module 911 | :param output_device: 912 | The output device index. Specify ``None`` (default) for 913 | half-duplex input-only streams. 914 | :param output_channels: 915 | The desired number of output channels. Ignored if 916 | `input_device` is not specified (or ``None``). 917 | :param output_format: 918 | |PaSampleFormat| constant. 919 | 920 | :rtype: bool 921 | :raises ValueError: tuple containing (error string, |PaErrorCode|). 922 | """ 923 | 924 | if input_device == None and output_device == None: 925 | raise ValueError("must specify stream format for input, " +\ 926 | "output, or both", paInvalidDevice); 927 | 928 | kwargs = {} 929 | 930 | if input_device != None: 931 | kwargs['input_device'] = input_device 932 | kwargs['input_channels'] = input_channels 933 | kwargs['input_format'] = input_format 934 | 935 | if output_device != None: 936 | kwargs['output_device'] = output_device 937 | kwargs['output_channels'] = output_channels 938 | kwargs['output_format'] = output_format 939 | 940 | return pa.is_format_supported(rate, **kwargs) 941 | 942 | def get_default_input_device_info(self): 943 | """ 944 | Return the default input Device parameters as a 945 | dictionary. The keys of the dictionary mirror the data fields 946 | of PortAudio's ``PaDeviceInfo`` structure. 947 | 948 | :raises IOError: No default input device available. 949 | :rtype: dict 950 | """ 951 | 952 | device_index = pa.get_default_input_device() 953 | return self.get_device_info_by_index(device_index) 954 | 955 | def get_default_output_device_info(self): 956 | """ 957 | Return the default output Device parameters as a 958 | dictionary. The keys of the dictionary mirror the data fields 959 | of PortAudio's ``PaDeviceInfo`` structure. 960 | 961 | :raises IOError: No default output device available. 962 | :rtype: dict 963 | """ 964 | 965 | device_index = pa.get_default_output_device() 966 | return self.get_device_info_by_index(device_index) 967 | 968 | 969 | def get_device_info_by_index(self, device_index): 970 | """ 971 | Return the Device parameters for device specified in 972 | `device_index` as a dictionary. The keys of the dictionary 973 | mirror the data fields of PortAudio's ``PaDeviceInfo`` 974 | structure. 975 | 976 | :param device_index: The device index 977 | :raises IOError: Invalid `device_index`. 978 | :rtype: dict 979 | """ 980 | 981 | return self._make_device_info_dictionary( 982 | device_index, 983 | pa.get_device_info(device_index) 984 | ) 985 | 986 | def _make_device_info_dictionary(self, index, device_info): 987 | """ 988 | Internal method to create Device Info dictionary that mirrors 989 | PortAudio's ``PaDeviceInfo`` structure. 990 | 991 | :rtype: dict 992 | """ 993 | 994 | device_name = device_info.name 995 | 996 | # Attempt to decode device_name 997 | for codec in ["utf-8", "cp1252"]: 998 | try: 999 | device_name = device_name.decode(codec) 1000 | break 1001 | except: 1002 | pass 1003 | 1004 | # If we fail to decode, we return the raw bytes and let the caller 1005 | # deal with the encoding. 1006 | return {'index' : index, 1007 | 'structVersion' : device_info.structVersion, 1008 | 'name' : device_name, 1009 | 'hostApi' : device_info.hostApi, 1010 | 'maxInputChannels' : device_info.maxInputChannels, 1011 | 'maxOutputChannels' : device_info.maxOutputChannels, 1012 | 'defaultLowInputLatency' : 1013 | device_info.defaultLowInputLatency, 1014 | 'defaultLowOutputLatency' : 1015 | device_info.defaultLowOutputLatency, 1016 | 'defaultHighInputLatency' : 1017 | device_info.defaultHighInputLatency, 1018 | 'defaultHighOutputLatency' : 1019 | device_info.defaultHighOutputLatency, 1020 | 'defaultSampleRate' : 1021 | device_info.defaultSampleRate 1022 | } 1023 | 1024 | 1025 | ###################################################################### 1026 | # Host Specific Stream Info 1027 | ###################################################################### 1028 | 1029 | try: 1030 | paMacCoreStreamInfo = pa.paMacCoreStreamInfo 1031 | except AttributeError: 1032 | pass 1033 | else: 1034 | class PaMacCoreStreamInfo: 1035 | """ 1036 | Mac OS X-only: PaMacCoreStreamInfo is a PortAudio Host API 1037 | Specific Stream Info data structure for specifying Mac OS 1038 | X-only settings. Instantiate this class (if desired) and pass 1039 | the instance as the argument in :py:func:`PyAudio.open` to parameters 1040 | ``input_host_api_specific_stream_info`` or 1041 | ``output_host_api_specific_stream_info``. 1042 | (See :py:func:`Stream.__init__`.) 1043 | 1044 | :note: Mac OS X only. 1045 | 1046 | .. |PaMacCoreFlags| replace:: :ref:`PortAudio Mac Core Flags ` 1047 | .. _PaMacCoreFlags: 1048 | 1049 | **PortAudio Mac Core Flags** 1050 | :py:data:`paMacCoreChangeDeviceParameters`, 1051 | :py:data:`paMacCoreFailIfConversionRequired`, 1052 | :py:data:`paMacCoreConversionQualityMin`, 1053 | :py:data:`paMacCoreConversionQualityMedium`, 1054 | :py:data:`paMacCoreConversionQualityLow`, 1055 | :py:data:`paMacCoreConversionQualityHigh`, 1056 | :py:data:`paMacCoreConversionQualityMax`, 1057 | :py:data:`paMacCorePlayNice`, 1058 | :py:data:`paMacCorePro`, 1059 | :py:data:`paMacCoreMinimizeCPUButPlayNice`, 1060 | :py:data:`paMacCoreMinimizeCPU` 1061 | 1062 | **Settings** 1063 | :py:func:`get_flags`, :py:func:`get_channel_map` 1064 | """ 1065 | 1066 | paMacCoreChangeDeviceParameters = pa.paMacCoreChangeDeviceParameters 1067 | paMacCoreFailIfConversionRequired = pa.paMacCoreFailIfConversionRequired 1068 | paMacCoreConversionQualityMin = pa.paMacCoreConversionQualityMin 1069 | paMacCoreConversionQualityMedium = pa.paMacCoreConversionQualityMedium 1070 | paMacCoreConversionQualityLow = pa.paMacCoreConversionQualityLow 1071 | paMacCoreConversionQualityHigh = pa.paMacCoreConversionQualityHigh 1072 | paMacCoreConversionQualityMax = pa.paMacCoreConversionQualityMax 1073 | paMacCorePlayNice = pa.paMacCorePlayNice 1074 | paMacCorePro = pa.paMacCorePro 1075 | paMacCoreMinimizeCPUButPlayNice = pa.paMacCoreMinimizeCPUButPlayNice 1076 | paMacCoreMinimizeCPU = pa.paMacCoreMinimizeCPU 1077 | 1078 | def __init__(self, flags=None, channel_map=None): 1079 | """ 1080 | Initialize with flags and channel_map. See PortAudio 1081 | documentation for more details on these parameters; they are 1082 | passed almost verbatim to the PortAudio library. 1083 | 1084 | :param flags: |PaMacCoreFlags| OR'ed together. 1085 | See :py:class:`PaMacCoreStreamInfo`. 1086 | :param channel_map: An array describing the channel mapping. 1087 | See PortAudio documentation for usage. 1088 | """ 1089 | 1090 | kwargs = {"flags" : flags, 1091 | "channel_map" : channel_map} 1092 | 1093 | if flags == None: 1094 | del kwargs["flags"] 1095 | if channel_map == None: 1096 | del kwargs["channel_map"] 1097 | 1098 | self._paMacCoreStreamInfo = paMacCoreStreamInfo(**kwargs) 1099 | 1100 | def get_flags(self): 1101 | """ 1102 | Return the flags set at instantiation. 1103 | 1104 | :rtype: integer 1105 | """ 1106 | 1107 | return self._paMacCoreStreamInfo.flags 1108 | 1109 | def get_channel_map(self): 1110 | """ 1111 | Return the channel map set at instantiation. 1112 | 1113 | :rtype: tuple or None 1114 | """ 1115 | 1116 | return self._paMacCoreStreamInfo.channel_map 1117 | 1118 | def _get_host_api_stream_object(self): 1119 | """Private method.""" 1120 | 1121 | return self._paMacCoreStreamInfo 1122 | -------------------------------------------------------------------------------- /src/_portaudiomodule.c: -------------------------------------------------------------------------------- 1 | /** 2 | * PyAudio: Python Bindings for PortAudio. 3 | * 4 | * Copyright (c) 2006-2012 Hubert Pham 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, copy, 10 | * modify, merge, publish, distribute, sublicense, and/or sell copies 11 | * of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 21 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 22 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | * SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include "Python.h" 29 | #include "portaudio.h" 30 | #include "_portaudiomodule.h" 31 | 32 | #ifdef MACOSX 33 | #include "pa_mac_core.h" 34 | #endif 35 | 36 | #define DEFAULT_FRAMES_PER_BUFFER 1024 37 | /* #define VERBOSE */ 38 | 39 | #define min(a,b) \ 40 | ({ __typeof__ (a) _a = (a); \ 41 | __typeof__ (b) _b = (b); \ 42 | _a < _b ? _a : _b; }) 43 | 44 | /************************************************************ 45 | * 46 | * Table of Contents 47 | * 48 | * I. Exportable PortAudio Method Definitions 49 | * II. Python Object Wrappers 50 | * - PaDeviceInfo 51 | * - PaHostInfo 52 | * - PaStream 53 | * III. PortAudio Method Implementations 54 | * - Initialization/Termination 55 | * - HostAPI 56 | * - DeviceAPI 57 | * - Stream Open/Close 58 | * - Stream Start/Stop/Info 59 | * - Stream Read/Write 60 | * IV. Python Module Init 61 | * - PaHostApiTypeId enum constants 62 | * 63 | ************************************************************/ 64 | 65 | 66 | /************************************************************ 67 | * 68 | * I. Exportable Python Methods 69 | * 70 | ************************************************************/ 71 | 72 | static PyMethodDef paMethods[] = { 73 | 74 | /* version */ 75 | {"get_version", pa_get_version, METH_VARARGS, "get version"}, 76 | {"get_version_text", pa_get_version_text, METH_VARARGS, 77 | "get version text"}, 78 | 79 | /* inits */ 80 | {"initialize", pa_initialize, METH_VARARGS, "initialize portaudio"}, 81 | {"terminate", pa_terminate, METH_VARARGS, "terminate portaudio"}, 82 | 83 | /* host api */ 84 | {"get_host_api_count", pa_get_host_api_count, METH_VARARGS, 85 | "get host API count"}, 86 | 87 | {"get_default_host_api", pa_get_default_host_api, METH_VARARGS, 88 | "get default host API index"}, 89 | 90 | {"host_api_type_id_to_host_api_index", 91 | pa_host_api_type_id_to_host_api_index, METH_VARARGS, 92 | "get default host API index"}, 93 | 94 | {"host_api_device_index_to_device_index", 95 | pa_host_api_device_index_to_device_index, 96 | METH_VARARGS, 97 | "get default host API index"}, 98 | 99 | {"get_host_api_info", pa_get_host_api_info, METH_VARARGS, 100 | "get host api information"}, 101 | 102 | /* device api */ 103 | {"get_device_count", pa_get_device_count, METH_VARARGS, 104 | "get host API count"}, 105 | 106 | {"get_default_input_device", pa_get_default_input_device, METH_VARARGS, 107 | "get default input device index"}, 108 | 109 | {"get_default_output_device", pa_get_default_output_device, METH_VARARGS, 110 | "get default output device index"}, 111 | 112 | {"get_device_info", pa_get_device_info, METH_VARARGS, 113 | "get device information"}, 114 | 115 | /* stream open/close */ 116 | {"open", (PyCFunction) pa_open, METH_VARARGS | METH_KEYWORDS, 117 | "open port audio stream"}, 118 | {"close", pa_close, METH_VARARGS, "close port audio stream"}, 119 | {"get_sample_size", pa_get_sample_size, METH_VARARGS, 120 | "get sample size of a format in bytes"}, 121 | {"is_format_supported", (PyCFunction) pa_is_format_supported, 122 | METH_VARARGS | METH_KEYWORDS, 123 | "returns whether specified format is supported"}, 124 | 125 | /* stream start/stop */ 126 | {"start_stream", pa_start_stream, METH_VARARGS, "starts port audio stream"}, 127 | {"stop_stream", pa_stop_stream, METH_VARARGS, "stops port audio stream"}, 128 | {"abort_stream", pa_abort_stream, METH_VARARGS, "aborts port audio stream"}, 129 | {"is_stream_stopped", pa_is_stream_stopped, METH_VARARGS, 130 | "returns whether stream is stopped"}, 131 | {"is_stream_active", pa_is_stream_active, METH_VARARGS, 132 | "returns whether stream is active"}, 133 | {"get_stream_time", pa_get_stream_time, METH_VARARGS, 134 | "returns stream time"}, 135 | {"get_stream_cpu_load", pa_get_stream_cpu_load, METH_VARARGS, 136 | "returns stream CPU load -- always 0 for blocking mode"}, 137 | 138 | /* stream read/write */ 139 | {"write_stream", pa_write_stream, METH_VARARGS, "write to stream"}, 140 | {"read_stream", pa_read_stream, METH_VARARGS, "read from stream"}, 141 | 142 | {"get_stream_write_available", 143 | pa_get_stream_write_available, METH_VARARGS, 144 | "get buffer available for writing"}, 145 | 146 | {"get_stream_read_available", 147 | pa_get_stream_read_available, METH_VARARGS, 148 | "get buffer available for reading"}, 149 | 150 | {NULL, NULL, 0, NULL} 151 | }; 152 | 153 | 154 | /************************************************************ 155 | * 156 | * II. Python Object Wrappers 157 | * 158 | ************************************************************/ 159 | 160 | 161 | /************************************************************* 162 | * PaDeviceInfo Type : Python object wrapper for PaDeviceInfo 163 | *************************************************************/ 164 | 165 | typedef struct { 166 | PyObject_HEAD 167 | PaDeviceInfo *devInfo; 168 | } _pyAudio_paDeviceInfo; 169 | 170 | 171 | /* sepcific getters into the PaDeviceInfo struct */ 172 | 173 | static PyObject * 174 | _pyAudio_paDeviceInfo_get_structVersion(_pyAudio_paDeviceInfo *self, 175 | void *closure) 176 | { 177 | /* sanity check */ 178 | if (!self->devInfo) { 179 | PyErr_SetString(PyExc_AttributeError, 180 | "No Device Info available"); 181 | return NULL; 182 | } 183 | 184 | return PyLong_FromLong(self->devInfo->structVersion); 185 | } 186 | 187 | static PyObject * 188 | _pyAudio_paDeviceInfo_get_name(_pyAudio_paDeviceInfo *self, 189 | void *closure) 190 | { 191 | /* sanity check */ 192 | if ((!self->devInfo) || (self->devInfo->name == NULL)) { 193 | PyErr_SetString(PyExc_AttributeError, 194 | "No Device Info available"); 195 | return NULL; 196 | } 197 | 198 | return PyBytes_FromString(self->devInfo->name); 199 | } 200 | 201 | static PyObject * 202 | _pyAudio_paDeviceInfo_get_hostApi(_pyAudio_paDeviceInfo *self, 203 | void *closure) 204 | { 205 | /* sanity check */ 206 | if (!self->devInfo) { 207 | PyErr_SetString(PyExc_AttributeError, 208 | "No Device Info available"); 209 | return NULL; 210 | } 211 | 212 | return PyLong_FromLong(self->devInfo->hostApi); 213 | } 214 | 215 | static PyObject * 216 | _pyAudio_paDeviceInfo_get_maxInputChannels(_pyAudio_paDeviceInfo *self, 217 | void *closure) 218 | { 219 | /* sanity check */ 220 | if (!self->devInfo) { 221 | PyErr_SetString(PyExc_AttributeError, 222 | "No Device Info available"); 223 | return NULL; 224 | } 225 | 226 | return PyLong_FromLong(self->devInfo->maxInputChannels); 227 | } 228 | 229 | static PyObject * 230 | _pyAudio_paDeviceInfo_get_maxOutputChannels(_pyAudio_paDeviceInfo *self, 231 | void *closure) 232 | { 233 | /* sanity check */ 234 | if (!self->devInfo) { 235 | PyErr_SetString(PyExc_AttributeError, 236 | "No Device Info available"); 237 | return NULL; 238 | } 239 | 240 | return PyLong_FromLong(self->devInfo->maxOutputChannels); 241 | } 242 | 243 | static PyObject * 244 | _pyAudio_paDeviceInfo_get_defaultLowInputLatency(_pyAudio_paDeviceInfo *self, 245 | void *closure) 246 | { 247 | /* sanity check */ 248 | if (!self->devInfo) { 249 | PyErr_SetString(PyExc_AttributeError, 250 | "No Device Info available"); 251 | return NULL; 252 | } 253 | 254 | return PyFloat_FromDouble(self->devInfo->defaultLowInputLatency); 255 | } 256 | 257 | static PyObject * 258 | _pyAudio_paDeviceInfo_get_defaultLowOutputLatency(_pyAudio_paDeviceInfo *self, 259 | void *closure) 260 | { 261 | /* sanity check */ 262 | if (!self->devInfo) { 263 | PyErr_SetString(PyExc_AttributeError, 264 | "No Device Info available"); 265 | return NULL; 266 | } 267 | 268 | return PyFloat_FromDouble(self->devInfo->defaultLowOutputLatency); 269 | } 270 | 271 | 272 | static PyObject * 273 | _pyAudio_paDeviceInfo_get_defaultHighInputLatency(_pyAudio_paDeviceInfo *self, 274 | void *closure) 275 | { 276 | /* sanity check */ 277 | if (!self->devInfo) { 278 | PyErr_SetString(PyExc_AttributeError, 279 | "No Device Info available"); 280 | return NULL; 281 | } 282 | 283 | return PyFloat_FromDouble(self->devInfo->defaultHighInputLatency); 284 | } 285 | 286 | static PyObject * 287 | _pyAudio_paDeviceInfo_get_defaultHighOutputLatency(_pyAudio_paDeviceInfo *self, 288 | void *closure) 289 | { 290 | /* sanity check */ 291 | if (!self->devInfo) { 292 | PyErr_SetString(PyExc_AttributeError, 293 | "No Device Info available"); 294 | return NULL; 295 | } 296 | 297 | return PyFloat_FromDouble(self->devInfo->defaultHighOutputLatency); 298 | } 299 | 300 | static PyObject * 301 | _pyAudio_paDeviceInfo_get_defaultSampleRate(_pyAudio_paDeviceInfo *self, 302 | void *closure) 303 | { 304 | /* sanity check */ 305 | if (!self->devInfo) { 306 | PyErr_SetString(PyExc_AttributeError, 307 | "No Device Info available"); 308 | return NULL; 309 | } 310 | 311 | return PyFloat_FromDouble(self->devInfo->defaultSampleRate); 312 | } 313 | 314 | 315 | 316 | static int 317 | _pyAudio_paDeviceInfo_antiset(_pyAudio_paDeviceInfo *self, 318 | PyObject *value, 319 | void *closure) 320 | { 321 | /* read-only: do not allow users to change values */ 322 | PyErr_SetString(PyExc_AttributeError, 323 | "Fields read-only: cannot modify values"); 324 | return -1; 325 | } 326 | 327 | static PyGetSetDef _pyAudio_paDeviceInfo_getseters[] = { 328 | {"name", 329 | (getter) _pyAudio_paDeviceInfo_get_name, 330 | (setter) _pyAudio_paDeviceInfo_antiset, 331 | "device name", 332 | NULL}, 333 | 334 | {"structVersion", 335 | (getter) _pyAudio_paDeviceInfo_get_structVersion, 336 | (setter) _pyAudio_paDeviceInfo_antiset, 337 | "struct version", 338 | NULL}, 339 | 340 | {"hostApi", 341 | (getter) _pyAudio_paDeviceInfo_get_hostApi, 342 | (setter) _pyAudio_paDeviceInfo_antiset, 343 | "host api index", 344 | NULL}, 345 | 346 | {"maxInputChannels", 347 | (getter) _pyAudio_paDeviceInfo_get_maxInputChannels, 348 | (setter) _pyAudio_paDeviceInfo_antiset, 349 | "max input channels", 350 | NULL}, 351 | 352 | {"maxOutputChannels", 353 | (getter) _pyAudio_paDeviceInfo_get_maxOutputChannels, 354 | (setter) _pyAudio_paDeviceInfo_antiset, 355 | "max output channels", 356 | NULL}, 357 | 358 | {"defaultLowInputLatency", 359 | (getter) _pyAudio_paDeviceInfo_get_defaultLowInputLatency, 360 | (setter) _pyAudio_paDeviceInfo_antiset, 361 | "default low input latency", 362 | NULL}, 363 | 364 | {"defaultLowOutputLatency", 365 | (getter) _pyAudio_paDeviceInfo_get_defaultLowOutputLatency, 366 | (setter) _pyAudio_paDeviceInfo_antiset, 367 | "default low output latency", 368 | NULL}, 369 | 370 | {"defaultHighInputLatency", 371 | (getter) _pyAudio_paDeviceInfo_get_defaultHighInputLatency, 372 | (setter) _pyAudio_paDeviceInfo_antiset, 373 | "default high input latency", 374 | NULL}, 375 | 376 | {"defaultHighOutputLatency", 377 | (getter) _pyAudio_paDeviceInfo_get_defaultHighOutputLatency, 378 | (setter) _pyAudio_paDeviceInfo_antiset, 379 | "default high output latency", 380 | NULL}, 381 | 382 | {"defaultSampleRate", 383 | (getter) _pyAudio_paDeviceInfo_get_defaultSampleRate, 384 | (setter) _pyAudio_paDeviceInfo_antiset, 385 | "default sample rate", 386 | NULL}, 387 | 388 | {NULL} 389 | }; 390 | 391 | static void 392 | _pyAudio_paDeviceInfo_dealloc(_pyAudio_paDeviceInfo* self) 393 | { 394 | /* reset the pointer */ 395 | self->devInfo = NULL; 396 | 397 | /* free the object */ 398 | Py_TYPE(self)->tp_free((PyObject*) self); 399 | } 400 | 401 | static PyTypeObject _pyAudio_paDeviceInfoType = { 402 | PyVarObject_HEAD_INIT(NULL, 0) 403 | "_portaudio.paDeviceInfo", /*tp_name*/ 404 | sizeof(_pyAudio_paDeviceInfo), /*tp_basicsize*/ 405 | 0, /*tp_itemsize*/ 406 | (destructor) _pyAudio_paDeviceInfo_dealloc, /*tp_dealloc*/ 407 | 0, /*tp_print*/ 408 | 0, /*tp_getattr*/ 409 | 0, /*tp_setattr*/ 410 | 0, /*tp_compare*/ 411 | 0, /*tp_repr*/ 412 | 0, /*tp_as_number*/ 413 | 0, /*tp_as_sequence*/ 414 | 0, /*tp_as_mapping*/ 415 | 0, /*tp_hash */ 416 | 0, /*tp_call*/ 417 | 0, /*tp_str*/ 418 | 0, /*tp_getattro*/ 419 | 0, /*tp_setattro*/ 420 | 0, /*tp_as_buffer*/ 421 | Py_TPFLAGS_DEFAULT, /*tp_flags*/ 422 | "Port Audio Device Info", /* tp_doc */ 423 | 0, /* tp_traverse */ 424 | 0, /* tp_clear */ 425 | 0, /* tp_richcompare */ 426 | 0, /* tp_weaklistoffset */ 427 | 0, /* tp_iter */ 428 | 0, /* tp_iternext */ 429 | 0, /* tp_methods */ 430 | 0, /* tp_members */ 431 | _pyAudio_paDeviceInfo_getseters, /* tp_getset */ 432 | 0, /* tp_base */ 433 | 0, /* tp_dict */ 434 | 0, /* tp_descr_get */ 435 | 0, /* tp_descr_set */ 436 | 0, /* tp_dictoffset */ 437 | 0, /* tp_init */ 438 | 0, /* tp_alloc */ 439 | 0, /* tp_new */ 440 | }; 441 | 442 | static _pyAudio_paDeviceInfo * 443 | _create_paDeviceInfo_object(void) 444 | { 445 | _pyAudio_paDeviceInfo *obj; 446 | 447 | /* don't allow subclassing? */ 448 | obj = (_pyAudio_paDeviceInfo *) PyObject_New(_pyAudio_paDeviceInfo, 449 | &_pyAudio_paDeviceInfoType); 450 | 451 | /* obj = (_pyAudio_Stream*) 452 | _pyAudio_StreamType.tp_alloc(&_pyAudio_StreamType, 0); */ 453 | return obj; 454 | } 455 | 456 | 457 | 458 | 459 | /************************************************************* 460 | * PaHostApi Info Python Object 461 | *************************************************************/ 462 | 463 | typedef struct { 464 | PyObject_HEAD 465 | PaHostApiInfo *apiInfo; 466 | } _pyAudio_paHostApiInfo; 467 | 468 | /* sepcific getters into the PaDeviceInfo struct */ 469 | 470 | static PyObject * 471 | _pyAudio_paHostApiInfo_get_structVersion(_pyAudio_paHostApiInfo *self, 472 | void *closure) 473 | { 474 | /* sanity check */ 475 | if ((!self->apiInfo)) { 476 | PyErr_SetString(PyExc_AttributeError, 477 | "No HostApi Info available"); 478 | return NULL; 479 | } 480 | 481 | return PyLong_FromLong(self->apiInfo->structVersion); 482 | } 483 | 484 | static PyObject * 485 | _pyAudio_paHostApiInfo_get_type(_pyAudio_paHostApiInfo *self, 486 | void *closure) 487 | { 488 | /* sanity check */ 489 | if ((!self->apiInfo)) { 490 | PyErr_SetString(PyExc_AttributeError, 491 | "No HostApi Info available"); 492 | return NULL; 493 | } 494 | 495 | return PyLong_FromLong((long) self->apiInfo->type); 496 | } 497 | 498 | static PyObject * 499 | _pyAudio_paHostApiInfo_get_name(_pyAudio_paHostApiInfo *self, 500 | void *closure) 501 | { 502 | /* sanity check */ 503 | if ((!self->apiInfo) || (self->apiInfo->name == NULL)) { 504 | PyErr_SetString(PyExc_AttributeError, 505 | "No HostApi Info available"); 506 | return NULL; 507 | } 508 | 509 | return PyUnicode_FromString(self->apiInfo->name); 510 | } 511 | 512 | static PyObject * 513 | _pyAudio_paHostApiInfo_get_deviceCount(_pyAudio_paHostApiInfo *self, 514 | void *closure) 515 | { 516 | /* sanity check */ 517 | if ((!self->apiInfo)) { 518 | PyErr_SetString(PyExc_AttributeError, 519 | "No HostApi Info available"); 520 | return NULL; 521 | } 522 | 523 | return PyLong_FromLong(self->apiInfo->deviceCount); 524 | } 525 | 526 | static PyObject * 527 | _pyAudio_paHostApiInfo_get_defaultInputDevice(_pyAudio_paHostApiInfo *self, 528 | void *closure) 529 | { 530 | /* sanity check */ 531 | if ((!self->apiInfo)) { 532 | PyErr_SetString(PyExc_AttributeError, 533 | "No HostApi Info available"); 534 | return NULL; 535 | } 536 | 537 | return PyLong_FromLong(self->apiInfo->defaultInputDevice); 538 | } 539 | 540 | static PyObject * 541 | _pyAudio_paHostApiInfo_get_defaultOutputDevice(_pyAudio_paHostApiInfo *self, 542 | void *closure) 543 | { 544 | /* sanity check */ 545 | if ((!self->apiInfo)) { 546 | PyErr_SetString(PyExc_AttributeError, 547 | "No HostApi Info available"); 548 | return NULL; 549 | } 550 | 551 | return PyLong_FromLong(self->apiInfo->defaultOutputDevice); 552 | } 553 | 554 | static int 555 | _pyAudio_paHostApiInfo_antiset(_pyAudio_paDeviceInfo *self, 556 | PyObject *value, 557 | void *closure) 558 | { 559 | /* read-only: do not allow users to change values */ 560 | PyErr_SetString(PyExc_AttributeError, 561 | "Fields read-only: cannot modify values"); 562 | return -1; 563 | } 564 | 565 | static void 566 | _pyAudio_paHostApiInfo_dealloc(_pyAudio_paHostApiInfo* self) 567 | { 568 | /* reset the pointer */ 569 | self->apiInfo = NULL; 570 | 571 | /* free the object */ 572 | Py_TYPE(self)->tp_free((PyObject*) self); 573 | } 574 | 575 | static PyGetSetDef _pyAudio_paHostApiInfo_getseters[] = { 576 | {"name", 577 | (getter) _pyAudio_paHostApiInfo_get_name, 578 | (setter) _pyAudio_paHostApiInfo_antiset, 579 | "host api name", 580 | NULL}, 581 | 582 | {"structVersion", 583 | (getter) _pyAudio_paHostApiInfo_get_structVersion, 584 | (setter) _pyAudio_paHostApiInfo_antiset, 585 | "struct version", 586 | NULL}, 587 | 588 | {"type", 589 | (getter) _pyAudio_paHostApiInfo_get_type, 590 | (setter) _pyAudio_paHostApiInfo_antiset, 591 | "host api type", 592 | NULL}, 593 | 594 | {"deviceCount", 595 | (getter) _pyAudio_paHostApiInfo_get_deviceCount, 596 | (setter) _pyAudio_paHostApiInfo_antiset, 597 | "number of devices", 598 | NULL}, 599 | 600 | {"defaultInputDevice", 601 | (getter) _pyAudio_paHostApiInfo_get_defaultInputDevice, 602 | (setter) _pyAudio_paHostApiInfo_antiset, 603 | "default input device index", 604 | NULL}, 605 | 606 | {"defaultOutputDevice", 607 | (getter) _pyAudio_paHostApiInfo_get_defaultOutputDevice, 608 | (setter) _pyAudio_paDeviceInfo_antiset, 609 | "default output device index", 610 | NULL}, 611 | 612 | {NULL} 613 | }; 614 | 615 | static PyTypeObject _pyAudio_paHostApiInfoType = { 616 | PyVarObject_HEAD_INIT(NULL, 0) 617 | "_portaudio.paHostApiInfo", /*tp_name*/ 618 | sizeof(_pyAudio_paHostApiInfo), /*tp_basicsize*/ 619 | 0, /*tp_itemsize*/ 620 | (destructor) _pyAudio_paHostApiInfo_dealloc, /*tp_dealloc*/ 621 | 0, /*tp_print*/ 622 | 0, /*tp_getattr*/ 623 | 0, /*tp_setattr*/ 624 | 0, /*tp_compare*/ 625 | 0, /*tp_repr*/ 626 | 0, /*tp_as_number*/ 627 | 0, /*tp_as_sequence*/ 628 | 0, /*tp_as_mapping*/ 629 | 0, /*tp_hash */ 630 | 0, /*tp_call*/ 631 | 0, /*tp_str*/ 632 | 0, /*tp_getattro*/ 633 | 0, /*tp_setattro*/ 634 | 0, /*tp_as_buffer*/ 635 | Py_TPFLAGS_DEFAULT, /*tp_flags*/ 636 | "Port Audio HostApi Info", /* tp_doc */ 637 | 0, /* tp_traverse */ 638 | 0, /* tp_clear */ 639 | 0, /* tp_richcompare */ 640 | 0, /* tp_weaklistoffset */ 641 | 0, /* tp_iter */ 642 | 0, /* tp_iternext */ 643 | 0, /* tp_methods */ 644 | 0, /* tp_members */ 645 | _pyAudio_paHostApiInfo_getseters, /* tp_getset */ 646 | 0, /* tp_base */ 647 | 0, /* tp_dict */ 648 | 0, /* tp_descr_get */ 649 | 0, /* tp_descr_set */ 650 | 0, /* tp_dictoffset */ 651 | 0, /* tp_init */ 652 | 0, /* tp_alloc */ 653 | 0, /* tp_new */ 654 | }; 655 | 656 | static _pyAudio_paHostApiInfo * 657 | _create_paHostApiInfo_object(void) 658 | { 659 | _pyAudio_paHostApiInfo *obj; 660 | 661 | /* don't allow subclassing? */ 662 | obj = (_pyAudio_paHostApiInfo *) PyObject_New(_pyAudio_paHostApiInfo, 663 | &_pyAudio_paHostApiInfoType); 664 | return obj; 665 | } 666 | 667 | /************************************************************* 668 | * Host-Specific Objects 669 | *************************************************************/ 670 | 671 | /************************************************************* 672 | * --> Mac OS X 673 | *************************************************************/ 674 | 675 | #ifdef MACOSX 676 | typedef struct { 677 | PyObject_HEAD 678 | PaMacCoreStreamInfo *paMacCoreStreamInfo; 679 | int flags; 680 | SInt32 *channelMap; 681 | int channelMapSize; 682 | } _pyAudio_MacOSX_hostApiSpecificStreamInfo; 683 | 684 | typedef _pyAudio_MacOSX_hostApiSpecificStreamInfo _pyAudio_Mac_HASSI; 685 | 686 | static void 687 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(_pyAudio_Mac_HASSI *self) 688 | { 689 | if (self->paMacCoreStreamInfo != NULL) { 690 | free(self->paMacCoreStreamInfo); 691 | self->paMacCoreStreamInfo = NULL; 692 | } 693 | 694 | if (self->channelMap != NULL) { 695 | free(self->channelMap); 696 | self->channelMap = NULL; 697 | } 698 | 699 | self->flags = paMacCorePlayNice; 700 | self->channelMapSize = 0; 701 | } 702 | 703 | static void 704 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_dealloc(_pyAudio_Mac_HASSI *self) 705 | { 706 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); 707 | Py_TYPE(self)->tp_free((PyObject *) self); 708 | } 709 | 710 | static int 711 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_init(PyObject *_self, 712 | PyObject *args, 713 | PyObject *kwargs) 714 | { 715 | _pyAudio_Mac_HASSI *self = (_pyAudio_Mac_HASSI *) _self; 716 | PyObject *channel_map = NULL; 717 | int flags = paMacCorePlayNice; 718 | 719 | static char *kwlist[] = {"flags", "channel_map", NULL}; 720 | 721 | if (! PyArg_ParseTupleAndKeywords(args, kwargs, "|iO", kwlist, 722 | &flags, &channel_map)) { 723 | return -1; 724 | } 725 | 726 | // cleanup (just in case) 727 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); 728 | 729 | if (channel_map != NULL) { 730 | // ensure channel_map is an array 731 | if (! PyTuple_Check(channel_map)) { 732 | PyErr_SetString(PyExc_ValueError, "Channel map must be a tuple"); 733 | return -1; 734 | } 735 | 736 | // generate SInt32 channelMap 737 | self->channelMapSize = (int) PyTuple_Size(channel_map); 738 | 739 | self->channelMap = (SInt32 *) malloc(sizeof(SInt32) * self->channelMapSize); 740 | 741 | if (self->channelMap == NULL) { 742 | PyErr_SetString(PyExc_SystemError, "Out of memory"); 743 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); 744 | return -1; 745 | } 746 | 747 | PyObject *element; 748 | int i; 749 | for (i = 0; i < self->channelMapSize; ++i) { 750 | element = PyTuple_GetItem(channel_map, i); 751 | if (element == NULL) { 752 | // error condition 753 | PyErr_SetString(PyExc_ValueError, 754 | "Internal error: out of bounds index"); 755 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); 756 | return -1; 757 | } 758 | 759 | // make sure element is an integer 760 | if (!PyNumber_Check(element)) { 761 | PyErr_SetString(PyExc_ValueError, 762 | "Channel Map must consist of integer elements"); 763 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); 764 | return -1; 765 | } 766 | 767 | PyObject *long_element = PyNumber_Long(element); 768 | 769 | // OK, looks good 770 | self->channelMap[i] = (SInt32) PyLong_AsLong(long_element); 771 | Py_DECREF(long_element); 772 | } 773 | } 774 | 775 | // malloc self->paMacCoreStreamInfo 776 | self->paMacCoreStreamInfo = 777 | (PaMacCoreStreamInfo *) malloc(sizeof(PaMacCoreStreamInfo)); 778 | 779 | if (self->paMacCoreStreamInfo == NULL) { 780 | PyErr_SetString(PyExc_SystemError, "Out of memeory"); 781 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_cleanup(self); 782 | return -1; 783 | } 784 | 785 | PaMacCore_SetupStreamInfo(self->paMacCoreStreamInfo, flags); 786 | 787 | if (self->channelMap) { 788 | PaMacCore_SetupChannelMap(self->paMacCoreStreamInfo, 789 | self->channelMap, 790 | self->channelMapSize); 791 | } 792 | 793 | self->flags = flags; 794 | 795 | return 0; 796 | } 797 | 798 | static PyObject * 799 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_get_flags(_pyAudio_Mac_HASSI *self, 800 | void *closure) 801 | { 802 | return PyLong_FromLong(self->flags); 803 | } 804 | 805 | static PyObject * 806 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_get_channel_map( 807 | _pyAudio_Mac_HASSI *self, 808 | void *closure) 809 | { 810 | if (self->channelMap == NULL || self->channelMapSize == 0) { 811 | Py_INCREF(Py_None); 812 | return Py_None; 813 | } 814 | 815 | int i; 816 | PyObject *channelMapTuple = PyTuple_New(self->channelMapSize); 817 | for (i = 0; i < self->channelMapSize; ++i) { 818 | PyObject *element = PyLong_FromLong(self->channelMap[i]); 819 | if (!element) { 820 | PyErr_SetString(PyExc_SystemError, "Invalid channel map"); 821 | return NULL; 822 | } 823 | 824 | if (PyTuple_SetItem(channelMapTuple, 825 | i, 826 | PyLong_FromLong(self->channelMap[i]))) { 827 | // non-zero on error 828 | PyErr_SetString(PyExc_SystemError, "Can't create channel map."); 829 | return NULL; 830 | } 831 | } 832 | return channelMapTuple; 833 | } 834 | 835 | static int 836 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_antiset(_pyAudio_Mac_HASSI *self, 837 | PyObject *value, 838 | void *closure) 839 | { 840 | /* read-only: do not allow users to change values */ 841 | PyErr_SetString(PyExc_AttributeError, 842 | "Fields read-only: cannot modify values"); 843 | return -1; 844 | } 845 | 846 | static PyGetSetDef _pyAudio_MacOSX_hostApiSpecificStreamInfo_getseters[] = { 847 | {"flags", 848 | (getter) _pyAudio_MacOSX_hostApiSpecificStreamInfo_get_flags, 849 | (setter) _pyAudio_MacOSX_hostApiSpecificStreamInfo_antiset, 850 | "flags", 851 | NULL}, 852 | 853 | {"channel_map", 854 | (getter) _pyAudio_MacOSX_hostApiSpecificStreamInfo_get_channel_map, 855 | (setter) _pyAudio_MacOSX_hostApiSpecificStreamInfo_antiset, 856 | "channel map", 857 | NULL}, 858 | 859 | {NULL} 860 | }; 861 | 862 | static PyTypeObject _pyAudio_MacOSX_hostApiSpecificStreamInfoType = { 863 | PyVarObject_HEAD_INIT(NULL, 0) 864 | "_portaudio.PaMacCoreStreamInfo", /*tp_name*/ 865 | sizeof(_pyAudio_MacOSX_hostApiSpecificStreamInfo), /*tp_basicsize*/ 866 | 0, /*tp_itemsize*/ 867 | /*tp_dealloc*/ 868 | (destructor) _pyAudio_MacOSX_hostApiSpecificStreamInfo_dealloc, 869 | 0, /*tp_print*/ 870 | 0, /*tp_getattr*/ 871 | 0, /*tp_setattr*/ 872 | 0, /*tp_compare*/ 873 | 0, /*tp_repr*/ 874 | 0, /*tp_as_number*/ 875 | 0, /*tp_as_sequence*/ 876 | 0, /*tp_as_mapping*/ 877 | 0, /*tp_hash */ 878 | 0, /*tp_call*/ 879 | 0, /*tp_str*/ 880 | 0, /*tp_getattro*/ 881 | 0, /*tp_setattro*/ 882 | 0, /*tp_as_buffer*/ 883 | Py_TPFLAGS_DEFAULT, /*tp_flags*/ 884 | "Mac OS X Specific HostAPI configuration", /* tp_doc */ 885 | 0, /* tp_traverse */ 886 | 0, /* tp_clear */ 887 | 0, /* tp_richcompare */ 888 | 0, /* tp_weaklistoffset */ 889 | 0, /* tp_iter */ 890 | 0, /* tp_iternext */ 891 | 0, /* tp_methods */ 892 | 0, /* tp_members */ 893 | _pyAudio_MacOSX_hostApiSpecificStreamInfo_getseters, /* tp_getset */ 894 | 0, /* tp_base */ 895 | 0, /* tp_dict */ 896 | 0, /* tp_descr_get */ 897 | 0, /* tp_descr_set */ 898 | 0, /* tp_dictoffset */ 899 | (int (*)(PyObject*, PyObject*, PyObject*))_pyAudio_MacOSX_hostApiSpecificStreamInfo_init, /* tp_init */ 900 | 0, /* tp_alloc */ 901 | 0, /* tp_new */ 902 | }; 903 | #endif 904 | 905 | 906 | /************************************************************* 907 | * Stream Wrapper Python Object 908 | *************************************************************/ 909 | 910 | typedef struct { 911 | PyObject *callback; 912 | long main_thread_id; 913 | unsigned int frame_size; 914 | } PyAudioCallbackContext; 915 | 916 | typedef struct { 917 | PyObject_HEAD 918 | PaStream *stream; 919 | PaStreamParameters *inputParameters; 920 | PaStreamParameters *outputParameters; 921 | 922 | /* include PaStreamInfo too! */ 923 | PaStreamInfo *streamInfo; 924 | 925 | /* context for callback */ 926 | PyAudioCallbackContext *callbackContext; 927 | 928 | int is_open; 929 | } _pyAudio_Stream; 930 | 931 | static int 932 | _is_open(_pyAudio_Stream *obj) { 933 | return (obj) && (obj->is_open); 934 | } 935 | 936 | static void 937 | _cleanup_Stream_object(_pyAudio_Stream *streamObject) 938 | { 939 | if (streamObject->stream != NULL) { 940 | Py_BEGIN_ALLOW_THREADS 941 | Pa_CloseStream(streamObject->stream); 942 | Py_END_ALLOW_THREADS 943 | streamObject->stream = NULL; 944 | } 945 | 946 | if (streamObject->streamInfo) 947 | streamObject->streamInfo = NULL; 948 | 949 | if (streamObject->inputParameters != NULL) { 950 | free(streamObject->inputParameters); 951 | streamObject->inputParameters = NULL; 952 | } 953 | 954 | if (streamObject->outputParameters != NULL) { 955 | free(streamObject->outputParameters); 956 | streamObject->outputParameters = NULL; 957 | } 958 | 959 | if (streamObject->callbackContext != NULL) { 960 | Py_XDECREF(streamObject->callbackContext->callback); 961 | free(streamObject->callbackContext); 962 | streamObject->callbackContext = NULL; 963 | } 964 | 965 | /* designate the stream as closed */ 966 | streamObject->is_open = 0; 967 | } 968 | 969 | static void 970 | _pyAudio_Stream_dealloc(_pyAudio_Stream* self) 971 | { 972 | /* deallocate memory if necessary */ 973 | _cleanup_Stream_object(self); 974 | 975 | /* free the object */ 976 | Py_TYPE(self)->tp_free((PyObject*) self); 977 | } 978 | 979 | 980 | static PyObject * 981 | _pyAudio_Stream_get_structVersion(_pyAudio_Stream *self, 982 | void *closure) 983 | { 984 | /* sanity check */ 985 | if (!_is_open(self)) { 986 | PyErr_SetObject(PyExc_IOError, 987 | Py_BuildValue("(s,i)", 988 | "Stream closed", 989 | paBadStreamPtr)); 990 | return NULL; 991 | } 992 | 993 | if ((!self->streamInfo)) { 994 | PyErr_SetObject(PyExc_IOError, 995 | Py_BuildValue("(s,i)", 996 | "No StreamInfo available", 997 | paBadStreamPtr)); 998 | return NULL; 999 | } 1000 | 1001 | return PyLong_FromLong(self->streamInfo->structVersion); 1002 | } 1003 | 1004 | static PyObject * 1005 | _pyAudio_Stream_get_inputLatency(_pyAudio_Stream *self, 1006 | void *closure) 1007 | { 1008 | /* sanity check */ 1009 | if (!_is_open(self)) { 1010 | PyErr_SetObject(PyExc_IOError, 1011 | Py_BuildValue("(s,i)", 1012 | "Stream closed", 1013 | paBadStreamPtr)); 1014 | return NULL; 1015 | } 1016 | 1017 | /* sanity check */ 1018 | if ((!self->streamInfo)) { 1019 | PyErr_SetObject(PyExc_IOError, 1020 | Py_BuildValue("(s,i)", 1021 | "No StreamInfo available", 1022 | paBadStreamPtr)); 1023 | return NULL; 1024 | } 1025 | 1026 | return PyFloat_FromDouble(self->streamInfo->inputLatency); 1027 | } 1028 | 1029 | static PyObject * 1030 | _pyAudio_Stream_get_outputLatency(_pyAudio_Stream *self, 1031 | void *closure) 1032 | { 1033 | /* sanity check */ 1034 | if (!_is_open(self)) { 1035 | PyErr_SetObject(PyExc_IOError, 1036 | Py_BuildValue("(s,i)", 1037 | "Stream closed", 1038 | paBadStreamPtr)); 1039 | return NULL; 1040 | } 1041 | 1042 | /* sanity check */ 1043 | if ((!self->streamInfo)) { 1044 | PyErr_SetObject(PyExc_IOError, 1045 | Py_BuildValue("(s,i)", 1046 | "No StreamInfo available", 1047 | paBadStreamPtr)); 1048 | return NULL; 1049 | } 1050 | 1051 | return PyFloat_FromDouble(self->streamInfo->outputLatency); 1052 | } 1053 | 1054 | static PyObject * 1055 | _pyAudio_Stream_get_sampleRate(_pyAudio_Stream *self, 1056 | void *closure) 1057 | { 1058 | /* sanity check */ 1059 | if (!_is_open(self)) { 1060 | PyErr_SetObject(PyExc_IOError, 1061 | Py_BuildValue("(s,i)", 1062 | "Stream closed", 1063 | paBadStreamPtr)); 1064 | return NULL; 1065 | } 1066 | 1067 | /* sanity check */ 1068 | if ((!self->streamInfo)) { 1069 | PyErr_SetObject(PyExc_IOError, 1070 | Py_BuildValue("(s,i)", 1071 | "No StreamInfo available", 1072 | paBadStreamPtr)); 1073 | return NULL; 1074 | } 1075 | 1076 | return PyFloat_FromDouble(self->streamInfo->sampleRate); 1077 | } 1078 | 1079 | static int 1080 | _pyAudio_Stream_antiset(_pyAudio_Stream *self, 1081 | PyObject *value, 1082 | void *closure) 1083 | { 1084 | /* read-only: do not allow users to change values */ 1085 | PyErr_SetString(PyExc_AttributeError, 1086 | "Fields read-only: cannot modify values"); 1087 | return -1; 1088 | } 1089 | 1090 | static PyGetSetDef _pyAudio_Stream_getseters[] = { 1091 | {"structVersion", 1092 | (getter) _pyAudio_Stream_get_structVersion, 1093 | (setter) _pyAudio_Stream_antiset, 1094 | "struct version", 1095 | NULL}, 1096 | 1097 | {"inputLatency", 1098 | (getter) _pyAudio_Stream_get_inputLatency, 1099 | (setter) _pyAudio_Stream_antiset, 1100 | "input latency", 1101 | NULL}, 1102 | 1103 | {"outputLatency", 1104 | (getter) _pyAudio_Stream_get_outputLatency, 1105 | (setter) _pyAudio_Stream_antiset, 1106 | "output latency", 1107 | NULL}, 1108 | 1109 | {"sampleRate", 1110 | (getter) _pyAudio_Stream_get_sampleRate, 1111 | (setter) _pyAudio_Stream_antiset, 1112 | "sample rate", 1113 | NULL}, 1114 | 1115 | {NULL} 1116 | }; 1117 | 1118 | static PyTypeObject _pyAudio_StreamType = { 1119 | PyVarObject_HEAD_INIT(NULL, 0) 1120 | "_portaudio.Stream", /*tp_name*/ 1121 | sizeof(_pyAudio_Stream), /*tp_basicsize*/ 1122 | 0, /*tp_itemsize*/ 1123 | (destructor) _pyAudio_Stream_dealloc, /*tp_dealloc*/ 1124 | 0, /*tp_print*/ 1125 | 0, /*tp_getattr*/ 1126 | 0, /*tp_setattr*/ 1127 | 0, /*tp_compare*/ 1128 | 0, /*tp_repr*/ 1129 | 0, /*tp_as_number*/ 1130 | 0, /*tp_as_sequence*/ 1131 | 0, /*tp_as_mapping*/ 1132 | 0, /*tp_hash */ 1133 | 0, /*tp_call*/ 1134 | 0, /*tp_str*/ 1135 | 0, /*tp_getattro*/ 1136 | 0, /*tp_setattro*/ 1137 | 0, /*tp_as_buffer*/ 1138 | Py_TPFLAGS_DEFAULT, /*tp_flags*/ 1139 | "Port Audio Stream", /* tp_doc */ 1140 | 0, /* tp_traverse */ 1141 | 0, /* tp_clear */ 1142 | 0, /* tp_richcompare */ 1143 | 0, /* tp_weaklistoffset */ 1144 | 0, /* tp_iter */ 1145 | 0, /* tp_iternext */ 1146 | 0, /* tp_methods */ 1147 | 0, /* tp_members */ 1148 | _pyAudio_Stream_getseters, /* tp_getset */ 1149 | 0, /* tp_base */ 1150 | 0, /* tp_dict */ 1151 | 0, /* tp_descr_get */ 1152 | 0, /* tp_descr_set */ 1153 | 0, /* tp_dictoffset */ 1154 | 0, /* tp_init */ 1155 | 0, /* tp_alloc */ 1156 | 0, /* tp_new */ 1157 | }; 1158 | 1159 | static _pyAudio_Stream * 1160 | _create_Stream_object(void) 1161 | { 1162 | _pyAudio_Stream *obj; 1163 | 1164 | /* don't allow subclassing? */ 1165 | obj = (_pyAudio_Stream *) PyObject_New(_pyAudio_Stream, 1166 | &_pyAudio_StreamType); 1167 | return obj; 1168 | } 1169 | 1170 | 1171 | /************************************************************ 1172 | * 1173 | * III. PortAudio Method Implementations 1174 | * 1175 | ************************************************************/ 1176 | 1177 | /************************************************************* 1178 | * Version Info 1179 | *************************************************************/ 1180 | 1181 | static PyObject * 1182 | pa_get_version(PyObject *self, PyObject *args) 1183 | { 1184 | if (!PyArg_ParseTuple(args, "")) 1185 | return NULL; 1186 | 1187 | return PyLong_FromLong(Pa_GetVersion()); 1188 | } 1189 | 1190 | static PyObject * 1191 | pa_get_version_text(PyObject *self, PyObject *args) 1192 | { 1193 | if (!PyArg_ParseTuple(args, "")) 1194 | return NULL; 1195 | 1196 | return PyUnicode_FromString(Pa_GetVersionText()); 1197 | } 1198 | 1199 | /************************************************************* 1200 | * Initialization/Termination 1201 | *************************************************************/ 1202 | 1203 | static PyObject * 1204 | pa_initialize(PyObject *self, PyObject *args) 1205 | { 1206 | int err; 1207 | err = Pa_Initialize(); 1208 | if (err != paNoError) { 1209 | Pa_Terminate(); 1210 | #ifdef VERBOSE 1211 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 1212 | fprintf(stderr, "Error number: %d\n", err); 1213 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); 1214 | #endif 1215 | PyErr_SetObject(PyExc_IOError, 1216 | Py_BuildValue("(s,i)", 1217 | Pa_GetErrorText(err), err)); 1218 | return NULL; 1219 | } 1220 | 1221 | Py_INCREF(Py_None); 1222 | return Py_None; 1223 | } 1224 | 1225 | static PyObject * 1226 | pa_terminate(PyObject *self, PyObject *args) 1227 | { 1228 | Pa_Terminate(); 1229 | Py_INCREF(Py_None); 1230 | return Py_None; 1231 | } 1232 | 1233 | /************************************************************* 1234 | * HostAPI 1235 | *************************************************************/ 1236 | 1237 | static PyObject * 1238 | pa_get_host_api_count(PyObject *self, PyObject *args) 1239 | { 1240 | PaHostApiIndex count; 1241 | 1242 | if (!PyArg_ParseTuple(args, "")) 1243 | return NULL; 1244 | 1245 | count = Pa_GetHostApiCount(); 1246 | 1247 | if (count < 0) { 1248 | 1249 | #ifdef VERBOSE 1250 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 1251 | fprintf(stderr, "Error number: %d\n", count); 1252 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(count)); 1253 | #endif 1254 | 1255 | PyErr_SetObject(PyExc_IOError, 1256 | Py_BuildValue("(s,i)", 1257 | Pa_GetErrorText(count), count)); 1258 | return NULL; 1259 | } 1260 | 1261 | return PyLong_FromLong(count); 1262 | } 1263 | 1264 | static PyObject * 1265 | pa_get_default_host_api(PyObject *self, PyObject *args) 1266 | { 1267 | PaHostApiIndex index; 1268 | 1269 | if (!PyArg_ParseTuple(args, "")) 1270 | return NULL; 1271 | 1272 | index = Pa_GetDefaultHostApi(); 1273 | 1274 | if (index < 0) { 1275 | 1276 | #ifdef VERBOSE 1277 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 1278 | fprintf(stderr, "Error number: %d\n", index); 1279 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(index)); 1280 | #endif 1281 | 1282 | PyErr_SetObject(PyExc_IOError, 1283 | Py_BuildValue("(s,i)", 1284 | Pa_GetErrorText(index), index)); 1285 | return NULL; 1286 | } 1287 | 1288 | return PyLong_FromLong(index); 1289 | } 1290 | 1291 | static PyObject * 1292 | pa_host_api_type_id_to_host_api_index(PyObject *self, PyObject *args) 1293 | { 1294 | PaHostApiTypeId typeid; 1295 | PaHostApiIndex index; 1296 | 1297 | if (!PyArg_ParseTuple(args, "i", &typeid)) 1298 | return NULL; 1299 | 1300 | index = Pa_HostApiTypeIdToHostApiIndex(typeid); 1301 | 1302 | if (index < 0) { 1303 | 1304 | #ifdef VERBOSE 1305 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 1306 | fprintf(stderr, "Error number: %d\n", index); 1307 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(index)); 1308 | #endif 1309 | 1310 | PyErr_SetObject(PyExc_IOError, 1311 | Py_BuildValue("(s,i)", 1312 | Pa_GetErrorText(index), index)); 1313 | return NULL; 1314 | } 1315 | 1316 | return PyLong_FromLong(index); 1317 | } 1318 | 1319 | static PyObject * 1320 | pa_host_api_device_index_to_device_index(PyObject *self, PyObject *args) 1321 | { 1322 | PaHostApiIndex apiIndex; 1323 | int hostApiDeviceindex; 1324 | PaDeviceIndex devIndex; 1325 | 1326 | 1327 | if (!PyArg_ParseTuple(args, "ii", &apiIndex, &hostApiDeviceindex)) 1328 | return NULL; 1329 | 1330 | devIndex = Pa_HostApiDeviceIndexToDeviceIndex(apiIndex, hostApiDeviceindex); 1331 | if (devIndex < 0) { 1332 | 1333 | #ifdef VERBOSE 1334 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 1335 | fprintf(stderr, "Error number: %d\n", devIndex); 1336 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(devIndex)); 1337 | #endif 1338 | 1339 | PyErr_SetObject(PyExc_IOError, 1340 | Py_BuildValue("(s,i)", 1341 | Pa_GetErrorText(devIndex), devIndex)); 1342 | return NULL; 1343 | } 1344 | 1345 | return PyLong_FromLong(devIndex); 1346 | } 1347 | 1348 | static PyObject * 1349 | pa_get_host_api_info(PyObject *self, PyObject *args) 1350 | { 1351 | PaHostApiIndex index; 1352 | PaHostApiInfo* _info; 1353 | _pyAudio_paHostApiInfo* py_info; 1354 | 1355 | if (!PyArg_ParseTuple(args, "i", &index)) 1356 | return NULL; 1357 | 1358 | _info = (PaHostApiInfo *) Pa_GetHostApiInfo(index); 1359 | 1360 | if (!_info) { 1361 | PyErr_SetObject(PyExc_IOError, 1362 | Py_BuildValue("(s,i)", 1363 | "Invalid host api info", 1364 | paInvalidHostApi)); 1365 | return NULL; 1366 | } 1367 | 1368 | py_info = _create_paHostApiInfo_object(); 1369 | py_info->apiInfo = _info; 1370 | 1371 | return (PyObject *) py_info; 1372 | } 1373 | 1374 | /************************************************************* 1375 | * Device API 1376 | *************************************************************/ 1377 | 1378 | static PyObject * 1379 | pa_get_device_count(PyObject *self, PyObject *args) 1380 | { 1381 | PaDeviceIndex count; 1382 | 1383 | if (!PyArg_ParseTuple(args, "")) 1384 | return NULL; 1385 | 1386 | count = Pa_GetDeviceCount(); 1387 | if (count < 0) { 1388 | 1389 | #ifdef VERBOSE 1390 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 1391 | fprintf(stderr, "Error number: %d\n", count); 1392 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(count)); 1393 | #endif 1394 | 1395 | PyErr_SetObject(PyExc_IOError, 1396 | Py_BuildValue("(s,i)", 1397 | Pa_GetErrorText(count), count)); 1398 | return NULL; 1399 | } 1400 | 1401 | return PyLong_FromLong(count); 1402 | } 1403 | 1404 | static PyObject * 1405 | pa_get_default_input_device(PyObject *self, PyObject *args) 1406 | { 1407 | PaDeviceIndex index; 1408 | 1409 | if (!PyArg_ParseTuple(args, "")) 1410 | return NULL; 1411 | 1412 | index = Pa_GetDefaultInputDevice(); 1413 | if (index == paNoDevice) { 1414 | PyErr_SetString(PyExc_IOError, "No Default Input Device Available"); 1415 | return NULL; 1416 | } else if (index < 0) { 1417 | 1418 | #ifdef VERBOSE 1419 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 1420 | fprintf(stderr, "Error number: %d\n", index); 1421 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(index)); 1422 | #endif 1423 | 1424 | PyErr_SetObject(PyExc_IOError, 1425 | Py_BuildValue("(s,i)", 1426 | Pa_GetErrorText(index), index)); 1427 | return NULL; 1428 | } 1429 | 1430 | return PyLong_FromLong(index); 1431 | } 1432 | 1433 | static PyObject * 1434 | pa_get_default_output_device(PyObject *self, PyObject *args) 1435 | { 1436 | PaDeviceIndex index; 1437 | 1438 | if (!PyArg_ParseTuple(args, "")) 1439 | return NULL; 1440 | 1441 | index = Pa_GetDefaultOutputDevice(); 1442 | if (index == paNoDevice) { 1443 | PyErr_SetString(PyExc_IOError, "No Default Output Device Available"); 1444 | return NULL; 1445 | } else if (index < 0) { 1446 | 1447 | #ifdef VERBOSE 1448 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 1449 | fprintf(stderr, "Error number: %d\n", index); 1450 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(index)); 1451 | #endif 1452 | 1453 | PyErr_SetObject(PyExc_IOError, 1454 | Py_BuildValue("(s,i)", 1455 | Pa_GetErrorText(index), index)); 1456 | return NULL; 1457 | } 1458 | 1459 | return PyLong_FromLong(index); 1460 | } 1461 | 1462 | static PyObject * 1463 | pa_get_device_info(PyObject *self, PyObject *args) 1464 | { 1465 | PaDeviceIndex index; 1466 | PaDeviceInfo* _info; 1467 | _pyAudio_paDeviceInfo* py_info; 1468 | 1469 | if (!PyArg_ParseTuple(args, "i", &index)) 1470 | return NULL; 1471 | 1472 | _info = (PaDeviceInfo *) Pa_GetDeviceInfo(index); 1473 | 1474 | if (!_info) { 1475 | PyErr_SetObject(PyExc_IOError, 1476 | Py_BuildValue("(s,i)", 1477 | "Invalid device info", paInvalidDevice)); 1478 | return NULL; 1479 | } 1480 | 1481 | py_info = _create_paDeviceInfo_object(); 1482 | py_info->devInfo = _info; 1483 | return (PyObject *) py_info; 1484 | } 1485 | 1486 | /************************************************************* 1487 | * Stream Open / Close / Supported 1488 | *************************************************************/ 1489 | 1490 | int 1491 | _stream_callback_cfunction(const void *input, 1492 | void *output, 1493 | unsigned long frameCount, 1494 | const PaStreamCallbackTimeInfo *timeInfo, 1495 | PaStreamCallbackFlags statusFlags, 1496 | void *userData) 1497 | { 1498 | int return_val = paAbort; 1499 | PyGILState_STATE _state = PyGILState_Ensure(); 1500 | 1501 | #ifdef VERBOSE 1502 | if (statusFlags != 0) { 1503 | printf("Status flag set: "); 1504 | if (statusFlags & paInputUnderflow) { 1505 | printf("input underflow!\n"); 1506 | } 1507 | if (statusFlags & paInputOverflow) { 1508 | printf("input overflow!\n"); 1509 | } 1510 | if (statusFlags & paOutputUnderflow) { 1511 | printf("output underflow!\n"); 1512 | } 1513 | if (statusFlags & paOutputUnderflow) { 1514 | printf("output overflow!\n"); 1515 | } 1516 | if (statusFlags & paPrimingOutput) { 1517 | printf("priming output!\n"); 1518 | } 1519 | } 1520 | #endif 1521 | 1522 | PyAudioCallbackContext *context = (PyAudioCallbackContext *)userData; 1523 | PyObject *py_callback = context->callback; 1524 | unsigned int bytes_per_frame = context->frame_size; 1525 | long main_thread_id = context->main_thread_id; 1526 | 1527 | PyObject *py_frame_count = PyLong_FromUnsignedLong(frameCount); 1528 | PyObject *py_time_info = Py_BuildValue("{s:d,s:d,s:d}", 1529 | "input_buffer_adc_time", 1530 | timeInfo->inputBufferAdcTime, 1531 | "current_time", 1532 | timeInfo->currentTime, 1533 | "output_buffer_dac_time", 1534 | timeInfo->outputBufferDacTime); 1535 | PyObject *py_status_flags = PyLong_FromUnsignedLong(statusFlags); 1536 | PyObject *py_input_data = Py_None; 1537 | const char *pData; 1538 | int output_len; 1539 | PyObject *py_result; 1540 | 1541 | if (input) { 1542 | py_input_data = PyBytes_FromStringAndSize(input, 1543 | bytes_per_frame * frameCount); 1544 | } 1545 | 1546 | py_result = PyObject_CallFunctionObjArgs(py_callback, 1547 | py_input_data, 1548 | py_frame_count, 1549 | py_time_info, 1550 | py_status_flags, 1551 | NULL); 1552 | 1553 | if (py_result == NULL) { 1554 | #ifdef VERBOSE 1555 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 1556 | fprintf(stderr, "Error message: Could not call callback function\n"); 1557 | #endif 1558 | PyObject *err = PyErr_Occurred(); 1559 | 1560 | if (err) { 1561 | PyThreadState_SetAsyncExc(main_thread_id, err); 1562 | 1563 | // Print out a stack trace to help debugging. 1564 | // TODO: make VERBOSE a runtime flag so users can control 1565 | // the amount of logging. 1566 | PyErr_Print(); 1567 | } 1568 | 1569 | goto end; 1570 | } 1571 | 1572 | 1573 | if (!PyArg_ParseTuple(py_result, 1574 | "z#i", 1575 | &pData, 1576 | &output_len, 1577 | &return_val)) { 1578 | #ifdef VERBOSE 1579 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 1580 | fprintf(stderr, "Error message: Could not parse callback return value\n"); 1581 | #endif 1582 | 1583 | PyObject *err = PyErr_Occurred(); 1584 | 1585 | if (err) { 1586 | PyThreadState_SetAsyncExc(main_thread_id, err); 1587 | 1588 | // Print out a stack trace to help debugging. 1589 | // TODO: make VERBOSE a runtime flag so users can control 1590 | // the amount of logging. 1591 | PyErr_Print(); 1592 | } 1593 | 1594 | Py_XDECREF(py_result); 1595 | return_val = paAbort; 1596 | goto end; 1597 | } 1598 | 1599 | Py_DECREF(py_result); 1600 | 1601 | if ((return_val != paComplete) && 1602 | (return_val != paAbort) && 1603 | (return_val != paContinue)) { 1604 | PyErr_SetString(PyExc_ValueError, 1605 | "Invalid PaStreamCallbackResult from callback"); 1606 | PyThreadState_SetAsyncExc(main_thread_id, PyErr_Occurred()); 1607 | PyErr_Print(); 1608 | 1609 | // Quit the callback loop 1610 | return_val = paAbort; 1611 | 1612 | goto end; 1613 | } 1614 | 1615 | // Copy bytes for playback only if this is an output stream: 1616 | 1617 | if (output) { 1618 | char *output_data = (char*)output; 1619 | memcpy(output_data, pData, min(output_len, bytes_per_frame * frameCount)); 1620 | 1621 | // Pad out the rest of the buffer with 0s if callback returned 1622 | // too few frames (and assume paComplete). 1623 | if (output_len < (frameCount * bytes_per_frame)) { 1624 | memset(output_data + output_len, 1625 | 0, 1626 | (frameCount * bytes_per_frame) - output_len); 1627 | return_val = paComplete; 1628 | } 1629 | } 1630 | 1631 | end: 1632 | 1633 | if (input) { 1634 | // Decrement this at the end, after memcpy, in case the user 1635 | // returns py_input_data back for playback. 1636 | Py_DECREF(py_input_data); 1637 | } 1638 | 1639 | Py_XDECREF(py_frame_count); 1640 | Py_XDECREF(py_time_info); 1641 | Py_XDECREF(py_status_flags); 1642 | 1643 | PyGILState_Release(_state); 1644 | return return_val; 1645 | } 1646 | 1647 | static PyObject * 1648 | pa_open(PyObject *self, PyObject *args, PyObject *kwargs) 1649 | { 1650 | int rate, channels; 1651 | int input, output, frames_per_buffer; 1652 | int input_device_index = -1; 1653 | int output_device_index = -1; 1654 | PyObject *input_device_index_arg = NULL; 1655 | PyObject *output_device_index_arg = NULL; 1656 | PyObject *stream_callback = NULL; 1657 | PaSampleFormat format; 1658 | PaError err; 1659 | PyObject *input_device_index_long; 1660 | PyObject *output_device_index_long; 1661 | PaStreamParameters *outputParameters = NULL; 1662 | PaStreamParameters *inputParameters = NULL; 1663 | PaStream *stream = NULL; 1664 | PaStreamInfo *streamInfo = NULL; 1665 | PyAudioCallbackContext *context = NULL; 1666 | _pyAudio_Stream *streamObject; 1667 | 1668 | /* pass in rate, channel, width */ 1669 | static char *kwlist[] = {"rate", 1670 | "channels", 1671 | "format", 1672 | "input", 1673 | "output", 1674 | "input_device_index", 1675 | "output_device_index", 1676 | "frames_per_buffer", 1677 | "input_host_api_specific_stream_info", 1678 | "output_host_api_specific_stream_info", 1679 | "stream_callback", 1680 | NULL}; 1681 | 1682 | #ifdef MACOSX 1683 | _pyAudio_MacOSX_hostApiSpecificStreamInfo *inputHostSpecificStreamInfo = 1684 | NULL; 1685 | _pyAudio_MacOSX_hostApiSpecificStreamInfo *outputHostSpecificStreamInfo = 1686 | NULL; 1687 | #else 1688 | /* mostly ignored...*/ 1689 | PyObject *inputHostSpecificStreamInfo = NULL; 1690 | PyObject *outputHostSpecificStreamInfo = NULL; 1691 | #endif 1692 | 1693 | /* default to neither output nor input */ 1694 | input = 0; 1695 | output = 0; 1696 | frames_per_buffer = DEFAULT_FRAMES_PER_BUFFER; 1697 | 1698 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, 1699 | #ifdef MACOSX 1700 | "iik|iiOOiO!O!O", 1701 | #else 1702 | "iik|iiOOiOOO", 1703 | #endif 1704 | kwlist, 1705 | &rate, &channels, &format, 1706 | &input, &output, 1707 | &input_device_index_arg, 1708 | &output_device_index_arg, 1709 | &frames_per_buffer, 1710 | #ifdef MACOSX 1711 | &_pyAudio_MacOSX_hostApiSpecificStreamInfoType, 1712 | #endif 1713 | &inputHostSpecificStreamInfo, 1714 | #ifdef MACOSX 1715 | &_pyAudio_MacOSX_hostApiSpecificStreamInfoType, 1716 | #endif 1717 | &outputHostSpecificStreamInfo, 1718 | &stream_callback)) 1719 | 1720 | return NULL; 1721 | 1722 | if (stream_callback && (PyCallable_Check(stream_callback) == 0)) { 1723 | PyErr_SetString(PyExc_TypeError, "stream_callback must be callable"); 1724 | return NULL; 1725 | } 1726 | 1727 | /* check to see if device indices were specified */ 1728 | if ((input_device_index_arg == NULL) || 1729 | (input_device_index_arg == Py_None)) { 1730 | 1731 | #ifdef VERBOSE 1732 | printf("Using default input device\n"); 1733 | #endif 1734 | 1735 | input_device_index = -1; 1736 | 1737 | } else { 1738 | // Support both Python 2 and Python 3 by using PyNumber_Check 1739 | if (!PyNumber_Check(input_device_index_arg)) { 1740 | PyErr_SetString(PyExc_ValueError, 1741 | "input_device_index must be integer (or None)"); 1742 | return NULL; 1743 | } 1744 | 1745 | input_device_index_long = 1746 | PyNumber_Long(input_device_index_arg); 1747 | 1748 | input_device_index = (int) PyLong_AsLong(input_device_index_long); 1749 | Py_DECREF(input_device_index_long); 1750 | 1751 | #ifdef VERBOSE 1752 | printf("Using input device index number: %d\n", input_device_index); 1753 | #endif 1754 | } 1755 | 1756 | if ((output_device_index_arg == NULL) || 1757 | (output_device_index_arg == Py_None)) { 1758 | 1759 | #ifdef VERBOSE 1760 | printf("Using default output device\n"); 1761 | #endif 1762 | 1763 | output_device_index = -1; 1764 | 1765 | } else { 1766 | // Support both Python 2 and Python 3 by using PyNumber_Check 1767 | if (!PyNumber_Check(output_device_index_arg)) { 1768 | PyErr_SetString(PyExc_ValueError, 1769 | "output_device_index must be integer (or None)"); 1770 | return NULL; 1771 | } 1772 | 1773 | output_device_index_long = 1774 | PyNumber_Long(output_device_index_arg); 1775 | output_device_index = (int) PyLong_AsLong(output_device_index_long); 1776 | Py_DECREF(output_device_index_long); 1777 | 1778 | #ifdef VERBOSE 1779 | printf("Using output device index number: %d\n", output_device_index); 1780 | #endif 1781 | } 1782 | 1783 | /* sanity checks */ 1784 | if (input == 0 && output == 0) { 1785 | PyErr_SetString(PyExc_ValueError, "Must specify either input or output"); 1786 | return NULL; 1787 | } 1788 | 1789 | if (channels < 1) { 1790 | PyErr_SetString(PyExc_ValueError, "Invalid audio channels"); 1791 | return NULL; 1792 | } 1793 | 1794 | if (output) { 1795 | outputParameters = 1796 | (PaStreamParameters *) malloc(sizeof(PaStreamParameters)); 1797 | 1798 | 1799 | if (output_device_index < 0) 1800 | /* default output device */ 1801 | outputParameters->device = Pa_GetDefaultOutputDevice(); 1802 | else 1803 | outputParameters->device = output_device_index; 1804 | 1805 | /* final check -- ensure that there is a default device */ 1806 | if (outputParameters->device < 0 || 1807 | outputParameters->device >= Pa_GetDeviceCount()) { 1808 | free(outputParameters); 1809 | PyErr_SetObject(PyExc_IOError, 1810 | Py_BuildValue("(s,i)", 1811 | "Invalid output device " 1812 | "(no default output device)", 1813 | paInvalidDevice)); 1814 | return NULL; 1815 | } 1816 | 1817 | outputParameters->channelCount = channels; 1818 | outputParameters->sampleFormat = format; 1819 | outputParameters->suggestedLatency = 1820 | Pa_GetDeviceInfo(outputParameters->device)->defaultLowOutputLatency; 1821 | outputParameters->hostApiSpecificStreamInfo = NULL; 1822 | 1823 | #ifdef MACOSX 1824 | if (outputHostSpecificStreamInfo) { 1825 | outputParameters->hostApiSpecificStreamInfo = 1826 | outputHostSpecificStreamInfo->paMacCoreStreamInfo; 1827 | } 1828 | #endif 1829 | 1830 | } 1831 | 1832 | if (input) { 1833 | inputParameters = 1834 | (PaStreamParameters *) malloc(sizeof(PaStreamParameters)); 1835 | 1836 | if (input_device_index < 0) { 1837 | /* default output device */ 1838 | inputParameters->device = Pa_GetDefaultInputDevice(); 1839 | } else { 1840 | inputParameters->device = input_device_index; 1841 | } 1842 | 1843 | /* final check -- ensure that there is a default device */ 1844 | if (inputParameters->device < 0) { 1845 | free(inputParameters); 1846 | PyErr_SetObject(PyExc_IOError, 1847 | Py_BuildValue("(s,i)", 1848 | "Invalid input device " 1849 | "(no default output device)", 1850 | paInvalidDevice)); 1851 | return NULL; 1852 | } 1853 | 1854 | inputParameters->channelCount = channels; 1855 | inputParameters->sampleFormat = format; 1856 | inputParameters->suggestedLatency = 1857 | Pa_GetDeviceInfo(inputParameters->device)->defaultLowInputLatency; 1858 | inputParameters->hostApiSpecificStreamInfo = NULL; 1859 | 1860 | #ifdef MACOSX 1861 | if (inputHostSpecificStreamInfo) { 1862 | inputParameters->hostApiSpecificStreamInfo = 1863 | inputHostSpecificStreamInfo->paMacCoreStreamInfo; 1864 | } 1865 | #endif 1866 | 1867 | } 1868 | 1869 | // Handle callback mode: 1870 | if (stream_callback) { 1871 | Py_INCREF(stream_callback); 1872 | context = (PyAudioCallbackContext *) malloc(sizeof(PyAudioCallbackContext)); 1873 | context->callback = (PyObject *) stream_callback; 1874 | context->main_thread_id = PyThreadState_Get()->thread_id; 1875 | context->frame_size = Pa_GetSampleSize(format) * channels; 1876 | } 1877 | 1878 | err = Pa_OpenStream(&stream, 1879 | /* input/output parameters */ 1880 | /* NULL values are ignored */ 1881 | inputParameters, 1882 | outputParameters, 1883 | /* Samples Per Second */ 1884 | rate, 1885 | /* allocate frames in the buffer */ 1886 | frames_per_buffer, 1887 | /* we won't output out of range samples 1888 | so don't bother clipping them */ 1889 | paClipOff, 1890 | /* callback, if specified */ 1891 | (stream_callback)?(_stream_callback_cfunction):(NULL), 1892 | /* callback userData, if applicable */ 1893 | context); 1894 | 1895 | if (err != paNoError) { 1896 | 1897 | #ifdef VERBOSE 1898 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 1899 | fprintf(stderr, "Error number: %d\n", err); 1900 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); 1901 | #endif 1902 | 1903 | PyErr_SetObject(PyExc_IOError, 1904 | Py_BuildValue("(s,i)", 1905 | Pa_GetErrorText(err), err)); 1906 | return NULL; 1907 | } 1908 | 1909 | streamInfo = (PaStreamInfo *) Pa_GetStreamInfo(stream); 1910 | if (!streamInfo) { 1911 | /* Pa_Terminate(); */ 1912 | PyErr_SetObject(PyExc_IOError, 1913 | Py_BuildValue("(s,i)", 1914 | "Could not get stream information", 1915 | paInternalError)); 1916 | return NULL; 1917 | } 1918 | 1919 | streamObject = _create_Stream_object(); 1920 | streamObject->stream = stream; 1921 | streamObject->inputParameters = inputParameters; 1922 | streamObject->outputParameters = outputParameters; 1923 | streamObject->is_open = 1; 1924 | streamObject->streamInfo = streamInfo; 1925 | streamObject->callbackContext = context; 1926 | 1927 | return (PyObject *) streamObject; 1928 | } 1929 | 1930 | static PyObject * 1931 | pa_close(PyObject *self, PyObject *args) 1932 | { 1933 | PyObject *stream_arg; 1934 | _pyAudio_Stream *streamObject; 1935 | 1936 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) 1937 | return NULL; 1938 | 1939 | streamObject = (_pyAudio_Stream *) stream_arg; 1940 | 1941 | _cleanup_Stream_object(streamObject); 1942 | 1943 | Py_INCREF(Py_None); 1944 | return Py_None; 1945 | } 1946 | 1947 | static PyObject * 1948 | pa_get_sample_size(PyObject *self, PyObject *args) 1949 | { 1950 | PaSampleFormat format; 1951 | int size_in_bytes; 1952 | 1953 | if (!PyArg_ParseTuple(args, "k", &format)) 1954 | return NULL; 1955 | 1956 | size_in_bytes = Pa_GetSampleSize(format); 1957 | 1958 | if (size_in_bytes < 0) { 1959 | PyErr_SetObject(PyExc_ValueError, 1960 | Py_BuildValue("(s,i)", 1961 | Pa_GetErrorText(size_in_bytes), 1962 | size_in_bytes)); 1963 | return NULL; 1964 | } 1965 | 1966 | return PyLong_FromLong(size_in_bytes); 1967 | } 1968 | 1969 | 1970 | static PyObject * 1971 | pa_is_format_supported(PyObject *self, PyObject *args, 1972 | PyObject *kwargs) 1973 | { 1974 | /* pass in rate, channel, width */ 1975 | static char *kwlist[] = { 1976 | "sample_rate", 1977 | "input_device", 1978 | "input_channels", 1979 | "input_format", 1980 | "output_device", 1981 | "output_channels", 1982 | "output_format", 1983 | NULL 1984 | }; 1985 | 1986 | int input_device, input_channels; 1987 | int output_device, output_channels; 1988 | float sample_rate; 1989 | PaStreamParameters inputParams; 1990 | PaStreamParameters outputParams; 1991 | PaSampleFormat input_format, output_format; 1992 | PaError error; 1993 | 1994 | input_device = input_channels = 1995 | output_device = output_channels = -1; 1996 | 1997 | input_format = output_format = -1; 1998 | 1999 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "f|iikiik", kwlist, 2000 | &sample_rate, 2001 | &input_device, 2002 | &input_channels, 2003 | &input_format, 2004 | &output_device, 2005 | &output_channels, 2006 | &output_format)) 2007 | return NULL; 2008 | 2009 | if (!(input_device < 0)) { 2010 | inputParams.device = input_device; 2011 | inputParams.channelCount = input_channels; 2012 | inputParams.sampleFormat = input_format; 2013 | inputParams.suggestedLatency = 0; 2014 | inputParams.hostApiSpecificStreamInfo = NULL; 2015 | } 2016 | 2017 | if (!(output_device < 0)) { 2018 | outputParams.device = output_device; 2019 | outputParams.channelCount = output_channels; 2020 | outputParams.sampleFormat = output_format; 2021 | outputParams.suggestedLatency = 0; 2022 | outputParams.hostApiSpecificStreamInfo = NULL; 2023 | } 2024 | 2025 | error = Pa_IsFormatSupported((input_device < 0) ? NULL : &inputParams, 2026 | (output_device < 0) ? NULL : &outputParams, 2027 | sample_rate); 2028 | 2029 | if (error == paFormatIsSupported) { 2030 | Py_INCREF(Py_True); 2031 | return Py_True; 2032 | } else { 2033 | PyErr_SetObject(PyExc_ValueError, 2034 | Py_BuildValue("(s,i)", 2035 | Pa_GetErrorText(error), 2036 | error)); 2037 | return NULL; 2038 | } 2039 | } 2040 | 2041 | /************************************************************* 2042 | * Stream Start / Stop / Info 2043 | *************************************************************/ 2044 | 2045 | static PyObject * 2046 | pa_start_stream(PyObject *self, PyObject *args) 2047 | { 2048 | int err; 2049 | PyObject *stream_arg; 2050 | _pyAudio_Stream *streamObject; 2051 | PaStream *stream; 2052 | 2053 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) 2054 | return NULL; 2055 | 2056 | streamObject = (_pyAudio_Stream *) stream_arg; 2057 | 2058 | if (!_is_open(streamObject)) { 2059 | PyErr_SetObject(PyExc_IOError, 2060 | Py_BuildValue("(s,i)", 2061 | "Stream closed", 2062 | paBadStreamPtr)); 2063 | return NULL; 2064 | } 2065 | 2066 | stream = streamObject->stream; 2067 | 2068 | if ( ((err = Pa_StartStream(stream)) != paNoError) && 2069 | (err != paStreamIsNotStopped)) { 2070 | _cleanup_Stream_object(streamObject); 2071 | 2072 | #ifdef VERBOSE 2073 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 2074 | fprintf(stderr, "Error number: %d\n", err); 2075 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); 2076 | #endif 2077 | 2078 | PyErr_SetObject(PyExc_IOError, 2079 | Py_BuildValue("(s,i)", 2080 | Pa_GetErrorText(err), 2081 | err)); 2082 | return NULL; 2083 | } 2084 | 2085 | Py_INCREF(Py_None); 2086 | return Py_None; 2087 | } 2088 | 2089 | static PyObject * 2090 | pa_stop_stream(PyObject *self, PyObject *args) 2091 | { 2092 | 2093 | int err; 2094 | PyObject *stream_arg; 2095 | _pyAudio_Stream *streamObject; 2096 | PaStream *stream; 2097 | 2098 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) 2099 | return NULL; 2100 | 2101 | streamObject = (_pyAudio_Stream *) stream_arg; 2102 | 2103 | if (!_is_open(streamObject)) { 2104 | PyErr_SetString(PyExc_IOError, "Stream not open"); 2105 | return NULL; 2106 | } 2107 | 2108 | stream = streamObject->stream; 2109 | 2110 | Py_BEGIN_ALLOW_THREADS 2111 | err = Pa_StopStream(stream); 2112 | Py_END_ALLOW_THREADS 2113 | 2114 | if ((err != paNoError) && (err != paStreamIsStopped)) { 2115 | _cleanup_Stream_object(streamObject); 2116 | 2117 | #ifdef VERBOSE 2118 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 2119 | fprintf(stderr, "Error number: %d\n", err); 2120 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); 2121 | #endif 2122 | 2123 | PyErr_SetObject(PyExc_IOError, 2124 | Py_BuildValue("(s,i)", 2125 | Pa_GetErrorText(err), 2126 | err)); 2127 | return NULL; 2128 | } 2129 | 2130 | Py_INCREF(Py_None); 2131 | return Py_None; 2132 | } 2133 | 2134 | static PyObject * 2135 | pa_abort_stream(PyObject *self, PyObject *args) 2136 | { 2137 | int err; 2138 | PyObject *stream_arg; 2139 | _pyAudio_Stream *streamObject; 2140 | PaStream *stream; 2141 | 2142 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) 2143 | return NULL; 2144 | 2145 | streamObject = (_pyAudio_Stream *) stream_arg; 2146 | 2147 | if (!_is_open(streamObject)) { 2148 | PyErr_SetString(PyExc_IOError, "Stream not open"); 2149 | return NULL; 2150 | } 2151 | 2152 | stream = streamObject->stream; 2153 | 2154 | Py_BEGIN_ALLOW_THREADS 2155 | err = Pa_AbortStream(stream); 2156 | Py_END_ALLOW_THREADS 2157 | 2158 | if ((err != paNoError) && (err != paStreamIsStopped)) { 2159 | _cleanup_Stream_object(streamObject); 2160 | 2161 | #ifdef VERBOSE 2162 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 2163 | fprintf(stderr, "Error number: %d\n", err); 2164 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); 2165 | #endif 2166 | 2167 | PyErr_SetObject(PyExc_IOError, 2168 | Py_BuildValue("(s,i)", 2169 | Pa_GetErrorText(err), 2170 | err)); 2171 | return NULL; 2172 | } 2173 | 2174 | Py_INCREF(Py_None); 2175 | return Py_None; 2176 | } 2177 | 2178 | static PyObject * 2179 | pa_is_stream_stopped(PyObject *self, PyObject *args) 2180 | { 2181 | int err; 2182 | PyObject *stream_arg; 2183 | _pyAudio_Stream *streamObject; 2184 | PaStream *stream; 2185 | 2186 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) 2187 | return NULL; 2188 | 2189 | streamObject = (_pyAudio_Stream *) stream_arg; 2190 | 2191 | if (!_is_open(streamObject)) { 2192 | PyErr_SetObject(PyExc_IOError, 2193 | Py_BuildValue("(s,i)", 2194 | "Stream closed", 2195 | paBadStreamPtr)); 2196 | return NULL; 2197 | } 2198 | 2199 | stream = streamObject->stream; 2200 | 2201 | if ((err = Pa_IsStreamStopped(stream)) < 0) { 2202 | _cleanup_Stream_object(streamObject); 2203 | 2204 | #ifdef VERBOSE 2205 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 2206 | fprintf(stderr, "Error number: %d\n", err); 2207 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); 2208 | #endif 2209 | 2210 | PyErr_SetObject(PyExc_IOError, 2211 | Py_BuildValue("(s,i)", 2212 | Pa_GetErrorText(err), 2213 | err)); 2214 | return NULL; 2215 | } 2216 | 2217 | if (err) { 2218 | Py_INCREF(Py_True); 2219 | return Py_True; 2220 | } 2221 | 2222 | Py_INCREF(Py_False); 2223 | return Py_False; 2224 | } 2225 | 2226 | static PyObject * 2227 | pa_is_stream_active(PyObject *self, PyObject *args) 2228 | { 2229 | 2230 | int err; 2231 | PyObject *stream_arg; 2232 | _pyAudio_Stream *streamObject; 2233 | PaStream *stream; 2234 | 2235 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) 2236 | return NULL; 2237 | 2238 | streamObject = (_pyAudio_Stream *) stream_arg; 2239 | 2240 | if (!_is_open(streamObject)) { 2241 | PyErr_SetString(PyExc_IOError, "Stream not open"); 2242 | return NULL; 2243 | } 2244 | 2245 | stream = streamObject->stream; 2246 | 2247 | if ((err = Pa_IsStreamActive(stream)) < 0) { 2248 | _cleanup_Stream_object(streamObject); 2249 | 2250 | #ifdef VERBOSE 2251 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 2252 | fprintf(stderr, "Error number: %d\n", err); 2253 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); 2254 | #endif 2255 | 2256 | PyErr_SetObject(PyExc_IOError, 2257 | Py_BuildValue("(s,i)", 2258 | Pa_GetErrorText(err), 2259 | err)); 2260 | return NULL; 2261 | } 2262 | 2263 | if (err) { 2264 | Py_INCREF(Py_True); 2265 | return Py_True; 2266 | } 2267 | 2268 | Py_INCREF(Py_False); 2269 | return Py_False; 2270 | } 2271 | 2272 | static PyObject * 2273 | pa_get_stream_time(PyObject *self, PyObject *args) 2274 | { 2275 | double time; 2276 | PyObject *stream_arg; 2277 | _pyAudio_Stream *streamObject; 2278 | PaStream *stream; 2279 | 2280 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) 2281 | return NULL; 2282 | 2283 | streamObject = (_pyAudio_Stream *) stream_arg; 2284 | 2285 | if (!_is_open(streamObject)) { 2286 | PyErr_SetObject(PyExc_IOError, 2287 | Py_BuildValue("(s,i)", 2288 | "Stream closed", 2289 | paBadStreamPtr)); 2290 | return NULL; 2291 | } 2292 | 2293 | stream = streamObject->stream; 2294 | 2295 | if ((time = Pa_GetStreamTime(stream)) == 0) { 2296 | _cleanup_Stream_object(streamObject); 2297 | PyErr_SetObject(PyExc_IOError, 2298 | Py_BuildValue("(s,i)", 2299 | "Internal Error", 2300 | paInternalError)); 2301 | return NULL; 2302 | } 2303 | 2304 | return PyFloat_FromDouble(time); 2305 | } 2306 | 2307 | static PyObject * 2308 | pa_get_stream_cpu_load(PyObject *self, PyObject *args) 2309 | { 2310 | PyObject *stream_arg; 2311 | _pyAudio_Stream *streamObject; 2312 | PaStream *stream; 2313 | 2314 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) 2315 | return NULL; 2316 | 2317 | streamObject = (_pyAudio_Stream *) stream_arg; 2318 | 2319 | if (!_is_open(streamObject)) { 2320 | PyErr_SetObject(PyExc_IOError, 2321 | Py_BuildValue("(s,i)", 2322 | "Stream closed", 2323 | paBadStreamPtr)); 2324 | return NULL; 2325 | } 2326 | 2327 | stream = streamObject->stream; 2328 | return PyFloat_FromDouble(Pa_GetStreamCpuLoad(stream)); 2329 | } 2330 | 2331 | 2332 | /************************************************************* 2333 | * Stream Read/Write 2334 | *************************************************************/ 2335 | 2336 | static PyObject * 2337 | pa_write_stream(PyObject *self, PyObject *args) 2338 | { 2339 | const char *data; 2340 | int total_size; 2341 | int total_frames; 2342 | int err; 2343 | int should_throw_exception = 0; 2344 | 2345 | PyObject *stream_arg; 2346 | _pyAudio_Stream *streamObject; 2347 | PaStream *stream; 2348 | 2349 | if (!PyArg_ParseTuple(args, "O!s#i|i", 2350 | &_pyAudio_StreamType, 2351 | &stream_arg, 2352 | &data, 2353 | &total_size, 2354 | &total_frames, 2355 | &should_throw_exception)) 2356 | return NULL; 2357 | 2358 | /* make sure total frames is larger than 0 */ 2359 | if (total_frames < 0) { 2360 | PyErr_SetString(PyExc_ValueError, 2361 | "Invalid number of frames"); 2362 | return NULL; 2363 | } 2364 | 2365 | streamObject = (_pyAudio_Stream *) stream_arg; 2366 | 2367 | if (!_is_open(streamObject)) { 2368 | PyErr_SetObject(PyExc_IOError, 2369 | Py_BuildValue("(s,i)", 2370 | "Stream closed", 2371 | paBadStreamPtr)); 2372 | return NULL; 2373 | } 2374 | 2375 | stream = streamObject->stream; 2376 | 2377 | Py_BEGIN_ALLOW_THREADS 2378 | err = Pa_WriteStream(stream, data, total_frames); 2379 | Py_END_ALLOW_THREADS 2380 | 2381 | if (err != paNoError) { 2382 | if (err == paOutputUnderflowed) { 2383 | if (should_throw_exception) 2384 | goto error; 2385 | } else 2386 | goto error; 2387 | } 2388 | 2389 | Py_INCREF(Py_None); 2390 | return Py_None; 2391 | 2392 | error: 2393 | /* cleanup */ 2394 | _cleanup_Stream_object(streamObject); 2395 | 2396 | #ifdef VERBOSE 2397 | fprintf(stderr, "An error occured while using the portaudio stream\n"); 2398 | fprintf(stderr, "Error number: %d\n", err); 2399 | fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); 2400 | #endif 2401 | 2402 | PyErr_SetObject(PyExc_IOError, 2403 | Py_BuildValue("(s,i)", 2404 | Pa_GetErrorText(err), 2405 | err)); 2406 | return NULL; 2407 | } 2408 | 2409 | static PyObject * 2410 | pa_read_stream(PyObject *self, PyObject *args) 2411 | { 2412 | int err; 2413 | int total_frames; 2414 | short *sampleBlock; 2415 | int num_bytes; 2416 | int should_warn = 0; 2417 | PyObject *rv; 2418 | 2419 | PyObject *stream_arg; 2420 | _pyAudio_Stream *streamObject; 2421 | PaStream *stream; 2422 | PaStreamParameters *inputParameters; 2423 | 2424 | if (!PyArg_ParseTuple(args, "O!i|i", 2425 | &_pyAudio_StreamType, 2426 | &stream_arg, 2427 | &total_frames, 2428 | &should_warn)) 2429 | return NULL; 2430 | 2431 | /* make sure value is positive! */ 2432 | if (total_frames < 0) { 2433 | PyErr_SetString(PyExc_ValueError, "Invalid number of frames"); 2434 | return NULL; 2435 | } 2436 | 2437 | streamObject = (_pyAudio_Stream *) stream_arg; 2438 | 2439 | if (!_is_open(streamObject)) { 2440 | PyErr_SetObject(PyExc_IOError, 2441 | Py_BuildValue("(s,i)", 2442 | "Stream closed", 2443 | paBadStreamPtr)); 2444 | return NULL; 2445 | } 2446 | 2447 | stream = streamObject->stream; 2448 | inputParameters = streamObject->inputParameters; 2449 | num_bytes = (total_frames) * (inputParameters->channelCount) * 2450 | (Pa_GetSampleSize(inputParameters->sampleFormat)); 2451 | 2452 | #ifdef VERBOSE 2453 | fprintf(stderr, "Allocating %d bytes\n", num_bytes); 2454 | #endif 2455 | 2456 | rv = PyBytes_FromStringAndSize(NULL, num_bytes); 2457 | sampleBlock = (short *) PyBytes_AsString(rv); 2458 | 2459 | if (sampleBlock == NULL) { 2460 | PyErr_SetObject(PyExc_IOError, 2461 | Py_BuildValue("(s,i)", 2462 | "Out of memory", 2463 | paInsufficientMemory)); 2464 | return NULL; 2465 | } 2466 | 2467 | Py_BEGIN_ALLOW_THREADS 2468 | err = Pa_ReadStream(stream, sampleBlock, total_frames); 2469 | Py_END_ALLOW_THREADS 2470 | 2471 | if (err != paNoError) { 2472 | 2473 | /* ignore input overflow and output underflow */ 2474 | if (err & paInputOverflowed) { 2475 | 2476 | if (should_warn) 2477 | fprintf(stderr, "WARN: Received paInputOverflowed\n"); 2478 | 2479 | #ifdef VERBOSE 2480 | fprintf(stderr, "Input Overflow.\n"); 2481 | #endif 2482 | 2483 | } else if (err & paOutputUnderflowed) { 2484 | 2485 | #ifdef VERBOSE 2486 | fprintf(stderr, "Output Underflow.\n"); 2487 | #endif 2488 | 2489 | } else { 2490 | /* clean up */ 2491 | _cleanup_Stream_object(streamObject); 2492 | 2493 | /* free the string buffer */ 2494 | Py_XDECREF(rv); 2495 | 2496 | PyErr_SetObject(PyExc_IOError, 2497 | Py_BuildValue("(s,i)", 2498 | Pa_GetErrorText(err), err)); 2499 | return NULL; 2500 | } 2501 | } 2502 | 2503 | return rv; 2504 | } 2505 | 2506 | static PyObject * 2507 | pa_get_stream_write_available(PyObject *self, PyObject *args) 2508 | { 2509 | signed long frames; 2510 | PyObject *stream_arg; 2511 | _pyAudio_Stream *streamObject; 2512 | PaStream *stream; 2513 | 2514 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) 2515 | return NULL; 2516 | 2517 | streamObject = (_pyAudio_Stream *) stream_arg; 2518 | 2519 | if (!_is_open(streamObject)) { 2520 | PyErr_SetObject(PyExc_IOError, 2521 | Py_BuildValue("(s,i)", 2522 | "Stream closed", 2523 | paBadStreamPtr)); 2524 | return NULL; 2525 | } 2526 | 2527 | stream = streamObject->stream; 2528 | frames = Pa_GetStreamWriteAvailable(stream); 2529 | return PyLong_FromLong(frames); 2530 | } 2531 | 2532 | static PyObject * 2533 | pa_get_stream_read_available(PyObject *self, PyObject *args) 2534 | { 2535 | signed long frames; 2536 | PyObject *stream_arg; 2537 | _pyAudio_Stream *streamObject; 2538 | PaStream *stream; 2539 | 2540 | if (!PyArg_ParseTuple(args, "O!", &_pyAudio_StreamType, &stream_arg)) 2541 | return NULL; 2542 | 2543 | streamObject = (_pyAudio_Stream *) stream_arg; 2544 | 2545 | if (!_is_open(streamObject)) { 2546 | PyErr_SetObject(PyExc_IOError, 2547 | Py_BuildValue("(s,i)", 2548 | "Stream closed", 2549 | paBadStreamPtr)); 2550 | return NULL; 2551 | } 2552 | 2553 | stream = streamObject->stream; 2554 | frames = Pa_GetStreamReadAvailable(stream); 2555 | return PyLong_FromLong(frames); 2556 | } 2557 | 2558 | 2559 | /************************************************************ 2560 | * 2561 | * IV. Python Module Init 2562 | * 2563 | ************************************************************/ 2564 | 2565 | #if PY_MAJOR_VERSION >= 3 2566 | #define ERROR_INIT NULL 2567 | #else 2568 | #define ERROR_INIT /**/ 2569 | #endif 2570 | 2571 | #if PY_MAJOR_VERSION >= 3 2572 | static struct PyModuleDef moduledef = { 2573 | PyModuleDef_HEAD_INIT, 2574 | "_portaudio", 2575 | NULL, 2576 | -1, 2577 | paMethods, 2578 | NULL, 2579 | NULL, 2580 | NULL, 2581 | NULL 2582 | }; 2583 | #endif 2584 | 2585 | PyMODINIT_FUNC 2586 | #if PY_MAJOR_VERSION >= 3 2587 | PyInit__portaudio(void) 2588 | #else 2589 | init_portaudio(void) 2590 | #endif 2591 | { 2592 | PyObject* m; 2593 | 2594 | PyEval_InitThreads(); 2595 | 2596 | _pyAudio_StreamType.tp_new = PyType_GenericNew; 2597 | if (PyType_Ready(&_pyAudio_StreamType) < 0) 2598 | return ERROR_INIT; 2599 | 2600 | _pyAudio_paDeviceInfoType.tp_new = PyType_GenericNew; 2601 | if (PyType_Ready(&_pyAudio_paDeviceInfoType) < 0) 2602 | return ERROR_INIT; 2603 | 2604 | _pyAudio_paHostApiInfoType.tp_new = PyType_GenericNew; 2605 | if (PyType_Ready(&_pyAudio_paHostApiInfoType) < 0) 2606 | return ERROR_INIT; 2607 | 2608 | #ifdef MACOSX 2609 | _pyAudio_MacOSX_hostApiSpecificStreamInfoType.tp_new = PyType_GenericNew; 2610 | if (PyType_Ready(&_pyAudio_MacOSX_hostApiSpecificStreamInfoType) < 0) 2611 | return ERROR_INIT; 2612 | #endif 2613 | 2614 | #if PY_MAJOR_VERSION >= 3 2615 | m = PyModule_Create(&moduledef); 2616 | #else 2617 | m = Py_InitModule("_portaudio", paMethods); 2618 | #endif 2619 | 2620 | Py_INCREF(&_pyAudio_StreamType); 2621 | Py_INCREF(&_pyAudio_paDeviceInfoType); 2622 | Py_INCREF(&_pyAudio_paHostApiInfoType); 2623 | 2624 | #ifdef MACOSX 2625 | Py_INCREF(&_pyAudio_MacOSX_hostApiSpecificStreamInfoType); 2626 | PyModule_AddObject(m, "paMacCoreStreamInfo", 2627 | (PyObject *) 2628 | &_pyAudio_MacOSX_hostApiSpecificStreamInfoType); 2629 | #endif 2630 | 2631 | /* Add PortAudio constants */ 2632 | 2633 | /* host apis */ 2634 | PyModule_AddIntConstant(m, "paInDevelopment", paInDevelopment); 2635 | PyModule_AddIntConstant(m, "paDirectSound", paDirectSound); 2636 | PyModule_AddIntConstant(m, "paMME", paMME); 2637 | PyModule_AddIntConstant(m, "paASIO", paASIO); 2638 | PyModule_AddIntConstant(m, "paSoundManager", paSoundManager); 2639 | PyModule_AddIntConstant(m, "paCoreAudio", paCoreAudio); 2640 | PyModule_AddIntConstant(m, "paOSS", paOSS); 2641 | PyModule_AddIntConstant(m, "paALSA", paALSA); 2642 | PyModule_AddIntConstant(m, "paAL", paAL); 2643 | PyModule_AddIntConstant(m, "paBeOS", paBeOS); 2644 | PyModule_AddIntConstant(m, "paWDMKS", paWDMKS); 2645 | PyModule_AddIntConstant(m, "paJACK", paJACK); 2646 | PyModule_AddIntConstant(m, "paWASAPI", paWASAPI); 2647 | PyModule_AddIntConstant(m, "paNoDevice", paNoDevice); 2648 | 2649 | /* formats */ 2650 | PyModule_AddIntConstant(m, "paFloat32", paFloat32); 2651 | PyModule_AddIntConstant(m, "paInt32", paInt32); 2652 | PyModule_AddIntConstant(m, "paInt24", paInt24); 2653 | PyModule_AddIntConstant(m, "paInt16", paInt16); 2654 | PyModule_AddIntConstant(m, "paInt8", paInt8); 2655 | PyModule_AddIntConstant(m, "paUInt8", paUInt8); 2656 | PyModule_AddIntConstant(m, "paCustomFormat", paCustomFormat); 2657 | 2658 | /* error codes */ 2659 | PyModule_AddIntConstant(m, "paNoError", paNoError); 2660 | PyModule_AddIntConstant(m, "paNotInitialized", paNotInitialized); 2661 | PyModule_AddIntConstant(m, "paUnanticipatedHostError", 2662 | paUnanticipatedHostError); 2663 | PyModule_AddIntConstant(m, "paInvalidChannelCount", 2664 | paInvalidChannelCount); 2665 | PyModule_AddIntConstant(m, "paInvalidSampleRate", 2666 | paInvalidSampleRate); 2667 | PyModule_AddIntConstant(m, "paInvalidDevice", paInvalidDevice); 2668 | PyModule_AddIntConstant(m, "paInvalidFlag", paInvalidFlag); 2669 | PyModule_AddIntConstant(m, "paSampleFormatNotSupported", 2670 | paSampleFormatNotSupported); 2671 | PyModule_AddIntConstant(m, "paBadIODeviceCombination", 2672 | paBadIODeviceCombination); 2673 | PyModule_AddIntConstant(m, "paInsufficientMemory", 2674 | paInsufficientMemory); 2675 | PyModule_AddIntConstant(m, "paBufferTooBig", paBufferTooBig); 2676 | PyModule_AddIntConstant(m, "paBufferTooSmall", paBufferTooSmall); 2677 | PyModule_AddIntConstant(m, "paNullCallback", paNullCallback); 2678 | PyModule_AddIntConstant(m, "paBadStreamPtr", paBadStreamPtr); 2679 | PyModule_AddIntConstant(m, "paTimedOut", paTimedOut); 2680 | PyModule_AddIntConstant(m, "paInternalError", paInternalError); 2681 | PyModule_AddIntConstant(m, "paDeviceUnavailable", paDeviceUnavailable); 2682 | PyModule_AddIntConstant(m, "paIncompatibleHostApiSpecificStreamInfo", 2683 | paIncompatibleHostApiSpecificStreamInfo); 2684 | PyModule_AddIntConstant(m, "paStreamIsStopped", paStreamIsStopped); 2685 | PyModule_AddIntConstant(m, "paStreamIsNotStopped", paStreamIsNotStopped); 2686 | PyModule_AddIntConstant(m, "paInputOverflowed", paInputOverflowed); 2687 | PyModule_AddIntConstant(m, "paOutputUnderflowed", paOutputUnderflowed); 2688 | PyModule_AddIntConstant(m, "paHostApiNotFound", paHostApiNotFound); 2689 | PyModule_AddIntConstant(m, "paInvalidHostApi", paInvalidHostApi); 2690 | PyModule_AddIntConstant(m, "paCanNotReadFromACallbackStream", 2691 | paCanNotReadFromACallbackStream); 2692 | PyModule_AddIntConstant(m, "paCanNotWriteToACallbackStream", 2693 | paCanNotWriteToACallbackStream); 2694 | PyModule_AddIntConstant(m, "paCanNotReadFromAnOutputOnlyStream", 2695 | paCanNotReadFromAnOutputOnlyStream); 2696 | PyModule_AddIntConstant(m, "paCanNotWriteToAnInputOnlyStream", 2697 | paCanNotWriteToAnInputOnlyStream); 2698 | PyModule_AddIntConstant(m, "paIncompatibleStreamHostApi", 2699 | paIncompatibleStreamHostApi); 2700 | 2701 | /* callback constants */ 2702 | PyModule_AddIntConstant(m, "paContinue", paContinue); 2703 | PyModule_AddIntConstant(m, "paComplete", paComplete); 2704 | PyModule_AddIntConstant(m, "paAbort", paAbort); 2705 | 2706 | /* callback status flags */ 2707 | PyModule_AddIntConstant(m, "paInputUnderflow", paInputUnderflow); 2708 | PyModule_AddIntConstant(m, "paInputOverflow", paInputOverflow); 2709 | PyModule_AddIntConstant(m, "paOutputUnderflow", paOutputUnderflow); 2710 | PyModule_AddIntConstant(m, "paOutputOverflow", paOutputOverflow); 2711 | PyModule_AddIntConstant(m, "paPrimingOutput", paPrimingOutput); 2712 | 2713 | #ifdef MACOSX 2714 | PyModule_AddIntConstant(m, "paMacCoreChangeDeviceParameters", 2715 | paMacCoreChangeDeviceParameters); 2716 | PyModule_AddIntConstant(m, "paMacCoreFailIfConversionRequired", 2717 | paMacCoreFailIfConversionRequired); 2718 | PyModule_AddIntConstant(m, "paMacCoreConversionQualityMin", 2719 | paMacCoreConversionQualityMin); 2720 | PyModule_AddIntConstant(m, "paMacCoreConversionQualityMedium", 2721 | paMacCoreConversionQualityMedium); 2722 | PyModule_AddIntConstant(m, "paMacCoreConversionQualityLow", 2723 | paMacCoreConversionQualityLow); 2724 | PyModule_AddIntConstant(m, "paMacCoreConversionQualityHigh", 2725 | paMacCoreConversionQualityHigh); 2726 | PyModule_AddIntConstant(m, "paMacCoreConversionQualityMax", 2727 | paMacCoreConversionQualityMax); 2728 | PyModule_AddIntConstant(m, "paMacCorePlayNice", 2729 | paMacCorePlayNice); 2730 | PyModule_AddIntConstant(m, "paMacCorePro", 2731 | paMacCorePro); 2732 | PyModule_AddIntConstant(m, "paMacCoreMinimizeCPUButPlayNice", 2733 | paMacCoreMinimizeCPUButPlayNice); 2734 | PyModule_AddIntConstant(m, "paMacCoreMinimizeCPU", 2735 | paMacCoreMinimizeCPU); 2736 | #endif 2737 | 2738 | #if PY_MAJOR_VERSION >= 3 2739 | return m; 2740 | #endif 2741 | } 2742 | --------------------------------------------------------------------------------