
/* This is the client stub module for Maelstrom Sound */

#include "sound_cmds.h"

#define SYNC_SOUND	0
#define ASYNC_SOUND	1

class SoundClient {

public:
	SoundClient(int asynchronous);
	~SoundClient();

	void SoundEvent(void);			/* Sound Event handler */
	int  QueryServer(void);
	int  SetVolume(unsigned short vol);
	int  LoadSound(short sndID);
	int  PlaySound(short sndID, short priority, 
					void (*STCallBack)(unsigned short));
	int  PlayChannel(short sndID, short priority,
		unsigned short theChannel, void (*STCallBack)(unsigned short));
	void HaltSounds(void);
	void HaltChannel(unsigned short theChannel);
	int  IsSoundPlaying(short sndID);
	void ChannelStatus(unsigned short *chanOnePriority, 
			   unsigned short *chanTwoPriority, 
			   unsigned short *chanThreePriority, 
			   unsigned short *chanFourPriority);

private:
	int  GetReply(int timeout);		/* Wait for OKAY_CMD */
	int  GetIntReply(void);			/* Wait for status return */
	int  SendCmdBuf(char *cmdbuf);		/* Send a command to server */
	int  SoundID(unsigned short channel);
	int  Status(unsigned short channel);
	void CallBack(unsigned short channel);

	int channel_fd;
	int sndserver_pid;
	int server_events;
	int server_reply;
	int run_async;				/* ASYNC I/O flag */

	struct channel {
		int    in_use;
		short  ID;
		short  priority;
		void (*Callback)(unsigned short);
		} channels[NUM_CHANNELS];

	struct Q_ent {
		unsigned short channel;
		struct Q_ent  *next;
		} Callback_Q, *Callback_Qtail;
	int awaiting_reply;

	inline void QueueCallback(unsigned short channel) {
		Callback_Qtail->next = new struct SoundClient::Q_ent;
		Callback_Qtail = Callback_Qtail;
		Callback_Qtail->channel = channel;
		Callback_Qtail->next = NULL;
	}
	inline void DequeueCallbacks(void) {
		struct SoundClient::Q_ent *oldptr, *ptr;

		awaiting_reply = 0;
		for ( ptr=Callback_Q.next; ptr; ) {
			CallBack(ptr->channel);
			oldptr = ptr;
			ptr = ptr->next;
			delete oldptr;
		}
		Callback_Qtail = &Callback_Q;
		Callback_Q.next = NULL;
	}
};
