wanpipe/api/libstelephony/stelephony.cpp

405 lines
10 KiB
C++

////////////////////////////////////////////////////////////////////////////////////
//stelephony.cpp - Definitions of the main class of the Sangoma Telephony Library
// (CStelephony).
//
// Author : David Rokhvarg <davidr@sangoma.com>
//
// Versions:
// v 1,0,0,1 May 29 2008 David Rokhvarg Initial Version
// Implemented FSK Caller ID detection for Analog FXO.
//
////////////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <stdio.h>
#include "stelephony.h"
#define DBG_STEL if(0)printf
CStelephony::CStelephony()
{
STEL_FUNC();
memset(&callback_functions, 0x00, sizeof(stelephony_callback_functions_t));
InitializeCriticalSection(&m_CriticalSection);
return;
}
CStelephony::~CStelephony()
{
STEL_FUNC();
return;
}
void CStelephony::SetCallbackFunctions(IN stelephony_callback_functions_t *cbf)
{
memcpy(&callback_functions, cbf, sizeof(stelephony_callback_functions_t));
if(cbf->Q931Event){
DBG_STEL("%s(): cbf->Q931Event: 0x%p\n", __FUNCTION__, cbf->Q931Event);
q931_event_decoder_callback_functions_t q931_cbf;
q931_cbf.OnQ931Event = cbf->Q931Event;
Q931EventsDecoderObj.SetCallbackFunctions(&q931_cbf);
}
}
void CStelephony::GetCallbackFunctions(OUT stelephony_callback_functions_t *cbf)
{
memcpy(cbf, &callback_functions, sizeof(stelephony_callback_functions_t));
}
void CStelephony::SetCallbackContext(void *cbc)
{
callback_context = cbc;
Q931EventsDecoderObj.SetCallbackObject(cbc);
}
void* CStelephony::GetCallbackContext(void)
{
return callback_context;
}
stelephony_status_t CStelephony::Init()
{
STEL_FUNC();
stelephony_status_t status = STEL_STATUS_SUCCESS;
status = InitDecoderLib();
if (status != STEL_STATUS_SUCCESS) return status;
status = InitEncoderLib();
if (status != STEL_STATUS_SUCCESS) return status;
return STEL_STATUS_SUCCESS;
}
stelephony_status_t CStelephony::Cleanup()
{
STEL_FUNC();
stelephony_status_t status = STEL_STATUS_SUCCESS;
status = CleanupDecoderLib();
if (status != STEL_STATUS_SUCCESS) return status;
status = CleanupEncoderLib();
if (status != STEL_STATUS_SUCCESS) return status;
return STEL_STATUS_SUCCESS;
}
stelephony_status_t CStelephony::InitDecoderLib()
{
if (ToneDecoderObj.Init()) {
return STEL_STATUS_INVALID_INPUT_ERROR;
}
return STEL_STATUS_SUCCESS;
}
stelephony_status_t CStelephony::InitEncoderLib()
{
if (ToneEncoderObj.Init()) {
return STEL_STATUS_INVALID_INPUT_ERROR;
}
return STEL_STATUS_SUCCESS;
}
stelephony_status_t CStelephony::CleanupDecoderLib()
{
ToneDecoderObj.WaveStreamEnd();
return STEL_STATUS_SUCCESS;
}
stelephony_status_t CStelephony::CleanupEncoderLib()
{
ToneEncoderObj.WaveStreamEnd();
return STEL_STATUS_SUCCESS;
}
int CStelephony::DecoderLibStreamInput(void *data, int dataLength)
{
//If user enabled FSK CallerID or SoftwareDTMF, call ToneDecoder with (voice) StreamInput.
if(callback_functions.FSKCallerIDEvent || callback_functions.DTMFEvent){
int retvalue, rc;
rc = ToneDecoderObj.WaveStreamInputEx((char*)data, dataLength, &retvalue);
//printf("retvalue: %d, rc: %d\n", retvalue, rc);
}
if(callback_functions.Q931Event){
Q931EventsDecoderObj.Input(data, dataLength);
}
return 0;
}
stelephony_status_t CStelephony::EncoderLibGenerateFSKCallerID(stelephony_caller_id_t* cid_info)
{
int retValue, rc;
rc = ToneEncoderObj.BufferGetFSKCallerID(cid_info, &retValue);
if (rc) {
return STEL_STATUS_ENCODER_LIB_ERROR;
}
return STEL_STATUS_SUCCESS;
}
stelephony_status_t CStelephony::EncoderLibGenerateSwDTMF(char dtmf_char)
{
int retValue, rc;
rc = ToneEncoderObj.BufferGetSwDTMF(dtmf_char, &retValue);
if (rc) {
return STEL_STATUS_ENCODER_LIB_ERROR;
}
return STEL_STATUS_SUCCESS;
}
void OnCallerID(void *callback_obj, char *Name, char *CallerNumber, char *CalledNumber, char *DateTime)
{
CStelephony* stelObj = (CStelephony*)callback_obj;
stelephony_callback_functions_t cbf;
DBG_STEL("%s(): Name: %s(%zu), CallerNumber: %s(%zu), CalledNumber: %s, DateTime: %s\r\n",
__FUNCTION__, Name, strlen(Name), CallerNumber, strlen(CallerNumber), CalledNumber, DateTime);
stelObj->GetCallbackFunctions(&cbf);
if(cbf.FSKCallerIDEvent){
cbf.FSKCallerIDEvent(stelObj->GetCallbackContext(), Name, CallerNumber, CalledNumber, DateTime);
}
}
void OnDTMF(void *callback_obj, long Key)
{
CStelephony* stelObj = (CStelephony*)callback_obj;
stelephony_callback_functions_t cbf;
DBG_STEL("%s(): Key: %c\r\n", __FUNCTION__, (int) Key);
stelObj->GetCallbackFunctions(&cbf);
if(cbf.DTMFEvent){
cbf.DTMFEvent(stelObj->GetCallbackContext(), Key);
}
}
void OnFSKCallerIDTransmit(void *callback_obj, buffer_t* buffer)
{
CStelephony* stelObj = (CStelephony*)callback_obj;
stelephony_callback_functions_t cbf;
stelObj->GetCallbackFunctions(&cbf);
if(cbf.FSKCallerIDTransmit){
cbf.FSKCallerIDTransmit(stelObj->GetCallbackContext(), buffer);
} else {
STEL_ERR("No CallerID Transmit callback function\n");
}
}
void OnSwDtmfTransmit(void *callback_obj, buffer_t* buffer)
{
CStelephony* stelObj = (CStelephony*)callback_obj;
stelephony_callback_functions_t cbf;
stelObj->GetCallbackFunctions(&cbf);
STEL_FUNC();
//call DTMF generation callback so user will transmit it.
if (cbf.SwDTMFBuffer) {
cbf.SwDTMFBuffer(stelObj->GetCallbackContext(), buffer);
} else {
STEL_ERR("No OnSwDtmfTransmit() callback function\n");
}
}
stelephony_status_t CStelephony::ToneEncoderEventControl(stelephony_event_t Event, stelephony_control_code_t ControlCode, void *optionalData)
{
//get current callback functions
sink_callback_functions_t scf;
ToneEncoderObj.GetCallbackFunctions(&scf);
switch(Event)
{
case STEL_FEATURE_FSK_CALLER_ID:
case STEL_FEATURE_SW_DTMF:
switch(ControlCode)
{
case STEL_CTRL_CODE_ENABLE:
switch(Event)
{
case STEL_FEATURE_FSK_CALLER_ID:
scf.OnFSKCallerIDTransmit = OnFSKCallerIDTransmit;
break;
case STEL_FEATURE_SW_DTMF:
scf.OnSwDtmfTransmit = OnSwDtmfTransmit;
break;
default:
return STEL_STATUS_INVALID_EVENT_ERROR;
}
m_ToneEncoderCodec = *(stelephony_option_t*)optionalData;
VARIANT var;
var.vt=VT_UI4;
if(m_ToneEncoderCodec == STEL_OPTION_ALAW){
var.intVal=WFI_CCITT_ALaw_8kHzMono;
}else{
var.intVal=WFI_CCITT_uLaw_8kHzMono;
}
ToneEncoderObj.WaveStreamEnd();
ToneEncoderObj.put_WaveFormatID(var);
ToneEncoderObj.put_FeatureFSKCallerID(TRUE);
ToneEncoderObj.put_FeatureSwDTMF(TRUE);
ToneEncoderObj.SetCallbackFunctionsAndObject(&scf, this);
ToneEncoderObj.WaveStreamStart();
break;
case STEL_CTRL_CODE_DISABLE:
switch(Event)
{
case STEL_FEATURE_FSK_CALLER_ID:
scf.OnFSKCallerIDTransmit = NULL;
break;
case STEL_FEATURE_SW_DTMF:
scf.OnSwDtmfTransmit = NULL;
break;
default:
return STEL_STATUS_INVALID_EVENT_ERROR;
}
ToneEncoderObj.WaveStreamEnd();
ToneEncoderObj.SetCallbackFunctionsAndObject(&scf, this);
break;
}
break;
default:
return STEL_STATUS_INVALID_EVENT_ERROR;
}
return STEL_STATUS_SUCCESS;
}
stelephony_status_t CStelephony::ToneDecoderEventControl(stelephony_event_t Event, stelephony_control_code_t ControlCode, void *optionalData)
{
//get current callback functions
sink_callback_functions_t scf;
ToneDecoderObj.GetCallbackFunctions(&scf);
//add/remove a function
switch(Event)
{
case STEL_EVENT_FSK_CALLER_ID:
case STEL_EVENT_DTMF:
switch(ControlCode)
{
case STEL_CTRL_CODE_ENABLE:
switch(Event)
{
case STEL_EVENT_Q931:
STEL_ERR("Q931 event not handled\n");
break;
case STEL_EVENT_FSK_CALLER_ID:
scf.OnCallerID = OnCallerID;
ToneDecoderObj.put_MonitorCallerID(TRUE);
break;
case STEL_EVENT_DTMF:
scf.OnDTMF = OnDTMF;
ToneDecoderObj.put_MonitorDTMF(TRUE);
break;
default:
return STEL_STATUS_INVALID_EVENT_ERROR;
}
m_ToneDecoderCodec = *(stelephony_option_t*)optionalData;
ToneDecoderObj.WaveStreamEnd();//stop stream, just in case it was running before.
VARIANT var;
var.vt=VT_UI4;
if(m_ToneDecoderCodec == STEL_OPTION_ALAW){
var.intVal=WFI_CCITT_ALaw_8kHzMono;
}else{
var.intVal=WFI_CCITT_uLaw_8kHzMono;
}
ToneDecoderObj.put_WaveFormatID(var);
ToneDecoderObj.WaveStreamStart();
break;
case STEL_CTRL_CODE_DISABLE:
switch(Event)
{
case STEL_EVENT_Q931:
STEL_ERR("Q931 event not handled\n");
break;
case STEL_EVENT_FSK_CALLER_ID:
scf.OnCallerID = NULL;
ToneDecoderObj.put_MonitorCallerID(FALSE);
break;
case STEL_EVENT_DTMF:
scf.OnDTMF = NULL;
ToneDecoderObj.put_MonitorDTMF(FALSE);
break;
default:
return STEL_STATUS_INVALID_EVENT_ERROR;
}
break;
}
break;
default:
return STEL_STATUS_INVALID_EVENT_ERROR;
}
ToneDecoderObj.SetCallbackFunctionsAndObject(&scf, this);
return STEL_STATUS_SUCCESS;
}
stelephony_status_t CStelephony::EventControl(stelephony_event_t Event, stelephony_control_code_t ControlCode, void *optionalData)
{
switch(Event)
{
case STEL_EVENT_FSK_CALLER_ID:
case STEL_EVENT_DTMF:
return ToneDecoderEventControl(Event, ControlCode, optionalData);
case STEL_FEATURE_FSK_CALLER_ID:
case STEL_FEATURE_SW_DTMF:
return ToneEncoderEventControl(Event, ControlCode, optionalData);
case STEL_EVENT_Q931:
return Q931EventsDecoderObj.EventControl(Event, ControlCode, optionalData);
default:
return STEL_STATUS_INVALID_EVENT_ERROR;
}
}
void CStelephony::EnterStelCriticalSection()
{
EnterCriticalSection(&m_CriticalSection);
}
void CStelephony::LeaveStelCriticalSection()
{
LeaveCriticalSection(&m_CriticalSection);
}
/*
///////////////////////////////////////////////////
FSK Decoder test results:
fsk file name: test-caller-id-stel.wav
old FSK CID library:
wanpipe1_if3: FSKCallerIDEvent() - Start
Name: DAVID
CallerNumber: 98765555
DateTime: 03-04 13:53
FSKCallerIDEvent() - End
new (open source) FSK CID library:
wanpipe22_if1: FSKCallerIDEvent() - Start
Name: DAVID
CallerNumber: 98765555
CalledNumber: Private
DateTime: 03041353
FSKCallerIDEvent() - End
///////////////////////////////////////////////////
*/