
/*
 * This file is a product of Sun Microsystems, Inc. and is provided for
 * unrestricted use provided that this legend is included on all tape
 * media and as a part of the software program in whole or part.  Users
 * may copy or modify this file without charge, but are not authorized to
 * license or distribute it to anyone else except as part of a product
 * or program developed by the user.
 * 
 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 * 
 * This file is provided with no support and without any obligation on the
 * part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 * 
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
 * OR ANY PART THEREOF.
 * 
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even
 * if Sun has been advised of the possibility of such damages.
 * 
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 */
#include "X.h"
#define	NEED_REPLIES
#include "Xlibint.h"
#include "Xproto.h"
#include "Xprotostr.h"
#include "audio.h"
#include <stdio.h>
#include <string.h>

/* GetReq() is a given Macro in Xlibint.h */
/* Notice : no space allowed between fields */
#define GETAUDIOREQ(dpy,reqname,req) \
	if (!code[ConnectionNumber(dpy)] ) \
		return(0); \
	GetReq(reqname,req); \
	req->reqType = code[ConnectionNumber(dpy)];

/* this is storage of Request code on different displays,
each server can have different request code for the same
extension */
/* 64 file descriptors - hopefully enough for most machines */
int	code[] = {
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	};

int
Find_req_code(dpy)
Display	 *dpy;
{
int	Rcode;
int	first_event, first_error;
	if (code[ConnectionNumber(dpy)] == 0)
	{
		XQueryExtension(dpy, AUDIONAME,&Rcode, &first_event, &first_error);
		code[ConnectionNumber(dpy)] = Rcode;
	}
	return( code[ConnectionNumber(dpy)] );
}

/*
	XAudioOpen(dpy) has to be called first before all 
	other audio calls.
*/


/*
*	Open the audio port on the server.
*	returns 1 if opened, 0 if error
*/
XAudioOpen(dpy)
Display *dpy;
{
xAudio_Reply	rep;
register xAudio_OpenReq	*req;
int	AudioReqCode = 0;

	LockDisplay(dpy);
	AudioReqCode = Find_req_code(dpy);
	if (AudioReqCode <= 0)
		return(0);
	GetReq(Audio_Open, req);
	req->reqType = AudioReqCode;
	req->minor_opcode = X_AUDIO_OPEN;
	if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
		UnlockDisplay(dpy);
		SyncHandle();
		return(0);
	}
	UnlockDisplay(dpy);
	SyncHandle();
	return(rep.opened);
}

/*
* Close the audio port
* If there is still data pending, the extension code
* will refuse to close till all data are processed.
*/
XAudioClose(dpy)
Display *dpy;
{
xAudio_Reply	rep;
register xAudio_CloseReq	*req;
	GETAUDIOREQ(dpy,Audio_Close,req)
	req->minor_opcode = X_AUDIO_CLOSE;
	if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
		SyncHandle();
		return(-1);
	}
		/* rep.closed = 1 if actually closed */
	if (rep.closed)
		code[ConnectionNumber(dpy)] = 0;
	return(rep.closed);
}

/*
* Send a buffer to the audio port for playing.
*/
XAudioPlay(dpy,buffer,sizeofbuffer)
Display *dpy;
char	*buffer;
int	sizeofbuffer;
{
xAudio_Reply	rep;
register long	nbytes;
register xAudio_PlayReq	*req;
	GETAUDIOREQ(dpy,Audio_Play,req)
	req->minor_opcode = X_AUDIO_PLAY;
/* sizeofbuffer has to be divisable by 4, drop the extras */
	nbytes = sizeofbuffer - sizeofbuffer%4;
	req->length += nbytes >> 2;
/* do this here, not in arguments to PackData, since PackData
  may be a macro which uses its arguments more than once */
#ifdef DEBUG
	fprintf(stderr,"XAudioPlay:size of buffer=%d\n",nbytes);
#endif DEBUG
	PackData(dpy, buffer, nbytes );
	if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
		SyncHandle();
		return(-1);
	}
	return(rep.status);
}

/*
 *	Stop the playing.
 */
XAudioPlayOff(dpy,forced)
Display *dpy;
int	forced;
{
register xAudio_Play_OffReq	*req;
	GETAUDIOREQ(dpy,Audio_Play_Off,req)
	req->minor_opcode = X_AUDIO_PLAY_OFF;
	req->forced = forced;
	SyncHandle();
	return(1);
}

/*
 * Set the volume.
 * change the play volume and record into 3 registers
 * that the server takes.
 */
XAudioSetVolume(dpy, play_volume, record_volume)
Display *dpy;
int	play_volume, record_volume;
{
int	tmp1, tmp2;
register xAudio_Set_VolumeReq	*req;
	GETAUDIOREQ(dpy,Audio_Set_Volume,req)
	req->minor_opcode = X_AUDIO_SET_VOLUME ;
	tmp1 = play_volume/2;
	tmp2 = play_volume - tmp1;
	if (tmp1 < MIN_VOLUME)
	{
		tmp1 = -10;
		tmp2 = play_volume - tmp1;
	}
	if (tmp2 > MAX_VOLUME)
	{
		tmp2 = 12;
		tmp1 = play_volume - tmp2;
	}
	req->ger = tmp1;
	req->gr = tmp2;
	req->gx = record_volume;
	SyncHandle();
	return(1);
}

/*
 * Record a buffer full of data.
 */
XAudioRecord(dpy,buffer)
Display *dpy;
char	*buffer;
{
register int	size;
register xAudio_RecordReq	*req;
xAudio_RecordReply	rep;

	GETAUDIOREQ(dpy,Audio_Record,req)
	req->minor_opcode = X_AUDIO_RECORD;
#ifdef DEBUG
	fprintf(stderr,"XAudioRecord:\n");
#endif DEBUG
	if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {
		return(-1);
	}
	size= rep.length << 2;
#ifdef DEBUG
	fprintf(stderr,"XAudioRecord:req=%d bytes\n",size);
#endif DEBUG
	_XReadPad (dpy, buffer, (long)size);
	return(size);
}

/*
 * Stop recording - do not read anymore data.
 */
XAudioRecordOff(dpy)
Display *dpy;
{
register xAudio_Record_OffReq	*req;
	GETAUDIOREQ(dpy,Audio_Record_Off,req)
	req->minor_opcode = X_AUDIO_RECORD_OFF;
	SyncHandle();
	return(1);
}

