Here you will find coding tips for a variety of telephony programming
situations. We hope you find them useful. If so, don't hesitate to visit some
of the advertisers in the left hand panel.
How to open a connection to a Genesys TServer
(C++.net)
How to start monitoring a Genesys TServer for
events(C++.net)
How to receive events from a Genesys TServer (C#,
C++.net)
How to check agent login status and extension with
Genesys TServer (C#, C++.net)
How to use TAPI via .net interop (C#)
First off, you must specify the required include files:
To open a connection to a TServer, you must supply the TServer server name, port and an application name for your client. Because the Genesys T-Lib api is an ANSI 'C' library, to use it from within a .net method we must marshal managed .net strings to ASCII 'C' character arrays. For this, we can use the static .net Marshal::StringToHGlobalAnsi methods defined in the System::Runtime::InteropServices namespace.
Refer to the example below for a simple C++ class method that takes a TServer name, port and application name, and returns a TServer handle. Note how the managed UNICODE strServer and strAppName are marshaled to their ANSII equivalents ready to be consumed by the T-Lib api. Also note the requisite socket functions conn_startup and atexit required for proper socket management. Finally, note the dispatch_function declaration, which is the address of the static callback function that will be called by T-Lib on event receipt.
The worker thread is a managed function that merely calls a static function:
The static function executed by the worker thread involves a loop that checks the TServer for events for a duration specified by the private member variable m_iScanTimeOut. The private member boolean m_blnMonitor can be set to false in another thread to cause this thread to terminate, and thus invoke a close of a connection to the TServer:
Note that the T-Lib api is not thread safe, meaning that while more than one connection to a TServer can be opened, only one worker thread scanning with TScanServerEx should be spawned, meaning only one TServer can be listened too. Trying otherwise may yield unpredictable results. An article with fully functional executable will be posted shortly showing how to monitor multiple TServers
Now that we have opened a connection to a TServer and started scanning for TServer events, we can receive and process event messages. To do so, a callback function must be made available so that our T-Lib implementation class can raise events to the consumer or client. We begin by defining a delegate as follows:
This delegate defines the signature of the callback function that will be supplied by the class consumer, and which will be assigned to a private member variable of our T-Lib implementation class as follows:
The delegate would be assigned after instantiating the T-Lib implementation class and before opening a connection to the TServer in the consumer as follows:
The code above demonstrates how a consumer would implement all concepts discussed so far. Note the using keyword would preceed the class namespace, it is displayed for convenience only. The TLibEvent private method address is what will be called by the T-Lib implementatin class when events are raised to the consumer.
Now that we've covered the fundamentals of how to connect too and receive events from a TServer, all that is left is the callback function event handler in the consumer of our T-Lib implementation class.
Once we have established a connection to a TServer, we can easily determine which DN an agent is logged into, if at all. The agent id must be configured in the Genesys configuration manager, and a simple call to TQueryAddress will send a request for information on the agent id DN. The corresponding event raised by TServer will be EventAddressInfo.
An implementing T-Lib wrapper class would expose a method such a QueryAgent which could accept a managed agent ID DN string, marshal it to it's ANSI 'C' quivalent and use it for the T-Lib TQueryAddress function call.
The important elements in the T-Lib function call below are AddressTypeAgentID and AddressInfoAddressType, which are the address type and the requested information type for the DN. These must be set as shown below.
TServer will respond with a EventAddressInfo event, which can be trapped in the event handler function specified in the TOpenServerEx function call used to establish a connection with the TServer. If the agent is logged in, the corresponding extension will be found in OtherDN of the T-Lib TEvent event structure.
Stay tuned for a functional T-Lib client and library download with full source code.
The following source code download is offered as an exercise in doing low level hooks using .net. It was originally built as a learning tool when .net 1.0 was first released. The CTI telephony api, TAPI, is used to create a .net application that enumerates all TAPI lines and addresses available to a desktop. The application allows for the selection of a line, and then proceeds to listen for incoming calls, upon which the MSISDN (or ANI) of the calling party is displayed.
There were a few interesting challenges when implementing the TAPI interfaces. The first involved mapping the TAPI 'C' structures. As an example, the TAPI structure LINEDEVCAPS was mapped by adding the attribute LayoutKind.Explicit , and specifying the size of the structure as well as the type of it's contents, Ansi characters, as follows:
[StructLayout(LayoutKind.Explicit, Size=2284, CharSet=CharSet.Ansi)]
Each member of the structure was preceeded by it's positional byte offset from the beginning of the structure:[FieldOffset(4)]public int dwNeededSize;
The other interesting aspect is giving a managed method to the TAPI api as the call back function to which telephony events are raised to the client. This was accomplished by specifying a delegate with the same signature as required by the TAPI lineInitialize and lineOpen functions:
private static extern int lineInitialize(
ref int lphLineApp,
int hIntance,
TapiCallBack lpfnCallback,
string lpszAppName,
ref int lpdwNumDevs)
Note in the source code the declaration of TapiCallBack as a delegate that requires a method with the same signature as expected by lineInitialize and lineOpen:
private delegate void TapiCallBack(
int hDevice,
int dwMessage,
int dwInstance,
int dwParam1,
int dwParam2,
int dwParam3)
The delegate is declared in the implementing class as follows:
private TapiCallBack m_TapiEvent;The delegate is initialized in the implementing class constructor as follows:
m_TapiEvent = new TapiCallBack(TapiEventHandler);And finally, the call back function, TapiEventHandler, is declared as a class method as follows:
private void TapiEventHandler(int hDevice,The delegate instance, m_TapiEvent, can now be passed to lineInitialize and lineOpen.
The final .net project solution implementing our TAPI client is available for download here. As always, if you find the download useful, please support free software by visiting out advertisers. Comments or suggestions can be sent here