Add flashing lights to your SPARCstation (patch to SunOS4.1 play)

Mario Wolczko mario at cs.man.ac.uk
Thu Feb 21 08:03:58 AEST 1991


Here's a quick patch to the sun-supplied "play" program (available on
sparcstations and SLCs, SunOS4.1 or higher).  Inspired by an earlier
program to set the keyboard LEDs, it uses them as a VU meter...

No man page, and not necessarily very clean, but it works (I think).

Enjoy!

Mario Wolczko

   ______      Dept. of Computer Science   Internet:      mario at cs.man.ac.uk
 /~      ~\    The University              uucp:      mcsun!ukc!man.cs!mario
(    __    )   Manchester M13 9PL          JANET:         mario at uk.ac.man.cs
 `-':  :`-'    U.K.                        Tel: +44-61-275 6146  (FAX: 6280)
____;  ;_____________the mushroom project___________________________________
*** play.c.sun	Fri Dec 21 18:30:16 1990
--- play.c	Tue Feb  5 18:23:19 1991
***************
*** 20,25 ****
--- 20,26 ----
  #include <multimedia/libaudio.h>
  #include <multimedia/audio_device.h>
  
+ #include <sundev/kbd.h>
  
  #define	Error		(void) fprintf
  
***************
*** 27,37 ****
  /* Local variables */
  char *prog;
  char prog_desc[] = "Play an audio file";
! char prog_opts[] = "Viv:d:?";		/* getopt() flags */
  
  char		*Stdin = "stdin";
  unsigned char	buf[1024 * 64];		/* size should depend on sample_rate */
  
  
  #define	MAX_GAIN		(100)		/* maximum gain */
  
--- 28,40 ----
  /* Local variables */
  char *prog;
  char prog_desc[] = "Play an audio file";
! char prog_opts[] = "lViv:d:?";		/* getopt() flags */
  
  char		*Stdin = "stdin";
  unsigned char	buf[1024 * 64];		/* size should depend on sample_rate */
  
+ int kbd;			/* fd of kbd */
+ unsigned char snd[2];		/* 2 buffer for writes to kbd */
  
  #define	MAX_GAIN		(100)		/* maximum gain */
  
***************
*** 41,47 ****
--- 44,65 ----
   */
  #define	SAMPLE_RATE_THRESHOLD	(.01)
  
+ /* These define the sample used for averaging to calculate the bar graph size */
+ #define LN2_SS 8
+ #define SAMPLE_SIZE (1 << LN2_SS)
  
+ /* how to convert an average to a bar graph, given only 5 different bar sizes */
+ static unsigned char bar[] = {
+ 	0,
+ 	LED_CAPS_LOCK,
+ 	LED_CAPS_LOCK|LED_COMPOSE,
+ 	LED_CAPS_LOCK|LED_COMPOSE,
+ 	LED_CAPS_LOCK|LED_COMPOSE|LED_SCROLL_LOCK,
+ 	LED_CAPS_LOCK|LED_COMPOSE|LED_SCROLL_LOCK,
+ 	LED_CAPS_LOCK|LED_COMPOSE|LED_SCROLL_LOCK|LED_NUM_LOCK,
+ 	LED_CAPS_LOCK|LED_COMPOSE|LED_SCROLL_LOCK|LED_NUM_LOCK
+ };
+ 
  unsigned	Volume = ~0;		/* output volume */
  double		Savevol;		/* saved volume level */
  int		Verbose = FALSE;	/* verbose messages */
***************
*** 52,59 ****
  Audio_hdr	Dev_hdr;		/* audio header for device */
  char		*Ifile;			/* current filename */
  Audio_hdr	File_hdr;		/* audio header for file */
  
- 
  /* Global variables */
  extern int getopt();
  extern int optind;
--- 70,77 ----
  Audio_hdr	Dev_hdr;		/* audio header for device */
  char		*Ifile;			/* current filename */
  Audio_hdr	File_hdr;		/* audio header for file */
+ int 		leds = TRUE;		/* use leds as vu meter */
  
  /* Global variables */
  extern int getopt();
  extern int optind;
***************
*** 63,73 ****
  usage()
  {
  	Error(stderr, "%s -- usage:\n\t%s ", prog_desc, prog);
! 	Error(stderr, "\t[-iV] [-v #] [-d dev] [file ...]\nwhere:\n");
  	Error(stderr, "\t-i\tDon't hang if audio device is busy\n");
  	Error(stderr, "\t-V\tPrint verbose warning messages\n");
  	Error(stderr, "\t-v #\tSet output volume (0 - %d)\n", MAX_GAIN);
  	Error(stderr, "\t-d dev\tSpecify audio device (default: /dev/audio)\n");
  	Error(stderr, "\tfile\tList of files to play\n");
  	Error(stderr, "\t\tIf no files specified, read stdin\n");
  	exit(1);
--- 81,92 ----
  usage()
  {
  	Error(stderr, "%s -- usage:\n\t%s ", prog_desc, prog);
! 	Error(stderr, "\t[-iV] [-v #] [-d dev] [-l] [file ...]\nwhere:\n");
  	Error(stderr, "\t-i\tDon't hang if audio device is busy\n");
  	Error(stderr, "\t-V\tPrint verbose warning messages\n");
  	Error(stderr, "\t-v #\tSet output volume (0 - %d)\n", MAX_GAIN);
  	Error(stderr, "\t-d dev\tSpecify audio device (default: /dev/audio)\n");
+ 	Error(stderr, "\t-l\tDon't use the keyboard LEDs\n");
  	Error(stderr, "\tfile\tList of files to play\n");
  	Error(stderr, "\t\tIf no files specified, read stdin\n");
  	exit(1);
***************
*** 83,91 ****
--- 102,125 ----
  			(void) audio_set_play_gain(Audio_fd, &Savevol);
  		(void) close(Audio_fd);			/* close output */
  	}
+ 	if (leds) {
+ 		snd[1]= 0 ; write(kbd, snd, 2);
+ 		(void) close(kbd);
+ 	}
  	exit(1);
  }
  
+ void set_channel(fd)		/* choose output port on env var */
+ int fd;
+ {
+ 	extern char *getenv();
+ 	unsigned port= getenv("SST_EARPHONES") ? AUDIO_HEADPHONE : AUDIO_SPEAKER;
+ 	
+  	(void) audio_set_play_port(fd, &port); 
+ }
+ 
+ 
+ 
  /*
   * Play a list of audio files.
   */
***************
*** 94,100 ****
  	char		**argv;
  {
  	int		i;
! 	int		cnt;
  	int		err;
  	int		ifd;
  	int		stdinseen;
--- 128,134 ----
  	char		**argv;
  {
  	int		i;
! 	int		cnt, cum_cnt;
  	int		err;
  	int		ifd;
  	int		stdinseen;
***************
*** 101,106 ****
--- 135,141 ----
  	double		vol;
  	struct stat	st;
  	struct sigvec	vec;
+ 	register unsigned char *bufp;
  
  	prog = argv[0];		/* save program initiation name */
  
***************
*** 123,128 ****
--- 158,166 ----
  	case 'i':
  		Immediate = TRUE;
  		break;
+ 	case 'l':
+ 		leds = FALSE;
+ 		break;
  	case '?':
  		usage();
  /*NOTREACHED*/
***************
*** 168,173 ****
--- 206,213 ----
  		exit(1);
  	}
  
+ 	set_channel(Audio_fd);
+ 
  	/* Get the device output encoding configuration */
  	if (audio_get_play_config(Audio_fd, &Dev_hdr) != AUDIO_SUCCESS) {
  		Error(stderr, "%s: %s is not an audio device\n",
***************
*** 188,193 ****
--- 228,239 ----
  		}
  	}
  
+ 	if (leds) { /* open keyboard device */
+ 		kbd= open("/dev/kbd", O_WRONLY);
+ 		snd[0]= 016;		/* code to set leds */
+ 		if (kbd < 0) leds = FALSE;
+ 	}
+ 
  	/* Set up SIGINT handler to flush output */
  	vec.sv_handler = sigint;
  	vec.sv_mask = 0;
***************
*** 254,271 ****
  
  		/*
  		 * At this point, we're all ready to copy the data.
  		 */
! 		while ((cnt = read(ifd, (char *)buf, sizeof (buf))) >= 0) {
! 			/* If input EOF, write an eof marker */
! 			err = write(Audio_fd, (char *)buf, cnt);
  
! 			if (err != cnt) {
! 				Error(stderr, "%s: output error: ", prog);
! 				perror("");
! 				break;
  			}
! 			if (cnt == 0)
! 				break;
  		}
  		if (cnt < 0) {
  			Error(stderr, "%s: error reading ", prog);
--- 300,358 ----
  
  		/*
  		 * At this point, we're all ready to copy the data.
+ 		 * The outer loop grabs a chunk of data.
  		 */
! 		for (cum_cnt=0; cnt = read(ifd, (char *)buf, sizeof (buf)), cnt > 0;) {
! 				/* the inner loop breaks the chunk into
! 				 SAMPLE_SIZEd samples, and averages them */
! 			for (bufp= buf; cnt >= SAMPLE_SIZE ;
! 			     bufp += SAMPLE_SIZE, cnt -= SAMPLE_SIZE) {
! 				register unsigned int total= 0, n;
  
! 				/* write to the audio channel */
! 				err = write(Audio_fd, (char *)bufp, SAMPLE_SIZE);
! 				if (err != SAMPLE_SIZE) {
! 					Error(stderr, "%s: output error: ", prog);
! 					perror("");
! 					break;
! 				}
! 
! 				if (leds) {
! 					cum_cnt += SAMPLE_SIZE;
! 					/* this is the averaging calculation */
! 					for (n= 0; n < SAMPLE_SIZE; ++n) {
! 						unsigned char b=bufp[n];
! 						/* full wave rectification */
! 						total += b&0x80 ? b^0xFF : b^0x7F;
! 					}
! 					
! 					/* now convert to bargraph pattern */
! 					/* seven bits of data -- strip 4 */
! 					snd[1]= bar[total >> (LN2_SS + 4)];
! 					/* and output to leds */
! 					write(kbd, snd, 2);
! 
! 					/* this keeps the leds and audio in sync */
! 					cum_cnt += SAMPLE_SIZE;
! 					if (cum_cnt > 8000) { /* approx 1s */
! 						audio_drain(Audio_fd,FALSE);
! 						cum_cnt= 0;
! 					}
! 				}
  			}
! 			/* remaining chunk: don't average */
! 			if (leds) { /* this keeps the leds and audio in sync */
! 				cum_cnt += SAMPLE_SIZE;
! 				if (cum_cnt > 8000) { /* approx 1s */
! 					audio_drain(Audio_fd,FALSE);
! 					cum_cnt= 0;
! 				}
! 				snd[1]= 0 ; write(kbd, snd, 2);
! 			}
! 			write(Audio_fd, (char *)buf, cnt);
! 
! 			/* If input EOF, write an eof marker */
! 			if (cnt > 0) write(Audio_fd, (char *)buf, 0);
  		}
  		if (cnt < 0) {
  			Error(stderr, "%s: error reading ", prog);



More information about the Alt.sources mailing list