@ -88,7 +88,7 @@ static struct ast_jb_conf default_jbconf =
. flags = 0 ,
. max_size = - 1 ,
. resync_threshold = - 1 ,
. impl = " "
. impl = " " ,
} ;
static struct ast_jb_conf global_jbconf ;
@ -264,9 +264,9 @@ END_CONFIG
# define TEXT_SIZE 256
#if 0
# define TRYOPEN 1 /* try to open on startup */
# define TRYOPEN 1 /* try to open on startup */
# endif
# define O_CLOSE 0x444 /* special 'close' mode for device */
# define O_CLOSE 0x444 /* special 'close' mode for device */
/* Which device to use */
# if defined( __OpenBSD__ ) || defined( __NetBSD__ )
# define DEV_DSP " / dev / audio"
@ -332,26 +332,26 @@ struct chan_oss_pvt {
* nosound is set to disable the audio data from the channel
* ( so we can play the tones etc . ) .
*/
int sndcmd [ 2 ] ; /* Sound command pipe */
int cursound ; /* index of sound to send */
int sampsent ; /* # of sound samples sent */
int nosound ; /* set to block audio from the PBX */
int sndcmd [ 2 ] ; /* Sound command pipe */
int cursound ; /* index of sound to send */
int sampsent ; /* # of sound samples sent */
int nosound ; /* set to block audio from the PBX */
int total_blocks ; /* total blocks in the output device */
int total_blocks ; /* total blocks in the output device */
int sounddev ;
enum { M_UNSET , M_FULL , M_READ , M_WRITE } duplex ;
int autoanswer ;
int autohangup ;
int hookstate ;
char * mixer_cmd ; /* initial command to issue to the mixer */
unsigned int queuesize ; /* max fragments in queue */
unsigned int frags ; /* parameter for SETFRAGMENT */
char * mixer_cmd ; /* initial command to issue to the mixer */
unsigned int queuesize ; /* max fragments in queue */
unsigned int frags ; /* parameter for SETFRAGMENT */
int warned ; /* various flags used for warnings */
int warned ; /* various flags used for warnings */
# define WARN_used_blocks 1
# define WARN_speed 2
# define WARN_frag 4
int w_errors ; /* overfull in the write path */
int w_errors ; /* overfull in the write path */
struct timeval lastopen ;
int overridecontext ;
@ -361,9 +361,9 @@ struct chan_oss_pvt {
* be representable in 16 bits to avoid overflows .
*/
# define BOOST_SCALE (1<<9)
# define BOOST_MAX 40 /* slightly less than 7 bits */
int boost ; /* input boost, scaled by BOOST_SCALE */
char device [ 64 ] ; /* device to open */
# define BOOST_MAX 40 /* slightly less than 7 bits */
int boost ; /* input boost, scaled by BOOST_SCALE */
char device [ 64 ] ; /* device to open */
pthread_t sthread ;
@ -371,25 +371,25 @@ struct chan_oss_pvt {
char ext [ AST_MAX_EXTENSION ] ;
char ctx [ AST_MAX_CONTEXT ] ;
char language [ MAX_LANGUAGE ] ;
char cid_name [ 256 ] ; /*XXX */
char cid_num [ 256 ] ; /*XXX */
char cid_name [ 256 ] ; /*XXX */
char cid_num [ 256 ] ; /*XXX */
char mohinterpret [ MAX_MUSICCLASS ] ;
/* buffers used in oss_write */
char oss_write_buf [ FRAME_SIZE * 2 ] ;
char oss_write_buf [ FRAME_SIZE * 2 ] ;
int oss_write_dst ;
/* buffers used in oss_read - AST_FRIENDLY_OFFSET space for headers
* plus enough room for a full frame
*/
char oss_read_buf [ FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET ] ;
int readpos ; /* read position above */
int readpos ; /* read position above */
struct ast_frame read_f ; /* returned by oss_read */
} ;
static struct chan_oss_pvt oss_default = {
. cursound = - 1 ,
. sounddev = - 1 ,
. duplex = M_UNSET , /* XXX check this */
. duplex = M_UNSET , /* XXX check this */
. autoanswer = 1 ,
. autohangup = 1 ,
. queuesize = QUEUE_SIZE ,
@ -420,9 +420,9 @@ static int oss_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static char tdesc [ ] = " OSS Console Channel Driver " ;
static const struct ast_channel_tech oss_tech = {
. type = " Console " ,
. description = tdesc ,
. capabilities = AST_FORMAT_SLINEAR ,
. type = " Console " ,
. description = tdesc ,
. capabilities = AST_FORMAT_SLINEAR ,
. requester = oss_request ,
. send_digit_begin = oss_digit_begin ,
. send_digit_end = oss_digit_end ,
@ -441,14 +441,16 @@ static const struct ast_channel_tech oss_tech = {
*/
static struct chan_oss_pvt * find_desc ( char * dev )
{
struct chan_oss_pvt * o ;
if ( dev = = NULL )
struct chan_oss_pvt * o = NULL ;
if ( ! dev )
ast_log ( LOG_WARNING , " null dev \n " ) ;
for ( o = oss_default . next ; o & & o - > name & & dev & & strcmp ( o - > name , dev ) ! = 0 ; o = o - > next )
;
if ( o = = NULL )
for ( o = oss_default . next ; o & & o - > name & & dev & & strcmp ( o - > name , dev ) ! = 0 ; o = o - > next ) ;
if ( ! o )
ast_log ( LOG_WARNING , " could not find <%s> \n " , dev ? dev : " --no-device-- " ) ;
return o ;
}
@ -466,18 +468,23 @@ static char *ast_ext_ctx(const char *src, char **ext, char **ctx)
struct chan_oss_pvt * o = find_desc ( oss_active ) ;
if ( ext = = NULL | | ctx = = NULL )
return NULL ; /* error */
return NULL ; /* error */
* ext = * ctx = NULL ;
if ( src & & * src ! = ' \0 ' )
* ext = ast_strdup ( src ) ;
if ( * ext = = NULL )
return NULL ;
if ( ! o - > overridecontext ) {
/* parse from the right */
* ctx = strrchr ( * ext , ' @ ' ) ;
if ( * ctx )
* ( * ctx ) + + = ' \0 ' ;
}
return * ext ;
}
@ -489,20 +496,19 @@ static int used_blocks(struct chan_oss_pvt *o)
struct audio_buf_info info ;
if ( ioctl ( o - > sounddev , SNDCTL_DSP_GETOSPACE , & info ) ) {
if ( ! ( o - > warned & WARN_used_blocks ) ) {
if ( ! ( o - > warned & WARN_used_blocks ) ) {
ast_log ( LOG_WARNING , " Error reading output space \n " ) ;
o - > warned | = WARN_used_blocks ;
}
return 1 ;
}
if ( o - > total_blocks = = 0 ) {
if ( 0 ) /* debugging */
ast_log ( LOG_WARNING , " fragtotal %d size %d avail %d \n " ,
info . fragstotal ,
info . fragsize ,
info . fragments ) ;
if ( 0 ) /* debugging */
ast_log ( LOG_WARNING , " fragtotal %d size %d avail %d \n " , info . fragstotal , info . fragsize , info . fragments ) ;
o - > total_blocks = info . fragments ;
}
return o - > total_blocks - info . fragments ;
}
@ -514,7 +520,7 @@ static int soundcard_writeframe(struct chan_oss_pvt *o, short *data)
if ( o - > sounddev < 0 )
setformat ( o , O_RDWR ) ;
if ( o - > sounddev < 0 )
return 0 ; /* not fatal */
return 0 ; /* not fatal */
/*
* Nothing complex to manage the audio device queue .
* If the buffer is full just drop the extra , otherwise write .
@ -524,12 +530,11 @@ static int soundcard_writeframe(struct chan_oss_pvt *o, short *data)
res = used_blocks ( o ) ;
if ( res > o - > queuesize ) { /* no room to write a block */
if ( o - > w_errors + + = = 0 & & ( oss_debug & 0x4 ) )
ast_log ( LOG_WARNING , " write: used %d blocks (%d) \n " ,
res , o - > w_errors ) ;
ast_log ( LOG_WARNING , " write: used %d blocks (%d) \n " , res , o - > w_errors ) ;
return 0 ;
}
o - > w_errors = 0 ;
return write ( o - > sounddev , ( ( void * ) data ) , FRAME_SIZE * 2 ) ;
return write ( o - > sounddev , ( ( void * ) data ) , FRAME_SIZE * 2 ) ;
}
/*
@ -549,37 +554,38 @@ static void send_sound(struct chan_oss_pvt *o)
int l_sampsent = o - > sampsent ;
struct sound * s ;
if ( o - > cursound < 0 ) /* no sound to send */
if ( o - > cursound < 0 ) /* no sound to send */
return ;
s = & sounds [ o - > cursound ] ;
for ( ofs = 0 ; ofs < FRAME_SIZE ; ofs + = l ) {
l = s - > samplen - l_sampsent ; /* # of available samples */
if ( l > 0 ) {
start = l_sampsent % s - > datalen ; /* source offset */
start = l_sampsent % s - > datalen ; /* source offset */
if ( l > FRAME_SIZE - ofs ) /* don't overflow the frame */
l = FRAME_SIZE - ofs ;
if ( l > s - > datalen - start ) /* don't overflow the source */
l = s - > datalen - start ;
bcopy ( s - > data + start , myframe + ofs , l * 2 ) ;
bcopy ( s - > data + start , myframe + ofs , l * 2 ) ;
if ( 0 )
ast_log ( LOG_WARNING , " send_sound sound %d/%d of %d into %d \n " ,
l_sampsent , l , s - > samplen , ofs ) ;
ast_log ( LOG_WARNING , " send_sound sound %d/%d of %d into %d \n " , l_sampsent , l , s - > samplen , ofs ) ;
l_sampsent + = l ;
} else { /* end of samples, maybe some silence */
static const short silence [ FRAME_SIZE ] = { 0 , } ;
} else { /* end of samples, maybe some silence */
static const short silence [ FRAME_SIZE ] = { 0 , } ;
l + = s - > silencelen ;
if ( l > 0 ) {
if ( l > FRAME_SIZE - ofs )
l = FRAME_SIZE - ofs ;
bcopy ( silence , myframe + ofs , l * 2 ) ;
bcopy ( silence , myframe + ofs , l * 2 ) ;
l_sampsent + = l ;
} else { /* silence is over, restart sound if loop */
} else { /* silence is over, restart sound if loop */
if ( s - > repeat = = 0 ) { /* last block */
o - > cursound = - 1 ;
o - > nosound = 0 ; /* allow audio data */
if ( ofs < FRAME_SIZE ) /* pad with silence */
bcopy ( silence , myframe + ofs , ( FRAME_SIZE - ofs ) * 2 ) ;
bcopy ( silence , myframe + ofs , ( FRAME_SIZE - ofs ) * 2 ) ;
}
l_sampsent = 0 ;
}
@ -593,7 +599,7 @@ static void send_sound(struct chan_oss_pvt *o)
static void * sound_thread ( void * arg )
{
char ign [ 4096 ] ;
struct chan_oss_pvt * o = ( struct chan_oss_pvt * ) arg ;
struct chan_oss_pvt * o = ( struct chan_oss_pvt * ) arg ;
/*
* Just in case , kick the driver by trying to read from it .
@ -609,11 +615,11 @@ static void *sound_thread(void *arg)
FD_SET ( o - > sndcmd [ 0 ] , & rfds ) ;
maxfd = o - > sndcmd [ 0 ] ; /* pipe from the main process */
if ( o - > cursound > - 1 & & o - > sounddev < 0 )
setformat ( o , O_RDWR ) ; /* need the channel, try to reopen */
setformat ( o , O_RDWR ) ; /* need the channel, try to reopen */
else if ( o - > cursound = = - 1 & & o - > owner = = NULL )
setformat ( o , O_CLOSE ) ; /* can close */
setformat ( o , O_CLOSE ) ; /* can close */
if ( o - > sounddev > - 1 ) {
if ( ! o - > owner ) { /* no one owns the audio, so we must drain it */
if ( ! o - > owner ) { /* no one owns the audio, so we must drain it */
FD_SET ( o - > sounddev , & rfds ) ;
maxfd = MAX ( o - > sounddev , maxfd ) ;
}
@ -638,7 +644,7 @@ static void *sound_thread(void *arg)
if ( sounds [ i ] . ind = = what ) {
o - > cursound = i ;
o - > sampsent = 0 ;
o - > nosound = 1 ; /* block audio from pbx */
o - > nosound = 1 ; /* block audio from pbx */
break ;
}
}
@ -646,13 +652,13 @@ static void *sound_thread(void *arg)
ast_log ( LOG_WARNING , " invalid sound index: %d \n " , what ) ;
}
if ( o - > sounddev > - 1 ) {
if ( FD_ISSET ( o - > sounddev , & rfds ) ) /* read and ignore errors */
if ( FD_ISSET ( o - > sounddev , & rfds ) ) /* read and ignore errors */
read ( o - > sounddev , ign , sizeof ( ign ) ) ;
if ( FD_ISSET ( o - > sounddev , & wfds ) )
send_sound ( o ) ;
}
}
return NULL ; /* Never reached */
return NULL ; /* Never reached */
}
/*
@ -670,15 +676,14 @@ static int setformat(struct chan_oss_pvt *o, int mode)
o - > duplex = M_UNSET ;
o - > sounddev = - 1 ;
}
if ( mode = = O_CLOSE ) /* we are done */
if ( mode = = O_CLOSE ) /* we are done */
return 0 ;
if ( ast_tvdiff_ms ( ast_tvnow ( ) , o - > lastopen ) < 1000 )
return - 1 ; /* don't open too often */
return - 1 ; /* don't open too often */
o - > lastopen = ast_tvnow ( ) ;
fd = o - > sounddev = open ( o - > device , mode | O_NONBLOCK ) ;
fd = o - > sounddev = open ( o - > device , mode | O_NONBLOCK ) ;
if ( fd < 0 ) {
ast_log ( LOG_WARNING , " Unable to re-open DSP device %s: %s \n " ,
o - > device , strerror ( errno ) ) ;
ast_log ( LOG_WARNING , " Unable to re-open DSP device %s: %s \n " , o - > device , strerror ( errno ) ) ;
return - 1 ;
}
if ( o - > owner )
@ -695,22 +700,22 @@ static int setformat(struct chan_oss_pvt *o, int mode)
return - 1 ;
}
switch ( mode ) {
case O_RDWR :
res = ioctl ( fd , SNDCTL_DSP_SETDUPLEX , 0 ) ;
/* Check to see if duplex set (FreeBSD Bug) */
res = ioctl ( fd , SNDCTL_DSP_GETCAPS , & fmt ) ;
if ( res = = 0 & & ( fmt & DSP_CAP_DUPLEX ) ) {
if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " Console is full duplex \n " ) ;
o - > duplex = M_FULL ;
} ;
break ;
case O_WRONLY :
o - > duplex = M_WRITE ;
break ;
case O_RDONLY :
o - > duplex = M_READ ;
break ;
case O_RDWR :
res = ioctl ( fd , SNDCTL_DSP_SETDUPLEX , 0 ) ;
/* Check to see if duplex set (FreeBSD Bug) */
res = ioctl ( fd , SNDCTL_DSP_GETCAPS , & fmt ) ;
if ( res = = 0 & & ( fmt & DSP_CAP_DUPLEX ) ) {
if ( option_verbose > 1 )
ast_verbose ( VERBOSE_PREFIX_2 " Console is full duplex \n " ) ;
o - > duplex = M_FULL ;
} ;
break ;
case O_WRONLY :
o - > duplex = M_WRITE ;
break ;
case O_RDONLY :
o - > duplex = M_READ ;
break ;
}
fmt = 0 ;
@ -719,7 +724,7 @@ static int setformat(struct chan_oss_pvt *o, int mode)
ast_log ( LOG_WARNING , " Failed to set audio device to mono \n " ) ;
return - 1 ;
}
fmt = desired = DEFAULT_SAMPLE_RATE ; /* 8000 Hz desired */
fmt = desired = DEFAULT_SAMPLE_RATE ; /* 8000 Hz desired */
res = ioctl ( fd , SNDCTL_DSP_SPEED , & fmt ) ;
if ( res < 0 ) {
@ -767,14 +772,14 @@ static int oss_digit_begin(struct ast_channel *c, char digit)
static int oss_digit_end ( struct ast_channel * c , char digit )
{
/* no better use for received digits than print them */
ast_verbose ( " << Console Received digit %c >> \n " , digit ) ;
ast_verbose ( " << Console Received digit %c >> \n " , digit ) ;
return 0 ;
}
static int oss_text ( struct ast_channel * c , const char * text )
{
/* print received messages */
ast_verbose ( " << Console Received text %s >> \n " , text ) ;
ast_verbose ( " << Console Received text %s >> \n " , text ) ;
return 0 ;
}
@ -793,10 +798,9 @@ static int oss_call(struct ast_channel *c, char *dest, int timeout)
struct chan_oss_pvt * o = c - > tech_pvt ;
struct ast_frame f = { 0 , } ;
ast_verbose ( " << Call to device '%s' dnid '%s' rdnis '%s' on console from '%s' <%s> >> \n " ,
dest , c - > cid . cid_dnid , c - > cid . cid_rdnis , c - > cid . cid_name , c - > cid . cid_num ) ;
ast_verbose ( " << Call to device '%s' dnid '%s' rdnis '%s' on console from '%s' <%s> >> \n " , dest , c - > cid . cid_dnid , c - > cid . cid_rdnis , c - > cid . cid_name , c - > cid . cid_num ) ;
if ( o - > autoanswer ) {
ast_verbose ( " << Auto-answered >> \n " ) ;
ast_verbose ( " << Auto-answered >> \n " ) ;
f . frametype = AST_FRAME_CONTROL ;
f . subclass = AST_CONTROL_ANSWER ;
ast_queue_frame ( c , & f ) ;
@ -817,14 +821,14 @@ static int oss_answer(struct ast_channel *c)
{
struct chan_oss_pvt * o = c - > tech_pvt ;
ast_verbose ( " << Console call has been answered >> \n " ) ;
ast_verbose ( " << Console call has been answered >> \n " ) ;
#if 0
/* play an answer tone (XXX do we really need it ?) */
ring ( o , AST_CONTROL_ANSWER ) ;
# endif
ast_setstate ( c , AST_STATE_UP ) ;
o - > cursound = - 1 ;
o - > nosound = 0 ;
o - > nosound = 0 ;
return 0 ;
}
@ -836,7 +840,7 @@ static int oss_hangup(struct ast_channel *c)
o - > nosound = 0 ;
c - > tech_pvt = NULL ;
o - > owner = NULL ;
ast_verbose ( " << Hangup on console >> \n " ) ;
ast_verbose ( " << Hangup on console >> \n " ) ;
ast_mutex_lock ( & usecnt_lock ) ; /* XXX not sure why */
usecnt - - ;
ast_mutex_unlock ( & usecnt_lock ) ;
@ -870,22 +874,20 @@ static int oss_write(struct ast_channel *c, struct ast_frame *f)
* in FRAME_SIZE chunks .
* Keep the residue stored for future use .
*/
src = 0 ; /* read position into f->data */
while ( src < f - > datalen ) {
src = 0 ; /* read position into f->data */
while ( src < f - > datalen ) {
/* Compute spare room in the buffer */
int l = sizeof ( o - > oss_write_buf ) - o - > oss_write_dst ;
if ( f - > datalen - src > = l ) { /* enough to fill a frame */
memcpy ( o - > oss_write_buf + o - > oss_write_dst ,
f - > data + src , l ) ;
soundcard_writeframe ( o , ( short * ) o - > oss_write_buf ) ;
memcpy ( o - > oss_write_buf + o - > oss_write_dst , f - > data + src , l ) ;
soundcard_writeframe ( o , ( short * ) o - > oss_write_buf ) ;
src + = l ;
o - > oss_write_dst = 0 ;
} else { /* copy residue */
} else { /* copy residue */
l = f - > datalen - src ;
memcpy ( o - > oss_write_buf + o - > oss_write_dst ,
f - > data + src , l ) ;
src + = l ; /* but really, we are done */
memcpy ( o - > oss_write_buf + o - > oss_write_dst , f - > data + src , l ) ;
src + = l ; /* but really, we are done */
o - > oss_write_dst + = l ;
}
}
@ -904,9 +906,8 @@ static struct ast_frame *oss_read(struct ast_channel *c)
f - > frametype = AST_FRAME_NULL ;
f - > src = oss_tech . type ;
res = read ( o - > sounddev , o - > oss_read_buf + o - > readpos ,
sizeof ( o - > oss_read_buf ) - o - > readpos ) ;
if ( res < 0 ) /* audio data not ready, return a NULL frame */
res = read ( o - > sounddev , o - > oss_read_buf + o - > readpos , sizeof ( o - > oss_read_buf ) - o - > readpos ) ;
if ( res < 0 ) /* audio data not ready, return a NULL frame */
return f ;
o - > readpos + = res ;
@ -925,9 +926,9 @@ static struct ast_frame *oss_read(struct ast_channel *c)
f - > samples = FRAME_SIZE ;
f - > datalen = FRAME_SIZE * 2 ;
f - > data = o - > oss_read_buf + AST_FRIENDLY_OFFSET ;
if ( o - > boost ! = BOOST_SCALE ) { /* scale and clip values */
if ( o - > boost ! = BOOST_SCALE ) { /* scale and clip values */
int i , x ;
int16_t * p = ( int16_t * ) f - > data ;
int16_t * p = ( int16_t * ) f - > data ;
for ( i = 0 ; i < f - > samples ; i + + ) {
x = ( p [ i ] * o - > boost ) / BOOST_SCALE ;
if ( x > 32767 )
@ -954,35 +955,33 @@ static int oss_indicate(struct ast_channel *c, int cond, const void *data, size_
struct chan_oss_pvt * o = c - > tech_pvt ;
int res = - 1 ;
switch ( cond ) {
case AST_CONTROL_BUSY :
case AST_CONTROL_CONGESTION :
case AST_CONTROL_RINGING :
res = cond ;
break ;
case - 1 :
o - > cursound = - 1 ;
o - > nosound = 0 ; /* when cursound is -1 nosound must be 0 */
return 0 ;
case AST_CONTROL_VIDUPDATE :
res = - 1 ;
break ;
case AST_CONTROL_HOLD :
ast_verbose ( " << Console Has Been Placed on Hold >> \n " ) ;
ast_moh_start ( c , data , o - > mohinterpret ) ;
break ;
case AST_CONTROL_UNHOLD :
ast_verbose ( " << Console Has Been Retrieved from Hold >> \n " ) ;
ast_moh_stop ( c ) ;
break ;
default :
ast_log ( LOG_WARNING ,
" Don't know how to display condition %d on %s \n " ,
cond , c - > name ) ;
return - 1 ;
switch ( cond ) {
case AST_CONTROL_BUSY :
case AST_CONTROL_CONGESTION :
case AST_CONTROL_RINGING :
res = cond ;
break ;
case - 1 :
o - > cursound = - 1 ;
o - > nosound = 0 ; /* when cursound is -1 nosound must be 0 */
return 0 ;
case AST_CONTROL_VIDUPDATE :
res = - 1 ;
break ;
case AST_CONTROL_HOLD :
ast_verbose ( " << Console Has Been Placed on Hold >> \n " ) ;
ast_moh_start ( c , data , o - > mohinterpret ) ;
break ;
case AST_CONTROL_UNHOLD :
ast_verbose ( " << Console Has Been Retrieved from Hold >> \n " ) ;
ast_moh_stop ( c ) ;
break ;
default :
ast_log ( LOG_WARNING , " Don't know how to display condition %d on %s \n " , cond , c - > name ) ;
return - 1 ;
}
if ( res > - 1 )
@ -994,8 +993,7 @@ static int oss_indicate(struct ast_channel *c, int cond, const void *data, size_
/*
* allocate a new channel .
*/
static struct ast_channel * oss_new ( struct chan_oss_pvt * o ,
char * ext , char * ctx , int state )
static struct ast_channel * oss_new ( struct chan_oss_pvt * o , char * ext , char * ctx , int state )
{
struct ast_channel * c ;
@ -1006,7 +1004,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o,
ast_string_field_build ( c , name , " OSS/%s " , o - > device + 5 ) ;
if ( o - > sounddev < 0 )
setformat ( o , O_RDWR ) ;
c - > fds [ 0 ] = o - > sounddev ; /* -1 if device closed, override later */
c - > fds [ 0 ] = o - > sounddev ; /* -1 if device closed, override later */
c - > nativeformats = AST_FORMAT_SLINEAR ;
c - > readformat = AST_FORMAT_SLINEAR ;
c - > writeformat = AST_FORMAT_SLINEAR ;
@ -1042,16 +1040,14 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o,
return c ;
}
static struct ast_channel * oss_request ( const char * type ,
int format , void * data , int * cause )
static struct ast_channel * oss_request ( const char * type , int format , void * data , int * cause )
{
struct ast_channel * c ;
struct chan_oss_pvt * o = find_desc ( data ) ;
ast_log ( LOG_WARNING , " oss_request ty <%s> data 0x%p <%s> \n " ,
type , data , ( char * ) data ) ;
ast_log ( LOG_WARNING , " oss_request ty <%s> data 0x%p <%s> \n " , type , data , ( char * ) data ) ;
if ( o = = NULL ) {
ast_log ( LOG_NOTICE , " Device %s not found \n " , ( char * ) data ) ;
ast_log ( LOG_NOTICE , " Device %s not found \n " , ( char * ) data ) ;
/* XXX we could default to 'dsp' perhaps ? */
return NULL ;
}
@ -1064,7 +1060,7 @@ static struct ast_channel *oss_request(const char *type,
* cause = AST_CAUSE_BUSY ;
return NULL ;
}
c = oss_new ( o , NULL , NULL , AST_STATE_DOWN ) ;
c = oss_new ( o , NULL , NULL , AST_STATE_DOWN ) ;
if ( c = = NULL ) {
ast_log ( LOG_WARNING , " Unable to create new OSS channel \n " ) ;
return NULL ;
@ -1083,8 +1079,7 @@ static int console_autoanswer(int fd, int argc, char *argv[])
if ( argc ! = 2 )
return RESULT_SHOWUSAGE ;
if ( o = = NULL ) {
ast_log ( LOG_WARNING , " Cannot find device %s (should not happen!) \n " ,
oss_active ) ;
ast_log ( LOG_WARNING , " Cannot find device %s (should not happen!) \n " , oss_active ) ;
return RESULT_FAILURE ;
}
if ( ! strcasecmp ( argv [ 1 ] , " on " ) )
@ -1104,10 +1099,9 @@ static char *autoanswer_complete(const char *line, const char *word, int pos, in
}
static char autoanswer_usage [ ] =
" Usage: autoanswer [on|off] \n "
" Enables or disables autoanswer feature. If used without \n "
" argument, displays the current on/off status of autoanswer. \n "
" The default value of autoanswer is in 'oss.conf'. \n " ;
" Usage: autoanswer [on|off] \n "
" Enables or disables autoanswer feature. If used without \n "
" argument, displays the current on/off status of autoanswer. \n " " The default value of autoanswer is in 'oss.conf'. \n " ;
/*
* answer command from the console
@ -1134,9 +1128,7 @@ static int console_answer(int fd, int argc, char *argv[])
return RESULT_SUCCESS ;
}
static char sendtext_usage [ ] =
" Usage: send text <message> \n "
" Sends a text message for display on the remote terminal. \n " ;
static char sendtext_usage [ ] = " Usage: send text <message> \n " " Sends a text message for display on the remote terminal. \n " ;
/*
* concatenate all arguments into a single string . argv is NULL - terminated
@ -1153,7 +1145,7 @@ static int console_sendtext(int fd, int argc, char *argv[])
ast_cli ( fd , " Not in a call \n " ) ;
return RESULT_FAILURE ;
}
ast_join ( buf , sizeof ( buf ) - 1 , argv + 2 ) ;
ast_join ( buf , sizeof ( buf ) - 1 , argv + 2 ) ;
if ( ! ast_strlen_zero ( buf ) ) {
struct ast_frame f = { 0 , } ;
int i = strlen ( buf ) ;
@ -1167,9 +1159,7 @@ static int console_sendtext(int fd, int argc, char *argv[])
return RESULT_SUCCESS ;
}
static char answer_usage [ ] =
" Usage: answer \n "
" Answers an incoming call on the console (OSS) channel. \n " ;
static char answer_usage [ ] = " Usage: answer \n " " Answers an incoming call on the console (OSS) channel. \n " ;
static int console_hangup ( int fd , int argc , char * argv [ ] )
{
@ -1179,7 +1169,7 @@ static int console_hangup(int fd, int argc, char *argv[])
return RESULT_SHOWUSAGE ;
o - > cursound = - 1 ;
o - > nosound = 0 ;
if ( ! o - > owner & & ! o - > hookstate ) { /* XXX maybe only one ? */
if ( ! o - > owner & & ! o - > hookstate ) { /* XXX maybe only one ? */
ast_cli ( fd , " No call to hang up \n " ) ;
return RESULT_FAILURE ;
}
@ -1190,9 +1180,7 @@ static int console_hangup(int fd, int argc, char *argv[])
return RESULT_SUCCESS ;
}
static char hangup_usage [ ] =
" Usage: hangup \n "
" Hangs up any call currently placed on the console. \n " ;
static char hangup_usage [ ] = " Usage: hangup \n " " Hangs up any call currently placed on the console. \n " ;
static int console_flash ( int fd , int argc , char * argv [ ] )
@ -1203,21 +1191,19 @@ static int console_flash(int fd, int argc, char *argv[])
if ( argc ! = 1 )
return RESULT_SHOWUSAGE ;
o - > cursound = - 1 ;
o - > nosound = 0 ; /* when cursound is -1 nosound must be 0 */
if ( ! o - > owner ) { /* XXX maybe !o->hookstate too ? */
o - > nosound = 0 ; /* when cursound is -1 nosound must be 0 */
if ( ! o - > owner ) { /* XXX maybe !o->hookstate too ? */
ast_cli ( fd , " No call to flash \n " ) ;
return RESULT_FAILURE ;
}
o - > hookstate = 0 ;
if ( o - > owner ) /* XXX must be true, right ? */
if ( o - > owner ) /* XXX must be true, right ? */
ast_queue_frame ( o - > owner , & f ) ;
return RESULT_SUCCESS ;
}
static char flash_usage [ ] =
" Usage: flash \n "
" Flashes the call currently placed on the console. \n " ;
static char flash_usage [ ] = " Usage: flash \n " " Flashes the call currently placed on the console. \n " ;
@ -1228,17 +1214,17 @@ static int console_dial(int fd, int argc, char *argv[])
if ( argc ! = 1 & & argc ! = 2 )
return RESULT_SHOWUSAGE ;
if ( o - > owner ) { /* already in a call */
if ( o - > owner ) { /* already in a call */
int i ;
struct ast_frame f = { AST_FRAME_DTMF , 0 } ;
if ( argc = = 1 ) { /* argument is mandatory here */
if ( argc = = 1 ) { /* argument is mandatory here */
ast_cli ( fd , " Already in a call. You can only dial digits until you hangup. \n " ) ;
return RESULT_FAILURE ;
}
s = argv [ 1 ] ;
/* send the string one char at a time */
for ( i = 0 ; i < strlen ( s ) ; i + + ) {
for ( i = 0 ; i < strlen ( s ) ; i + + ) {
f . subclass = s [ i ] ;
ast_queue_frame ( o - > owner , & f ) ;
}
@ -1262,15 +1248,11 @@ static int console_dial(int fd, int argc, char *argv[])
return RESULT_SUCCESS ;
}
static char dial_usage [ ] =
" Usage: dial [extension[@context]] \n "
" Dials a given extension (and context if specified) \n " ;
static char dial_usage [ ] = " Usage: dial [extension[@context]] \n " " Dials a given extension (and context if specified) \n " ;
static char mute_usage [ ] =
" Usage: mute \n Mutes the microphone \n " ;
static char mute_usage [ ] = " Usage: mute \n Mutes the microphone \n " ;
static char unmute_usage [ ] =
" Usage: unmute \n Unmutes the microphone \n " ;
static char unmute_usage [ ] = " Usage: unmute \n Unmutes the microphone \n " ;
static int console_mute ( int fd , int argc , char * argv [ ] )
{
@ -1302,19 +1284,18 @@ static int console_transfer(int fd, int argc, char *argv[])
return RESULT_SHOWUSAGE ;
if ( o = = NULL )
return RESULT_FAILURE ;
if ( o - > owner = = NULL | | ( b = ast_bridged_channel ( o - > owner ) ) = = NULL ) {
if ( o - > owner = = NULL | | ( b = ast_bridged_channel ( o - > owner ) ) = = NULL ) {
ast_cli ( fd , " There is no call to transfer \n " ) ;
return RESULT_SUCCESS ;
}
tmp = ast_ext_ctx ( argv [ 1 ] , & ext , & ctx ) ;
if ( ctx = = NULL ) /* supply default context if needed */
if ( ctx = = NULL ) /* supply default context if needed */
ctx = o - > owner - > context ;
if ( ! ast_exists_extension ( b , ctx , ext , 1 , b - > cid . cid_num ) )
ast_cli ( fd , " No such extension exists \n " ) ;
else {
ast_cli ( fd , " Whee, transferring %s to %s@%s. \n " ,
b - > name , ext , ctx ) ;
ast_cli ( fd , " Whee, transferring %s to %s@%s. \n " , b - > name , ext , ctx ) ;
if ( ast_async_goto ( b , ctx , ext , 1 ) )
ast_cli ( fd , " Failed to transfer :( \n " ) ;
}
@ -1323,16 +1304,11 @@ static int console_transfer(int fd, int argc, char *argv[])
return RESULT_SUCCESS ;
}
static char transfer_usage [ ] =
" Usage: transfer <extension>[@context] \n "
" Transfers the currently connected call to the given extension (and \n "
" context if specified) \n " ;
static char transfer_usage [ ] = " Usage: transfer <extension>[@context] \n " " Transfers the currently connected call to the given extension (and \n " " context if specified) \n " ;
static char console_usage [ ] =
" Usage: console [device] \n "
" If used without a parameter, displays which device is the current \n "
" console. If a device is specified, the console sound device is changed to \n "
" the device specified. \n " ;
" Usage: console [device] \n "
" If used without a parameter, displays which device is the current \n " " console. If a device is specified, the console sound device is changed to \n " " the device specified. \n " ;
static int console_active ( int fd , int argc , char * argv [ ] )
{
@ -1343,8 +1319,8 @@ static int console_active(int fd, int argc, char *argv[])
else {
struct chan_oss_pvt * o ;
if ( strcmp ( argv [ 1 ] , " show " ) = = 0 ) {
for ( o = oss_default . next ; o ; o = o - > next )
ast_cli ( fd , " device [%s] exists \n " , o - > name ) ;
for ( o = oss_default . next ; o ; o = o - > next )
ast_cli ( fd , " device [%s] exists \n " , o - > name ) ;
return RESULT_SUCCESS ;
}
o = find_desc ( argv [ 1 ] ) ;
@ -1366,16 +1342,14 @@ static void store_boost(struct chan_oss_pvt *o, char *s)
ast_log ( LOG_WARNING , " invalid boost <%s> \n " , s ) ;
return ;
}
if ( boost < - BOOST_MAX ) {
ast_log ( LOG_WARNING , " boost %s too small, using %d \n " ,
s , - BOOST_MAX ) ;
if ( boost < - BOOST_MAX ) {
ast_log ( LOG_WARNING , " boost %s too small, using %d \n " , s , - BOOST_MAX ) ;
boost = - BOOST_MAX ;
} else if ( boost > BOOST_MAX ) {
ast_log ( LOG_WARNING , " boost %s too large, using %d \n " ,
s , BOOST_MAX ) ;
ast_log ( LOG_WARNING , " boost %s too large, using %d \n " , s , BOOST_MAX ) ;
boost = BOOST_MAX ;
}
boost = exp ( log ( 10 ) * boost / 20 ) * BOOST_SCALE ;
boost = exp ( log ( 10 ) * boost / 20 ) * BOOST_SCALE ;
o - > boost = boost ;
ast_log ( LOG_WARNING , " setting boost %s to %d \n " , s , o - > boost ) ;
}
@ -1385,25 +1359,24 @@ static int do_boost(int fd, int argc, char *argv[])
struct chan_oss_pvt * o = find_desc ( oss_active ) ;
if ( argc = = 2 )
ast_cli ( fd , " boost currently %5.1f \n " ,
20 * log10 ( ( ( double ) o - > boost / ( double ) BOOST_SCALE ) ) ) ;
ast_cli ( fd , " boost currently %5.1f \n " , 20 * log10 ( ( ( double ) o - > boost / ( double ) BOOST_SCALE ) ) ) ;
else if ( argc = = 3 )
store_boost ( o , argv [ 2 ] ) ;
return RESULT_SUCCESS ;
}
static struct ast_cli_entry myclis [ ] = {
{ { " answer " , NULL } , console_answer , " Answer an incoming console call " , answer_usage } ,
{ { " hangup " , NULL } , console_hangup , " Hangup a call on the console " , hangup_usage } ,
{ { " flash " , NULL } , console_flash , " Flash a call on the console " , flash_usage } ,
{ { " dial " , NULL } , console_dial , " Dial an extension on the console " , dial_usage } ,
{ { " mute " , NULL } , console_mute , " Disable mic input " , mute_usage } ,
{ { " unmute " , NULL } , console_unmute , " Enable mic input " , unmute_usage } ,
{ { " transfer " , NULL } , console_transfer , " Transfer a call to a different extension " , transfer_usage } ,
{ { " send " , " text " , NULL } , console_sendtext , " Send text to the remote device " , sendtext_usage } ,
{ { " autoanswer " , NULL } , console_autoanswer , " Sets/displays autoanswer " , autoanswer_usage , autoanswer_complete } ,
{ { " oss " , " boost " , NULL } , do_boost , " Sets/displays mic boost in dB " } ,
{ { " console " , NULL } , console_active , " Sets/displays active console " , console_usage } ,
{ { " answer " , NULL } , console_answer , " Answer an incoming console call " , answer_usage } ,
{ { " hangup " , NULL } , console_hangup , " Hangup a call on the console " , hangup_usage } ,
{ { " flash " , NULL } , console_flash , " Flash a call on the console " , flash_usage } ,
{ { " dial " , NULL } , console_dial , " Dial an extension on the console " , dial_usage } ,
{ { " mute " , NULL } , console_mute , " Disable mic input " , mute_usage } ,
{ { " unmute " , NULL } , console_unmute , " Enable mic input " , unmute_usage } ,
{ { " transfer " , NULL } , console_transfer , " Transfer a call to a different extension " , transfer_usage } ,
{ { " send " , " text " , NULL } , console_sendtext , " Send text to the remote device " , sendtext_usage } ,
{ { " autoanswer " , NULL } , console_autoanswer , " Sets/displays autoanswer " , autoanswer_usage , autoanswer_complete } ,
{ { " oss " , " boost " , NULL } , do_boost , " Sets/displays mic boost in dB " } ,
{ { " console " , NULL } , console_active , " Sets/displays active console " , console_usage } ,
} ;
/*
@ -1415,10 +1388,9 @@ static void store_mixer(struct chan_oss_pvt *o, char *s)
{
int i ;
for ( i = 0 ; i < strlen ( s ) ; i + + ) {
for ( i = 0 ; i < strlen ( s ) ; i + + ) {
if ( ! isalnum ( s [ i ] ) & & index ( " \t -/ " , s [ i ] ) = = NULL ) {
ast_log ( LOG_WARNING ,
" Suspect char %c in mixer cmd, ignoring: \n \t %s \n " , s [ i ] , s ) ;
ast_log ( LOG_WARNING , " Suspect char %c in mixer cmd, ignoring: \n \t %s \n " , s [ i ] , s ) ;
return ;
}
}
@ -1439,7 +1411,7 @@ static void store_callerid(struct chan_oss_pvt *o, char *s)
/*
* grab fields from the config file , init the descriptor and open the device .
*/
static struct chan_oss_pvt * store_config ( struct ast_config * cfg , char * ctg )
static struct chan_oss_pvt * store_config ( struct ast_config * cfg , char * ctg )
{
struct ast_variable * v ;
struct chan_oss_pvt * o ;
@ -1462,9 +1434,9 @@ static struct chan_oss_pvt * store_config(struct ast_config *cfg, char *ctg)
strcpy ( o - > mohinterpret , " default " ) ;
o - > lastopen = ast_tvnow ( ) ; /* don't leave it 0 or tvdiff may wrap */
o - > lastopen = ast_tvnow ( ) ; /* don't leave it 0 or tvdiff may wrap */
/* fill other fields from configuration */
for ( v = ast_variable_browse ( cfg , ctg ) ; v ; v = v - > next ) {
for ( v = ast_variable_browse ( cfg , ctg ) ; v ; v = v - > next ) {
M_START ( v - > name , v - > value ) ;
/* handle jb conf */
@ -1472,20 +1444,21 @@ static struct chan_oss_pvt * store_config(struct ast_config *cfg, char *ctg)
continue ;
M_BOOL ( " autoanswer " , o - > autoanswer )
M_BOOL ( " autohangup " , o - > autohangup )
M_BOOL ( " overridecontext " , o - > overridecontext )
M_STR ( " device " , o - > device )
M_UINT ( " frags " , o - > frags )
M_UINT ( " debug " , oss_debug )
M_UINT ( " queuesize " , o - > queuesize )
M_STR ( " context " , o - > ctx )
M_STR ( " language " , o - > language )
M_STR ( " mohinterpret " , o - > mohinterpret )
M_STR ( " extension " , o - > ext )
M_F ( " mixer " , store_mixer ( o , v - > value ) )
M_F ( " callerid " , store_callerid ( o , v - > value ) )
M_F ( " boost " , store_boost ( o , v - > value ) )
M_END ( ; ) ;
M_BOOL ( " autohangup " , o - > autohangup )
M_BOOL ( " overridecontext " , o - > overridecontext )
M_STR ( " device " , o - > device )
M_UINT ( " frags " , o - > frags )
M_UINT ( " debug " , oss_debug )
M_UINT ( " queuesize " , o - > queuesize )
M_STR ( " context " , o - > ctx )
M_STR ( " language " , o - > language )
M_STR ( " mohinterpret " , o - > mohinterpret )
M_STR ( " extension " , o - > ext )
M_F ( " mixer " , store_mixer ( o , v - > value ) )
M_F ( " callerid " , store_callerid ( o , v - > value ) )
M_F ( " boost " , store_boost ( o , v - > value ) )
M_END ( ;
) ;
}
if ( ast_strlen_zero ( o - > device ) )
ast_copy_string ( o - > device , DEV_DSP , sizeof ( o - > device ) ) ;
@ -1497,22 +1470,20 @@ static struct chan_oss_pvt * store_config(struct ast_config *cfg, char *ctg)
system ( cmd ) ;
free ( cmd ) ;
}
if ( o = = & oss_default ) /* we are done with the default */
if ( o = = & oss_default ) /* we are done with the default */
return NULL ;
openit :
openit :
# if TRYOPEN
if ( setformat ( o , O_RDWR ) < 0 ) { /* open device */
if ( option_verbose > 0 ) {
ast_verbose ( VERBOSE_PREFIX_2 " Device %s not detected \n " , ctg ) ;
ast_verbose ( VERBOSE_PREFIX_2 " Turn off OSS support by adding "
" 'noload=chan_oss.so' in /etc/asterisk/modules.conf \n " ) ;
ast_verbose ( VERBOSE_PREFIX_2 " Turn off OSS support by adding " " 'noload=chan_oss.so' in /etc/asterisk/modules.conf \n " ) ;
}
goto error ;
}
if ( o - > duplex ! = M_FULL )
ast_log ( LOG_WARNING , " XXX I don't work right with non "
" full-duplex sound cards XXX \n " ) ;
ast_log ( LOG_WARNING , " XXX I don't work right with non " " full-duplex sound cards XXX \n " ) ;
# endif /* TRYOPEN */
if ( pipe ( o - > sndcmd ) ! = 0 ) {
ast_log ( LOG_ERROR , " Unable to create pipe \n " ) ;
@ -1526,7 +1497,7 @@ openit:
}
return o ;
error :
error :
if ( o ! = & oss_default )
free ( o ) ;
return NULL ;
@ -1565,7 +1536,7 @@ static int load_module(void)
/* XXX should cleanup allocated memory etc. */
return - 1 ;
}
ast_cli_register_multiple ( myclis , sizeof ( myclis ) / sizeof ( struct ast_cli_entry ) ) ;
ast_cli_register_multiple ( myclis , sizeof ( myclis ) / sizeof ( struct ast_cli_entry ) ) ;
return 0 ;
}
@ -1575,10 +1546,9 @@ static int unload_module(void)
struct chan_oss_pvt * o ;
ast_channel_unregister ( & oss_tech ) ;
ast_cli_unregister_multiple ( myclis ,
sizeof ( myclis ) / sizeof ( struct ast_cli_entry ) ) ;
ast_cli_unregister_multiple ( myclis , sizeof ( myclis ) / sizeof ( struct ast_cli_entry ) ) ;
for ( o = oss_default . next ; o ; o = o - > next ) {
for ( o = oss_default . next ; o ; o = o - > next ) {
close ( o - > sounddev ) ;
if ( o - > sndcmd [ 0 ] > 0 ) {
close ( o - > sndcmd [ 0 ] ) ;
@ -1586,7 +1556,7 @@ static int unload_module(void)
}
if ( o - > owner )
ast_softhangup ( o - > owner , AST_SOFTHANGUP_APPUNLOAD ) ;
if ( o - > owner ) /* XXX how ??? */
if ( o - > owner ) /* XXX how ??? */
return - 1 ;
/* XXX what about the thread ? */
/* XXX what about the memory allocated ? */