📄 voipapp.cpp
字号:
//intialize the speaker volume as the current active volume mode
PHSetActiveVolume(RingerVolumeMode);
hr = EnableCalling();
if (FAILED(hr))
{
PHONEAPP_RETAILMSG(ZONE_PHONEAPP_ERROR, (L"Failed to enable calling, hr = 0x%x", hr));
goto exit;
}
//start listening the setting changes
hr = m_Settings.StartListening();
if (FAILED(hr))
{
PHONEAPP_RETAILMSG(ZONE_PHONEAPP_ERROR, (L"Failed to start listening the setting changes, hr = 0x%x", hr));
goto exit;
}
PumpMessages();
exit:
//cleanup
m_AudioManager.Uninitialize();
m_Poom.Uninitialize();
if (m_PendingAuthAction != ActionInvalid)
{
PHCancelAuthenticationRequest(m_NotificationWindow);
}
DestroyWindow(m_NotificationWindow);
return hr;
}
/*------------------------------------------------------------------------------
VoIPApp_t::CreateNotificationWindow
Creates the listner window
------------------------------------------------------------------------------*/
HRESULT
VoIPApp_t::CreateNotificationWindow(
void
)
{
if (m_NotificationWindow != NULL)
{
//already registered!
ASSERT(FALSE);
return S_FALSE;
}
//register our notification window class
WNDCLASS WindowClass = {0};
WindowClass.lpfnWndProc = s_NotificationWindowProc;
WindowClass.hInstance = GlobalData_t::s_ModuleInstance;
WindowClass.lpszClassName = WNDCLASS_PHONEAPP;
//it's ok if our class already exists...
if (! RegisterClass(&WindowClass) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Could not register the window class - last error = (decimal) %d", GetLastError()));
ASSERT(FALSE);
return E_FAIL;
}
//create the notification window and pack our 'this' pointer into the CREATESTRUCT
m_NotificationWindow = CreateWindow(
WNDCLASS_PHONEAPP,
NULL,
0, 0, 0, 0, 0, NULL, NULL,
GlobalData_t::s_ModuleInstance,
reinterpret_cast<void*>(this)
);
if (m_NotificationWindow == NULL)
{
ASSERT(FALSE);
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Could not create the listener window! - error code (decimal) %d", GetLastError()));
return CommonUtilities_t::GetErrorFromWin32();
}
return S_OK;
}
/*------------------------------------------------------------------------------
VoIPApp_t::s_NotificationWindowProc
Static WndProc for our notification window class.
Delegates processing to an instance of the window class
------------------------------------------------------------------------------*/
/* static */ LRESULT WINAPI VoIPApp_t::s_NotificationWindowProc(
HWND hwnd,
UINT Message,
WPARAM wParam,
LPARAM lParam
)
{
VoIPApp_t *pVoIPApp = NULL;
if (Message == WM_CREATE)
{
//On WM_CREATE we packed a VoIPApp_t object into the createstruct.
//Now we extract that object and store it in the USERDATA section of the window
CREATESTRUCT *pCreateStruct = reinterpret_cast<CREATESTRUCT*>(lParam);
if (! pCreateStruct)
{
ASSERT(FALSE);
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"CreateStruct is empty - cannot create this window"));
return -1;
}
pVoIPApp = reinterpret_cast<VoIPApp_t*>(pCreateStruct->lpCreateParams);
if (! pVoIPApp)
{
ASSERT(FALSE);
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"No canvas object in the create struct - cannot create this window"));
return -1;
}
//Pack the canvas object into the window for future retrieval
SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast<LONG>(pVoIPApp));
}
//Retrieve the object from the window userdata section
pVoIPApp = reinterpret_cast<VoIPApp_t*>(GetWindowLong(hwnd, GWL_USERDATA));
if (! pVoIPApp)
{
return DefWindowProc(hwnd, Message, wParam, lParam);
}
//stabilize the object for this message processing
pVoIPApp->AddRef();
//Let the object handle the message
LRESULT ReturnValue = pVoIPApp->NotificationWindowProc(hwnd, Message, wParam, lParam);
//release the reference we added before processing the message
pVoIPApp->Release();
if (Message == WM_DESTROY)
{
SetWindowLong(hwnd, GWL_USERDATA, 0);
}
return ReturnValue;
}
LRESULT VoIPApp_t::NotificationWindowProc(
HWND hwnd,
UINT Message,
WPARAM wParam,
LPARAM lParam
)
{
LRESULT ReturnValue = 0;
PCOPYDATASTRUCT pCopyDataStruct = NULL;
switch (Message)
{
//on create we need to register the hotkeys
case WM_CREATE:
HotKeys_t::RegisterHotKeys(hwnd);
InitializeHookState();
break;
case WM_DESTROY:
HotKeys_t::UnRegisterHotKeys(hwnd);
ReturnValue = 1; //implies NOT processed
break;
case WM_CLOSE:
Shutdown();
ReturnValue = 0;
break;
//On hotkey, delegate to the handlers
case WM_HOTKEY:
ReturnValue = RespondToHotKey(
(INT)wParam,
(UINT)HIWORD(lParam),
((UINT)LOWORD(lParam) & MOD_KEYUP)
);
break;
case WM_HIBERNATE:
OnHibernate();
break;
case WM_TIMER:
m_Timers.OnTimerEvent(wParam);
break;
case WM_NEW_COMMAND_LINE:
// Just set existing app as the foreground window for now
ForegroundExistingApp();
break;
case WM_DIALED_DIGIT:
m_UIManager.OnHookDialing(
static_cast<WCHAR>(wParam)
);
break;
case WM_AUTH_COMPLETE:
OnAuthRequestComplete(
static_cast<AuthenticationResult_e>(wParam)
);
break;
#ifdef DEBUG
case WM_DEBUG_PHONE_STATE:
DebugPhoneState();
break;
#endif
case WM_COPYDATA:
pCopyDataStruct = (PCOPYDATASTRUCT) lParam;
if (pCopyDataStruct == NULL)
{
break;
}
switch (pCopyDataStruct->dwData)
{
case MAKE_PHONE_CALL:
if (pCopyDataStruct->cbData != sizeof(PH_MAKEPHONECALL_PARAMETERS))
{
return E_INVALIDARG;
}
return (HRESULT)MakePhoneCall(static_cast<PH_MAKEPHONECALL_PARAMETERS*>(pCopyDataStruct->lpData));
break;
#ifdef ENABLE_VOIP_TEST_HOOKS
case GET_FORMATTED_NUMBER:
if (pCopyDataStruct->lpData == NULL)
{
break;
}
TestGetFormattedNumber(
((DIAL_STRING_INFO*)(pCopyDataStruct->lpData))->DialString,
((DIAL_STRING_INFO*)(pCopyDataStruct->lpData))->DialStringLength,
((DIAL_STRING_INFO*)(pCopyDataStruct->lpData))->FormatType
);
break;
case GET_IS_NUMBER_AUTODIALABLE:
if (pCopyDataStruct->lpData == NULL)
{
ASSERT(FALSE);
return FALSE;
}
return (LRESULT)TestGetIsNumberAutodialable(
(const WCHAR*)pCopyDataStruct->lpData
);
#endif
default:
break;
}
break;
default:
ReturnValue = DefWindowProc(hwnd, Message, wParam, lParam);
break;
}
return ReturnValue;
}
void
VoIPApp_t::OnTimerExpires(
UINT TimerID
)
{
return;
}
/*------------------------------------------------------------------------------
VoIPApp_t::EnableCalling
Enable the VoIP calling by creating and initializing the
RTC Client and registering our event sink
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT VoIPApp_t::EnableCalling()
{
TRACE(ZONE_PHONEAPP_FUNCTION);
if (m_cpRTCClient != NULL)
{
return S_FALSE;
}
//Ctor starts the marker, Dtor stops the marker
CComPtr<IRTCClient2> cpClient2;
if (m_cpRTCClient != NULL)
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"This object has already been initialized..."));
return E_FAIL;
}
HRESULT hr = m_cpRTCClient.CoCreateInstance(CLSID_RTCClient);
if (FAILED(hr))
{
//Need to log the error...
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Cannot co create the RTC Client. Error 0x%x -- Is the client properly installed though COM reg settings? Is the dll signed? Are all the dependent dll's also in the image? ", hr));
goto exit;
}
//need the client2 interface to call InitializeEx
hr = m_cpRTCClient->QueryInterface(
IID_IRTCClient2,
reinterpret_cast<void**>(&cpClient2)
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to QI the RTC client for IRTCClient2. Error 0x%x.", hr));
goto exit;
}
//initialize the rtc client
hr = cpClient2->InitializeEx(
GetRTCInitializationFlags()
);
if (FAILED(hr))
{
//Need to log the error...
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Cannot initialize the RTC Client with flags 0x%x. Error code: 0x%x", GetRTCInitializationFlags()));
goto exit;;
}
//register our event sink as a callback for the rtc client
hr = RegisterCallbackInterface();
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Cannot register the callback interface - error 0x%x", hr));
goto exit;
}
//register for specific events
hr = m_cpRTCClient->put_EventFilter(
RTCEF_CLIENT |
RTCEF_PARTICIPANT_STATE_CHANGE |
RTCEF_SESSION_STATE_CHANGE |
RTCEF_REGISTRATION_STATE_CHANGE |
RTCEF_SESSION_REFER_STATUS |
RTCEF_SESSION_REFERRED |
RTCEF_SESSION_OPERATION_COMPLETE |
RTCEF_SUBSCRIPTION_STATE_CHANGE |
RTCEF_SUBSCRIPTION_NOTIFY
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to set an event filter with the RTC Client"));
goto exit;
}
//listen for new incoming sessions
hr = m_cpRTCClient->put_ListenForIncomingSessions(GetRTCListenMode());
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failure when asking the RTC Client to listen for all incoming sessions"));
goto exit;
}
//get the maximum number of calls that are allowed simutanously
m_MaxNumberOfCalls = GetMaxNumberOfCalls();
//start proxy services
m_ProxyServices.StartServices();
exit:
if (FAILED(hr))
{
DisableCalling();
}
return hr;
}
/*------------------------------------------------------------------------------
VoIPApp_t::RegisterCallbackInterface
Registers 'this' object as an event sink for RTC's IRTCEventNotification
connection point callback
Returns (HRESULT): indicating whether the connection was made
(or E_UNEXPECTED if we are already registered)
------------------------------------------------------------------------------*/
HRESULT VoIPApp_t::RegisterCallbackInterface()
{
if (m_cpRTCClient == NULL || m_ConnectionPtCookie != 0)
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Already (at least partially) registered - returning E_FAIL"));
return E_FAIL;
}
CComPtr<IConnectionPointContainer> cpContainer;
//Recast the RTC Client as a connection point container
HRESULT hr = m_cpRTCClient->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast<void**>(&cpContainer));
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Couldn't get the connection point container from the RTC Client - error 0x%x", hr));
return hr;
}
//Find the event notification connection point - we will advise the connection point of our
//event sink in the next step.
hr = cpContainer->FindConnectionPoint(IID_IRTCEventNotification, &m_cpConnectionPt);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to find an IRTCEventNotification connection point - error code 0x%x", hr));
return hr;
}
//now advise the connection point that this object is the event sink for the given connection
hr = m_cpConnectionPt->Advise(static_cast<IUnknown*>(static_cast<IRTCEventNotification*>(this)), &m_ConnectionPtCookie);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to advise the connection point - error 0x%x", hr));
return hr;
}
ASSERT(m_ConnectionPtCookie != 0);
return S_OK;
}
/*------------------------------------------------------------------------------
VoIPApp_t::DisableCalling
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -