home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Audio 4.94 - Over 11,000 Files
/
audio-11000.iso
/
amiga
/
midi
/
obrst103.lha
/
OberSuite-1.03
/
SourceCode
/
serial.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-23
|
8KB
|
314 lines
/**************************************************************************
* serial.c: Low-level serial device functions.
* A part of OberSuite for the Commodore Amiga.
*
* Author: Daniel Barrett, barrett@cs.umass.edu.
* Version: 1.0.
* Copyright: None! This program is in the Public Domain.
* Please share it with others.
***************************************************************************/
#include "decl.h"
#include "midi.h"
#include "oberheim.h"
/***************************************************************************
* A "placeholder" value indicating that a field needs to be filled in later.
***************************************************************************/
#define FILL_IN_LATER 0
/***************************************************************************
* "Global" variables for the serial port structure.
***************************************************************************/
static struct MsgPort *MidiPort = NULL;
static struct IOExtSer *Midi = NULL;
static long serialFlags = 0L;
/***************************************************************************
* Flags that indicate which structures have been allocated.
***************************************************************************/
#define F_MIDIPORT 1
#define F_MIDI 2
#define F_DEVICE 4
#define F_SERPARAMS 8
/****************************************************************************
* Prototypes.
****************************************************************************/
BOOL MakeSerialDeviceName(char *str, char *device, int *unit);
/****************************************************************************
* SerialSetup: Open the serial port and its message port.
* By default, we use the device DEFAULT_MIDI_DEVICE, unit DEFAULT_MIDI_UNIT.
* However, the user may set an environment variable ENVIRONMENT_VAR to
* indicate the presence of an alternate MIDI device.
****************************************************************************/
BOOL SerialSetup(void)
{
char deviceName[BUFSIZ], *envVar;
int unit;
/* Assume we are using the default MIDI device. */
strcpy(deviceName, DEFAULT_MIDI_DEVICE);
unit = DEFAULT_MIDI_UNIT;
/*
* If the user has set the environment variable, use that MIDI device
* instead. If the environment variable value is illegal, quit.
*/
if ((envVar = GetEnv(ENVIRONMENT_VAR))
&& (!MakeSerialDeviceName(envVar, deviceName, &unit)))
return(FALSE);
/* Do the magic incantations to open the serial device. */
if (! (MidiPort = CreatePort(0, 0)) )
{
ErrorMsg(ERROR_CREATEPORT);
SerialShutdown();
return(FALSE);
}
else
serialFlags |= F_MIDIPORT;
if (! (Midi = (struct IOExtSer *)
CreateExtIO(MidiPort, sizeof(struct IOExtSer))))
{
ErrorMsg(ERROR_IOEXTSER);
SerialShutdown();
return(FALSE);
}
else
serialFlags |= F_MIDI;
Midi->io_SerFlags = SERF_SHARED;
if (OpenDevice(deviceName, unit, (struct IORequest *)Midi, 0))
{
ErrorMsg(ERROR_OPENDEVICE);
if (envVar && ERR_OUTPUT_ALLOWED)
{
fprintf(stderr,
"Perhaps you have the value of your "
ENVIRONMENT_VAR
" variable set incorrectly;\n"
" its value is currently set to \"%s\"\n"
" (meaning \"DEVICE=%s, UNIT=%d\".)\n",
envVar, deviceName, unit);
}
SerialShutdown();
return(FALSE);
}
else
serialFlags |= F_DEVICE;
Midi->io_SerFlags = SERF_RAD_BOOGIE | SERF_EOFMODE;
Midi->io_Baud = MIDI_BAUD_RATE;
Midi->io_TermArray.TermArray0 = 0xF7F7F7F7;
Midi->io_TermArray.TermArray1 = 0xF7F7F7F7;
Midi->io_ExtFlags = 0; /* For future compatibility */
Midi->IOSer.io_Command = SDCMD_SETPARAMS;
if (DoIO((struct IORequest *)Midi) != 0)
{
ErrorMsg(ERROR_SETPARAMS);
SerialShutdown();
return(FALSE);
}
else
serialFlags |= F_SERPARAMS;
return(TRUE);
}
/****************************************************************************
* SerialShutdown: Close the serial port and its message port.
* Be sure to close things in the opposite order in which they were opened.
****************************************************************************/
void SerialShutdown(void)
{
if (serialFlags & F_DEVICE)
{
ResetSerialPort();
AbortIO((struct IORequest *)Midi);
WaitIO((struct IORequest *)Midi);
CloseDevice((struct IORequest *)Midi);
}
if (serialFlags & F_MIDI)
DeleteExtIO((struct IORequest *)Midi);
if (serialFlags & F_MIDIPORT)
DeletePort(MidiPort);
}
/****************************************************************************
* ResetSerialPort: Clear all data from the serial port.
***************************************************************************/
void ResetSerialPort(void)
{
Midi->IOSer.io_Command = CMD_CLEAR;
DoIO((struct IORequest *)Midi);
}
/****************************************************************************
* Is any data there?
***************************************************************************/
long AnyMidiData(void)
{
Midi->IOSer.io_Command = SDCMD_QUERY;
DoIO((struct IORequest *)Midi);
return(Midi->IOSer.io_Actual);
}
/****************************************************************************
* PrepareToReadMidi: Prepare a READ request for the MIDI port.
* PrepareToWriteMidi: Prepare a WRITE request for the MIDI port.
***************************************************************************/
void PrepareToReadMidi(UBYTE buf[], int len)
{
Midi->IOSer.io_Command = CMD_READ;
Midi->IOSer.io_Data = (APTR)buf;
Midi->IOSer.io_Length = len;
}
void PrepareToWriteMidi(UBYTE buf[], int len)
{
Midi->IOSer.io_Command = CMD_WRITE;
Midi->IOSer.io_Data = (APTR)buf;
Midi->IOSer.io_Length = len;
}
/****************************************************************************
* DoTheIO: General-purpose MIDI I/O routine. Quits on ^C.
****************************************************************************/
long DoTheIO(void)
{
int mask, temp;
long bytesDone = 0L;
mask = SIGBREAKF_CTRL_C | (1L << MidiPort->mp_SigBit);
SendIO((struct IORequest *)Midi);
while (1)
{
temp = Wait(mask);
if (temp & SIGBREAKF_CTRL_C)
{
bytesDone = CTRL_C_NO_BYTES;
break;
}
if (CheckIO((struct IORequest *)Midi))
{
WaitIO((struct IORequest *)Midi);
bytesDone = Midi->IOSer.io_Actual;
break;
}
}
AbortIO((struct IORequest *)Midi);
WaitIO((struct IORequest *)Midi);
return(bytesDone);
}
/****************************************************************************
* RequestOnePatch: Request a patch dump from an Oberheim synth.
***************************************************************************/
void RequestOnePatch(UBYTE patchNum, int mode)
{
static UBYTE request[7] = { SYSEX_BEGIN,
OBERHEIM_SYSEX_ID,
OBERHEIM_DEVICE_NUMBER,
DUMP_REQUEST,
FILL_IN_LATER,
FILL_IN_LATER,
SYSEX_END };
request[BYTE_PATCHTYPE] = (UBYTE)mode;
request[BYTE_PATCHNUMBER] = patchNum;
ResetSerialPort();
Midi->IOSer.io_Command = CMD_WRITE;
Midi->IOSer.io_Data = (APTR)request;
Midi->IOSer.io_Length = sizeof(request);
(void)DoTheIO();
}
/***************************************************************************
* Environment variable functions.
***************************************************************************/
/*
* Given the string "str", break it into the device name and unit number.
* Environment variable syntax is "DEVICENAME:UNITNUMBER".
* For example: "midi.device:2".
*
* "device" MUST preallocated.
*/
BOOL MakeSerialDeviceName(char *str, char *device, int *unit)
{
/*
* Copy "str" into the device name, until we reach a ':' or run out
* of data.
*/
while (str && *str && (*str != ':'))
*(device++) = *(str++);
/* Terminate the device name, so it is a valid string. */
*device = '\0';
/* If we did not reach a colon, complain and exit! */
if ((*str != ':') || *(str+1) == '\0')
{
ErrorMsg(ERROR_OBDEVICE);
return(FALSE);
}
/* Skip the colon. */
str++;
/*
* The remaining string data must represent a non-negative integer.
* If so, grab the data as the value of "unit".
* Otherwise, complain and exit!
*/
if (!AllDigits(str))
{
ErrorMsg(ERROR_OBUNIT);
return(FALSE);
}
else
*unit = atoi(str);
/* If we got here, everything is just groovy! */
return(TRUE);
}