Click here to Skip to main content
Click here to Skip to main content

Simplified TAPI and Serial communication through CTapiLine class

, 27 Dec 2004
Rate this:
Please Sign up or sign in to vote.
Simple tutorial on TAPI 2.x using TAPISample dialog app with CTapiLine class

Sample Image - TAPISample.jpg

Introduction

Microsoft TAPI (Telephony API) in Windows provides telephony functionality for the application, it is a bit confusing for programmers. I have many friends asking me the same question how to connect and communicate through modem. Finally, I came up with this sample tool to do the coaching. I tried to keep this tool source bare minimum to get an easy hold of TAPI programming even though I got to do some juggling. Here, I have used TAPI 2.0. TAPI 3.0 and above is much more simplified and easy to use.

About TAPI

Microsoft TAPI supports a wide variety of devices operating on voice grade lines, ISDN lines, and private branch exchanges. It provides services for placing outgoing calls, accepting incoming calls and managing calls, devices, etc. It simplifies the complexity to program telephony applications. You can ignore the need to know about modem initialization string, AT command and all other strenuous stuffs. TAPI is an abstraction layer built on top of TSPs (Telephony Service Providers). TSPs are the components that provide hardware or service-specific functionality. TSPs are specific to hardware. When an application requests that a telephony device perform an action, TAPI figures out which TSP services that device and makes a call to it. Then TSP will do the rest. Writing TSPs are the next level in telephony development. Rest of this article, leaving the TSPs, I’m explaining only TAPI programming.

TAPI is classified into five parts. Those are LineApp, Line, Call, PhoneApp and Phone. These parts in TAPI are depicted in the picture below:

LineApp: A LineApp is created when lineInitializeEx is called, and destroyed when lineShutdown is called. A process can create multiple LineApps if necessary, but need at least one to access TAPI. Each LineApp represents a distinct TAPI session.

Line: Lines are created by an application's call to lineOpen and are represented by their Line handles. In the end, these Line handles are closed by lineClose. Line devices are owned by the LineApp, and multiple Lines can be owned concurrently by a single LineApp. Lines are most commonly used for call control purposes.

Call: Application creates a call by making a call using lineMakeCall or answering an incoming call using lineAnswer. An application can destroy the call by calling lineDrop. Each Call is identified by a Call handle. Calls are created on a Line, and so are always associated with Line. Though a Call is always owned by a Line, the relationship is not necessarily one-to-one. A single Line can own more than one call. Call waiting and conferencing are other examples.

PhoneApp: A PhoneApp is created when phoneInitializeEx is called, and destroyed when phoneShutdown is called. A process can create multiple PhoneApps if necessary but need at least one to access phone specific TAPIs. Each PhoenApp represents a distinct TAPI session.

Phone: Phone is created by calling phoneOpen TAPI and destroyed by calling phoneClose TAPI. Phone is a logical representation of the terminal equipment. As in the physical telephony world, Phone can be used without calls. For example, you can use a telephone as an interface to a voice mail, SMS, etc.

In this example, totally excluding the PhoneApp and Phone sections, I concentrated on the first three connection-oriented parts. Take a look at the CTapiLine class; I feel it is comprehensive enough to teach call making and answering procedures.

CTapiLine class

This class is not a complete wrapper for TAPI as I said earlier. It posses a minimal set to make or answer a call. All the methods in this class return zero for success and non-zero for failure (other than the HANDLE return).

Open: Open method is the initial method to call. Inside this, it initializes the LineApp and opens the Line. It can open the line in any one of the two modes. First mode opens in the data/fax mode and the other opens in voice mode. To make your PC as an answering machine, you should open in the second mode. The first mode only connects or answers a data call. On successful open, it starts a thread to monitor the line message. Successful connection is notified through one of these messages.

MakeOutgoingCall: This method takes number string as the parameter and dials. It doesn't retrieve or prompt any other sophisticated dialing details. This method should be modified if it needs to dial country code, area code, etc. The simple code in this method is as follows:

LPLINECALLPARAMS lpCallParams;

lpCallParams = (LPLINECALLPARAMS)malloc(sizeof(LINECALLPARAMS)+1024);

memset(lpCallParams,0,sizeof(LINECALLPARAMS)+1024);

lpCallParams->dwTotalSize = sizeof(LINECALLPARAMS)+1024;

// This is where we configure the line for DATAMODEM usage.
lpCallParams->dwBearerMode = LINEBEARERMODE_VOICE;
lpCallParams->dwMediaMode  = LINEMEDIAMODE_DATAMODEM;

// This specifies that we want to use only IDLE calls and
// don't want to cut into a call that might not be IDLE (ie, in use).
lpCallParams->dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;

// if there are multiple addresses on line, use first anyway.
// It will take a more complex application than a simple tty app
// to use multiple addresses on a line anyway.
lpCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
lpCallParams->dwAddressID = 0;

// Address we are dialing.
lpCallParams->dwDisplayableAddressOffset = sizeof(LINECALLPARAMS);
lpCallParams->dwDisplayableAddressSize = strlen(szAddress);
strcpy((LPSTR)lpCallParams+sizeof(LINECALLPARAMS), szAddress);

lRet = lineMakeCall(m_hLine, &m_hCall, szAddress, 0, lpCallParams);

GetIncomingCall: This is a blocking method. Until a call comes, it blocks. After a call, it tries to answer and if it is successful, it returns zero. Success does not mean connected. The code, which answers, is...

// Now we wait for notification.
switch(WaitForSingleObject(m_hEventFromThread, INFINITE))
{
case WAIT_OBJECT_0:
    if(m_dwLineMsg == LINECALLSTATE_OFFERING)
    {        // answer the call
        lRet = lineAnswer(m_hCall, NULL, 0);
        lRet = (lRet>0)?0:lRet;

        if(lRet)
            Close();
        return lRet;
    }
    break;
case WAIT_TIMEOUT:
    return ERROR_TIMEOUT;
};

Message monitoring thread will indicate through an event when a call comes. Then this method answers by calling lineAnswer TAPI.

GetHandle: This returns the HANDLE of the requested class only after successful connection. This handle is very similar to what you would get by opening the COM port using the CreateFile API. By default, the handle is opened for overlapped I/O operation. After use, retrieved process should close this handle. Check the code below, it retrieves the HANDLE for serial communication:

VARSTRING *pvarStrDevID = (VARSTRING *)malloc(sizeof(VARSTRING)+255);

memset(pvarStrDevID,0,sizeof(VARSTRING)+255);
pvarStrDevID->dwTotalSize = sizeof(VARSTRING)+255;

long lRet = lineGetID(m_hLine,0,m_hCall,
        LINECALLSELECT_LINE,pvarStrDevID,"comm/datamodem");
if(lRet)
{
    *lError = lRet;
    return NULL;
}

*lError = 0;

return *((LPHANDLE)((char *)pvarStrDevID + pvarStrDevID->dwStringOffset));

lineGetID returns VARSTRING, which is a variable structure. On successful return, end of this structure will contain 4 byte HANDLE corresponding to the class requested. Next to this HANDLE, a null terminated modem string name (from the driver) will appear, which can be ignored. Here in this tool, specified hard-coded class name is "comm/datamodem".

Close: Close closes the entire operation. Inside, it closes the Line and shuts down the LineApp. Also terminates the message monitoring thread.

Class Usage

The following picture shows the typical TAPI use, using CTAPILine class methods.

One of the complications in TAPI programming is, most of the TAPIs use variable structure. I.e., when you code for successful operation, you should always check for LINEERR_STRUCTURETOOSMALL error code from the TAPI and reallocate the structure constantly to fit. To simplify, I haven't coded this class in that way. Here, I scrupulously allocated all of the variable structure with huge memory, it prevents the failure in ordinary execution.

Tool Demo

TAPISample is the perfect sample tool which uses the CTapiLine class. TAPISample tool's picture on top was captured when making a dialup connection to server in Internet. Those who have dialup Internet access can replicate this. To start, click 'Open' and type the number to dial. There is no feature in this tool to indicate the connected status. You can find the connected sign by the modem sound. Once connected, modem stops squeaking. Now get the handle by clicking "Get Handle" and start the reading by clicking "Read". Now you can see some bytes coming on "Data from stream" edit box. When you click "Write", the text you typed on "Data to write" will be sent.

Here in this tool, serial communication handle is retrieved. It is Overlapped serial communication handle. This is used on the "Serial communication" section on the dialog, same like a handle created by the CreateFile with Overlapped flag.

More on TAPI

Here, I have demonstrated only serial communication using TAPI. You can use this to record and playback Wave files on the phone line only if you have voice capable modem. Then you can use your PC as an answering machine.

To record or playback first, you must open with LINEMEDIAMODE_AUTOMATEDVOICE media mode (first mode in Open) and with LINECALLPRIVILEGE_OWNER privilege. Then request the handles for "wave/in" and "wave/out" and use these handles in Wave API waveInStart and waveOutWrite to record and playback.

Conclusion

I have performed very little test on this class and the tool, since I don't have the luxury of resources like extra PCs with modem, ISDN modem, data/fax/voice modem, etc. So I guarantee you this class has some serious bugs lurking. If you find any such thing, please update me. Please appreciate if you find this useful and don't curse me if you find it difficult. Definitely, this is a bit obsolete tutorial after TAPI 3.0 and later release. If you are a beginner, I bet it will provide you a good start. Thanks.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Ramanan.T
Software Developer (Senior)
Australia Australia
No Biography provided

Comments and Discussions

 
QuestionDownload links for the two .zip files are incorrect PinmemberMember 1082738118-May-14 15:38 
QuestionI need this in c# Pinmemberj2me.sun1-Dec-13 6:09 
QuestionNeed Help for TApi PinmemberTheeNerd7-Mar-12 22:51 
QuestionGet list of incoming calls PinmemberSoft0092-Aug-11 17:23 
GeneralMy vote of 5 Pinmemberkfke17-Sep-10 23:53 
Questionusing the sample in another country [modified] Pinmemberbasculo5-Mar-10 7:10 
General[Message Deleted] Pinmemberit.ragester28-Mar-09 5:37 
QuestionPC and fax Pinmemberstefkhel7-Sep-08 5:52 
GeneralDevive not connected Pinmemberkaleeswaramurthy27-Dec-07 0:20 
QuestionWindows Fax Service & Another Tapi Application Pinmemberfaxproject31-Oct-07 23:36 
QuestionRe: Windows Fax Service & Another Tapi Application PinmemberAmakakeru3-Dec-07 18:26 
Generalthx a lot. Pinmemberlisp20087-Oct-07 21:45 
GeneralRegarding Retrieve Datas From Device Pinmemberprabhuranganathan5-Sep-07 23:50 
QuestionI want to know soem good example of PhoneAPIs. PinmemberDivyang Mithaiwala4-Sep-07 0:12 
Generaltapi-Cellphone Pinmembermahe_uma31-May-07 19:26 
GeneralNot call to phone Pinmembersongdongemdem15-Apr-07 6:24 
Why I had did lineInittializeEx,lineNegotiateAPIVersion,lineopen and lineMakecall,no why when i call to number of my phone,but in my phone have'n signal(not ringing)?
Thanks you very much.
QuestionlineMakeCall returns "LINEERR_INVALLINEHANDLE" PinmemberPatel Jigna23-Feb-07 20:30 
GeneralBasic setup required PinmemberPrabin Kumar9-Nov-06 1:29 
Generalplz help "how can i remove echo??" Pinmembermehdi_9725-Oct-06 4:57 
Generalwant to get status of the call PinmemberBrij21812-Jul-06 22:19 
GeneralSend and Receive File With Modem PinmemberBehzad Bahjat Manesh9-Jul-06 21:26 
GeneralGood tutorial Thanks alot Pinmemberlolo_monmon5-Mar-06 12:41 
GeneralMake the incomming call through to agent Pinmemberwaz_iiui12-Feb-06 23:47 
GeneralTAPI versions Pinmemberronen0009993-Feb-06 23:01 
QuestionTAPI lineGetID problem - trying to get device handle for "wave/out" PinmemberHarish Palaniappan15-Jan-06 18:35 
Question(SOS) PLZ HELP ME! Pinmemberasemoon59@yahoo.com18-Oct-05 10:51 
Question(SOS) PLZ HELP ME! Pinmemberasemoon59@yahoo.com18-Oct-05 10:49 
Question(SOS) PLZ HELP ME! Pinmemberasemoon59@yahoo.com18-Oct-05 10:49 
GeneralReciving a phonecall in Tapi Pinmembernirmit18-Sep-05 8:17 
GeneralPlease help me in fax via this tapi sample Pinmemberzalmay30-Aug-05 19:19 
Questionhow to dial in PULSE mode ?? Pinmembermohsen nourian27-Aug-05 21:25 
GeneralAnswer a phone call Pinmembernirmit23-Aug-05 7:35 
GeneralReciving a phone call Pinmembernirmit23-Aug-05 7:24 
GenerallineMakeCall returns "LINEERR_INVALLINEHANDLE" PinsussSoloVision21-Aug-05 21:40 
QuestionCan we send the AT commands directly to the communication device ?? PinmemberJigar Mehta8-Aug-05 21:48 
AnswerRe: Can we send the AT commands directly to the communication device ?? Pinmemberandy18024-Aug-05 12:18 
AnswerRe: Can we send the AT commands directly to the communication device ?? PinmemberYe lai Fang12-Nov-07 18:34 
Questiontapi sdk??? Pinmembermaria_uet2-Aug-05 7:57 
Generalimprovment on LINEDEVCAPS Pinmembericestatue19-Jul-05 14:52 
Generalwriting Audio Data PinmemberTili14-Jul-05 9:20 
QuestionHow to detect LineConnected? Pinmembermaihuaz4-Jul-05 2:15 
Generalmaria...note i mispell my email it is maria_uet2003@yahoo.com Pinmembermaria_uet27-Jun-05 0:58 
GeneralPlz help me...maria Pinmembermaria_uet27-Jun-05 0:54 
GeneralRe: Plz help me...maria PinmemberTili14-Jul-05 9:01 
GeneralRe: Plz help me...maria Pinmembermaria_uet2-Aug-05 8:03 
GeneralRe: Plz help me...maria PinmemberTili4-Aug-05 16:35 
GeneralAbout key phones Pinsussicaro19-Apr-05 22:53 
GeneralSMDR(System Message Dynamic Recording) Pinmembershiva tavasoli31-Jan-05 23:27 
QuestionData Call over XDA II - PDA ? Pinsussrajesh_s7616-Jan-05 19:24 
AnswerRe: Data Call over XDA II - PDA ? PinmemberT.YogaRamanan17-Jan-05 5:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.141015.1 | Last Updated 27 Dec 2004
Article Copyright 2004 by Ramanan.T
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid