 
/* The following functions are provided with the tools for the sake
 * of experimentation, but there are no direct examples of their
 * use (yet).  Want to be sure that these meld consistently with
 * already existing functions.
 */

/* To request "any" stereo pair, use pair = -1;
 * To request a specific stereo pair, use pair = {100,101,102,or 103}
 * corresponding to channels 0 and 1, 0 and 2, 1 and 3 or 2 and 3
 * respectively.  (Channels 0 and 3 are connected to the LEFT output
 * channel, and channels 1 and 2 go to the RIGHT output).
 *
 * Values of 104 and 105 are special, representing "get two LEFT
 * channels" (104) or "get two RIGHT channels" (105).  You do this
 * so as to keep a sound on the same side without ping ponging back
 * and forth as some programs do.
 */
int
GetPair(pair)
	LONG pair;
{
	int error, value;
	struct ExtIOB *iob, controlIOB;

	iob = &controlIOB;
	iob->ioa_Request.io_Device    = device;
	iob->ioa_Request.io_Message.mn_ReplyPort = controlPort;

	InitBlock(iob,0);	/* init it for CMD_WRITE, then change */

	/* set precedence of the request for a channel */
	iob->ioa_Request.io_Message.mn_Node.ln_Pri = 20;

	/* Type of command is ALLOCATE */
	iob->ioa_Request.io_Command = ADCMD_ALLOCATE;
	if(pair == -1)
	{	/* Point to the allocation map */ 
		iob->ioa_Data = (UBYTE *)stereostuff;
		
		/* It contains 4 entries */
		iob->ioa_Length = 4;
	}
	else if(pair >=100 && pair <= 105)
	{	iob->ioa_Data = (UBYTE *)(&stereostuff[pair-100]);
		iob->ioa_Length = 1;
	}
	else	/* chose a bad channel pair; cannot allocate it */
	{	
		return(-1);
	}
	/* Don't wait for allocation, channels
	 * should be available!  If we don't set
	 * ADIOF_NOWAIT, the task will idle waiting
	 * for a chance to allocate the channel, 
	 * looking again each time another task
	 * allocates or frees a channel.         
	 */
	iob->ioa_Request.io_Flags = ADIOF_NOWAIT | IOF_QUICK;

	BeginIO(iob); 

	error = WaitIO(iob);  /* returns nonzero if error */
	if(!(iob->ioa_Request.io_Flags & IOF_QUICK))
	{	/* if flag not set, then the message
		 * was appended to the reply port 
		 * (was not quick I/O after all)  */
		GetMsg(iob->ioa_Request.io_Message.mn_ReplyPort);
	}
	if(error)
	{	return(-1);
	}
	/* Save the values... freeing the IOB on exit */
	gotunit   = (iob->ioa_Request.io_Unit);
	gotkey	  = (iob->ioa_AllocKey);
		
	switch((LONG)(iob->ioa_Request.io_Unit))
	{	
		/* stereo allocations possible */

		case  3:	value = 100;	break;
		case  5:	value = 101;	break;
		case 10:	value = 102;	break;
		case 12:	value = 103;	break;

		/* two-channel monophonic allocations */

		case  9:        value = 104;    break;
		case  6:        value = 105;    break;
		default:	value = -1;	break;
	}
	return(value);
}

/* 

The reason for the odd choice of numbers is so that there
would be no conflict (or misunderstanding) with GetChannel.
Examine the code for GetChannel and you'll note that the
unit value is saved away for future use.

If you get a stereo pair, the same alloc_key can be saved
away for two different channels.  And if you have successfully
allocated both channels with this single call, you have the
right to store those values for the channels as though they
are independent anyway.

Return value to be tested this way or the equivalent (I am sure
that a lot of you can discern a much more elegant way of doing
this).

	pair = GetStereoPair(-1);

	switch (pair) {
		case 100:
			key[0] = gotkey;  key[1] = gotkey;
			unit[0] = 1;  unit[1] = 2;
			break;
		case 101:
			key[0] = gotkey;  key[2] = gotkey;
			unit[0] = 1;  unit[2] = 4;
			break;
		case 102:
			key[1] = gotkey;  key[3] = gotkey;
			unit[1] = 2;  unit[3] = 8;
			break;
		case 103:
			key[2] = gotkey;  key[3] = gotkey;
			unit[2] = 4;  unit[3] = 8;
			break;
		case 104:
			key[0] = gotkey;  key[3] = gotkey;
			unit[0] = 1;  unit[3] = 8;
			break;
		case 105:
			key[1] = gotkey;  key[2] = gotkey;
			unit[1] = 2;  unit[2] = 8;
			break;
		case -1:
		default:
			break;
		};


As a direct result of the above, if the USER keeps track of which
channels he allocated, he can free them one at a time, or use them
one at a time, even though the allocation key is common to both 
channels.  Also this is useful for stopping both channels in a 
single command, then to queue notes to both channels individually 
and use a single command to start both channels at once.

The function "ControlChannel" will have to be modified to recognize
channel pair numbers 100, 101, 102 and 103, and extract the appropriate
key value and set the corresponding unit value so that both channels
can be controlled at the same time.  (Corresponding unit values are
listed in GetStereoPair above).   If both channel's notes are
in sync as queued, they'll remain in sync when the queue floodgates
are opened.  Though user can still Control the channels individually
if desired, just by using the normal channel numbers 0, 1, 2 and 3
if user owns those channels.

*/

