At Thu, 31 May 2007 22:00:25 +0100, Alan Horstmann wrote:
On Wednesday 30 May 2007 07:47, you wrote:
Alan Horstmann wrote:
On Tuesday 29 May 2007 17:55, you wrote:
While I see the advantage by your hack (small and backward compatible), I feel that it's too hackish -- it introduces an incompatible way of the existing ioctl.
Do you mean in that ioctls in general are not meant to work like that, in effect passing 2 numbers rather than one?
No, packing two values into one numbers is done with other ioctls too, e.g., SNDCTL_DSP_SETFRAGMENT.
The problem I see is that your patch changes the OSS API in a way that is incompatible with every implementation other than ALSA's. The whole purpose of providing the OSS API in the first place is to be compatible with other implementations.
After a quick thought, another possible fix would be to let apps open each direction separately. For that,
- add some way to make the given PCM stream to non-fullduplex (proc or module options?)
Are you thinking that if an option were set, Alsa-OSS would create separate devices for capture and playback rather than a single duplex device?
No; just a way to disable DSP_CAP_DUPLEX and/or SNDCTL_DSP_SETDUPLEX. When these do not work, applications are forced to open the playback and capture devices separately, e.g.:
fd_playback = open("/dev/dsp", O_WRONLY); fd_capture = open("/dev/dsp", O_RDONLY);
- change portaudio to open each direction separately, O_RDONLY and O_WRONLY at first, then use O_RDWR as fallback
This would be the preferred way. After all, this is the only way that is possible with the existing OSS API when you want to use different sample formats, and it is recommended in all cases (see http://manuals.opensound.com/developer/full_duplex.html).
My reading of the 4Front info is different. I read that they recommend best opening SEPARATE devices, one O_RDONLY and the other O_WRONLY, in their scheme called 'twodevice'. It also states in fulldup.c:-
"... The one device full duplex scheme requires that the device file is opened with O_RDWR."
Whereas what is being suggested here is to open /dev/dsp twice simultaneously, O_RDONLY and O_WRONLY which 4Front definitely doesn't propose.
The crutial point is that Alsa-OSS at present isn't really compatible with 4Front etc BECAUSE they implement separate NON-duplex devices for each capture and playback channel pair, whereas Alsa-OSS just has one, duplex! If for example I use the 4Front driver for my DMX6fire, then (-see: http://manuals.opensound.com/developer/oss_devices.html)
I would have 11 non-duplex devices, which can be opened separately to record and play to the card without the channels-set problem. With Alsa-OSS I have just one! Even if Alsa-OSS had just the 'all outputs' and 'all inputs' devices that would be fine.
Well, I'd say that the current ALSA-OSS implementation _is_ compatible to OSS API. What they do is also a pure hack, as you know, just a workaround because the API doesn't provide the functionality properly for full-duplex with multi-channels. The solution might be different, but it's not the question about "compatibility".
It seems odd that an OSS emulated device is provided to an audio card that could have differing numbers of capture and playback channels, eg 4 capture and 2 playback, but it is impossible to set 4C and 2P when opening it for simultaneous capture and playback. The underlying stream has no problem with doing so, it is just there is no way to pass the numbers. My workaround is to solve an incompatibility that already exists. It seems 4Front avoids this by creating non-duplex devices. The patch extends the functionality of the ioctl in a way that only Alsa-OSS may need, (or perhaps all OSS should adopt?).
The problem is that your patch introduces a real "incompatibility", because it's an extension. That is what I don't like. And, in your way, you'll have to change _both_ kernel and apps.
Following this thread, I come to believe that the problem with audacity is actually the application problem. It tries to open a full-duplex device with different number of channels for both directions. It cannot work because it's not defined in API. OTOH, if the number of channels are same for both directions, it should work with O_RDWR.
So, the fix would be simply like below...
Takashi
--- lib-src/portaudio/pa_unix_oss/pa_unix.c-dist 2007-05-30 17:52:10.000000000 +0200 +++ lib-src/portaudio/pa_unix_oss/pa_unix.c 2007-06-01 11:51:35.000000000 +0200 @@ -779,7 +779,8 @@ PaError PaHost_OpenStream( internalPortA /* ------------------------- OPEN DEVICE -----------------------*/
/* just output */ - if (past->past_OutputDeviceID == past->past_InputDeviceID) + if (past->past_OutputDeviceID == past->past_InputDeviceID && + past->past_NumOutputChannels == past->past_NumInputChannels) {
if ((past->past_NumOutputChannels > 0) && (past->past_NumInputChannels > 0) )