The TAPI connection

The TApdTapiDevice is used to establish modem connections in passthrough mode, answering or dialing.   This component uses the Telephony API (TAPI) to gain access to the serial port, to configure the device and to establish the actual connection. In this Tech Tip, we'll discuss several aspects of establishing connections with TAPI.

 

The no-connection connection

The most basic connection that TAPI can make is not really a connection at all.  TAPI supports a 'passthrough' mode than gives the application access to the serial port controlled by the TAPI device.  In APRO, this mode is started with the TApdTapiDevice.ConfigAndOpen method.  Like the name implies, this method will request that TAPI configures the modem and port according to the modem's property pages, then hands us the open port.  When ConfigAndOpen is called the port is opened for exclusive use by the application that opened the port (no sharing allowed).  This method is handy when you want to do something that TAPI doesn't let you do with the other methods (such as specifying non-standard line parameters without going through the modem's property pages).

 

The originating connection

The TApdTapiDevice originates a TAPI connection with the Dial method.  The sole parameter to this method is the phone number to dial. When you call this method, APRO requests that TAPI establish the connection by dialing the specified number.  When the connection is established, TAPI will give us an open serial port (indicated by the OnTapiPortOpen event).  Prior to TAPI establishing the connection, the serial port is not accessible by the application.

A quick word about phone numbers

One of the frequently asked questions about the Dial method is why it doesn't use the TAPI Locations settings (where you tell the device to dial '9' for an outside line or specify a calling card to use).  APRO will use whatever you pass into the Dial method, with no translations.  To translate a phone number to something that uses the Locations setting is beyond the scope of this Tech Tip, refer to http://www.turbopower.com/techtip/980223/default.asp for details.

 

The answering connection

The TApdTapiDevice can also wait for incoming calls with the AutoAnswer method.  When you use that method, APRO will register an internal callback for that device and will patiently wait for the TAPI messages saying it detected a ring signal.  Once we have seen the number of rings specified by the AnswerOnRings property, we request TAPI to answer the call.  Once the connection is established, the OnTapiPortOpen event will be generated indicating that TAPI has given us an open port.  Prior to establishing the connection, the serial port is not accessible by the application.

 

The connection connection

After reading this, you may start to see a pattern.  We request TAPI to do an operation; TAPI may or may not comply with our request.  Fortunately, TAPI will tell us if it can't do what we want, and we will pass that to you in the OnTapiFail event.  Actually, the OnTapiFail is only your notification that TAPI couldn't do what you wanted it to, but the FailureCode property will tell you the last error message that we received from TAPI.  The FailureCodeMsg method can translate that code into a string for display if you'd like.  You should be aware that if you do not have an OnTapiFail event handler an exception would be raised instead.

Another trait shared between the connection techniques is the availability of the serial port.  When you use TAPI to establish a connection, TAPI does not give you a serial port until the connection is established.  Likewise, when the connection is terminated, TAPI will take the port away.  When the connection is established, TAPI gives us the port and we will generate the OnTapiPortOpen event.  When a real connection is established (through the Dial or AutoAnswer methods) the OnTapiConnect event will also be generated.  When the connection is terminated, TAPI will take our port away and APRO will generate the OnTapiPortClose event. 

The last common theme we'll discuss is the availability of the serial port while a connection is in progress.  When TAPI opens a port and hands it to us, TAPI opens the port in a mode that could be shared between applications, but APRO does not allow it.  This port sharing is called a call handoff in TAPI.  Only one application has access to the port at any given time, but that access could be handed off to another application. 

 

That covers the TAPI connection techniques available in APRO.  I know you have some questions about how this all relates to what you want to do, so go ahead and ask them now...   

OK, I can answer a call, how do I answer the next calls?

When a connection is terminated, the OnTapiPortClose event will be generated.  The AutoAnswer method, however, only tells TAPI to answer the next call, once that call is completed TAPI will not answer the next call unless you tell it to.  Starting with APRO 3.04, it is real easy to get back into AutoAnswer mode.  From your OnTapiPortClose event, just call the AutoAnswer method again.  Prior to 3.04, you needed to post a message from the OnTapiPortOpen event, but that is now handled internally for you.

But I want to dial using the same device that I'm answering with

It would seem from the description above that you would not be able to be in AutoAnswer mode, then switch to dialing, but you can.  You would have to use two TApdTapiDevices and two TApdComPorts to do it.  For the sake of argument, lets call then ApdComPort1, ApdTapiDevice1, ApdComPort2 and ApdTapiDevice2.  Set the ApdTapiDevice.SelectedDevice to the name of the same device for both TApdTapiDevice components.  To get in AutoAnswer mode, call the AutoAnswer method for one of the ApdTapiDevices.  When you want to make an outbound call, use the Dial method of the other ApdTapiDevice.  Everything will work right...unless the answering device has an established connection in progress, the Dial would fail because the device was in use already.  To work around that, check the TapiState of the answering device.  If a connection is not in progress (waiting for a call), the TapiState will be tsIdle.  So, if the answering device' TapiState is tsIdle it is safe for you to make an outbound call.  Something like this would figure out if it was safe to dial using the device:

 

procedure TForm1.btnDialClick(Sender: TObject);

begin

  if ApdTapiDevice1.TapiState = tsIdle then

    ApdTapiDevice2.Dial('555-1212')

  else

    ShowMessage('Can''t dial now, I''m busy');

end;

 

That's great, but I have several devices waiting for calls and want to dial using the first available device

Why didn't you say so in the first place?  You can do this too, but it will take a little more work.  You could maintain a list of all of your TAPI devices, then check each one until the TapiState is tsIdle, but why not do something real cool instead.  The Form's Components property contains references to all components that are on the form, you can walk through the list there, and find the first TApdTapiDevice with a TapiState of tsIdle.  Some of the concepts here are verging on the complex side; see the Delphi help for the methods you are not familiar with.  This method will find the first available ApdTapiDevice and use it to make an outbound call:

 

procedure TForm1.btnDialClick(Sender: TObject);

var

  I : Integer;

begin

  { walk the Components to find an ApdTapiDevice that is idle }

    ApdTapiDeviceDial.SelectedDevice := '';

    for I := 0 to ComponentCount - 1 do

      if Components[I] is TApdTapiDevice then

        if TApdTapiDevice(Components[I]).TapiState = tsIdle then begin

          { found one, use it to dial }

          ApdTapiDeviceDial.SelectedDevice := TApdTapiDevice(Components[I]).SelectedDevice;

          Break;

        end;

 

    if ApdTapiDeviceDial.SelectedDevice = '' then begin

    { all devices are in use (TapiState <> tsIdle), can't use one of them now }

      ShowMessage('All devices currently have active calls, try dialing later');

      Exit;

    end;

 

    ApdTapiDeviceDial.Dial('555-1212');

end;

 

Using something like this, the answering device will continue answering after the dialed connection has terminated.

 

Gee, you've covered a lot of ground here, is there a real convoluted example that puts it all together?

Funny you should ask this particular question.  The DialAnsw.zip archive on ftp.turbopower.com/pub/apro/demos is about as convoluted as you can get.  This example supports 3 devices set up for answering, and another device that you can dial with.  Walking the Components property is used heavily throughout the events to associate status responses with the terminals they should be displayed on. 

This site is not affiliated, endorsed, or otherwise associated with the entity formerly known as TurboPower Software. The owners and maintainers of Aprozilla.com were merely meager employees of the aforementioned organization, providing this site out of the pure goodness of their collective hearts. SourceForge.net Logo

Last updated: July 22, 2003.