Module Name:    src
Committed By:   nat
Date:           Tue May 15 00:28:00 UTC 2018

Modified Files:
        src/sys/dev: audio.c

Log Message:
Expose the audio_info structure of vchan zero(0) the mix ring to allow
setting the hardware gain and balance via audioctl(1) using the -p 0
switch.

It is not possible to influence the hardware gain/blance from the
audio_info structure of vchans 1 onwards.  It is now possible to return
the audio mixers audio format from the audio_info structure of vchan 0 to
ease applications configuring for mmapped play back.

This is conformant to the audio specification posted on tech-kern see:
        "NetBSD Audio Specification 2018"
or audio.7 manual page to be added in a follow up commit.


To generate a diff of this commit:
cvs rdiff -u -r1.453 -r1.454 src/sys/dev/audio.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/audio.c
diff -u src/sys/dev/audio.c:1.453 src/sys/dev/audio.c:1.454
--- src/sys/dev/audio.c:1.453	Tue May 15 00:19:08 2018
+++ src/sys/dev/audio.c	Tue May 15 00:28:00 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: audio.c,v 1.453 2018/05/15 00:19:08 nat Exp $	*/
+/*	$NetBSD: audio.c,v 1.454 2018/05/15 00:28:00 nat Exp $	*/
 
 /*-
  * Copyright (c) 2016 Nathanial Sloss <nathanialsl...@yahoo.com.au>
@@ -148,7 +148,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.453 2018/05/15 00:19:08 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.454 2018/05/15 00:28:00 nat Exp $");
 
 #ifdef _KERNEL_OPT
 #include "audio.h"
@@ -3076,7 +3076,7 @@ audio_ioctl(dev_t dev, struct audio_soft
 
 	KASSERT(mutex_owned(sc->sc_lock));
 
-	if (sc->sc_usemixer) {
+	if (sc->sc_usemixer && chan->deschan != 0) {
 		SIMPLEQ_FOREACH(pchan, &sc->sc_audiochan, entries) {
 			if (pchan->chan == chan->deschan)
 				break;
@@ -3086,7 +3086,10 @@ audio_ioctl(dev_t dev, struct audio_soft
 	} else
 		pchan = chan;
 
-	vc = pchan->vc;
+	if (chan->deschan != 0)
+		vc = pchan->vc;
+	else
+		vc = &sc->sc_mixring;
 
 	DPRINTF(("audio_ioctl(%lu,'%c',%lu)\n",
 		 IOCPARM_LEN(cmd), (char)IOCGROUP(cmd), cmd&0xff));
@@ -3100,7 +3103,7 @@ audio_ioctl(dev_t dev, struct audio_soft
 			*(int*)addr = chan->chan;
 		break;
 	case AUDIO_SETCHAN:
-		if ((int *)addr != NULL && *(int*)addr > 0)
+		if ((int *)addr != NULL && *(int*)addr >= 0)
 			chan->deschan = *(int*)addr;
 		break;
 	case FIONBIO:
@@ -4195,6 +4198,12 @@ audio_set_vchan_defaults(struct audio_so
 
 	if (error == 0)
 		error = audiosetinfo(sc, &ai, true, vc);
+	if (error == 0) {
+		vc = &sc->sc_mixring;
+
+		vc->sc_rparams = sc->sc_vchan_params;
+		vc->sc_pparams = sc->sc_vchan_params;
+	}
 
 	return error;
 }
@@ -4559,6 +4568,9 @@ audiosetinfo(struct audio_softc *sc, str
 	rp = vc->sc_rparams;	/* case setting the modes fails. */
 	nr = np = 0;
 
+	if (vc == &sc->sc_mixring)
+		goto done;
+
 	if (SPECIFIED(p->sample_rate)) {
 		pp.sample_rate = p->sample_rate;
 		np++;
@@ -4644,9 +4656,10 @@ audiosetinfo(struct audio_softc *sc, str
 			vc->sc_mode &= ~AUMODE_RECORD;
 	}
 
+done:
 	oldpus = vc->sc_pustream;
 	oldrus = vc->sc_rustream;
-	if (modechange || reset) {
+	if (vc != &sc->sc_mixring && (modechange || reset)) {
 		int indep;
 
 		indep = audio_get_props(sc) & AUDIO_PROP_INDEPENDENT;
@@ -4741,23 +4754,41 @@ audiosetinfo(struct audio_softc *sc, str
 		if (error)
 			goto cleanup;
 	}
-	if (SPECIFIED(p->gain))
-		vc->sc_swvol = p->gain;
+	if (SPECIFIED(p->gain)) {
+		if (!sc->sc_usemixer || vc == &sc->sc_mixring) {
+			au_get_gain(sc, &sc->sc_outports, &gain, &balance);
+			error = au_set_gain(sc, &sc->sc_outports, p->gain, balance);
+			if (error)
+				goto cleanup;
+		} else
+			vc->sc_swvol = p->gain;
+	}
 
-	if (SPECIFIED(r->gain))
-		vc->sc_recswvol = r->gain;
+	if (SPECIFIED(r->gain)) {
+		if (!sc->sc_usemixer || vc == &sc->sc_mixring) {
+			au_get_gain(sc, &sc->sc_outports, &gain, &balance);
+			error = au_set_gain(sc, &sc->sc_outports, r->gain, balance);
+			if (error)
+				goto cleanup;
+		} else
+			vc->sc_recswvol = r->gain;
+	}
 
 	if (SPECIFIED_CH(p->balance)) {
-		au_get_gain(sc, &sc->sc_outports, &gain, &balance);
-		error = au_set_gain(sc, &sc->sc_outports, gain, p->balance);
-		if (error)
-			goto cleanup;
+		if (!sc->sc_usemixer || vc == &sc->sc_mixring) {
+			au_get_gain(sc, &sc->sc_outports, &gain, &balance);
+			error = au_set_gain(sc, &sc->sc_outports, gain, p->balance);
+			if (error)
+				goto cleanup;
+		}
 	}
 	if (SPECIFIED_CH(r->balance)) {
-		au_get_gain(sc, &sc->sc_inports, &gain, &balance);
-		error = au_set_gain(sc, &sc->sc_inports, gain, r->balance);
-		if (error)
-			goto cleanup;
+		if (!sc->sc_usemixer || vc == &sc->sc_mixring) {
+			au_get_gain(sc, &sc->sc_inports, &gain, &balance);
+			error = au_set_gain(sc, &sc->sc_inports, gain, r->balance);
+			if (error)
+				goto cleanup;
+		}
 	}
 
 	if (SPECIFIED(ai->monitor_gain) && sc->sc_monitor_port != -1) {
@@ -4901,8 +4932,13 @@ audiogetinfo(struct audio_softc *sc, str
 		r->avail_ports = sc->sc_inports.allports;
 		p->avail_ports = sc->sc_outports.allports;
 
-		au_get_gain(sc, &sc->sc_inports, &r->gain, &r->balance);
-		au_get_gain(sc, &sc->sc_outports, &p->gain, &p->balance);
+		if (!sc->sc_usemixer || vc == &sc->sc_mixring) {
+			au_get_gain(sc, &sc->sc_inports, &r->gain, &r->balance);
+			au_get_gain(sc, &sc->sc_outports, &p->gain, &p->balance);
+		} else {
+			p->gain = vc->sc_swvol;
+			r->gain = vc->sc_recswvol;
+		}
 	}
 
 	if (sc->sc_monitor_port != -1 && buf_only_mode == 0) {

Reply via email to