diff options
Diffstat (limited to 'tutorials/sndkit/userdev_demo')
| -rw-r--r-- | tutorials/sndkit/userdev_demo/Makefile | 6 | ||||
| -rw-r--r-- | tutorials/sndkit/userdev_demo/udserver.c | 285 | 
2 files changed, 291 insertions, 0 deletions
| diff --git a/tutorials/sndkit/userdev_demo/Makefile b/tutorials/sndkit/userdev_demo/Makefile new file mode 100644 index 0000000..530adf9 --- /dev/null +++ b/tutorials/sndkit/userdev_demo/Makefile @@ -0,0 +1,6 @@ +CFLAGS=-I/usr/lib/oss/include/sys -I/usr/include/oss -g + +all: udserver + +clean: +	rm -f *.o udserver diff --git a/tutorials/sndkit/userdev_demo/udserver.c b/tutorials/sndkit/userdev_demo/udserver.c new file mode 100644 index 0000000..eafe8c9 --- /dev/null +++ b/tutorials/sndkit/userdev_demo/udserver.c @@ -0,0 +1,285 @@ +/* + * Sample server program that uses the oss_userdev driver. + * + * Copyright (C) 4Front Technologies. Released under the BSD license. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <signal.h> +#include <sys/stat.h> + +/* + * OSS specific includes. Use correct -I setting when compiling. Typically + * -I/usr/lib/oss/include/sys or -I/usr/include/sys + */ +#include <soundcard.h> +#include <oss_userdev_exports.h> + +#define SERVER_DEVNAME		"/dev/oss/oss_userdev0/server" + +int server_fd = -1;	/* File descriptor for the server side device. */ + +static void +terminator(int sig) +{ +	wait(); +	exit(0); +} + +static void +create_mixer_interface(int fd) +{ +	userdev_mixctl_t ctl; +	userdev_mixgroup_t grp; +	userdev_mixvalues_t rec; +	int group; + +/* + * Create a slider on the top level + */ + +	memset(&ctl, 0, sizeof(ctl)); +	strcpy(ctl.name, "volumitaz"); +	ctl.parent	=	0; /* Device root group */ +	ctl.type	= 	MIXT_STEREOSLIDER16; +	ctl.flags	= 	MIXF_READABLE|MIXF_WRITEABLE; +	ctl.index	= 	0;	/* Use position 0 of the value array */ +	ctl.maxvalue	= 	100; +	ctl.offset	= 	0; +	ctl.rgbcolor	=	OSS_RGB_RED; + +	if (ioctl(fd, USERDEV_CREATE_MIXCTL, &ctl)==-1) +	{ +		perror("USERDEV_CREATE_MIXCTL"); +		return; +	} +	 +/* + * Create a mixer group under the device root + */ + +	memset(&grp, 0, sizeof(grp)); + +	strcat(grp.name, "private"); +	grp.parent	=	0; +	 +	if (ioctl(fd, USERDEV_CREATE_MIXGROUP, &grp)==-1) +	{ +		perror("USERDEV_CREATE_MIXGROUP"); +		return; +	} + +	group = grp.num; + +/* + * Create an enumerated control under the "private" group that was created above + */ +	memset(&ctl, 0, sizeof(ctl)); +	strcpy(ctl.name, "mode"); +	ctl.parent	=	group; /* See above */ +	ctl.type	= 	MIXT_ENUM; +	ctl.flags	= 	MIXF_READABLE|MIXF_WRITEABLE; +	ctl.index	= 	1;	/* Use position 1 of the value array */ +	ctl.maxvalue	= 	4; + +	memset (&ctl.enum_present, 0xff, sizeof(ctl.enum_present)); /* Mark all choices active */ + +	strcpy(ctl.enum_choises, "stall crawl cruise warp"); + +	if (ioctl(fd, USERDEV_CREATE_MIXCTL, &ctl)==-1) +	{ +		perror("USERDEV_CREATE_MIXCTL"); +		return; +	} + +/* + * Finally set the initial values for all the controls + */ +	memset(&rec, 0, sizeof(rec)); /* Set all to zeroes */ + +	rec.values[0] = 100 | (100<<16);	// volumitaz = 100:100 +	rec.values[1] = 2;			// private.mode = "cruise" + +/* + * Post the initial settings + */ +	if (ioctl(fd, USERDEV_SET_MIXERS, &rec)==-1) +	{ +		perror("USERDEV_SET_MIXERS"); +	} +} + +static void +poll_mixer(int fd) +{ +	static int prev_count=0; +	int count; + +	if (ioctl(fd, USERDEV_GET_MIX_CHANGECOUNT, &count)==-1) +	{ +		perror("USERDEV_GET_MIX_CHANGECOUNT"); +		return; +	} + +	if (count > prev_count) /* Something has changed */ +	{ +		userdev_mixvalues_t rec; +		int i; + +		if (ioctl(fd, USERDEV_GET_MIXERS, &rec)==-1) +		{ +			perror("USERDEV_GET_MIXERS"); +			return; +		} + +		printf("Mixer change %d\n", count); + +		/* +		 * Print only the controls that were allocated in +		 * create_mixer_interface() +		 */ +		for (i=0;i<2;i++) +		    printf("%2d: %08x\n", i, rec.values[i]); +		fflush(stdout); +	} + +	prev_count = count; +} + +int +main(int argc, char *argv[]) +{ +	userdev_create_t crea = {0}; +	char cmd[512]; + +/* + * Sample rate/format we would like to use on server side. The client side + * can use whatever they want since OSS will automatically do the required  + * conversions. + */ +	int rate = 48000; +	int fmt = AFMT_S16_LE; +	int channels = 2; + + + +	int tmp; +	int fragsize=0; + +	if (argc != 2) +	{ +		fprintf(stderr, "Usage: %s <command>\n", argv[0]); +		exit(-1); +	} + +/* + * Open the server side device. A new userdev instance (client&server) + * will automatically get created when the device is opened. However + * creation of the client side will be delayed until USERDEV_CREATE_INSTANCE + * gets called. + */ + +	if ((server_fd = open(SERVER_DEVNAME, O_RDWR, 0))==-1) +	{ +		perror(SERVER_DEVNAME); +		exit(-1); +	} + +/* + * Create the client side device. + */ +	sprintf(crea.name, "udserver device for %s", getenv("USER")); +	crea.flags = USERDEV_F_VMIX_ATTACH | USERDEV_F_VMIX_PRIVATENODE; /* Doesn't work at this moment */ +	crea.match_method = UD_MATCH_UID; +	crea.match_key = geteuid(); +	crea.poll_interval = 10; /* In milliseconds */ + +	if (ioctl(server_fd, USERDEV_CREATE_INSTANCE, &crea)==-1) +	{ +		perror("USERDEV_CREATE_INSTANCE"); +		exit(-1); +	} + +/* + * Set up the master side parameters such as sampling rate and sample format. + * The server application can select whatever format is best for its + * purposes. The client side can select different rate/format if necessary. + */ + +	tmp=0; +	ioctl(server_fd, SNDCTL_DSP_COOKEDMODE, &tmp); /* Turn off conversions */ + +	if (ioctl(server_fd, SNDCTL_DSP_SETFMT, &fmt)==-1) +	   perror("SNDCTL_DSP_SETFMT"); + +	if (ioctl(server_fd, SNDCTL_DSP_CHANNELS, &channels)==-1) +	   perror("SNDCTL_DSP_CHANNELS"); + +	if (ioctl(server_fd, SNDCTL_DSP_SPEED, &rate)==-1) +	   perror("SNDCTL_DSP_SPEED"); + +	if (ioctl(server_fd, SNDCTL_DSP_GETBLKSIZE, &fragsize)==-1) +	   fragsize = 1024; + +	create_mixer_interface(server_fd); + +	if (fork()) +	{ +		/* +		 * Server side code. In this case we have just a simple echo loop +		 * that writes back everything everything received from the client side. +		 */ +		int l; +		int poll_count=0; + +		char *buffer; +		signal(SIGCHLD, terminator); + +		buffer = malloc (fragsize); +		memset(buffer, 0, fragsize); + +		write(server_fd, buffer, fragsize); +		write(server_fd, buffer, fragsize); + +		while ((l=read(server_fd, buffer, fragsize))>0) +		{ +			if (write(server_fd, buffer, l)!=l) +			{ +				perror("write"); +				exit(-1); +			} + +			if (poll_count++ > 10) +			{ +				poll_mixer(server_fd); +				poll_count = 0; +			} +		} + +		exit(0); +	} + +/* + * Client side code. Simply execute the command that was given in + * argv[1]. However replace all %s's by the client side device node name. + */ + +	if (setenv("OSS_AUDIODEV", crea.devnode, 1) == -1) +	   perror("setenv OSS_AUDIODEV"); + +	if (setenv("OSS_MIXERDEV", crea.devnode, 1) == -1) +	   perror("setenv OSS_MIXERDEV"); + +	setenv("PS1", "udserver> ", 1); + +	sprintf(cmd, argv[1], crea.devnode, crea.devnode, crea.devnode); +	printf("Running '%s'\n", cmd); + +	system(cmd); +	exit(0); +} | 
