Commit Graph

233 Commits

Author SHA1 Message Date
Lars Immisch
26ba938e04 Make commands optional 2024-04-19 18:32:38 +01:00
Lars Immisch
f5e9d52c74 Add missing attribute 2024-04-19 13:10:39 +01:00
Ville Viinikka
436c31f9fd Add nominal_bits and physical_bits info
Adds the information discussed in pull request #144
2024-03-13 10:59:11 +01:00
Ville Viinikka
eda913b203 Use correct sample bit width
snd_pcm_hw_params_get_sbits gives the number of significant bits, not
the actual number of bits stored. Change to snd_pcm_format_physical_width.

This fixes a bug where, for example on my hardware:
format = 'S32_LE'
significant bits = 24
physical bits = 32

the program will segfault because the allocated buffer is too small.
2024-02-20 18:31:00 +01:00
Lars Immisch
0aba948277 Whitespace cleanup.
I ended up using Visual Studio Code and did a global regex replace
` +\n` -> `\n` (StackOverflow)
2024-02-20 18:08:09 +01:00
Oswald Buddenhagen
9b7b767594 fix docu typo 2024-02-06 00:39:15 +01:00
Oswald Buddenhagen
db87f2ced5 document new avail() and polldescriptors_revents() PCM functions
amends 43a94b3 and 5221311.
2024-02-06 00:39:15 +01:00
Oswald Buddenhagen
f179db2d9b de-duplicate PCM.info() documentation
... and move the dumpinfo() docu.

amends 4e098da - clearly, i'm blind.
2024-02-06 00:39:15 +01:00
Oswald Buddenhagen
420b538321 improve documentation of PCM c'tor and info() method
reformulate and redistribute the information, somewhat inspired by text
provided by Ronald van Elburg in response to issue #110.
2024-02-06 00:39:15 +01:00
Oswald Buddenhagen
ae5c4aad9b add xrun handling to the examples
it's very primitive, but it shows adequately what can happen and what to
do about it minimally (that is, complain and move on).
2024-02-06 00:39:15 +01:00
Oswald Buddenhagen
d23b26b2e5 isine example: fix stereo handling (#42)
while it's usually not actually necessary to generate a stereo signal
(alsa's default plughw device will happily duplicate it for us), we
still do it for demo purposes, just because.

a more realistic demo would actually use numpy, as that's what the
library will most likely be used with, but anyway.
2024-02-06 00:39:15 +01:00
Oswald Buddenhagen
1d63226e56 isine example: simplify calculations in generate()
i found them a tad hard to follow ...
2024-02-06 00:39:15 +01:00
Oswald Buddenhagen
664f81a777 isine example: simplify thread run loop
avoid code duplication.
2024-02-06 00:39:15 +01:00
Oswald Buddenhagen
eb51d11619 isine example: actually play some tones
the thread in the background actually needs time to do something
sensible. this is most easily achieved by simply sleeping in the
foreground thread.

i addition to the 440 Hz tone, also play 1 kHz, to demonstrate how
the change() function is used.
2024-02-06 00:39:15 +01:00
Oswald Buddenhagen
2f74e8e8a4 isine example: fix use of deprecated Thread.setDaemon() 2024-02-06 00:39:15 +01:00
Oswald Buddenhagen
6f52de9da0 isine example: remove questionable setting of period size
there is no need to be pedantic about the period size, especially with
a blocking device. what's more, attempting to set it on an already
playing device would error out, and it would be rather counter-
productive to temporarily stop it.
2024-02-06 00:39:15 +01:00
Oswald Buddenhagen
8fb33ddd49 improve write() underrun handling, take 2
we *really* should not paper over underruns, as they require attention.
however, the previous attempt (c2a6b6e) caused an exception to be thrown
(see #130), which was a bit excessive, and was consequently reverted
(438e52e).

so instead we make the handling consistent with what we do in read():
return the verbatim -EPIPE in this case. this can be simply ignored, and
the next write will resume the stream, so this is mostly backwards-
compatible (the failing write will be discarded and would need
repeating, but that will just cause a skip after the interruption,
which does not seem particularly relevant).

as a drive-by, again stop using snd_pcm_recover(), as it still just
obfuscates the snd_pcm_prepare() call it does in the end.
2024-02-05 23:01:30 +01:00
Oswald Buddenhagen
691c1d9b23 fix return value of PCM.write() on success (#137)
the `else` branch of the return value handling cascade got lost in
commit 438e52e, leading to us returning None on success.

rather than restoring the old code exactly, delay the construction
of the final return code object. this is more consistent with
alsapcm_read() and overall nicer.
2024-02-05 23:01:30 +01:00
Oswald Buddenhagen
061c297f4b remove stray snd_pcm_prepare() call from alsapcm_write()
this came from 438e52e, which tried to partially revert c2a6b6e, but
inserted a chunk that actually belonged to alsapcm_drop(). the latter
does not need to be restored, as we now handle SND_PCM_STATE_SETUP prior
to reading/writing.
2024-02-05 23:01:30 +01:00
Oswald Buddenhagen
8ff3e169cd unbreak read buffer overrun handling
my commit c2a6b6e broke it big time; we'd now just paper over overruns.
:}

the previous handling was fundamentally correct, needing only two
adjustments:
- to recover from drop()/drain(), we need to call snd_pcm_prepare() when
  the stream state is SND_PCM_STATE_SETUP. notably, we must not do this
  when the state is SND_PCM_STATE_XRUN.
- we should error-check the unlikely case that the recovery from an xrun
  fails.

that way we now have two snd_pcm_prepare() call sites in read(), which
looks a bit messy, but it's actually correct.

as a drive-by, simplify the return value check of snd_pcm_prepare() -
values higher than zero are impossible.
2024-02-05 23:01:30 +01:00
Oswald Buddenhagen
7d9c16618b slightly clarify docu of read() wrt. underrun 2024-02-05 23:01:30 +01:00
Oswald Buddenhagen
16345a139a make alsapcm_read()'s return value preparation clearer
... by nesting the success case into the != -EPIPE block.
2024-02-05 23:01:30 +01:00
Lars Immisch
1c730123eb pre-release updates
- update CHANGES.md
- bump version in setup.py

[Revisionist Note] This is the end of the rewritten branch. The original
history can be found in the branch main-pre-rewrite.
2024-02-02 11:42:30 +01:00
Lars Immisch
0df2e0ee6f Ignore volume events if shairplay-sync is running 2024-02-02 11:36:58 +01:00
Lars Immisch
fe3fbe5376 loopback.py: bugfixes 2024-02-02 11:36:58 +01:00
Lars Immisch
42ca8acbad Add a (naive) loopback implementation (#132)
* WIP
* Open/close the playback device when idle.
  It takes a long time until it's stopped, though.
* open/close logic of playback device
* Fix opening logic, make period size divisible by 6
* Be less verbose in level info
* Extra argument for output mixer card index
  Sometimes, this cannot be deduced from the output device
* Better silence detection
* Run run_after_stop when idle on startup
2024-02-02 11:36:58 +01:00
Lars Immisch
522131123c Add PCM.polldescriptors_revents()
Will be used in the upcoming loopback implementation, but it is
worthwhile regardless.
2024-02-02 11:36:58 +01:00
Lars Immisch
43a94b3c62 Add PCM.avail()
Will be used in the upcoming loopback implementation, but it is
worthwhile regardless.
2024-02-02 11:36:58 +01:00
Lars Immisch
9637703ab5 Fix build (#133)
[Revisionist Note] This is a squashed commit formed from commits
f374adb, 3743cf5, and cd44517, still found in the main-pre-rewrite
branch. It incorporates a suggestion from PR #134.
2024-02-02 11:36:58 +01:00
Lars Immisch
438e52e3fc Restore previous behaviour of calling snd_pcm_prepare in case of XRUN (#131) 2024-02-02 11:36:58 +01:00
Lars Immisch
07ac637b1c Fix memory leaks in PCM.write() error paths on python3 2024-02-02 11:36:58 +01:00
Lars Immisch
bdca4dc061 Small improvement to VolumeForwarder 2024-02-02 11:36:58 +01:00
Lars Immisch
24eef474da Refactor loopback. SCNR.
The Reactor now takes a callable, and the loopback and volume forwarder
are now implemented as callable instances, which seemed the most
Pythonic solution.
2024-02-02 11:36:58 +01:00
Lars Immisch
24d26a5161 Better error logging and comments 2024-02-02 11:36:58 +01:00
Lars Immisch
f62e61f844 Add volume control forwarding
This needs the patches from (probably)
https://lkml.org/lkml/2021/3/1/419. They are already in the raspberry OS
kernel sources and the setup works on an RPi 4.
2024-02-02 11:36:58 +01:00
Lars Immisch
53f4f093e1 mixertest.py: print capture volume 2024-02-02 11:36:58 +01:00
Lars Immisch
82308f32ed Add a naive loopback implementation using select.poll()
It does work, though.
2024-02-02 11:36:58 +01:00
Lars Immisch
39d6acd3ac Handle events in alsamixer_getvolume. Closes #126
This issue can be worked around by calling mixer.handleevents() before
calling mixer.getvolume(), but it makes more sense to handle all events
before returning the volume.
2024-02-02 11:36:58 +01:00
Lars Immisch
c5153db0ac Whitespace fixes
- strip trailing whitespace in several files
- fix some indentation (tabs vs. spaces)
2024-02-02 11:36:58 +01:00
Lars Immisch
f25c8243dc Update changes for release
[Revisionist Note] This commit was originally c6a0c80, still available
on the main-pre-rewrite branch. The 0.10.0 tag used to point to it.
0.10.0
2024-02-02 11:33:22 +01:00
Lars Immisch
073d708bd1 Remove trailing whitespace in CHANGES.md 2024-02-02 09:52:11 +01:00
Oswald Buddenhagen
946694d263 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-03-02 00:41:01 +01:00
Oswald Buddenhagen
574f78939d 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.
2023-03-02 00:41:01 +01:00
Oswald Buddenhagen
17d171c1a5 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().
2023-03-02 00:41:01 +01:00
Oswald Buddenhagen
de2fc3c992 bump (minor) version
we're about to add new features.
2023-03-02 00:41:01 +01:00
Oswald Buddenhagen
c2a6b6e583 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.
2023-03-02 00:41:01 +01:00
Oswald Buddenhagen
da7d04e2fd reduce scope of GIL releases
it's pointless to enclose snd_pcm_close() and snd_pcm_pause(), as these
calls don't sleep.
2023-03-02 00:41:01 +01:00
Oswald Buddenhagen
1c1af45a7f 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.
2023-03-02 00:41:01 +01:00
Oswald Buddenhagen
9b773b48d6 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.
2023-03-02 00:41:01 +01:00
Oswald Buddenhagen
b05efa0ad6 add some best practices to the docu
addresses #110, among other things.
2023-03-02 00:41:01 +01:00