1

I need to create a program to monitor activity of phone call.And get information about the calls, like number and Name. I'm not strong with TAPI code and C#, so hope that anybody can help me, I'm desperate.

I have this code where I try to detect the available devices and obtain information from those devices when a call comes in:

using System;
using TAPI3Lib; 
using JulMar.Atapi; 

namespace ConsoleApp1
{
  class Program
  {
    private void tapi_ITTAPIEventNotification_Event(TAPI_EVENT TapiEvent, object pEvent)
    {
        try
        {
            ITCallNotificationEvent cn = pEvent as ITCallNotificationEvent;
            if(cn.Call.CallState == CALL_STATE.CS_CONNECTED)
            {
                string calledidname = cn.Call.get_CallInfoString(CALLINFO_STRING.CIS_CALLEDIDNAME);
                Console.WriteLine("Called ID Name " + calledidname);
                string callednumber = cn.Call.get_CallInfoString(CALLINFO_STRING.CIS_CALLEDIDNUMBER);
                Console.WriteLine("Called Number " + callednumber);
                string calleridname = cn.Call.get_CallInfoString(CALLINFO_STRING.CIS_CALLERIDNAME);
                Console.WriteLine("Caller ID Name " + calleridname);
                string callernumber = cn.Call.get_CallInfoString(CALLINFO_STRING.CIS_CALLERIDNUMBER);
                Console.WriteLine("Caller Number " + callernumber);


            }
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }



    static void Main(string[] args)
    {
        TapiManager mgr = new TapiManager("ConsoleApp1");
        mgr.Initialize();

        foreach(TapiLine line in mgr.Lines)
        {
            foreach (string s in line.Capabilities.AvailableDeviceClasses)
                Console.WriteLine("{0} - {1}", line.Name, s);
        }
    }
}
}

But when I run it, just see the available devices but don't see any information about calls. I'm used to programming in java so I guess I should send to call the method that gets the call information in the main, but I do not know how to do that and in any code I've seen they do. So, hope that you can help me to understand how TAPI works and what can I do to do my code work.

Nancy
  • 11
  • 1
  • 4

2 Answers2

2

Okay, first, you want to stick to one Version of TAPI. In your using statements, youre importing a TAPI 2.x managed libaray and a TAPI 3.x managed library.

using TAPI3Lib; // this is a TAPI 3.x library
using JulMar.Atapi; // this is a TAPI 2.x library

If you're choosing to go with TAPI 3.x, you should start by creating a new class, which handles different kinds of TAPI events. To do so, it needs to implement the ITTAPIEventNotification interface:

public class CallNotification : ITTAPIEventNotification
{
    public void Event(TAPI_EVENT TapiEvent, object pEvent)
    {
        if(pEvent == null)
            throw new ArgumentNullException(nameof(pEvent));

        switch (TapiEvent)
        {
            case TAPI_EVENT.TE_CALLNOTIFICATION:
                // This event will be raised every time a new call is created on an monitored line-
                // You can use CALLINFO_LONG.CIL_ORIGIN to see weather it's an inbound call, or an
                // outbound call.
                break;
            case TAPI_EVENT.TE_CALLSTATE:
                // This event will be raised every time the state of a call on one of your monitored
                // Lines changes.
                // If you'd want to read information about a call, you can do it here:
                ITCallStateEvent callStateEvent = (ITCallStateEvent)pEvent;
                ITCallInfo call = callStateEvent.Call;

                string calledidname = call.get_CallInfoString(CALLINFO_STRING.CIS_CALLEDIDNAME);
                Console.WriteLine("Called ID Name " + calledidname);

                string callednumber = call.get_CallInfoString(CALLINFO_STRING.CIS_CALLEDIDNUMBER);
                Console.WriteLine("Called Number " + callednumber);

                string calleridname = call.get_CallInfoString(CALLINFO_STRING.CIS_CALLERIDNAME);
                Console.WriteLine("Caller ID Name " + calleridname);

                string callernumber = call.get_CallInfoString(CALLINFO_STRING.CIS_CALLERIDNUMBER);
                Console.WriteLine("Caller Number " + callernumber);
                break;
        }

        // Since you're working with COM objects, you should release any used references.
        Marshal.ReleaseComObject(pEvent); 
    }
}

In order to use this class, you need to create a new instance of TAPI3Lib.TAPIClass and call its Initialize method. After that, you can attach your newly create CallNotification class as an event handler. You could also specify which types of events you want your handler to receive. Notice that you wont receive any event notifications at this point, because you haven't told TAPIClass which lines it should monitor:

CallNotification callevent = new CallNotification();
TAPIClass tapi = new TAPIClass();
tapi.Initialize();
tapi.EventFilter = (int)(TAPI_EVENT.TE_CALLNOTIFICATION | TAPI_EVENT.TE_CALLSTATE);
tapi.ITTAPIEventNotification_Event_Event += new ITTAPIEventNotification_EventEventHandler(callevent.Event);

In order to tell TAPIClass which lines it should monitor, you need to do two things. ask for all lines registered to you IPBX and determine, weather its a line you have the rights to monitor (this is an IPBX configuration):

public List<ITAddress> EnumerateLines(TAPIClass tapi)
{
    List<ITAddress> addresses = new List<ITAddress>();

    ITAddress address;
    uint arg = 0;

    ITAddressCapabilities addressCapabilities;
    int callfeatures;
    int linefeatures;
    bool hasCallFeaturesDial;
    bool hasLineFeaturesMakeCall;

    IEnumAddress ea = tapi.EnumerateAddresses();

    do
    {
        ea.Next(1, out address, ref arg);

        if (address != null)
        {
            addressCapabilities = (ITAddressCapabilities)address;

            callfeatures = addressCapabilities.get_AddressCapability(ADDRESS_CAPABILITY.AC_CALLFEATURES1);
            linefeatures = addressCapabilities.get_AddressCapability(ADDRESS_CAPABILITY.AC_LINEFEATURES);

            hasCallFeaturesDial = (callfeatures1 & (int)0x00000040) != 0; //Contains LineCallFeatures Dial; see Tapi.h for details
            hasLineFeaturesMakeCall = (linefeatures & (int)0x00000008) != 0; //Contains LineFeatures MakeCall; see Tapi.h for details

            // this is basically saying "Am I allowed to dial numbers and create calls on this specific line?"
            if(hasCallFeaturesDial && hasLineFeaturesMakeCall)
                addresses.Add(address);
        }
    } while (address != null);

    return addresses;
}

public void RegisterLines(TAPIClass tapi, IEnumerable<ITAddress> addresses)
{
    if (tapi == null)
        throw new ArgumentNullException(nameof(tapi));

    if (addresses == null)
        throw new ArgumentNullException(nameof(addresses));

    foreach (ITAddress address in addresses)
    {
        tapi.RegisterCallNotifications(address, true, true, TapiConstants.TAPIMEDIATYPE_AUDIO, 2);
    }
}

so Your initialization would look like this:

CallNotification callevent = new CallNotification();
TAPIClass tapi = new TAPIClass();
tapi.Initialize();

IEnumerable<ITAddress> addresses = this.EnumerateLines(tapi);
this.RegisterLines(tapi, addresses);

tapi.EventFilter = (int)(TAPI_EVENT.TE_CALLNOTIFICATION | TAPI_EVENT.TE_CALLSTATE);
tapi.ITTAPIEventNotification_Event_Event += callevent.Event;

Once you run your program, and it's done executing above code, you will get notifications from incoming and outgoing calls when their call state changes.

I hope you could follow this post. If you have any questions, just ask =)

Jamiu S.
  • 5,257
  • 5
  • 12
  • 34
Oerk
  • 148
  • 10
  • 1
    your code works, but only once. To get notifications for many calls one must watch for callstate CS_DISCONNECT and unregister that address with the int handle that one got with the registration then register again. – henon Oct 05 '22 at 18:32
0

The line is TapiLine, you have to use TapiCall.

Polluks
  • 525
  • 2
  • 8
  • 19