/* Copyright (c) 1999 Microsoft Corporation */ #include "phonemgr.h" #include #include #include #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; iStopDialtone(); // // 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 ); }