?? voipcall.cpp
字號:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "VoIPCall.hpp"
#include "CommonFunctions.hpp"
#include <auto_xxx.hxx> //for auto_bstr etc.
#include <rtcerr.h> //for RTC error codes
#include "DialEngine.hpp"
#include "Debug.hpp"
#include "VoIPApp.hpp"
#include "SettingsApi.hpp"
bool
IsValidTime(
const SYSTEMTIME* pTime
)
{
if (pTime == NULL)
{
return false;
}
FILETIME FileTime = {0};
if (!SystemTimeToFileTime(pTime, &FileTime))
{
return false;
}
if (FileTime.dwHighDateTime == 0 && FileTime.dwLowDateTime == 0)
{
return false;
}
return true;
}
/*------------------------------------------------------------------------------
GetULLAsSystemTime
Utility function that gets the current system time as an unsigned long long
------------------------------------------------------------------------------*/
HRESULT
GetULLAsSystemTime(
ULONGLONG ull,
__out SYSTEMTIME* pSystemTime
)
{
if (pSystemTime == NULL)
{
return E_INVALIDARG;
}
ull /= 10000; // convert to ms -- 1 ns is 10^6 ms so 100 ns is 10^4 ms
pSystemTime->wMilliseconds = (WORD)(ull % 1000);
ull /= 1000;
pSystemTime->wSecond = (WORD)(ull % 60);
ull /= 60;
pSystemTime->wMinute = (WORD)(ull % 60);
ull /= 60;
pSystemTime->wHour = (WORD)(ull % 24);
ull /= 24;
pSystemTime->wDay = (WORD)ull;
pSystemTime->wYear = 0;
pSystemTime->wDayOfWeek = 0;
pSystemTime->wMonth = 0;
return S_OK;
}
/*------------------------------------------------------------------------------
GetSystemTimeAsULL
Utility function that gets the current system time as an unsigned long long
------------------------------------------------------------------------------*/
HRESULT
GetSystemTimeAsULL(
const SYSTEMTIME* pSystemTime,
__out ULONGLONG* pDest
)
{
if (pDest == NULL || pSystemTime == NULL)
{
ASSERT(FALSE);
return E_POINTER;
}
FILETIME FileTime = {0};
if (! SystemTimeToFileTime(pSystemTime, &FileTime))
{
ASSERT(FALSE);
return CommonUtilities_t::GetErrorFromWin32();
}
//shift the high time over to the upper 32 bits and OR in the lower bits
*pDest = (static_cast<ULONGLONG>(FileTime.dwHighDateTime) << 32) | FileTime.dwLowDateTime;
return S_OK;
}
const UINT VoIPCall_t::sc_RingbackStartTimeout = 150;
const UINT VoIPCall_t::sc_TransferDoneTimeout = 10 * 1000;
/*------------------------------------------------------------------------------
VoIPCall_t::CreateNewCall
Static method used for creating and initializing a new call object
Parameters:
IsOutgoingCall: Is this an outgoing call?
pFriendlyNumber: (optional) Friendly number string if it is already known before we create the call. e.g outgoing call
pFriendlyName: (optional) Friendly name string if it is already known before we create the call. e.g. PHMakePhoneCall is called
pRTCSession: pointer to a valid RTC Session object
ppCall: OUT - the returned call
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
/* static */ HRESULT VoIPCall_t::CreateNewCall(
bool IsOutgoingCall,
const WCHAR* pFriendlyNumber,
const WCHAR* pFriendlyName,
IRTCSession* pRTCSession,
Call_t** ppCall
)
{
//validate parameters
if (ppCall == NULL || pRTCSession == NULL)
{
ASSERT(FALSE);
return E_POINTER;
}
VoIPCall_t* pOutCall = new VoIPCall_t();
if (! pOutCall)
{
return E_OUTOFMEMORY;
}
HRESULT hr = pOutCall->Initialize(
IsOutgoingCall,
pFriendlyNumber,
pFriendlyName,
pRTCSession
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to initialize the call - error: 0x%x", hr));
//cleanup
//
pOutCall->Release();
*ppCall = NULL;
return hr;
}
*ppCall = static_cast<Call_t*>(pOutCall);
return S_OK;
}
/*------------------------------------------------------------------------------
VoIPCall_t::VoIPCall_t
Ctor
------------------------------------------------------------------------------*/
VoIPCall_t::VoIPCall_t()
{
TRACE(ZONE_PHONEAPP_CTOR);
m_CouldBeMissed = true;
m_IsLogged = false;
m_PlayingRingbackTone = false;
m_StartRingbackTimerId = 0;
m_cpRTCParticipant = NULL;
m_cpRTCSession = NULL;
m_cpRTCSessionReferredEvent = NULL;
m_cpReferringCall = NULL;
}
/*------------------------------------------------------------------------------
VoIPCall_t::~VoIPCall_t
Dtor
------------------------------------------------------------------------------*/
VoIPCall_t::~VoIPCall_t()
{
TRACE(ZONE_PHONEAPP_CTOR);
//terminate the session once this object is to be destroyed
//since we are not tracking it
if ((m_cpRTCSession) && (GetCallStatus() != RTCSS_DISCONNECTED))
{
m_cpRTCSession->Terminate(RTCTR_SHUTDOWN);
}
StopRingbackTone();
m_cpRTCParticipant = NULL;
m_cpRTCSession = NULL;
m_cpRTCSessionReferredEvent = NULL;
m_cpReferringCall = NULL;
}
/*------------------------------------------------------------------------------
VoIPCall_t::Initialize
Initializes this object from an existing IRTCSession
Parameters:
IsOutgoingCall: Is this an outgoing call?
pFriendlyNumber: (optional) Friendly number string if it is already known before we create the call. e.g outgoing call
pFriendlyName: (optional) Friendly name string if it is already known before we create the call. e.g. PHMakePhoneCall is called
pRTCSession: pointer to a valid RTC Session object
Returns (HRESULT): indicating success or failure
------------------------------------------------------------------------------*/
HRESULT VoIPCall_t::Initialize(
bool IsOutgoingCall,
const WCHAR* pFriendlyNumber,
const WCHAR* pFriendlyName,
IRTCSession* pRTCSession
)
{
if (pRTCSession == NULL)
{
return E_INVALIDARG;
}
m_CallType = IsOutgoingCall ? e_vctOutgoing : e_vctIncoming;
//set the new session variable
m_cpRTCSession = pRTCSession;
CComPtr<IRTCEnumParticipants> cpEnumParticipants;
HRESULT hr = m_cpRTCSession->EnumerateParticipants(
&cpEnumParticipants
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed to get participant list from the session - hr = 0x%x", hr));
return hr;
}
CComPtr<IRTCParticipant> cpParticipant;
hr = cpEnumParticipants->Next(1, &m_cpRTCParticipant, NULL);
if (hr != S_OK)
{
PHONEAPP_DEBUGMSG(hr != S_FALSE && ZONE_PHONEAPP_ERROR, (L"Failed to get the next participant from the session - hr = 0x%x", hr));
return hr;
}
hr = m_cpRTCParticipant->get_UserURI(&m_bstrURI);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at getting the remove URI, hr = 0x%x", hr));
return hr;
}
//use the specified friendly number first if it exists
if (pFriendlyNumber != NULL &&
pFriendlyNumber[0] != L'\0')
{
m_bstrFriendlyNumber = SysAllocString(pFriendlyNumber);
if (m_bstrFriendlyNumber == NULL)
{
return E_OUTOFMEMORY;
}
}
else
{
//otherwise, get it by converting from URI
hr = GetApp()->GetDialEngine().GetPhoneNumberToDisplay(
m_bstrURI,
-1,
NULL, //use active profile
&m_bstrFriendlyNumber
);
}
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at formating the remote URI, hr = 0x%x", hr));
return hr;
}
hr = m_cpRTCParticipant->get_Name(&m_bstrName);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at gettting name from network, hr = 0x%x", hr));
}
//use the specified friendly name first if it exists
if (pFriendlyName != NULL &&
pFriendlyName[0] != L'\0')
{
m_bstrFriendlyName = SysAllocString(pFriendlyName);
if (m_bstrFriendlyName == NULL)
{
return E_OUTOFMEMORY;
}
}
//get the caller information from database
hr = GetApp()->GetDatabase().GetCallerInfo(
m_bstrFriendlyNumber,
(m_bstrFriendlyName != NULL && m_bstrFriendlyName[0] != L'\0') ? NULL : &m_bstrFriendlyName,
&m_bstrRingTonePath,
&m_IsBlocked
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at gettting information from database, hr = 0x%x", hr));
}
//if we still don't have a good caller id, try the POOM
if (m_bstrFriendlyName == NULL ||
m_bstrFriendlyName[0] == L'\0')
{
hr = GetApp()->GetPoom().GetCallerName(
m_bstrFriendlyNumber,
&m_bstrFriendlyName
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at getting caller id from Poom, hr = 0x%x", hr));
}
}
return S_OK;
}
/*------------------------------------------------------------------------------
VoIPCall_t::ForceDestroy
Delete this object and null out RTC pointers
------------------------------------------------------------------------------*/
void
VoIPCall_t::ForceDestroy(
void
)
{
PhoneAppUtilities_t::NullOutCOMPtr<IRTCParticipant>(&m_cpRTCParticipant);
PhoneAppUtilities_t::NullOutCOMPtr<IRTCSession>(&m_cpRTCSession);
delete this;
return;
}
/*------------------------------------------------------------------------------
VoIPCall_t::DoPhoneVerb
Perform an action for the phone application.
------------------------------------------------------------------------------*/
HRESULT
VoIPCall_t::DoPhoneVerb(
PH_VERB Verb,
VPARAM Parameter
)
{
HRESULT hr = S_OK;
switch (Verb)
{
case PH_VERB_HOLD:
case PH_VERB_UNHOLD:
hr = DoVerbHoldUnhold(Verb);
break;
case PH_VERB_ACCEPT_INCOMING:
case PH_VERB_REJECT_INCOMING:
hr = DoVerbAcceptRejectIncomingCall(Verb);
break;
case PH_VERB_TALK:
hr = DoVerbTalk();
break;
case PH_VERB_END:
hr = DoVerbEnd();
break;
case PH_VERB_TRANSFER:
hr = DoVerbTransfer(Parameter);
break;
default:
hr = E_NOTIMPL;
break;
}
return hr;
}
/*------------------------------------------------------------------------------
VoIPCall_t::Contains
Overloaded Comparison operator - compares internal participant to specified
participant
------------------------------------------------------------------------------*/
bool
VoIPCall_t::Contains(
IRTCParticipant* pParticipant
)
{
return PhoneAppUtilities_t::AreCOMPointersEqual<IRTCParticipant>(
static_cast<IRTCParticipant*>(m_cpRTCParticipant),
pParticipant
);
}
/*------------------------------------------------------------------------------
VoIPCall_t::operator==
Overloaded comparison operator - compares internal session to specified
session
------------------------------------------------------------------------------*/
bool
VoIPCall_t::Contains(
IRTCSession* pSession
)
{
return PhoneAppUtilities_t::AreCOMPointersEqual<IRTCSession>(
static_cast<IRTCSession*>(m_cpRTCSession),
pSession
);
}
/*------------------------------------------------------------------------------
VoIPCall_t::UpdateDisconnectReason
When the call disconnects, this retreives the reason why the call disconnects
to help determine if the call was terminated for strange reasons (e.g. busy etc)
------------------------------------------------------------------------------*/
HRESULT
VoIPCall_t::UpdateDisconnectReason(
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -