www.pudn.com > speakfs72.zip > ANSWER.C, change:2002-01-05,size:34500b


/* 
 
				Answering Machine 
				 
*/ 
 
#include "netfone.h" 
 
#define answerBufferSize 2048			// Buffer for reading message file 
 
#ifdef answerBufferSize 
static char answerBuffer[answerBufferSize]; 
#endif 
 
char answerFileName[MAX_PATH] = "";		// Answering machine file name 
char answerOutFileName[MAX_PATH] = "";		// Answering machine outgoing message file name 
int answerRecord = TRUE;				// Record incoming messages 
 
static FILE *answerFile = NULL; 		// Answering machine file descriptor 
static long answerLen;					// Length of answering machine file 
static long answerPlayPos;				// Current replay address  
static int replaying = FALSE;			// Nonzero when replay is active 
static int currentMessage;				// Current message being replayed 
static time_t lastPacket = 0;			// Time of last packet recorded 
 
static long FAR *msgTable = NULL;		// Pointers to messages in file 
static int msgMax = 0;					// Message table size 
static int msgCount = 0;				// Messages currently in table 
 
#define newMessageCriterion	2			// Gap length, in seconds, defining a new message 
 
/*	SETMESSAGECOUNT  --  If answering machine is displayed, update the 
						 number of messages in the file.  */ 
 
static void setMessageCount(void) 
{ 
	if (hDlgAnswer != NULL) { 
		char mno[24]; 
		 
		if (currentMessage >= 0) { 
			wsprintf(mno, Format(42), currentMessage + 1, msgCount); 
		} else { 
			if (msgCount > 1) { 
				wsprintf(mno, Format(43), msgCount); 
			} else { 
				strcpy(mno, msgCount == 1 ? rstring(IDS_T_ONE_MESSAGE) : 
										    rstring(IDS_T_NO_MESSAGES)); 
			} 
		} 
		SetDlgItemText(hDlgAnswer, IDC_RP_MSGBOX, mno); 
	} 
} 
 
//	GROWMESSAGETABLE  --  Expand in-memory message table if needed 
 
static int growMessageTable(HWND hwnd, int currentMessage) 
{ 
  long FAR *oldmsgTable;		// In case the ReAlloc fails. 
 
	if (currentMessage >= msgMax) { 
		msgMax += 50; 
    oldmsgTable = msgTable; 
		msgTable = GlobalReAllocPtr(msgTable, msgMax * sizeof(long), 0); 
		if (msgTable == NULL) { 
	    	MessageBox(hwnd, rstring(IDS_T_EXPAND_MSG_TABLE_ERR), 
		   		NULL, MB_OK | MB_ICONEXCLAMATION); 
         
        /* At this point, the re-allocation failed (out of memory, etc.), 
         * but we still have the first few messages in memory.  So, let's 
         * point back to the old location.  -BCW 05/26/1999 
         */ 
        msgTable = oldmsgTable; 
		   	return FALSE; 
		} 
	} 
	return TRUE; 
} 
 
/*  ANSWEROPEN  --  Open the answering machine file.  */ 
 
int answerOpen(void) 
{ 
	answerFile = fopen(answerFileName, "r+b"); 
	if (answerFile == NULL) { 
		answerFile = fopen(answerFileName, "w+b"); 
	} 
	if (answerFile != NULL) { 
#ifdef answerBufferSize 
		setvbuf(answerFile, answerBuffer, _IOFBF, sizeof answerBuffer); 
#endif 
		fseek(answerFile, 0L, 2); 
		answerLen = ftell(answerFile); 
		rewind(answerFile); 
	} 
	replaying = FALSE; 
	return answerFile != NULL; 
} 
 
//	ANSWERENABLED  --  Determine if recording messages is possible 
 
int answerEnabled(void) 
{ 
	return answerFile != NULL; 
} 
 
/*	ANSWERSAVE  --  If the answering machine is on, save a sound 
					buffer in the answering machine file.  */ 
					 
void answerSave(struct in_addr IPaddr, LPSTR hostName, soundbuf *sb) 
{ 
	if (answerRecord && answerFile != NULL) { 
		struct respHeader r; 
		char lh[MAX_HOST]; 
		long scomp; 
		 
		fseek(answerFile, answerLen, 0); 
		r.hostIPnumber = IPaddr; 
		r.itemTime = time(NULL); 
		r.hostNameLength = lstrlen(hostName) + 1; 
		r.soundBufLength = (WORD) (sb->buffer.buffer_len + (sizeof(soundbuf) - BUFL)); 
		fwrite(&r, sizeof r, 1, answerFile); 
		_fmemcpy(lh, hostName, r.hostNameLength); 
		fwrite(lh, r.hostNameLength, 1, answerFile); 
		scomp = sb->compression; 
		sb->compression = fProtocol | fPlayback | (((r.itemTime - lastPacket) > newMessageCriterion) ? 
			fAnsNewMsg : 0) /* | (scomp & fComp2X) */ ; 
		lastPacket = r.itemTime;  
		fwrite(sb, r.soundBufLength, 1, answerFile); 
		if ((hDlgAnswer != NULL) && (sb->compression & fAnsNewMsg) && 
			(msgTable != NULL)) { 
			if (growMessageTable(hDlgAnswer, msgCount + 1)) { 
				msgTable[msgCount++] = answerLen; 
				setMessageCount(); 
			} 
		}  
		sb->compression = scomp; 
		answerLen = ftell(answerFile); 
		if (hDlgAnswer != NULL) { 
			EnableWindow(GetDlgItem(hDlgAnswer, IDC_RP_NEXT), answerLen > 0); 
			EnableWindow(GetDlgItem(hDlgAnswer, IDC_RP_ERASE), answerLen > 0); 
		} 
	} 
} 
 
/*  ANSWERSYNC  --  Make sure output data are written to file.  */ 
 
void answerSync(void) 
{ 
	if (answerFile != NULL) { 
		fflush(answerFile); 
	} 
} 
 
/*  ANSWERCLOSE  --  Close the answering machine.  */ 
 
void answerClose(void) 
{ 
	if (answerFile != NULL) { 
		fclose(answerFile); 
		answerFile = NULL; 
	} 
} 
 
/*  ANSWERREPLAY  --  Begin replay of answering machine.  */ 
 
static void answerReplay(void) 
{ 
	answerSync(); 
	replaying = TRUE; 
} 
 
/*  ANSWERREAD  --  Read the next buffer from the answering machine.  */ 
 
static int answerRead(struct in_addr *IPaddr, time_t *rtime, 
					  char *hostName, soundbuf *sb) 
{ 
	struct respHeader r; 
     
    fseek(answerFile, answerPlayPos, 0); 
	if (fread(&r, sizeof r, 1, answerFile) != 1) { 
		return FALSE; 
	} 
	*IPaddr = r.hostIPnumber; 
	*rtime = r.itemTime; 
	if (fread(hostName, r.hostNameLength, 1, answerFile) != 1) { 
		return FALSE; 
	} 
	if (fread(sb, r.soundBufLength, 1, answerFile) != 1) { 
		return FALSE; 
	} 
    answerPlayPos = ftell(answerFile); 
    return TRUE; 
} 
 
/*  ANSWERREPLAYDONE  --  End replay of answer file.  */ 
 
static void answerReplayDone(void) 
{ 
	replaying = FALSE; 
	answerPlayPos = 0; 
} 
 
//	SCANMESSAGEFILE  --  Built in-memory message table 
 
static void scanMessageFile(HWND hwnd) 
{ 
	struct in_addr IPaddr; 
	char hostName[MAX_HOST]; 
	time_t t; 
	long lp; 
     
	answerPlayPos = 0; 
	msgCount = 0; 
    if (answerFile != NULL) {    				 
		while (lp = answerPlayPos, answerRead(&IPaddr, &t, hostName, &ebuf)) { 
			if (ebuf.compression & fAnsNewMsg) { 
				if (!growMessageTable(hwnd, msgCount + 1)) { 
					return; 
				} 
				msgTable[msgCount++] = lp; 
			}	 
		} 
		answerPlayPos = 0; 
	} 
} 
 
//	ANSWERDLGPROC  --  Answering machine dialogue procedure 
 
BOOL CALLBACK answerDlgProc(HWND hwnd, UINT nMessage, 
							WPARAM wParam, LPARAM lParam) 
{ 
	static int replaying; 
	static int firstPacket, hostShown, hostPrelim; 
	static int buttonPushed; 
 
	switch (nMessage) { 
    	case WM_INITDIALOG: 
    		replaying = FALSE; 
			msgMax = 50; 
			msgTable = (long FAR *) GlobalAllocPtr(GPTR, msgMax * sizeof(long)); 
			if (msgTable == NULL) { 
		    	MessageBox(hwnd, rstring(IDS_T_ALLOC_MSG_TABLE_ERR), 
			   		NULL, MB_OK | MB_ICONEXCLAMATION); 
			   	DestroyWindow(hwnd); 
			} 
			hDlgAnswer = hwnd; 
			scanMessageFile(hwnd); 
setIdle:	EnableWindow(GetDlgItem(hwnd, IDC_RP_PREV), FALSE); 
			EnableWindow(GetDlgItem(hwnd, IDC_RP_REPLAY), FALSE); 
			EnableWindow(GetDlgItem(hwnd, IDC_RP_REWIND), FALSE); 
			EnableWindow(GetDlgItem(hwnd, IDC_RP_NEXT), answerFile && msgCount > 0); 
			EnableWindow(GetDlgItem(hwnd, IDC_RP_ERASE), answerFile && answerLen > 0); 
			EnableWindow(GetDlgItem(hwnd, IDC_RP_RECORD), answerFile != NULL);  
			EnableWindow(GetDlgItem(hwnd, IDC_RP_SAVE), FALSE); 
			CheckDlgButton(hwnd, IDC_RP_RECORD, answerFile && answerRecord); 
			if (answerFileName != NULL) { 
				SetDlgItemText(hwnd, IDC_RP_MSGFILE, answerFileName); 
			}  
			if (answerOutFileName != NULL) { 
				SetDlgItemText(hwnd, IDC_RP_OUTMSGFILE, answerOutFileName); 
			}  
			SetDlgItemText(hwnd, IDC_RP_SITE, ""); 
			SetDlgItemText(hwnd, IDC_RP_TIME, ""); 
			currentMessage = -1;			// Nothing played yet 
			buttonPushed = 0; 
			setMessageCount(); 
	    	return TRUE; 
	    	 
	    case WM_CLOSE: 
/*{ static double zee = 1.0; 
  static double grex = 0.0; 
  static char ig[8]; 
  // Divide by zero to test floating point exception mode settings 
  zee = zee / sin(grex); 
  _fmemcpy(ig, &zee, 8); 
  zee++; 
  grex += 2; 
}*/ 
	    	DestroyWindow(hwnd); 
	    	return TRUE; 
 
        case WM_COMMAND: 
        	switch ((short) WM_COMMAND_ID(wParam)) { 
        	 
        		case IDC_RP_PREV: 
            { 
				      struct in_addr IPaddr; 
				      char hostName[MAX_HOST]; 
				      time_t t; 
		    			char ft[24]; 
		    			struct tm *lt; 
 
					    if(currentMessage > 0) 
                currentMessage--; 
#ifdef ANSWER_OLD_BEHAVIOR 
					goto playCurrent; 
#else 
          // Update message display. 
					answerPlayPos = msgTable[currentMessage]; 
          if(answerRead(&IPaddr, &t, hostName, &ebuf)) 
          { 
            setMessageCount(); 
            lt = localtime(&t);		 
            sprintf(ft, Format(49), rstring(IDS_WEEKDAYS + lt->tm_wday), 
                    lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, 
                    lt->tm_hour, lt->tm_min, lt->tm_sec);  
            SetDlgItemText(hwnd, IDC_RP_TIME, ft); 
            SetDlgItemText(hwnd, IDC_RP_SITE, hostName); 
          } 
 
					answerPlayPos = msgTable[currentMessage]; 
 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_PREV), currentMessage > 0); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_NEXT), currentMessage < (msgCount - 1)); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_REPLAY), currentMessage >= 0); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_REWIND), TRUE); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_ERASE), TRUE); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_BROWSE), TRUE); 
        	EnableWindow(GetDlgItem(hwnd, IDC_RP_SAVE), currentMessage >= 0); 
          break; 
#endif 
              } 
        		case IDC_RP_NEXT: 
            { 
				      struct in_addr IPaddr; 
				      char hostName[MAX_HOST]; 
				      time_t t; 
		    			char ft[24]; 
		    			struct tm *lt; 
 
          if(currentMessage < msgCount) 
    				currentMessage++; 
#ifndef ANSWER_OLD_BEHAVIOR 
          // Update message display. 
					answerPlayPos = msgTable[currentMessage]; 
          if(answerRead(&IPaddr, &t, hostName, &ebuf)) 
          { 
            setMessageCount(); 
            lt = localtime(&t);		 
            sprintf(ft, Format(49), rstring(IDS_WEEKDAYS + lt->tm_wday), 
                    lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, 
                    lt->tm_hour, lt->tm_min, lt->tm_sec);  
            SetDlgItemText(hwnd, IDC_RP_TIME, ft); 
            SetDlgItemText(hwnd, IDC_RP_SITE, hostName); 
          } 
 
					answerPlayPos = msgTable[currentMessage]; 
 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_PREV), currentMessage > 0); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_NEXT), currentMessage < (msgCount - 1)); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_REPLAY), currentMessage >= 0); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_REWIND), TRUE); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_ERASE), TRUE); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_BROWSE), TRUE); 
        	EnableWindow(GetDlgItem(hwnd, IDC_RP_SAVE), currentMessage >= 0); 
          break; 
            } 
#endif 
							 
				case IDC_RP_REPLAY: 
#ifdef ANSWER_OLD_BEHAVIOR 
playCurrent:		 
#endif 
          setMessageCount(); 
					buttonPushed = WM_COMMAND_ID(wParam);  
    				if (obtainOutput(hwndMDIFrame)) { 
        				answerReplay(); 
						answerPlayPos = msgTable[currentMessage]; 
						//	Disable controls to prevent mischief while we're playing 
        				EnableWindow(GetDlgItem(hwnd, IDC_RP_PREV), FALSE); 
        				EnableWindow(GetDlgItem(hwnd, IDC_RP_NEXT), FALSE); 
        				EnableWindow(GetDlgItem(hwnd, IDC_RP_REPLAY), FALSE); 
        				EnableWindow(GetDlgItem(hwnd, IDC_RP_SAVE), FALSE); 
						EnableWindow(GetDlgItem(hwnd, IDC_RP_ERASE), FALSE); 
						EnableWindow(GetDlgItem(hwnd, IDC_RP_REWIND), FALSE); 
						EnableWindow(GetDlgItem(hwnd, IDC_RP_BROWSE), FALSE); 
        				replaying = TRUE; 
        				firstPacket = TRUE; 
        				hostShown = hostPrelim = FALSE; 
        				SetTimer(hwnd, 5, 1, NULL); 
    				} 
        			break; 
        	 
        		case IDC_RP_ERASE: 
					fclose(answerFile); 
					answerFile = fopen(answerFileName, "w+b"); 
					msgCount = 0; 
        			answerLen = 0; 
					//	Note fall-through 
			 
				case IDC_RP_REWIND:  
        			goto setIdle; 
        			 
                case IDC_RP_BROWSE: 
			     	{ 
			     		OPENFILENAME ofn; 
			     		char szString[MAX_PATH]; 
			 
			            memset(&ofn, 0, sizeof(ofn)); 
						ofn.lStructSize = sizeof(OPENFILENAME); 
						ofn.hwndOwner = hwnd; 
						ofn.lpstrFilter = rfilter(IDS_T_ANSWER_MESSAGE_FILTER); 
						ofn.lpstrCustomFilter = NULL; 
						strcpy(szString, answerFileName); 
						ofn.lpstrFile = (LPSTR) szString; 
						ofn.nMaxFile = sizeof(szString); 
						ofn.lpstrInitialDir = NULL; 
						ofn.lpstrTitle = rstring(IDS_T_ANSWER_OPEN_TITLE); 
						ofn.Flags = OFN_NOREADONLYRETURN | OFN_HIDEREADONLY | OFN_SHOWHELP; 
						fileHelpKey = rstring(IDS_HELP_ANSWER); 
						if (GetOpenFileName((LPOPENFILENAME) &ofn)) { 
							SetDlgItemText(hwnd, IDC_RP_MSGFILE, szString); 
							_fstrcpy(answerFileName, szString); 
							answerClose(); 
							answerOpen(); 
							currentMessage = -1; 
							scanMessageFile(hwnd); 
							EnableWindow(GetDlgItem(hwnd, IDC_RP_PREV), FALSE); 
							EnableWindow(GetDlgItem(hwnd, IDC_RP_REWIND), FALSE); 
							EnableWindow(GetDlgItem(hwnd, IDC_RP_REPLAY), FALSE); 
        			EnableWindow(GetDlgItem(hwnd, IDC_RP_SAVE), FALSE); 
							EnableWindow(GetDlgItem(hwnd, IDC_RP_NEXT), answerFile && msgCount > 0); 
							EnableWindow(GetDlgItem(hwnd, IDC_RP_ERASE), answerFile && answerLen > 0); 
							EnableWindow(GetDlgItem(hwnd, IDC_RP_RECORD), answerFile != NULL);  
							SetDlgItemText(hwnd, IDC_RP_SITE, ""); 
							SetDlgItemText(hwnd, IDC_RP_TIME, ""); 
							setMessageCount(); 
						} 
					} 
					break; 
 
				case IDC_RP_CLEAR_INCOMING: 
					SetDlgItemText(hwnd, IDC_RP_MSGFILE, ""); 
					strcpy(answerFileName, ""); 
					answerClose(); 
					currentMessage = -1; 
					scanMessageFile(hwnd); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_PREV), FALSE); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_REWIND), FALSE); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_REPLAY), FALSE); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_NEXT), FALSE); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_ERASE), FALSE); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_RECORD), FALSE);  
        	EnableWindow(GetDlgItem(hwnd, IDC_RP_SAVE), FALSE); 
					SetDlgItemText(hwnd, IDC_RP_SITE, ""); 
					SetDlgItemText(hwnd, IDC_RP_TIME, ""); 
					setMessageCount(); 
					break; 
					 
                case IDC_RP_BROWSE_OUTGOING: 
			     	{ 
			     		OPENFILENAME ofn; 
			     		char szString[MAX_PATH]; 
			 
			            memset(&ofn, 0, sizeof(ofn)); 
						ofn.lStructSize = sizeof(OPENFILENAME); 
						ofn.hwndOwner = hwnd; 
						ofn.lpstrFilter = rfilter(IDS_T_SOUND_FILE_FILTER); 
						ofn.lpstrCustomFilter = NULL; 
						strcpy(szString, answerOutFileName); 
						ofn.lpstrFile = (LPSTR) szString; 
						ofn.nMaxFile = sizeof(szString); 
						ofn.lpstrInitialDir = NULL; 
						ofn.lpstrTitle = rstring(IDS_T_ANSWER_OUTOPEN_TITLE); 
						ofn.Flags = OFN_SHOWHELP; 
						fileHelpKey = rstring(IDS_HELP_ANSWER); 
						if (GetOpenFileName((LPOPENFILENAME) &ofn)) { 
							SetDlgItemText(hwnd, IDC_RP_OUTMSGFILE, szString); 
							_fstrcpy(answerOutFileName, szString); 
						} 
					} 
					break; 
 
				case IDC_RP_CLEAR_OUTGOING: 
					strcpy(answerOutFileName, ""); 
					SetDlgItemText(hwnd, IDC_RP_OUTMSGFILE, ""); 
					break; 
					 
				case IDC_RP_RECORD: 
					answerRecord = IsDlgButtonChecked(hwnd, IDC_RP_RECORD); 
					break; 
        	 
        case IDC_RP_SAVE: 
        { 
			    OPENFILENAME ofn; 
			    char szWaveMessage[MAX_PATH]; 
				  struct in_addr IPaddr; 
				  char hostName[MAX_HOST]; 
				  time_t t; 
				  long sfp; 
				  int ateof = FALSE; 
          DWORD write_pos; 
          char szError[200]; 
          HMMIO    hmmioOut; 
          MMIOINFO mmioinfoOut; 
          MMCKINFO ckOutRIFF; 
          MMCKINFO ckOut; 
          LPSTR pcmdata; 
          DWORD dwPCMBytes; 
          WAVEFORMATEX pwf; 
		 
			    memset(&ofn, 0, sizeof(ofn)); 
					ofn.lStructSize = sizeof(OPENFILENAME); 
					ofn.hwndOwner = hwnd; 
					ofn.lpstrFilter = rfilter(IDS_T_WAVE_FILE_FILTER); 
					ofn.lpstrCustomFilter = NULL; 
					szWaveMessage[0] = '\0'; 
					ofn.lpstrFile = (LPSTR) szWaveMessage; 
					ofn.nMaxFile = sizeof(szWaveMessage); 
					ofn.lpstrInitialDir = NULL; 
					ofn.lpstrTitle = rstring(IDS_T_ANSWER_SAVE_TITLE); 
					ofn.Flags = OFN_SHOWHELP; 
					fileHelpKey = rstring(IDS_HELP_ANSWER); 
					 
          if (GetOpenFileName((LPOPENFILENAME) &ofn)) 
          { 
            if(!strchr(szWaveMessage, '.')) 
            { 
              strcat(szWaveMessage, ".wav"); 
            } 
 
            SetCursor(LoadCursor(NULL, IDC_WAIT)); 
 
            hmmioOut = mmioOpen(szWaveMessage, NULL, 
                                MMIO_ALLOCBUF | MMIO_WRITE | MMIO_CREATE); 
 
            if (!hmmioOut) 
            { 
              sprintf(szError,rstring(IDS_T_OPEN_WAVE_FILE_ERR), szWaveMessage); 
              MessageBox(NULL, szError, NULL, MB_OK | MB_ICONEXCLAMATION); 
              break; 
            } 
 
            // Create the output file RIFF chunk of form type WAVE. 
 
            ckOutRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E'); 
            ckOutRIFF.cksize  = 0; 
             
            if (mmioCreateChunk(hmmioOut, &ckOutRIFF, MMIO_CREATERIFF) 
  		          != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Initialize the WAVEFORMATEX structure 
 
	          pwf.nChannels = audioChannels; 
    	      pwf.nSamplesPerSec = samplesPerSecond; 
    	      pwf.nAvgBytesPerSec = bytesPerSecond; 
    	      pwf.nBlockAlign = sampleAlignment; 
    	      pwf.wBitsPerSample = bitsPerSample; 
            pwf.wFormatTag      = WAVE_FORMAT_PCM; 
            pwf.cbSize          = 0; 
 
            // Create the fmt chunk 
 
            ckOut.ckid = mmioFOURCC('f', 'm', 't', ' '); 
            ckOut.cksize = sizeof(pwf); 
 
            if (mmioCreateChunk(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Write the WAVEFORMATEX structure to the fmt chunk. 
 
            if (mmioWrite(hmmioOut, (HPSTR) &pwf, sizeof(pwf)) 
                != sizeof(pwf)) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Ascend out of the fmt chunk, back into the RIFF chunk. 
 
            if (mmioAscend(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Create the data chunk that holds the waveform samples. 
 
            ckOut.ckid   = mmioFOURCC('d', 'a', 't', 'a'); 
            ckOut.cksize = 0; 
             
            if (mmioCreateChunk(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            mmioGetInfo(hmmioOut, &mmioinfoOut, 0); 
 
            setMessageCount(); 
        		answerReplay(); 
 
						answerPlayPos = msgTable[currentMessage]; 
            sfp = answerPlayPos; 
        		replaying = TRUE; 
        		firstPacket = TRUE; 
					   
            while((answerRead(&IPaddr, &t, hostName, &ebuf)) 
                  && (firstPacket || !(ebuf.compression & fAnsNewMsg))) 
            {  
		        		  firstPacket = FALSE; 
                  // Decompress and/or decrypt packet 
							    decodeSound(NULL, &ebuf, aboutOutBits, aboutOutSamples, 
                              &pcmdata, &dwPCMBytes); 
                   
                  // Write packet to file. 
                  for (write_pos = 0; write_pos < dwPCMBytes; write_pos++) 
                  { 
 
  	                // Check if we are at the end of the output buffer. 
                    // If so, flush it. 
	                  if (mmioinfoOut.pchNext == mmioinfoOut.pchEndWrite) 
	                  { 
                      mmioinfoOut.dwFlags |= MMIO_DIRTY; 
 
                      if (mmioAdvance(hmmioOut, &mmioinfoOut, MMIO_WRITE) 
                          != MMSYSERR_NOERROR) 
                      { 
                        MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
                        mmioClose(hmmioOut, 0); 
                        break; 
                      } 
 
	                  } 
 
                    // Copy one byte 
	                  *mmioinfoOut.pchNext++ = pcmdata[write_pos]; 
                  } 
 
                  // Free up the PCM buffer. 
                  GlobalFreePtr(pcmdata); 
            } 
             
            answerPlayPos = sfp; 
				    replaying = FALSE; 
				    answerReplayDone(); 
 
	          // Mark the current chunk as dirty and flush it 
            mmioinfoOut.dwFlags |= MMIO_DIRTY; 
            if (mmioSetInfo(hmmioOut, &mmioinfoOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Ascend out of data chunk 
            if (mmioAscend(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Ascend out of RIFF chunk 
            if (mmioAscend(hmmioOut, &ckOutRIFF, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Close the file 
            if (mmioClose(hmmioOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
             
            SetCursor(LoadCursor(NULL, IDC_ARROW)); 
          } 
          break; 
        } 
           
        case IDC_RP_SAVE_ALL: 
        { 
			    OPENFILENAME ofn; 
			    char szWaveMessage[MAX_PATH]; 
				  struct in_addr IPaddr; 
				  char hostName[MAX_HOST]; 
				  time_t t; 
				  long sfp; 
				  int ateof = FALSE; 
          DWORD write_pos; 
          char szError[200]; 
          HMMIO    hmmioOut; 
          MMIOINFO mmioinfoOut; 
          MMCKINFO ckOutRIFF; 
          MMCKINFO ckOut; 
          LPSTR pcmdata; 
          DWORD dwPCMBytes; 
          WAVEFORMATEX pwf; 
		 
			    memset(&ofn, 0, sizeof(ofn)); 
					ofn.lStructSize = sizeof(OPENFILENAME); 
					ofn.hwndOwner = hwnd; 
					ofn.lpstrFilter = rfilter(IDS_T_WAVE_FILE_FILTER); 
					ofn.lpstrCustomFilter = NULL; 
					szWaveMessage[0] = '\0'; 
					ofn.lpstrFile = (LPSTR) szWaveMessage; 
					ofn.nMaxFile = sizeof(szWaveMessage); 
					ofn.lpstrInitialDir = NULL; 
					ofn.lpstrTitle = rstring(IDS_T_ANSWER_SAVE_TITLE); 
					ofn.Flags = OFN_SHOWHELP; 
					fileHelpKey = rstring(IDS_HELP_ANSWER); 
					 
          if (GetOpenFileName((LPOPENFILENAME) &ofn)) 
          { 
            if(!strchr(szWaveMessage, '.')) 
            { 
              strcat(szWaveMessage, ".wav"); 
            } 
 
            SetCursor(LoadCursor(NULL, IDC_WAIT)); 
 
            hmmioOut = mmioOpen(szWaveMessage, NULL, 
                                MMIO_ALLOCBUF | MMIO_WRITE | MMIO_CREATE); 
 
            if (!hmmioOut) 
            { 
              sprintf(szError,rstring(IDS_T_OPEN_WAVE_FILE_ERR), szWaveMessage); 
              MessageBox(NULL, szError, NULL, MB_OK | MB_ICONEXCLAMATION); 
              break; 
            } 
 
            // Create the output file RIFF chunk of form type WAVE. 
 
            ckOutRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E'); 
            ckOutRIFF.cksize  = 0; 
             
            if (mmioCreateChunk(hmmioOut, &ckOutRIFF, MMIO_CREATERIFF) 
  		          != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Initialize the WAVEFORMATEX structure 
 
	          pwf.nChannels = audioChannels; 
    	      pwf.nSamplesPerSec = samplesPerSecond; 
    	      pwf.nAvgBytesPerSec = bytesPerSecond; 
    	      pwf.nBlockAlign = sampleAlignment; 
    	      pwf.wBitsPerSample = bitsPerSample; 
            pwf.wFormatTag      = WAVE_FORMAT_PCM; 
            pwf.cbSize          = 0; 
 
            // Create the fmt chunk 
 
            ckOut.ckid = mmioFOURCC('f', 'm', 't', ' '); 
            ckOut.cksize = sizeof(pwf); 
 
            if (mmioCreateChunk(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Write the WAVEFORMATEX structure to the fmt chunk. 
 
            if (mmioWrite(hmmioOut, (HPSTR) &pwf, sizeof(pwf)) 
                != sizeof(pwf)) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Ascend out of the fmt chunk, back into the RIFF chunk. 
 
            if (mmioAscend(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Create the data chunk that holds the waveform samples. 
 
            ckOut.ckid   = mmioFOURCC('d', 'a', 't', 'a'); 
            ckOut.cksize = 0; 
             
            if (mmioCreateChunk(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            mmioGetInfo(hmmioOut, &mmioinfoOut, 0); 
 
            setMessageCount(); 
        		answerReplay(); 
 
						answerPlayPos = msgTable[0]; 
            sfp = msgTable[currentMessage]; 
        		replaying = TRUE; 
        		firstPacket = TRUE; 
					   
            while((answerRead(&IPaddr, &t, hostName, &ebuf))) 
            {  
		        		  firstPacket = FALSE; 
                  // Decompress and/or decrypt packet 
							    decodeSound(NULL, &ebuf, aboutOutBits, aboutOutSamples, 
                              &pcmdata, &dwPCMBytes); 
                   
                  // Write packet to file. 
                  for (write_pos = 0; write_pos < dwPCMBytes; write_pos++) 
                  { 
 
  	                // Check if we are at the end of the output buffer. 
                    // If so, flush it. 
	                  if (mmioinfoOut.pchNext == mmioinfoOut.pchEndWrite) 
	                  { 
                      mmioinfoOut.dwFlags |= MMIO_DIRTY; 
 
                      if (mmioAdvance(hmmioOut, &mmioinfoOut, MMIO_WRITE) 
                          != MMSYSERR_NOERROR) 
                      { 
                        MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
                        mmioClose(hmmioOut, 0); 
                        break; 
                      } 
 
	                  } 
 
                    // Copy one byte 
	                  *mmioinfoOut.pchNext++ = pcmdata[write_pos]; 
                  } 
 
                  // Free up the PCM buffer. 
                  GlobalFreePtr(pcmdata); 
            } 
             
            answerPlayPos = sfp; 
				    replaying = FALSE; 
				    answerReplayDone(); 
 
	          // Mark the current chunk as dirty and flush it 
            mmioinfoOut.dwFlags |= MMIO_DIRTY; 
            if (mmioSetInfo(hmmioOut, &mmioinfoOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Ascend out of data chunk 
            if (mmioAscend(hmmioOut, &ckOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Ascend out of RIFF chunk 
            if (mmioAscend(hmmioOut, &ckOutRIFF, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
 
            // Close the file 
            if (mmioClose(hmmioOut, 0) != MMSYSERR_NOERROR) 
            { 
              MessageBox(NULL, rstring(IDS_T_WRITE_FILE_ERR), NULL, MB_OK | MB_ICONEXCLAMATION); 
              mmioClose(hmmioOut, 0); 
              break; 
            } 
             
            SetCursor(LoadCursor(NULL, IDC_ARROW)); 
          } 
          break; 
        } 
           
		    	case IDOK: 
		    		answerRecord = IsDlgButtonChecked(hwnd, IDC_RP_RECORD); 
					PostMessage(hwnd, WM_CLOSE, 0, 0L); 
		        	break; 
		        	 
                case ID_HELP: 
                	WinHelp(hwndMDIFrame, rstring(IDS_HELPFILE), HELP_KEY, 
                				((DWORD) (Lrstring(IDS_HELP_ANSWER)))); 
                	holped = TRUE; 
                	break; 
		    } 
        	return FALSE; 
	    	 
	    case WM_DESTROY: 
	    	if (replaying) { 
	    		KillTimer(hwnd, 5); 
	    	} 
	    	if (msgTable != NULL) { 
	    		GlobalFreePtr(msgTable); 
	    		msgTable = NULL; 
	    	} 
	    	hDlgAnswer = NULL; 
	    	return 0; 
		        	 
        case WM_TIMER: 
			{ 
				struct in_addr IPaddr; 
				char hostName[MAX_HOST]; 
				time_t t; 
				DWORD startTicks = GetTickCount(); 
				long et, sfp; 
				int ateof = FALSE; 
        				 
				if (replaying) { 
					sfp = answerPlayPos; 
    				if (answerRead(&IPaddr, &t, hostName, &ebuf)) { 
    					if (firstPacket || !(ebuf.compression & fAnsNewMsg)) {  
		        			firstPacket = FALSE; 
							playSound(hwndMDIFrame, NULL, &ebuf, aboutOutBits, aboutOutSamples); 
	                         
	                        if (!hostShown) { 
		    					char ft[24]; 
		    					struct tm *lt; 
                                 
								//	Update host when definitive name seen 
								if (hostName[0] != '(') { 
									hostShown = TRUE; 
									hostPrelim = FALSE; 
								} 
								 
                                if (!hostPrelim) { 
				        			lt = localtime(&t);		 
			    				    sprintf(ft, Format(49), rstring(IDS_WEEKDAYS + lt->tm_wday), 
			    				    	lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, 
			    				    	lt->tm_hour, lt->tm_min, lt->tm_sec);  
			    					SetDlgItemText(hwnd, IDC_RP_TIME, ft); 
									SetDlgItemText(hwnd, IDC_RP_SITE, hostName); 
									hostPrelim = TRUE; 
								} 
							} 
							 
				            /* The following code is needed because when we're reading 
				               sound from a file, as opposed to receiving it in real 
				               time from the CODEC, we must meter out the samples 
				               at the rate they will actually be played by the destination 
				               machine.  For 8000 samples per second, this amounts 
				               to 125 microseconds per sample. */ 
				 
#define kOverhead 30000L 
				            et = ((ebuf.buffer.buffer_len * 125L) - kOverhead) - 
				            	((GetTickCount() - startTicks) * 1000); 
				            if (et <= 0) { 
				            	et = 1; 
				            } 
				            SetTimer(hwnd, 5, (UINT) (et / 1000), NULL); 
				        } else { 
				        	answerPlayPos = sfp; 
				        	replaying = FALSE; 
				        } 
    				} else { 
    					replaying = FALSE; 
    					ateof = TRUE; 
    				}	        				 
				} 
				if (!replaying) { 
        answerReplayDone(); 
					KillTimer(hwnd, 5); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_PREV), currentMessage > 0); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_NEXT), !ateof); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_REPLAY), currentMessage >= 0); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_REWIND), TRUE); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_ERASE), TRUE); 
					EnableWindow(GetDlgItem(hwnd, IDC_RP_BROWSE), TRUE); 
        	EnableWindow(GetDlgItem(hwnd, IDC_RP_SAVE), currentMessage >= 0); 
					 
					/*	Restore focus to the button we pushed, or the logical 
						successor if it isn't enabled any more.  */ 
					 
					if (buttonPushed != 0 && !IsWindowEnabled(GetDlgItem(hwnd, buttonPushed))) { 
						if (IsWindowEnabled(GetDlgItem(hwnd, IDC_RP_NEXT))) { 
							buttonPushed = IDC_RP_NEXT;  
						} else if (IsWindowEnabled(GetDlgItem(hwnd, IDC_RP_PREV))) { 
							buttonPushed = IDC_RP_PREV;  
						} else if (IsWindowEnabled(GetDlgItem(hwnd, IDC_RP_REPLAY))) { 
							buttonPushed = IDC_RP_REPLAY;  
						} else { 
							buttonPushed = IDOK; 
						}   
					} 
					SetFocus(GetDlgItem(hwnd, buttonPushed)); 
				} 
			} 
        	break; 
       
        default: 
        	if (nMessage == fileOpenHelpButton && fileHelpKey != NULL) { 
            	WinHelp(hwndMDIFrame, rstring(IDS_HELPFILE), HELP_KEY, 
            				((DWORD) (LPSTR) fileHelpKey)); 
            	holped = TRUE; 
        	} 
        	break;	    	 
    } 
    return FALSE; 
} 
 
//	ANSWERDIALOGUE  --  Answering machine dialogue 
 
VOID answerDialogue(HWND hwndParent) 
{ 
    CreateDialog(hInst, MAKEINTRESOURCE(IDD_REPONDEUR), 
    			 hwndParent, answerDlgProc); 
}