This model uses the sr_NotifyEvt( ) function to send event notification (a user-specified message) to a user-specified window. The main application loop follows the standard Windows message handling scheme. When a Dialogic completion event occurs:
Choose the Asynchronous with Windows Callback model for an application that needs the tightest possible integration with the Windows messaging scheme.
Asynchronous with Windows Callback Model Advantages
Asynchronous with Windows Callback Model Disadvantages
Asynchronous with Windows Callback Model Programming Notes· sr_gettevtdev( ) to get the event's device handle.
· sr_gettevttype( ) to get the event type.
Asynchronous with Windows Callback Model ExampleAn example of the Asynchronous with Windows 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 windowsx.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 1
}
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
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);
}
break;
}
// 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