Module Name:    src
Committed By:   nia
Date:           Tue Jun  8 19:26:48 UTC 2021

Modified Files:
        src/lib/libossaudio: oss_dsp.c

Log Message:
ossaudio(3): nested switch statements are hard to read, refactor


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/lib/libossaudio/oss_dsp.c

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

Modified files:

Index: src/lib/libossaudio/oss_dsp.c
diff -u src/lib/libossaudio/oss_dsp.c:1.1 src/lib/libossaudio/oss_dsp.c:1.2
--- src/lib/libossaudio/oss_dsp.c:1.1	Tue Jun  8 18:43:54 2021
+++ src/lib/libossaudio/oss_dsp.c	Tue Jun  8 19:26:48 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: oss_dsp.c,v 1.1 2021/06/08 18:43:54 nia Exp $	*/
+/*	$NetBSD: oss_dsp.c,v 1.2 2021/06/08 19:26:48 nia Exp $	*/
 
 /*-
  * Copyright (c) 1997-2021 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: oss_dsp.c,v 1.1 2021/06/08 18:43:54 nia Exp $");
+__RCSID("$NetBSD: oss_dsp.c,v 1.2 2021/06/08 19:26:48 nia Exp $");
 
 #include <sys/audioio.h>
 #include <stdbool.h>
@@ -38,6 +38,9 @@ __RCSID("$NetBSD: oss_dsp.c,v 1.1 2021/0
 	(((info)->mode == AUMODE_RECORD) \
 	    ? (info)->record.name : (info)->play.name)
 
+static int encoding_to_format(u_int, u_int);
+static int format_to_encoding(int, struct audio_info *);
+
 static int get_vol(u_int, u_char);
 static void set_vol(int, int, bool);
 
@@ -54,8 +57,6 @@ _oss_dsp_ioctl(int fd, unsigned long com
 	struct count_info cntinfo;
 	struct audio_encoding tmpenc;
 	u_int u;
-	u_int encoding;
-	u_int precision;
 	int perrors, rerrors;
 	static int totalperrors = 0;
 	static int totalrerrors = 0;
@@ -173,82 +174,8 @@ _oss_dsp_ioctl(int fd, unsigned long com
 		break;
 	case SNDCTL_DSP_SETFMT:
 		AUDIO_INITINFO(&tmpinfo);
-		switch (INTARG) {
-		case AFMT_MU_LAW:
-			tmpinfo.play.precision =
-			tmpinfo.record.precision = 8;
-			tmpinfo.play.encoding =
-			tmpinfo.record.encoding = AUDIO_ENCODING_ULAW;
-			break;
-		case AFMT_A_LAW:
-			tmpinfo.play.precision =
-			tmpinfo.record.precision = 8;
-			tmpinfo.play.encoding =
-			tmpinfo.record.encoding = AUDIO_ENCODING_ALAW;
-			break;
-		case AFMT_U8:
-			tmpinfo.play.precision =
-			tmpinfo.record.precision = 8;
-			tmpinfo.play.encoding =
-			tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR;
-			break;
-		case AFMT_S8:
-			tmpinfo.play.precision =
-			tmpinfo.record.precision = 8;
-			tmpinfo.play.encoding =
-			tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR;
-			break;
-		case AFMT_S16_LE:
-			tmpinfo.play.precision =
-			tmpinfo.record.precision = 16;
-			tmpinfo.play.encoding =
-			tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
-			break;
-		case AFMT_S16_BE:
-			tmpinfo.play.precision =
-			tmpinfo.record.precision = 16;
-			tmpinfo.play.encoding =
-			tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE;
-			break;
-		case AFMT_U16_LE:
-			tmpinfo.play.precision =
-			tmpinfo.record.precision = 16;
-			tmpinfo.play.encoding =
-			tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_LE;
-			break;
-		case AFMT_U16_BE:
-			tmpinfo.play.precision =
-			tmpinfo.record.precision = 16;
-			tmpinfo.play.encoding =
-			tmpinfo.record.encoding = AUDIO_ENCODING_ULINEAR_BE;
-			break;
-		/*
-		 * XXX: When the kernel supports 24-bit LPCM by default,
-		 * the 24-bit formats should be handled properly instead
-		 * of falling back to 32 bits.
-		 */
-		case AFMT_S24_PACKED:
-		case AFMT_S24_LE:
-		case AFMT_S32_LE:
-			tmpinfo.play.precision =
-			tmpinfo.record.precision = 32;
-			tmpinfo.play.encoding =
-			tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_LE;
-			break;
-		case AFMT_S24_BE:
-		case AFMT_S32_BE:
-			tmpinfo.play.precision =
-			tmpinfo.record.precision = 32;
-			tmpinfo.play.encoding =
-			tmpinfo.record.encoding = AUDIO_ENCODING_SLINEAR_BE;
-			break;
-		case AFMT_AC3:
-			tmpinfo.play.precision =
-			tmpinfo.record.precision = 16;
-			tmpinfo.play.encoding =
-			tmpinfo.record.encoding = AUDIO_ENCODING_AC3;
-			break;
-		default:
+		retval = format_to_encoding(INTARG, &tmpinfo);
+		if (retval < 0) {
 			/*
 			 * OSSv4 specifies that if an invalid format is chosen
 			 * by an application then a sensible format supported
@@ -270,7 +197,6 @@ _oss_dsp_ioctl(int fd, unsigned long com
 			tmpinfo.record.precision =
 			    (tmpinfo.mode == AUMODE_RECORD) ?
 			    hwfmt.record.precision : hwfmt.play.precision ;
-			break;
 		}
 		/*
 		 * In the post-kernel-mixer world, assume that any error means
@@ -284,55 +210,17 @@ _oss_dsp_ioctl(int fd, unsigned long com
 		retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
 		if (retval < 0)
 			return retval;
-		encoding = GETPRINFO(&tmpinfo, encoding);
-		precision = GETPRINFO(&tmpinfo, precision);
-		switch (encoding) {
-		case AUDIO_ENCODING_ULAW:
-			idat = AFMT_MU_LAW;
-			break;
-		case AUDIO_ENCODING_ALAW:
-			idat = AFMT_A_LAW;
-			break;
-		case AUDIO_ENCODING_SLINEAR_LE:
-			if (precision == 32)
-				idat = AFMT_S32_LE;
-			else if (precision == 24)
-				idat = AFMT_S24_LE;
-			else if (precision == 16)
-				idat = AFMT_S16_LE;
-			else
-				idat = AFMT_S8;
-			break;
-		case AUDIO_ENCODING_SLINEAR_BE:
-			if (precision == 32)
-				idat = AFMT_S32_BE;
-			else if (precision == 24)
-				idat = AFMT_S24_BE;
-			else if (precision == 16)
-				idat = AFMT_S16_BE;
-			else
-				idat = AFMT_S8;
-			break;
-		case AUDIO_ENCODING_ULINEAR_LE:
-			if (precision == 16)
-				idat = AFMT_U16_LE;
-			else
-				idat = AFMT_U8;
-			break;
-		case AUDIO_ENCODING_ULINEAR_BE:
-			if (precision == 16)
-				idat = AFMT_U16_BE;
-			else
-				idat = AFMT_U8;
-			break;
-		case AUDIO_ENCODING_ADPCM:
-			idat = AFMT_IMA_ADPCM;
-			break;
-		case AUDIO_ENCODING_AC3:
-			idat = AFMT_AC3;
-			break;
+		if (tmpinfo.mode == AUMODE_RECORD)
+			retval = encoding_to_format(tmpinfo.record.encoding,
+			    tmpinfo.record.precision);
+		else
+			retval = encoding_to_format(tmpinfo.play.encoding,
+			    tmpinfo.play.precision);
+		if (retval < 0) {
+			errno = EINVAL;
+			return retval;
 		}
-		INTARG = idat;
+		INTARG = retval;
 		break;
 	case SNDCTL_DSP_CHANNELS:
 		retval = ioctl(fd, AUDIO_GETBUFINFO, &tmpinfo);
@@ -386,60 +274,10 @@ _oss_dsp_ioctl(int fd, unsigned long com
 		for(idat = 0, tmpenc.index = 0;
 		    ioctl(fd, AUDIO_GETENC, &tmpenc) == 0;
 		    tmpenc.index++) {
-			switch(tmpenc.encoding) {
-			case AUDIO_ENCODING_ULAW:
-				idat |= AFMT_MU_LAW;
-				break;
-			case AUDIO_ENCODING_ALAW:
-				idat |= AFMT_A_LAW;
-				break;
-			case AUDIO_ENCODING_SLINEAR:
-				idat |= AFMT_S8;
-				break;
-			case AUDIO_ENCODING_SLINEAR_LE:
-				if (tmpenc.precision == 32)
-					idat |= AFMT_S32_LE;
-				else if (tmpenc.precision == 24)
-					idat |= AFMT_S24_LE;
-				else if (tmpenc.precision == 16)
-					idat |= AFMT_S16_LE;
-				else
-					idat |= AFMT_S8;
-				break;
-			case AUDIO_ENCODING_SLINEAR_BE:
-				if (tmpenc.precision == 32)
-					idat |= AFMT_S32_BE;
-				else if (tmpenc.precision == 24)
-					idat |= AFMT_S24_BE;
-				else if (tmpenc.precision == 16)
-					idat |= AFMT_S16_BE;
-				else
-					idat |= AFMT_S8;
-				break;
-			case AUDIO_ENCODING_ULINEAR:
-				idat |= AFMT_U8;
-				break;
-			case AUDIO_ENCODING_ULINEAR_LE:
-				if (tmpenc.precision == 16)
-					idat |= AFMT_U16_LE;
-				else
-					idat |= AFMT_U8;
-				break;
-			case AUDIO_ENCODING_ULINEAR_BE:
-				if (tmpenc.precision == 16)
-					idat |= AFMT_U16_BE;
-				else
-					idat |= AFMT_U8;
-				break;
-			case AUDIO_ENCODING_ADPCM:
-				idat |= AFMT_IMA_ADPCM;
-				break;
-			case AUDIO_ENCODING_AC3:
-				idat |= AFMT_AC3;
-				break;
-			default:
-				break;
-			}
+			retval = encoding_to_format(tmpenc.encoding,
+			    tmpenc.precision);
+			if (retval != -1)
+				idat |= retval;
 		}
 		INTARG = idat;
 		break;
@@ -709,3 +547,139 @@ set_channels(int fd, int mode, int nchan
 		}
 	}
 }
+
+/* Convert a NetBSD "encoding" to a OSS "format". */
+static int
+encoding_to_format(u_int encoding, u_int precision)
+{
+	switch(encoding) {
+	case AUDIO_ENCODING_ULAW:
+		return AFMT_MU_LAW;
+	case AUDIO_ENCODING_ALAW:
+		return AFMT_A_LAW;
+	case AUDIO_ENCODING_SLINEAR:
+		if (precision == 32)
+			return AFMT_S32_NE;
+		else if (precision == 24)
+			return AFMT_S24_NE;
+		else if (precision == 16)
+			return AFMT_S16_NE;
+		return AFMT_S8;
+	case AUDIO_ENCODING_SLINEAR_LE:
+		if (precision == 32)
+			return AFMT_S32_LE;
+		else if (precision == 24)
+			return AFMT_S24_LE;
+		else if (precision == 16)
+			return AFMT_S16_LE;
+		return AFMT_S8;
+	case AUDIO_ENCODING_SLINEAR_BE:
+		if (precision == 32)
+			return AFMT_S32_BE;
+		else if (precision == 24)
+			return AFMT_S24_BE;
+		else if (precision == 16)
+			return AFMT_S16_BE;
+		return AFMT_S8;
+	case AUDIO_ENCODING_ULINEAR:
+		if (precision == 16)
+			return AFMT_U16_NE;
+		return AFMT_U8;
+	case AUDIO_ENCODING_ULINEAR_LE:
+		if (precision == 16)
+			return AFMT_U16_LE;
+		return AFMT_U8;
+	case AUDIO_ENCODING_ULINEAR_BE:
+		if (precision == 16)
+			return AFMT_U16_BE;
+		return AFMT_U8;
+	case AUDIO_ENCODING_ADPCM:
+		return AFMT_IMA_ADPCM;
+	case AUDIO_ENCODING_AC3:
+		return AFMT_AC3;
+	}
+	return -1;
+}
+
+/* Convert an OSS "format" to a NetBSD "encoding". */
+static int
+format_to_encoding(int fmt, struct audio_info *tmpinfo)
+{
+	switch (fmt) {
+	case AFMT_MU_LAW:
+		tmpinfo->record.precision =
+		tmpinfo->play.precision = 8;
+		tmpinfo->record.encoding =
+		tmpinfo->play.encoding = AUDIO_ENCODING_ULAW;
+		return 0;
+	case AFMT_A_LAW:
+		tmpinfo->record.precision =
+		tmpinfo->play.precision = 8;
+		tmpinfo->record.encoding =
+		tmpinfo->play.encoding = AUDIO_ENCODING_ALAW;
+		return 0;
+	case AFMT_U8:
+		tmpinfo->record.precision =
+		tmpinfo->play.precision = 8;
+		tmpinfo->record.encoding =
+		tmpinfo->play.encoding = AUDIO_ENCODING_ULINEAR;
+		return 0;
+	case AFMT_S8:
+		tmpinfo->record.precision =
+		tmpinfo->play.precision = 8;
+		tmpinfo->record.encoding =
+		tmpinfo->play.encoding = AUDIO_ENCODING_SLINEAR;
+		return 0;
+	case AFMT_S16_LE:
+		tmpinfo->record.precision =
+		tmpinfo->play.precision = 16;
+		tmpinfo->record.encoding =
+		tmpinfo->play.encoding = AUDIO_ENCODING_SLINEAR_LE;
+		return 0;
+	case AFMT_S16_BE:
+		tmpinfo->record.precision =
+		tmpinfo->play.precision = 16;
+		tmpinfo->record.encoding =
+		tmpinfo->play.encoding = AUDIO_ENCODING_SLINEAR_BE;
+		return 0;
+	case AFMT_U16_LE:
+		tmpinfo->record.precision =
+		tmpinfo->play.precision = 16;
+		tmpinfo->record.encoding =
+		tmpinfo->play.encoding = AUDIO_ENCODING_ULINEAR_LE;
+		return 0;
+	case AFMT_U16_BE:
+		tmpinfo->record.precision =
+		tmpinfo->play.precision = 16;
+		tmpinfo->record.encoding =
+		tmpinfo->play.encoding = AUDIO_ENCODING_ULINEAR_BE;
+		return 0;
+	/*
+	 * XXX: When the kernel supports 24-bit LPCM by default,
+	 * the 24-bit formats should be handled properly instead
+	 * of falling back to 32 bits.
+	 */
+	case AFMT_S24_PACKED:
+	case AFMT_S24_LE:
+	case AFMT_S32_LE:
+		tmpinfo->record.precision =
+		tmpinfo->play.precision = 32;
+		tmpinfo->record.encoding =
+		tmpinfo->play.encoding = AUDIO_ENCODING_SLINEAR_LE;
+		return 0;
+	case AFMT_S24_BE:
+	case AFMT_S32_BE:
+		tmpinfo->record.precision =
+		tmpinfo->play.precision = 32;
+		tmpinfo->record.encoding =
+		tmpinfo->play.encoding = AUDIO_ENCODING_SLINEAR_BE;
+		return 0;
+	case AFMT_AC3:
+		tmpinfo->record.precision =
+		tmpinfo->play.precision = 16;
+		tmpinfo->record.encoding =
+		tmpinfo->play.encoding = AUDIO_ENCODING_AC3;
+		return 0;
+	}
+	return -1;
+}

Reply via email to