Back at work on the ossaudiodev docs for a few minutes. Documenting an
API is always a great opportunity to clean it up, and the
ossaudiodev.open() function has a weird interface right now. From the
current docs:
"""
open([device, ] mode)
Open an audio device and return an OSS audio device object. This
object supports many file-like methods, such as read(), write(), and
fileno() (although there are subtle differences between conventional
Unix read/write semantics and those of OSS audio devices). It also
supports a number of audio-specific methods; see below for the
complete list of methods.
Note the unusual calling syntax: the first argument is optional, and
the second is required. This is a historical artifact for
compatibility with the older linuxaudiodev module which ossaudiodev
supersedes.
device is the audio device filename to use. If it is not specified,
this module first looks in the environment variable AUDIODEV for a
device to use. If not found, it falls back to /dev/dsp.
mode is one of 'r' for read-only (record) access, 'w' for write-only
(playback) access and 'rw' for both. Since many soundcards only
allow one process to have the recorder or player open at a time it
is a good idea to open the device only for the activity
needed. Further, some soundcards are half-duplex: they can be opened
for reading or writing, but not both at once.
"""
The historical background is that in linuxaudiodev prior to Python 2.3,
it was *impossible* to specify the device file to open -- you had to do
something like this:
os.environ['AUDIODEV'] = "/dev/dsp2"
dsp = linuxaudiodev.open("w")
Fixing that wart is what led me to create ossaudiodev in the first
place. Cleaning up the remaining ugliness in ossaudiodev.open() brings
things nicely full-circle. Anyways, since the module has been renamed,
who cares about backwards compatibility with linuxaudiodev? I'd like to
change the open() interface to:
open(device, mode)
where both are required. (Most use of the audio device is for playback,
not recording. But a default mode of "w" goes counter to expectations.
So I think 'mode' should be required.)
This would also mean getting rid of the $AUDIODEV check in
ossaudiodev.c. Less C code is a good thing, unless of course it leads
to lots of redundant Python code all over the world.
Finally, for consistency I should also change openmixer() to require a
'device' argument (currently, it does the same thing, but hardcodes
"/dev/mixer" and checks $MIXERDEVICE).
Of course, this will lead people to hardcode "/dev/dsp" (and/or
"/dev/mixer") into their Python audio scripts. That's bad if other
OSS-using operating systems have different names for the standard audio
devices. Do they?
But it's certainly no *worse* than the situation for C programmers, who
have to assume "/dev/dsp" as a default -- the open(2) system call
certainly doesn't let you get away with leaving the filename out. And
besides, "/dev/dsp" is already hard-coded into ossaudiodev.c, so if
that's inappropriate on certain operating systems, somebody's going to
lose already.
Thoughts?
Greg
--
Greg Ward
Back at work on the ossaudiodev docs for a few minutes.
Great! I wonder if you have any thoughts on why running test_ossaudiodev hangs when run on Linux Red Hat 7.3? I'm currently using a 2.4.18-24.7.x kernel. I have no idea what other info would be useful to debug this. Regarding the changes you propose, I was going to vote +1 on all, but I realize I'm not a user so my vote should only count as epsilon. --Guido van Rossum (home page: http://www.python.org/~guido/)
Greg Ward
Of course, this will lead people to hardcode "/dev/dsp" (and/or "/dev/mixer") into their Python audio scripts. That's bad if other OSS-using operating systems have different names for the standard audio devices. Do they?
with devfs (Linux) this would be /dev/sound/dsp and /dev/sound/mixer (but there are compatibility links...)
On 11 March 2003, Guido van Rossum said:
Great! I wonder if you have any thoughts on why running test_ossaudiodev hangs when run on Linux Red Hat 7.3? I'm currently using a 2.4.18-24.7.x kernel. I have no idea what other info would be useful to debug this.
The most obvious cause is that some other process has the audio device
open, and your audio {hardware, device driver} only allows one at a
time.
If you're running one of those newfangled GUI environments like KDE or
GNOME, it's quite likely that the esound or aRTSd (however you spell it)
daemon started when you logged in, and is thus blocking all access to
your /dev/dsp. This sucks, but IMHO it's not ossaudiodev's job to know
about esound and similar.
One way to test this is to take your system down to single-user (or at
least a console-only, no-X11 runlevel) and then try running
test_ossaudiodev.
Hmmm, it looks like calling open() with O_NONBLOCK helps. I know this
does *not* affect later read()/write() -- there's a special ioctl() for
non-blocking read/write -- but it *does* appear to fix blocking open().
At least for me it turned a second open() attempt on the same device
from "hang" to "IOError: [Errno 16] Device or resource busy:
'/dev/dsp2'".
Try this patch; if it works I'll check it in:
--- Modules/ossaudiodev.c 10 Mar 2003 03:17:06 -0000 1.24
+++ Modules/ossaudiodev.c 11 Mar 2003 15:56:24 -0000
@@ -131,7 +131,7 @@
basedev = "/dev/dsp";
}
- if ((fd = open(basedev, imode)) == -1) {
+ if ((fd = open(basedev, imode|O_NONBLOCK)) == -1) {
PyErr_SetFromErrnoWithFilename(PyExc_IOError, basedev);
return NULL;
}
test_ossaudiodev.py will still need fixing to handle the EBUSY error,
but at least this should prevent hanging on open().
Greg
--
Greg Ward
On 11 March 2003, Guido van Rossum said:
Great! I wonder if you have any thoughts on why running test_ossaudiodev hangs when run on Linux Red Hat 7.3? I'm currently using a 2.4.18-24.7.x kernel. I have no idea what other info would be useful to debug this.
[Greg]
The most obvious cause is that some other process has the audio device open, and your audio {hardware, device driver} only allows one at a time.
Hm, but I *do* hear some sound coming out of the speaker: a quiet, sped-up squeaky version of the "nobody expects the spanish inquisition" soundclip that test_linuxaudiodev also used to play. (The latter now crashes for me with "linuxaudiodev.error: (0, 'Error')".)
If you're running one of those newfangled GUI environments like KDE or GNOME, it's quite likely that the esound or aRTSd (however you spell it) daemon started when you logged in, and is thus blocking all access to your /dev/dsp. This sucks, but IMHO it's not ossaudiodev's job to know about esound and similar.
One way to test this is to take your system down to single-user (or at least a console-only, no-X11 runlevel) and then try running test_ossaudiodev.
I tried this at runlevel 1, and the symptoms are identical: some squeaks, then it hangs.
Hmmm, it looks like calling open() with O_NONBLOCK helps. I know this does *not* affect later read()/write() -- there's a special ioctl() for non-blocking read/write -- but it *does* appear to fix blocking open(). At least for me it turned a second open() attempt on the same device from "hang" to "IOError: [Errno 16] Device or resource busy: '/dev/dsp2'".
Try this patch; if it works I'll check it in:
--- Modules/ossaudiodev.c 10 Mar 2003 03:17:06 -0000 1.24 +++ Modules/ossaudiodev.c 11 Mar 2003 15:56:24 -0000 @@ -131,7 +131,7 @@ basedev = "/dev/dsp"; }
- if ((fd = open(basedev, imode)) == -1) { + if ((fd = open(basedev, imode|O_NONBLOCK)) == -1) { PyErr_SetFromErrnoWithFilename(PyExc_IOError, basedev); return NULL; }
test_ossaudiodev.py will still need fixing to handle the EBUSY error, but at least this should prevent hanging on open().
Yes, it fixes the hang. Please check it in! The sample is still played at too high a speed, but maybe that's expected? --Guido van Rossum (home page: http://www.python.org/~guido/)
On 11 March 2003, Guido van Rossum said:
Yes, it fixes the hang. Please check it in!
OK, done.
The sample is still played at too high a speed, but maybe that's expected?
No, definitely not. On my system, it sounds the same as it has with
linuxaudiodev for quite a while, and the same as it did with sunaudiodev
on my old Sun box at CNRI before that.
*Maybe* there's something wrong with how setparameters() initializes the
audio device. Try this patch and see how it goes:
--- Lib/test/test_ossaudiodev.py 14 Feb 2003 19:29:22 -0000 1.4
+++ Lib/test/test_ossaudiodev.py 11 Mar 2003 21:42:31 -0000
@@ -52,8 +52,10 @@
a.fileno()
# set parameters based on .au file headers
- a.setparameters(rate, 16, nchannels, fmt)
- a.write(data)
+ a.setfmt(fmt)
+ a.channels(nchannels)
+ a.speed(rate)
+ a.writeall(data)
a.flush()
a.close()
Hmmm, I just noticed that setting O_NONBLOCK at open() time *does* have
an effect -- I needed to change that write() to writeall() in order to
hear the whole test sound. Uh-oh.
Greg
--
Greg Ward
Guido van Rossum wrote The sample is still played at too high a speed, but maybe that's expected?
For what it's worth, my redhat 7.3 Dell laptop does this whenever
it gets a mono sample to play. I'm waiting for RH8.1, this will
hopefully fix the problem.
Anthony
--
Anthony Baxter
participants (4)
-
Anthony Baxter
-
Arne Koewing
-
Greg Ward
-
Guido van Rossum