forked from auracaster/pyalsaaudio
Compare commits
2 Commits
larsimmisc
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3d11582e0 | ||
|
|
2a2fa8f742 |
@@ -46,14 +46,9 @@ First, get the sources and change to the source directory:
|
||||
$ cd pyalsaaudio
|
||||
```
|
||||
|
||||
Then, build:
|
||||
Then, build and install:
|
||||
```
|
||||
$ python setup.py build
|
||||
```
|
||||
|
||||
And install:
|
||||
```
|
||||
$ sudo python setup.py install
|
||||
$ pip install .
|
||||
```
|
||||
|
||||
# Using the API
|
||||
|
||||
@@ -1,28 +1,18 @@
|
||||
# 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.
|
||||
|
||||
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.
|
||||
This should trigger a build via a github actions and publish pre-built binaries to pypi.org
|
||||
|
||||
# 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.
|
||||
|
||||
To publish the documentation, you need to clone the `gh-pages` branch of this repository into
|
||||
|
||||
@@ -86,11 +86,7 @@ ship with ALSA kernels.
|
||||
|
||||
To install, execute the following: --- ::
|
||||
|
||||
$ python setup.py build
|
||||
|
||||
And then as root: --- ::
|
||||
|
||||
# python setup.py install
|
||||
$ pip install .
|
||||
|
||||
|
||||
*******
|
||||
|
||||
109
src/alsaaudio.c
109
src/alsaaudio.c
@@ -1448,6 +1448,114 @@ alsapcm_read(alsapcm_t *self, PyObject *args)
|
||||
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)
|
||||
{
|
||||
int datalen;
|
||||
@@ -1767,6 +1875,7 @@ static PyMethodDef alsapcm_methods[] = {
|
||||
{"getratebounds", (PyCFunction)alsapcm_getratemaxmin, METH_VARARGS},
|
||||
{"getrates", (PyCFunction)alsapcm_getrates, METH_VARARGS},
|
||||
{"read", (PyCFunction)alsapcm_read, METH_VARARGS},
|
||||
{"read_sw", (PyCFunction)alsapcm_read_sw, METH_VARARGS},
|
||||
{"write", (PyCFunction)alsapcm_write, METH_VARARGS},
|
||||
{"avail", (PyCFunction)alsapcm_avail, METH_VARARGS},
|
||||
{"pause", (PyCFunction)alsapcm_pause, METH_VARARGS},
|
||||
|
||||
Reference in New Issue
Block a user