The Synchronous with SRL Callback Model combines some of the advantages of both synchronous and asynchronous programming.
Choose this model for an application that needs to execute processing for synchronous Dialogic devices, and that needs to be notified of some asynchronous Dialogic events.
Call the sr_enbhdlr( ) function to enable a callback function that services some asynchronous Dialogic events. As an alternative, you can create your own thread which calls the sr_waitevt( ) function to receive asynchronous Dialogic events.
Synchronous with SRL Callback Model Advantages
Synchronous with SRL Callback Model Disadvantages
Synchronous with SRL Callback Model Programming Notes
Synchronous with SRL Callback Model ExampleAn example of the Synchronous with SRL Callback model is shown below:
/***************************************************************************************
*
* This Windows Callback model sample application was designed to work with
* D/41ESC, VFX/40ESC, LSI/81SC, LSI/161SC and D/160SC-LS boards only.
* It was compiled using MS-VC++.
* It cycles through 4 channels going offhook, dialing a digit string,
* going onhook. This is repeated until the user stops the processing from the
* Test menu in the main Window
* The test can be started by choosing the Go option of the Test menu in the
* program window
* ***************************************************************************************/ #define STRICT
#include <windows.h>
#include <windowsx.h>
#include <afxres.h>
#include <process.h>
#include <dxxxlib.h>
#include <srllib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include "resource.h"
#include <sctools.h>
// Defines
#define MAXCHAN 4 // maximum number of voice channels in system
#define WM_SRNOTIFYEVENT WM_USER + 100
#define ROWHEIGHT 20
// Modified version of the normal HANDLE_MSG macro in windows.h
#define HANDLE_DLGMSG(hwnd, message, fn) \
case (message): \
return(SetDlgMsgResult(hwnd, uMsg, \
HANDLE_##message((hwnd), (wParam), \
(lParam), (fn))))
// This may be expanded to contain other information such as state typedef struct dx_info {
int chdev;
int iter;
} DX_INFO;
// Globals
DX_INFO dxinfo[MAXCHAN+1];
int Kbhit_flag = 0;
char tmpbuf[128];
HANDLE hInst;
char gRowVal[MAXCHAN+1][80];
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void General_OnCommand(HWND , int , HWND , UINT ); // Window's WM_COMMAND handler int dlgc_OnCommand(HWND ); // WM_SRNOTIFYEVENT handler
int DialogicSysInit(HWND );
void DialogicClose(HWND);
int get_ts(int );
void disp_status(HWND, int , char *);
/*************************************************************************************
* NAME : WinMain()
* DESCRIPTION : Windows application entry point
* CAUTIONS : none.
*************************************************************************************/
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow) {
HWND hWnd;
WNDCLASS wc;
MSG msg;
hInst = hInstance;
if (!hinstPrev)
{
// Fill in window class structure with parameters that
// describe the main window.
wc.style = CS_HREDRAW | CS_VREDRAW;// Class style(s).
wc.lpfnWndProc = (WNDPROC)WndProc; // Window Procedure
wc.cbClsExtra = 0; // No per-class extra data.
wc.cbWndExtra = 0; // No per-window extra data.
wc.hInstance = hInstance; // Owner of this class
wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1)); // Icon name from .RC
wc.hCursor = LoadCursor(NULL, IDC_ARROW);// Cursor
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);// Default color
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
wc.lpszClassName = "WinCallBack"; // Name to register
// Register the window class and return success/failure code.
if (!RegisterClass(&wc))
return (FALSE); // Exits if unable to register
}
hWnd = CreateWindowEx(0L,"WinCallBack", "Windows Callback Demo", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
// If window could not be created, return "failure"
if (!hWnd)
return (FALSE);
sr_NotifyEvent(hWnd, WM_SRNOTIFYEVENT, SR_NOTIFY_ON);
ShowWindow(hWnd, SW_SHOW); // Show the window
UpdateWindow(hWnd); // Sends WM_PAINT message
// Get and dispatch messages until a WM_QUIT message is received. while (GetMessage(&msg, NULL, 0,0))
{
TranslateMessage(&msg);// Translates virtual key code DispatchMessage(&msg); // Dispatches message to window
}
return (0);
}
/*************************************************************************************
* NAME : WndProc()
* DESCRIPTION : Windows Procedure
* CAUTIONS : none. *************************************************************************************/
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
int numchan;
switch (uMsg) {
// Handle the WM_COMMAND messages HANDLE_MSG(hWnd, WM_COMMAND, General_OnCommand);
case WM_SRNOTIFYEVENT:
if (dlgc_OnCommand( hWnd)) {// Dialogic event DialogicClose(hWnd);
DestroyWindow(hWnd); // if dlgc_OnCommand() returns FALSE }
break;
case WM_CREATE:
break;
case WM_PAINT:
// get the actual window rectangle
GetClientRect(hWnd, &rect);
hDC = BeginPaint(hWnd, &ps);
// display name of application
rect.top = ROWHEIGHT;
sprintf(tmpbuf,"Windows Callback Demo");
DrawText(hDC,tmpbuf , -1, &rect, DT_SINGLELINE|DT_CENTER);
// display status of channel
for (numchan=1;numchan<=MAXCHAN;numchan++) {
rect.top = (numchan+2) * ROWHEIGHT;
DrawText(hDC, gRowVal[numchan], -1, &rect, DT_SINGLELINE);
}
EndPaint(hWnd, &ps);
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0); // Allow GetMessage() to return FALSE
break;
default:
return (DefWindowProc(hWnd, uMsg, wParam, lParam));
} // switch (uMsg)
}
/*************************************************************************************
* NAME : General_OnCommand()
* DESCRIPTION : Message Handler for WM_COMMAND
* CAUTIONS : none.
*************************************************************************************/
void General_OnCommand(HWND hWnd, int id, HWND hwndCtl, UINT codeNotify)
{
switch (id) {
case ID_TEST_EXIT:
DestroyWindow(hWnd); // post WM_DESTROY message for WndProc to exit app break;
case ID_TEST_GO: // create threads here and gray the "start" menu and
// launch the call control threads
if (DialogicSysInit(hWnd)) {
// initialize Dialogic devices, if error initializing then show error message and exit MessageBox(hWnd, "Error initializing",
"ERROR", MB_OK | MB_ICONSTOP| MB_APPLMODAL); break;
}
// // ungrey the "stop" menu
EnableMenuItem(GetMenu(hWnd), ID_TEST_STOP, MF_ENABLED );
EnableMenuItem(GetMenu(hWnd), ID_TEST_GO, MF_DISABLED | MF_GRAYED);
break;
case ID_TEST_STOP: // "terminate" the call control threads and ungray menu items // terminate the call control
threads
DialogicClose(hWnd);
// disable the Action/Stop menu item
EnableMenuItem(GetMenu(hWnd), ID_TEST_STOP, MF_DISABLED | MF_GRAYED); EnableMenuItem(GetMenu(hWnd),
ID_TEST_GO, MF_ENABLED );
break;
default:
return;
} // switch (id)
}
/*************************************************************************************
* NAME : dlgc_OnCommand()
* DESCRIPTION : Message Handler for WM_SRNOTIFYEVENT
* CAUTIONS : none.
*************************************************************************************/
int dlgc_OnCommand(HWND hWnd)
{
int rc = 0;
int chdev;
int event;
DX_CST *cstp;
static iter=0;
int channum;
if (sr_waitevt(0) == -1) {
sprintf(tmpbuf, "sr_waitevt() ERROR %s", ATDV_ERRMSGP( SRL_DEVICE )); MessageBox(hWnd,tmpbuf, "ERROR" , MB_OK|MB_APPLMODAL);
return (1);
}
chdev = sr_getevtdev();
event = sr_getevttype();
/*
* Switch according to the event received. */
switch ( event ) {
case TDX_SETHOOK:
cstp = (DX_CST *)sr_getevtdatap(); switch( cstp->cst_event) { case DX_ONHOOK:
/* Go offhook next */
if (dx_sethook(chdev, DX_OFFHOOK, EV_ASYNC) == -1) {
sprintf(tmpbuf,"FAILED: dx_sethook(%s, DX_OFFHOOK): %s (error #%d)", ATDV_NAMEP(chdev), ATDV_ERRMSGP(chdev),
ATDV_LASTERR(chdev));
MessageBox(hWnd, tmpbuf, "ERROR",MB_OK|MB_APPLMODAL); return(1);
}
break;
case DX_OFFHOOK:
/* dial next */
if (dx_dial(chdev, "12025551212", NULL, EV_ASYNC) == -1) { sprintf(tmpbuf,"FAILED: dx_dial(%s): %s (error #%d) ", ATDV_NAMEP(chdev),
ATDV_ERRMSGP(chdev),
ATDV_LASTERR(chdev));
MessageBox(hWnd, tmpbuf, "ERROR",MB_OK|MB_APPLMODAL); return(1);
}
break;
}
break;
case TDX_DIAL:
/* Next go onhook */
if (dx_sethook(chdev, DX_ONHOOK, EV_ASYNC) == -1) {
sprintf(tmpbuf,"FAILED: dx_sethook(%s, DX_ONHOOK): %s (error #%d) ", ATDV_NAMEP(chdev), ATDV_ERRMSGP(chdev),
ATDV_LASTERR(chdev));
MessageBox(hWnd, tmpbuf, "ERROR",MB_OK|MB_APPLMODAL);
return(1);
}
}
// retrieve channel number using the USERCONTEXT feature of the SRL
if (sr_getparm(chdev, SR_USERCONTEXT, (void *)&channum) == -1) { sprintf(tmpbuf,"FAILED: sr_getparm(%s): %s (error #%d) ", ATDV_NAMEP(dxinfo[channum].chdev),
ATDV_ERRMSGP(dxinfo[channum].chdev),
ATDV_LASTERR(dxinfo[channum].chdev));
MessageBox(hWnd, tmpbuf, "ERROR",MB_OK|MB_APPLMODAL);
return(1);
}
sprintf(tmpbuf, "Iteration %d Completed", ++dxinfo[channum].iter); disp_status(hWnd, channum, tmpbuf );
return (0);
}
/*************************************************************************************
* NAME : DialogicSysInit()
* DESCRIPTION : Initialization of Dialogic devices
* CAUTIONS : none.
*************************************************************************************
/ int DialogicSysInit(HWND hWnd)
{
int numchan;
char channame[20];
/* Initial processing for MAXCHANS */
for (numchan=1;numchan<=MAXCHAN;numchan++) {
/* build name of voice channel */
sprintf(channame, "dxxxB%dC%d", ((numchan-1) / 4) + 1,
((numchan -1)% 4) + 1);
/* open voice channel */
if ((dxinfo[numchan].chdev = dx_open(channame, 0)) == -1) {sprintf(tmpbuf,"FAILED: dx_open(%s): system error = %d ", channame,
dx_fileerrno());
MessageBox(hWnd, tmpbuf, "ERROR",MB_OK|MB_APPLMODAL);
return(1);
}
/* set user specific information in the device, in this
** case the channel number
*/
if (sr_setparm(dxinfo[numchan].chdev, SR_USERCONTEXT, (void *)&numchan) == -1) { sprintf(tmpbuf,"FAILED: sr_setparm(%s): %s (error #%d) ", ATDV_NAMEP(dxinfo[numchan].chdev), ATDV_ERRMSGP(dxinfo[numchan].chdev), ATDV_LASTERR(dxinfo[numchan].chdev));
MessageBox(hWnd, tmpbuf, "ERROR",MB_OK|MB_APPLMODAL);
return(1);
}
/* Start the application by putting the channel in onhook state */
if (dx_sethook(dxinfo[numchan].chdev,DX_ONHOOK,EV_ASYNC) == -1) { sprintf(tmpbuf,"FAILED: dx_sethook(%s): %s (error #%d) ",
ATDV_NAMEP(dxinfo[numchan].chdev), ATDV_ERRMSGP(dxinfo[numchan].chdev), ATDV_LASTERR(dxinfo[numchan].chdev));
MessageBox(hWnd, tmpbuf, "ERROR",MB_OK|MB_APPLMODAL); return(1);
}
}
return(0);
}
/*************************************************************************************
* NAME : DialogicClose()
* DESCRIPTION : Tier down of Dialogic devices
* CAUTIONS : none.
*************************************************************************************/ void DialogicClose(HWND hWnd)
{
int numchan;
/* Close all voice devices before exiting */
for (numchan=1;numchan<=MAXCHAN;numchan++) {
// attempt to stop the channel dx_stopch(dxinfo[numchan].chdev,EV_SYNC); dx_close(dxinfo[numchan].chdev);
}
}
/***************************************************************************
* NAME: disp_status(hwnd, chnum, stringp)
* INPUTS: chno - channel number (1 - 12)
* stringp - pointer to string to display
* DESCRIPTION: display the current activity on the channel in window 2
* the string pointed to by stringp) using chno as a Y offset
*************************************************************************/
void disp_status(HWND hWnd, int channum, char *stringp)
{
RECT rect;
// get the entire window rectangle and modify it
GetClientRect(hWnd, &rect);
rect.top = (channum+2) * ROWHEIGHT;
rect.bottom = (channum+3) * ROWHEIGHT;
// buffer the message
sprintf(gRowVal[channum], "Channel %d: %s", channum, stringp);
InvalidateRect(hWnd, &rect, TRUE);
UpdateWindow(hWnd);
}
Click here to contact Dialogic Customer Engineering
Copyright 2001, Dialogic Corporation