Subject: pkg/35772: audio/timidity (using 'sun' output driver) pauses at start of playback
To: None <pkg-manager@netbsd.org, gnats-admin@netbsd.org,>
From: None <svs@ropnet.ru>
List: pkgsrc-bugs
Date: 02/21/2007 21:25:00
>Number:         35772
>Category:       pkg
>Synopsis:       audio/timidity (using 'sun' output driver) pauses at start of playback
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Wed Feb 21 21:25:00 +0000 2007
>Originator:     Sergey Svishchev
>Release:        3.0.2_PATCH
>Organization:
>Environment:
auich0 at pci0 dev 31 function 5: i82801EB (ICH5) AC-97 Audio
auich0: interrupting at ioapic0 pin 17 (irq 11)
auich0: ac97: Analog Devices AD1985 codec; headphone, 20 bit DAC, no 3D stereo
auich0: ac97: ext id 3c7<AMAP,LDAC,SDAC,CDAC,SPDIF,DRA,VRA>
auich0: measured ac97 link rate at 48000 Hz
audio0 at auich0: full duplex, mmap, independent

>Description:
timidity plays for less than a second, then pauses for a second or so (waiting for audio buffer to drain, it seems), and then plays the rest of the MIDI.

The reason seems to be: sun_a.c does not handle PM_REQ_GETQSIZ and PM_REQ_GETFRAGSIZ requests, and thus Timidity has to guess the size of audio buffer.
>How-To-Repeat:
Play a MIDI file.  Say, one of these: http://home.modemss.brisnet.org.au/~mlevoi/elp.html
>Fix:
--- timidity/sun_a.c.orig	2004-09-27 03:40:14.000000000 +0400
+++ timidity/sun_a.c	2007-01-29 22:36:14.000000000 +0300
@@ -296,6 +296,18 @@
 
 
 #if !defined(I_FLUSH) || !defined(FLUSHW)
+#  if defined(AUDIO_FLUSH)	/* NetBSD */
+static int sun_discard_playing(void)
+{
+    if(ioctl(dpm.fd, AUDIO_FLUSH, NULL) < 0)
+    {
+	ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: (ioctl) %s",
+		  dpm.name, strerror(errno));
+	return -1;
+    }
+    return 0;
+}
+#  else
 static void null_proc(){}
 static int sun_discard_playing(void)
 {
@@ -308,6 +320,7 @@
     signal(SIGALRM, orig_alarm_handler);
     return open_output();
 }
+#  endif
 #else
 static int sun_discard_playing(void)
 {
@@ -328,6 +341,21 @@
 
     switch(request)
     {
+#ifdef __NetBSD__
+      case PM_REQ_GETQSIZ:
+	if(ioctl(audioctl_fd, AUDIO_GETINFO, &auinfo) < 0)
+	    return -1;
+	return auinfo.play.buffer_size;
+
+      case PM_REQ_GETFRAGSIZ:
+	if(ioctl(audioctl_fd, AUDIO_GETINFO, &auinfo) < 0)
+	    return -1;
+	return auinfo.blocksize;
+
+      case PM_REQ_OUTPUT_FINISH:
+	return ioctl(audioctl_fd, AUDIO_DRAIN, NULL);
+#endif
+
       case PM_REQ_GETFILLED:
 	if(ioctl(audioctl_fd, AUDIO_GETINFO, &auinfo) < 0)
 	    return -1;