33 Commits

Author SHA1 Message Date
Lars Immisch
62e5515341 Document the release process. 2020-07-13 22:00:44 +02:00
Lars Immisch
ed027a6141 More output for playwav 2020-07-13 20:42:25 +01:00
Lars Immisch
5302dc524d Cleanup warnings 2020-07-13 20:59:49 +02:00
Lars Immisch
b17b36be50 Better error messages in tests 2020-07-13 20:51:59 +02:00
Lars Immisch
08bdce9ed9 Tests for Depreciations 2020-07-13 20:20:28 +02:00
Lars Immisch
0224c8a308 Inline documentation (and .gitignore) 2020-07-10 00:54:24 +02:00
Lars Immisch
f07627543c Update documentation 2020-07-10 00:45:57 +02:00
Lars Immisch
df889b94ef Don't use setrate etc. in samples. 2020-07-09 21:22:06 +02:00
Lars Immisch
2a21bf6c42 Support all essential parameters in alsapcm_new. 2020-07-08 22:39:46 +02:00
Lars Immisch
8084297926 Merge pull request #83 from stalkerg/master
fix generate switch capabilities
2020-05-25 12:58:03 +02:00
stalkerg
8fbc04e18d fix generate switch capabilities 2020-05-21 17:21:40 +09:00
Lars Immisch
8ed9f924cd Attempt to fix #45 2020-04-23 21:36:29 +01:00
Lars Immisch
046e7c4e87 Get rid of warnings, adjust CHANGES 2020-04-01 22:47:11 +02:00
Lars Immisch
a4c4c7cb62 Consistent indentation and some code style changes (whould be ws only) 2020-03-09 22:28:08 +01:00
Lars Immisch
f478797f6f Merge branch 'dev/card-detail' of https://github.com/jdstmporter/pyalsaaudio into jdstmporter-dev/card-detail 2020-03-09 22:07:23 +01:00
Lars Immisch
12f807698a Merge #80 2020-03-09 22:05:50 +01:00
Julian Porter
fc011b5ea6 restored gitignore! 2020-03-06 20:21:47 +00:00
Julian Porter
f244a70111 tidied up 2020-03-06 20:06:59 +00:00
Julian Porter
a056a90c61 modified version of pyalsaaudio module 2020-03-06 19:59:04 +00:00
Julian Porter
be1b3e131d demo 2020-03-05 00:50:30 +00:00
Danny
8abf06bedf Prevent hang on close after capturing audio
Currently, after recording audio using pyalsaaudio, the client is unable to close the device.

The reason is that PulseAudio client tries to drain the pipe to the PulseAudio server (presumably in order to prevent Broken Pipe error) on closing. That will never finish since new data will always arrive in the pipe.

Worse, the __del__ handler was auto-closing and thus auto-hanging.

Therefore, pause before de-allocating.
2019-12-02 21:39:44 +00:00
Lars Immisch
dcc831e607 Merge pull request #44 from Oranos25/contribution
add support for snd_pcm_drop function
2019-11-14 13:24:36 +01:00
Lars Immisch
e587df9143 Merge pull request #55 from moham96/patch-1
update playwav.py for python 3
2019-11-14 13:20:12 +01:00
Lars Immisch
82febd3f7e Merge pull request #67 from pdericson/master
Update pyalsaaudio.rst
2018-11-16 12:50:52 +01:00
Peter Ericson
1695066c11 Update pyalsaaudio.rst 2018-11-16 16:51:05 +08:00
Lars Immisch
25717020ef Transactional semantics for the alsapcm_set* calls 2018-02-28 09:52:53 +00:00
Lars Immisch
1aae655d24 Update periodsize only after alsapcm_setup succeeded 2018-02-28 00:35:26 +01:00
MOHAMMAD RASIM
c1c8362eb2 update playwav.py for python 3
use int division for periodsize to be compatible with python 3
2018-02-24 19:40:45 +03:00
Lars Immisch
723eff3887 Prepare next release 2018-02-20 12:18:44 +01:00
Lars Immisch
aa9867de18 Document changes, i.e. #53. 2018-02-20 12:10:20 +01:00
Lars Immisch
58f4522769 Merge pull request #53 from jcea/jcea/read_period_size
Unlimited setperiod buffer size when reading frames
2018-02-20 12:05:37 +01:00
Jesus Cea
f2fb61d324 Unlimited setperiod buffer size when reading frames 2018-02-20 11:52:47 +01:00
Anthony Piau
9e79494a95 add support for snd_pcm_drop function 2017-12-28 16:30:32 +00:00
12 changed files with 2272 additions and 1869 deletions

4
.gitignore vendored
View File

@@ -4,6 +4,8 @@ MANIFEST
doc/gh-pages/
doc/html/
doc/doctrees/
doc/_build/
gh-pages/
build/
dist/
dist/
.vscode/

29
CHANGES
View File

@@ -1,3 +1,32 @@
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)

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,22 @@
# 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
Upload the package:
python3 setup.py sdist
Don't forget to update the documentation.
# Publish the documentation
The documentation is published through the `gh-pages` branch.

View File

@@ -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:
@@ -108,7 +107,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 +116,14 @@ 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 +153,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()

View File

@@ -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

View File

@@ -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)

View File

@@ -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:

View File

@@ -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)

View File

@@ -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)
# 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)
loops = 1000000
while loops > 0:
loops -= 1
# Read data from device
l, data = inp.read()
if l:
f.write(data)
time.sleep(.001)

View File

@@ -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.0'
if __name__ == '__main__':
setup(

212
test.py
View File

@@ -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()