SwyxIt! v4.1 Client SDK (kb2386)
The information in this article applies to:
- SwyxIt! v4.10
[ Summary | Information ]
Summary
Summary
SwyxIt! provides two interfaces for call control:
- Client SDK (a COM Interface)
- TAPI (SwyxIt! TSP supports TAPI 2.x)
If there are no special reasons (e.g. an existing TAPI application) for using TAPI, we really recommend to use the Client SDK. Using Client SDK you may use any call control options of SwyxIt!.
Information
Information
The SwyxIT! Client SDK is version dependent. Further SDK versions can be found here:
The central module on a client PC is the Client Line Manager (CLMgr.exe). All applications like SwyxIt!, Swyx Client TSP, Swyx Outlook Addin and third party applications are running on top of the Client Line Manager. For this the Client Line Manager provides a COM interface one can use for controlling lines (establish calls, switch lines, ...). In this way several applications may use the same lines simultaneously. A call may be established using Outlook Addin and can be switched using SwyxIt! later on. Actions like hook off, dialling or switching are initiated by functions of the COM interfaces, state changes of lines will be signalled as COM events or window messages to a window or thread of the client application.
The Client SDK includes a documented interface definition (CLMgrPub.idl) and some example applications in Visual C++, Visual Basic and Visual Basic Script.
Directory PublicInterface:
- CLMgrPub.idl:
- Definition of the public interface
- CLMgrPubTypes.c:
- Definition of the required GUIDs (for Visual C++)
- CLMgrPubTypes.h:
- Some types and enumerations for return values
Directory Samples:
- Visual Basic Simple:
-
Simple Visual Basic Application
Displays information about the selected line.
Allows simple call control. - Visual Basic Script:
-
Very simple example.
Explains how to just dial a number. - Visual C++ Simple:
-
Simple Visual C++ Application
Dialog based MFC Application
Displays information about the selected line.
Allows simple call control. - Visual C++ PlayToRtp:
-
Simple Visual C++ Application
Dialog based MFC Application
Recording and playback of voice stream. - Visual C++ Call Log:
-
Simple Visual C++ Application
Dialog based MFC Application
Logs incoming and outgoing calls - Visual C++ ATL PlugIn:
-
Enhanced Visual C++ Application
Based on Active Template Library.
Explains the implementation of a Line Manager Plugin.
Provides name resolution for SwyxIt!.
Using Client SDK from several programming languages
Visual Basic
With Visual Basic 6 the Client SDK can be added to a project using menu Project\References. Check the library "CLMgr 2.0 Type Library". Afterwards the Object Browser will list all available objects and methods for library CLMGRLib. Due to technical reasons you will see many more objects and interfaces than you can use. From Visual Basic you can use the objects ClientLineMgr and ClientLine and its methods and properties. Only the object ClientLineMgr will be created by your application:
Public WithEvents PhoneLineMgr As CLMGRLib.ClientLineMgr
Set PhoneLineMgr = CreateObject("CLMgr.ClientLineMgr")
ClientLine objects are not created directly, but you will access the line by calling appropriate ClientLineMgr functions. The following example retrieves the selected line and puts it on hold:
Public PhoneLineFocus As Object
Set PhoneLineFocus = PhoneLineMgr.DispSelectedLine
PhoneLineFocus.DispHold
Now follows a selection of methods and properties of the ClientLineMgr object. You will find a detailed description in file CLMgrPub.idl. Though reading an idl-file is uncommon for Visual Basic developers, you will understand it when comparing it with the methods listed in the object browser.
Log on/off
All applications that are registering to the SwyxServer have to call the following functions:
On start: PubInit and PubRegisterUser
On termination: PubReleaseUser
Otherwise the Client Line Manager would not shut down and the user could keep logged on to the SwyxServer.
Important: Log on/off is not required for most applications. As long SwyxIt! is running, it will take care of log on/off and your application should not log on/off. As long SwyxIt! is running and logged on all methods of the Client SDK can be used. Nevertheless, the example "Visual Basic Simple" will show how to log on/off.
Initializing: DispInit(ServerName As String) As Long
Return code 0: no error. Otherwise the result is a HRESULT error code.
Log on: DispRegisterUser(UserName As String) As Long
Return code: user id. If 0 is returned, an error occurred.
Log off: DispReleaseUser(UserId As Long) As Long
Access to lines, switch lines, ...
Access line no. iLineNumber. First line has index 0! DispGetLine(iLineNumber As Long) As Object
Number of selected line. First line has index 0! DispSelectedLineNumber As Long
Access selected line: DispSelectedLine As Object
Switch to line iLineNumber. First line has index 0! DispSelectLineNumber(iLineNumber As Long) As Long
Switch to line ClientLine DispSelectLine(pIClientLine As ClientLine) As Long
Dial a number on arbitrary line DispSimpleDialEx(dialstring As String) As Long
Return code 0: the number has been dialled. Otherwise an error occurred.
On a line you can hook off, dial, put on hold, ...:
Hook off: DispHookOff
Hook on: DispHookOn
Press hook: DispPressHook
Dial: DispDial(dialstring As String)
Put on hold: DispHold
Activate from Hold: DispActivate
Transfer two lines: DispTransferCall(pITargetLine As Object);
Get line state: DispState As Long
0: | not active |
1: | hook off, internal dial tone |
2: | hook off, external dial tone (public line) |
3: | incoming call, ringing |
4: | dialling |
5: | outgoing call, ringing on destination |
6: | outgoing call, knocking (second call) on destination |
7: | outgoing call, destination or ISDN busy. More details in property DispDiscReason |
8: | active |
9: | on hold |
10: | active conference |
11: | conference on hold |
12: | terminated. More details in property DispDiscReason |
13: | transferring. Blind call transfer in progress |
14: | disabled. Wrap up time. Line does not signal incoming calls |
Dial string acknowledged by server: DispAcknowledgedDialstring As String
Phone number of peer: DispPeerNumber As String
Name of peer: DispPeerName As String
Reason for busy / terminated: DispDiscReason As Long
0: | nothing special |
1: | peer was busy |
2: | peer rejected call |
3: | call was cancelled |
4: | call was transferred |
5: | call was added to conference on other line |
6: | peer did not pick up, timeout |
7: | call was already picked up from other phone |
8: | direct call to peer was not allowed |
9: | invalid number was dialed |
10: | destination is unreachable |
11: | call was redirected |
12: | call routing failed, possible script error (script of peer) |
13: | permission for call was denied due to call restrictions |
14: | no line available (public ISDN network) |
15: | no gateway channel available |
16: | number of destination has changed |
17: | destination is incompatible (compression) |
Further functions and properties are documented in file CLMgrPub.idl.
Receiving Line Manager events with Visual Basic:
Define a ClientLineMgr object: Public WithEvents PhoneLineMgr As CLMGRLib.ClientLineMgr
Create an object: Set PhoneLineMgr = CreateObject("CLMgr.ClientLineMgr")
Add the following function to your code, that will receive the events. The meaning of parameter param is explained in file CLMgrPubTypes.h.
Sub PhoneLineMgr_DispOnLineMgrNotification(ByVal msg As Long, ByVal param As Long)
Select Case msg
Case PubCLMgrLineStateChangedMessage
Case PubCLMgrLineSelectionChangedMessage
Case PubCLMgrLineDetailsChangedMessage
Case PubCLMgrCallDetailsMessage
Case PubCLMgrServerDownMessage
Case PubCLMgrServerUpMessage
Case PubCLMgrWaveDeviceChanged
Case PubCLMgrGroupCallNotificationMessage
Case PubCLMgrClientShutDownRequest
Case PubCLMgrNameKeyStateChangedMessage
Case PubCLMgrNumberOfLinesChangedMessage
Case PubCLMgrClientShutDownRequest
Case PubCLMgrPowerSuspendMessage
Case PubCLMgrPowerResumeMessage
Case PubCLMgrHandsetStateChangedMessage
End Select
End Sub
Visual Basic Script
The same interface will be used as with Visual Basic, but receiving events will not be possible.
Defining objects: Dim PhoneLineMgr : Set PhoneLineMgr = Nothing
Dim PhoneLineFocus : Set PhoneLineFocus = Nothing
Dim errval
Create the ClientLineMgr object: Set PhoneLineMgr = Wscript.CreateObject("CLMgr.ClientLineMgr")
Dial a number: errval = PhoneLineMgr.DispSimpleDial("001191")
Get line in focus: Set PhoneLineFocus = PhoneLineMgr.DispSelectedLine
Put line on hold: PhoneLineFocus.DispHold
For further details read the paragraph about Visual Basic.
Visual C++
Example "Visual C++ Simple"
For Visual C++ add the files CLMgrPubTypes.h, CLMgrPubTypes.c und CLMgrPub.idl to your project. You may create a Client Line Manager object (CLSID_ClientLineMgr) and use its interfaces IClientLineMgrPub and IClientLineMgrPub2. The Client Line Manager object provides methods for accessing lines. Using the line interface IClientLinePub you may initiate actions on a line or retrieve line details. This will be shown in the first example "Visual C++ Simple".
Following a selection of methods of the ClientLineMgr object. A detailed documentation is given in file CLMgrPub.idl.
Log on/off
All applications that are registering to the SwyxServer have to call the following functions:
On start: PubInit and PubRegisterUser
On termination: PubReleaseUser
Otherwise the Client Line Manager would not shut down and the user could keep logged on to the SwyxServer.
Important: Log on/off is not required for most applications. As long SwyxIt! is running, it will take care of log on/off and your application should not log on/off. As long SwyxIt! is running and logged on all methods of the Client SDK can be used. Nevertheless, the example "Visual C++ Simple" will show how to log on/off.
Initializing: HRESULT PubInit([in] BSTR ServerName);
Return code 0: no error. Otherwise the result is a HRESULT error code.
Log on: HRESULT PubRegisterUser([in] BSTR UserName, [out] long *pUserId);
Return code: user id. If 0 is returned, an error occurred.
Log off: HRESULT PubReleaseUser([in] long UserId);
Access to lines, switch lines, ...
Access line no. iLineNumber. First line has index 0! HRESULT PubGetLine([in] long iLineNumber, [out] IClientLinePub** ppIClientLinePub);
Number of selected line. First line has index 0! HRESULT PubGetSelectedLineNumber([out] long *piLineNumber);
Access selected line: HRESULT PubGetSelectedLine([out] IClientLinePub** ppIClientLine);
Switch to line iLineNumber. First line has index 0! HRESULT PubSelectLineNumber([in] long iLineNumber);
Switch to line pIClientLine HRESULT PubSelectLine([in] IClientLinePub* pIClientLine);
Dial a number on arbitrary line HRESULT PubSimpleDial([in] BSTR dialstring);
Return code 0: the number has been dialled. Otherwise an error occurred.
On a line you can hook off, dial, put on hold, ...:
Hook off: HRESULT PubHookOff();
Hook on: HRESULT PubHookOn();
Press hook: HRESULT PubPressHook();
Dial: HRESULT PubDial([in] BSTR dialstring);
Put on hold: HRESULT PubHold();
Activate from Hold: HRESULT PubActivate();
Transfer two lines: HRESULT PubTransferCall([in] IClientLinePub* pITargetLine);
Get line state: HRESULT PubGetState([out] long *piState);
- PubLSInactive:
- not active
- PubLSHookOffInternal:
- hook off, internal dial tone
- PubLSHookOffExternal:
- hook off, external dial tone (public line)
- PubLSRinging:
- incoming call, ringing
- PubLSDialing:
- dialling
- PubLSAlerting:
- outgoing call, ringing on destination
- PubLSKnocking:
- outgoing call, knocking (second call) on destination
- PubLSBusy:
- outgoing call, destination or ISDN busy. More details in PubCLMgrLineDetails
- PubLSActive:
- active
- PubLSOnHold:
- on hold
- PubLSConferenceActive:
- active conference
- PubLSConferenceOnHold:
- conference on hold
- PubLSTerminated:
- terminated. More details in PubCLMgrLineDetails
- PubLSTransferring:
- Call is being transferred
- PubLSDisabled:
- Line is disabled (wrap up time)
Reason for busy / terminated:
- PubSCl3DRNormal:
- nothing special
- PubSCl3DRBusy:
- peer was busy
- PubSCl3DRRejected:
- peer rejected call
- PubSCl3DRCancelled:
- call was cancelled
- PubSCl3DRTransferred:
- call was transferred
- PubSCl3DRJoinedConference:
- call was added to conference on other line
- PubSCl3DRNoAnswer:
- peer did not pick up, timeout
- PubSCl3DRTooLate:
- call was already picked up from other phone
- PubSCl3DRDirectCallImpossible:
- direct call to peer was not allowed
- PubSCl3DRWrongNumber:
- invalid number was dialed
- PubSCl3DRUnreachable:
- destination is unreachable
- PubSCl3DRCallDiverted:
- call was redirected
- PubSCl3DRCallRoutingFailed:
- call routing failed, possible script error (script of peer)
- PubSCl3DRPermissionDenied:
- permission for call was denied due to call restrictions
- PubSCl3DRNetworkCongestion:
- no line available (public ISDN network)
- PubSCl3DRNoChannelAvailable:
- no gateway channel available
- PubSCl3DRNumberChanged:
- number of destination has changed
- PubSCl3DRIncompatibleDestination:
- destination is incompatible (compression)
Further functions are documented in file CLMgrPub.idl.
Events from the Line Manager can be received both as COM events or as window messages. The example "Visual C++ Simple" shows both ways. The build targets "Win32 Debug Using Event Sink" and "Win32 Release Using Event Sink" define USE_EVENT_SINK and use connection points and COM events. In the other case the main window will be registered as target for window messages.
The window messages will be handled in function CMfcClientDlg::OnClientLineManagerEvent(WPARAM wParam, LPARAM lParam)
the COM events land in function CCLMgrEventSink::DispOnLineMgrNotification(long msg, long param)
The class CCLMgrEventSink may be used modified in your project.
Example "Visual C++ Call Log"
The example "Visual C++ Call Log" shows a MFC client that logs calls. This client runs besides SwyxIt! and does not log on nor off. Here too there are two build targets "Win32 Debug Using Event Sink" and "Win32 Release Using Event Sink" showing both usage of connection points and COM events. The class CCLMgrEventSink may be used modified in your project.
Example "Visual C++ PlayToRtp"
The example "Visual C++ PlayToRtp" shows a MFC client that plays and records wave files to resp. from RTP.
Example "Visual C++ ATL PlugIn"
The example "Visual C++ ATL PlugIn" shows an ATL based client. It implements a Client Line Manager PlugIn that provides name resolution for SwyxIt!. For unknown peer numbers the Client Line Manager will ask all installed PlugIns for a matching name resolution. So you will be able to provide name resolution based on your own database application. This client too will not register with the SwyxServer.
For a customization one has to replace the GUIDs and friendly class names PlugInSample.MyResolver etc. in the files PlugInSample.idl and MyResolver.rgs with new GUIDs and names in order to avoid conflicts with other 3rd party applications based on the Client SDK. But never change any GUID from the files CLMgrPub.idl and CLMgrPubTypes.c!
In file PlugInSample.cpp the functions for registration and deregistration of the PlugIn are implemented. In order to be loaded by the Client Line Manager, the PlugIn writes its class ID into the Line Managers registry HKLM\SOFTWARE\Swyx\Client Line Manager\CurrentVersion\Options\PlugIns\{GUID}
The actual PlugIn object CMyResolver is defined and declared in the files MyResolver.cpp and MyResolver.h. The Das PlugIn object implements the interfaces IClientAddInLoader, IClientResolverAddIn and IClientLineMgrEventsDisp. The interface IClientAddInLoader will be used by the Line Manager on loading and releasing the PlugIn, the interface IClientResolverAddIn provides name resolution. The interface IClientLineMgrEventsDisp finally receives the Line Manager events.
When loading the PlugIn, the Line Manager calls the functions IClientAddInLoader::Initialize, IClientAddInLoader::GetName and IClientAddInLoader::GetVersion. Before releasing the interface IClientAddInLoader and unloading the PlugIn, the Line Manager calls the method IClientAddInLoader::UnInitialize. The PlugIn has then a chance for clean up memory and other resources.
In the example implementation of CMyResolver::Initialize the PlugIn registers an event sink towards the Line Manager for receiving events. The Line Manager interface pointer pIClientLineMgrPub will be stored in the global interface table. Using its cookie m_dwCLMgrCookie the pointer will be retrieved on demand from the global interface table and automatically marshalled into the current thread context. You will find the used helper functions in the files githelp.cpp and githelp.h. This effort is required as soon as a COM interface pointer is used from multiple threads. GetName are GetVersion unspectacular. In the implementation of CMyResolver::UnInitialize the event sink will be released, that's always a good idea.
Line Manager events drop in in function CMyResolver::DispOnLineMgrNotification. Your PlugIn could e.g. write journal entries into a database or trigger a database application for popping up contact information.
In CMyResolver::GetPreferredNumberStyle the PlugIn can ask for a phone number format to be used for name resolution. Usually one would use the format PubCLMgrNumberStyleFull (like 0004923147770 or 0023147770). For any number to be resolved the Client Line Manager will call CMyResolver::ResolveNumber.
Replacing SwyxIt!
If you would like to replace SwyxIt!.exe by an own application (but who would really like to do this?), your application has to implement full call control. Otherwise the user would not have the chance to accept a second call or put a call on hold. Usually it is recommended, that your application just runs beside SwyxIt! for dialling or call monitoring.
The behaviour of the Client Line Managers towards other call control applications can be configured in the registry:
HKEY_LOCAL_MACHINE\SOFTWARE\SWYX\Client Line Manager\CurrentVersion\Options
DWORD "LaunchCallControlApplication"
activates (1, default) or deactivates (0) launching of a call control application in case of hook off. If no application should be launched on hook off, set this value to 0.
DWORD "AlternateCallControl"
activates (1) or deactivates (0, default) launching of an alternate call control application. If your own application should be launched instead of SwyxIt!, set this value to 1.
String "AlternateCallControlApplication"
provides the full path to the alternate call control application. In this case AlternateCallControl has to be set to 1. The path can include command line options.
To avoid that your alternate application is launched multiple times, your application has to open a named semaphore with name ALTERNATEPHONECLIENTRUNNING. The Client Line Manger will launch your application only if this semaphore does not yet exist:
//use semaphore for checking running instance
HANDLE hSemaphore=OpenSemaphore(SYNCHRONIZE, FALSE, "ALTERNATEPHONECLIENTRUNNING");
if(hSemaphore)
{
CloseHandle(hSemaphore);
}
else
{
//no running instance, launch call control application
WinExec(m_pLineMgr->m_sFullCallControlClientPath.c_str(), SW_SHOW);
}