Click here to Skip to main content
15,897,518 members
Articles / Desktop Programming / MFC

A Simple Prototype for Demonstration of Voice Communication via Network/Internet

Rate me:
Please Sign up or sign in to vote.
4.35/5 (24 votes)
14 Jun 2000 204.3K   8.4K   102  
Voice communication
/**************************************************************************
 *    file:         talkclientDlg.cpp                                     *
 *    create:       June 9, 2000                                          *
 *    copyright:    @ 2000, by Zhaohui Xing                               *
 *    e-mail:       xinghh@yahoo.com                                      * 
 *    description:  implementation of CTalkclientDlg class                *
 **************************************************************************/
#include "stdafx.h"
#include "talkclient.h"
#include "talkclientDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/**************************************************************************
 *                                                                        *
 * CAboutDlg dialog used for App About                                    *
 *                                                                        *
 **************************************************************************/
class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/**************************************************************************
 *                                                                        *
 * CTalkclientDlg dialog                                                  *
 *                                                                        *
 **************************************************************************/
CTalkclientDlg::CTalkclientDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTalkclientDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTalkclientDlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_strUserName = _T("");
	m_strServer = _T("");
	m_bVoiceTalk = FALSE;
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_bConnect = FALSE;
    m_bTalking = FALSE;
	memset(m_lpPeerName, 0, 16);

	m_bVoiceMsg = FALSE;
	m_uiBufLen = VT_MAX;
	m_iWaveFormat = VT_WAVE1M08;
}

void CTalkclientDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTalkclientDlg)
	DDX_Control(pDX, IDC_BTNCONNECT, m_btnConnect);
	DDX_Control(pDX, IDC_BTNSEND, m_btnSendTxtMsg);
	DDX_Control(pDX, IDC_CHKVOICE, m_chkVoice);
	DDX_Control(pDX, IDC_EDITNAME, m_editUserName);
	DDX_Control(pDX, IDC_EDITSERVER, m_editServer);
	DDX_Control(pDX, IDC_EDITRECV, m_TextRecv);
	DDX_Control(pDX, IDC_EDITSEND, m_TextSend);
	DDX_Control(pDX, IDC_COMBPROT, m_ComBoProts);
	DDX_Control(pDX, IDC_COMBCHATTER, m_ComBoTalker);
	DDX_Control(pDX, IDC_SENDMETER, m_progctrlSend);
	DDX_Control(pDX, IDC_RECVMETER, m_progctrlRecv);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CTalkclientDlg, CDialog)
	//{{AFX_MSG_MAP(CTalkclientDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
    ON_MESSAGE(VTM_DATAREADY, OnVTDataReady)
    ON_MESSAGE(VTM_READYFORWRITE, OnVTReadyForWrite)
    ON_MESSAGE(MM_WIM_DATA, OnRecordEvent)
    ON_MESSAGE(MM_WOM_DONE, OnPlayEvent)
	ON_EN_CHANGE(IDC_EDITNAME, OnChangeEditname)
	ON_EN_CHANGE(IDC_EDITSERVER, OnChangeEditserver)
	ON_CBN_SELCHANGE(IDC_COMBPROT, OnSelchangeCombprot)
	ON_CBN_SELCHANGE(IDC_COMBCHATTER, OnSelchangeCombchatter)
	ON_BN_CLICKED(IDC_BTNCONNECT, OnBtnconnect)
	ON_BN_CLICKED(IDC_BTNDISCONNECT, OnBtndisconnect)
	ON_BN_CLICKED(IDC_BTNSEND, OnBtnsend)
	ON_BN_CLICKED(IDC_CHKVOICE, OnChkvoice)
	ON_WM_CLOSE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/**************************************************************************
 *                                                                        *
 * CTalkclientDlg message handlers                                        *
 *                                                                        *
 **************************************************************************/

/**************************************************************************
 *  Initialize the dialogbox                                              *
 **************************************************************************/
BOOL CTalkclientDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here

	// Initialize the edit boxes and combo-boxes
    m_ComBoTalker.ResetContent();
	m_ComBoProts.ResetContent();
	m_editUserName.LimitText(15);
	m_progctrlSend.SetRange(0, 1);
	m_progctrlRecv.SetRange(0, 1);
	m_progctrlSend.SetPos(0);
	m_progctrlRecv.SetPos(0);
	

	// Check version data and load winsock dll
    WORD      wVersionRequested;
    WSADATA   wsaData;
    char      outtext[128];
    int       iLoop;

    wVersionRequested = MAKEWORD(1,1);
    if (WSAStartup(wVersionRequested, &wsaData) != 0)
    {
        return FALSE;
    }

	// Check compatible network protocols
	if(!InitProtocols())
		return FALSE;
	
	// Add compatible protocol to protocol combo-box
	for(iLoop = 0; iLoop < m_iNumWorkProts; iLoop++)
    {
		wsprintf(outtext, "%2d: %s", iLoop, 
			     m_lpProtBuf[m_iWorkProts[iLoop]].lpProtocol);
		m_ComBoProts.InsertString(-1, outtext); 
	}

	// Set the controls status
	DoConnection(FALSE);

	// Initialize the wave I/O device
	m_bVoiceMsg = FALSE;
    m_vtPlay.SetHwnd(GetSafeHwnd());
    m_vtPlay.SetVTWaveFormat(m_iWaveFormat);
    m_vtPlay.AllocMemory();

	m_vtRecord.SetHwnd(GetSafeHwnd());
    m_vtRecord.SetVTWaveFormat(m_iWaveFormat);
	m_vtRecord.AllocMemory();
    
	// return TRUE  unless you set the focus to a control
	return TRUE;  
}


/**************************************************************************
 * Dialog box closed                                                      *
 **************************************************************************/
void CTalkclientDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default

	// Clean the combo-boxes
    m_ComBoTalker.ResetContent();
	m_ComBoProts.ResetContent();

	// Close and clean the socket
    closesocket(m_MySock.m_hSock);
    WSACleanup();
	
	
	// Close the wave I/O device and
	// Clean the wave I/O buffers
    if(m_bVoiceMsg)
       m_vtPlay.StopPlay();
	if(m_bVoiceTalk)
       m_vtRecord.StopRecord();
	
	m_vtPlay.CleanMemory(); 
    m_vtRecord.CleanMemory();

	CDialog::OnClose();
}


/**************************************************************************
 * System menu commands                                                   *
 **************************************************************************/
void CTalkclientDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}


/**************************************************************************
 * Paint function                                                         *
 * If you add a minimize button to your dialog, you will need the code    *
 * below to draw the icon.  For MFC applications using the document/view  *
 * model, this is automatically done for you by the framework.            *
 **************************************************************************/
void CTalkclientDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

/**************************************************************************
 * The system calls this to obtain the cursor to display while the user   *
 * drags the minimized window.                                            *
 **************************************************************************/
HCURSOR CTalkclientDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}


/**************************************************************************
 * Check compatible network protocols                                     *
 **************************************************************************/
BOOL CTalkclientDlg::InitProtocols(void)
{
    int      numStrucs;
    int      index;
    unsigned long  iProtBufSize = 0;

	// Call EnumProtocols with NULL buffer in order 
	// to determine size of buffer required
	EnumProtocols(NULL, NULL, &iProtBufSize);

	// Allocate buffer to protocol information structure
    if((m_lpProtBuf = (LPPROTOCOL_INFO)VirtualAlloc(NULL,
                                         iProtBufSize,
                                         MEM_COMMIT,
                                         PAGE_READWRITE)) == NULL)
    {
        // ERROR -- abort
		AfxMessageBox("Failed to allocate memory for m_lpProtBuf!");
        return FALSE;
    }

    // Calling EnumProtocols with large enough buffer
    if((numStrucs = EnumProtocols(NULL, 
		                           m_lpProtBuf, 
								   &iProtBufSize)) == SOCKET_ERROR)
    {
        // Error -- abort
		AfxMessageBox("Failed to numerate protocol!");
        return FALSE;
    }

	// Add every connection oriented protocol to protocol combo box
	m_iNumWorkProts = 0;
    for(index = 0; index < numStrucs; index++)
    {
        if((m_lpProtBuf[index].dwServiceFlags & XP_CONNECTIONLESS) == 0)
        {
			// Keep track of workable protocols
            m_iWorkProts[m_iNumWorkProts++] = index; 
        }
    }

	// OK
	return TRUE;
}


/**************************************************************************
 * Intialize the different protocol sockets                               *
 **************************************************************************/
BOOL CTalkclientDlg::InitSockets(int iProtIndex)
{
    int numStrucs;
    GUID guidNW = SVCID_NETWARE(VT_NETID);    // Generate GUID for Novel prot
    GUID guidDNS = SVCID_TCP(VT_DNSID);       // Generate GUID for DNS
	char strServName[128];
    char outtext[128];


	// Check the protocol type
    switch(m_lpProtBuf[iProtIndex].iAddressFamily)
    {
        case AF_IPX:
		    //  SAP/Bindery Name Space
		    m_dwCSABufsize = sizeof(m_CSABuf);
            numStrucs = GetAddressByName(0, 
                                         &guidNW, 
                                         "VOICE_TALK_SERVER_IPX", 
                                         NULL, 
                                         RES_FIND_MULTIPLE, 
                                         NULL, 
                                         m_CSABuf,
                                         &m_dwCSABufsize, 
                                         NULL,  
                                         NULL);
			
            if((numStrucs == SOCKET_ERROR) || (numStrucs == 0))
            {
                // Error -- try another protocol.  We've got lots!
                AfxMessageBox("Server not found.  Try a different protocol");
                return FALSE;
            }
            break;
        case AF_INET:
            //  DNS Name Space
            // Static Name Space requires us to specify the host name
		    m_dwCSABufsize = sizeof(m_CSABuf);
            strcpy(strServName, m_strServer);
            numStrucs = GetAddressByName(0, 
                                         &guidDNS, 
                                         strServName, 
                                         NULL, 
                                         RES_FIND_MULTIPLE, 
                                         NULL, 
                                         m_CSABuf,
                                         &m_dwCSABufsize, 
                                         NULL,  
                                         NULL);

            if((numStrucs == SOCKET_ERROR) || (numStrucs == 0))
            {
                // Error -- try another protocol.  We've got lots!
                AfxMessageBox("Server not found.  Try a different protocol");
                return FALSE;
            }
            break;

        case AF_NETBIOS:
			// NetBIOS name space???
		    
            // no netbios name space provider so fill in lpCSABuf ourselves
            numStrucs = 1;
            m_CSABuf[0].iSocketType = m_lpProtBuf[iProtIndex].iSocketType;
            m_CSABuf[0].iProtocol = m_lpProtBuf[iProtIndex].iProtocol;

            SET_NETBIOS_SOCKADDR(&m_NBAddr,
                                 NETBIOS_GROUP_NAME,
                                 "VOICE_TALK_SERVER_NETBIOS",
                                 0);
	        m_CSABuf[0].RemoteAddr.lpSockaddr = (LPSOCKADDR)&m_NBAddr;
			m_CSABuf[0].RemoteAddr.iSockaddrLength = sizeof(m_NBAddr);
            break;

        default:
		    // We don't support anything else
            AfxMessageBox("Name Space not supported over this protocol family. \
				          Try a different protocol");
            return FALSE;
    }

	// Set SOCK data
	m_MySock.m_iSockType = m_lpProtBuf[iProtIndex].iSocketType;
	m_MySock.m_iProtocol = m_lpProtBuf[iProtIndex].iProtocol; 

	// Call socket() using triple provided by EnumProtocols()
    if((m_MySock.m_hSock = socket(m_lpProtBuf[iProtIndex].iAddressFamily,
                             m_lpProtBuf[iProtIndex].iSocketType,
                             m_lpProtBuf[iProtIndex].iProtocol)) 
							 == INVALID_SOCKET)
    {
        // ERROR
        wsprintf(outtext, "Failure: socket() returned %u", WSAGetLastError());
		AfxMessageBox(outtext);
        return FALSE;
    }

	// Call connect() using info from GetAddressByName()
    if(connect(m_MySock.m_hSock,
                m_CSABuf[0].RemoteAddr.lpSockaddr,
                m_CSABuf[0].RemoteAddr.iSockaddrLength) 
				== SOCKET_ERROR)
    {
        // ERROR
        wsprintf(outtext, "Failure: connect() returned %u", WSAGetLastError());
		AfxMessageBox(outtext);
        return FALSE;
    }

	// Specify message to signal accepted socket
    if(WSAAsyncSelect(m_MySock.m_hSock, 
		               GetSafeHwnd(), 
		               VTM_READYFORWRITE, 
					   FD_WRITE) == SOCKET_ERROR)
    {
        wsprintf(outtext, "Failure: WSAAsyncSelect() returned %u", WSAGetLastError());
		AfxMessageBox(outtext);
        return FALSE;
    }


	return TRUE;
}


/**************************************************************************
 * Set dialogbox status in connection/disconnection                       *
 **************************************************************************/
void CTalkclientDlg::DoConnection(BOOL bTrue)
{
	m_bConnect = bTrue;

	// Connection
	if(bTrue)
	{
		// Reset the talker list
        m_ComBoTalker.ResetContent();
		m_ComBoTalker.InsertString(0, "No one to talk");

		// Reset socket working status
		if(WSAAsyncSelect(m_MySock.m_hSock, 
			              GetSafeHwnd(),
						  VTM_DATAREADY, 
						  FD_READ | FD_CLOSE) == SOCKET_ERROR)
		{
            // ERROR  do something
			AfxMessageBox("Failure: WSAAsyncSelect() to get online users!");
			return;
		}
	}
	else // disconnection
	{
		// Close socket
        closesocket(m_MySock.m_hSock);

		// Reset the edit boxes, combo-boxes, etc.
        m_ComBoTalker.ResetContent();
		m_ComBoTalker.InsertString(0, "No one to talk");
		m_chkVoice.SetCheck(0);
		m_bVoiceMsg = FALSE;
	    m_progctrlSend.SetPos(0);
	    m_progctrlRecv.SetPos(0);
	}

	// Enable/Disable various buttons, edit boxes
	m_btnConnect.EnableWindow(!bTrue);
	m_editUserName.EnableWindow(!bTrue);
	m_editServer.EnableWindow(!bTrue);
	m_ComBoProts.EnableWindow(!bTrue);

	// If disconnected
	if(!bTrue)
	{
		// Reset flags and controls
		EnableTalking(FALSE);
        
		// Close wave I/O devices
		if(m_bVoiceMsg)
           m_vtPlay.StopPlay();
	
	    if(m_bVoiceTalk)
           m_vtRecord.StopRecord();
	}
}


/**************************************************************************
 * Set communication status flags and controls                            *
 **************************************************************************/
void CTalkclientDlg::EnableTalking(BOOL bTrue)
{
    char sShowText[128];
    int  iIndex;

	// Set communication flag
	m_bTalking = bTrue;
	
	// Set graphic controls status
	m_btnSendTxtMsg.EnableWindow(bTrue);
	m_chkVoice.EnableWindow(bTrue);
	m_progctrlSend.EnableWindow(bTrue);
	m_progctrlRecv.EnableWindow(bTrue);

	// Set talker list and dialog title bar
	if(bTrue)
	{
        wsprintf(sShowText, "%s: in talking with %s", m_MySock.m_sUserName, \
			     m_lpPeerName);
        
	    iIndex = m_ComBoTalker.FindString(0, m_lpPeerName);
		m_ComBoTalker.SetCurSel(iIndex); 
	}
	else
	{
		if(lstrlen(m_MySock.m_sUserName) > 0)
		    wsprintf(sShowText, "%s: free", m_MySock.m_sUserName);
		else
            wsprintf(sShowText, "Voice Talk Client");
	}

	SetWindowText(sShowText);
}


/**************************************************************************
 * Parse the content in the receiving message                             *
 **************************************************************************/
void CTalkclientDlg::ParseMsgData(void)
{
	CString           strRecv;
	
	// Check message type
	switch(m_vtRecvMsgBuf.m_ucMsgType)
	{
	    case VT_TEXT:  // Text
			 // Stop voice communication
			 if(m_bVoiceMsg)
			 {
			     m_bVoiceMsg = FALSE;
                 m_vtPlay.StopPlay();
	             m_progctrlRecv.SetPos(0);
			 }		 

			 // Put text message to the edit box
			 strRecv = (char*)(m_vtRecvMsgBuf.m_pData);
			 m_TextRecv.SetWindowText(strRecv);
			 return;
        case VT_WAVE1M08:   // Voice message
        case VT_WAVE1S08:
        case VT_WAVE1M16:
        case VT_WAVE1S16:
        case VT_WAVE2M08:
        case VT_WAVE2S08:
        case VT_WAVE2M16:
        case VT_WAVE2S16:
        case VT_WAVE4M08:
        case VT_WAVE4S08:
        case VT_WAVE4M16:
        case VT_WAVE4S16:
			 // Reset the indicatior
             m_progctrlRecv.SetPos(1);
			 // Get wave data buffer size 
			 m_uiBufLen = m_vtRecvMsgBuf.m_lLength - SIZEVTMSGHDR;
			 // Copy wave data buffer 
		     memcpy((void*)m_pWaveData, (void*)m_vtRecvMsgBuf.m_pData,
                    m_uiBufLen);
			 if(!m_bVoiceMsg)
			 {
				 // Set wave data to output device and play it
			     m_bVoiceMsg = TRUE;
				 m_vtPlay.SetPlayData(m_pWaveData, m_uiBufLen);  
                 m_vtPlay.StartPlay();
			 }		 
			 return;
	}
}


/**************************************************************************
 * Response to the VTM_DATAREADY message                                  *
 **************************************************************************/
LONG CTalkclientDlg::OnVTDataReady(WPARAM wparam, LPARAM lparam)
{
    // If the server connection was closed
	char sPeerName[16];
	char sShowText[128];
    int  iIndex;
	int  iCount;
	
	// Clean the temperary buffers
	memset((void*)sPeerName, 0, 16);
	memset((void*)sShowText, 0, 128);

    // If get "server close" message
	if(LOWORD(lparam) == FD_CLOSE)
	{
		// Disconnect
		AfxMessageBox("Server Connection Dropped!");
		DoConnection(FALSE);
		return 1L;
	}

	// Clean the buffer for receiving message
    memset((void*)&m_vtRecvMsgBuf, 0, SIZEVTMSG);

    // Read the incoming message data
    if(!RecvVTMessage(&m_MySock, &m_vtRecvMsgBuf))
    {
		// Failed
        return 0L;
    }

    // Recieved the whole message!  
	// check the command flag
    switch(m_vtRecvMsgBuf.m_ucCmd)
    {
		// Register a talking user name
        case VTCMD_REGNAME:   
            // Add the peer name to "Talk With" combobox
	        memcpy((void*)sPeerName, (void*)m_vtRecvMsgBuf.m_pData, 
				   16*sizeof(char)); 
			iCount = m_ComBoTalker.GetCount(); 
			m_ComBoTalker.InsertString(iCount, sPeerName);
            break;

        // Deregister a talking user name
		case VTCMD_DEREGNAME:  
            // Remove name from list box
			memcpy((void*)sPeerName, (void*)m_vtRecvMsgBuf.m_pData, 
				   16*sizeof(char)); 
            iIndex = m_ComBoTalker.FindString(-1, sPeerName); 
		    if(iIndex != LB_ERR)
			{	
                // found the index to the item...delete it!
				m_ComBoTalker.DeleteString(iIndex); 
            }
            break;
        
        // Invite to join the session
		case VTCMD_REQSESSION: 
		    // Someone is asking us for a chat session
            lstrcpy(sShowText, (char*)m_vtRecvMsgBuf.m_pData);
            lstrcat(sShowText, " requests to talk.");
            if(AfxMessageBox(sShowText, MB_OKCANCEL) == IDOK)
            {
                // Save the name of the peer
                lstrcpy(m_lpPeerName, (char*)m_vtRecvMsgBuf.m_pData);
                // Send response
                memset(&m_vtSendMsgBuf, 0, SIZEVTMSG);  
				m_vtSendMsgBuf.m_ucIdentity = VT_IDENTITY;
				m_vtSendMsgBuf.m_ucCmd = VTCMD_SESSIONREQRESP;
                m_vtSendMsgBuf.m_ucMsgType = VT_TEXT;
                m_vtSendMsgBuf.m_lLength = SIZEVTMSGHDR + 2;
				m_vtSendMsgBuf.m_pData[0] = 1;
                if(SendVTMessage(m_MySock.m_hSock, &m_vtSendMsgBuf))
					EnableTalking(TRUE);
				else
                    AfxMessageBox("Can't send message to server");
                return 1L;
            }
            else
            {
                // Rejected the session request,
				// send the denial message
                memset(&m_vtSendMsgBuf, 0, SIZEVTMSG);  
				m_vtSendMsgBuf.m_ucIdentity = VT_IDENTITY;
				m_vtSendMsgBuf.m_ucCmd = VTCMD_SESSIONREQRESP;
                m_vtSendMsgBuf.m_ucMsgType = VT_TEXT;
                m_vtSendMsgBuf.m_lLength = SIZEVTMSGHDR + 2;
				m_vtSendMsgBuf.m_pData[0] = 0;
                if(SendVTMessage(m_MySock.m_hSock, &m_vtSendMsgBuf))
					EnableTalking(FALSE);
            }
            break;  // should never get here

        // Response to request
        case VTCMD_SESSIONREQRESP: 
		    // Someone responded to our session request!
            if(m_MySock.m_iStatus != VTSOCKET_REQSESSION)
            {
				// unwanted packet
                return 0L;  
            }
            if(*m_vtRecvMsgBuf.m_pData == 1)
            {
                //Acceptannce message
                EnableTalking(TRUE);
            }
            else
            {
                // Denial message
                EnableTalking(FALSE);
            }
			break;

        // Peer exit the session
        case VTCMD_SESSIONCLOSE:
			// Set dialogbox
			EnableTalking(FALSE);
			// Set socket status
            m_MySock.m_iStatus = VTSOCKET_AVAILABLE;
            wsprintf(sShowText, "%s: available for talking", m_MySock.m_sUserName);
            SetWindowText(sShowText);
			// Stop wave I/O devices
            if(m_bVoiceMsg)
                m_vtPlay.StopPlay();
	
	        if(m_bVoiceTalk)
                m_vtRecord.StopRecord();

            return FALSE;
        
        // The valid message packet
		case VTCMD_MSGDATA:	  
			// Parse the message and display it
			ParseMsgData();
            break;
		
		default:
			return 0L;
	}

	return 1L;
}


/**************************************************************************
 * Response to the VTM_READYFORWRITE message                              *
 **************************************************************************/
LONG CTalkclientDlg::OnVTReadyForWrite(WPARAM wparam, LPARAM lparam)
{
	// Clean and reset the user name
	memset((void*)m_MySock.m_sUserName, 0, 16*sizeof(char));
	strncpy(m_MySock.m_sUserName, m_strUserName, m_strUserName.GetLength()+1);
	
    // Prepare the name registration packet
    memset(&m_vtSendMsgBuf, 0, SIZEVTMSG);  
	m_vtSendMsgBuf.m_ucIdentity = VT_IDENTITY;
	m_vtSendMsgBuf.m_ucCmd = VTCMD_REGNAME;
    m_vtSendMsgBuf.m_ucMsgType = VT_TEXT;
    m_vtSendMsgBuf.m_lLength = SIZEVTMSGHDR + REALLEN(m_MySock.m_sUserName);
	memcpy((void*)m_vtSendMsgBuf.m_pData, (void*)m_MySock.m_sUserName, 
		   REALLEN(m_MySock.m_sUserName));


    // Send name registration packet
    if(SendVTMessage(m_MySock.m_hSock, &m_vtSendMsgBuf))
	{
        DoConnection(TRUE);
	}

	return 1L;
}


/**************************************************************************
 * Response to the MM_WIM_DATA (completing recording buffer) message      *
 **************************************************************************/
LONG CTalkclientDlg::OnRecordEvent(WPARAM wparam, LPARAM lparam)
{
    // Wrong status  
	if(!m_bVoiceTalk)
		return 1L;

	m_progctrlSend.SetPos(1);

	// Get WAVEHAEDER data
    WAVEHDR* lpwhdr = (WAVEHDR*)lparam;

	// Reset the voice message packet
    memset(&m_vtSendMsgBuf, 0, SIZEVTMSG);  
    m_vtSendMsgBuf.m_ucIdentity = VT_IDENTITY;
    m_vtSendMsgBuf.m_ucCmd = VTCMD_MSGDATA;
    m_vtSendMsgBuf.m_ucMsgType = m_iWaveFormat;
    m_vtSendMsgBuf.m_lLength = SIZEVTMSGHDR + lpwhdr->dwBufferLength;
	memcpy((void*)m_vtSendMsgBuf.m_pData, (void*)lpwhdr->lpData, 
		   lpwhdr->dwBufferLength);
	
	// Restart to record new sound
	m_vtRecord.ResetRecord();
	
	// Send the voice message packet
    SendVTMessage(m_MySock.m_hSock, &m_vtSendMsgBuf);

	// Reset indicator
	m_progctrlSend.SetPos(0);

	return 1L;
}


/**************************************************************************
 * Response to the MM_WOM_DONE (completing playing buffer) message        *
 **************************************************************************/
LONG CTalkclientDlg::OnPlayEvent(WPARAM wparam, LPARAM lparam)
{
    // Wrong status  
    if(!m_bVoiceMsg)
        return 0L;

	// Reset indicator
    m_progctrlRecv.SetPos(0);	
    
	// Reset playing device 
	m_vtPlay.ResetPlay();
    // Copy the new sound data to output device buffer
    m_vtPlay.SetPlayData(m_pWaveData, m_uiBufLen);  
	// Restart play sound
	m_vtPlay.RestartPlay();

	return 1L;
}


/**************************************************************************
 * Input new user name                                                    *
 **************************************************************************/
void CTalkclientDlg::OnChangeEditname() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// TODO: Add your control notification handler code here
	m_editUserName.GetWindowText(m_strUserName);
}


/**************************************************************************
 * Input new server name                                                    *
 **************************************************************************/
void CTalkclientDlg::OnChangeEditserver() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// TODO: Add your control notification handler code here
	m_editServer.GetWindowText(m_strServer);
	
}


/**************************************************************************
 * Selected the network protocol                                          *
 **************************************************************************/
void CTalkclientDlg::OnSelchangeCombprot() 
{
	// TODO: Add your control notification handler code here
    int iIndex;
    
	iIndex = m_ComBoProts.GetCurSel(); 

	if(iIndex == LB_ERR)
	{
		AfxMessageBox("An error ocurred in slecting protocols!");
		return;
	}

    // Protocol selected!  Check which one...
    switch(m_lpProtBuf[m_iWorkProts[iIndex]].iAddressFamily)
    {
       case AF_IPX:
       case AF_NETBIOS:
           // For IPX and NetBIOS, we don't need the server name
		   // so disable that edit control
		   m_editServer.SetWindowText(""); 
		   m_editServer.EnableWindow(FALSE); 
           break;

       case AF_INET:
	        // For TCP/IP we need a protocol, name, and machine name
			// in order for data to be valid
		   m_editServer.EnableWindow(TRUE); 
           break;
       default: // Nothing
		   m_editServer.SetWindowText(""); 
		   m_editServer.EnableWindow(FALSE); 
           break;
    }
}


/**************************************************************************
 * Selected the peer user                                                 *
 **************************************************************************/
void CTalkclientDlg::OnSelchangeCombchatter() 
{
	// TODO: Add your control notification handler code here
    int    iIndex;
    int    iRev;
	char   sNewPeer[16];
	
	memset(sNewPeer, 0, 16);

	iIndex = m_ComBoTalker.GetCurSel(); 

	if(iIndex == LB_ERR)
	{
		AfxMessageBox("An error ocurred in slecting peer talker");
		return;
	}

	// Exit current session
	if(iIndex == 0)
	{
		if(m_bTalking)
		{
           // Prepare the "session close " message
		   // and send it out	
           memset(&m_vtSendMsgBuf, 0, SIZEVTMSG);  
		   m_vtSendMsgBuf.m_ucIdentity = VT_IDENTITY;
		   m_vtSendMsgBuf.m_ucCmd = VTCMD_SESSIONCLOSE;
           m_vtSendMsgBuf.m_ucMsgType = VT_TEXT;
           m_vtSendMsgBuf.m_lLength = SIZEVTMSGHDR;
           if(SendVTMessage(m_MySock.m_hSock, &m_vtSendMsgBuf))
		   {
			   // Reset socket state
			   if(WSAAsyncSelect(m_MySock.m_hSock, 
				                 GetSafeHwnd(), 
								 0, 
								 0) != SOCKET_ERROR)
			   {
                   EnableTalking(FALSE);
				   return;
			   }
		   }
		}
		return;
	}
    else
	{
       // Get peer user name
	   iRev = m_ComBoTalker.GetLBText(iIndex, sNewPeer);
	   if(iRev == CB_ERR)
	   {
           AfxMessageBox("An error ocurred in getting new talker's name");
		   return;
	   }
    
	   // No change 
	   if(lstrcmp(sNewPeer, m_lpPeerName) == 0)
	   {
           return;
       }

	   // Store the new peer's name
	   lstrcpy(m_lpPeerName, sNewPeer);

	   // Prepare the "session request" message and
	   // send it out
	   m_MySock.m_iStatus = VTSOCKET_REQSESSION;
       memset(&m_vtSendMsgBuf, 0, SIZEVTMSG);  
       m_vtSendMsgBuf.m_ucIdentity = VT_IDENTITY;
	   m_vtSendMsgBuf.m_ucCmd = VTCMD_REQSESSION;
       m_vtSendMsgBuf.m_ucMsgType = VT_TEXT;
       m_vtSendMsgBuf.m_lLength = SIZEVTMSGHDR + REALLEN(sNewPeer);
	   memcpy((void*)m_vtSendMsgBuf.m_pData, (void*)sNewPeer, 
		      REALLEN(sNewPeer));

       if(SendVTMessage(m_MySock.m_hSock, &m_vtSendMsgBuf))
       {
		   // Reset the socket state
		   if(WSAAsyncSelect(m_MySock.m_hSock, 
			                 GetSafeHwnd(), 
							 VTM_DATAREADY, 
							 FD_READ | FD_CLOSE) != SOCKET_ERROR)
		   {
               EnableTalking(TRUE);
			   return;
		   }
	   }	   
	}
}


/**************************************************************************
 * Clicked the "Connect" button                                           *
 **************************************************************************/
void CTalkclientDlg::OnBtnconnect() 
{
	// TODO: Add your control notification handler code here
    int iIndex;
    
	iIndex = m_ComBoProts.GetCurSel(); 

	// No protocol selected
	if(iIndex == LB_ERR)
	{
		AfxMessageBox("Did not select a protocol!");
		return;
	}

	// No user name
	if(m_strUserName.IsEmpty())
	{
		AfxMessageBox("Did not input a user name");
		return;
	}
	
	// No server name for TCP/IP
	if(m_lpProtBuf[m_iWorkProts[iIndex]].iAddressFamily
	   == AF_INET && m_strServer.IsEmpty())
	{
		AfxMessageBox("Did not input a server name");
		return;
	}	

	// Set up socket 
	if(!InitSockets(m_iWorkProts[iIndex]))
	{
		//DoConnection(TRUE);
		AfxMessageBox("Can't bulid connection with server!");
	}
}


/**************************************************************************
 * Clicked the "Disconnect" button                                           *
 **************************************************************************/
void CTalkclientDlg::OnBtndisconnect() 
{
	// TODO: Add your control notification handler code here
	// Disconnect
	if(m_bConnect)
       DoConnection(FALSE);
}


/**************************************************************************
 * Clicked the "Send text message" button                                 *
 **************************************************************************/
void CTalkclientDlg::OnBtnsend() 
{
	// TODO: Add your control notification handler code here
	CString strSend;

	// Get text message
	m_TextSend.GetWindowText(strSend);
    
	// Prepare the text message packet
    memset(&m_vtSendMsgBuf, 0, SIZEVTMSG);  
    m_vtSendMsgBuf.m_ucIdentity = VT_IDENTITY;
    m_vtSendMsgBuf.m_ucCmd = VTCMD_MSGDATA;
    m_vtSendMsgBuf.m_ucMsgType = VT_TEXT;
    m_vtSendMsgBuf.m_lLength = SIZEVTMSGHDR + strSend.GetLength()+1;
	lstrcpy((char*)m_vtSendMsgBuf.m_pData, strSend);

	// Sen the text message packet
    SendVTMessage(m_MySock.m_hSock, &m_vtSendMsgBuf);

}


/**************************************************************************
 * Checked/Unchecked the "Voice Talk" radio button                        *
 **************************************************************************/
void CTalkclientDlg::OnChkvoice() 
{
	// TODO: Add your control notification handler code here
	// Wrong state
	if(!m_bConnect)
		return;

	// If unchecked previously
	if(!m_bVoiceTalk)
    {
		// Check it
        m_bVoiceTalk = TRUE;
		m_chkVoice.SetCheck(1); 
		// And disable "Send text message" button
		m_btnSendTxtMsg.EnableWindow(FALSE);
		// Start to reord voice message
	    m_vtRecord.StartRecord();
	}
	else // If checked previously
	{
		// Uncheck it
        m_bVoiceTalk = FALSE;
		m_chkVoice.SetCheck(0);
        // And enable "Send text message" button
		m_btnSendTxtMsg.EnableWindow(TRUE);
		// stop reording voice message
		m_vtRecord.StopRecord();
	}

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


Written By
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions