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

📄 simpletapi.cpp

📁 DOS下采用中断接收数据的串口通讯的例子,很难找到的好东西!
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    if ( result != 0 )
        ::MessageBox( GetWindow(),
                      "Something bad happened",
                      "SimpleTapi Message",
                      MB_OK );
}

//
// Configuring phone calls is another fairly difficult task 
// that TAPI takes on for us. All we have to do is pass in
// the ID of the device and the phone number to be called.
// TAPI then creates a dialog that takes care of thinking 
// about all sorts of dialing issues.
//
void SimpleTapi::ConfigureCall( int index, const string &number )
{
    int dev_id = m_Devices[ index ].m_iDeviceNumber;
    LONG result = lineTranslateDialog( m_hLineApp,
                                       dev_id,
                                       TAPI_CURRENT_VERSION,
                                       GetWindow(),
                                       number.c_str() );
    if ( result != 0 )
        Error( "Error returned from lineTranslateDialog : ",
               result );
}

//
// If a line is open and doesn't have a call in progress, we 
// can use this routine to initiate a call. Looking down into
// the call, you can see that you need to have a valid m_hLine
// handle to make the call, along with a number and a device
// id. The first part of the function calls 
// lineTranslateAddress() to mangle the digit string into
// something that can be used to make the call. It needs the
// device ID and the phone number to do that.
//
// Once the phone number has been properly mangled, we set up
// a LINECALLPARMS structure and make a call to lineMakeCall.
// That function can do one of three things. It might fail
// with an error, It might return immediately with a valid 
// result. But most likely, it will tell me that it doesn't 
// have a result yet, and I'll just have to wait. When that 
// happens, I set up the m_ReplyAction so that I know I'm
// expecting something, and I return.
//
// Note that when you call this function, or the other 
// asynchronous functions in SimpleTapi, you never get 
// anything useful back, which is why these guys are all of
// type void. You wait for response to come back from the
// callback notification routines.
//

void SimpleTapi::MakeCall( const string &number )
{
    //
    // This first call is another one of those with an
    // indeterminate requirement for the size of the 
    // data structure. The Redmond way is to call it twice,
    // the first time you will fail but find out how much
    // space you need. The second time you call it with the
    // correct amount of space. I thwart this strategy by
    // allocating a hugely excessive amount of space so 
    // that I'll never fail. probably.
    //
    char buf[ 4096 ];
    LINETRANSLATEOUTPUT *lto = (LINETRANSLATEOUTPUT *) buf;
    lto->dwTotalSize = 4096;
    LONG result = lineTranslateAddress( m_hLineApp,
                                        m_iDeviceId,
                                        TAPI_CURRENT_VERSION,
                                        number.c_str(),
                                        0,
                                        0,
                                        lto );
    if ( result != 0 ) {
        Error( "Error returned from lineTranslateAddress : ", result );
        return;
    }
    m_sNumber = string( buf + lto->dwDialableStringOffset, 
                        lto->dwDialableStringSize );
    m_Trace << "Dial number = "
            << m_sNumber
            << "\n";
    LINECALLPARAMS lcp;
    memset( &lcp, 0, sizeof( LINECALLPARAMS ) );
    lcp.dwTotalSize = sizeof( LINECALLPARAMS );
    lcp.dwBearerMode = LINEBEARERMODE_VOICE;
    lcp.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
    lcp.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
    lcp.dwAddressMode = LINEADDRESSMODE_ADDRESSID;

    result = lineMakeCall( m_hLine,
                           &m_hCall,
                           m_sNumber.c_str(),
                           0,
                           &lcp );

    if ( result < 0 ) {
        Error( "Error returned from lineMakeCall : ", result );
        return;
    } else if ( result == 0 ) {
        m_Trace << "lineMakeCall returned : "
                << TranslateTapiError( result )
                << "\n";
        HandleMakeCallResult( 0 );
    } else {
        m_ReplyAction = HANDLE_MAKE_CALL_RESULT;
        m_dwPendingReplyCode = result;
    }
}

//
// Dropping a call is easier than making one, but it still
// has to be dealt with asynchronously. All we need to 
// get the whole thing going is a call handle, which we
// pass to lineDrop(). It might generate an eerror, or an
// immediate response, but most likely it will let us 
// know that it will get back to us later via notification
// We make a note of that by setting the m_ReplyAction
// enumerated value to signify that we are waiting for a 
// drop result.
//
void SimpleTapi::DropCall()
{
    LONG result = lineDrop( m_hCall,
                            NULL,
                            0 );
    if ( result < 0 ) {
        Error( "Error returned from lineDrop : ", result );
        return;
    } else if ( result == 0 ) {
        m_Trace << "lineDrop returned : "
                << dec << result
                << "\n";
        HandleDropResult( 0 );
    } else {
        m_ReplyAction = HANDLE_DROP_RESULT;
        m_dwPendingReplyCode = result;
    }
}

//
// These three functions are all fundamentally the same.
// Each of them is called when a delayed response comes
// in to a previous action, which is either a request to
// make a call, answer a call, or drop a call.
//
// Each of the functions does a small amount of internal
// class maintenance. Two of the functions then call a
// user notification function. The two notification functions
// are pure virtual, so they must be defined in a derived
// class.
//
// Why doesn't the Answer handler have a notification 
// routine? SimpleTapi doesn't have an Answer call that the
// user of the class can call. Instead, it automatically 
// answers any incoming call. So the user doesn't ever have
// to worry about a response to an Answer call. A more 
// completel TAPI class wouldn't automatically answer calls;
// it would notify users of incoming offering states and
// let the user make some sort of answer response.
//
void SimpleTapi::HandleMakeCallResult( DWORD result )
{
    m_Trace << "lineMakeCall returned (delayed) : "
            << TranslateTapiError( result )
            << "\n";
    if ( result == 0 )
        m_bCallHandleValid = true;
    else {
        Error( "Delayed error returned from lineMakeCall : ", result );
        m_bCallHandleValid = false;
    }
    MakeCallResult( m_bCallHandleValid );
}

void SimpleTapi::HandleAnswerResult( DWORD result )
{
    m_Trace << "lineAnswer returned (delayed) : " 
            << result
            << "\n";
    if ( result == 0 )
        m_bCallHandleValid = true;
    else {
        Error( "Delayed error returned from lineAnswer : ", result );
        m_bCallHandleValid = false;
    }
}

void SimpleTapi::HandleDropResult( DWORD result )
{
    m_Trace << "lineDrop returned (delayed) : "
            << result
            << "\n";
    if ( result != 0 ) 
        Error( "Delayed error returned from lineDrop : ", result );
    DropCallResult( result == 0 );
}

//
// After creating the TAPI object, the user has to open a 
// line to do antyhing useful at all. This is done with a
// call to lineOpen(). That call expects a valid device
// id, which we get from the caller, and an app handle,
// which was created when the object was first built.
//
// The device ID is retrieved from the m_Devices[] vector,
// which got copies of all device names and IDs when we
// iterated through the list at creation time.
// 
// If we opne the line succesfully, the m_hLine member will
// then have a valid handle, and we are ready to make and
// accept calls.
//
int SimpleTapi::OpenLine( int index )
{
    m_iDeviceId = m_Devices[ index ].m_iDeviceNumber;
    LONG result = lineOpen( m_hLineApp,
                            m_iDeviceId,
                            &m_hLine,
                            TAPI_CURRENT_VERSION,
                            0,
                            (DWORD) this,
                            LINECALLPRIVILEGE_OWNER,
                            LINEMEDIAMODE_DATAMODEM,
                            NULL );
    if ( result != 0 )
        Error( "Error returned in WaitFoprCall from lineOpen : ", result );
    else
        NotifyCallStateChange( LINECALLSTATE_IDLE );
    return result;
}

//
// Before shutting down we really need to close the line.
// This is also a good way to make sure we don't accidentally
// answer any incoming calls. TAPI function lineClose() 
// takes care of this immediately.
int SimpleTapi::CloseLine()
{
    LONG result = lineClose( m_hLine );
    m_hLine = 0;
    if ( result < 0 )
        Error( "Error returned from lineClose : ", result );
    else {
        m_Trace << "lineClose returned : "
                << result
                << "\n";
        NotifyCallStateChange( -1 );
    }
    return result;
}

//
// This function is a little deceptive. After a call is put
// through to the connected state, we can take the resulting
// handle and treat it as a port handle, using it for normal
// serial port functions. In the Chapter 15 example we take 
// the resulting port handle and turn it into a Win32Port, 
// and proceed to use it as a terminal emulator.
//
// Once we get this port handle, we bear a certain measure 
// of responsibility for it. When we are done using it, we
// have to specifically close it with a call to 
// CloseHandle(), or the books in the O/S won't balance.
//
HANDLE SimpleTapi::GetPortHandle()
{
    //
    // This is another one of those calls that take an
    // unknown number of byte. I drastically overestimate 
    // the amount in hopes that I won't have to deal with
    // possibility of failure.
    //
    char temp[ 4096 ];
    VARSTRING *vs = (VARSTRING *) temp;
    vs->dwTotalSize = 4096;

    LONG result = lineGetID( 0,                    //hLine
                             0,                    //dwAddressID
                             m_hCall,              //hCall
                             LINECALLSELECT_CALL,  //dwSelect
                             vs,
                             "comm/datamodem" );
    if ( result < 0 ) {
        Error( "Error returned from lineGetID : ", result );
        return 0;
    }
    HANDLE *p = (HANDLE *) ((LPSTR) vs + vs->dwStringOffset);
    return *p;
}

//EOF SimpleTapi.cpp

⌨️ 快捷键说明

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