📄 ansrmt.c
字号:
/* AnsrMT.
* Multi threaded synchrounous answering phone demo for WinNT
*
* FEATURES: This sample program demonstrates how to implement a Dialogic
* Multi-threaded asynchronous code with voice and network devices.
* The programs creates one thread per voice channel. If a network (dti)
* device is selected, the corresponding tslots are opened and get routed
* to the associated voice channel.
* AnsrMT also demonstrates the use of the Compatibility Libraries, with the
* inclusion of the C source files for each library, as well as the calling
* of the xx_libinit() functions.
*
* NOTES: Inter.c is the GUI interface to this program, and Display.c is the
* file that contains the various functions that display the error, messages
* status information for the channels.
*
*/
/**
** System Header Files
**/
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
/**
** Dialogic Header Files
**/
#include "inter.h"
#include "sctools.h"
/*
* Globals
*/
char tmpbuff[ 256 ][MAXCHANS]; /* Temporary Buffer */
DX_INFO Dxinfo[ MAXCHANS ];
/**
** Global data
**/
/*
* File Descriptors for VOX Files
*/
static int gc_start = 0; // Indicate GC has not started yet
static int connected = 0;
static HWND hwnd;
static HANDLE hRingEvent[MAXCHANS]; // Event object used for ring detection
extern HANDLE hExitEvent;
extern int maxchans; /* Default Number of D/4x Channels to use */
extern int d4xbdnum; /* Default D/4x Board Number to Start use */
extern int dtibdnum; /* Default DTI Board Number to Start use */
extern int frontend; /* Default network frontend is ANALOG */
extern int routeag; /* Route analog frontend to resource ??? */
extern char protocol[]; /* The name of protocol for GC */
/*
* Function declarations
*/
void WINAPI ThreadFunc( int );
void intr_hdlr( int );
void sysinit( void );
int play( DX_INFO * );
int record( DX_INFO * );
int get_digits( DX_INFO * );
int set_hkstate(DX_INFO * , int );
int process( DX_INFO * );
int WaitRing( DX_INFO * );
long sig_hdlr( unsigned long );
long cst_hdlr( unsigned long );
long gc_hdlr( unsigned long );
int get_index( long );
void windexit( int );
void StopDialogic( void );
WINAPI InitDialogic ( HWND *tempHwnd ); // opens all the channels up!
void CloseDialogic(); // closes all the channels down
void print_GC_error( int index, char *msg );
/***************************************************************************
* NAME: void StopDialogic()
* DESCRIPTION: This function attempts to stop all I/O activity on all of the
* threads.
* INPUT: None
* OUTPUT: None.
* RETURNS: None.
* CAUTIONS: None.
***************************************************************************/
void StopDialogic()
{
int thread_num;
for ( thread_num = 0; thread_num < maxchans; thread_num++ )
{
Dxinfo[ thread_num ].stop_cause = USER_STOP;
dx_stopch( Dxinfo[ thread_num ].chdev, EV_ASYNC);
}
}
/***************************************************************************
* NAME: void CloseDialogic()
* DESCRIPTION: This function closes all the channels.
* INPUT: None
* OUTPUT: None.
* RETURNS: None.
* CAUTIONS: None.
***************************************************************************/
void CloseDialogic()
{
int thread_num;
/*
* Close all the channels opened after stopping all I/O activity.
* It is okay to stop the I/O on a channel as the program is
* being terminated.
*/
for ( thread_num = 0; thread_num < maxchans; thread_num++ )
{
set_hkstate( &Dxinfo[ thread_num ], DX_ONHOOK );
if ( frontend == CT_NTDM3 )
{
sr_dishdlr( Dxinfo[ thread_num ].ldev, EV_ANYEVT, gc_hdlr );
if ( gc_Close( Dxinfo[ thread_num ].ldev ) != GC_SUCCESS )
{
print_GC_error( thread_num, "gc_Close" );
}
continue;
}
if ( frontend == CT_NTANALOG )
{
sr_dishdlr( Dxinfo[ thread_num ].chdev, TDX_CST, cst_hdlr );
}
else
{ /* Digital Frontend */
/*
* Unroute the digital timeslots from their resource channels.
*/
nr_scunroute( Dxinfo[ thread_num ].tsdev, SC_DTI,
Dxinfo[ thread_num ].chdev, SC_VOX, SC_FULLDUP );
sr_dishdlr( Dxinfo[ thread_num ].tsdev, DTEV_SIG, sig_hdlr );
/*
* If E1 frontend, reset to "Blocking state"
*/
if ( frontend == CT_NTE1 )
{
dt_settssigsim( Dxinfo[ thread_num ].tsdev, DTB_BON );
}
dt_close( Dxinfo[ thread_num ].tsdev );
}
dx_close( Dxinfo[ thread_num ].chdev );
}
}
/***************************************************************************
* NAME: void sysinit()
* DESCRIPTION: Open VOX files and create an initialization thread per
* channel device
* INPUT: None.
* OUTPUT: None.
* RETURNS: None.
* CAUTIONS: None.
***************************************************************************/
void sysinit( void )
{
int channum, index;
int parmvalue = 6000;
char d4xname[ 32 ];
char dtiname[ 32 ];
char msg[ 512 ];
CT_DEVINFO ct_devinfo;
if ( maxchans > MAXCHANS )
{
sprintf( tmpbuff[ 0 ], "Only %d Channels will be used", MAXCHANS );
disp_msg( hwnd, tmpbuff[ 0 ] );
maxchans = MAXCHANS;
}
disp_msg( hwnd, "Initializing the Dialogic devices...." );
/*
* Clear the Dxinfo structure
* Initialize Channel States to Detect Call.
*/
memset( Dxinfo, -1, ( sizeof( DX_INFO ) * ( MAXCHANS ) ) );
//If the frontend is DM3 then Start GC
if ( frontend == CT_NTDM3 && gc_start == 0 )
{
if ( gc_Start( NULL) != GC_SUCCESS )
{
print_GC_error( -1, "gc_Start" );
QUIT( 1 );
}
gc_start = 1;
}
for ( channum = 1; channum <= maxchans; channum++ )
{
index = channum - 1;
//If the frontend is not the DM3 then open the Voice Device
if ( frontend != CT_NTDM3 )
{
/*
* Open the D/4x Channels
*/
sprintf( d4xname, "dxxxB%dC%d",
(channum % 4) ? (channum / 4) + d4xbdnum + 1 : d4xbdnum + (channum / 4) ,
(channum % 4) ? (channum % 4) : 4 );
if ( ( Dxinfo[ index ].chdev = dx_open( d4xname, 0 ) ) == -1 )
{
sprintf( tmpbuff[ index ], "Unable to open channel %s, errno = %d", d4xname, errno );
disp_status( hwnd, index+1, tmpbuff[ index ] );
if ( channum > 1 )
{ // at least two channels open, proceed
maxchans = channum-1;
continue;
}
else
QUIT( 2 );
}
// Save the device name( Vox and Dti )
sprintf( Dxinfo[ index ].dev_name, "%s", d4xname);
sprintf( tmpbuff[ index ], "Opened channel %s", d4xname);
disp_msg( hwnd, tmpbuff[ index ] );
}
if ( frontend == CT_NTANALOG )
{
/*
* Route analog frontend timeslots to its resource in SCbus mode,
* if required.
*/
if ( dx_getctinfo( Dxinfo[ index ].chdev, &ct_devinfo ) == -1 )
{
sprintf( tmpbuff[ index ], "dx_getctinfo() failed for %s",
ATDV_NAMEP( Dxinfo[ index ].chdev ) );
disp_msg( hwnd, tmpbuff[ index ] );
QUIT( 2 );
}
if ( ( routeag == TRUE ) && ct_devinfo.ct_busmode == CT_BMSCBUS )
{
nr_scunroute( Dxinfo[ index ].chdev, SC_LSI,
Dxinfo[ index ].chdev, SC_VOX, SC_FULLDUP );
if (nr_scroute( Dxinfo[ index ].chdev, SC_LSI,
Dxinfo[ index ].chdev, SC_VOX, SC_FULLDUP ) == -1 )
{
sprintf( tmpbuff[ index ], "nr_scroute() failed for %s",
ATDV_NAMEP( Dxinfo[ index ].chdev ) );
disp_msg( hwnd, tmpbuff[ index ] );
QUIT( 2 );
} // if (nr_scroute)
} // if (routeag)
}
else
/* Digital Frontend */
if ( frontend != CT_NTDM3 )
{
/*
* Form digital timeslots' names
*/
sprintf( dtiname, "dtiB%dT%d", dtibdnum+1, channum );
/*
* Open DTI timeslots.
*/
if ( ( Dxinfo[ index ].tsdev = dt_open( dtiname, 0 ) ) == -1 )
{
sprintf( tmpbuff[ index ], "Unable to open timeslot %s, errno = %d",
dtiname, errno );
disp_status( hwnd, index+1, tmpbuff[ index ] );
QUIT( 2 );
}
// Save the device name( Vox and Dti )
sprintf( Dxinfo[ index ].dev_name, "%s", dtiname);
/*
* Route timeslots to channels
*/
nr_scunroute( Dxinfo[ index ].tsdev, SC_DTI,
Dxinfo[ index ].chdev, SC_VOX, SC_FULLDUP );
if (nr_scroute( Dxinfo[ index ].tsdev, SC_DTI,
Dxinfo[ index ].chdev, SC_VOX, SC_FULLDUP ) == -1 )
{
sprintf( tmpbuff[ index ], "nr_scroute() failed for %s - %s",
ATDV_NAMEP( Dxinfo[ index ].tsdev ),
ATDV_NAMEP( Dxinfo[ index ].chdev ) );
disp_msg( hwnd, tmpbuff[ index ]);
disp_err( hwnd, index, Dxinfo[ index ].chdev);
QUIT( 2 );
}
}
else //This is the DM3 then issue gc_Open()
{
sprintf( Dxinfo[ index ].dev_name, ":N_dtiB%dT%d:P_%s", dtibdnum+1, channum, protocol );
if ( gc_Open( &Dxinfo[ index ].ldev, Dxinfo[ index ].dev_name, 0 ) != GC_SUCCESS )
{
print_GC_error( index, "gc_Open" );
QUIT( 2 );
}
if ( gc_GetVoiceH( Dxinfo[ index ].ldev, &Dxinfo[ index ].chdev ) != GC_SUCCESS )
{
print_GC_error( index, "gc_GetVoiceH" );
QUIT( 2 );
}
if ( gc_GetNetworkH( Dxinfo[ index ].ldev, &Dxinfo[ index ].tsdev ) != GC_SUCCESS )
{
print_GC_error( index, "gc_GetNetworkH" );
QUIT( 2 );
}
// Form the device name( Vox and Dti )
sprintf( Dxinfo[ index ].dev_name, ":N_%s:V_%s",
ATDV_NAMEP( Dxinfo[ index ].tsdev ),
ATDV_NAMEP( Dxinfo[ index ].chdev ) );
}
/*
* Set the sampling rate
*/
if ( dx_setparm( Dxinfo[ index ].chdev, DXCH_PLAYDRATE, &parmvalue ) == -1 )
{
sprintf( tmpbuff[ index ], "Cannot set the play rate for %s",
ATDV_NAMEP( Dxinfo[ index ].chdev ) );
disp_msg( hwnd, tmpbuff[ index ] );
disp_err( hwnd, index, Dxinfo[ index ].chdev );
QUIT( 2 );
}
if ( dx_setparm( Dxinfo[ index ].chdev, DXCH_RECRDRATE, &parmvalue ) == -1 )
{
sprintf( tmpbuff[ index ], "Cannot set the record rate for %s",
ATDV_NAMEP( Dxinfo[ index ].chdev ) );
disp_msg( hwnd, tmpbuff[ index ]);
disp_err( hwnd, index, Dxinfo[ index ].chdev);
QUIT( 2 );
}
if ( frontend != CT_NTDM3 )
{
/*
* Enable the CST events
*/
if ( dx_setevtmsk( Dxinfo[ index ].chdev, DM_RINGS ) == -1 )
{
sprintf( tmpbuff[ index ], "Cannot set CST events for %s",
ATDV_NAMEP( Dxinfo[ index ].chdev ) );
disp_msg( hwnd, tmpbuff[ index ]);
disp_err( hwnd, index, Dxinfo[ index ].chdev);
QUIT( 2 );
}
/*
* Set to answer after MAXRING rings
*/
if ( dx_setrings( Dxinfo[ index ].chdev, MAXRING ) == -1 )
{
sprintf( tmpbuff[ index ], "dx_setrings() failed for %s",
ATDV_NAMEP( Dxinfo[ index ].chdev ) );
disp_msg( hwnd, tmpbuff[ index ]);
disp_err( hwnd, index, Dxinfo[ index ].chdev );
QUIT( 2 );
}
}
sprintf( Dxinfo[ index ].ac_code, "%d234", channum%10 );
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -