Tapi for the home
Part I - Basics of TAPI

My interest for TAPI was prompted when I decided to develop «home» applications that would provide my computer with dialing, callerID and answering machine capabilities. I decided to develop a TAPI application myself. As a result, in this series of four articles, I will review the basics of TAPI, devise a component, develop the recording and playback capabilities for the modem and develop an In-process automation server called gtroTelServer that would provide the required capabilities to calling applications. This first article introduces the TAPI capabilities that will be used [the other three articles are in preparation].

The idea of using computers to communicate is not new. Using a telephone line as a communication medium between computers is not exactly a space-age concept either. Fast dedicated computers have had controlled telephone switches for quite some time, and modems are now one of the most common PC peripherals. 

Telephony is a technology that integrates computers with the telephone network. With telephony, people can use their computers to take advantage of a wide range of sophisticated communications features and services over a telephone line. Historically, it has been associated with proprietary enterprise solutions such as IVRs and PBX switches. This equipment is expensive, and is commonly supplied by the vendor with proprietary software to drive it. Relatively inexpensive telephony peripherals have been available for some time, but the software to drive them has also been hardware-specific. 

Most home telephone connections in the world are of the type POTS, or Plain Old Telephone Service. Most POTS calls are transmitted digitally except while in the local loop the part of the telephone network between the telephone and the telephone company's central switching office. The scope of this article is limited to POTS and its objective is to develop basic understanding that can be used by ordinary users using a standard PC equipped with a voice modem and running under relatively new versions of Windows (I use Windows Vista Home Premium, SP-1).  

What is TAPI?

TAPI is an acronym for the Telephony Application Programming Interface. It lets programmers develop applications that provide personal telephony to users. Microsoft designed it to offer an alternative to hardware-dependent telephony solutions. It is an abstraction software that inserts itself between custom applications and the hardware. Its goal is to present both software and hardware vendors with a consistent, device-independent programming model. With TAPI, applications need not know anything about the underlying hardware.

Versions of TAPI

It has evolved with the consecutive versions of Windows. It was introduced in 1993 as the result of joint development by Microsoft and Intel. The first publicly available version of TAPI was version 1.3, which was released as a patch on top of Microsoft Windows 3.1 (no longer supported),. The first version on Windows 95 was TAPI 1.4. It had support for 32-bit applications.TAPI 2.0 was introduced with Windows NT 4.0. It was the first version on the Windows NT platform. It made a significant step forward by supporting ACD and PBX-specific functionality. In 1997, Microsoft released TAPI 2.1. This version of TAPI was available as a downloadable update and was the first version to be supported on both the Microsoft Windows 95 and Windows NT/2000 platforms.TAPI 3.0 was released in 1999 together with Windows 2000. This version enables IP telephony (VoIP) by providing simple and generic methods for making connections between two (using H.323) or more (using IP Multicast) computers and now also offers the ability to access any media streams involved in the connection. Windows XP included both TAPI 3.1 and TAPI 2.2. TAPI 3.1 supports the Microsoft Component Object Model and provides a set of COM objects to application programmers. This version uses File Terminals which allow applications to record streaming data to a file and play this recorded data back to a stream.

For the programmer, the primary advantage of TAPI is that Microsoft has committed to providing the TAPI model as part of the basic operating system for all future versions of Windows. It can be used in four levels of complexity:

The last three levels are often referred to as full telephony.

TAPI conceptual objects

TAPI is an abstraction of the hardware and software used in telephony. In order to be device-independant, TAPI uses four types of telephony conceptual objects: LineApp, Line, Phone, and Call

Basic Telephony

The Basic Telephony service model has several API calls for handling and fulfilling service requests. These calls can be collected into logical groups

The following table shows the Basic Telephony API calls, sorted by functional group, along with a short description of their use.

Table III -The Basic Telephony line device API set
Function Group API Call Description
Line-handling       lineInitialize Initializes the Telephony API line abstraction for use by the invoking application.
lineShutdown Shuts down the application's use of the Telephony API line.
lineNegotiateAPIVersion Allows an application to negotiate an API version to use.
lineOpen Opens a specified line device for providing subsequent monitoring and/or control of the line.
lineClose Closes a specified opened line device.
lineDrop Disconnects a call, or abandons a call attempt in progress.
lineDeallocateCall De-allocates the specified call handle.
Line settings and status           lineGetDevCaps Returns the capabilities of a given line device.
lineGetDevConfig Returns the configuration of a media stream device.
lineGetlineDevStatus Returns the current status of the specified open line device.
lineSetDevConfig Sets the configuration of the specified media stream device.
lineSetStatusMessages Specifies the status changes for which the application wants to be notified.
lineGetStatusMessages Returns the application's current line and address status message settings.
lineGetID Retrieves a device ID associated with the specified open line, address, or call.
lineSetNumRings Indicates the number of rings after which inbound calls are to be answered.
lineGetNumRings This function returns the minimum number of rings requested with lineSetNumRings.
lineGetIcon Allows an application to retrieve an icon for display to the user.
lineConfigDialog Causes the provider of the specified line device to display a dialog that allows the user to configure parameters related to the line device.
Inbound and outbound calls   lineMakeCall Makes an outbound call and returns a call handle for it.
lineDial Dials calls
lineAnswer Answers an inbound call.

Along with the extensive API set for Basic Telephony, the TAPI model defines several data structures that are used to pass information between TAPI and the requesting application. The layout of the structures contains variable as well as fixed data. This allows the API set to contain information of indeterminate length without prior knowledge of the contents of the structure.

Most Windows APIs are primarily concerned with what goes on inside your computer, but TAPI is designed to interface with external, noncomputer devices that can be highly dissimilar and unpredictable. Here, we will deal with basic telephony as well as with simple hardware and software: a modem and a telephony service provider (Unimodem/5). I will describe them in the forthcoming sections.


A modem (MOdulator DEModulator) is a device that enables a computer to transmit data over telephone or cable lines. As computer information is stored digitally, whereas information transmitted over a telephone line is analog, a modem converts between the two forms. Traditionally, they are connected to a serial port. They may be internal or external

A voice modem is a modem that is capable of playing and recording audio over a telephone line.  While almost all modems are capable of doing data and fax, a growing number have voice capabilities.  Modern voice modems are powerful telephony devices capable of advanced features like voice interaction, call transfers, and outbound dialing.  For most users, a high quality voice modem and advanced telephony software will allow them to create a professional communications solution.

TAPI Service Provider (TSP)

The term "service provider" is nothing more than a fancy name for a driver. A TAPI service provider (TSP) is a driver that allows TAPI applications to communicate with different types of TAPI hardware. It translates TAPI functions into commands that the hardware can understand, and translates events from the hardware into data that the TAPI application can understand. Because different telephony hardware can support different kinds of features, different TSP's can support different TAPI functions. 

On PCs, the voice drivers are interfaced with Windows through the Unimodem TSP, Windows' universal modem voice drivers.   Audio devices (or Wave Devices) for the voice modem are usually provided by the manufacturer.

Unimodem is the default TSP used by Windows. Unimodem comes in a few different flavors:

Most modem vendors support Unimodem/5 with most of their voice modems.  Such support is provided  with an information file (*.inf) that contains the information that tells Unimodem/5 how to interact with the modem

As a telephony service provider, Unimodem has severe restrictions:

  1. Due to the half-duplex capabilities of voice modems regarding media streaming via PC you can only use "wave/in"  or "wave/out" device at the same time. This is a system wide restriction, i.e. any application or service having one of the modem's wave devices opened prevents any other application from opening it too.
  2. Modems driven by Unimodem.TSP only support  8 kHz, 16-bit, mono, WAVE_FORMAT_PCM wave format.

In the preceeding sections, I have provided basics of TAPI. For more on TAPI, the reader is referred to the Microsoft Windows Telephony API TAPI Programmer's Reference. More can be obtained from the FAQs by Bruce Pennypacker,  Andreas Marshall, Grant Schenck and Michael Dunn.

How it works

In terms of the process involved, working with telephony is similar to working with many other computer technologies, including multimedia. First you must establish a connection with the hardware through its driver(s). You accomplish this task by initializing TAPI.

TAPI Versioning

The TAPI Version refers to the revision history of the API calling and parameter-passing conventions. As TAPI evolved, new API functions were added, new events and messages were added, and modifications were made to existing standards. Each such revision has been given a version number. To assure backward compatibility, operating systems ship with binaries that support a certain range of TAPI versions 

Handling TAPI messages

Up to now, TAPI has been initialized and we have chosen to have a callback function to process TAPI messages. The available line devices have been enumerated and the modem selected as the active line device. We now need to figure out how to handle the messages.

TAPI is strongly event-driven and TAPI function calls are frequently asynchronous. When an API function requests that a certain action be performed, the request is passed to TAPI, TAPI passes it down to the TSP, the request is queued, and the API function returns. Later when the operation is completed, the application is notified.

The Callback function

The Callback function is used by TAPI to inform an application about various events that happen during the TAPI session. First of all, the good news is that you can leave the callback function empty in case you do not intend to use any TAPI handles during session lifetime. This function is declared as follows and must be a procedure that is external to any class:

procedure CallBackProc(hDevice, dwMessage, dwInstance, dwParam1, dwParam2, dwParam3 : DWORD); stdcall;

The first parameter is a handle either of a line device or a call on which TAPI is informing your application. More interesting parameters are the dwParam(s) parameters. They describe the fired message and its specific data. You can find a complete list of TAPI messages in the SDK documentation with a detailed description of each message parameter. 

Additionally, the callback function must be a global procedure, not a class member (method). The problem  in substituting a callback function by a class member is that Windows does not understand either C++ class member functions or Delphi's methods which carry "this" and "self" as a first hidden parameter.

Types of messages

All of these messages are sent to the application through the message notification mechanism that the application specified in lineInitializeEx(). The message always contains a handle to the relevant telephony object (phone, line, or call), which the application can use to determine the message type.  The structure of the messages presented hereunder follows very closely the structure used in the TapiCallback() method presented above.

Line related messages

In the type of line related messages, hDevice contains a handle to the line.

Call related messages

For the following messages, the hDevice parameter contains a handle to the call

Other messages

Opening a line

After having obtained the capabilities of a line and have developed a callback procedure responding to TAPI messages, an application must open a line device before it can access telephony functions on that line. We obtain a handle to a capable telephone line with a call to the lineOpen() API function:

function lineOpen(hLineApp: HLINEAPP; dwDeviceID: DWORD; lphLine: PHLine;
dwAPIVersion, dwExtVersion, dwCallbackInstance, dwPrivileges,
dwMediaModes: DWORD; lpCallParams: PLineCallParams): Longint; stdcall;

This function that requires many inputs from the application: the TAPI Application handle hLineApp obtained from lineInitialize(), the identification of the device dwDeviceId, the dwAPIVersion received from lineNegotiateAPIVersion(), the line call priviledge and the media mode selected by the application. The parameters marked as pointers return 

In TAPI, a line is an abstraction, a device-independent representation of a physical line device, such as a modem. It can contain one or more identical communications channels (used for signaling and/or information) between the application and the switch or network. Because channels belonging to a single line have identical capabilities, they are interchangeable. In many cases (as with POTS), a service provider will model a line as having only one channel. Other technologies, like ISDN, offer more channels, and the service provider should treat them accordingly. Here, we deal with POTS.

The function lineOpen() can be invoked in one of two ways: 

The ability of an application to deal with inbound and outbound calls on a line is determined by the value used for the and the dwPrivilegesdwMediaModes parameters of the lineOpen() function. With this function, the application indicates its interest in monitoring calls or receiving ownership of inbound calls of one or more specific media modes, or of any (unspecified) media mode.

Call privileges

Ownership of a call is a type of privilege. Applications obtain owner or monitor privilege to new incoming calls by specifying the desired privilege as a parameter of lineOpen(). The privilege with which a line is opened remains in effect for subsequent calls used by that application on that line. An application always has owner privileges on calls it creates. When the application opens a line to place calls (as opposed to taking inbound calls) it invokes lineOpen() with the privilege LINECALLPRIVILEGE_NONE, which insulates the application from incoming calls while allowing outgoing calls. The other privileges used with the lineOpe() function are only for incoming calls.

When a call handle is first provided to an application or whenever call privileges of that application are modified, the LINE_CALLSTATE message is sent to the application. When an application hands off a call, and if the receiving application does not already have a handle with owner privileges, then this message informs the application about its new privileges to the call. In this test bed, opening a line for monitoring inbound calls is done using LINECALLPRIVILEGE_MONITOR orLINECALLPRIVILEGE_OWNER for the call privilege.

Bearer Mode

The bearer mode corresponds to the quality of transmission requested from the network for establishing a call. It is important to keep the concept of bearer mode separate from that of media type. As an example, the analog telephone network provides only a 3.1 kHz voice-grade bearer mode but calls using it can support media types such as voice, fax, or data modem.

Media modes

The media mode is the form in which data is transmitted on a line. The four main types of media mode are voice, speech, fax, and data. The interest of an application for calls of given media modes is notified with the dwMediaModes parameter of lineOpen(). An inbound call of a certain media mode is given to the application that has opened the line device for that particular media mode. A single application may specify multiple flags simultaneously to handle multiple media modes. Alternatively, an application that wants to handle calls for which the actual media mode present has not yet been determined would turn on the unknown media bit as a parameter of lineOpen().

Handling calls

Once TAPI has been initialized and a line opened, the event-driven TAPI waits for a call to occur. Such call may be outbound or inbound.

Ending calls and leaving TAPI

When a call  is finished, the application receives a LINE_CALLSTATE message, which informs it that the state of a line device has changed: a remote disconnect has occurred. The application disconnects the call at the local end (it "goes on-hook") with lineDrop(). Alternatively, the application itself may choose to end the call by invoking lineDrop() before receiving the remote-disconnect message.

Here are the steps that might be used to end a call, close the line, and leave TAPI: 

  1. The application calls lineDrop(), which places the call in the IDLE state. The call still exists, and the application still has its handle. Now the application can examine the call-information record, if desired. 
  2. The application calls lineDeallocateCall() to release the call handle for the finished call. The call no longer exists. 
  3. If the application expects no more calls on the line, it uses lineClose() to close the line. At this point, there will be no more incoming or outgoing calls on that line.
  4. The application invokes lineShutdown() to end the use of TAPI's functions for the current session.


That is about all that is needed to understand the design and implementation of the TgtroCallerID component that will be discussed in the second article of this series (not available yet).The scope of this article has been restricted on purpose to the simplest part of TAPI: POTS. TAPI is much more than what is covered here. TAPI also lets you make connections over other types of networks. More advanced kinds of data transmission methods are being developed, refined, and installed. 


Much of this page has been retrieved from the references listed hereunder. Indebtness is hereby acknowledged.

  1. Telephony Application Programming Interface from Wikiperia.
  2. TAPI Quick Reference by Jialong He; 
  3. TAPI 3.1 Overview from MSDN;
  4. "For the Telephony API, Press 1; For Unimodem, Press 2; or Stay on the Line" by Hiroo Umeno (Microsoft System Journal, April 1998);

This code was developed for the pleasure of it. Anyone who decides to use it does so at its own risk and agrees not to hold the author responsible for its failure.

Questions or comments?
Last modified: September 4th 2014 10:44:23. []