static PyObject * oss_writeall(oss_audio_t *self, PyObject *args) { char *cp; int rv, size; fd_set write_set_fds; int select_rv; /* NB. writeall() is only useful in non-blocking mode: according to Guenter Geiger <*****@*****.**> on the linux-audio-dev list (http://eca.cx/lad/2002/11/0380.html), OSS guarantees that write() in blocking mode consumes the whole buffer. In blocking mode, the behaviour of write() and writeall() from Python is indistinguishable. */ if (!_is_fd_valid(self->fd)) return NULL; if (!PyArg_ParseTuple(args, "y#:write", &cp, &size)) return NULL; if (!_PyIsSelectable_fd(self->fd)) { PyErr_SetString(PyExc_ValueError, "file descriptor out of range for select"); return NULL; } /* use select to wait for audio device to be available */ FD_ZERO(&write_set_fds); FD_SET(self->fd, &write_set_fds); while (size > 0) { Py_BEGIN_ALLOW_THREADS select_rv = select(self->fd+1, NULL, &write_set_fds, NULL, NULL); Py_END_ALLOW_THREADS assert(select_rv != 0); /* no timeout, can't expire */ if (select_rv == -1) return PyErr_SetFromErrno(PyExc_IOError); Py_BEGIN_ALLOW_THREADS rv = write(self->fd, cp, size); Py_END_ALLOW_THREADS if (rv == -1) { if (errno == EAGAIN) { /* buffer is full, try again */ errno = 0; continue; } else /* it's a real error */ return PyErr_SetFromErrno(PyExc_IOError); } else { /* wrote rv bytes */ self->ocount += rv; size -= rv; cp += rv; } } Py_INCREF(Py_None); return Py_None; }
static PyObject * oss_writeall(oss_audio_t *self, PyObject *args) { Py_buffer data; const char *cp; Py_ssize_t size; Py_ssize_t rv; fd_set write_set_fds; int select_rv; /* NB. writeall() is only useful in non-blocking mode: according to Guenter Geiger <*****@*****.**> on the linux-audio-dev list (http://eca.cx/lad/2002/11/0380.html), OSS guarantees that write() in blocking mode consumes the whole buffer. In blocking mode, the behaviour of write() and writeall() from Python is indistinguishable. */ if (!_is_fd_valid(self->fd)) return NULL; if (!PyArg_ParseTuple(args, "y*:writeall", &data)) return NULL; if (!_PyIsSelectable_fd(self->fd)) { PyErr_SetString(PyExc_ValueError, "file descriptor out of range for select"); PyBuffer_Release(&data); return NULL; } /* use select to wait for audio device to be available */ FD_ZERO(&write_set_fds); FD_SET(self->fd, &write_set_fds); cp = (const char *)data.buf; size = data.len; while (size > 0) { Py_BEGIN_ALLOW_THREADS select_rv = select(self->fd+1, NULL, &write_set_fds, NULL, NULL); Py_END_ALLOW_THREADS assert(select_rv != 0); /* no timeout, can't expire */ if (select_rv == -1) { PyBuffer_Release(&data); return PyErr_SetFromErrno(PyExc_OSError); } rv = _Py_write(self->fd, cp, Py_MIN(size, INT_MAX)); if (rv == -1) { /* buffer is full, try again */ if (errno == EAGAIN) { PyErr_Clear(); continue; } /* it's a real error */ PyBuffer_Release(&data); return NULL; } /* wrote rv bytes */ self->ocount += rv; size -= rv; cp += rv; } PyBuffer_Release(&data); Py_RETURN_NONE; }