⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tapiutils.cpp

📁 一个采用TAPI编程的电话拨号程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// TAPIUTILS.CPP
//
// This module implements the CTapiConnection class.
//
#include "stdafx.h"
#include <string.h>
#include "TapiUtils.h"

// All TAPI line functions return 0 for SUCCESS, so define it.
#define SUCCESS 0

// TAPI version that this sample is designed to use.
#define SAMPLE_TAPI_VERSION 0x00010004

// Early TAPI version
#define EARLY_TAPI_VERSION 0x00010003

// Possible return error for resynchronization functions.
#define WAITERR_WAITABORTED  1

// A pointer to my class because TAPI needs a callback
CTapiConnection *MyThis;

#if FALSE
// Structures needed to handle special non-dialable characters.
#define g_sizeofNonDialable (sizeof(g_sNonDialable)/sizeof(g_sNonDialable[0]))

typedef struct {
    LONG lError;
    DWORD dwDevCapFlag;
    LPSTR szToken;
    LPSTR szMsg;
} NONDIALTOKENS;

NONDIALTOKENS g_sNonDialable[] = {
    {LINEERR_DIALBILLING,  LINEDEVCAPFLAGS_DIALBILLING,  "$", 
            "Wait for the credit card bong tone" },
    {LINEERR_DIALDIALTONE, LINEDEVCAPFLAGS_DIALDIALTONE, "W", 
            "Wait for the second dial tone" },
    {LINEERR_DIALDIALTONE, LINEDEVCAPFLAGS_DIALDIALTONE, "w", 
            "Wait for the second dial tone" },
    {LINEERR_DIALQUIET,    LINEDEVCAPFLAGS_DIALQUIET,    "@", 
            "Wait for the remote end to answer" },
    {LINEERR_DIALPROMPT,   0,                            "?", 
            "Press OK when you are ready to continue dialing"},
};
#endif

// 
// Constructor
//
CTapiConnection::CTapiConnection()
{
    m_bShuttingDown = FALSE;
    m_bStoppingCall = FALSE;
    m_bInitializing = FALSE;
    m_bTapiInUse = FALSE;
    m_dwNumDevs = 0;
    m_hCall = NULL;
    m_hLine = NULL;
    m_dwDeviceID = 0;
    m_hLineApp = NULL;

    MyThis = this;

};

//
// Destructor
//
CTapiConnection::~CTapiConnection()
{
    m_bInitialized = FALSE;
};

//
//  FUNCTION: BOOL Create()
//
//  PURPOSE: Initializes TAPI
//
BOOL CTapiConnection::Create(char *szPhoneNumber)
{
    long lReturn;

    // If we're already initialized, then initialization succeeds.
    if (m_hLineApp)
        return TRUE;

    // If we're in the middle of initializing, then fail, we're not done.
    if (m_bInitializing)
        return FALSE;

    m_bInitializing = TRUE;

    // Initialize TAPI
    do
    {
        lReturn = ::lineInitialize(&m_hLineApp, 
            AfxGetInstanceHandle(), 
            lineCallbackFunc, 
            "DialIt", 
            &m_dwNumDevs);

        if (m_dwNumDevs == 0)
        {
            AfxMessageBox("There are no telephony devices installed.");
            m_bInitializing = FALSE;
            return FALSE;
        }

        if (HandleLineErr(lReturn))
            continue;
        else
        {
            OutputDebugString("lineInitialize unhandled error\n");
            m_bInitializing = FALSE;
            return FALSE;
        }
    }
    while(lReturn != SUCCESS);

    OutputDebugString("Tapi initialized.\n");

    // If the user furnished a phone number copy it over.
    if (szPhoneNumber)
        strcpy(m_szPhoneNumber, szPhoneNumber);

    m_bInitializing = FALSE;
    return TRUE;
}

//
//  FUNCTION: DialCall()
//
//  PURPOSE: Get a number from the user and dial it.
//
BOOL CTapiConnection::DialCall(char *szPhoneNumber)
{
    long lReturn;
    LPLINEDEVCAPS lpLineDevCaps = NULL;

    if (m_bTapiInUse)
    {
        AfxMessageBox("A call is already being handled.");
        return FALSE;
    }

    // Make sure TAPI is initialized properly
    if (!m_hLineApp)
    {
        if (!Create(NULL))
            return FALSE;
    }

    // If there are no line devices installed on the machine, quit.
    if (m_dwNumDevs < 1)
        return FALSE;

    // We now have a call active.  Prevent future calls.
    m_bTapiInUse = TRUE;

    // Get a phone number from the user.
    if (szPhoneNumber == (char *)NULL)
    {
        if (m_szPhoneNumber == (char *)NULL)
        {
            HangupCall();
            goto DeleteBuffers;
        }
    }
    else 
        strcpy(m_szPhoneNumber, szPhoneNumber);

    // Get the line to use
    lpLineDevCaps = GetDeviceLine(&m_dwAPIVersion, lpLineDevCaps);

    // Need to check the DevCaps to make sure this line is usable.
    if (lpLineDevCaps == NULL)
    {
        OutputDebugString("Error on Requested line\n");
        goto DeleteBuffers;
    }

    if (!(lpLineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE ))
    {
        AfxMessageBox("The selected line doesn't support VOICE capabilities");
        goto DeleteBuffers;
    }

    // Does this line have the capability to make calls?
    if (!(lpLineDevCaps->dwLineFeatures & LINEFEATURE_MAKECALL))
    {
        AfxMessageBox("The selected line doesn't support MAKECALL capabilities");
        goto DeleteBuffers;
    }

    // Does this line have the capability for interactive voice?
    if (!(lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE))
    {
        AfxMessageBox("The selected line doesn't support INTERACTIVE VOICE capabilities");
        goto DeleteBuffers;
    }

    // Open the Line for an outgoing call.
    do
    {
        lReturn = ::lineOpen(m_hLineApp, m_dwDeviceID, &m_hLine,
            m_dwAPIVersion, 0, 0,
            LINECALLPRIVILEGE_NONE, 0, 0);

        if((lReturn == LINEERR_ALLOCATED)||(lReturn == LINEERR_RESOURCEUNAVAIL))
        {
            HangupCall();
            OutputDebugString("Line is already in use by a non-TAPI application "
                "or by another TAPI Service Provider.\n");
            goto DeleteBuffers;
        }

        if (HandleLineErr(lReturn))
            continue;
        else
        {
            OutputDebugString("Unable to Use Line\n");
            HangupCall();
            goto DeleteBuffers;
        }
    }
    while(lReturn != SUCCESS);

    // Start dialing the number
    if( MakeTheCall(lpLineDevCaps, m_szPhoneNumber))
        OutputDebugString("lineMakeCall succeeded.\n");
    else
    {
        OutputDebugString("lineMakeCall failed.\n");
        HangupCall();
    }

DeleteBuffers:

    if (lpLineDevCaps)
        LocalFree(lpLineDevCaps);

    return m_bTapiInUse;
}

//
//  FUNCTION: void GetDeviceLine()
//
//  PURPOSE: Gets the first available line device.
//
//
LPLINEDEVCAPS CTapiConnection::GetDeviceLine(DWORD *pdwAPIVersion, LPLINEDEVCAPS lpLineDevCaps)
{
    DWORD dwDeviceID;
    char szLineUnavail[] = "Line Unavailable";
    char szLineUnnamed[] = "Line Unnamed";
    char szLineNameEmpty[] = "Line Name is Empty";
    LPSTR lpszLineName;
    long lReturn;
    char buf[MAX_PATH];
    LINEEXTENSIONID lineExtID;
    BOOL bDone = FALSE;

    for (dwDeviceID = 0; (dwDeviceID < m_dwNumDevs) && !bDone; dwDeviceID ++)
    {

        lReturn = ::lineNegotiateAPIVersion(m_hLineApp, dwDeviceID, 
            EARLY_TAPI_VERSION, SAMPLE_TAPI_VERSION,
            pdwAPIVersion, &lineExtID);

        if ((HandleLineErr(lReturn))&&(*pdwAPIVersion))
        {
            lpLineDevCaps = MylineGetDevCaps(lpLineDevCaps, dwDeviceID, *pdwAPIVersion);

            if ((lpLineDevCaps -> dwLineNameSize) &&
                (lpLineDevCaps -> dwLineNameOffset) &&
                (lpLineDevCaps -> dwStringFormat == STRINGFORMAT_ASCII))
            {
                // This is the name of the device.
                lpszLineName = ((char *) lpLineDevCaps) + 
                    lpLineDevCaps -> dwLineNameOffset;
                sprintf(buf, "Name of device is: %s\n", lpszLineName);
                OutputDebugString(buf);

            }
            else  // DevCaps doesn't have a valid line name.  Unnamed.
                lpszLineName = szLineUnnamed;
        }
        else  // Couldn't NegotiateAPIVersion.  Line is unavail.
            lpszLineName = szLineUnavail;

        // If this line is usable and we don't have a default initial
        // line yet, make this the initial line.
        if ((lpszLineName != szLineUnavail) && 
            (lReturn == SUCCESS )) 
        {          
            m_dwDeviceID = dwDeviceID;
            bDone = TRUE;
        }
        else 
            m_dwDeviceID = MAXDWORD;
    }
    return (lpLineDevCaps);
}

//
//  FUNCTION: MylineGetDevCaps(LPLINEDEVCAPS, DWORD , DWORD)
//
//  PURPOSE: Gets a LINEDEVCAPS structure for the specified line.
//
//  COMMENTS:
//
//    This function is a wrapper around lineGetDevCaps to make it easy
//    to handle the variable sized structure and any errors received.
//    
//    The returned structure has been allocated with LocalAlloc,
//    so LocalFree has to be called on it when you're finished with it,
//    or there will be a memory leak.
//
//    Similarly, if a lpLineDevCaps structure is passed in, it *must*
//    have been allocated with LocalAlloc and it could potentially be 
//    LocalFree()d.
//
//    If lpLineDevCaps == NULL, then a new structure is allocated.  It is
//    normal to pass in NULL for this parameter unless you want to use a 
//    lpLineDevCaps that has been returned by a previous I_lineGetDevCaps
//    call.
//
//

LPLINEDEVCAPS CTapiConnection::MylineGetDevCaps(
    LPLINEDEVCAPS lpLineDevCaps,
    DWORD dwDeviceID, DWORD dwAPIVersion)
{
    // Allocate enough space for the structure plus 1024.
    size_t sizeofLineDevCaps = sizeof(LINEDEVCAPS) + 1024;
    long lReturn;
    
    // Continue this loop until the structure is big enough.
    while(TRUE)
    {
        // Make sure the buffer exists, is valid and big enough.
        lpLineDevCaps = 
            (LPLINEDEVCAPS) CheckAndReAllocBuffer(
                (LPVOID) lpLineDevCaps, // Pointer to existing buffer, if any
                sizeofLineDevCaps);      // Minimum size the buffer should be

        if (lpLineDevCaps == NULL)
            return NULL;

        // Make the call to fill the structure.
        do
        {            

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -