windows-nt/Source/XPSP1/NT/net/tapi/skywalker/hidtsp/phonemgr/phonemgr.cpp
2020-09-26 16:20:57 +08:00

765 lines
20 KiB
C++

/* Copyright (c) 1999 Microsoft Corporation */
#include "phonemgr.h"
#include <stdlib.h>
#include <stdio.h>
#include <wxdebug.h>
#ifdef _DBG
#define DEBUG(_x_) OutputDebugString(_x_)
#else
#define DEBUG(_x_)
#endif
ITRequest * g_pITRequest = NULL;
HRESULT InitAssistedTelephony(void)
{
HRESULT hr;
//
// Initialize COM.
//
printf("Initializing COM...\n");
hr = CoInitializeEx(
NULL,
COINIT_MULTITHREADED
);
if ( FAILED(hr) )
{
printf("CoInitialize failed - 0x%08x\n", hr);
return hr;
}
//
// Cocreate the assisted telephony object.
//
printf("Creating RequestMakeCall object...\n");
hr = CoCreateInstance(
CLSID_RequestMakeCall,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITRequest,
(void **) & g_pITRequest
);
if ( FAILED(hr) )
{
printf("CoCreateInstance failed - 0x%08x\n", hr);
return hr;
}
return S_OK;
}
HRESULT MakeAssistedTelephonyCall(WCHAR * wszDestAddress)
{
HRESULT hr;
BSTR bstrDestAddress = NULL;
BSTR bstrAppName = NULL;
BSTR bstrCalledParty = NULL;
BSTR bstrComment = NULL;
bstrDestAddress = SysAllocString(
wszDestAddress
);
if ( bstrDestAddress == NULL )
{
printf("SysAllocString failed");
return E_OUTOFMEMORY;
}
//
// Make a call.
//
printf("Calling ITRequest::MakeCall...\n");
hr = g_pITRequest->MakeCall(
bstrDestAddress,
bstrAppName,
bstrCalledParty,
bstrComment
);
SysFreeString(
bstrDestAddress
);
if ( FAILED(hr) )
{
printf("ITRequest::MakeCall failed - 0x%08x\n", hr);
return hr;
}
return S_OK;
}
int
WINAPI
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
MSG msg;
HWND hwnd, hwndEdit;
ghInst = hInstance;
DialogBox(
ghInst,
MAKEINTRESOURCE(IDD_MAINDLG),
NULL,
MainWndProc
);
return 0;
}
INT_PTR
CALLBACK
MainWndProc(
HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
LPCTSTR lszAppName = _T("Generate DialTone");
DWORD dwNumDevs, i;
LONG lResult;
PHONEINITIALIZEEXPARAMS initExParams;
PMYPHONE pNextPhone;
PWCHAR szAddressToCall;
ghDlg = hDlg;
switch (uMsg)
{
case WM_INITDIALOG:
initExParams.dwTotalSize = sizeof (PHONEINITIALIZEEXPARAMS);
initExParams.dwOptions = (DWORD) PHONEINITIALIZEEXOPTION_USEHIDDENWINDOW;
lResult = phoneInitializeEx(
(LPHPHONEAPP) &ghPhoneApp,
(HINSTANCE) ghInst,
(PHONECALLBACK) tapiCallback,
lszAppName,
(LPDWORD) &dwNumDevs,
(LPDWORD) &gdwAPIVersion,
(LPPHONEINITIALIZEEXPARAMS) &initExParams
);
if (lResult == 0)
{
gdwNumPhoneDevs = dwNumDevs;
}
gpPhone = (PMYPHONE) LocalAlloc(LPTR,gdwNumPhoneDevs * sizeof(MYPHONE));
g_wszMsg = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * 100 );
g_wszDest = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * 100 );
// Opening all the phones
for(i = 0, pNextPhone = gpPhone; i < gdwNumPhoneDevs; i++, pNextPhone++)
{
CreatePhone(pNextPhone, i);
}
SetStatusMessage(TEXT("Waiting for input from Phones"));
g_szDialStr = (LPWSTR) LocalAlloc(LPTR, 20 * sizeof(WCHAR));
lstrcpy(g_szDialStr, TEXT("Dial Number: "));
break;
case WM_COMMAND:
if ( LOWORD(wParam) == IDCANCEL )
{
//
// The close box or Exit button was pressed.
//
SetStatusMessage(TEXT("End Application"));
if(ghPhoneApp)
{
phoneShutdown(ghPhoneApp);
}
EndDialog( hDlg, 0 );
LocalFree(g_szDialStr);
LocalFree(g_wszMsg);
LocalFree(g_wszDest);
for( i=0; i<gdwNumPhoneDevs; i++ )
{
FreePhone(&gpPhone[i]);
}
LocalFree(gpPhone);
}
else if ( LOWORD(wParam) == IDC_MAKECALL )
{
//
// The Make Call button was pressed.
//
//
// Stop dialtone.
// this only works for one phone.
// Should be fine as we don't have
// the window visible unless you have the phone off hook.
//
gpPhone[0].pTonePlayer->StopDialtone();
//
// Dial the dest address in the edit box.
//
const int ciMaxPhoneNumberSize = 400;
WCHAR wszPhoneNumber[ciMaxPhoneNumberSize];
UINT uiResult;
uiResult = GetDlgItemText(
ghDlg, // handle to dialog box
IDC_DESTADDRESS, // identifier of control
wszPhoneNumber, // pointer to buffer for text (unicode)
ciMaxPhoneNumberSize // maximum size of string (in our buffer)
);
if ( uiResult == 0 )
{
DoMessage(L"Could not get dialog item text; not making call");
}
else
{
MakeAssistedTelephonyCall(wszPhoneNumber);
}
}
break;
default:
break;
}
return 0;
}
VOID
CALLBACK
tapiCallback(
DWORD hDevice,
DWORD dwMsg,
ULONG_PTR CallbackInstance,
ULONG_PTR Param1,
ULONG_PTR Param2,
ULONG_PTR Param3
)
{
PMYPHONE pPhone;
DWORD i;
BOOL bDialtone = FALSE;
if (hDevice != NULL)
{
pPhone = GetPhone((HPHONE) hDevice);
if (pPhone == NULL)
{
DEBUG(L"tapiCallback - phone not found\n");
return;
}
}
switch (dwMsg)
{
case PHONE_STATE:
DEBUG(L"PHONE_STATE\n");
if (pPhone != NULL)
{
EnterCriticalSection(&pPhone->csdial);
if ( Param1 == PHONESTATE_HANDSETHOOKSWITCH )
{
if ( Param2 != PHONEHOOKSWITCHMODE_ONHOOK ) // if off hook
{
if ( FAILED(pPhone->pTonePlayer->StartDialtone()) )
{
DoMessage(L"StartDialTone Failed");
}
// ZoltanS: show the window now
ShowWindow(ghDlg, SW_SHOWNORMAL);
pPhone->dwHandsetMode = PHONEHOOKSWITCHMODE_MICSPEAKER;
lstrcpy(pPhone->wszDialStr,TEXT(""));
lstrcpy(g_wszMsg,TEXT("Generating Dialtone for phones: "));
for( i=0 ; i < gdwNumPhoneDevs; i++)
{
if ( gpPhone[i].pTonePlayer->IsInUse() )
{
wsprintf(g_wszDest,TEXT("%d"),i);
lstrcat(g_wszMsg,g_wszDest);
}
}
SetStatusMessage(g_wszMsg);
}
else // on hook
{
pPhone->dwHandsetMode = PHONEHOOKSWITCHMODE_ONHOOK;
lstrcpy(pPhone->wszDialStr,TEXT(""));
if ( pPhone->pTonePlayer->IsInUse() )
{
pPhone->pTonePlayer->StopDialtone();
}
// ZoltanS: hide the window now
ShowWindow(ghDlg, SW_HIDE);
bDialtone = FALSE;
lstrcpy(g_wszMsg,TEXT("Generating Dialtone for phones: "));
for( i = 0 ; i < gdwNumPhoneDevs; i++ )
{
if ( gpPhone[i].pTonePlayer->DialtonePlaying() )
{
wsprintf(g_wszDest,TEXT("%d"),i);
lstrcat(g_wszMsg,g_wszDest);
bDialtone = TRUE;
}
}
if(!bDialtone)
{
SetStatusMessage(TEXT("Waiting for input from Phones"));
}
else
{
SetStatusMessage(g_wszMsg);
}
}
}
LeaveCriticalSection(&pPhone->csdial);
}
break;
case PHONE_BUTTON:
DEBUG(L"PHONE_BUTTON\n");
if (pPhone != NULL)
{
EnterCriticalSection(&pPhone->csdial);
if ( Param2 == PHONEBUTTONMODE_KEYPAD )
{
if (pPhone->dwHandsetMode != PHONEHOOKSWITCHMODE_ONHOOK)
{
if ( Param3 == PHONEBUTTONSTATE_DOWN )
{
if ( pPhone->pTonePlayer->IsInUse() )
{
if ( ( (int)Param1 >= 0 ) && ( (int)Param1 <= 9 ) )
{
//
// We have a dialed digit. Append it to the phone
// number we have so far.
//
wsprintf(g_wszDest, TEXT("%d"), Param1);
lstrcat(pPhone->wszDialStr, g_wszDest);
//
// Append the phone number so far to a standard prefix
// ("Phone number: ") and update the UI.
//
lstrcpy(g_wszMsg, g_szDialStr);
lstrcat(g_wszMsg,pPhone->wszDialStr);
SetStatusMessage(g_wszMsg);
//
// Generate a DTMF tone for this digit.
//
pPhone->pTonePlayer->GenerateDTMF( (long)Param1 );
}
else if ( Param1 == 10 )
{
//
// Generate a DTMF tone for "*". This will not count
// as part of the dialed number.
//
pPhone->pTonePlayer->GenerateDTMF( (long)Param1 );
}
else if ( Param1 == 11 )
{
//
// Generate a DTMF tone for "#". This will not count
// as part of the dialed number but it will tell us
// to make the call immediately.
//
pPhone->pTonePlayer->GenerateDTMF( (long)Param1 );
//
// Make the call.
//
if ( S_OK == MakeAssistedTelephonyCall(pPhone->wszDialStr) )
{
SetStatusMessage(L"Call created");
}
else
{
SetStatusMessage(L"Failed to create the call");
}
}
} // if in use
} // if button down
} // if off hook
} // if keypad
LeaveCriticalSection(&pPhone->csdial);
}
break; // case phone_button
case PHONE_CLOSE:
DEBUG(L"PHONE_CLOSE\n");
if (pPhone != NULL)
{
EnterCriticalSection(&pPhone->csdial);
phoneClose(pPhone->hPhone);
LeaveCriticalSection(&pPhone->csdial);
}
break;
case PHONE_REMOVE:
DEBUG(L"PHONE_REMOVE\n");
pPhone = GetPhoneByID( (DWORD)Param1);
if (pPhone != NULL)
{
FreePhone(pPhone);
RemovePhone(pPhone);
}
break;
case PHONE_CREATE:
DEBUG(L"PHONE_CREATE\n");
pPhone = AddPhone();
CreatePhone(pPhone, (DWORD)Param1);
break;
default:
break;
}
}
//////////////////////////////////////////////////////////////////
// SetStatusMessage
//////////////////////////////////////////////////////////////////
void
SetStatusMessage(
LPWSTR pszMessage
)
{
SetDlgItemText(
ghDlg,
IDC_STATUS,
pszMessage
);
}
//////////////////////////////////////////////////////////////////
// CreatePhone
//////////////////////////////////////////////////////////////////
void
CreatePhone(
PMYPHONE pPhone,
DWORD dwDevID
)
{
LRESULT lResult;
pPhone->hPhoneApp = ghPhoneApp;
InitializeCriticalSection(&pPhone->csdial);
// won't detect overrun if dialing more than 100 digits
pPhone->wszDialStr = (LPWSTR) LocalAlloc(LPTR, 100 * sizeof(WCHAR));
pPhone->dwHandsetMode = PHONEHOOKSWITCHMODE_ONHOOK;
lResult = phoneOpen(
ghPhoneApp,
dwDevID,
&pPhone->hPhone,
gdwAPIVersion,
0,
(DWORD_PTR) NULL,
PHONEPRIVILEGE_OWNER
);
//
// Save info about this phone that we can display later
//
pPhone->dwDevID = dwDevID;
pPhone->dwAPIVersion = gdwAPIVersion;
pPhone->dwPrivilege = PHONEPRIVILEGE_OWNER;
DWORD dwBigBuffSize = sizeof(VARSTRING) +
sizeof(DWORD) * 5;
LPVOID pBuffer = LocalAlloc(LPTR,dwBigBuffSize);
LPVARSTRING lpDeviceID = (LPVARSTRING) pBuffer;
lpDeviceID->dwTotalSize = dwBigBuffSize;
LPWSTR lpszDeviceClass;
lpszDeviceClass = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * 20);
lstrcpy(lpszDeviceClass, TEXT("wave/in"));
lResult = phoneGetID(
pPhone->hPhone,
lpDeviceID,
lpszDeviceClass
);
if(lResult != 0)
{
pPhone->lCaptureID = WAVE_MAPPER;
}
else
{
CopyMemory(
&pPhone->lCaptureID,
(LPBYTE) lpDeviceID + lpDeviceID->dwStringOffset,
lpDeviceID->dwStringSize
);
}
lstrcpy(lpszDeviceClass, TEXT("wave/out"));
lResult = phoneGetID(
pPhone->hPhone,
lpDeviceID,
lpszDeviceClass
);
if(lResult != 0)
{
pPhone->lRenderID = WAVE_MAPPER;
}
else
{
CopyMemory(
&pPhone->lRenderID,
(LPBYTE) lpDeviceID + lpDeviceID->dwStringOffset,
lpDeviceID->dwStringSize
);
}
LocalFree(lpszDeviceClass);
LocalFree(pBuffer);
lResult = phoneSetStatusMessages(
pPhone->hPhone,
PHONESTATE_HANDSETHOOKSWITCH,
PHONEBUTTONMODE_FEATURE | PHONEBUTTONMODE_KEYPAD,
PHONEBUTTONSTATE_UP | PHONEBUTTONSTATE_DOWN
);
pPhone->pTonePlayer = new CTonePlayer;
if ( (pPhone->pTonePlayer == NULL) ||
FAILED(pPhone->pTonePlayer->Initialize()) )
{
DoMessage(L"Tone Player Initialization Failed");
}
else if ( FAILED(pPhone->pTonePlayer->OpenWaveDevice( pPhone->lRenderID )) )
{
DoMessage(L"OpenWaveDevice Failed");
}
if ( FAILED( InitAssistedTelephony() ) )
{
DoMessage(L"InitAssistedTelephony Failed");
}
}
//////////////////////////////////////////////////////////////////
// FreePhone
//////////////////////////////////////////////////////////////////
void
FreePhone(
PMYPHONE pPhone
)
{
EnterCriticalSection(&pPhone->csdial);
if ( pPhone->pTonePlayer->IsInUse() )
{
pPhone->pTonePlayer->StopDialtone();
pPhone->pTonePlayer->CloseWaveDevice();
}
LocalFree(pPhone->wszDialStr);
LeaveCriticalSection(&pPhone->csdial);
DeleteCriticalSection(&pPhone->csdial);
}
///////////////////////////////////////////////////////////////////
// GetPhone
///////////////////////////////////////////////////////////////////
PMYPHONE
GetPhone (HPHONE hPhone )
{
DWORD i;
for(i = 0; i < gdwNumPhoneDevs; i++)
{
if(gpPhone[i].hPhone == hPhone)
{
return &gpPhone[i];
}
}
return (PMYPHONE) NULL;
}
///////////////////////////////////////////////////////////////////
// GetPhoneByID
///////////////////////////////////////////////////////////////////
PMYPHONE
GetPhoneByID (DWORD dwDevID )
{
DWORD i;
for(i = 0; i < gdwNumPhoneDevs; i++)
{
if(gpPhone[i].dwDevID == dwDevID)
{
return &gpPhone[i];
}
}
return (PMYPHONE) NULL;
}
///////////////////////////////////////////////////////////////////
// RemovePhone
///////////////////////////////////////////////////////////////////
void
RemovePhone (PMYPHONE pPhone)
{
DWORD i,j;
PMYPHONE pNewPhones;
pNewPhones = (PMYPHONE) LocalAlloc(LPTR,(gdwNumPhoneDevs-1) * sizeof(MYPHONE));
for(i = 0, j = 0; i < gdwNumPhoneDevs; i++)
{
if(&gpPhone[i] != pPhone)
{
CopyMemory( &pNewPhones[j], &gpPhone[i], sizeof(MYPHONE));
j++;
}
}
LocalFree(gpPhone);
gpPhone = pNewPhones;
gdwNumPhoneDevs--;
}
///////////////////////////////////////////////////////////////////
// AddPhone
///////////////////////////////////////////////////////////////////
PMYPHONE
AddPhone ()
{
PMYPHONE pNewPhones;
pNewPhones = (PMYPHONE) LocalAlloc(LPTR,(gdwNumPhoneDevs+1) * sizeof(MYPHONE));
CopyMemory( pNewPhones, gpPhone, gdwNumPhoneDevs * sizeof(MYPHONE));
LocalFree(gpPhone);
gpPhone = pNewPhones;
gdwNumPhoneDevs++;
return &gpPhone[gdwNumPhoneDevs-1];
}
///////////////////////////////////////////////////////////////////
// DoMessage
///////////////////////////////////////////////////////////////////
void
DoMessage(
LPWSTR pszMessage
)
{
MessageBox(
ghDlg,
pszMessage,
gszTapi30,
MB_OK
);
}