[comp.sources.amiga] v90i019: chatterbox - play sounds when certain events occur, Part02/02

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (01/17/90)

Submitted-by: karl@sugar.hackercorp.com (Karl Lehenbauer)
Posting-number: Volume 90, Issue 019
Archive-name: audio/chatterbox/part02

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 2)."
# Contents:  8svx.c player.c tracker.c windows.c
# Wrapped by tadguy@xanth on Tue Jan 16 21:23:14 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f '8svx.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'8svx.c'\"
else
echo shar: Extracting \"'8svx.c'\" \(8137 characters\)
sed "s/^X//" >'8svx.c' <<'END_OF_FILE'
X/* quasi-minimal IFF 8SVX sample file loader for Karl's Audio Stuff
X * by Karl Lehenbauer, based originally on public domain IFF code from
X * Electronic Arts
X * rewritten 2/25/88 KEL to support chaining of samples through a
X * central sample store and to support music (it's now carrying
X * around octave and one-shot info)
X
X *
X * this version for the sound effect player has had the octave stuff
X * hacked back out but the central sample store is still there
X *
X */
X
X#include <exec/types.h>
X#include <functions.h>
X#include <exec/memory.h>
X#include <exec/nodes.h>
X#include <exec/lists.h>
X#include <stdio.h>
X#include <fcntl.h>
X#include "assert.h"
X
X#include "iff.h"
X#include "8svx.h"
X
X#include "sample.h"
X
Xstruct List SampleStore;
Xstruct List *SampleList = &SampleStore;
X
X/* this is a global variable that is set by Load8SVX to indicate whether
X * it found the sample in memory already or not.  When we're playing
X * sounds for the timer and noload is selected, it's a good thing to know
X * and we already return a value (bleah, C is a bit restrictive in this
X * case)
X */
Xint sample_was_in_cache;
X
Xchar *SamplePath = "ChatterBox:";
X
Xvoid UnloadAllSamples()
X{
X#ifdef DEBUG
X	fprintf(stderr,"UnloadAllSamples cleanup routine executing\n");
X#endif
X	while (SampleList->lh_TailPred != SampleList)
X	{
X		UnloadSampleAt(SampleList->lh_Head);
X	}
X#ifdef DEBUG
X	fprintf(stderr,"UnloadAllSamples cleanup routine complete\n");
X#endif
X}
X
X
XInit8SVX()
X{
X	NewList(SampleList);
X	add_cleanup(UnloadAllSamples);
X}
X
XSample *Load8SVX(fname)
Xchar *fname;
X{
X	int iffile;
X	ChunkHeader chunkhead;
X	Voice8Header voicehead;
X	LONG samplebytes, fibbytes;
X	LONG formtype;
X    char *sampbufp, *fibbufp;
X	register Sample *samptr;
X	LONG headsize;
X	short flags = 0;
X	char fnamebuf[256];
X
X	assert(sizeof(chunkhead) == 8);
X
X#ifndef NOAUDIT
X	if (SampleList->lh_Head == (struct Node *)NULL)
X		panic("called Load8SVX without calling Init8SVX\n");
X#endif
X
X#ifdef DEBUG
X	printf("checking sample store for %s - ",fname);
X#endif
X	if ((samptr = (Sample *)FindName(SampleList, fname)) != NULL)
X	{
X#ifdef DEBUG
X		printf("request for %s satisfied from sample store\n",fname);
X#endif
X		sample_was_in_cache = YES;
X		return(samptr);
X	}
X
X	sample_was_in_cache = NO;
X
X#ifdef DEBUG
X	printf("didn't find it\n");
X#endif
X
X	sprintf(fnamebuf,"%s%s",SamplePath,fname);
X#ifdef DEBUG
X	printf("looking for IFF file, name of %s\n",fnamebuf);
X	fflush(stdout);
X#endif
X	if ((iffile = OpenIFF(fnamebuf, ID_8SVX)) < 0)
X	{
X		fprintf(stderr,"Load8SVX: can't open IFF sample file %s\n",fnamebuf);
X		return((Sample *)NULL);
X	}
X
X	if ((headsize = chunkuntil(iffile,ID_VHDR)) == -1)
X	{
X		fputs("Load8SVX: IFF 8SVX VHDR chunk search failed\n",stderr);
X		return((Sample *)NULL);
X	}
X
X	if (!readchunk(iffile,&voicehead,headsize))
X	{
X		fputs("Load8SVX: read of IFF VHDR chunk failed\n",stderr);
X		return((Sample *)NULL);
X	}
X#ifdef DEBUG
X	DumpVoiceHead(&voicehead);
X#endif
X
X	if ((samplebytes = chunkuntil(iffile,ID_BODY)) < 0)
X	{
X		fputs("Load8SVX: IFF 8SVX BODY chunk search failed\n",stderr);
X		return((Sample *)NULL);
X	}
X
X	if (voicehead.sCompression == sCmpFibDelta)
X	{
X#ifdef DEBUG
X		fprintf(stderr,"Load8SVX: sample uses Fibonacci Delta Encoding\n");
X#endif
X		fibbytes = samplebytes;
X		samplebytes = (fibbytes - 2) * 2;
X	}
X
X    if ((sampbufp = (char *)AllocMem(samplebytes,MEMF_FAST)) == (char *)NULL)
X	{
X	    if ((sampbufp = (char *)AllocMem(samplebytes,MEMF_CHIP)) == (char *)NULL)
X		{
X			fputs("Load8SVX: unable to allocate memory for waveform\n",stderr);
X			return((Sample *)NULL);
X		}
X		else
X			flags = SAMPLE_ALLOCATED_IN_CHIP_RAM;
X
X	}
X	else
X		flags = SAMPLE_ALLOCATED_IN_FAST_RAM;
X
X	if (voicehead.sCompression == sCmpFibDelta)
X	{
X
X		/* load the delta compressed data into the back half of the sample
X		 * buffer just allocated.  We will decompress the data into the 
X		 * same sample memory, without overwriting the compressed data.
X		 * It'll work.  Trust me, I know what I'm doing.
X		 */
X
X		fibbufp = &sampbufp[samplebytes / 2];
X
X		if (!readchunk(iffile,fibbufp,fibbytes))
X		{
X			fputs("Read of fib sample data failed!\n",stderr);
X			FreeMem(sampbufp,samplebytes);
X			return((Sample *)NULL);
X		}
X		FibUnpack(fibbufp+2,fibbytes-2,sampbufp,fibbufp[1]);
X	}
X	else if (!readchunk(iffile,sampbufp,samplebytes))
X	{
X		fputs("Read of sample data failed!\n",stderr);
X		FreeMem(sampbufp,samplebytes);
X		return((Sample *)NULL);
X	}
X
X	close(iffile);
X
X	if ((samptr = (Sample *)AllocMem(sizeof(Sample),0L)) == (Sample *)NULL)
X	{
X	   fputs("Load8SVX: unable to allocate memory for Sample structure\n",stderr);
X	   FreeMem(sampbufp,samplebytes);
X	   return((Sample *)NULL);
X	}
X
X	/* allocate memory for sample name */
X	if ((samptr->node.ln_Name = (char *)AllocMem(strlen(fname) + 1,0)) == (char *)NULL)
X	{
X		fputs("Load8SVX: unable to allocate memory for Sample name\n",stderr);
X		FreeMem(sampbufp,samplebytes);
X		FreeMem(samptr,sizeof(Sample));
X		return((Sample *)NULL);
X	}
X
X	/* structure copy in Voice8Header info */
X	samptr->sampleheader = voicehead;
X
X	/* set up pointer to sample data and store length */
X	if (flags & SAMPLE_ALLOCATED_IN_FAST_RAM)
X	{
X		samptr->fastsampledata = sampbufp;
X		samptr->sampledata = NULL;
X	}
X	else if (flags & SAMPLE_ALLOCATED_IN_CHIP_RAM)
X	{
X		samptr->fastsampledata = NULL;
X		samptr->sampledata = sampbufp;
X	}
X	samptr->samplebytes = samplebytes;
X
X	/* copy in the voice name */
X	strcpy(samptr->node.ln_Name,fname);
X
X	/* ...and set up the flags */
X	samptr->sample_flags = flags;
X
X	/* set the number of current "users" of the sample in chip RAM to zero */
X	samptr->chip_use_count = 0;
X
X	/* initialize the rest of the node fields */
X	samptr->node.ln_Type = samptr->node.ln_Pri = 0;
X
X	/* stick this new sample onto the end of the sample list */
X	AddTail(SampleList,&samptr->node);
X
X#ifndef NOAUDIT
X	samptr->magic = SAMPLE_MAGIC;
X#endif
X
X#ifdef DEBUG
X	fprintf(stderr,"Load8SVX: waveform bytes %ld, samples/second %d\n",samplebytes,voicehead.samplesPerSec);
X	fprintf(stderr,"Load8SVX: samptr %lx, sampledata %lx\n",samptr,sampbufp);
X#endif
X	return(samptr);
X}
X
X/* FibUnpack - unpack Fibonacci Delta Compressed audio sample
X *				see IFF file formats in the ROM Kernel Exec manual
X *				or on one of the Fred Fish disks
X */
X
Xchar FibToDelta[16] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
X
XFibUnpack(inp,n,outp,val)
Xchar *inp, *outp;
Xlong n;
Xchar val;
X{
X	register char pair;
X#ifdef DEBUG
X	fprintf(stderr,"FibUnpack: inp %lx, n %ld, outp %lx, val %d\n",inp,n,outp,val);
X#endif
X	while (n--)
X	{
X		pair = *inp++;				/* get a pair of compressed samples */
X		val += FibToDelta[(pair >> 4) & 0xf]; /* uncompress first sample */
X		*outp++ = val;
X		val += FibToDelta[pair & 0xf];		/* uncompress second sample */
X		*outp++ = val;
X	}
X}
X
X/* unload sample at address */
XUnloadSampleAt(samptr)
XSample *samptr;
X{
X	ASSERT_SAMPLE_MAGIC(samptr);
X
X#ifdef DEBUG
X	printf("UnloadSampleAt: Unloading Sample %s\n",samptr->node.ln_Name);
X#endif
X
X	/* remove the sample from the sample list */
X	Remove(&samptr->node);
X
X	/* free the space allocated for the sample's name */
X	FreeMem(samptr->node.ln_Name,strlen(samptr->node.ln_Name)+1);
X
X	/* free the sample data itself */
X	if (samptr->sample_flags & SAMPLE_ALLOCATED_IN_CHIP_RAM)
X	{
X		FreeMem(samptr->sampledata,samptr->samplebytes);
X	}
X	else
X	{
X		assert(samptr->sample_flags & SAMPLE_ALLOCATED_IN_FAST_RAM);
X		FreeMem(samptr->fastsampledata,samptr->samplebytes);
X	}
X#ifndef NOAUDIT
X	samptr->magic = 0;
X#endif
X	samptr->sample_flags = 0;
X
X	/* free the sample structure */
X	FreeMem(samptr,sizeof(Sample));
X}
X
XUnloadSample(name)
Xchar *name;
X{
X	Sample *samptr;
X
X#ifdef DEBUG
X	printf("UnloadSample(%s)\n",name);
X#endif
X	
X	if ((samptr = (Sample *)FindName(SampleList,name)) != NULL)
X		UnloadSampleAt(samptr);
X	else
X		fprintf(stderr,"couldn't find sample %s to unload it\n",name);
X}
X
X#ifdef DEBUG
XDumpVoiceHead(vptr)
XVoice8Header *vptr;
X{
X	printf("oneShotHiSamples %d, repeatHiSamples %d\n",
X		vptr->oneShotHiSamples, vptr->repeatHiSamples);
X	printf("samplesPerHiCycle %ld, samplesPerSec %d\n",
X		vptr->samplesPerHiCycle, vptr->samplesPerSec);
X	printf("ctOctave %d, sCompression %d, volume %d\n",
X		vptr->ctOctave, vptr->sCompression, vptr->volume);
X}
X#endif
X
X/* end of 8svx.c */
END_OF_FILE
if test 8137 -ne `wc -c <'8svx.c'`; then
    echo shar: \"'8svx.c'\" unpacked with wrong size!
fi
# end of '8svx.c'
fi
if test -f 'player.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'player.c'\"
else
echo shar: Extracting \"'player.c'\" \(12352 characters\)
sed "s/^X//" >'player.c' <<'END_OF_FILE'
X/* player - sound playing portion of karl's smus player */
X/* hacked to be an effects player */
X
X
X/* note - "channels", throughout the code below, are a structure I have
X * invented, a logical channel sort of thing that is useful for what
X * I'm trying to do.  There is not a 1-1 correspondence between these
X * channels and the hardware channels, which hardware channel is used
X * for a given channel is determined by audio.device when we make a
X * request to allocate a channel.
X */
X
X#include <exec/types.h>
X#include <functions.h>
X#include <exec/memory.h>
X#include <devices/audio.h>
X#include <stdio.h>
X
X#include "assert.h"
X#include "8svx.h"
X
X#include "sample.h"
X#include "channels.h"
X
X#define YES 1
X#define NO 0
X
Xshort audio_up = NO, audio_down = NO;
X
Xextern int debug;
X
X#ifdef DEBUG
X#define WHERE fprintf(stderr,"%s %s %d\n",__FILE__,__FUNC__,__LINE__); fflush(stderr);
X#define WHAT(x) fprintf(stderr,"%s %s %d %s\n",__FILE__,__FUNC__,__LINE__,x->name);
X#else
X#define WHERE
X#define WHAT(x)
X#endif
X
X#define CLOCKFREQ 3579545
X
X/* define the channel array - this is the top level of data for an audio
X channel */
XChannel Channels[MAX_CHANNELS];
X
Xstruct Device *AudioDevice;
Xstruct MsgPort *sfx_port;
Xstruct SMUS_IOAudio *openIOB;
X
Xshort MasterVolume = 127;
X
X/* allocation maps for requesting channel assignments from audio.device:
X * I use LeftMap and RightMap to insist on a stereo side - if it can't
X * allocate (at play time) that side it will blow off the note.
X * I use TryLeftMap and TryRightMap to indicate a preference for a
X * stereo side, but if I can't have a channel on that side, it'll
X * give me one from the other side if one is available there
X */
Xstatic UBYTE LeftMap[] = {LEFT0, LEFT1};
Xstatic UBYTE RightMap[] = {RIGHT0, RIGHT1};
Xstatic UBYTE TryLeftMap[] = {LEFT1, LEFT0, RIGHT1, RIGHT0};
Xstatic UBYTE TryRightMap[] = {RIGHT1, RIGHT0, LEFT1, LEFT0};
X
X/* SMUS_IOBallocate - allocates a SMUS player IOB
X * It shouldn't panic when the allocate fails, and will be eventually
X * made to back out properly.
X * Not much to the routine at all...
X */
Xstruct SMUS_IOAudio *SMUS_IOBallocate()
X{
X	struct SMUS_IOAudio *IOB;
X	extern UBYTE *MyAllocMem();
X
X	if ((IOB = (struct SMUS_IOAudio *)MyAllocMem(sizeof(struct SMUS_IOAudio), (long)MEMF_PUBLIC | MEMF_CLEAR)) == (struct SMUS_IOAudio *) NULL)
X		panic("SMUS_IOBallocate failed"); 
X
X	return(IOB);
X}
X
X/* free an IOB created by SMUS_IOBallocate */
XSMUS_IOBfree(IOBp)
Xstruct SMUS_IOAudio *IOBp;
X{
X	if (IOBp != NULL)
X		FreeMem(IOBp, sizeof(struct SMUS_IOAudio));
X}
X
X/* Init the IOB for the oneshot portion of the sound */
XSMUS_InitShotIOB(channel)
Xint channel;
X{
X	struct SMUS_IOAudio *IOB = Channels[channel].IOBs[ONESHOT_IOB];
X
X	IOB->smusIOB.ioa_Request.io_Command = CMD_WRITE;
X	IOB->smusIOB.ioa_Request.io_Flags = ADIOF_PERVOL;
X
X	/* NEEDS WORK - needs to dynamically set volume based on volume
X	 * commands we receive from the track, and the overall volume
X	 * from the song structure */
X	IOB->smusIOB.ioa_Volume = 127;
X
X	/* cycles to repeat is 1, this is a oneshot sound */
X	IOB->smusIOB.ioa_Cycles = 1;
X}
X
X/* Init an IOB that will stop the playing sound */
XSMUS_InitStopIOB(channel)
Xint channel;
X{
X	struct SMUS_IOAudio *IOB = Channels[channel].IOBs[STOP_IOB];
X
X	/* I switched from ADCMD_FINISH to CMD_FLUSH because I
X	 * can have up to three things queued on a channel
X	 * and I want to kill them all - ADCMD_FINISH would only
X	 * kill the one in progress
X	 * IOB->smusIOB.ioa_Request.io_Command = ADCMD_FINISH;
X	 */
X	IOB->smusIOB.ioa_Request.io_Command = CMD_FLUSH;
X	IOB->smusIOB.ioa_Request.io_Flags = IOF_QUICK;
X}
X
X
X/* Init an IOB that will allocate a channel */
XSMUS_InitAllocIOB(channel)
Xint channel;
X{
X	struct SMUS_IOAudio *allocIOB = Channels[channel].IOBs[ALLOC_IOB];
X
X	static BYTE attack_precedences[] = {50, 40, 30, 20};
X
X	allocIOB->smusIOB.ioa_Request.io_Command = ADCMD_ALLOCATE;
X
X	allocIOB->smusIOB.ioa_Request.io_Message.mn_Node.ln_Pri = attack_precedences[channel];
X
X	/* The IFF SMUS spec says priority is to be highest for track 1 
X	 * and descending with progressively higher tracks.
X	 *
X	 * The audio.device doc in the ROM Kernel Manual says that
X	 * higher priorities should be given for the attack portions
X	 * of each note and that priorities for notes in a music
X	 * program range from -50 (lowest) to 50 (highest)
X	 *
X	 * Consequently, since I'm orienting it toward four tracks on the
X	 * Amiga, and this code is totally Amiga dependent anyway, I
X	 * am assigning attack priorities of 50 for the first track, and
X	 * each successive track minus 10, with the sustain portion of
X	 * the note having its precedence lowered effectively by 50
X	 *
X	 */
X
X	/* for now, channel 1 and 3 prefer the left channel, while 2 and 4
X	 * prefer the right
X	 */
X	allocIOB->smusIOB.ioa_Data = (channel) ? TryLeftMap : TryRightMap;
X	allocIOB->smusIOB.ioa_Length = 4;
X
X	allocIOB->smusIOB.ioa_Request.io_Flags = (ADIOF_NOWAIT | IOF_QUICK);
X}
X
X/* Init an IOB that will deallocate the channel */
XSMUS_InitDeallocIOB(channel)
Xint channel;
X{
X	struct SMUS_IOAudio *IOB = Channels[channel].IOBs[FREE_IOB];
X
X	IOB->smusIOB.ioa_Request.io_Command = ADCMD_FREE;
X	IOB->smusIOB.ioa_Request.io_Flags = IOF_QUICK;
X}
X
X/* init a channel
X *
X * this guy takes care of allocating and initting all the different IOBs 
X */
XInitChannel(channelindex)
Xint channelindex;
X{
X	int i;
X	struct SMUS_IOAudio *IOB;
X	Channel *channelp = &Channels[channelindex];
X
X	/* for all the IOBs,
X	 *   allocate the IOB and set the channel's IOB pointer to it
X	 *   set the channel pointer field that I tack onto the end
X	 *     of IOBs to point back to the channel (so that we can 
X	 *     tell to what channel an IOB we receive on a message 
X	 *     port belongs, if we need to)
X	 */
X	for (i = 0; i < MAX_CHANNEL_IOBS; i++)
X	{
X		IOB = channelp->IOBs[i] = SMUS_IOBallocate();
X
X		IOB->channelp = channelp;	/* set pointer to IOB's Channel parent */
X
X		/* set replyport and device */
X		/* see someday if having the reply port is really neccessary */
X		IOB->smusIOB.ioa_Request.io_Message.mn_ReplyPort = sfx_port;
X
X		/* set the device in the request to the audio device */
X		IOB->smusIOB.ioa_Request.io_Device = AudioDevice;
X
X		/* let audio.device assign the alloc keys first time through */
X		IOB->smusIOB.ioa_AllocKey = 0;
X	}
X
X	/* initialize the different kinds of IOBs we use */
X	SMUS_InitShotIOB(channelindex);
X	SMUS_InitStopIOB(channelindex);
X	SMUS_InitAllocIOB(channelindex);
X	SMUS_InitDeallocIOB(channelindex);
X
X	channelp->samptr = NULL;
X}
X
XInitAudio()
X{
X	int EndAudio();
X	int i;
X
X	openIOB = NULL;
X	AudioDevice = NULL;
X
X	add_cleanup(EndAudio);
X
X	openIOB = SMUS_IOBallocate();
X
X	if (OpenDevice(AUDIONAME, 0, &openIOB->smusIOB, 0) != 0)
X		panic("can't open audio device");
X
X	AudioDevice = openIOB->smusIOB.ioa_Request.io_Device;
X
X	if ((sfx_port = CreatePort((char *)NULL, 0)) == (struct MsgPort *)NULL)
X		panic("can't create sfx_port");
X
X	for (i = 0; i < MAX_CHANNELS; i++)
X		InitChannel(i);
X
X	audio_up = YES;
X}
X
XEndAudio()
X{
X	int i, j;
X	Channel *channelp;
X
X#ifdef DEBUG
X	fprintf(stderr,"endaudio cleanup routine executing\n");
X#endif
X	if(audio_down)
X		return;
X	audio_down = YES;
X
X	if (audio_up)
X	{
X		for (i = 0; i < MAX_CHANNELS; i++)
X			StopChannelNote(&Channels[i]);
X	}
X	audio_up = NO;
X
X	if (sfx_port)
X		DeletePort(sfx_port,sizeof(struct MsgPort));
X
X	for (i = 0; i < MAX_CHANNELS; i++)
X	{
X		channelp = &Channels[i];
X		for (j = 0; j < MAX_CHANNEL_IOBS; j++) 
X		{
X			SMUS_IOBfree(channelp->IOBs[j]);
X			channelp->IOBs[j] = NULL;
X		}
X	}
X	if(openIOB) 
X	{
X		if(AudioDevice) 
X		{
X			CloseDevice(openIOB);
X			AudioDevice = NULL;
X		}
X		SMUS_IOBfree(openIOB);
X		openIOB = NULL;
X	}
X#ifdef DEBUG
X	fprintf(stderr,"endaudio cleanup routine complete\n");
X#endif
X}
X
X/* the guts of note playing, right here */
X
XPlayChannelSample(samptr,velocity,stereo_side)
XSample *samptr;
Xint velocity;
Xint stereo_side;
X{
X	int i;
X	struct SMUS_IOAudio *iobptr;
X	Channel *channelp;
X	struct OctaveStruct *octave_ptr;
X	int octave, noctaves;
X	short shift_up_n_octaves = 0;
X	short shift_down_n_octaves = 0;
X	short period;
X	short volume;
X	int channel = -1;
X	struct SMUS_IOAudio *allocIOB;
X	struct SMUS_IOAudio *shotIOB;
X
X	/* make relatively certain samptr points to a good sample */
X	ASSERT_SAMPLE_MAGIC(samptr);
X
X	/* gimme one of my logical channels */
X	for (channel = 0; channel < 4; channel++)
X	{
X		channelp = &Channels[channel];
X		if (!(channelp->flags & (LOOP_PLAYING | SHOT_PLAYING)))
X			goto got_channel;
X	}
X
X#ifdef DEBUG
X		printf("failed to get a channel, they're all in use\n");
X#endif
X	return;
X
X	got_channel:
X	/* cons up some convenient pointers */
X	/* these assignments could be moved to where they're needed to prevent
X	 * their being assigned but unused because of alloc failure,
X	 * no need for oneshot, etc. */
X	allocIOB = channelp->IOBs[ALLOC_IOB];
X	shotIOB = channelp->IOBs[ONESHOT_IOB];
X
X
X	/* zero the alloc key so we'll get a fresh one - it's the only way
X	 * to be sure we won't conflict with someone else */
X	/* allocIOB->smusIOB.ioa_AllocKey = 0; */
X	/* I think we're OK if we alloc it once */
X	allocIOB->smusIOB.ioa_Data = (stereo_side) ? TryLeftMap : TryRightMap;
X	BeginIO(&allocIOB->smusIOB);
X
X	/* the only possible error return is ADIOERR_NOALLOCATION */
X	if (allocIOB->smusIOB.ioa_Request.io_Error)
X	{
X		fprintf(stderr,"alloc failed on channel %d\n",channel);
X		return;
X	}
X#ifdef DEBUG
X	fprintf(stderr,"channel %d allockey %d\n",channel,allocIOB->smusIOB.ioa_AllocKey);
X#endif
X
X	channelp->samptr = samptr;
X
X	/* copy the Unit and AllocKey into the other IOBs 
X	 * This is not the coolest way to go.
X	 * It doesn't need to copy it to all of them.
X	 * Perhaps it should only copy it into the channel and
X	 * the other routines would get it out of the channel and
X	 * shove it into the IOB - I don't know, maybe later
X	 * also, AllocKey need only be propogated once
X	 */
X	for (i = 0; i < MAX_CHANNEL_IOBS; i++)
X	{
X		iobptr = Channels[channel].IOBs[i];
X		iobptr->smusIOB.ioa_Request.io_Unit = allocIOB->smusIOB.ioa_Request.io_Unit;
X		iobptr->smusIOB.ioa_AllocKey = allocIOB->smusIOB.ioa_AllocKey;
X	}
X
X
X	assert(samptr->sampleheader.samplesPerSec != 0);
X	shotIOB->smusIOB.ioa_Period = (CLOCKFREQ / samptr->sampleheader.samplesPerSec);
X
X	if (make_sample_chip(samptr))
X	{
X		shotIOB->smusIOB.ioa_Data = (UBYTE *)samptr->sampledata;
X		shotIOB->smusIOB.ioa_Length = (ULONG)samptr->samplebytes;
X		shotIOB->smusIOB.ioa_Volume = 64;
X		shotIOB->smusIOB.ioa_Cycles = 1;
X
X		BeginIO(&shotIOB->smusIOB);
X		/* possible errors are IOERR_ABORTED and ADIOERR_NOALLOCATION */
X		if (shotIOB->smusIOB.ioa_Request.io_Error)
X			return;
X		channelp->flags |= SHOT_PLAYING;
X#ifdef DEBUG
X		fprintf(stderr,"queued shot on channel %d\n",channel);
X#endif
X	}
X	else
X	{
X		fprintf(stderr,"chatterbox: chip RAM allocation failed\n");
X	}
X}
X
X/* stop playing the channel if it's playing (we may not have been able to
X * allocate a channel you know) and deallocate it 
X */
X/* memo to self:  you should always stop all notes that stop in a 
X * certain time interval prior to starting any new ones 
X */
XStopChannelNote(channelp)
XChannel *channelp;
X{
X
X	struct SMUS_IOAudio *stopIOB = channelp->IOBs[STOP_IOB];
X	struct SMUS_IOAudio *freeIOB= channelp->IOBs[FREE_IOB];
X
X	if (channelp->flags & (LOOP_PLAYING | SHOT_PLAYING))
X	{
X		BeginIO(&stopIOB->smusIOB);
X		/* only error return is ADIOERR_NOALLOCATION */
X
X		if (channelp->flags & SHOT_PLAYING)
X		{
X#ifdef DEBUG
X			fprintf(stderr,"SHOT playing\n");
X#endif
X			WaitIO(&channelp->IOBs[ONESHOT_IOB]->smusIOB);
X		}
X		if (channelp->flags & LOOP_PLAYING)
X		{
X#ifdef DEBUG
X			fprintf(stderr,"LOOP wait\n");
X#endif
X			WaitIO(&channelp->IOBs[LOOP_IOB]->smusIOB);
X		/* error returns can be IOERR_ABORTED and ADIOERR_NOALLOCATION */
X		}
X
X		/* there's no point in waiting on precedence, it's synchronous */
X		channelp->flags &= ~(SHOT_PLAYING | LOOP_PLAYING);
X
X#ifdef DEBUG
X	fprintf(stderr,"free channel %d, alloc key %d\n",channel,freeIOB->smusIOB.ioa_AllocKey);
X#endif
X		BeginIO(&freeIOB->smusIOB);
X		/* only possible error return is ADIOERR_NOALLOCATION */
X#ifndef NOAUDIT
X		if (freeIOB->smusIOB.ioa_Request.io_Error)
X			fprintf(stderr,"dealloc i/o error\n");
X#endif
X
X		free_sample_chip(channelp->samptr);
X	}
X}
X/* I have forgone magic numbers on channel structures because of the static
X * nature of the channels and their small number (4)
X */
Xstruct SMUS_IOAudio *SMUS_GetMsg()
X{
X	return((struct SMUS_IOAudio *)GetMsg(sfx_port));
X}
X
X/* end of player.c */
END_OF_FILE
if test 12352 -ne `wc -c <'player.c'`; then
    echo shar: \"'player.c'\" unpacked with wrong size!
fi
# end of 'player.c'
fi
if test -f 'tracker.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tracker.c'\"
else
echo shar: Extracting \"'tracker.c'\" \(9277 characters\)
sed "s/^X//" >'tracker.c' <<'END_OF_FILE'
X/* tracking memory allocator */
X
X#ifdef TRACKER
X
X#include <exec/types.h>
X#include <exec/memory.h>
X#include <functions.h>
X#include <stdio.h>
X
X/* comment out the following line if you want locks freed twice reported
X * at the cost of getting spurious resource error messages when
X * reusing the lock */
X/* #define FORGET_LOCKS_WHEN_UNLOCKED */
X
X/* comment out the following line if you want memory freed twice reported
X * at the cost of getting spurious resource error messages when
X * freeing and reallocating memory */
X/* #define FORGET_MEMORY_WHEN_FREED */
X
X/* make sure our invocations of the real routines on behalf of the user
X   don't cause us to recurse */
X
X#ifdef AllocMem
X#undef AllocMem
X#undef FreeMem
X#undef AllocSignal
X#undef FreeSignal
X#undef Lock
X#undef UnLock
X#undef DupLock
X#endif
X
X/* my flags */
X#define FREED_IT 1
X
Xstruct TrackingAllocMemData
X{
X	UBYTE *where;			/* address returned by allocator */
X	long amount;			/* number of bytes allocated */
X	long alloc_flags;		/* flags passed to allocator */
X	char *file;				/* filename of caller from the macro */
X	int line;				/* line number of caller from macro */
X	long my_flags;			/* flags internal to tracker */
X	struct TrackingAllocMemData *next;	/* pointer to next entry */
X};
X
Xstruct TrackingAllocMemData *TrackingAllocMemList = NULL;
Xlong MemAllocCount = 0, MemFreeCount = 0;
X
Xvoid *TrackingAllocMem(amount,flags,file,line)
Xlong amount;
Xlong flags;
Xchar *file;
Xint line;
X{
X	register struct TrackingAllocMemData *rp;
X	UBYTE *users_memory;
X
X	/* perform the actual alloc */
X	users_memory = AllocMem(amount,flags);
X
X	/* if it succeeded, record tracking info */
X	if (users_memory)
X	{
X		MemAllocCount++;
X
X		if ((rp = AllocMem((long)sizeof(struct TrackingAllocMemData),0L)) == NULL)
X			panic("tracker: can't alloc memory to record AllocMem data");
X
X		/* add new alloc data entry to linked list */
X		rp->next = TrackingAllocMemList;
X		TrackingAllocMemList = rp;
X
X		/* shove in save values */
X		rp->amount = amount;
X		rp->alloc_flags = flags;
X		rp->where = users_memory;
X		rp->file = file;
X		rp->line = line;
X		rp->my_flags = 0;
X	}
X	/* return pointer to the space allocated */
X	return(users_memory);
X}
X
Xvoid TrackingFreeMem(where,amount,file,line)
XUBYTE *where;
Xlong amount;
Xchar *file;
Xint line;
X{
X	register struct TrackingAllocMemData *rp, *op, *freep;
X
X	MemFreeCount++;
X	/* scan the memory tracking list for a match */
X	for (rp = TrackingAllocMemList, op = NULL; rp != NULL; op = rp, rp = rp->next)
X	{
X		/* if we matched the address */
X		if (rp->where == where)
X		{
X			/* if they got the amount wrong, tell them */
X			if (rp->amount != amount)
X			{
X				fprintf(stderr,"freed addr %lx OK but length differs, talloc'ed %ld, freed %ld,\n\tallocated at file %s line %d, freed at file %s line %d\n",
X				where,rp->amount,amount,rp->file,rp->line,file,line);
X			}
X#ifndef FORGET_MEMORY_WHEN_FREED
X			/* if it's already free, tell them they freed twice */
X			if (rp->my_flags & FREED_IT)
X			{
X				fprintf(stderr,"freed memory twice at %lx, amount %ld,\n\tallocated in file %s at line %d, freed in file %s at line %d\n",where,amount,rp->file,rp->line,file,line);
X				return;
X			}
X			else
X			{
X				/* mark this entry as free */
X				rp->my_flags |= FREED_IT;
X			}
X#else
X			/* remove entry from linked list and free it */
X			if (op != NULL) op->next = rp->next;
X			else
X				TrackingAllocMemList = rp->next;
X			freep = rp;
X			rp = rp->next;
X			FreeMem(freep,(long)sizeof(struct TrackingAllocMemData));
X#endif
X			FreeMem(where,amount);
X
X			return;
X		}
X	}
X	fprintf(stderr,"Freed memory at %lx of amount %ld that wasn't allocated,\n\tfreed at file %s line %d\n",where,amount,file,line);
X	FreeMem(where,amount);
X}
X
Xvoid ReportUnfreedMemory()
X{
X	struct TrackingAllocMemData *rp = TrackingAllocMemList, *freep;
X
X	while (rp != NULL)
X	{
X		if (!(rp->my_flags & FREED_IT))
X		{
X			fprintf(stderr,"FreeMem was never called for memory at %lx, amount %ld,\n\tthe alloc was performed at file %s line %d\n",rp->where,rp->amount,rp->file,rp->line);
X		}
X		freep = rp;
X		rp = rp->next;
X		FreeMem(freep,(long)sizeof(struct TrackingAllocMemData));
X	}
X	printf("Total tracked AllocMem calls %ld, FreeMem calls %ld\n",MemAllocCount,MemFreeCount);
X}
X
X
X/* track signals */
X/* tracking AllocSignal doesn't currently track where it was called from */
X
Xlong TrackingSignalMask = 0;
Xlong SignalAllocCount = 0, SignalFreeCount = 0;
X
Xlong TrackingAllocSignal(signal_num,file,line)
Xlong signal_num;
Xchar *file;
Xint line;
X{
X	SignalAllocCount++;
X
X	signal_num = AllocSignal(signal_num);
X
X	if (signal_num != -1)
X		TrackingSignalMask |= (1 << signal_num);
X
X	return(signal_num);
X}
X
Xvoid TrackingFreeSignal(signal_num,file,line)
Xlong signal_num;
Xchar *file;
Xint line;
X{
X	SignalFreeCount++;
X
X	if (!(TrackingSignalMask & (1 << signal_num)))
X	{
X		fprintf("freed a signal (%ld) that was never allocated, at file %s line %d\n",
X			signal_num,file,line);
X		TrackingSignalMask &= ~(1 << signal_num);
X	}
X}
X
Xvoid ReportUnfreedSignals()
X{
X	if (TrackingSignalMask)
X		fprintf("failed to free signals indicated by this mask: %8lx\n",
X			TrackingSignalMask);
X	printf("Total tracked AllocSignal calls %ld, FreeSignal calls %ld\n",SignalAllocCount,SignalFreeCount);
X}
X
X/* tracking lock and unlock */
X
Xstruct TrackingLockData
X{
X	struct FileLock *lock;	/* lock returned by Lock */
X	char *name;				/* name of file that was locked */
X	long accessMode;		/* access mode of the file that was locked */
X	char *file;				/* ptr to file name of line of caller */
X	int line;				/* ptr to line number text of locker */
X	long my_flags;			/* flags internal to tracker */
X	struct TrackingLockData *next;	/* pointer to next entry */
X};
X
X/* flags */
X#define CREATED_BY_DUPLOCK 1
X
Xstruct TrackingLockData *TrackingLockList = NULL;
Xlong TrackerLockCount = 0, TrackerUnLockCount = 0;
X
Xstruct FileLock *TrackingLock(name, accessMode, file, line)
Xchar *name;
Xlong accessMode;
Xchar *file;
Xint line;
X{
X	register struct TrackingLockData *lp;
X	struct FileLock *users_lock;
X
X	users_lock = Lock(name, (long)accessMode);
X
X	if (users_lock)
X	{
X		TrackerLockCount++;
X
X		if ((lp = AllocMem((long)sizeof(struct TrackingLockData),0L)) == NULL)
X			panic("tracker: can't alloc memory to record lock data");
X
X		/* add new alloc data entry to linked list */
X		lp->next = TrackingLockList;
X		TrackingLockList = lp;
X
X		/* shove in save values */
X		lp->accessMode = accessMode;
X		lp->file = file;
X		lp->line = line;
X		lp->my_flags = 0;
X		lp->lock = users_lock;
X
X		/* alloc space for filename and save */
X		if ((lp->name = AllocMem((long)(strlen(name)+1),0L)) == NULL)
X			panic("tracker: can't alloc memory to record lock filename");
X		strcpy(lp->name,name);
X	}
X	return(users_lock);
X}
X
Xstruct FileLock *TrackingDupLock(lock, file, line)
Xstruct FileLock *lock;
Xchar *file;
Xint line;
X{
X	register struct TrackingLockData *lp;
X	struct FileLock *users_lock;
X
X	users_lock = DupLock(lock);
X
X	if (users_lock)
X	{
X		TrackerLockCount++;
X
X		if ((lp = AllocMem((long)sizeof(struct TrackingLockData),0L)) == NULL)
X			panic("tracker: can't alloc memory to record lock data");
X
X		/* add new alloc data entry to linked list */
X		lp->next = TrackingLockList;
X		TrackingLockList = lp;
X
X		lp->file = file;
X		lp->line = line;
X		lp->name = NULL;
X		lp->lock = users_lock;
X		lp->my_flags = CREATED_BY_DUPLOCK;			
X	}
X	return(users_lock);
X}
X
Xvoid TrackingUnLock(lock,file,line)
Xstruct FileLock *lock;
Xchar *file;
Xint line;
X{
X	register struct TrackingLockData *lp, *op, *freep;
X
X	TrackerUnLockCount++;
X
X	/* scan the lock tracking list for a match */
X	for (lp = TrackingLockList, op = NULL; lp != NULL; op = lp, lp = lp->next)
X	{
X		/* if we matched the lock */
X		if (lp->lock == lock)
X		{
X#ifndef FORGET_LOCKS_WHEN_UNLOCKED
X			/* if it's already free, tell them they freed twice */
X			if (lp->my_flags & FREED_IT)
X			{
X				fprintf(stderr,"freed lock twice, lock %lx, filename %s\n\tlocked at file %s line %d, freed at file %s line %d\n",lock,lp->name,lp->file,lp->line,file,line);
X				return;
X			}
X			else
X			{
X				/* mark this entry as free */
X				lp->my_flags |= FREED_IT;
X			}
X#else
X			if (op != NULL) op->next = lp->next;
X			else TrackingLockList = lp->next;
X			freep = lp;
X			lp = lp->next;
X			if (lp->name != NULL)
X				FreeMem(lp->name,(long)(strlen(lp->name)+1));
X			FreeMem(freep,(long)(sizeof(struct TrackingLockData)));
X#endif
X			UnLock(lock);
X			return;
X		}
X	}
X	fprintf(stderr,"Freed lock %lx that hadn't been allocated at file %s line %d\n",lock,file,line);
X}
X
XReportUnfreedLocks()
X{
X	struct TrackingLockData *lp = TrackingLockList, *freep;
X
X	while (lp != NULL)
X	{
X		if (!(lp->my_flags & FREED_IT))
X		{
X			if (lp->my_flags & CREATED_BY_DUPLOCK)
X			{
X				fprintf(stderr,"UnLock was never called for lock %lx,\n\It was created by DupLock at file %s line %d\n",lp->lock,lp->file,lp->line);
X			}
X			else
X			{
X				fprintf(stderr,"UnLock was never called for lock %lx,\n\It was created by a Lock of %s\nat file %s line %d\n",lp->lock,lp->name,lp->file,lp->line);
X			}
X		}
X		if (lp->name != NULL)
X			FreeMem(lp->name,(long)(strlen(lp->name)+1));
X		freep = lp;
X		lp = lp->next;
X		FreeMem(freep,(long)sizeof(struct TrackingLockData));
X	}
X	printf("Total tracked Lock and DupLock calls %ld, UnLock calls %ld\n",TrackerLockCount,TrackerUnLockCount);
X}
X
XTrackerExitReport()
X{
X	ReportUnfreedMemory();
X	ReportUnfreedLocks();
X	ReportUnfreedSignals();
X}
X
X#endif
END_OF_FILE
if test 9277 -ne `wc -c <'tracker.c'`; then
    echo shar: \"'tracker.c'\" unpacked with wrong size!
fi
# end of 'tracker.c'
fi
if test -f 'windows.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'windows.c'\"
else
echo shar: Extracting \"'windows.c'\" \(12546 characters\)
sed "s/^X//" >'windows.c' <<'END_OF_FILE'
X
Xstruct IntuiText XIText1 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"Quit",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XMenuItem3 = {
X	NULL,	/* next MenuItem structure */
X	0,18,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	112,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText1,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* SubItem list */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText2 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"arranging services, and pro sampling.",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XSubItem5 = {
X	NULL,	/* next SubItem structure */
X	97,24,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	416,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText2,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* no SubItem list for SubItems */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText3 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"(including SMUS and MIDI players), composition and",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XSubItem4 = {
X	&XSubItem5,	/* next SubItem structure */
X	97,16,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	416,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText3,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* no SubItem list for SubItems */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText4 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"Contact me for innovative, licensable audio software",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XSubItem3 = {
X	&XSubItem4,	/* next SubItem structure */
X	97,8,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	416,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText4,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* no SubItem list for SubItems */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText5 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XSubItem2 = {
X	&XSubItem3,	/* next SubItem structure */
X	97,0,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	416,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText5,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* no SubItem list for SubItems */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText6 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"Freely redistributable for noncommercial purposes.",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XSubItem1 = {
X	&XSubItem2,	/* next SubItem structure */
X	97,-8,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	416,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText6,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* no SubItem list for SubItems */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText7 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"Redistribution",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XMenuItem2 = {
X	&XMenuItem3,	/* next MenuItem structure */
X	0,9,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	112,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText7,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	&XSubItem1,	/* SubItem list */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText8 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"Internet: karl@sugar.hackercorp.com",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XSubItem11 = {
X	NULL,	/* next SubItem structure */
X	97,32,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	280,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText8,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* no SubItem list for SubItems */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText9 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"Usenet: uunet!sugar!karl",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XSubItem10 = {
X	&XSubItem11,	/* next SubItem structure */
X	97,24,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	280,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText9,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* no SubItem list for SubItems */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText10 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"Missouri City, TX  77459",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XSubItem9 = {
X	&XSubItem10,	/* next SubItem structure */
X	97,16,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	280,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText10,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* no SubItem list for SubItems */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText11 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"3918 Panorama",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XSubItem8 = {
X	&XSubItem9,	/* next SubItem structure */
X	97,8,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	280,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText11,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* no SubItem list for SubItems */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText12 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"by Karl Lehenbauer, Hackercorp",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XSubItem7 = {
X	&XSubItem8,	/* next SubItem structure */
X	97,0,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	280,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText12,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* no SubItem list for SubItems */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText13 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"Chatterbox - v0.1",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XSubItem6 = {
X	&XSubItem7,	/* next SubItem structure */
X	97,-8,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	280,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText13,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	NULL,	/* no SubItem list for SubItems */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct IntuiText XIText14 = {
X	3,1,COMPLEMENT,	/* front and back text pens, drawmode and fill byte */
X	0,0,	/* XY origin relative to container TopLeft */
X	NULL,	/* font pointer or NULL for default */
X	(UBYTE *)"About",	/* pointer to text */
X	NULL	/* next IntuiText structure */
X};
X
Xstruct MenuItem XMenuItem1 = {
X	&XMenuItem2,	/* next MenuItem structure */
X	0,0,	/* XY of Item hitbox relative to TopLeft of parent hitbox */
X	112,8,	/* hit box width and height */
X	ITEMTEXT+ITEMENABLED+HIGHCOMP,	/* Item flags */
X	0,	/* each bit mutually-excludes a same-level Item */
X	(APTR)&XIText14,	/* Item render  (IntuiText or Image or NULL) */
X	NULL,	/* Select render */
X	NULL,	/* alternate command-key */
X	&XSubItem6,	/* SubItem list */
X	MENUNULL	/* filled in by Intuition for drag selections */
X};
X
Xstruct Menu XMenu1 = {
X	NULL,	/* next Menu structure */
X	0,0,	/* XY origin of Menu hit box relative to screen TopLeft */
X	75,0,	/* Menu hit box width and height */
X	MENUENABLED,	/* Menu flags */
X	"Project",	/* text of Menu name */
X	&XMenuItem1	/* MenuItem linked list pointer */
X};
X
X#define XMenuList1 XMenu1
X
Xstruct NewWindow XNewWindowStructure1 = {
X	355,22,	/* window XY origin relative to TopLeft of screen */
X	165,10,	/* window width and height */
X	0,1,	/* detail and block pens */
X	MENUPICK+CLOSEWINDOW+NEWPREFS+DISKINSERTED+DISKREMOVED+ACTIVEWINDOW+INACTIVEWINDOW,	/* IDCMP flags */
X	WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE,	/* other window flags */
X	NULL,	/* first gadget in gadget list */
X	NULL,	/* custom CHECKMARK imagery */
X	(UBYTE *)"Chatterbox",	/* window title */
X	NULL,	/* custom screen pointer */
X	NULL,	/* custom bitmap */
X	5,5,	/* minimum width and height */
X	640,200,	/* maximum width and height */
X	WBENCHSCREEN	/* destination screen type */
X};
X
X
Xvoid HandleEvent(object)
XAPTR object;
X{
X  if (object == (APTR)&XMenuItem3) { Quit(object); return; }
X}
X#define HANDLEEVENT HandleEvent
X
X/* end of PowerWindows source generation */
END_OF_FILE
if test 12546 -ne `wc -c <'windows.c'`; then
    echo shar: \"'windows.c'\" unpacked with wrong size!
fi
# end of 'windows.c'
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
	amiga@cs.odu.edu	
or	amiga@xanth.cs.odu.edu	( obsolescent mailers may need this address )
or	...!uunet!xanth!amiga	( very obsolescent mailers need this address )

Comments, questions, and suggestions s should be addressed to ``amiga-request''
(only use ``amiga'' for submissions) at the above addresses.