forked from auracaster/pyalsaaudio
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfda54642d | ||
|
|
3f6fb9844d | ||
|
|
4d9f6e5b50 | ||
|
|
40a4a36b1d | ||
|
|
38ea69bbaa | ||
|
|
c8f3916337 | ||
|
|
f19af8eba0 | ||
|
|
b8980d992b | ||
|
|
ebd2b5359d | ||
|
|
c5f22fd7e0 | ||
|
|
3c3f0af74a | ||
|
|
17f3b440cc | ||
|
|
b2a303121a | ||
|
|
3168833b4e | ||
|
|
c74669850b | ||
|
|
1a4c0541d7 | ||
|
|
e6a6445375 | ||
|
|
97f2abcb30 | ||
|
|
a53ffd0d4f | ||
|
|
da71e01f9c | ||
|
|
f6736ec43a | ||
|
|
e48b294b84 | ||
|
|
d037297632 | ||
|
|
c8e7261e94 | ||
|
|
5c481b4094 | ||
|
|
1e3c7f3fd0 | ||
|
|
0ae60f80f3 | ||
|
|
4018ab4f6c | ||
|
|
07f84a8e95 | ||
|
|
d83e829de1 | ||
|
|
62e5515341 | ||
|
|
ed027a6141 | ||
|
|
5302dc524d | ||
|
|
b17b36be50 | ||
|
|
08bdce9ed9 | ||
|
|
0224c8a308 | ||
|
|
f07627543c | ||
|
|
df889b94ef | ||
|
|
2a21bf6c42 | ||
|
|
8084297926 | ||
|
|
8fbc04e18d | ||
|
|
8ed9f924cd | ||
|
|
046e7c4e87 | ||
|
|
a4c4c7cb62 | ||
|
|
f478797f6f | ||
|
|
12f807698a | ||
|
|
fc011b5ea6 | ||
|
|
f244a70111 | ||
|
|
a056a90c61 | ||
|
|
be1b3e131d | ||
|
|
8abf06bedf | ||
|
|
dcc831e607 | ||
|
|
e587df9143 | ||
|
|
82febd3f7e | ||
|
|
1695066c11 | ||
|
|
25717020ef | ||
|
|
1aae655d24 | ||
|
|
c1c8362eb2 | ||
|
|
723eff3887 | ||
|
|
aa9867de18 | ||
|
|
58f4522769 | ||
|
|
f2fb61d324 | ||
|
|
9e79494a95 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -4,6 +4,11 @@ MANIFEST
|
||||
doc/gh-pages/
|
||||
doc/html/
|
||||
doc/doctrees/
|
||||
doc/_build/
|
||||
gh-pages/
|
||||
build/
|
||||
dist/
|
||||
dist/
|
||||
.vscode/
|
||||
/__pycache__/
|
||||
/pyalsaaudio.egg-info/
|
||||
*.raw
|
||||
|
||||
70
CHANGES
70
CHANGES
@@ -1,70 +0,0 @@
|
||||
Version 0.8.2:
|
||||
- fix #3 (we cannot get the revision from git for pip installs)
|
||||
|
||||
Version 0.8.1:
|
||||
- document changes (this file)
|
||||
|
||||
Version 0.8:
|
||||
- 'PCM()' has new 'device' and 'cardindex' keyword arguments.
|
||||
|
||||
The keyword 'device' allows to select virtual devices, 'cardindex' can be
|
||||
used to select hardware cards by index (as with 'mixers()' and 'Mixer()').
|
||||
|
||||
The 'card' keyword argument is still supported, but deprecated.
|
||||
|
||||
The reason for this change is that the 'card' keyword argument guessed
|
||||
a device name from the card name, but this only works sometimes, and breaks
|
||||
opening virtual devices.
|
||||
|
||||
- new function 'pcms()' to list available PCM devices.
|
||||
|
||||
- mixers() and Mixer() take an additional 'device' keyword argument.
|
||||
This allows to list or open virtual devices.
|
||||
|
||||
- The default behaviour of Mixer() without any arguments has changed.
|
||||
Now Mixer() will try to open the 'default' Mixer instead of the Mixer
|
||||
that is associated with card 0.
|
||||
|
||||
- fix a memory leak under Python 3.x
|
||||
|
||||
- some more memory leaks in error conditions fixed.
|
||||
|
||||
Version 0.7:
|
||||
- fixed several memory leaks (patch 3372909), contributed by Erik Kulyk)
|
||||
|
||||
|
||||
Version 0.6:
|
||||
- mostly reverted patch 2594366: alsapcm_setup did not do complete error
|
||||
checking for good reasons; some ALSA functions in alsapcm_setup may fail without
|
||||
rendering the device unusable
|
||||
|
||||
|
||||
Version 0.5:
|
||||
- applied patch 2777035: Fixed setrec method in alsaaudio.c
|
||||
This included a mixertest with more features
|
||||
- fixed/applied patch 2594366: alsapcm_setup does not do any error checking
|
||||
|
||||
|
||||
Version 0.4:
|
||||
- API changes: mixers() and Mixer() now take a card index instead of a
|
||||
card name as optional parameter.
|
||||
- Support for Python 3.0
|
||||
- Documentation converted to reStructuredText; use Sphinx instead of LaTeX.
|
||||
- added cards()
|
||||
- added PCM.close()
|
||||
- added Mixer.close()
|
||||
- added mixer.getenum()
|
||||
|
||||
|
||||
Version 0.3:
|
||||
- wrapped blocking calls with Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS
|
||||
- added pause
|
||||
|
||||
|
||||
Version 0.2:
|
||||
- Many bugfixes related to playback in particular
|
||||
- Module documentation in the doc subdirectory
|
||||
|
||||
|
||||
Version 0.1:
|
||||
- Initial version
|
||||
100
CHANGES.md
Normal file
100
CHANGES.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Version 0.9.1:
|
||||
- Support decibel, percentage, and raw volumes in getvolume, setvolume, and getrange (#109 from @chrisdiamand):
|
||||
|
||||
# Version 0.9.0:
|
||||
- Added keyword arguments for channels, format, rate and periodsize
|
||||
- Deprecated `setchannel`, `setformat`, `setrate` and `setperiodsize`
|
||||
|
||||
# Version 0.8.6:
|
||||
- Added four methods to the `PCM` class to allow users to get detailed information about the device:
|
||||
|
||||
- `getformats()` returns a dictionary of name / value pairs, one for each of the card's
|
||||
supported formats - e.g. `{"U8": 1, "S16_LE": 2}`,
|
||||
- `getchannels()` returns a list of the supported channel numbers, e.g. `[1, 2]`,
|
||||
- `getrates()` returns supported sample rates for the device, e.g. `[48000]`,
|
||||
- `getratebounds()` returns the device's official minimum and maximum supported
|
||||
sample rates as a tuple, e.g. `(4000, 48000)`.
|
||||
|
||||
(#82 contributed by @jdstmporter)
|
||||
|
||||
- Prevent hang on close after capturing audio (#80 contributed by @daym)
|
||||
|
||||
# Version 0.8.5:
|
||||
- Return an empty string/bytestring when `read()` detects an
|
||||
overrun. Previously the returned data was undefined (contributed by @jcea)
|
||||
|
||||
- Unlimited setperiod buffer size when reading frames (contributed by @jcea)
|
||||
|
||||
# Version 0.8.4:
|
||||
- Fix Python3 API usage broken in 0.8.3
|
||||
|
||||
# Version 0.8.3:
|
||||
- Add DSD sample formats (contributed by @lintweaker)
|
||||
- Add Mixer.handleevents() to acknowledge events identified by select.poll (contributed by @PaulSD)
|
||||
- Add functions for listing cards and their names (contributed by @chrisdiamand)
|
||||
- Add a method for setting enums (contributed by @chrisdiamand)
|
||||
|
||||
# Version 0.8.2:
|
||||
- fix #3 (we cannot get the revision from git for pip installs)
|
||||
|
||||
# Version 0.8.1:
|
||||
- document changes (this file)
|
||||
|
||||
# Version 0.8:
|
||||
- `PCM()` has new `device` and `cardindex` keyword arguments.
|
||||
|
||||
The keyword `device` allows to select virtual devices, `cardindex` can be
|
||||
used to select hardware cards by index (as with `mixers()` and `Mixer()`).
|
||||
|
||||
The `card` keyword argument is still supported, but deprecated.
|
||||
|
||||
The reason for this change is that the `card` keyword argument guessed
|
||||
a device name from the card name, but this only works sometimes, and breaks
|
||||
opening virtual devices.
|
||||
|
||||
- new function `pcms()` to list available PCM devices.
|
||||
|
||||
- `mixers()` and `Mixer()` take an additional `device` keyword argument.
|
||||
This allows to list or open virtual devices.
|
||||
|
||||
- The default behaviour of `Mixer()` without any arguments has changed.
|
||||
Now Mixer() will try to open the `default` Mixer instead of the Mixer
|
||||
that is associated with card 0.
|
||||
|
||||
- fix a memory leak under Python 3.x
|
||||
|
||||
- some more memory leaks in error conditions fixed.
|
||||
|
||||
# Version 0.7:
|
||||
- fixed several memory leaks (patch 3372909), contributed by Erik Kulyk)
|
||||
|
||||
# Version 0.6:
|
||||
- mostly reverted patch 2594366: alsapcm_setup did not do complete error
|
||||
checking for good reasons; some ALSA functions in alsapcm_setup may fail without
|
||||
rendering the device unusable
|
||||
|
||||
# Version 0.5:
|
||||
- applied patch 2777035: Fixed setrec method in alsaaudio.c
|
||||
This included a mixertest with more features
|
||||
- fixed/applied patch 2594366: alsapcm_setup does not do any error checking
|
||||
|
||||
# Version 0.4:
|
||||
- API changes: mixers() and Mixer() now take a card index instead of a
|
||||
card name as optional parameter.
|
||||
- Support for Python 3.0
|
||||
- Documentation converted to reStructuredText; use Sphinx instead of LaTeX.
|
||||
- added `cards()`
|
||||
- added `PCM.close()`
|
||||
- added `Mixer.close()`
|
||||
- added `mixer.getenum()`
|
||||
|
||||
# Version 0.3:
|
||||
- wrapped blocking calls with `Py_BEGIN_ALLOW_THREADS`/`Py_END_ALLOW_THREADS`
|
||||
- added pause
|
||||
|
||||
# Version 0.2:
|
||||
- Many bugfixes related to playback in particular
|
||||
- Module documentation in the doc subdirectory
|
||||
|
||||
# Version 0.1:
|
||||
- Initial version
|
||||
11
NOTES.md
11
NOTES.md
@@ -1,11 +0,0 @@
|
||||
# Publishing the documentation
|
||||
|
||||
- Install Sphinx; `sudo pip install sphinx`
|
||||
- Clone gh-pages branch: `cd doc; git clone -b gh-pages git@github.com:larsimmisch/pyalsaaudio.git gh-pages`
|
||||
- `cd doc; make publish`
|
||||
|
||||
# Release procedure
|
||||
|
||||
- Update version number in setup.py
|
||||
- Create tag and push it, i.e. `git tag x.y.z; git push origin x.y.z`
|
||||
- `python setup.py sdist upload -r pypi`
|
||||
4128
alsaaudio.c
4128
alsaaudio.c
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,26 @@
|
||||
# Make a new release
|
||||
|
||||
Update the version in setup.py
|
||||
|
||||
pyalsa_version = '0.9.0'
|
||||
|
||||
Commit and push the update.
|
||||
|
||||
Create and push a tag naming the version (i.e. 0.9.0):
|
||||
|
||||
git tag 0.9.0
|
||||
git push origin 0.9.0
|
||||
|
||||
Create the package:
|
||||
|
||||
python3 setup.py sdist
|
||||
|
||||
Upload the package
|
||||
|
||||
twine upload dist/*
|
||||
|
||||
Don't forget to update the documentation.
|
||||
|
||||
# Publish the documentation
|
||||
|
||||
The documentation is published through the `gh-pages` branch.
|
||||
|
||||
@@ -33,13 +33,13 @@ The :mod:`alsaaudio` module defines functions and classes for using ALSA.
|
||||
.. % should be enclosed in \var{...}.
|
||||
|
||||
|
||||
.. function:: pcms([type=PCM_PLAYBACK])
|
||||
.. function:: pcms(pcmtype=PCM_PLAYBACK)
|
||||
|
||||
List available PCM devices by name.
|
||||
|
||||
Arguments are:
|
||||
|
||||
* *type* - can be either :const:`PCM_CAPTURE` or :const:`PCM_PLAYBACK`
|
||||
* *pcmtype* - can be either :const:`PCM_CAPTURE` or :const:`PCM_PLAYBACK`
|
||||
(default).
|
||||
|
||||
**Note:**
|
||||
@@ -63,7 +63,6 @@ The :mod:`alsaaudio` module defines functions and classes for using ALSA.
|
||||
useful. If you want to see a list of available PCM devices, use :func:`pcms`
|
||||
instead.
|
||||
|
||||
|
||||
.. function:: mixers(cardindex=-1, device='default')
|
||||
|
||||
List the available mixers. The arguments are:
|
||||
@@ -98,6 +97,9 @@ The :mod:`alsaaudio` module defines functions and classes for using ALSA.
|
||||
changed. Since 0.8, this functions returns the mixers for the default
|
||||
device, not the mixers for the first card.
|
||||
|
||||
.. function:: asoundlib_version()
|
||||
|
||||
Return a Python string containing the ALSA version found.
|
||||
|
||||
.. _pcm-objects:
|
||||
|
||||
@@ -108,7 +110,7 @@ PCM objects in :mod:`alsaaudio` can play or capture (record) PCM
|
||||
sound through speakers or a microphone. The PCM constructor takes the
|
||||
following arguments:
|
||||
|
||||
.. class:: PCM(type=PCM_PLAYBACK, mode=PCM_NORMAL, device='default', cardindex=-1)
|
||||
.. class:: PCM(type=PCM_PLAYBACK, mode=PCM_NORMAL, rate=44100, channels=2, format=PCM_FORMAT_S16_LE, periodsize=32, device='default', cardindex=-1)
|
||||
|
||||
This class is used to represent a PCM device (either for playback and
|
||||
recording). The arguments are:
|
||||
@@ -117,75 +119,13 @@ following arguments:
|
||||
(default).
|
||||
* *mode* - can be either :const:`PCM_NONBLOCK`, or :const:`PCM_NORMAL`
|
||||
(default).
|
||||
* *device* - the name of the PCM device that should be used (for example
|
||||
a value from the output of :func:`pcms`). The default value is
|
||||
``'default'``.
|
||||
* *cardindex* - the card index. If this argument is given, the device name
|
||||
is constructed as 'hw:*cardindex*' and
|
||||
the `device` keyword argument is ignored.
|
||||
``0`` is the first hardware sound card.
|
||||
|
||||
This will construct a PCM object with these default settings:
|
||||
|
||||
* Sample format: :const:`PCM_FORMAT_S16_LE`
|
||||
* Rate: 44100 Hz
|
||||
* Channels: 2
|
||||
* Period size: 32 frames
|
||||
|
||||
*Changed in 0.8:*
|
||||
* *rate* - the sampling rate in Hz. Typical values are ``8000`` (mainly used for telephony), ``16000``, ``44100`` (default), ``48000`` and ``96000``.
|
||||
* *channels* - the number of channels. The default value is 2 (stereo).
|
||||
* *format* - the data format. This controls how the PCM device interprets data for playback, and how data is encoded in captures.
|
||||
The default value is :const:`PCM_FORMAT_S16_LE`.
|
||||
|
||||
- The `card` keyword argument is still supported,
|
||||
but deprecated. Please use `device` instead.
|
||||
|
||||
- The keyword argument `cardindex` was added.
|
||||
|
||||
The `card` keyword is deprecated because it guesses the real ALSA
|
||||
name of the card. This was always fragile and broke some legitimate usecases.
|
||||
|
||||
|
||||
PCM objects have the following methods:
|
||||
|
||||
|
||||
.. method:: PCM.pcmtype()
|
||||
|
||||
Returns the type of PCM object. Either :const:`PCM_CAPTURE` or
|
||||
:const:`PCM_PLAYBACK`.
|
||||
|
||||
|
||||
.. method:: PCM.pcmmode()
|
||||
|
||||
Return the mode of the PCM object. One of :const:`PCM_NONBLOCK`,
|
||||
:const:`PCM_ASYNC`, or :const:`PCM_NORMAL`
|
||||
|
||||
|
||||
.. method:: PCM.cardname()
|
||||
|
||||
Return the name of the sound card used by this PCM object.
|
||||
|
||||
|
||||
.. method:: PCM.setchannels(nchannels)
|
||||
|
||||
Used to set the number of capture or playback channels. Common
|
||||
values are: ``1`` = mono, ``2`` = stereo, and ``6`` = full 6 channel audio.
|
||||
Few sound cards support more than 2 channels
|
||||
|
||||
|
||||
.. method:: PCM.setrate(rate)
|
||||
|
||||
Set the sample rate in Hz for the device. Typical values are ``8000``
|
||||
(mainly used for telephony), ``16000``, ``44100`` (CD quality),
|
||||
``48000`` and ``96000``.
|
||||
|
||||
|
||||
.. method:: PCM.setformat(format)
|
||||
|
||||
The sound *format* of the device. Sound format controls how the PCM device
|
||||
interpret data for playback, and how data is encoded in captures.
|
||||
|
||||
The following formats are provided by ALSA:
|
||||
|
||||
========================= ===============
|
||||
Format Description
|
||||
Format Description
|
||||
========================= ===============
|
||||
``PCM_FORMAT_S8`` Signed 8 bit samples for each channel
|
||||
``PCM_FORMAT_U8`` Signed 8 bit samples for each channel
|
||||
@@ -215,15 +155,66 @@ PCM objects have the following methods:
|
||||
``PCM_FORMAT_U24_3LE`` Unsigned 24 bit samples for each channel (Little Endian byte order in 3 bytes)
|
||||
``PCM_FORMAT_U24_3BE`` Unsigned 24 bit samples for each channel (Big Endian byte order in 3 bytes)
|
||||
========================= ===============
|
||||
|
||||
* *periodsize* - the period size in frames. Each write should consist of *periodsize* frames. The default value is 32.
|
||||
* *device* - the name of the PCM device that should be used (for example
|
||||
a value from the output of :func:`pcms`). The default value is
|
||||
``'default'``.
|
||||
* *cardindex* - the card index. If this argument is given, the device name
|
||||
is constructed as 'hw:*cardindex*' and
|
||||
the `device` keyword argument is ignored.
|
||||
``0`` is the first hardware sound card.
|
||||
|
||||
This will construct a PCM object with the given settings.
|
||||
|
||||
*Changed in 0.9:*
|
||||
|
||||
- Added the optional named parameters `rate`, `channels`, `format` and `periodsize`.
|
||||
|
||||
*Changed in 0.8:*
|
||||
|
||||
- The `card` keyword argument is still supported,
|
||||
but deprecated. Please use `device` instead.
|
||||
|
||||
- The keyword argument `cardindex` was added.
|
||||
|
||||
The `card` keyword is deprecated because it guesses the real ALSA
|
||||
name of the card. This was always fragile and broke some legitimate usecases.
|
||||
|
||||
|
||||
PCM objects have the following methods:
|
||||
|
||||
.. method:: PCM.pcmtype()
|
||||
|
||||
Returns the type of PCM object. Either :const:`PCM_CAPTURE` or
|
||||
:const:`PCM_PLAYBACK`.
|
||||
|
||||
|
||||
.. method:: PCM.pcmmode()
|
||||
|
||||
Return the mode of the PCM object. One of :const:`PCM_NONBLOCK`,
|
||||
:const:`PCM_ASYNC`, or :const:`PCM_NORMAL`
|
||||
|
||||
|
||||
.. method:: PCM.cardname()
|
||||
|
||||
Return the name of the sound card used by this PCM object.
|
||||
|
||||
.. method:: PCM.setchannels(nchannels)
|
||||
|
||||
.. deprecated:: 0.9 Use the `channels` named argument to :func:`PCM`.
|
||||
|
||||
.. method:: PCM.setrate(rate)
|
||||
|
||||
.. deprecated:: 0.9 Use the `rate` named argument to :func:`PCM`.
|
||||
|
||||
.. method:: PCM.setformat(format)
|
||||
|
||||
.. deprecated:: 0.9 Use the `format` named argument to :func:`PCM`.
|
||||
|
||||
.. method:: PCM.setperiodsize(period)
|
||||
|
||||
Sets the actual period size in frames. Each write should consist of
|
||||
exactly this number of frames, and each read will return this
|
||||
number of frames (unless the device is in :const:`PCM_NONBLOCK` mode, in
|
||||
which case it may return nothing at all)
|
||||
|
||||
.. deprecated:: 0.9 Use the `periodsize` named argument to :func:`PCM`.
|
||||
|
||||
.. method:: PCM.read()
|
||||
|
||||
@@ -267,11 +258,61 @@ PCM objects have the following methods:
|
||||
.. method:: PCM.polldescriptors()
|
||||
|
||||
Returns a tuple of *(file descriptor, eventmask)* that can be used to
|
||||
wait for changes on the mixer with *select.poll*.
|
||||
wait for changes on the PCM with *select.poll*.
|
||||
|
||||
The *eventmask* value is compatible with `poll.register`__ in the Python
|
||||
:const:`select` module.
|
||||
|
||||
.. method:: PCM.set_tstamp_mode([mode=PCM_TSTAMP_ENABLE])
|
||||
|
||||
Set the ALSA timestamp mode on the device. The mode argument can be set to
|
||||
either :const:`PCM_TSTAMP_NONE` or :const:`PCM_TSTAMP_ENABLE`.
|
||||
|
||||
.. method:: PCM.get_tstamp_mode()
|
||||
|
||||
Return the integer value corresponding to the ALSA timestamp mode. The
|
||||
return value can be either :const:`PCM_TSTAMP_NONE` or :const:`PCM_TSTAMP_ENABLE`.
|
||||
|
||||
.. method:: PCM.set_tstamp_type([type=PCM_TSTAMP_TYPE_GETTIMEOFDAY])
|
||||
|
||||
Set the ALSA timestamp mode on the device. The type argument
|
||||
can be set to either :const:`PCM_TSTAMP_TYPE_GETTIMEOFDAY`,
|
||||
:const:`PCM_TSTAMP_TYPE_MONOTONIC` or :const:`PCM_TSTAMP_TYPE_MONOTONIC_RAW`.
|
||||
|
||||
.. method:: PCM.get_tstamp_type()
|
||||
|
||||
Return the integer value corresponding to the ALSA timestamp type. The
|
||||
return value can be either :const:`PCM_TSTAMP_TYPE_GETTIMEOFDAY`,
|
||||
:const:`PCM_TSTAMP_TYPE_MONOTONIC` or :const:`PCM_TSTAMP_TYPE_MONOTONIC_RAW`.
|
||||
|
||||
.. method:: PCM.htimestamp()
|
||||
|
||||
Return a Python tuple *(seconds, nanoseconds, frames_available_in_buffer)*.
|
||||
|
||||
The type of output is controlled by the tstamp_type, as described in the table below.
|
||||
|
||||
================================= ===========================================
|
||||
Timestamp Type Description
|
||||
================================= ===========================================
|
||||
``PCM_TSTAMP_TYPE_GETTIMEOFDAY`` System-wide realtime clock with seconds
|
||||
since epoch.
|
||||
``PCM_TSTAMP_TYPE_MONOTONIC`` Monotonic time from an unspecified starting
|
||||
time. Progress is NTP synchronized.
|
||||
``PCM_TSTAMP_TYPE_MONOTONIC_RAW`` Monotonic time from an unspecified starting
|
||||
time using only the system clock.
|
||||
================================= ===========================================
|
||||
|
||||
The timestamp mode is controlled by the tstamp_mode, as described in the table below.
|
||||
|
||||
================================= ===========================================
|
||||
Timestamp Mode Description
|
||||
================================= ===========================================
|
||||
``PCM_TSTAMP_NONE`` No timestamp.
|
||||
``PCM_TSTAMP_ENABLE`` Update timestamp at every hardware position
|
||||
update.
|
||||
================================= ===========================================
|
||||
|
||||
|
||||
__ poll_objects_
|
||||
|
||||
**A few hints on using PCM devices for playback**
|
||||
@@ -425,11 +466,11 @@ Mixer objects have the following methods:
|
||||
This method will fail if the mixer has no playback switch capabilities.
|
||||
|
||||
|
||||
.. method:: Mixer.getrange([direction])
|
||||
.. method:: Mixer.getrange(pcmtype=PCM_PLAYBACK)
|
||||
|
||||
Return the volume range of the ALSA mixer controlled by this object.
|
||||
|
||||
The optional *direction* argument can be either :const:`PCM_PLAYBACK` or
|
||||
The optional *pcmtype* argument can be either :const:`PCM_PLAYBACK` or
|
||||
:const:`PCM_CAPTURE`, which is relevant if the mixer can control both
|
||||
playback and capture volume. The default value is :const:`PCM_PLAYBACK`
|
||||
if the mixer has playback channels, otherwise it is :const:`PCM_CAPTURE`.
|
||||
@@ -443,18 +484,18 @@ Mixer objects have the following methods:
|
||||
This method will fail if the mixer has no capture switch capabilities.
|
||||
|
||||
|
||||
.. method:: Mixer.getvolume([direction])
|
||||
.. method:: Mixer.getvolume(pcmtype=PCM_PLAYBACK)
|
||||
|
||||
Returns a list with the current volume settings for each channel. The list
|
||||
elements are integer percentages.
|
||||
|
||||
The optional *direction* argument can be either :const:`PCM_PLAYBACK` or
|
||||
The optional *pcmtype* argument can be either :const:`PCM_PLAYBACK` or
|
||||
:const:`PCM_CAPTURE`, which is relevant if the mixer can control both
|
||||
playback and capture volume. The default value is :const:`PCM_PLAYBACK`
|
||||
if the mixer has playback channels, otherwise it is :const:`PCM_CAPTURE`.
|
||||
|
||||
|
||||
.. method:: Mixer.setvolume(volume, [channel], [direction])
|
||||
.. method:: Mixer.setvolume(volume, channel=None, pcmtype=PCM_PLAYBACK)
|
||||
|
||||
Change the current volume settings for this mixer. The *volume* argument
|
||||
controls the new volume setting as an integer percentage.
|
||||
@@ -463,7 +504,7 @@ Mixer objects have the following methods:
|
||||
only for this channel. This assumes that the mixer can control the
|
||||
volume for the channels independently.
|
||||
|
||||
The optional *direction* argument can be either :const:`PCM_PLAYBACK` or
|
||||
The optional *pcmtype* argument can be either :const:`PCM_PLAYBACK` or
|
||||
:const:`PCM_CAPTURE`, which is relevant if the mixer can control both
|
||||
playback and capture volume. The default value is :const:`PCM_PLAYBACK`
|
||||
if the mixer has playback channels, otherwise it is :const:`PCM_CAPTURE`.
|
||||
|
||||
@@ -75,7 +75,7 @@ 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 hass full support for sound capture, playback of sound, as well as
|
||||
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
|
||||
|
||||
5
isine.py
5
isine.py
@@ -56,10 +56,7 @@ class SinePlayer(Thread):
|
||||
def __init__(self, frequency = 440.0):
|
||||
Thread.__init__(self)
|
||||
self.setDaemon(True)
|
||||
self.device = alsaaudio.PCM()
|
||||
self.device.setchannels(channels)
|
||||
self.device.setformat(format)
|
||||
self.device.setrate(sampling_rate)
|
||||
self.device = alsaaudio.PCM(channels=channels, format=format, rate=sampling_rate)
|
||||
self.queue = Queue()
|
||||
self.change(frequency)
|
||||
|
||||
|
||||
29
mixertest.py
29
mixertest.py
@@ -43,11 +43,36 @@ def show_mixer(name, kwargs):
|
||||
sys.exit(1)
|
||||
|
||||
print("Mixer name: '%s'" % mixer.mixer())
|
||||
print("Capabilities: %s %s" % (' '.join(mixer.volumecap()),
|
||||
volcap = mixer.volumecap()
|
||||
print("Capabilities: %s %s" % (' '.join(volcap),
|
||||
' '.join(mixer.switchcap())))
|
||||
|
||||
if "Volume" in volcap or "Joined Volume" in volcap or "Playback Volume" in volcap:
|
||||
pmin, pmax = mixer.getrange(alsaaudio.PCM_PLAYBACK)
|
||||
pmin_keyword, pmax_keyword = mixer.getrange(pcmtype=alsaaudio.PCM_PLAYBACK, units=alsaaudio.VOLUME_UNITS_RAW)
|
||||
pmin_default, pmax_default = mixer.getrange()
|
||||
assert pmin == pmin_keyword
|
||||
assert pmax == pmax_keyword
|
||||
assert pmin == pmin_default
|
||||
assert pmax == pmax_default
|
||||
print("Raw playback volume range {}-{}".format(pmin, pmax))
|
||||
pmin_dB, pmax_dB = mixer.getrange(units=alsaaudio.VOLUME_UNITS_DB)
|
||||
print("dB playback volume range {}-{}".format(pmin_dB / 100.0, pmax_dB / 100.0))
|
||||
|
||||
if "Capture Volume" in volcap or "Joined Capture Volume" in volcap:
|
||||
# Check that `getrange` works with keyword and positional arguments
|
||||
cmin, cmax = mixer.getrange(alsaaudio.PCM_CAPTURE)
|
||||
cmin_keyword, cmax_keyword = mixer.getrange(pcmtype=alsaaudio.PCM_CAPTURE, units=alsaaudio.VOLUME_UNITS_RAW)
|
||||
assert cmin == cmin_keyword
|
||||
assert cmax == cmax_keyword
|
||||
print("Raw capture volume range {}-{}".format(cmin, cmax))
|
||||
cmin_dB, cmax_dB = mixer.getrange(pcmtype=alsaaudio.PCM_CAPTURE, units=alsaaudio.VOLUME_UNITS_DB)
|
||||
print("dB capture volume range {}-{}".format(cmin_dB / 100.0, cmax_dB / 100.0))
|
||||
|
||||
volumes = mixer.getvolume()
|
||||
volumes_dB = mixer.getvolume(units=alsaaudio.VOLUME_UNITS_DB)
|
||||
for i in range(len(volumes)):
|
||||
print("Channel %i volume: %i%%" % (i,volumes[i]))
|
||||
print("Channel %i volume: %i%% (%.1f dB)" % (i, volumes[i], volumes_dB[i] / 100.0))
|
||||
|
||||
try:
|
||||
mutes = mixer.getmute()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# -*- mode: python; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
|
||||
|
||||
## playbacktest.py
|
||||
##
|
||||
@@ -38,18 +39,11 @@ if __name__ == '__main__':
|
||||
|
||||
f = open(args[0], 'rb')
|
||||
|
||||
# Open the device in playback mode.
|
||||
out = alsaaudio.PCM(alsaaudio.PCM_PLAYBACK, device=device)
|
||||
|
||||
# Set attributes: Mono, 44100 Hz, 16 bit little endian frames
|
||||
out.setchannels(1)
|
||||
out.setrate(44100)
|
||||
out.setformat(alsaaudio.PCM_FORMAT_S16_LE)
|
||||
|
||||
# Open the device in playback mode in Mono, 44100 Hz, 16 bit little endian frames
|
||||
# The period size controls the internal number of frames per period.
|
||||
# The significance of this parameter is documented in the ALSA api.
|
||||
out.setperiodsize(160)
|
||||
|
||||
out = alsaaudio.PCM(alsaaudio.PCM_PLAYBACK, channels=1, rate=44100, format=alsaaudio.PCM_FORMAT_S16_LE, periodsize=160, device=device)
|
||||
# Read data from stdin
|
||||
data = f.read(320)
|
||||
while data:
|
||||
|
||||
84
playwav.py
84
playwav.py
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# -*- mode: python; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
|
||||
|
||||
# Simple test script that plays (some) wav files
|
||||
|
||||
@@ -9,57 +10,54 @@ import wave
|
||||
import getopt
|
||||
import alsaaudio
|
||||
|
||||
def play(device, f):
|
||||
def play(device, f):
|
||||
|
||||
print('%d channels, %d sampling rate\n' % (f.getnchannels(),
|
||||
f.getframerate()))
|
||||
# Set attributes
|
||||
device.setchannels(f.getnchannels())
|
||||
device.setrate(f.getframerate())
|
||||
format = None
|
||||
|
||||
# 8bit is unsigned in wav files
|
||||
if f.getsampwidth() == 1:
|
||||
device.setformat(alsaaudio.PCM_FORMAT_U8)
|
||||
# Otherwise we assume signed data, little endian
|
||||
elif f.getsampwidth() == 2:
|
||||
device.setformat(alsaaudio.PCM_FORMAT_S16_LE)
|
||||
elif f.getsampwidth() == 3:
|
||||
device.setformat(alsaaudio.PCM_FORMAT_S24_3LE)
|
||||
elif f.getsampwidth() == 4:
|
||||
device.setformat(alsaaudio.PCM_FORMAT_S32_LE)
|
||||
else:
|
||||
raise ValueError('Unsupported format')
|
||||
# 8bit is unsigned in wav files
|
||||
if f.getsampwidth() == 1:
|
||||
format = alsaaudio.PCM_FORMAT_U8
|
||||
# Otherwise we assume signed data, little endian
|
||||
elif f.getsampwidth() == 2:
|
||||
format = alsaaudio.PCM_FORMAT_S16_LE
|
||||
elif f.getsampwidth() == 3:
|
||||
format = alsaaudio.PCM_FORMAT_S24_3LE
|
||||
elif f.getsampwidth() == 4:
|
||||
format = alsaaudio.PCM_FORMAT_S32_LE
|
||||
else:
|
||||
raise ValueError('Unsupported format')
|
||||
|
||||
periodsize = f.getframerate() / 8
|
||||
periodsize = f.getframerate() // 8
|
||||
|
||||
device.setperiodsize(periodsize)
|
||||
|
||||
data = f.readframes(periodsize)
|
||||
while data:
|
||||
# Read data from stdin
|
||||
device.write(data)
|
||||
data = f.readframes(periodsize)
|
||||
print('%d channels, %d sampling rate, format %d, periodsize %d\n' % (f.getnchannels(),
|
||||
f.getframerate(),
|
||||
format,
|
||||
periodsize))
|
||||
|
||||
device = alsaaudio.PCM(channels=f.getnchannels(), rate=f.getframerate(), format=format, periodsize=periodsize, device=device)
|
||||
|
||||
data = f.readframes(periodsize)
|
||||
while data:
|
||||
# Read data from stdin
|
||||
device.write(data)
|
||||
data = f.readframes(periodsize)
|
||||
|
||||
|
||||
def usage():
|
||||
print('usage: playwav.py [-d <device>] <file>', file=sys.stderr)
|
||||
sys.exit(2)
|
||||
print('usage: playwav.py [-d <device>] <file>', file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
device = 'default'
|
||||
device = 'default'
|
||||
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'd:')
|
||||
for o, a in opts:
|
||||
if o == '-d':
|
||||
device = a
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'd:')
|
||||
for o, a in opts:
|
||||
if o == '-d':
|
||||
device = a
|
||||
|
||||
if not args:
|
||||
usage()
|
||||
|
||||
f = wave.open(args[0], 'rb')
|
||||
device = alsaaudio.PCM(device=device)
|
||||
|
||||
play(device, f)
|
||||
|
||||
f.close()
|
||||
if not args:
|
||||
usage()
|
||||
|
||||
with wave.open(args[0], 'rb') as f:
|
||||
play(device, f)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# -*- mode: python; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
|
||||
|
||||
## recordtest.py
|
||||
##
|
||||
@@ -22,48 +23,42 @@ import getopt
|
||||
import alsaaudio
|
||||
|
||||
def usage():
|
||||
print('usage: recordtest.py [-d <device>] <file>', file=sys.stderr)
|
||||
sys.exit(2)
|
||||
print('usage: recordtest.py [-d <device>] <file>', file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
device = 'default'
|
||||
device = 'default'
|
||||
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'd:')
|
||||
for o, a in opts:
|
||||
if o == '-d':
|
||||
device = a
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'd:')
|
||||
for o, a in opts:
|
||||
if o == '-d':
|
||||
device = a
|
||||
|
||||
if not args:
|
||||
usage()
|
||||
if not args:
|
||||
usage()
|
||||
|
||||
f = open(args[0], 'wb')
|
||||
f = open(args[0], 'wb')
|
||||
|
||||
# Open the device in nonblocking capture mode. The last argument could
|
||||
# just as well have been zero for blocking mode. Then we could have
|
||||
# left out the sleep call in the bottom of the loop
|
||||
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NONBLOCK, device=device)
|
||||
# Open the device in nonblocking capture mode in mono, with a sampling rate of 44100 Hz
|
||||
# and 16 bit little endian samples
|
||||
# The period size controls the internal number of frames per period.
|
||||
# The significance of this parameter is documented in the ALSA api.
|
||||
# For our purposes, it is suficcient to know that reads from the device
|
||||
# will return this many frames. Each frame being 2 bytes long.
|
||||
# This means that the reads below will return either 320 bytes of data
|
||||
# or 0 bytes of data. The latter is possible because we are in nonblocking
|
||||
# mode.
|
||||
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NONBLOCK,
|
||||
channels=1, rate=44100, format=alsaaudio.PCM_FORMAT_S16_LE,
|
||||
periodsize=160, device=device)
|
||||
|
||||
# Set attributes: Mono, 44100 Hz, 16 bit little endian samples
|
||||
inp.setchannels(1)
|
||||
inp.setrate(44100)
|
||||
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)
|
||||
loops = 1000000
|
||||
while loops > 0:
|
||||
loops -= 1
|
||||
# Read data from device
|
||||
l, data = inp.read()
|
||||
|
||||
# The period size controls the internal number of frames per period.
|
||||
# The significance of this parameter is documented in the ALSA api.
|
||||
# For our purposes, it is suficcient to know that reads from the device
|
||||
# will return this many frames. Each frame being 2 bytes long.
|
||||
# This means that the reads below will return either 320 bytes of data
|
||||
# or 0 bytes of data. The latter is possible because we are in nonblocking
|
||||
# mode.
|
||||
inp.setperiodsize(160)
|
||||
|
||||
loops = 1000000
|
||||
while loops > 0:
|
||||
loops -= 1
|
||||
# Read data from device
|
||||
l, data = inp.read()
|
||||
|
||||
if l:
|
||||
f.write(data)
|
||||
time.sleep(.001)
|
||||
if l:
|
||||
f.write(data)
|
||||
time.sleep(.001)
|
||||
|
||||
2
setup.py
2
setup.py
@@ -8,7 +8,7 @@ from setuptools import setup
|
||||
from setuptools.extension import Extension
|
||||
from sys import version
|
||||
|
||||
pyalsa_version = '0.8.4'
|
||||
pyalsa_version = '0.9.1'
|
||||
|
||||
if __name__ == '__main__':
|
||||
setup(
|
||||
|
||||
212
test.py
212
test.py
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# -*- mode: python; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
|
||||
|
||||
# These are internal tests. They shouldn't fail, but they don't cover all
|
||||
# of the ALSA API. Most importantly PCM.read and PCM.write are missing.
|
||||
@@ -12,125 +13,148 @@ import alsaaudio
|
||||
import warnings
|
||||
|
||||
# we can't test read and write well - these are tested otherwise
|
||||
PCMMethods = [('pcmtype', None),
|
||||
('pcmmode', None),
|
||||
('cardname', None),
|
||||
('setchannels', (2,)),
|
||||
('setrate', (44100,)),
|
||||
('setformat', (alsaaudio.PCM_FORMAT_S8,)),
|
||||
('setperiodsize', (320,))]
|
||||
PCMMethods = [
|
||||
('pcmtype', None),
|
||||
('pcmmode', None),
|
||||
('cardname', None)
|
||||
]
|
||||
|
||||
PCMDeprecatedMethods = [
|
||||
('setchannels', (2,)),
|
||||
('setrate', (44100,)),
|
||||
('setformat', (alsaaudio.PCM_FORMAT_S8,)),
|
||||
('setperiodsize', (320,))
|
||||
]
|
||||
|
||||
# A clever test would look at the Mixer capabilities and selectively run the
|
||||
# omitted tests, but I am too tired for that.
|
||||
|
||||
MixerMethods = [('cardname', None),
|
||||
('mixer', None),
|
||||
('mixerid', None),
|
||||
('switchcap', None),
|
||||
('volumecap', None),
|
||||
('getvolume', None),
|
||||
('getrange', None),
|
||||
('getenum', None),
|
||||
# ('getmute', None),
|
||||
# ('getrec', None),
|
||||
# ('setvolume', (60,)),
|
||||
# ('setmute', (0,))
|
||||
# ('setrec', (0')),
|
||||
]
|
||||
('mixer', None),
|
||||
('mixerid', None),
|
||||
('switchcap', None),
|
||||
('volumecap', None),
|
||||
('getvolume', None),
|
||||
('getrange', None),
|
||||
('getenum', None),
|
||||
# ('getmute', None),
|
||||
# ('getrec', None),
|
||||
# ('setvolume', (60,)),
|
||||
# ('setmute', (0,))
|
||||
# ('setrec', (0')),
|
||||
]
|
||||
|
||||
class MixerTest(unittest.TestCase):
|
||||
"""Test Mixer objects"""
|
||||
"""Test Mixer objects"""
|
||||
|
||||
def testMixer(self):
|
||||
"""Open the default Mixers and the Mixers on every card"""
|
||||
|
||||
for c in alsaaudio.card_indexes():
|
||||
mixers = alsaaudio.mixers(cardindex=c)
|
||||
|
||||
for m in mixers:
|
||||
mixer = alsaaudio.Mixer(m, cardindex=c)
|
||||
mixer.close()
|
||||
def testMixer(self):
|
||||
"""Open the default Mixers and the Mixers on every card"""
|
||||
|
||||
for c in alsaaudio.card_indexes():
|
||||
mixers = alsaaudio.mixers(cardindex=c)
|
||||
|
||||
for m in mixers:
|
||||
mixer = alsaaudio.Mixer(m, cardindex=c)
|
||||
mixer.close()
|
||||
|
||||
def testMixerAll(self):
|
||||
"Run common Mixer methods on an open object"
|
||||
def testMixerAll(self):
|
||||
"Run common Mixer methods on an open object"
|
||||
|
||||
mixers = alsaaudio.mixers()
|
||||
mixer = alsaaudio.Mixer(mixers[0])
|
||||
mixers = alsaaudio.mixers()
|
||||
mixer = alsaaudio.Mixer(mixers[0])
|
||||
|
||||
for m, a in MixerMethods:
|
||||
f = alsaaudio.Mixer.__dict__[m]
|
||||
if a is None:
|
||||
f(mixer)
|
||||
else:
|
||||
f(mixer, *a)
|
||||
for m, a in MixerMethods:
|
||||
f = alsaaudio.Mixer.__dict__[m]
|
||||
if a is None:
|
||||
f(mixer)
|
||||
else:
|
||||
f(mixer, *a)
|
||||
|
||||
mixer.close()
|
||||
mixer.close()
|
||||
|
||||
def testMixerClose(self):
|
||||
"""Run common Mixer methods on a closed object and verify it raises an
|
||||
error"""
|
||||
def testMixerClose(self):
|
||||
"""Run common Mixer methods on a closed object and verify it raises an
|
||||
error"""
|
||||
|
||||
mixers = alsaaudio.mixers()
|
||||
mixer = alsaaudio.Mixer(mixers[0])
|
||||
mixer.close()
|
||||
mixers = alsaaudio.mixers()
|
||||
mixer = alsaaudio.Mixer(mixers[0])
|
||||
mixer.close()
|
||||
|
||||
for m, a in MixerMethods:
|
||||
f = alsaaudio.Mixer.__dict__[m]
|
||||
if a is None:
|
||||
self.assertRaises(alsaaudio.ALSAAudioError, f, mixer)
|
||||
else:
|
||||
self.assertRaises(alsaaudio.ALSAAudioError, f, mixer, *a)
|
||||
for m, a in MixerMethods:
|
||||
f = alsaaudio.Mixer.__dict__[m]
|
||||
if a is None:
|
||||
self.assertRaises(alsaaudio.ALSAAudioError, f, mixer)
|
||||
else:
|
||||
self.assertRaises(alsaaudio.ALSAAudioError, f, mixer, *a)
|
||||
|
||||
class PCMTest(unittest.TestCase):
|
||||
"""Test PCM objects"""
|
||||
"""Test PCM objects"""
|
||||
|
||||
def testPCM(self):
|
||||
"Open a PCM object on every card"
|
||||
def testPCM(self):
|
||||
"Open a PCM object on every card"
|
||||
|
||||
for c in alsaaudio.card_indexes():
|
||||
pcm = alsaaudio.PCM(cardindex=c)
|
||||
pcm.close()
|
||||
for c in alsaaudio.card_indexes():
|
||||
pcm = alsaaudio.PCM(cardindex=c)
|
||||
pcm.close()
|
||||
|
||||
def testPCMAll(self):
|
||||
"Run all PCM methods on an open object"
|
||||
def testPCMAll(self):
|
||||
"Run all PCM methods on an open object"
|
||||
|
||||
pcm = alsaaudio.PCM()
|
||||
pcm = alsaaudio.PCM()
|
||||
|
||||
for m, a in PCMMethods:
|
||||
f = alsaaudio.PCM.__dict__[m]
|
||||
if a is None:
|
||||
f(pcm)
|
||||
else:
|
||||
f(pcm, *a)
|
||||
for m, a in PCMMethods:
|
||||
f = alsaaudio.PCM.__dict__[m]
|
||||
if a is None:
|
||||
f(pcm)
|
||||
else:
|
||||
f(pcm, *a)
|
||||
|
||||
pcm.close()
|
||||
pcm.close()
|
||||
|
||||
def testPCMClose(self):
|
||||
"Run all PCM methods on a closed object and verify it raises an error"
|
||||
def testPCMClose(self):
|
||||
"Run all PCM methods on a closed object and verify it raises an error"
|
||||
|
||||
pcm = alsaaudio.PCM()
|
||||
pcm.close()
|
||||
pcm = alsaaudio.PCM()
|
||||
pcm.close()
|
||||
|
||||
for m, a in PCMMethods:
|
||||
f = alsaaudio.PCM.__dict__[m]
|
||||
if a is None:
|
||||
self.assertRaises(alsaaudio.ALSAAudioError, f, pcm)
|
||||
else:
|
||||
self.assertRaises(alsaaudio.ALSAAudioError, f, pcm, *a)
|
||||
for m, a in PCMMethods:
|
||||
f = alsaaudio.PCM.__dict__[m]
|
||||
if a is None:
|
||||
self.assertRaises(alsaaudio.ALSAAudioError, f, pcm)
|
||||
else:
|
||||
self.assertRaises(alsaaudio.ALSAAudioError, f, pcm, *a)
|
||||
|
||||
def testPCMDeprecated(self):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
# Cause all warnings to always be triggered.
|
||||
warnings.simplefilter("always")
|
||||
def testPCMDeprecated(self):
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
# Cause all warnings to always be triggered.
|
||||
warnings.simplefilter("always")
|
||||
|
||||
try:
|
||||
pcm = alsaaudio.PCM(card='default')
|
||||
except alsaaudio.ALSAAudioError:
|
||||
pass
|
||||
|
||||
# Verify we got a DepreciationWarning
|
||||
self.assertEqual(len(w), 1, "PCM(card='default') expected a warning" )
|
||||
self.assertTrue(issubclass(w[-1].category, DeprecationWarning), "PCM(card='default') expected a DeprecationWarning")
|
||||
|
||||
for m, a in PCMDeprecatedMethods:
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
# Cause all warnings to always be triggered.
|
||||
warnings.simplefilter("always")
|
||||
|
||||
pcm = alsaaudio.PCM()
|
||||
|
||||
f = alsaaudio.PCM.__dict__[m]
|
||||
if a is None:
|
||||
f(pcm)
|
||||
else:
|
||||
f(pcm, *a)
|
||||
|
||||
# Verify we got a DepreciationWarning
|
||||
method = "%s%s" % (m, str(a))
|
||||
self.assertEqual(len(w), 1, method + " expected a warning")
|
||||
self.assertTrue(issubclass(w[-1].category, DeprecationWarning), method + " expected a DeprecationWarning")
|
||||
|
||||
try:
|
||||
pcm = alsaaudio.PCM(card='default')
|
||||
except alsaaudio.ALSAAudioError:
|
||||
pass
|
||||
|
||||
# Verify we got a DepreciationWarning
|
||||
assert len(w) == 1
|
||||
assert issubclass(w[-1].category, DeprecationWarning)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user