|
|
/*******************************************************************************
Module Name:
work.cpp
Abstract:
Implements main function of the bridge test application
Author:
Qianbo Huai (qhuai) Jan 27 2000
*******************************************************************************/
#include "stdafx.h"
// command line
LPSTR glpCmdLine = NULL;
// dialog
HWND ghDlg = NULL;
// true: exit button on dialog was clicked
bool gfExitButton = false;
// bridge
CBridgeApp *gpBridgeApp = NULL;
// callback func in dialog
BOOL CALLBACK MainDialogProc ( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
// func to deal with TAPI events
HRESULT OnTapiEvent ( TAPI_EVENT TapiEvent, IDispatch *pEvent );
HRESULT OnPrivateEvent (IDispatch *pEvent);
// set status message on dialog
void SetStatusMessage (LPWSTR pszMessage); void DoMessage (LPWSTR pszMessage); void EnableDisconnectButton (BOOL fYes);
/*//////////////////////////////////////////////////////////////////////////////
WinMain ////*/
int WINAPI WinMain ( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd ) { // init com
if (FAILED (CoInitializeEx(NULL, COINIT_MULTITHREADED))) return 0;
// init debug
BGLOGREGISTER (L"work");
// keep command line which determines which SDP to join
glpCmdLine = lpCmdLine;
// init CBridgeApp
HRESULT hr; gpBridgeApp = new CBridgeApp (&hr); if (gpBridgeApp==NULL || FAILED (hr)) { LOG ((BG_ERROR, "Failed to init CBridgeApp")); return 0; } // start dialog box
if (!DialogBox (hInst, MAKEINTRESOURCE(IDD_MAINDLG), NULL, MainDialogProc)) { LOG ((BG_TRACE, "Dialog ends")); }
// dialog finished
delete gpBridgeApp;
BGLOGDEREGISTER (); CoUninitialize ();
return 1; }
/*//////////////////////////////////////////////////////////////////////////////
Callback for dialog ////*/
BOOL CALLBACK MainDialogProc ( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { ghDlg = hDlg; EnableDisconnectButton (false); return 0; } case WM_PRIVATETAPIEVENT: { OnTapiEvent ((TAPI_EVENT)wParam, (IDispatch *)lParam); return 0; } case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_EXIT: { gfExitButton = true; gpBridgeApp->DisconnectAllCalls (DC_NORMAL);
// check if in connection
if (!IsWindowEnabled (GetDlgItem (ghDlg, IDC_DISCONNECT))) { // not in connection
EndDialog (ghDlg, 0); } // else
// remember exit button is clicked
// do not call EndDialog because a disconnected event is to come
return 1; } case IDC_DISCONNECT: { gpBridgeApp->DisconnectAllCalls (DC_NORMAL);
// disable disconnect button
EnableDisconnectButton (false); return 1; } } case IDC_NEXTSUBSTREAM: { gpBridgeApp->NextSubStream (); return 1; }
return 0; } default: return 0; } }
/*//////////////////////////////////////////////////////////////////////////////
Deals with TAPI events ////*/
HRESULT OnTapiEvent ( TAPI_EVENT TapiEvent, IDispatch *pEvent ) { HRESULT hr = S_OK;
// LOGEvent ((BG_TE, TapiEvent));
switch (TapiEvent) { case TE_CALLNOTIFICATION: { if (BST_CHECKED != IsDlgButtonChecked (ghDlg, IDC_REJECT)) { // if h323 call and to us, init h323 call
if (FAILED (hr = gpBridgeApp->CreateH323Call (pEvent))); LOG ((BG_ERROR, "Failed to create h323 call, %x", hr)); } break; } case TE_CALLSTATE: { CALL_STATE cs; ITCallStateEvent *pCallStateEvent = NULL;
// get call state event
hr = pEvent->QueryInterface ( IID_ITCallStateEvent, (void **)&pCallStateEvent ); if (FAILED(hr)) break;
// get call state
hr = pCallStateEvent->get_State (&cs); pCallStateEvent->Release (); if (FAILED(hr)) break;
// LOGEvent ((BG_CS, cs));
// if offering, connect
if (CS_OFFERING == cs) { CBridgeItem *pItem = NULL;
// check if h323 call created successful
hr = gpBridgeApp->HasH323Call (pEvent, &pItem); if (S_OK != hr || NULL == pItem) { LOG ((BG_ERROR, "Failed to check h323 call, %x", hr)); hr = S_OK; break; }
// create sdp call
if (FAILED (hr = gpBridgeApp->CreateSDPCall (pItem))) { gpBridgeApp->DisconnectCall (pItem, DC_REJECTED);
// delete pItem;
LOG ((BG_ERROR, "Failed to create SDP call, %x", hr)); break; }
// bridge call
if (FAILED (hr = gpBridgeApp->BridgeCalls (pItem))) { gpBridgeApp->DisconnectCall (pItem, DC_REJECTED);
// delete pItem;
LOG ((BG_ERROR, "Failed to bridge calls, %x", hr)); break; }
// enable disconnect button
EnableDisconnectButton (true); } // if disconnect
else if (CS_DISCONNECTED == cs) { CBridgeItem *pItem = NULL;
// check if h323 call created successful
hr = gpBridgeApp->HasH323Call (pEvent, &pItem); if (S_OK == hr && NULL != pItem) { // the call already disconnected
// call disconnect here only to remove pItem from the list
gpBridgeApp->RemoveCall (pItem); delete pItem; }
// if exit button is clicked and all call disconnected
if (gfExitButton) { if (S_OK != gpBridgeApp->HasCalls ()) EndDialog (ghDlg, 0); } else { if (S_OK != gpBridgeApp->HasCalls ()) EnableDisconnectButton (false); } } break; } case TE_CALLMEDIA: { CALL_MEDIA_EVENT cme; ITCallMediaEvent *pCallMediaEvent;
// get call media event
hr = pEvent->QueryInterface ( IID_ITCallMediaEvent, (void **)&pCallMediaEvent ); if (FAILED(hr)) break;
// get the event
hr = pCallMediaEvent->get_Event (&cme); if (FAILED(hr)) break;
// LOGEvent ((BG_CME, cme));
// check media event
switch (cme) { case CME_STREAM_FAIL: hr = E_FAIL; LOG ((BG_ERROR, "Stream failed")); break; case CME_TERMINAL_FAIL: hr = E_FAIL; LOG ((BG_ERROR, "Terminal failed")); break; default: break; }
// we no longer need this interface.
pCallMediaEvent->Release(); break; } case TE_PRIVATE: hr = OnPrivateEvent (pEvent); break; default: break; }
pEvent->Release(); // we addrefed it CTAPIEventNotification::Event()
return hr; }
/*//////////////////////////////////////////////////////////////////////////////
////*/
HRESULT OnPrivateEvent ( IDispatch *pEvent ) { ENTER_FUNCTION ("OnPrivateEvent"); // LOG ((BG_TRACE, "%s entered", __fxName));
HRESULT hr = S_OK;
ITPrivateEvent *pPrivateEvent = NULL; IDispatch *pDispatch = NULL; ITParticipantEvent *pPartEvent = NULL; ITParticipant *pParticipant = NULL; PARTICIPANT_EVENT event;
ITCallInfo *pCallInfo = NULL; ITBasicCallControl *pCallControl = NULL;
// get private event interface
if (FAILED (hr = pEvent->QueryInterface (&pPrivateEvent))) { LOG ((BG_ERROR, "%s failed to query ITPrivateEvent", __fxName)); return hr; }
// get event interface
if (FAILED (hr = pPrivateEvent->get_EventInterface (&pDispatch))) { LOG ((BG_ERROR, "%s failed to query event interface", __fxName)); goto Error; }
// get participant event interface
hr = pDispatch->QueryInterface (&pPartEvent); pDispatch->Release (); pDispatch = NULL;
if (FAILED (hr)) { LOG ((BG_ERROR, "%s failed to query participant interface", __fxName)); goto Error; }
// get event
if (FAILED (hr = pPartEvent->get_Event (&event))) { LOG ((BG_ERROR, "%s failed to get event", __fxName)); goto Error; }
// LOGEvent ((BG_PE, event));
// check the event
switch (event) { case PE_PARTICIPANT_ACTIVE: { // get call info
if (FAILED (hr = pPrivateEvent->get_Call (&pCallInfo))) { LOG ((BG_ERROR, "%s failed to get call info", __fxName)); goto Error; }
// get call control
if (FAILED (hr = pCallInfo->QueryInterface (&pCallControl))) { LOG ((BG_ERROR, "%s failed to get call control", __fxName)); goto Error; }
// get participant interface
if (FAILED (hr = pPartEvent->get_Participant (&pParticipant))) { LOG ((BG_ERROR, "%s failed to get participant", __fxName)); goto Error; }
// show participant
hr = gpBridgeApp->ShowParticipant (pCallControl, pParticipant); if (FAILED (hr)) { LOG ((BG_ERROR, "%s failed to show participant, %x", __fxName, hr)); }
if (S_FALSE == hr) { hr = S_OK; // *ppszMessage = L"Participant active but call not found in list";
// or no substream found on the stream
} } break; default: break;
} Cleanup: if (pCallInfo) pCallInfo->Release (); if (pCallControl) pCallControl->Release (); if (pPrivateEvent) pPrivateEvent->Release (); if (pPartEvent) pPartEvent->Release (); if (pParticipant) pParticipant->Release ();
// LOG ((BG_TRACE, "%s exits", __fxName));
return hr;
Error: goto Cleanup; }
/*//////////////////////////////////////////////////////////////////////////////
Popup message box ////*/
WCHAR gMsgBoxTitle[] = L"TAPI 3.0 Bridge Test Application";
void DoMessage (LPWSTR pszMessage) { #if POPUP_MESSAGE
MessageBox ( ghDlg, pszMessage, gMsgBoxTitle, MB_OK ); #endif
}
/*//////////////////////////////////////////////////////////////////////////////
Status message ////*/
void SetStatusMessage (LPWSTR pszMessage) { SetDlgItemText (ghDlg, IDC_STATUS, pszMessage); }
/*//////////////////////////////////////////////////////////////////////////////
////*/
void EnableDisconnectButton (BOOL fYes) { if (fYes) { // enable
SetStatusMessage (L"Bridging calls ...");
SendDlgItemMessage ( ghDlg, IDC_NEXTSUBSTREAM, BM_SETSTYLE, BS_DEFPUSHBUTTON, 0 ); SendDlgItemMessage ( ghDlg, IDC_DISCONNECT, BM_SETSTYLE, BS_DEFPUSHBUTTON, 0 ); EnableWindow ( GetDlgItem (ghDlg, IDC_NEXTSUBSTREAM), TRUE ); EnableWindow ( GetDlgItem (ghDlg, IDC_DISCONNECT), TRUE ); SetFocus (GetDlgItem (ghDlg, IDC_DISCONNECT)); } else { // disable
SetStatusMessage (L"Waiting for calls ...");
SendDlgItemMessage ( ghDlg, IDC_NEXTSUBSTREAM, BM_SETSTYLE, BS_PUSHBUTTON, 0 ); SendDlgItemMessage ( ghDlg, IDC_DISCONNECT, BM_SETSTYLE, BS_PUSHBUTTON, 0 ); EnableWindow ( GetDlgItem (ghDlg, IDC_NEXTSUBSTREAM), FALSE ); EnableWindow ( GetDlgItem (ghDlg, IDC_DISCONNECT), FALSE ); } }
|