[rec.music.synth] Unix MIDI software

tjt@cbnewsh.ATT.COM (timothy.j.thompson) (10/01/89)

From article <10430001@hp-lsd.COS.HP.COM>, by dag@hp-lsd.COS.HP.COM (David Geiser):
> Silence?

Perhaps this will stimulate things.

Enclosed is a minimal device driver that provides a /dev/midi that
talks to an MPU-compatible MIDI hardware interface.  It *only* allows
use of the UART mode of the MPU hardware, and the timing resolution of
the clock it provides is (I think) 10 milliseconds.  It was written
for AT&T System V Release 3.2 on a 6386, but may be portable to most
SVR3-based operating systems, perhaps even SVR2.  See the README
and midi.7 files for more info.  The right way to do something like
this is to use streams.  This is a quick and dirty (but also quite
usable) hack.
                   Tim Thompson = tjt@twitch.att.com | att!twitch!tjt

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	devmidi
# This archive created: Sun Oct  1 12:37:02 1989
export PATH; PATH=/bin:$PATH
if test ! -d 'devmidi'
then
	echo shar: creating directory "'devmidi'"
	mkdir 'devmidi'
fi
echo shar: entering directory "'devmidi'"
cd 'devmidi'
echo shar: extracting "'Driver.c'" '(5377 characters)'
if test -f 'Driver.c'
then
	echo shar: will not over-write existing file "'Driver.c'"
else
cat << \SHAR_EOF > 'Driver.c'
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/errno.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/buf.h>
#include <sys/sysmacros.h>
#include <sys/systm.h>
#include <sys/midi.h>

/* BUFSIZ is the size of the buffers obtained from geteblk().  Is there */
/* a #define elsewhere that gives this value?  (besides stdio.h) */
#define BUFSIZ 1024

#define CIRCLESIZE (BUFSIZ*MIDI_BUFS)

#define controller(dev) (minor(dev))

#define DATA_PORT 0x330
#define STATUS_PORT 0x331
#define DATA_READY 0x40
#define DATA_AVAILABLE 0x80
#define RESET 0xff
#define UART 0x3f
/* note that active sensing and ACK from controller are the same */
#define ACK 0xfe
#define ACTIVE 0xfe

#define midi_putdata(ctlr,c)	(outb(ctlr_to_data_port[ctlr],(c)))
#define midi_putcmd(ctlr,c)	(outb(ctlr_to_status_port[ctlr],(c)))
#define midi_getdata(ctlr)	(inb(ctlr_to_data_port[ctlr]))
#define midi_getstatus(ctlr)	(inb(ctlr_to_status_port[ctlr]))
#define data_is_available(ctlr)	(!(midi_getstatus(ctlr)&DATA_AVAILABLE))
#define ready_for_data(ctlr)	(!(midi_getstatus(ctlr)&DATA_READY))

void
midiinit()
{
	register int n;

	/* create an irq_to_ctlr array so that midiintr() can */
	/* get the ctlr number quickly. */
	for ( n=0; n<NUMIRQ; n++ )
		irq_to_ctlr[n] = 0;
	for ( n=0; n<midi_nctlr; n++ )
		irq_to_ctlr[ ctlr_to_irq[n] ] = n;
}

unsigned char *
midiqchr(q,off)
struct midi_queue *q;
off_t off;
{
	struct buf *b;
	unsigned char *a;

	b = q->buf[(int)((off/BUFSIZ)%MIDI_BUFS)];
	if ( ! b )
		return NULL;
	a = (unsigned char *)(b->b_un.b_addr);
	if ( ! a )
		return NULL;
	return (a + (int)(off%BUFSIZ));
}

void
midiqput(q,c)
register struct midi_queue *q;
int c;
{
	register unsigned char *p = midiqchr(q,q->high);

	if ( p ) {
		*p = c;
		q->high++;
		/* if we wrap around in the circular buffer, */
		/* make sure the low offset keeps up (ie. this */
		/* throws away the oldest unread data) */
		if ( (q->high - q->low) >= CIRCLESIZE )
			q->low = q->high - CIRCLESIZE + 1;
	}
}

midiqget(q)
struct midi_queue *q;
{
	register unsigned char *p;
	register int c;

	if ( q->low == q->high )
		return -1;

	p = midiqchr(q,q->low);
	if ( ! p )
		return -1;
	c = *p;
	q->low++;
	return c;
}

void
midireset(ctlr,uart)
{
	register struct midi_ctlr *m = &midi_ctlr[ ctlr ];
	register time_t etime;
	int n;

	while ( data_is_available(ctlr) )
		(void) midi_getdata(ctlr);

	/* try reset twice if ACK not received */
	for ( n=0; n<2; n++ ) {
		midi_putcmd(ctlr,RESET);
		/* probably shouldn't busy loop */
		etime = lbolt + HZ / 40;	/* for 25 milliseconds */
		while ( lbolt >= etime ) {
			if ( midiqget(&(m->in)) == ACK )
				break;
		}
		if ( lbolt < etime )
			break;
	}
	if ( n >= 2 )
		printf("midireset didn't get ACK?\n");
	if ( uart )
		midi_putcmd(ctlr,UART);	/* doesn't send an ACK back */
}

void
midiopen(dev)
{
	register struct midi_ctlr *m;
	register int ctlr = controller(dev);
	register int n;

	if ( ctlr >= midi_nctlr ) {
		u.u_error = ENXIO;
		return;
	}
	m = &midi_ctlr[ctlr];
	if ( ((m->flags)&ISOPEN) == 0 ) {
		/* opened for the first time */
		for ( n=0; n<MIDI_BUFS; n++ ) {
			m->in.buf[n] = geteblk();
			m->in.low = m->in.high = 0;
		}
		m->flags |= ISOPEN;
		m->flags &= (~ACTSENSE);/* default is to ignore active sensing */
		m->clockoffset = lbolt;	/* TIME starts out at 0 */
		midireset(ctlr,1);	/* default is UART mode */
	}
}

void
midiioctl(dev, cmd, arg, mode)
{
	register int ctlr = controller(dev);
	register struct midi_ctlr *m;
	time_t *t;
	off_t n;

	m = &midi_ctlr[ ctlr ];
	switch(cmd) {
	case MIDIACTIVE:
		if ( arg )
			m->flags |= ACTSENSE;
		else
			m->flags &= (~ACTSENSE);
		break;
	case MIDIRESET:
		midireset(ctlr,1);	/* default is UART mode */
		break;
	case MIDITHRU:
		midireset(ctlr,0);
		break;
	case MIDITIMERESET:
		m->clockoffset = lbolt;
		break;
	case MIDITIME:
		t = (time_t *)arg;
#define MILLIPERHZ (1000/HZ)
		if ( t )
			suword(t,(long)(MILLIPERHZ*(lbolt - m->clockoffset)));
		break;
	default:
		u.u_error = EINVAL;
		break;
	}
}

midi_wait_for_ready(ctlr)
{
	int tmout;

	for ( tmout=50000; tmout>0; tmout-- ) {
		if ( ready_for_data(ctlr) )
			break;
	}
	if ( tmout <= 0 ) {
		printf("/dev/midi timed out waiting for data ready\n");
		return 0;
	}
	return 1;
}

void
midiclose(dev)
{
	register struct midi_ctlr *m;
	register int n;
	register int ctlr = controller(dev);

	m = &midi_ctlr[ ctlr ];
	if ( ((m->flags)&ISOPEN) != 0 ) {	/* paranoia */
		m->flags &= (~ISOPEN);
		for ( n=0; n<MIDI_BUFS; n++ )
			brelse(m->in.buf[n]);
	}
	midireset(ctlr,0);
}

void
midiread(dev)
{
	register struct midi_ctlr *m;
	register int ctlr = controller(dev);
	register int c;

	m = &midi_ctlr[ ctlr ];
	while ( u.u_count ) {
		c = midiqget(&(m->in));
		if ( c < 0 )
			break; 
		/* active sensing may be ignored */
		if ( c == ACTIVE && ((m->flags&ACTSENSE)==0) )
			break;
		subyte(u.u_base,c);
		u.u_base++;
		u.u_count--;
	}
}

void
midiwrite(dev)
{
	register int ctlr = controller(dev);

	while ( u.u_count ) {
		if ( midi_wait_for_ready(ctlr) ) {
			midi_putdata(ctlr,fubyte(u.u_base));
			u.u_base++;
			u.u_count--;
		}
	}
}

void
midiintr(irq)
{
	register struct midi_ctlr *m;
	register int ctlr;
	register int c;

	ctlr = irq_to_ctlr[irq];
	if ( data_is_available(ctlr) ) {
		c = midi_getdata(ctlr);
		m = &midi_ctlr[ ctlr ];
		if ( (m->flags & ISOPEN) != 0 )
			midiqput(&(m->in),c);
	}
}
SHAR_EOF
if test 5377 -ne "`wc -c < 'Driver.c'`"
then
	echo shar: error transmitting "'Driver.c'" '(should have been 5377 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Files'" '(24 characters)'
if test -f 'Files'
then
	echo shar: will not over-write existing file "'Files'"
else
cat << \SHAR_EOF > 'Files'
/usr/include/sys/midi.h
SHAR_EOF
if test 24 -ne "`wc -c < 'Files'`"
then
	echo shar: error transmitting "'Files'" '(should have been 24 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Install'" '(3491 characters)'
if test -f 'Install'
then
	echo shar: will not over-write existing file "'Install'"
else
cat << \SHAR_EOF > 'Install'
#
# Install script for Midi device driver package
#

if [ "$1" = -f ]
then
	force=true
else
	force=false
fi

TMP=/tmp/midi.err
rm -f $TMP
ERROR1=" Errors have been written to the file $TMP."
ERROR2=" The Midi Driver software was not installed, and the System has not been modified."

if [ "`id | grep root`" = "" ]
then
	message "You have to be 'root' in order to install the driver! $ERROR2"
	exit 1
fi

echo "Installing Midi Device Driver Package..."

# BEGIN DYNAMIC CREATION OF Space.c, System, and Node
# based on controller info entered interactively

cat <<EOF > Space.c
/* THIS FILE WAS CREATED BY THE Install SCRIPT. */
#include "config.h"
#include "sys/types.h"
#include "sys/midi.h"

struct midi_ctlr midi_ctlr[MIDI_UNITS];
int midi_nctlr = MIDI_UNITS;
int irq_to_ctlr[NUMIRQ];	/* to be filled in by midi_init */

EOF

echo "\nHow many Midi controllers do you have? [1] --> \c"
read nctlr
if [ "$nctlr" = "" ]
then
	nctlr=1
fi
n=0
while [ "$n" -lt $nctlr ]
do
	cn=`expr $n + 1`
	echo "\nWhat is the IRQ # for controller number $cn ? [2] --> \c"
	read vect
	if [ "$vect" = "" ]
	then
		vect=2
	fi
	# On the 6386, vector 2 gets linked to 9
	if [ "$vect" = 2 ]
	then
		vect=9
	fi
	eval vect$n=$vect

	echo "Starting address (in hex) for controller number $cn ? [330] --> \c"
	read addr
	if [ "$addr" = "" ]
	then
		addr=330
	fi
	eval saddr$n=$addr

	echo "Ending address (in hex) for controller number $cn ? [331] --> \c"
	read addr
	if [ "$addr" = "" ]
	then
		addr=331
	fi
	eval eaddr$n=$addr
	n=`expr $n + 1`
done

n=0
> System
while [ "$n" -lt $nctlr ]
do
	eval echo "midi:Y:1:7:1:\$vect$n:\$saddr$n:\$eaddr$n:0:0" |
		sed "s/:/	/g" >> System
	n=`expr $n + 1`
done

echo "int ctlr_to_irq[] = {" >> Space.c
echo MIDI_0_VECT >> Space.c
n=1
while [ "$n" -lt $nctlr ]
do
	echo ",MIDI_${n}_VECT" >> Space.c
	n=`expr $n + 1`
done
echo "};" >> Space.c

echo "int ctlr_to_data_port[] = {" >> Space.c
echo MIDI_0_SIOA >> Space.c
n=1
while [ "$n" -lt $nctlr ]
do
	echo ",MIDI_${n}_SIOA" >> Space.c
	n=`expr $n + 1`
done
echo "};" >> Space.c

echo "int ctlr_to_status_port[] = {" >> Space.c
echo "MIDI_0_SIOA + 1" >> Space.c
n=1
while [ "$n" -lt $nctlr ]
do
	echo ", MIDI_${n}_SIOA + 1" >> Space.c
	n=`expr $n + 1`
done
echo "};" >> Space.c

echo "midi	midi	c	0" > Node
n=1
while [ "$n" -lt $nctlr ]
do
	echo "midi	midi`expr $n + 1`	c	$n" >> Node
	n=`expr $n + 1`
done

echo ""

# END OF DYNAMIC CREATION OF Space.c, System, and Node

/etc/conf/bin/idcheck -p midi 2>> $TMP
if [ $? != 0 ]
then
	if [ $force = true ]
	then
		/etc/conf/bin/idinstall -d midi
	else
		message -cu "The Midi Device Driver is already installed (or partially installed).
Do you wish to overwrite the existing device driver software?"
		if [ $? = 0 ]
		then
			/etc/conf/bin/idinstall -d midi
		else
			exit 1
		fi
	fi
fi

inc=/usr/include/sys/midi.h
cp midi.h $inc
chown bin $inc
chgrp bin $inc
chmod 444 $inc

if [ -f Driver.c ]
then
	echo "Compiling Driver.c ..."
	cc -c Driver.c 2>> $TMP
	if [ $? != 0 ]
	then
		message "There was an error while compiling Driver.c. $ERROR1 $ERROR2"
		exit 1
	fi
fi

/etc/conf/bin/idinstall -a -k midi 2>> $TMP
if [ $? != 0 ]
then
	message "There was an error during package installation. $ERROR1 $ERROR2"
	exit 1
fi

/etc/conf/bin/idbuild 2>> $TMP
if [ $? != 0 ]
then
	# if an error occurs here, remove the driver components
	/etc/conf/bin/idinstall -d midi
	rm -f $inc
	message "There was an error during Kernel reconfiguration. $ERROR1 $ERROR2"
	exit 1
fi

rm -f $TMP
exit 0
SHAR_EOF
if test 3491 -ne "`wc -c < 'Install'`"
then
	echo shar: error transmitting "'Install'" '(should have been 3491 characters)'
fi
chmod +x 'Install'
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(217 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
all : testread testwrite resetmidi

clean :
	rm -f testread testwrite resetmidi *.o

lint : lintlib.ln
	lint -nux lintlib.ln Driver.c | grep -v "struct/union.*never defined"

lintlib.ln : lintlib.c
	lint -c lintlib.c
SHAR_EOF
if test 217 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 217 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Master'" '(32 characters)'
if test -f 'Master'
then
	echo shar: will not over-write existing file "'Master'"
else
cat << \SHAR_EOF > 'Master'
midi	ocrwiI	icH	midi	0	0	1	1	-1
SHAR_EOF
if test 32 -ne "`wc -c < 'Master'`"
then
	echo shar: error transmitting "'Master'" '(should have been 32 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Name'" '(35 characters)'
if test -f 'Name'
then
	echo shar: will not over-write existing file "'Name'"
else
cat << \SHAR_EOF > 'Name'
386unix Midi Device Driver Package
SHAR_EOF
if test 35 -ne "`wc -c < 'Name'`"
then
	echo shar: error transmitting "'Name'" '(should have been 35 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Node'" '(29 characters)'
if test -f 'Node'
then
	echo shar: will not over-write existing file "'Node'"
else
cat << \SHAR_EOF > 'Node'
midi	midi	c	0
midi	midi2	c	1
SHAR_EOF
if test 29 -ne "`wc -c < 'Node'`"
then
	echo shar: error transmitting "'Node'" '(should have been 29 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'README'" '(673 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
This is a minimal device driver that provides a /dev/midi that
talks to an MPU-compatible MIDI hardware interface.  It ONLY allows
use of the UART mode of the MPU hardware.  It was written for AT&T
System V Release 3.2 on a 6386, but may be portable to most System V
Release 3-based operating systems.   To install, invoke (as root):

     Install

This assumes the installable device driver structure of System V 3.2.
The hardware interrupt # and address will be requested interactively.
Included are testread.c and testwrite.c programs that can be used
to exercise the device.  See midi.7 for more info.

                                Tim Thompson = tjt@twitch.att.com
SHAR_EOF
if test 673 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 673 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Reboot'" '(23 characters)'
if test -f 'Reboot'
then
	echo shar: will not over-write existing file "'Reboot'"
else
cat << \SHAR_EOF > 'Reboot'
/etc/conf/bin/idreboot
SHAR_EOF
if test 23 -ne "`wc -c < 'Reboot'`"
then
	echo shar: error transmitting "'Reboot'" '(should have been 23 characters)'
fi
chmod +x 'Reboot'
fi # end of overwriting check
echo shar: extracting "'Remove'" '(419 characters)'
if test -f 'Remove'
then
	echo shar: will not over-write existing file "'Remove'"
else
cat << \SHAR_EOF > 'Remove'
#
# Remove script for Midi device driver
#

TMP=/tmp/midi.err
RERR="An error was encountered while removing the Midi Driver Package.
The file $TMP contains errors reported by the system."

echo "Removing Midi Device Driver Package..."

/etc/conf/bin/idinstall -d midi 2> $TMP
if [ $? != 0 ]
then
	message $RERR
	exit 1
fi

/etc/conf/bin/idbuild 2>> $TMP
if [ $? != 0 ]
then
	message $RERR
	exit 1
fi

rm -f $TMP
exit 0
SHAR_EOF
if test 419 -ne "`wc -c < 'Remove'`"
then
	echo shar: error transmitting "'Remove'" '(should have been 419 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Size'" '(18 characters)'
if test -f 'Size'
then
	echo shar: will not over-write existing file "'Size'"
else
cat << \SHAR_EOF > 'Size'
ROOT=1500
USR=500
SHAR_EOF
if test 18 -ne "`wc -c < 'Size'`"
then
	echo shar: error transmitting "'Size'" '(should have been 18 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'Space.c'" '(420 characters)'
if test -f 'Space.c'
then
	echo shar: will not over-write existing file "'Space.c'"
else
cat << \SHAR_EOF > 'Space.c'
/* THIS FILE WAS CREATED BY THE Install SCRIPT. */
#include "config.h"
#include "sys/types.h"
#include "sys/midi.h"

struct midi_ctlr midi_ctlr[MIDI_UNITS];
int midi_nctlr = MIDI_UNITS;
int irq_to_ctlr[NUMIRQ];	/* to be filled in by midi_init */

int ctlr_to_irq[] = {
MIDI_0_VECT
,MIDI_1_VECT
};
int ctlr_to_data_port[] = {
MIDI_0_SIOA
,MIDI_1_SIOA
};
int ctlr_to_status_port[] = {
MIDI_0_SIOA + 1
, MIDI_1_SIOA + 1
};
SHAR_EOF
if test 420 -ne "`wc -c < 'Space.c'`"
then
	echo shar: error transmitting "'Space.c'" '(should have been 420 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'System'" '(54 characters)'
if test -f 'System'
then
	echo shar: will not over-write existing file "'System'"
else
cat << \SHAR_EOF > 'System'
midi	Y	1	7	1	9	330	331	0	0
midi	Y	1	7	1	7	300	301	0	0
SHAR_EOF
if test 54 -ne "`wc -c < 'System'`"
then
	echo shar: error transmitting "'System'" '(should have been 54 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'midi.7'" '(1025 characters)'
if test -f 'midi.7'
then
	echo shar: will not over-write existing file "'midi.7'"
else
cat << \SHAR_EOF > 'midi.7'
.TH MIDI 7
.SH SYNOPSIS
/dev/midi
.SH DESCRIPTION
/dev/midi controls a MIDI interface.
Data read from and written to /dev/midi is pure MIDI data.
Reading is always non-blocking, returning immediately if
no input is available.
A static number of system buffers is allocated for MIDI input when
/dev/midi is first opened, forming a large circular buffer in which new MIDI
input overwrites the oldest MIDI input (which may still be unread).
Ioctl commands are:
.P
ioctl(fd,MIDIRESET)
.IP
Reset the interface, flushing all pending MIDI input and output.
The MIDI clock time is reset to 0.
.P
ioctl(fd,MIDITHRU)
.IP
Turn ``thru'' mode
on.  This is a mode in which MIDI input is routed directly to
MIDI output, and no MIDI input can be read from /dev/midi until
a MIDIRESET is done.
.P
ioctl(fd,MIDITIMERESET)
.IP
Reset the MIDI clock time to 0.
.P
ioctl(fd,MIDITIME,arg)
.IP
Get the MIDI clock time (relative to the last time a MIDITIMERESET
was done) in milliseconds.
arg is a pointer to a long, into which the value is written.
SHAR_EOF
if test 1025 -ne "`wc -c < 'midi.7'`"
then
	echo shar: error transmitting "'midi.7'" '(should have been 1025 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'midi.h'" '(873 characters)'
if test -f 'midi.h'
then
	echo shar: will not over-write existing file "'midi.h'"
else
cat << \SHAR_EOF > 'midi.h'
/* MIDI_BUFS is the number of buffers to allocate for MIDI I/O queues. */
/* All of the buffers get allocated when /dev/midi is first */
/* opened, and get freed when /dev/midi is finally closed. */
#define MIDI_BUFS 5

#define NUMIRQ 16

#define MIDIC		('M'<<8)
#define MIDIRESET	(MIDIC|01)
#define MIDITIME	(MIDIC|02)
#define MIDITIMERESET	(MIDIC|03)
#define MIDIACTIVE	(MIDIC|04)
#define MIDITHRU	(MIDIC|05)

/* bits for midi_ctlr.flags */
#define ISOPEN		01
/* active sensing is passed on to the reader */
#define ACTSENSE	02

struct midi_queue {
	struct buf *	buf[MIDI_BUFS];
	off_t		low;
	off_t		high;
};

struct midi_ctlr {
	int			flags;
	time_t			clockoffset;
	struct midi_queue	in;
};

extern struct midi_ctlr midi_ctlr[];
extern int midi_nctlr;
extern int irq_to_ctlr[];
extern int ctlr_to_irq[];
extern int ctlr_to_data_port[];
extern int ctlr_to_status_port[];
SHAR_EOF
if test 873 -ne "`wc -c < 'midi.h'`"
then
	echo shar: error transmitting "'midi.h'" '(should have been 873 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'resetmidi.c'" '(273 characters)'
if test -f 'resetmidi.c'
then
	echo shar: will not over-write existing file "'resetmidi.c'"
else
cat << \SHAR_EOF > 'resetmidi.c'
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/midi.h>
#include <sys/signal.h>

main(argc,argv)
int argc;
char **argv;
{
	int fd;

	if ( argc > 1 )
		fd = open(argv[1],O_RDONLY );
	else
		fd = open("/dev/midi",O_RDONLY );
	ioctl(fd,MIDIRESET,0);
	close(fd);
}
SHAR_EOF
if test 273 -ne "`wc -c < 'resetmidi.c'`"
then
	echo shar: error transmitting "'resetmidi.c'" '(should have been 273 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'testread.c'" '(618 characters)'
if test -f 'testread.c'
then
	echo shar: will not over-write existing file "'testread.c'"
else
cat << \SHAR_EOF > 'testread.c'
/*
 * A test program for reading from /dev/midi.
 * Invoke it, and play something on the MIDI input keyboard.
 * Interrupt to terminate.
 */

#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/midi.h>

main(argc,argv)
int argc;
char **argv;
{
	int n, k;
	unsigned char buff[100];
	long t;
	int fd;

	if ( argc > 1 )
		fd = open(argv[1],O_RDONLY );
	else
		fd = open("/dev/midi",O_RDONLY );
	ioctl(fd,MIDIRESET,0);
	while ( 1 ) {
		if ( (n=read(fd,buff,sizeof(buff))) > 0 ) {
			ioctl(fd,MIDITIME,&t);
			printf("Time=%ld  ",t);
			for ( k=0; k<n; k++ )
				printf("  0x%x",buff[k]);
			printf("\n");
		}
	}
}
SHAR_EOF
if test 618 -ne "`wc -c < 'testread.c'`"
then
	echo shar: error transmitting "'testread.c'" '(should have been 618 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'testwrite.c'" '(873 characters)'
if test -f 'testwrite.c'
then
	echo shar: will not over-write existing file "'testwrite.c'"
else
cat << \SHAR_EOF > 'testwrite.c'
/*
 * A test program for writing to /dev/midi.
 *
 * Usage: testwrite {file}
 * 
 * The contents of the file will be used to control the pitches of
 * notes written to /dev/midi.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/midi.h>

main(argc,argv)
int argc;
char **argv;
{
	int n, k, c;
	unsigned char buff[100];
	long t;
	int fd;
	FILE *fin;
	long tm, nexttm;

	if ( argc > 2 ) {
		fd = open(argv[1],O_WRONLY );
		argc--;
		argv++;
	}
	else
		fd = open("/dev/midi",O_WRONLY );

	if ( argc > 1 )
		fin = fopen(argv[1],"r");
	else
		fin = stdin;
	ioctl(fd,MIDIRESET,0);
	ioctl(fd,MIDITIME,&tm);
	while ( (c=getc(fin)) != EOF ) {
		buff[0] = 0x90;
		buff[1] =  c % 128;
		buff[2] = 0x40;
		write(fd,buff,3);
		nexttm = tm + 100;
		while ( tm < nexttm )
			ioctl(fd,MIDITIME,&tm);
		buff[2] = 0x00;
		write(fd,buff,3);
	}
	close(fd);
}
SHAR_EOF
if test 873 -ne "`wc -c < 'testwrite.c'`"
then
	echo shar: error transmitting "'testwrite.c'" '(should have been 873 characters)'
fi
fi # end of overwriting check
echo shar: done with directory "'devmidi'"
cd ..
#	End of shell archive
exit 0

bender@oobleck.Central.Sun.COM (Michael Bender) (10/04/89)

Does anyone know of any UNIX-based MIDI software (specifically
for a Sun)?  Preferably PD?  I'm looking for a sequencer/patch
editor-librarian/sample editor, whatever's out there.

thanks,
mike bender
------------------------------------------------------------------------
michael bender - bender@sun                (can't think of a witty thing
 415 336-6353 (w)  415 941-3864 (h)         to put here yet)
------------------------------------------------------------------------

rlw@ttardis.UUCP (Ron Wilson) (10/04/89)

In article <4401@cbnewsh.ATT.COM>, tjt@cbnewsh.ATT.COM (timothy.j.thompson) writes:
>Enclosed is a minimal device driver that provides a /dev/midi that
>talks to an MPU-compatible MIDI hardware interface.  It *only* allows
>use of the UART mode of the MPU hardware, and the timing resolution of
>the clock it provides is (I think) 10 milliseconds.  It was written
>for AT&T System V Release 3.2 on a 6386, but may be portable to most
>SVR3-based operating systems, perhaps even SVR2.  See the README
>and midi.7 files for more info.  The right way to do something like
>this is to use streams.  This is a quick and dirty (but also quite
>usable) hack.
>                   Tim Thompson = tjt@twitch.att.com | att!twitch!tjt
[shell archive deleted]

Any chance of a psuedo driver that would use the standard tty driver
in external baud rate mode?

(Please cross post to rec.music - thanks)