Files
sw_pyalsaaudio/doc/pyalsaaudio.rst
Oswald Buddenhagen 196ca87a05 assorted improvements (#123)
* fix draining/closing, take 2

commit 8abf06be introduced a pause() prior to draining, in an attempt
to work around clearly broken pulseaudio client behavior for capture
streams (drain() is supposed to imply a stop).

but as the workaround was also applied to playback streams, it would
cause nasty "clicks", as the stream would (obviously) stop before being
resumed for draining.

but draining is actually pointless for capture streams, as we're closing
right afterwards, so the samples are lost anyway.

what's more, destructors are not supposed to wait for anything, so
draining in alsapcm_dealloc() was wrong to start with. so we remove it.
note that this is a minor behavior change, which is reflected by the
adjustment of the playback test to have an explicit close() at the end.

finally, close() was also affected by the pulseaudio bug (which was not
addressed before), so there we make draining exclusive to playback
streams.

* fix memory leaks in *_polldescriptors()

the calloc'd pollfd arrays were not freed.

* fix memory handling in mixer access error paths

in case of error, alsamixer_new() would leak the object, while
alsamixer_list() might crash due to a null pointer.

as a drive-by, make alsamixer_gethandle() `static`.

* fix crashes when accessing already closed devices

PCM.htimestamp() gets the usual exception emission,
Mixer.close() gets a "double invocation" check like PCM.close() has.

* fix deprecation warning about PyEval_InitThreads()

PyEval_InitThreads is a no-op in since python 3.9.

* fix deprecation warning about PyUnicode_AsUnicode()

converting to ascii for the purpose of comparison is inefficient.

* remove redundant snd_pcm_hw_params_any() call

we just called it (and even error-checked it) a few lines above.

* add new high-speed samples rates

closes #89 (but alsa doesn't support 768khz yet).

* drop some pointless comments from the tex => sphinx conversion

amends 5c2a00655.

* remove bogus markup from the documentation

the poll objects are linked properly in a different way, and the
footnote appears outdated.

* unify line spacing in .rst files

one empty line, except for high-level sections, which get two.

while at it, trim whitespace on otherwise empty lines.

* formatting/language fixes in introduction document

* improve terminology document

mention xruns, and rework the definition of periods: concentrate on
relevant information, and remove the misinformation about period size
reduction being not that bad (pedantically, an application could run
somewhat asynchronously to the interrupts by using some timer, and
therefore actually save some of the overhead, but why would one use a
small period size in the first place then?).

also, language and formatting fixes.

* add missing and update incorrect/outdated documentation

for clarity, this includes docs which were previously omitted
(presumably) intentionally, but mark them as comments.

the getrec() and getmute() functions' docs are moved around, so they
appear in pairs with their set*() counterparts, like the *volume() ones
already did.

notably, this also fixes the docu of PCM_FORMAT_U8, which closes #104.

* add some best practices to the docu

addresses #110, among other things.

* purge pydoc from the source

it's been obsolete for a *long* time, and having it redundantly to the
rst sources is bad hygiene. it still contained some useful info, which
has been transplanted to the rst source in the previous commit.

* use data types closer to those of ALSA

this removes lots of casts around snd_pcm_hw_params_get_*() calls

we could go further with that to make the code clean if we enabled all
the warnings, but it doesn't seem worth the effort.

* reduce scope of GIL releases

it's pointless to enclose snd_pcm_close() and snd_pcm_pause(), as these
calls don't sleep.

* reshuffle XRUN recovery somewhat

perform it prior to invoking read()/write() if necessary, not right
after a failure event. this makes things more uniform and predictable.

we don't use snd_pcm_recover() any more, as we used it only for the
EPIPE case anyway, which boils down to snd_pcm_prepare() exactly.
handling ESTRPIPE as well might be desirable, but that's a separate
consideration.

* bump (minor) version

we're about to add new features.

* make period count configurable

the period count is just as important for playback latency as the period
size, so it makes no sense to have only one of them configurable.

as a drive-by, fix up the handling of periods in info() & dumpinfo().

* add PCM.drain()

for playback, this allows making sure that all written frames are
played, without using an external delay.

in principle, it's also usable for capture, but there isn't really a
practical reason to do so, as simply discarding excess captured frames
has no real cost.

* add PCM.state() and associated enum values

in principle, the state is already available from info(), but that's a
rather heavy function for something one might want to query often.

a practical use case might be checking whether a playback stream is done
draining, for example.
2023-04-15 21:45:32 +02:00

129 lines
4.0 KiB
ReStructuredText

************
Introduction
************
:Author: Casper Wilstrup <cwi@aves.dk>
:Author: Lars Immisch <lars@ibp.de>
.. |release| replace:: version
.. _front:
This software is licensed under the PSF license - the same one used by the
majority of the python distribution. Basically you can use it for anything you
wish (even commercial purposes). There is no warranty whatsoever.
.. topic:: Abstract
This package contains wrappers for accessing the ALSA API from Python. It is
currently fairly complete for PCM devices and Mixer access. MIDI sequencer
support is low on our priority list, but volunteers are welcome.
If you find bugs in the wrappers please use the github issue tracker.
Please don't send bug reports regarding ALSA specifically. There are several
bugs in this API, and those should be reported to the ALSA team - not me.
************
What is ALSA
************
The Advanced Linux Sound Architecture (ALSA) provides audio and MIDI
functionality to the Linux operating system.
Logically ALSA consists of these components:
* A set of kernel drivers. --- These drivers are responsible for handling the
physical sound hardware from within the Linux kernel, and have been the
standard sound implementation in Linux since kernel version 2.5
* A kernel level API for manipulating the ALSA devices.
* A user-space C library for simplified access to the sound hardware from
userspace applications. This library is called *libasound* and is required by
all ALSA capable applications.
More information about ALSA may be found on the project homepage
`<http://www.alsa-project.org>`_
ALSA and Python
===============
The older Linux sound API (OSS) -- which is now deprecated -- is well supported
by the standard Python library, through the ossaudiodev module. No native ALSA
support exists in the standard library.
There are a few other "ALSA for Python" projects available, including at least
two different projects called pyAlsa. Neither of these seem to be under active
development at the time - and neither are very feature complete.
I wrote PyAlsaAudio to fill this gap. My long term goal is to have the module
included in the standard Python library, but that looks currently unlikely.
PyAlsaAudio has full support for sound capture, playback of sound, as well as
the ALSA Mixer API.
MIDI support is not available, and since I don't own any MIDI hardware, it's
difficult for me to implement it. Volunteers to work on this would be greatly
appreciated.
************
Installation
************
Note: the wrappers link with the alsasound library (from the alsa-lib package)
and need the ALSA headers for compilation. Verify that you have
/usr/lib/libasound.so and /usr/include/alsa (or similar paths) before building.
*On Debian (and probably Ubuntu), install libasound2-dev.*
Naturally you also need to use a kernel with proper ALSA support. This is the
default in Linux kernel 2.6 and later. If you are using kernel version 2.4 you
may need to install the ALSA patches yourself - although most distributions
ship with ALSA kernels.
To install, execute the following: --- ::
$ python setup.py build
And then as root: --- ::
# python setup.py install
*******
Testing
*******
Make sure that :code:`aplay` plays a file through the soundcard you want, then
try::
$ python playwav.py <filename.wav>
If :code:`aplay` needs a device argument, like
:code:`aplay -D hw:CARD=sndrpihifiberry,DEV=0`, use::
$ python playwav.py -d hw:CARD=sndrpihifiberry,DEV=0 <filename.wav>
To test PCM recordings (on your default soundcard), verify your
microphone works, then do::
$ python recordtest.py -d <device> <filename>
Speak into the microphone, and interrupt the recording at any time
with ``Ctl-C``.
Play back the recording with::
$ python playbacktest.py -d <device> <filename>
There is a minimal test suite in :code:`test.py`, but it is
a bit dependent on the ALSA configuration and may fail without indicating
a real problem.
If you find bugs/problems, please file a `bug report
<https://github.com/larsimmisch/pyalsaaudio/issues>`_.