/*
Speak Freely 7.2
Copyright (C) 1997-2002 Brian C. Wiles.  All Rights Reserved.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

			Master include file
			
*/

//  System include files

#include <windows.h>
#include <shellapi.h>
#define _INC_SHELLAPI

#ifndef RC_INVOKED

#include <windowsx.h>
#include <winsock.h>
#include <mmsystem.h>

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <memory.h>
#include <time.h>
#include <float.h>
#include <io.h>
#include <commdlg.h>
#include <math.h>
#include <wchar.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <share.h>
#include <commctrl.h>

#define WM_COMMAND_ID(x)	(LOWORD(x))
#define WM_COMMAND_NOTIFY	(HIWORD(wParam))

//	Sugar coating of gratuitous incompatibilities between 16 and 32 bit Windows

#define LPWAVEFORMATxx LPWAVEFORMATEX

//	Application include files

#include "md5.h"
#include "blowfish.h"
#include "des.h"
#include "ndes.h"
#include "idea.h"
#include "ulaw.h"
#include "gsm.h"
#include "adpcm_u.h"
#include "rtp.h"
#include "rtpacket.h"
#include "lpc.h"
#include "vox.h"

#endif

#include "resource.h"

#ifdef NDEBUG
/*	Generate readable compile-time message if we leave debug output in
	a release build.  Genuinely conditional output should be explicitly
	conditioned on NDEBUG.  */
#ifdef OutputDebugString
#undef OutputDebugString
#endif	  
#define OutputDebugString { extern void OutputDebugString_in_release_build(void); \
							OutputDebugString_in_release_build(1); }
#else 
/*	If we're building for debugging, we'll probably eventually
	use the hex dump, so let's compile it in.  */
#define HEXDUMP
#endif
#define Gag(text) OutputDebugString("Gag me with a " #text "!\r\n");

//  Socket used to exchange sound packets

#define NETFONE_COMMAND_PORT           2074

//	If defined, show rant about serial I/O on comm errors

#define RANT_ON_ERROR

//  Maximum length (in characters) of a host name

#define MAX_HOST                        256

//  Get/SetWindowLong offsets

#define GWL_CLIENT                      0               // Client-side data

//  Type fields for client/server window data structures

#define WINDOW_TYPE_CLIENT              1

//  Various timeouts in seconds

#define FRAME_TIMER_ID                  1

#define TIMEOUT_CONNECTION				30				// Remote connection timeout
#define TIMEOUT_AUDIO_OUTPUT			4				// Release audio output timeout
#define TIMEOUT_RESEND_LWL				(119)			// Resend Look Who's Listening listing
#define TIMEOUT_RESEND_SDES				10				// Reset VAT/RTP ID interval
#define BroadcastUnsubscribe			10				// Broadcast mike blip length (seconds) 

//  Maximum printf-like output allowed by MsgBox

#define MAX_PRINTF_OUTPUT               1024

//	LPC encoding frame size

#define LPC_FRAME_SIZE			160

//	Number of recent connections to remember

#define REMEMBER_CONNECTIONS	5

//	Multicast definitions missing from WINSOCK.H

#ifndef IN_MULTICAST
#define IN_MULTICAST(i) ((ntohl((long)(i)) & 0xF0000000) == 0xE0000000)
#endif

//  Messages posted by the asynchronous socket APIs

#define WM_SOCKET_SELECT	(WM_USER + 100)		// Data socket notifications
#define WM_SOCKET_ASYNC		(WM_USER + 101)		// Asynchronous request completions
#define WM_SOCKET_LWL		(WM_USER + 102)		// LWL socket notifications
#define WM_SOCKET_CONTROL	(WM_USER + 103)		// Control socket notifications
#define WM_CLEAN_UP_YOUR_ACT (WM_USER + 104)	// Too depressing to explain--see FRAME.C

// Messages posted to start other sessions

#define WM_NEW_COMMANDLINE	(WM_USER + 200)		// Second instance launched with new site

#define HANDLE_WM_SOCKET_SELECT(hwnd, wParam, lParam, fn) \
    ((fn)((hwnd), (SOCKET)(wParam), (SOCKERR)WSAGETSELECTERROR(lParam), \
    (SOCKEVENT)WSAGETSELECTEVENT(lParam)), 0L)
#define FORWARD_WM_SOCKET_SELECT(hwnd, socket, serr, sevent, fn) \
    (void)(fn)((hwnd), WM_SOCKET_SELECT, (WPARAM)(socket), \
    (LPARAM)WSAMAKESELECTREPLY(sevent, serr))

#define HANDLE_WM_SOCKET_ASYNC(hwnd, wParam, lParam, fn) \
    ((fn)((hwnd), (HANDLE)(wParam), (SOCKERR)WSAGETASYNCERROR(lParam), \
    (WORD)WSAGETASYNCBUFLEN(lParam)), 0L)
#define FORWARD_WM_GETXBYX(hwnd, hAsync, serr, cbBuffer, fn) \
    (void)(fn)((hwnd), WM_SOCKET_ASYNC, (WPARAM)(hAsync), \
    (LPARAM)WSAMAKEASYNCREPLY(cbBuffer, serr))

//  Determine number of elements in an array

#define ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))

//	Macro for retrieving formats from the resource file

#define Format(n)   rstring(IDS_FORMATS + (n))

/*	Force a resource string to be FAR for those (like wsprintf)
	who can't figure out by themselves.  */
	
#define Lrstring(n)	((LPSTR) rstring(n))

//  Make life with RC a little easier

#ifdef RC_INVOKED
#define ID(x)           x
#else
#define ID(x)           MAKEINTRESOURCE(x)
#endif

///	Resource IDs

#define IDI_BASE                        1000
#define IDM_BASE                        2000
#define IDD_BASE                        3000
#define IDA_BASE                        4000

//  Icon resource IDs

#define IDI_FRAME                       ID(1000)        // IDI_BASE + 0
#define IDI_CLIENT                      ID(1001)        // IDI_BASE + 1
#define IDI_SERVER                      ID(1002)        // IDI_BASE + 2

//  Menu resource IDs

#define IDM_FRAME_BASE                  2000            // IDM_BASE + 0
#define IDM_FRAME                       ID(IDM_FRAME_BASE)
#define IDM_CONNECTION_BASE             (IDM_FRAME_BASE + 0)
#define IDM_CONNECTION_EXIT             (IDM_CONNECTION_BASE + 3)

#define IDM_WINDOW_BASE                 (IDM_FRAME_BASE + 100)
#define IDM_WINDOW_CASCADE              (IDM_WINDOW_BASE + 0)
#define IDM_WINDOW_TILE_VERTICALLY      (IDM_WINDOW_BASE + 1)
#define IDM_WINDOW_TILE_HORIZONTALLY    (IDM_WINDOW_BASE + 2)
#define IDM_WINDOW_ARRANGE_ICONS        (IDM_WINDOW_BASE + 3)
#define IDM_WINDOW_FIRST_CHILD          (IDM_WINDOW_BASE + 4)

#define IDM_HELP_BASE                   (IDM_FRAME_BASE + 200)
#define IDM_HELP_ABOUT                  (IDM_HELP_BASE + 0)

#define IDM_CUSTOM						9000			// Custom (remembered file) menu items

//  Dialog resource IDs

#define IDD_ABOUT                       ID(3000)        // IDD_BASE + 0

#define IDD_NEW                         ID(3100)        // IDD_BASE + 100
#define IDD_NEW_HOST                    3101
#define IDD_NEW_HOST_LABEL              3102

//  Accelerator table resource IDs

#define IDA_FRAME	ID(4000)			// IDA_BASE + 0

#define BUFL	3600					// Sound buffer maximum length (actually less)

#define LONG	long

#define SPEAK_FREE_FRAME_CLASS "SpeakFreeFrameClass"

struct soundbuf {
	LONG compression;
	char sendinghost[16];
	struct {
		LONG buffer_len;
		char buffer_val[BUFL];
	} buffer;
};
typedef struct soundbuf soundbuf;

// Packet mode flags

#define fComp2X     1		      // Simple 2 to 1 compression
#define fDebug	    2		      // Debug mode
#define fSetDest    4		      // Set sound output destination
#define fDestSpkr   0		      // Destination: speaker
#define fDestJack   8		      // Destination: audio output jack
#define fLoopBack   16		      // Loopback packets for testing
#define fCompGSM    32		      // GSM compression
#define fEncDES     64		      // DES encrypted
#define fEncOTP     128 	      // One-time pad encrypted
#define fEncIDEA    256 	      // IDEA encrypted
#define fCompADPCM	512 		  // ADPCM compressed
#define fEncPGP		1024		  // PGP-protected session key encrypted
#define fKeyPGP		2048		  // Packet contains PGP-encrypted session key
#define fCompLPC	4096		  // LPC compressed
#define fFaceData   8192          // Request/reply for face data
#define fFaceOffer  16384         // Offer face image to remote host
#define fNewProto   0x8000    // Version 7.1 Protocol Enhancements
#define fCompVOX	0x10000		  // VOX compressed
#define fCompLPC10	0x20000 	  // LPC-10 compressed
#define fCompRobust	0x40000		  // Robust duplicate packet mode
#define fEncBF		0x80000		  // Blowfish encrypted
#define fProtocol   0x40000000    // Speak Freely protocol flag

// Special definitions for face data packets (which have fFaceData set)

#define faceRequest 1             // Face data request
#define faceReply   2             // Face data reply
#define faceLess    4             // No face available

// Mask to extract compression modes

#define fCompressionModes   (fComp2X | fCompGSM | fCompADPCM | fCompLPC | fCompVOX)

/*	The following flags appear in the compression field of sound
	buffers but never figure in buffers actually transmitted on
	the network; they're used purely for internal housekeeping.
	In some cases flags used in network buffers are reused.  */

#define fFromModem	0x8000		  // From the modem
#define fPlayback	0x02000000	  // Answering machine playback packet
#define fAnsNewMsg	0x01000000	  // Start of new message on answering machine

// Test if a packet actually contains sound

#define isSoundPacket(c)    (((c) & (fFaceData | fKeyPGP)) == 0)

// Protocol types

#define PROTOCOL_SPEAKFREE  0		// Speak Freely protocol
#define PROTOCOL_VAT        1		// VAT protocol
#define PROTOCOL_RTP        2		// RTP protocol
#define PROTOCOL_VATRTP_CRYPT 3		// Probably encrypted VAT or RTP message
#define PROTOCOL_UNKNOWN    4		// No evidence as to protocol yet

//	Answering machine file format

struct respHeader {
	struct in_addr hostIPnumber;	// IP number of sending host
	time_t itemTime;				// Time and date buffer received
	short hostNameLength;			// Length of hostName including zero terminator
	short soundBufLength;			// Length of sound buffer
	
/*	The following items appear in the file after the header defined
	above, with lengths as given in the header.  */

//	char hostName[hostNameLength];	// Full name of host
//	soundbuf fileSoundBuf;			// Sound buffer, truncated to soundBufLength bytes 
};

//	Local loopback packet buffer

struct localLoop {
	struct localLoop *llnext;		// Next buffer in chain or NULL
	int lllen;						// Length of packet in bytes
	int llsamples;					// Number of samples in packet
	SOCKADDR_IN lladdr;				// Address packet sent to
	char llpacket[0];				// Packet data
};

#define IS_LOCALHOST(i) (ntohl((long)(i)) == 0x7F000001)
#define LOOPBACK_ENABLED	1		// Enabled flag in localLoopback 
#define LOOPBACK_PLAYING	2		// Flag in localLoopback for play active

//	Auxiliary socket

struct auxSocket {
	struct auxSocket *asnext;		// Next auxiliary socket
	short asrefc;					// Reference count if not permanent: 0 = socket closed
	unsigned short asport;			// Port number (host byte order)
	SOCKET asdata;					// Data (even port) socket
	SOCKET asctrl;					// Control (odd port) socket 
};

//	Sampling rate conversion tools

typedef struct ratestuff {
	unsigned long lcmrate;			/* least common multiple of rates */
	unsigned long inskip, outskip;	/* LCM increments for I & O rates */
	unsigned long total;
	unsigned long intot, outtot;		/* total samples in terms of LCM rate */
	long lastsamp;
} rate_t;

//  Socket-specific types

typedef INT	SOCKERR;        			// A socket error code
typedef WORD PORT;           			// A socket port number
typedef WORD SOCKEVENT;					// An asynchronous socket event

//  Potential states for connection windows

typedef enum _CLIENT_STATE
{
    Embryonic,                          // Newly creates connection
    Idle,                               // Idle
    SendingLiveAudio,                   // Sending live audio
    Transferring,                       // Sending audio file
    PlayingReceivedAudio                // Playing audio received from remote host

} CLIENT_STATE;

/*  Connection window data.  A pointer to this structure is
	kept at offset GWL_CLIENT in each connection window. */

typedef struct _CLIENT_DATA {
    DWORD dwType;                		// Type of window (WINDOW_TYPE_CLIENT)
    CLIENT_STATE state;                 // Current state.
    SOCKET sReply;                		// Socket waiting for reply from srv
    SOCKET sControl;					// Socket for RTP/VAT control messages
    int timeout;               			// Timeout counter
    SOCKADDR_IN inetSock;            	// Client's socket address
    unsigned short port;				// Destination data port number
    struct auxSocket *auxSock;			// Auxiliary socket, if any
    CHAR szHost[MAX_HOST];    			// Target server's host name
    HFILE hFile;                 		// Handle to open file
    DWORD cbSent;                		// Count of bytes sent so far.
    DWORD cbReceived;            		// Count of bytes received so far
    CHAR szFile[MAX_PATH];      		// Name of file being sent
    HANDLE getNameTask;					// Get full site name task handle
    BYTE hostBuffer[MAXGETHOSTSTRUCT];	// Host name reply buffer
    
    int modemConnection;				// Connection is via the modem
    HMMIO mmioHandle;					// WAVE file MMIO handle
    LPWAVEFORMAT mmioFormat;			// WAVE file format descriptor
    DWORD mmioDataLeft;					// WAVE file data left to send
    int quitSoundFile;					// Abort current sound file ?
    int wantsInput;						// Is wave input wanted ?
    int outputSocketBusy;				// Output socket is busy with a sendto()
    DWORD broadcastBeginTime;			// Time (ticks) when subscribed to broadcast
    int broadcastEnd;					// Terminate broadcast connection ?
    struct sockaddr_in name;			// Target system address
    struct sockaddr_in ctrl;			// Target system control port address
    char desKeyString[256];				// DES key string
    char deskey[9];                   	// Destination DES key, if any
    char rtpdeskey[9];					// Destination RTP DES key, if any
    char vatdeskey[9];					// Destination VAT DES key, if any
    char ideaKeyString[256];			// IDEA key string
    char ideakey[17];                 	// Destination IDEA key, if any
	char blowfishKeyString[256];		// Blowfish key string
	char blowfish_spec;					// Is Blowfish key specified?
	BF_KEY blowfishkey;					// Generated Blowfish key
    char pgpkeymd5[16];					// Inbound MD5 signature of PGP session key
    char pgpkey[17];					// Inbound PGP-transmitted session key
    char pgpFileName[MAX_PATH];			// Inbound PGP decoded file name, if strlen > 0
	char opgpUserList[256];				// Outbound PGP user ID list
    char opgpkey[17];					// Outbound PGP-transmitted session key
    char opgpFileName[MAX_PATH];		// Outbound PGP decoded file name, if strlen > 0
    char otpFileName[MAX_PATH];			// One-time pad file name
    char otp[BUFL];                     // One-time pad
    int multicast_scope;				// Multicast scope (time-to-live)
    int squelch;						// Squelch
    int ring;							// Ring
    int debugging;						// Debug mode
    int debugReq;						// Debug output requested by remote ?
    int loopback;						// Loopback mode
    int saveKeys;						// Save keys in connection file
    char connectionFileName[MAX_PATH];	// Connection file name for save
    gsm gsmh;							// GSM handle for incoming audio
    lpcstate_t lpc_state;				// LPC decoder state
	rate_t rateconv;					// Rate conversion state
	int rseq;							// Robust mode packet sequence number
    
    short protocol;               		// Transmission protocol
    
    short localLoopback;				// Local loopback enabled ?
    struct localLoop *llhead,			// Local loopback packet chain
    				 *lltail;
    					
    char session_id[4];              	// VAT/RTP session identifier
    int sendSDEStimer;					// Sent RTP/VAT ID timer
    int buttonUpTimer;					// Button up timer running
    LPSTR uname;						// User name, if known
    char email[256];					// User E-mail address, if known
    char szRemoteProgram[256];  // Name of program other user has.
    
    int face_stat;                    	// Face retrieval status
    long face_address;                	// Address of current block request
    int face_retry;                   	// Timeout retry count
    int face_timeout;                 	// Timeout interval
    LPSTR face_bmp;						// In memory copy of face .bmp file
    int face_is_gif;					// Face being received as .gif file
    long face_file_length;				// Length of face file being received
    int face_shown;						// Face bitmap currently displayed ?
    int bSentOutgoingMessage; // Sent outgoing message already.
    DWORD dwStartTime;        // Time (ticks) the call was started.
    float fMoneySaved;        // Money saved during this call.
} CLIENT_DATA, *LPCLIENT_DATA;

#define CLIENTPTR(w)            ((LPCLIENT_DATA)GetWindowLong((w), GWL_CLIENT))
#define IS_CLIENT_WINDOW(w)     (CLIENTPTR(w)->dwType == WINDOW_TYPE_CLIENT)

// Face retrieval status values for face_stat

#define FSinit      0                 	// Nothing requested yet
#define FSrequest   1                 	// Request sent, awaiting reply
#define FSreply     2                 	// Reply received, ready for next request
#define FScomplete  3                 	// Face file reception complete
#define FSabandoned 4                 	// Face file retrieval abandoned

// Face retrieval configuration parameters

#define FaceFetchInterval   250			// Interval between block requests, msec
#define FaceTimeout			20        	// Resend block request after this number of intervals                                    
#define FaceMaxRetries      10        	// Maximum retries to obtain face data

typedef enum {
	AE_PCMU, AE_PCMA, AE_G721, AE_IDVI, AE_G723, AE_GSM,
	AE_1016, AE_LPC, 
	AE_L8, AE_L16, AE_L24, AE_L32,
	AE_G728, AE_TRUE,
	AE_MAX
} audio_encoding_t;

/* Common audio description for files and workstations */

typedef struct {
	audio_encoding_t encoding;  /* type of encoding (differs) */
	unsigned sample_rate;       /* sample frames per second */
	unsigned channels;          /* number of interleaved channels */
} audio_descr_t;

//  Socket related data

extern SOCKET sCommand;							// Command socket
extern struct auxSocket *asList;				// List of auxiliary sockets

//  Various handles

extern HINSTANCE hInst;							// The current instance handle
extern HACCEL hAccel;							// Accelerator table handle
extern HWND hwndMDIFrame;						// MDI frame  window handle
extern HWND hwndMDIClient;						// MDI client window handle
extern HWND hDlgPropeller;						// Propeller head dialogue handle
extern HWND hDlgAnswer;							// Answering machine dialogue handle
extern HWND hDlgChat;							// Chat dialogue handle
extern HWND hDlgSpectral;						// Spectral display dialogue handle
extern HWND hSplash;               // The splash screen on startup.
extern HWND hwndToolBar;           // The main toolbar.

//  Window class names

extern LPSTR pszFrameClass;						// MDI frame  window class
extern LPSTR pszMDIClientClass;					// MDI client window class
extern LPSTR pszClientClass;					// MDI child window class

//  Miscellaneous data

extern LPSTR pszAppName;						// Application name
extern INT tmAveCharWidth;						// TEXTMETRIC.tmAveCharWidth
extern INT tmHeight;							// TEXTMETRIC.tmHeight
extern LPSTR commandLine;						// Command line from invocation
extern int holped;								// Help was invoked somewhere
extern UINT fileOpenHelpButton;					// File open help button message value
extern char *fileHelpKey;						// Help key for file open/save in progress
extern BOOL jitterPause;						// Queueing packets for anti-jitter ?

extern HWAVEOUT hWaveOut;						// Wave output handle
extern HWAVEIN hWaveIn;                  		// Wave input handle

extern soundbuf ebuf;							// Utility sound buffer

extern int audioChannels, samplesPerSecond, bytesPerSecond, sampleAlignment, bitsPerSample;

//	Compression modes

extern int voxmode;								// VOX mode
extern int breakinput;							// break input audio stream for output
extern int compression;							// 2X compression mode
extern int gsmcompress;							// GSM compression mode
extern int adpcmcompress;						// ADPCM compression mode
extern int lpccompress;							// LPC compression mode
extern int lpc10compress;						// LPC-10 compression mode
extern int robust;								// Robust mode for LPC-10
extern int voxcompress;							// VOXGSM compression mode
extern int protocolXmit;						// Default protocol to send (!protocolAuto or new connection)
extern int protocolSent;						// Protocol we're currently sending 
extern int protocolAuto;						// Send same protocol as received from connection
extern gsm gsmh;								// GSM compression handle
extern rate_t xrate;							// Simple (2X) compression context
extern int currentInputSamples;					// Samples desired in current input buffers

//	Transmission modes

extern int broadcasting;						// Broadcasting to all connections ?
extern int listeners;							// Current wantsInput windows
extern int bConferencing;						// TRUE if we send to and listen to all connections.

//	Audio settings for About dialogue

extern int isWaveSound;							// Input from wave file ?
extern int inputActive, outputActive;			// Current activity flags
extern int inputPaused;							// Is input paused for output ?
extern int halfDuplex;                          // Is hardware half-duplex
extern int aboutInSamples;						// Input samples per second
extern int aboutInBits;							// Input bits per sample
extern int aboutOutSamples;						// Output samples per second
extern int aboutOutBits;						// Output bits per sample 

//	Propeller head information

extern long packetsReceived, packetsSent;		// Network packet traffic counters
extern long inputPacketsLost, outputPacketsLost;// Packets lost counters
extern int openConnections;						// Number of open connections
extern int halfDuplexTransition;				// Transitioning from output to input ?
extern int outputInShutdown;					// Close output when last buffer returned
extern long outputPending;						// Output buffers in queue
extern int messageQueueSize;					// Message queue size
extern long messageChecks;						// Anti-lockup calls on DefaultMessageLoop

//	Network configuration for About dialogue

extern int aboutUDPmax;                         // Longest UDP packet network handles
extern int netMaxSamples;						// Maximum samples, possibly net constrained

//	Windows and driver bug work-around options

extern int alwaysBindSocket;					// Bind output socket to avoid
												// bug in some WINSOCK implementations
extern int useSendNotSendto;					/* Use send() instead of sendto()
												   if buggy (Microsoft) WINSOCK
												   refuses to accept sendto() on
												   a connect()-ed socket. */
extern int waNetNoConnect;						// Don't connect(), use sendto()
extern int waNetUseSend;						// Use send(), not sendto() always
extern int waNetMultiTTLisChar;					// Argument to IP_MULTICAST_TTL setsockopt is char
extern int waNetNoOutOverflow;					// Disable output overflow detection and recovery
extern int waNetNoMsgLoopIns;					// Disable message loop insurance
extern int waNetSynchronousGetHostname;			// Use gethostbyaddr(), not WASAsync variant
extern int waNetSynchronousGetHostnameAction;	// Action depending on above and Winsock type

extern int waProtNoHeartbeat;					// No heartbeat in Speak Freely protocol
extern int waProtUseLargerRTCPackets;			// Use large packets with RTP protocol
extern int waProtNoVAT;							// Disable auto-sensing of VAT protocol
extern int waProtNoRTP;							// Disable auto-sensing of RTP protocol
extern int waProtNoRTCPCrypt;					// Don't encrypt RTCP packets			 

extern int waAudioHalf;							// Assume audio half-duplex; don't test
extern int waAudio11025;						// Assume audio 11025 samples/sec												
extern int waAudioRingMaxVolume;				// Force maximum output volume for remote ring

//	Modem configuration information

#define	modemInputQueue	10240
#define modemOutputQueue 10240

extern int modemEnable;							// Modem connections enabled ?
extern char modemInitString[128];				// Modem initialisation string
extern char baudrate[12];						// Baud rate
extern char commport[12];						// Communications port
extern int modemHandle;							// Open modem comm port handle
extern int modemSessions;						// Open sessions on modem
extern int modemShowRant;						// Show rant about Windows serial I/O support

//	Remembered connections

extern int rememberedConnections;				// Number of remembered connections
extern LPSTR rememberedConnection[REMEMBER_CONNECTIONS];  // Remembered connections

//	Multicast settings

extern int multiMemberships;					// Number of multicast group memberships
#ifdef IP_MAX_MEMBERSHIPS
extern struct in_addr multiAddr[IP_MAX_MEMBERSHIPS]; // Multicast group IP numbers
extern LPSTR multiName[IP_MAX_MEMBERSHIPS];		// Multicast group names
#endif
extern int multiLoop;							// Multicast loop-back mode
extern int multiBrainDead;						// Multicast loop-back option not supported

//	Answering machine

extern char answerFileName[MAX_PATH];			// Answering machine file name
extern char answerOutFileName[MAX_PATH];			// Answering machine outgoing message file name
extern int answerRecord;						// Record incoming messages

//	Show Your Face

extern char faceFileName[MAX_PATH];				// Face image file name
extern HFILE faceFile; 							// Face image file handle
extern int faceShow;							// Show faces ?

//	Look Who's Listening

extern char lwl_s_server[MAX_PATH];				// Look Who's Listening server name
extern char lwl_s_email[80];					//		E-mail address
extern char lwl_s_fullname[80];					//		Full name
extern char lwl_s_phone[80];					//		Telephone number
extern char lwl_s_location[80];					//		Location name
extern int lwl_s_publish;						//		Publish in directory ?
extern int lwl_s_exact;							//		Exact match only ?

extern char lwl_a_server[MAX_PATH];				// Look Who's Listening query server
extern int lwl_a_exact;							//		Exact matches only

extern int lwl_t_published;						// Directory listing published
extern int lwl_t_resend;						// Time to update directory listing ?
extern int lwl_t_pending;						// LWL server update pending ?
extern struct sockaddr_in lookhost;   			// Look who's listening host, if any

//	VAT/RTP communication state

extern unsigned long ssrc;			  			// RTP synchronisation source identifier
extern unsigned long timestamp; 	  			// RTP packet timestamp
extern unsigned short seq;			  			// RTP packet sequence number
extern unsigned long rtpdesrand;				// RTP DES random RTCP prefix
extern char *sdes;			  					// RTP SDES packet
extern int sdesl;					  			// RTP SDES packet length
extern int spurt;								// Start of talk spurt flag	
extern char *vatid;			  					// VAT ID packet
extern int vatidl;					  			// VAT ID packet length
extern char *rtpsdes;			  				// RTP SDES packet
extern int rtpsdesl;					  		// RTP SDES packet length

extern HCURSOR phoneCursor, earCursor, boltCursor;	// Cursor handles

//	Anti-remote reincarnation protection

extern u_long Lazarus;							// Lazarus host ID
extern int LazarusLong;							// If nonzero, anti-reincarnation timeout
#define LazarusLength	15						// Lazarus timeout in seconds

extern char blankit[];                          // Long string of blanks

extern float fTotalMoneySaved;

#define V	(void)

#ifdef RANT_ON_ERROR
#define errorRant(hwnd)	{if (modemShowRant) { modemRant(hwnd); } }
#else
#define errorRant(hwnd)
#endif
                                                        
//	Function prototypes

extern void revlong(long *l);
extern void revshort(short *s);                                                        

//	Connection window functions

extern LRESULT CALLBACK connectWndProc(HWND hwnd, UINT nMessage,
								WPARAM wParam, LPARAM lParam);
extern HWND createNewConnection(LPCLIENT_DATA pClientData);
extern void connFetchFace(HWND hwndClient, LPCLIENT_DATA pClientData);

//  Dialogue functions

extern VOID aboutDialogue(HWND hwndParent);
extern VOID propellerHeadDialogue(HWND hwndParent);
extern BOOL CALLBACK propellerHeadDlgProc(HWND hwnd,
							UINT nMessage, WPARAM wParam, LPARAM lParam);
extern void propUpdateAudio(void);							
extern VOID benchDialogue(HWND hwndParent);
extern BOOL newHostDialogue(HWND hwndParent, LPSTR pszHostName, LPIN_ADDR paddr,
							unsigned short *port);
extern VOID genKeyDialogue(HWND hwnd);
extern VOID connectionProperties(HWND hwnd, LPCLIENT_DATA d);
extern VOID modemSetupDialogue(HWND hwnd);
extern void modemRant(HWND hwnd);
extern VOID multicastGroupsDialogue(HWND hwnd);
extern VOID answerDialogue(HWND hwndParent);
extern BOOL CALLBACK answerDlgProc(HWND hwnd, UINT nMessage,
							WPARAM wParam, LPARAM lParam);
extern int faceDialogue(HWND hWndParent);							
extern BOOL CALLBACK faceDlgProc(HWND hwnd, UINT nMessage,
							WPARAM wParam, LPARAM lParam);							
extern VOID lwl_ask(HWND hwnd);
extern VOID lwl_tell_settings(HWND hwnd);
extern BOOL voxMonitorDialog(HWND hwndParent);
extern BOOL IsVoxMonitorMessage(MSG *pmsg);
extern void voxMonitorUpdate(long nAudio, long nVox);
extern BOOL IsVoxMonitorOn();
extern BOOL CALLBACK Splash_DlgProc(HWND hwnd, UINT nMessage, WPARAM wParam, LPARAM lParam);

//  Frame window functions

extern LRESULT CALLBACK Frame_WndProc(HWND hwnd, UINT nMessage, WPARAM wParam, LPARAM lParam);
extern void ParseCommandLine(HWND hwnd, LPSTR pszCmdLine);

//  Initialisation functions

extern BOOL InitApplication(HINSTANCE hInstance);
extern BOOL InitInstance(HINSTANCE hInstance, LPSTR pszCmdLine, INT nCmdShow);
void SetupICQ(void);
void SetICQData(HKEY hSpeakFreelyKey, char *szSpeakFreelyPath);

// Default Message Loop

extern void DefaultMessageLoop();

//	WAVE file I/O functions

extern int readWaveInit(HWND hwndApp, LPCLIENT_DATA d, LPSTR szFileName);
extern int readWaveNext(HWND hwnd, LPCLIENT_DATA d);
extern void readWaveTerm(LPCLIENT_DATA d);

#ifdef MODEM

//	CRC calculator functions

extern unsigned short crc(unsigned char *buff, int bufflen);

//	Modem driver functions

extern int openModem(HWND hwnd);
extern int closeModem(HWND hwnd);
#endif

//	Answering machine functions

extern int answerOpen(void);
extern void answerSave(struct in_addr IPaddr, LPSTR hostName, soundbuf *sb);
extern void answerSync(void);
extern void answerClose(void);
extern int answerEnabled(void);

//	Local loopback functions

extern void loop_flush(LPCLIENT_DATA d);
extern int loop_sendto(LPCLIENT_DATA d, const char *buf, int len,
					   const struct sockaddr *to, int tolen);
extern int loop_recvfrom(LPCLIENT_DATA d, char *buf, int len,
             			  struct sockaddr *from, int *fromlen);
extern int loop_samples(LPCLIENT_DATA d);
extern BOOL loop_control_port(LPCLIENT_DATA d);             			  				

//	Show Your Face functions

extern void closeFaceFile(void);
extern int openFaceFile(HWND hwnd);
extern void processFaceRequest(soundbuf *d);
extern void processFaceData(HWND hwnd, LPCLIENT_DATA c, soundbuf *d);

//	Look Who's Listening interface

extern int sendLwlMessage(HWND hDlg, int dobye);
extern int lwl_reconnect(HWND hDlg);

//	RTP protocol functions

extern int rtp_make_sdes(char **pkt, unsigned long ssrc_i, int port, int exact, int strict);
extern int rtp_make_bye(unsigned char *p, unsigned long ssrc_i, char *raison, int strict);
extern int rtp_make_app(unsigned char *p, unsigned long ssrc_i,
						int strict, char *type, char *content);
extern LONG rtpout(soundbuf *sb, unsigned long ssrc_i,
			unsigned long timestamp_i, unsigned short seq_i,
			int spurt);
extern int isValidRTCPpacket(unsigned char *p, int len);
extern int isRTCPByepacket(unsigned char *p, int len);
extern int isRTCPAPPpacket(unsigned char *p, int len, char *name, unsigned char **app_ptr);
extern int isrtp(unsigned char *pkt, int len);
extern int parseSDES(unsigned char *packet, struct rtcp_sdes_request *r);
extern void copySDESitem(char *s, char *d);
extern void string_DES_key(LPSTR key, LPBYTE des_key, char algorithm[16]);

//	Text chat functions

#define RTCP_APP_TEXT_CHAT	"SFtc"			// APP packet name for text chat
#define WM_CHAT_TEXT_SEND (WM_USER + 1004)	// Message sent to frame to transmit text chat
extern VOID chatDialogue(HWND hwndParent);
extern BOOL CALLBACK chatDlgProc(HWND hwnd, UINT nMessage, WPARAM wParam, LPARAM lParam);
extern void chatLog(HWND hwnd, char *ident, char *text);

//	VAT protocol functions

extern int isvat(unsigned char *pkt, int len);
extern LONG vatout(soundbuf *sb, unsigned long ssrc_i, unsigned long timestamp_i, int spurt);
extern int makeVATid(char **vp, unsigned long ssrc_i);
extern int makevatdone(unsigned char *v, unsigned long ssrc_i);

//	LPC10 compression functions

extern void lpc10init(void);
extern int lpc10encode(unsigned char *in, unsigned char *out, int inlen);
extern int lpc10decode(unsigned char *in, unsigned char *out, int inlen);

//	Spectrum display functions

extern BOOL spectrumBarGraph;			// Plot spectrum as bar chart, equaliser style ?
extern BOOL spectrumVoicePrint;			// Plot spectrum as horizontal "waterfall" ?
extern BOOL spectrumTransmitOnly;		// Show transmitted audio only ?
extern BOOL spectrumReceiveOnly;		// Show received audio only ?
extern BOOL spectrumMaxEnergy;			// Show maximum energy in packet, not RMS
extern double spectrum(short *samples, int nsamples, double *ps, int nfreqs, double maxpwr);
extern void spectrumEnd(void);			        
extern VOID spectralDialogue(HWND hwndParent);
extern BOOL CALLBACK spectralDlgProc(HWND hwnd, UINT nMessage, WPARAM wParam, LPARAM lParam);
extern void spectrumUpdate(LPSTR buffer, WORD buflen, DWORD channels,
						   DWORD rate, DWORD bytesec, WORD align, BOOL isInput);

//  Utility functions

extern char *rstring(int resid);
extern char *rfilter(int resid);
extern INT MsgBox(HWND hwndParent, UINT fuType, LPSTR pszFormat, ...);
extern VOID WinPrintf(HDC hdc, INT row, INT col, LPSTR pszFormat, ...);
extern LPSTR SockerrToString(SOCKERR serr);
extern SOCKERR ResetSocket(SOCKET sock);
extern SOCKERR CreateSocket(SOCKET *psock, INT type, ULONG address, PORT port);
extern void playSound(HWND hWnd, LPCLIENT_DATA pClientData, soundbuf *d,
					  int bitsPerSample, int samplesPerSecond);
extern void decodeSound(LPCLIENT_DATA pClientData, soundbuf *d,
			      int bitsPerSample, int samplesPerSecond, LPSTR* lpPCMData, DWORD* pdwPCMLength);
extern VOID newConnection(HWND hwnd, LPSTR connectionFile, LPSTR knownHost);					 
extern void adpcmdecomp( struct soundbuf *sb);					  
extern int startWaveInput(HWND hwnd);
extern int inputSampleCount(void);
extern void terminateWaveInput(void);
extern void compress2X(soundbuf *asb);
extern void createSoundBuffer(LPSTR buffer, WORD buflen, DWORD channels,
							  DWORD rate, DWORD bytesec, WORD align);
extern void shipSoundBuffer(HWND hwnd, LPCLIENT_DATA pClientData);							  
extern VOID startSoundFile(HWND hwnd, LPSTR pszFile);
extern LPBYTE GIFtoBMP(LPBYTE gif, int imageNumber);
extern void sessionKeyGenerate(LPSTR key, BOOL binary);
extern int makeInternalEncryptionKeys(HWND hwnd, LPCLIENT_DATA d);
extern void multicastJoin(HWND hwnd, int join);
extern void propeller(int control, DWORD value);
extern int obtainOutput(HWND hwnd);
extern unsigned char alaw2ulaw(unsigned char aval);
extern void rate_start(rate_t *rate, int inrate, int outrate);
extern void rate_flow(rate_t *rate, unsigned char *ibuf, unsigned char *obuf,
					  int *isamp, int *osamp);
#ifdef HEXDUMP
extern void xd(void *buf, int bufl, int dochar);
#endif


// Definitions for different builds of the program (e.g. domestic/exportable versions).

#define CONFERENCE_SUPPORT
#define BROADCAST_SUPPORT
#define ECHO_SUPPORT
