📄 mstapi3.cpp
字号:
/*
Copyright (c) 2005 Serban Iordache
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, provided that the above
copyright notice(s) and this permission notice appear in all copies of
the Software and that both the above copyright notice(s) and this
permission notice appear in supporting documentation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Except as contained in this notice, the name of a copyright holder
shall not be used in advertising or otherwise to promote the sale, use
or other dealings in this Software without prior written authorization
of the copyright holder.
*/
#include "stdafx.h"
#include "MSTapi3.h"
#include "TAPI3EventNotification.h"
#include "Util.h"
// constructor
MSTapi3::MSTapi3() : tapi(NULL), tapi3EventNotification(NULL), currCallID(0), isDown(false) {
logger = new Logger("MSTapi3");
swapOnHold = false;
}
// destructor
MSTapi3::~MSTapi3() {
logger->debug("MSTapi3 dtor.");
ShutdownTapi();
logger->debug("Deleting logger...");
delete logger;
logger = NULL;
logger->debug("Logger deleted.");
}
list<wstring> MSTapi3::getAddressNames() {
list<wstring> addressNames;
for (AddressMap::iterator it = addresses.begin(); it != addresses.end(); ++it) {
addressNames.push_back((*it).first);
}
return addressNames;
}
//////////////////////////////////////////////////////////////
// InitializeTapi
//
// Various tapi initializations
///////////////////////////////////////////////////////////////
HRESULT MSTapi3::InitializeTapi(CallbackNotification aCallback) {
// cocreate the TAPI object
logger->debug("InitializeTapi() called.");
HRESULT hr = CoCreateInstance(
CLSID_TAPI,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITTAPI,
(LPVOID *)&tapi
);
if (FAILED(hr)) {
logger->error("CoCreateInstance on TAPI failed: hr=%08X", hr);
return hr;
}
logger->debug("CoCreateInstance on TAPI succeeded.");
callback = aCallback;
// call initialize. this must be called before
// any other tapi functions are called.
hr = tapi->Initialize();
if (FAILED(hr)) {
logger->error("TAPI failed to initialize");
tapi->Release();
tapi = NULL;
return hr;
}
logger->debug("tapi->Initialize() succeeded.");
//
// Create our own event notification object and register it
//
tapi3EventNotification = new TAPI3EventNotification(this, callback);
logger->debug("tapi3EventNotification created.");
hr = RegisterTapiEventInterface();
if (FAILED(hr)) {
logger->error("RegisterTapiEventInterface() failed.");
tapi->Release();
tapi = NULL;
return hr;
}
logger->debug("RegisterTapiEventInterface() succeeded.");
// Set the Event filter to only give us the events we process
tapi->put_EventFilter(TE_ADDRESS | TE_CALLNOTIFICATION | TE_CALLSTATE | TE_CALLMEDIA | TE_CALLHUB | TE_CALLINFOCHANGE);
// tapi->put_EventFilter(0x2FFFFFF);
// find all address objects that we will use to listen for calls on
logger->debug("Calling ListenOnAddresses...");
hr = ListenOnAddresses();
if (FAILED(hr)) {
logger->error("Could not find any addresses to listen on");
tapi->Release();
tapi = NULL;
return hr;
}
logger->debug("ListenOnAddresses() succeeded.");
return S_OK;
}
///////////////////////////////////////////////////////////////
// ShutdownTapi
///////////////////////////////////////////////////////////////
void MSTapi3::ShutdownTapi() {
if(isDown) {
logger->warn("TAPI already shut down");
return;
}
isDown = true;
ReleaseAddresses();
UnregisterCallNotifications();
HRESULT hr = UnregisterTapiEventInterface();
if(FAILED(hr)) {
logger->error("UnregisterTapiEventInterface() failed: hr=%08X", hr);
} else {
logger->debug("UnregisterTapiEventInterface() succeeded");
}
// release main object.
if (NULL != tapi) {
logger->debug("Shutting down tapi object...");
try {
HRESULT hr = tapi->Shutdown();
} catch(...) {
logger->error("tapi->Shutdown() failed.");
}
logger->debug("Releasing tapi object...");
tapi->Release();
tapi = NULL;
logger->debug("Tapi object shut down and released.");
} else {
logger->info("tapi object already NULL.");
}
}
/////////////////////////////////////////////////////////////////
// MakeTheCall
//
// Sets up and makes a call
/////////////////////////////////////////////////////////////////
HRESULT MSTapi3::MakeTheCall(int callID, wstring& address, wstring& destination) {
ITAddress* pITAddress = getITAddress(address);
if(pITAddress == NULL) {
logger->error("Address not found: %S", address.c_str());
return -1;
}
// find out which media types this address supports
long lMediaTypes = 0;
if ( AddressSupportsMediaType(pITAddress, TAPIMEDIATYPE_AUDIO) ) {
lMediaTypes |= TAPIMEDIATYPE_AUDIO; // we will use audio
}
if ( AddressSupportsMediaType(pITAddress, TAPIMEDIATYPE_VIDEO) ) {
lMediaTypes |= TAPIMEDIATYPE_VIDEO; // we will use video
}
logger->debug("MakeTheCall(%d, %S, %S)", callID, address.c_str(), destination.c_str());
ITBasicCallControl* pCallControl = getCallControl(callID);
if(pCallControl != NULL) {
logger->warn("Call not null. Releasing old call...");
removeCallControl(callID);
} else {
logger->debug("Ok: empty entry found for callID=%d.", callID);
}
// Create the call.
HRESULT hr = pITAddress->CreateCall(const_cast<unsigned short*>(destination.c_str()),
LINEADDRESSTYPE_PHONENUMBER, lMediaTypes, &pCallControl);
if (FAILED(hr)) {
logger->error("Could not create a call to %S on %S.", destination, address);
return hr;
}
calls[callID] = pCallControl;
logger->debug("Call successfully created.");
// Select our terminals on the call; if any of the selections fail, we proceed without that terminal.
hr = SelectTerminalsOnCall(pITAddress, pCallControl);
if(FAILED(hr)) {
logger->warn("SelectTerminalsOnCall() failed: hr=%08X. Trying to make the call without a terminal.", hr);
}
ITCallInfo* pCallInfo;
hr = pCallControl->QueryInterface( IID_ITCallInfo, (void**)&pCallInfo );
if(FAILED(hr)) {
logger->error("Getting callInfo failed. hr=%08X. Cannot set CIS_CALLEDIDNUMBER", hr);
} else {
BSTR bstrDestination = SysAllocString(destination.c_str());
hr = pCallInfo->put_CallInfoString(CIS_CALLEDIDNUMBER, bstrDestination);
if(FAILED(hr)) {
logger->error("Cannot set CIS_CALLEDIDNUMBER. hr=%08X", hr);
}
pCallInfo->Release();
SysFreeString(bstrDestination);
}
// We're now ready to call connect.
//
// the VARIANT_TRUE parameter indicates that this call is sychronous - that is, it won't
// return until the call is in the connected state (or fails to connect).
hr = pCallControl->Connect(VARIANT_TRUE);
if (FAILED(hr)) {
removeCallControl(callID);
logger->error("Could not connect the call to %S on %S.", destination.c_str(), address.c_str());
return hr;
} else {
logger->info("Successfully connected to %S on %S.", destination.c_str(), address.c_str());
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////
// Dial a number on the call
// This allows extra digits, such as long distance authorization codes, to
// be dialed on a call.
/////////////////////////////////////////////////////////////////////
HRESULT MSTapi3::Dial(int callID, wstring& destination) {
logger->debug("Dial(%d, %S)", callID, destination.c_str());
// get a handle on the call control
ITBasicCallControl* pCallControl = getCallControl(callID);
if(pCallControl == NULL) {
logger->warn("Error: Call is null.");
return S_FALSE;
} else {
logger->debug("Ok: empty entry found for callID=%d.", callID);
}
// Now dial the digits on the call
HRESULT hr = pCallControl->Dial(const_cast<unsigned short*>(destination.c_str()));
// test for success. Don't remove callcontrol on failure -- we didn't create it.
if (FAILED(hr)) {
logger->error("Could not dial the call to %S.", destination.c_str());
return hr;
} else {
logger->info("Successfully dialed to %S.", destination.c_str());
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////
// Answer the call
/////////////////////////////////////////////////////////////////////
HRESULT MSTapi3::AnswerTheCall(int callID) {
logger->debug("Answering callID=%d...", callID);
ITBasicCallControl* callControl = getCallControl(callID);
if (NULL == callControl) {
logger->error("Cannot answer. CallID %d not found", callID);
return E_UNEXPECTED;
}
// get the address object of this call
ITCallInfo* pCallInfo;
HRESULT hr = callControl->QueryInterface( IID_ITCallInfo, (void**)&pCallInfo );
if(FAILED(hr)) {
logger->error("Getting callInfo failed. hr=%08X", hr);
removeCallControl(callID);
return hr;
}
ITAddress* pAddress;
hr = pCallInfo->get_Address( &pAddress );
pCallInfo->Release();
if (FAILED(hr)) {
removeCallControl(callID);
logger->error("get_Address() failed. hr=%08X", hr);
return hr;
}
BSTR bstrAddrName;
hr = pAddress->get_AddressName(&bstrAddrName);
if(FAILED(hr)) {
logger->error("get_AddressName() failed: hr=%08X", hr);
pAddress->Release();
return hr;
}
wstring strAddress = bstrAddrName;
SysFreeString(bstrAddrName);
// Select our terminals on the call; if any of the selections fail, we proceed without that terminal
hr = SelectTerminalsOnCall(pAddress, callControl);
pAddress->Release();
if(FAILED(hr)) {
logger->error("SelectTerminalsOnCall() failed. hr=%08X. Answering without a terminal.", hr);
}
// Now we can actually answer the call
hr = callControl->Answer();
if(FAILED(hr)) {
logger->error("Answer() failed. hr=%08X", hr);
} else {
logger->debug("Answer() successfully done.");
callback(net_sourceforge_gjtapi_raw_tapi3_Tapi3Provider_METHOD_TERMINAL_CONNECTION_TALKING, callID, strAddress,
net_sourceforge_gjtapi_raw_tapi3_Tapi3Provider_JNI_CAUSE_NORMAL, NULL);
}
return hr;
}
//////////////////////////////////////////////////////////////////////
// HoldTheCall
//
// Holds the call
//////////////////////////////////////////////////////////////////////
HRESULT MSTapi3::HoldTheCall(int callID) {
logger->debug("Holding callID=%d...", callID);
ITBasicCallControl* callControl = getCallControl(callID);
if (NULL != callControl) {
bool swapIt = swapOnHold;
HRESULT hr;
if(!swapIt) {
hr = callControl->Hold(VARIANT_TRUE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -