Subject: lib/12796: ossaudio's ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) doesn't properly update "info.fragments".
To: None <gnats-bugs@gnats.netbsd.org>
From: Frederick Bruckman <fb@enteract.com>
List: netbsd-bugs
Date: 04/30/2001 15:11:54
>Number:         12796
>Category:       lib
>Synopsis:       ossaudio's ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) doesn't properly update "info.fragments".
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Apr 30 13:12:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Frederick Bruckman
>Release:        NetBSD-1.5.1_BETA
>Organization:
>Environment:
System: NetBSD fiona.amberites.invalid 1.5.1_BETA NetBSD 1.5.1_BETA (FIONA) #0:
  Thu Apr 5 23:18:39 CDT 2001 fredb@fiona.amberites.invalid:
  /usr/src/sys/arch/i386/compile/FIONA i386


>Description:
After...

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>

int fd, len;
size_t someSize;
void *someBuffer;
audio_buf_info oss_buf_info;

/* ... */
fd= open("/dev/audio", O_WRONLY);
while (...)
	write=(fd, someBuffer, someSize);
/* ... */
ioctl(fd, SNDCTL_DSP_GETOSPACE, &oss_buf_info)

"oss_buf_info.fragments" and "oss_buf_info.fragstotal" always return
the maximum blocks that could possibly be available, without regard for
either the actual state of the audio device, or it's current blocksize.
This causes "squeak-3.0", which evidently depends on
"oss_buf_info.fragments" on Linux to tell it when it's safe to write,
to wedge hard after playing any sound on NetBSD (with ossaudio).

I suggest we can calculate the requested information using the audio
device's "audio->seek" and "audio->hiwat". Moreover,
"oss_buf_info.fragstotal" looks to me like it should relate to
"oss_buf_info.fragments", that is, it should be the highest value that
"oss_buf_info.fragments" could obtain given the current settings, and
not the highest value that could be stuffed into "audio->play->buffer_size"
== "oss_buf_info.bytes" for any combination of settings.

The following patches allow "squeak", with little modification, to retain
interactive performance during and after audio playback. Of course, I'll
need to find another work-around for the "squeak" package, for non-current
systems, which is why this is low priority. The bump in "SOUND_VERSION"
is so we can work around this bug only if necessary (conditionally).

>How-To-Repeat:
	Build and run the "squeak", and watch it appear to hang after
	playing any sound. The current package has possibly a different 
	problem with sound -- it hangs _before_ it even plays the sound,
	but it may be the same thing (just haven't tried it yet).

	You can get the current "squeak" VM from

	ftp://ftp.inria.fr/INRIA/Projects/SOR/users/piumarta/squeak/

	and I will share my (unfinished) squeak-3.0pre2 package with anyone
	who asks.
>Fix:
Index: ossaudio.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libossaudio/ossaudio.c,v
retrieving revision 1.12
diff -c -r1.12 ossaudio.c
*** ossaudio.c	2000/08/16 16:14:33	1.12
--- ossaudio.c	2001/04/30 20:10:36
***************
*** 339,346 ****
  			return retval;
  		setblocksize(fd, &tmpinfo);
  		bufinfo.fragsize = tmpinfo.blocksize;
! 		bufinfo.fragments = /* XXX */
! 		bufinfo.fragstotal = tmpinfo.play.buffer_size / bufinfo.fragsize;
  		bufinfo.bytes = tmpinfo.play.buffer_size;
  		*(struct audio_buf_info *)argp = bufinfo;
  		break;
--- 339,346 ----
  			return retval;
  		setblocksize(fd, &tmpinfo);
  		bufinfo.fragsize = tmpinfo.blocksize;
! 		bufinfo.fragments = tmpinfo.hiwat - tmpinfo.play.seek / bufinfo.fragsize;
! 		bufinfo.fragstotal = tmpinfo.hiwat;
  		bufinfo.bytes = tmpinfo.play.buffer_size;
  		*(struct audio_buf_info *)argp = bufinfo;
  		break;
Index: soundcard.h
===================================================================
RCS file: /cvsroot/basesrc/lib/libossaudio/soundcard.h,v
retrieving revision 1.10
diff -c -r1.10 soundcard.h
*** soundcard.h	1999/11/16 23:56:42	1.10
--- soundcard.h	2001/04/30 20:10:37
***************
*** 46,52 ****
  #ifndef _SOUNDCARD_H_
  #define _SOUNDCARD_H_
  
! #define SOUND_VERSION	0x030000
  
  #define	SNDCTL_DSP_RESET		_IO  ('P', 0)
  #define	SNDCTL_DSP_SYNC			_IO  ('P', 1)
--- 46,52 ----
  #ifndef _SOUNDCARD_H_
  #define _SOUNDCARD_H_
  
! #define SOUND_VERSION	0x030001
  
  #define	SNDCTL_DSP_RESET		_IO  ('P', 0)
  #define	SNDCTL_DSP_SYNC			_IO  ('P', 1)
>Release-Note:
>Audit-Trail:
>Unformatted: