/**************************************************************************
* 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();
}
}