mirror of
https://github.com/larsimmisch/pyalsaaudio.git
synced 2026-06-12 15:22:25 +00:00
Compare commits
32 Commits
0.11.0-test
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b3d11582e0 | |||
| 2a2fa8f742 | |||
| acc6f152a3 | |||
| 0d6e0e7bb4 | |||
| 4f3c299e53 | |||
| e78c145d9e | |||
| 6acae81487 | |||
| 5eed8adfe5 | |||
| e3e51cc34d | |||
| f6f53ce92a | |||
| 38d0882379 | |||
| 6822cffcc8 | |||
| 8c1e370e04 | |||
| 6d17bc92b7 | |||
| 3e41a9eb97 | |||
| df8886dde1 | |||
| aac2843f73 | |||
| 7987986ee4 | |||
| ae93ddc48e | |||
| a48389b750 | |||
| 0b8db5f46d | |||
| 6b2c4c22db | |||
| a7896ee069 | |||
| ed83b3e29b | |||
| e96f550862 | |||
| 40f4647d8c | |||
| 3a8c53851d | |||
| f6770e3a42 | |||
| 0ac28e9eea | |||
| fdc5f3782e | |||
| 6efef83429 | |||
| df5c2f4685 |
@@ -2,7 +2,7 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- mttbernardini/chore/modern-packaging
|
- main
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: "pages"
|
group: "pages"
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ jobs:
|
|||||||
upload_pypi:
|
upload_pypi:
|
||||||
needs: [build_wheels, build_sdist]
|
needs: [build_wheels, build_sdist]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# TODO: set environment back to pypi after testing
|
environment: pypi
|
||||||
environment: testpypi
|
|
||||||
permissions:
|
permissions:
|
||||||
id-token: write
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
@@ -54,6 +53,3 @@ jobs:
|
|||||||
path: dist
|
path: dist
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
- uses: pypa/gh-action-pypi-publish@release/v1
|
- uses: pypa/gh-action-pypi-publish@release/v1
|
||||||
# TODO: delete below once workflow is proved functional
|
|
||||||
with:
|
|
||||||
repository-url: https://test.pypi.org/legacy/
|
|
||||||
|
|||||||
@@ -46,14 +46,9 @@ First, get the sources and change to the source directory:
|
|||||||
$ cd pyalsaaudio
|
$ cd pyalsaaudio
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, build:
|
Then, build and install:
|
||||||
```
|
```
|
||||||
$ python setup.py build
|
$ pip install .
|
||||||
```
|
|
||||||
|
|
||||||
And install:
|
|
||||||
```
|
|
||||||
$ sudo python setup.py install
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Using the API
|
# Using the API
|
||||||
|
|||||||
+8
-18
@@ -1,28 +1,18 @@
|
|||||||
# Make a new release
|
# Make a new release
|
||||||
|
|
||||||
Update the version in setup.py
|
Create and push a tag naming the version (i.e. 0.11.1):
|
||||||
|
|
||||||
pyalsa_version = '0.9.0'
|
git tag 0.11.1
|
||||||
|
git push origin 0.11.1
|
||||||
|
|
||||||
Commit and push the update.
|
This should trigger a build via a github actions and publish pre-built binaries to pypi.org
|
||||||
|
|
||||||
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
|
# Publish the documentation
|
||||||
|
|
||||||
|
All commits to main should trigger a rebuild of the documentation.
|
||||||
|
|
||||||
|
## Historical background
|
||||||
|
|
||||||
The documentation is published through the `gh-pages` branch.
|
The documentation is published through the `gh-pages` branch.
|
||||||
|
|
||||||
To publish the documentation, you need to clone the `gh-pages` branch of this repository into
|
To publish the documentation, you need to clone the `gh-pages` branch of this repository into
|
||||||
|
|||||||
@@ -807,9 +807,6 @@ Play back the recording with::
|
|||||||
|
|
||||||
$ python playbacktest.py <filename>
|
$ python playbacktest.py <filename>
|
||||||
|
|
||||||
playbacktest.py accepts the commandline option
|
|
||||||
*-d <device>*.
|
|
||||||
|
|
||||||
mixertest.py
|
mixertest.py
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
+2
-6
@@ -77,7 +77,7 @@ Note: the wrappers link with the alsasound library (from the alsa-lib package)
|
|||||||
and need the ALSA headers for compilation. Verify that you have
|
and need the ALSA headers for compilation. Verify that you have
|
||||||
/usr/lib/libasound.so and /usr/include/alsa (or similar paths) before building.
|
/usr/lib/libasound.so and /usr/include/alsa (or similar paths) before building.
|
||||||
|
|
||||||
*On Debian/Ubuntu, install libasound2-dev.*
|
*On Debian (and probably Ubuntu), install libasound2-dev.*
|
||||||
|
|
||||||
Naturally you also need to use a kernel with proper ALSA support. This is the
|
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
|
default in Linux kernel 2.6 and later. If you are using kernel version 2.4 you
|
||||||
@@ -86,11 +86,7 @@ ship with ALSA kernels.
|
|||||||
|
|
||||||
To install, execute the following: --- ::
|
To install, execute the following: --- ::
|
||||||
|
|
||||||
$ python setup.py build
|
$ pip install .
|
||||||
|
|
||||||
And then as root: --- ::
|
|
||||||
|
|
||||||
# python setup.py install
|
|
||||||
|
|
||||||
|
|
||||||
*******
|
*******
|
||||||
|
|||||||
+109
@@ -1448,6 +1448,114 @@ alsapcm_read(alsapcm_t *self, PyObject *args)
|
|||||||
return tuple_obj;
|
return tuple_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
alsapcm_read_sw(alsapcm_t *self, PyObject *args)
|
||||||
|
{
|
||||||
|
snd_pcm_state_t state;
|
||||||
|
int res;
|
||||||
|
int max_frames_to_read;
|
||||||
|
int size;
|
||||||
|
int sizeout = 0;
|
||||||
|
PyObject *buffer_obj, *tuple_obj, *res_obj;
|
||||||
|
char *buffer;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args,"i:read_sw", &max_frames_to_read))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!self->handle) {
|
||||||
|
PyErr_SetString(ALSAAudioError, "PCM device is closed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->pcmtype != SND_PCM_STREAM_CAPTURE)
|
||||||
|
{
|
||||||
|
PyErr_Format(ALSAAudioError, "Cannot read from playback PCM [%s]",
|
||||||
|
self->cardname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = self->framesize * max_frames_to_read;
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
buffer_obj = PyString_FromStringAndSize(NULL, size);
|
||||||
|
if (!buffer_obj)
|
||||||
|
return NULL;
|
||||||
|
buffer = PyString_AS_STRING(buffer_obj);
|
||||||
|
#else
|
||||||
|
buffer_obj = PyBytes_FromStringAndSize(NULL, size);
|
||||||
|
if (!buffer_obj)
|
||||||
|
return NULL;
|
||||||
|
buffer = PyBytes_AS_STRING(buffer_obj);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// After drop() and drain(), we need to prepare the stream again.
|
||||||
|
// Note that fresh streams are already prepared by snd_pcm_hw_params().
|
||||||
|
state = snd_pcm_state(self->handle);
|
||||||
|
if ((state != SND_PCM_STATE_SETUP) ||
|
||||||
|
!(res = snd_pcm_prepare(self->handle))) {
|
||||||
|
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
res = snd_pcm_readi(self->handle, buffer, max_frames_to_read);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
if (res == -EPIPE) {
|
||||||
|
// This means buffer overrun, which we need to report.
|
||||||
|
// However, we recover the stream, so the next PCM.read() will work
|
||||||
|
// again. If recovery fails (very unlikely), report that instead.
|
||||||
|
if (!(res = snd_pcm_prepare(self->handle)))
|
||||||
|
res = -EPIPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != -EPIPE)
|
||||||
|
{
|
||||||
|
if (res == -EAGAIN)
|
||||||
|
{
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
else if (res < 0) {
|
||||||
|
PyErr_Format(ALSAAudioError, "%s [%s]", snd_strerror(res),
|
||||||
|
self->cardname);
|
||||||
|
|
||||||
|
Py_DECREF(buffer_obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sizeout = res * self->framesize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != sizeout) {
|
||||||
|
#if PY_MAJOR_VERSION < 3
|
||||||
|
/* If the following fails, it will free the object */
|
||||||
|
if (_PyString_Resize(&buffer_obj, sizeout))
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
/* If the following fails, it will free the object */
|
||||||
|
if (_PyBytes_Resize(&buffer_obj, sizeout))
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
res_obj = PyLong_FromLong(res);
|
||||||
|
if (!res_obj) {
|
||||||
|
Py_DECREF(buffer_obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
tuple_obj = PyTuple_New(2);
|
||||||
|
if (!tuple_obj) {
|
||||||
|
Py_DECREF(buffer_obj);
|
||||||
|
Py_DECREF(res_obj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Steal reference counts */
|
||||||
|
PyTuple_SET_ITEM(tuple_obj, 0, res_obj);
|
||||||
|
PyTuple_SET_ITEM(tuple_obj, 1, buffer_obj);
|
||||||
|
|
||||||
|
return tuple_obj;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *alsapcm_write(alsapcm_t *self, PyObject *args)
|
static PyObject *alsapcm_write(alsapcm_t *self, PyObject *args)
|
||||||
{
|
{
|
||||||
int datalen;
|
int datalen;
|
||||||
@@ -1767,6 +1875,7 @@ static PyMethodDef alsapcm_methods[] = {
|
|||||||
{"getratebounds", (PyCFunction)alsapcm_getratemaxmin, METH_VARARGS},
|
{"getratebounds", (PyCFunction)alsapcm_getratemaxmin, METH_VARARGS},
|
||||||
{"getrates", (PyCFunction)alsapcm_getrates, METH_VARARGS},
|
{"getrates", (PyCFunction)alsapcm_getrates, METH_VARARGS},
|
||||||
{"read", (PyCFunction)alsapcm_read, METH_VARARGS},
|
{"read", (PyCFunction)alsapcm_read, METH_VARARGS},
|
||||||
|
{"read_sw", (PyCFunction)alsapcm_read_sw, METH_VARARGS},
|
||||||
{"write", (PyCFunction)alsapcm_write, METH_VARARGS},
|
{"write", (PyCFunction)alsapcm_write, METH_VARARGS},
|
||||||
{"avail", (PyCFunction)alsapcm_avail, METH_VARARGS},
|
{"avail", (PyCFunction)alsapcm_avail, METH_VARARGS},
|
||||||
{"pause", (PyCFunction)alsapcm_pause, METH_VARARGS},
|
{"pause", (PyCFunction)alsapcm_pause, METH_VARARGS},
|
||||||
|
|||||||
Reference in New Issue
Block a user