示例#1
0
static void *fast_originate(void *data)
{
    int res = 0,
	reason;
    struct fast_originate_helper *in = data;
    struct cw_channel *chan = NULL;

    cw_indicate(in->frommember->chan, CW_CONTROL_RINGING);


    if (1) {
		res = cw_pbx_outgoing_app(
			in->tech, CW_FORMAT_SLINEAR, 
			in->data, in->timeout, 
			in->app, in->appdata, 
			&reason, 1, 
			!cw_strlen_zero(in->cid_num) ? in->cid_num : NULL, 
			!cw_strlen_zero(in->cid_name) ? in->cid_name : NULL,
			in->vars, &chan );
    } else {
		res = cw_pbx_outgoing_exten(
			in->tech, CW_FORMAT_SLINEAR, 
			in->data, in->timeout, 
			in->context, in->exten, in->priority, 
			&reason, 1, 
			!cw_strlen_zero(in->cid_num) ? in->cid_num : NULL, 
			!cw_strlen_zero(in->cid_name) ? in->cid_name : NULL,
			in->vars, NULL );
    }   

    cw_log(CW_CONF_DEBUG,"Originate returned %d \n",reason);
    cw_indicate(in->frommember->chan, -1);

    if ( reason == CW_CONTROL_ANSWER ) {
	conference_queue_sound( in->frommember, "beep" );
    } 
    else {
	conference_queue_sound( in->frommember, "beeperr" );
    }

    if (chan)
	cw_mutex_unlock(&chan->lock);
    free(in);
    return NULL;
}
示例#2
0
int conference_parse_admin_command(struct cw_conf_member *member) {
    char action;
    char *parameters;
    int res = 0;

    action=member->dtmf_buffer[0];
    parameters=member->dtmf_buffer+1;

    switch (action) {
	case '1':
	    queue_incoming_silent_frame( member, 2 );
	    res = conf_do_originate(member,parameters);
	    break;
	case '4':
	    if      ( parameters[0] == '0' )
	        add_command_to_queue( member->conf, member, CONF_ACTION_ENABLE_SOUNDS , 0, "" );
	    else if ( parameters[0] == '1' )
	        add_command_to_queue( member->conf, member, CONF_ACTION_ENABLE_SOUNDS , 1, "" );
	    else
		conference_queue_sound( member, "beeperr" );
	    break;
	case '5':
	    if      ( parameters[0] == '0' )
	        add_command_to_queue( member->conf, member, CONF_ACTION_MUTE_ALL , 0, "" );
	    else if ( parameters[0] == '1' )
	        add_command_to_queue( member->conf, member, CONF_ACTION_MUTE_ALL , 1, "" );
	    else
		conference_queue_sound( member, "beeperr" );
	    break;
	case '6':
	    if      ( parameters[0] == '0' )
	        add_command_to_queue( member->conf, member, CONF_ACTION_PLAYMOH , 0, "" );
	    else if ( parameters[0] == '1' )
	        add_command_to_queue( member->conf, member, CONF_ACTION_PLAYMOH , 1, "" );
	    else
		conference_queue_sound( member, "beeperr" );
	    break;
	case '7':
	    if      ( parameters[0] == '0' ) {
		member->conf->is_locked = 0;
		conference_queue_sound( member, "conf-unlockednow" );
	    }
	    else if ( parameters[0] == '1' ) {
		member->conf->is_locked = 1;
		conference_queue_sound( member, "conf-lockednow" );
	    }
	    else {
		conference_queue_sound( member, "beep" );
	    }
	    break;
	case '9':
	    res = conference_set_pin(member,parameters);
	    conference_queue_sound( member, "beep" );
	    break;
	case '0':
	    if      ( parameters[0] == '0' )
	        add_command_to_queue( member->conf, member, CONF_ACTION_HANGUP , 0, "" );
	    else if ( parameters[0] == '1' )
	        add_command_to_queue( member->conf, member, CONF_ACTION_HANGUP , 1, "" );
	    else if ( parameters[0] == '2' )
	        add_command_to_queue( member->conf, member, CONF_ACTION_HANGUP , 2, "" );
	    else
		conference_queue_sound( member, "beeperr" );
	    break;
	default:
	    cw_log(CW_CONF_DEBUG,"Admin mode: Action: %c parameters: %s. Invalid or unknown\n",
		action, parameters);
	    break;
    }

    return 1;
}
示例#3
0
int member_exec( struct cw_channel* chan, int argc, char **argv ) {
    int left = 0 ;
    int res;

    struct cw_conference  *conf   	= NULL;
    struct cw_conf_member *member	= NULL;
    struct cw_frame *f		= NULL;

    cw_log( CW_CONF_DEBUG, "Launching NConference %s\n", "$Revision: 5349 $" ) ;

    if (chan->_state != CW_STATE_UP)
	if ( (res = cw_answer( chan )) )
	{
    	    cw_log( LOG_ERROR, "unable to answer call\n" ) ;
    	    return -1 ;
	}

    member = create_member( chan, argc, argv ) ;

    // unable to create member, return an error
    if ( member == NULL ) 
    {
	cw_log( LOG_ERROR, "unable to create member\n" ) ;
	return -1 ;
    }

    //
    // setup CallWeaver read/write formats
    //
     cw_log(CW_CONF_DEBUG, 
              "CHANNEL INFO, CHANNEL => %s, DNID => %s, CALLER_ID => %s, ANI => %s\n",
              chan->name  ?  chan->name  :  "----",
              chan->cid.cid_dnid  ?  chan->cid.cid_dnid  :  "----",
              chan->cid.cid_num  ?  chan->cid.cid_num  :  "----",
              chan->cid.cid_ani  ?  chan->cid.cid_ani  :  "----");

    cw_log(CW_CONF_DEBUG, 
    	 	 "CHANNEL CODECS, CHANNEL => %s, NATIVE => %d, READ => %d, WRITE => %d\n", 
	    	 chan->name,
             chan->nativeformats,
             member->read_format,
             member->write_format);

    if ( cw_set_read_format( chan, member->read_format ) < 0 )
    {
    	cw_log( LOG_ERROR, "unable to set read format.\n" ) ;
    	delete_member( member ) ;
    	return -1 ;
    } 

    // for right now, we'll send everything as slinear
    if ( cw_set_write_format( chan, member->write_format ) < 0 )
    {
    	cw_log( LOG_ERROR, "unable to set write format.\n" ) ;
    	delete_member( member ) ;
    	return -1 ;
    }

    //
    // setup a conference for the new member
    //

    conf = start_conference( member ) ;
	
    if ( conf == NULL )
    {
	cw_log( LOG_ERROR, "unable to setup member conference\n" ) ;
	delete_member( member) ;
	return -1 ;
    } else {
	if (conf->is_locked && (member->type != MEMBERTYPE_MASTER) ) {
	    if ( strcmp(conf->pin,member->pin) ) {
		conference_queue_sound(member,"conf-locked");
		conf_play_soundqueue( member ); 
		member->force_remove_flag = 1 ;
	    }
	}  else {
	    member->conf = conf;
	    if ( member->type == MEMBERTYPE_MASTER )
		conf->auto_destroy = member->auto_destroy;
	}
    }

    if ( member->type == MEMBERTYPE_MASTER ) {
	conf->auto_destroy = member->auto_destroy;
	if ( strlen( member->pin ) > 0 ) {
	    strncpy(conf->pin,member->pin,sizeof(conf->pin));
	    cw_log( CW_CONF_DEBUG, "Conference pin set to => %s\n", conf->pin ) ;
	}
    }

    //
    // process loop for new member ( this runs in it's own thread
    //
	
    cw_log( CW_CONF_DEBUG, "begin member event loop, channel => %s\n", chan->name ) ;

    // Activate the generator for the channel.
    res = cw_conf_member_genactivate( member );
    if ( !res ) {
	member->force_remove_flag = 1;
	cw_log( CW_CONF_DEBUG, "member marked for removal => %s\n", chan->name ) ;
    }

    //Play the join info messages
    if (!member->force_remove_flag && !member->quiet_mode) {
	conference_queue_sound( member, "conf-youareinconfnum" );
	conference_queue_number( member, member->id );
    }

    // The member at the very beginningis speaking
    member->is_speaking = 1 ;
    // tell conference_exec we're ready for frames
    member->active_flag = 1 ;

    //Main loop.
    while ( !member->force_remove_flag || member->soundq != NULL )
    {
	usleep(1000);

	// make sure we have a channel to process
	if ( chan == NULL )
	{
	    cw_log( LOG_NOTICE, "member channel has closed\n" ) ;
	    break ;
	}

	//-----------------//
	// INCOMING FRAMES //
	//-----------------//

	if ( member->force_remove_flag == 1 ) {
	    // break to the loop
	    break;
	}

	// wait for an event on this channel
	int waittime = ( member->framelen == 0 ) ? CW_CONF_WAITFOR_TIME : member->framelen;

	left = cw_waitfor( chan, waittime ) ;

	f = NULL;

	if ( left < 0 )
	{
	    // an error occured	
	    cw_log( 
		LOG_NOTICE, 
		"an error occured waiting for a frame, channel => %s, error => %d\n", 
		chan->name, left
		) ;
	}
	else if ( left == 0 )
	{
	    // No frame avalaible
	    member->lostframecount ++;

	    // We have lost a frame.
	    // In this case, we queue some silence
	    // Sothat if we keep loosing frames,
	    // there will be no glitching in the conference.
	    // Set the speaking state to 0.
	    if ( member->lostframecount == 1 ) {
		queue_incoming_silent_frame(member,1);
	    }
	    member->is_speaking = 0;
	}
	else if ( left > 0 ) 
	{
	    // a frame has come in before the latency timeout 
	    // was reached, so we process the frame

	    // let's reset the lost frame count
	    if ( member->lostframecount ) {
		member->lostframecount = 0;
		// If vad is not enabled, then set the speaking state back to 1
		if ( !member->enable_vad )
		    member->is_speaking = 1;
	    }
	    
	    f = cw_read( chan ) ;
			
	    if ( f == NULL ) 
	    {
		cw_log( CW_CONF_DEBUG, "unable to read from channel, channel => %s. Got Hangup.\n", chan->name ) ;
		queue_incoming_silent_frame(member,5);
		member->is_speaking = 0;
		break ;
	    } 
	    else {
/*
		cw_log( CW_CONF_DEBUG, 
			"Read (PRE dsp), channel => %s, datalen: %d samplefreq: %ld len: %ld samples %d class: %d\n", 
			chan->name, f->datalen, member->samplefreq, f->len, f->samples, f->subclass) ;
*/
		if ( member->samplefreq == 0 && f->samples != 0 )
		{
		    if ( ( f->len == 0 ) && ( f->datalen == 320 ) && ( f->samples == 160 ) )
			member->framelen = 20;				// This is probably chan_zap not setting the correct len.
		    else
			member->framelen   = f->len;			// frame length in milliseconds
		    member->datalen    = f->datalen;			// frame length in milliseconds
		    member->samples    = f->samples;			// number of samples in framelen
		    member->samplefreq = (int)(member->samples/member->framelen)*1000;	// calculated sample frequency
		    cw_log( CW_CONF_DEBUG, "MEMBER FRAME DATA: datalen %d  samples %d  len(ms) %ld, offset: %d \n", f->datalen, f->samples, f->len, f->offset );

/*
		    // Try to initialize the smoother, only once
		    queue_incoming_silent_frame(member);
		    if ( member->smooth_size_in < 0 ) {
			member->smooth_size_in = f->samples ;
			cw_log( CW_CONF_DEBUG, "Initializing Smooother.\n");
			member->inSmoother = cw_smoother_new(member->smooth_size_in); 
			if ( member->inSmoother == NULL )
			    cw_log( CW_CONF_DEBUG, "Smoother initialization failed\n");
		    }
*/

		} 

		if ( 
			    ( (member->framelen != f->len      ) && ( f->len !=0     ) ) 
				|| 
			    ( (member->samples  != f->samples  ) && ( f->samples !=0 )  && ( f->len !=0     ) )
			) 
		{
		    cw_log( CW_CONF_DEBUG, "FRAME CHANGE  : samples %d  len(ms) %ld\n", f->samples, f->len );
		    cw_log( CW_CONF_DEBUG, "FRAME SHOULDBE: samples %d  len(ms) %ld\n", member->samples, member->framelen );
		    if (member->samples == 0 ) {
			member->framelen   = f->len;				// frame length in milliseconds
			member->datalen    = f->datalen;			// frame length in milliseconds
			member->samples    = f->samples;			// number of samples in framelen
			member->samplefreq = (int) ( f->samples/f->len)*1000;	// calculated sample frequency
		    }
		}
		
		// This fix is for chan_zap
		// Chan_zap NEVER sets framelen value.
		// Probably when adding support to 16Khz we should add a check for this.
		if ( ( member->framelen == 0 ) && ( member->datalen == 320 ) && ( member->samples == 160 ) )
		    member->framelen = 20;
		
	    }
	}

	// actually process the frame.
	res = process_incoming(member, f);

	if (member->force_remove_flag)
	    member->remove_flag = 1 ;

    }

    //
    // clean up
    //

    if ( member != NULL ) 
	member->remove_flag = 1 ;

    cw_log( CW_CONF_DEBUG, "end member event loop, time_entered => %ld -  removal: %d\n", member->time_entered.tv_sec, member->remove_flag ) ;

    //cw_log( CW_CONF_DEBUG, "Deactivating generator - Channel => %s\n", member->chan->name ) ;
    cw_generator_deactivate(chan);

    return -1 ;
		
}
示例#4
0
static void cw_conf_command_execute( struct cw_conference *conf ) {
    struct cw_conf_command_queue 	*cq;
    struct cw_conf_member *member 	= NULL ;

    cq = get_command_from_queue(conf);

    if ( cq == NULL ) return;

    cw_log(CW_CONF_DEBUG,"Parsing Command Queue for conference %s\n",conf->name);

    switch (cq->command) {
	case CONF_ACTION_MUTE_ALL: 
	    // get list of conference members
	    member = conf->memberlist ;
	    // loop over member list to retrieve queued frames
	    while ( member != NULL )
	    {
		if (member != cq->issuedby) {
		    cw_mutex_lock( &member->lock ) ;
		    queue_incoming_silent_frame(member,2);
		    member->talk_mute = cq->param_number;
		    cw_log(CW_CONF_DEBUG,"(CQ) Member Talk MUTE set to %d\n",member->talk_mute);
		    if (cq->param_number)
			conference_queue_sound( member, "conf-muted" );
		    else
			conference_queue_sound( member, "conf-unmuted" );
		    cw_mutex_unlock( &member->lock ) ;
		}
		// adjust our pointer to the next inline
		member = member->next ;
	    } 
	    break;
	case CONF_ACTION_ENABLE_SOUNDS: 
	    // get list of conference members
	    member = conf->memberlist ;
	    // loop over member list to retrieve queued frames
	    while ( member != NULL )
	    {
		cw_mutex_lock( &member->lock ) ;
		queue_incoming_silent_frame(member,2);
		member->dont_play_any_sound =  cq->param_number;
		cw_log(CW_CONF_DEBUG,"(CQ) Member Talk Disable sounds set to %d\n",member->dont_play_any_sound);
		cw_mutex_unlock( &member->lock ) ;
		// adjust our pointer to the next inline
		member = member->next ;
	    } 
	    break;
	case CONF_ACTION_QUEUE_SOUND: 
	    // get list of conference members
	    member = conf->memberlist ;
	    // loop over member list to retrieve queued frames
	    while ( member != NULL )
	    {
		if (member != cq->issuedby) {
		    cw_mutex_lock( &member->lock ) ;
		    queue_incoming_silent_frame(member,2);
		    if ( !(member->quiet_mode == 1 && cq->param_number) )
			conference_queue_sound( member, cq->param_text );
		    cw_mutex_unlock( &member->lock ) ;
		    // adjust our pointer to the next inline
		}
		    member = member->next ;
	    } 
	    break;
	case CONF_ACTION_QUEUE_NUMBER: 
	    // get list of conference members
	    member = conf->memberlist ;
	    // loop over member list to retrieve queued frames
	    while ( member != NULL )
	    {
		if (member != cq->issuedby) {
		    cw_mutex_lock( &member->lock ) ;
		    queue_incoming_silent_frame(member,2);
		    if ( !(member->quiet_mode == 1 && cq->param_number) )
			conference_queue_number( member, cq->param_text );
		    cw_mutex_unlock( &member->lock ) ;
		    // adjust our pointer to the next inline
		}
		member = member->next ;
	    } 
	    break;
	case CONF_ACTION_PLAYMOH: 
	    // get list of conference members
	    member = conf->memberlist ;
	    // loop over member list to retrieve queued frames
	    while ( member != NULL )
	    {
		if (member != cq->issuedby) {;
		    cw_mutex_lock( &member->lock ) ;
		    if ( cq->param_number == 1) {
			member->force_on_hold =  1;
		    } 
		    else {
			member->force_on_hold = -1;
		    }
		    cw_mutex_unlock( &member->lock ) ;
		    cw_log(CW_CONF_DEBUG,"(CQ) Member: playing moh set to %d\n",cq->param_number);
		    // adjust our pointer to the next inline
		}
		member = member->next ;
	    } 
	    break;
	case CONF_ACTION_HANGUP: 
	    member = conf->memberlist ;
	    // Scan all the members
	    while ( member != NULL )
	    {
		// If it's not me and we don't have to kick all members
		if (member != cq->issuedby) {
		    cw_mutex_lock( &member->lock ) ;
		    queue_incoming_silent_frame(member,2);
		    if (cq->param_number == 0) 
			conference_queue_sound( member, "goodbye" );
		    else
			conference_queue_sound( member, "conf-kicked" );
		    member->force_remove_flag = 1;
		    cw_log(CW_CONF_DEBUG,"(CQ) Conf %s Member Kicked: %s\n",conf->name, member->channel_name);
		    cw_mutex_unlock( &member->lock ) ;
		    if (cq->param_number == 1) 
			break;
		}
		// adjust our pointer to the next inline
		member 	= member->next ;
	    } 
	    break;
	default:
	    cw_log( LOG_WARNING, "Conference %s : don't know how to execute command %d\n", conf->name, cq->command) ;	
	    break;
    }

    // Free the struct we got
    free(cq);
}
int member_exec( struct ast_channel* chan, void* data ) {
    int left = 0 ;
    int res;

    struct ast_conference  *conf   	= NULL;
    struct ast_conf_member *member	= NULL;
    struct ast_frame *f		= NULL;
    struct ast_app *app = NULL;

    ast_log( AST_CONF_DEBUG, "Launching NConference %s\n", "$Revision: 2325 $" ) ;

	// make sure we have a channel to process
	if ( chan == NULL )
	{
	    ast_log( LOG_NOTICE, "member channel has closed\n" ) ;
	    return -1 ;
	}

    if (chan->_state != AST_STATE_UP)
	if ( (res = ast_answer( chan )) )
	{
    	    ast_log( LOG_ERROR, "unable to answer call\n" ) ;
    	    return -1 ;
	}

    member = create_member( chan, (const char*)( data ) ) ;

    // unable to create member, return an error
    if ( member == NULL ) 
    {
	ast_log( LOG_ERROR, "unable to create member\n" ) ;
	return -1 ;
    }

    //
    // setup Openpbx read/write formats
    //
	
    //ast_log( AST_CONF_DEBUG, 
	//	"CHANNEL INFO, CHANNEL => %s, DNID => %s, CALLER_ID => %s, ANI => %s\n", 
	//	chan->name, chan->cid.cid_dnid, chan->cid.cid_num, chan->cid.cid_ani ) ;

    ast_log( AST_CONF_DEBUG, 
		"CHANNEL CODECS, CHANNEL => %s, NATIVE => %d, READ => %d, WRITE => %d\n", 
		chan->name, chan->nativeformats, member->read_format, member->write_format ) ;


    if ( ast_set_read_format( chan, member->read_format ) < 0 )
    {
    	ast_log( LOG_ERROR, "unable to set read format.\n" ) ;
    	delete_member( member ) ;
    	return -1 ;
    } 

    // for right now, we'll send everything as slinear
    if ( ast_set_write_format( chan, member->write_format ) < 0 )
    {
    	ast_log( LOG_ERROR, "unable to set write format.\n" ) ;
    	delete_member( member ) ;
    	return -1 ;
    }

    //
    // setup a conference for the new member
    //

    conf = start_conference( member ) ;
	
    if ( conf == NULL )
    {
	ast_log( LOG_ERROR, "unable to setup member conference\n" ) ;
	delete_member( member) ;
	return -1 ;
    } else {
	if (conf->is_locked && (member->type != MEMBERTYPE_MASTER) ) {
	    if (strlen(conf->pin) == 0 || strncmp(conf->pin,member->pin,sizeof(conf->pin)) ) {
		/* Conference is Locked and an invalid PIN was entered */
		remove_member(conf, member);
		return -2 ;
	    }
	}  else {
	    member->conf = conf;
	    if ( member->type == MEMBERTYPE_MASTER )
		conf->auto_destroy = member->auto_destroy;
	}
    }

    if ( member->type == MEMBERTYPE_MASTER ) {
	conf->auto_destroy = member->auto_destroy;
	if ( strlen( member->pin ) > 0 ) {
	    strncpy(conf->pin,member->pin,sizeof(conf->pin));
	    ast_log( AST_CONF_DEBUG, "Conference pin set to => %s\n", conf->pin ) ;
	}
    }

    //
    // process loop for new member ( this runs in it's own thread
    //
	
    ast_log( AST_CONF_DEBUG, "begin member event loop, channel => %s\n", chan->name ) ;

    // Add user to monitor
    if (member->monitor) {
        const char * const monitorfilename = pbx_builtin_getvar_helper(chan, "MONITOR_FILENAME");
        if (monitorfilename) {
            ast_monitor_start(chan, NULL, monitorfilename, 1);
        } else if (chan->cdr) {
            ast_monitor_start(chan, NULL, chan->cdr->uniqueid, 1);
        } else {
            char tmpid[256];
            snprintf(tmpid, sizeof(tmpid), "chan-%x", rand());
            ast_monitor_start(chan, NULL, tmpid, 1);
        }
        if (member->monitor_join) {
            ast_monitor_setjoinfiles(chan, 1);
        }
    }

    // Run AGI script
    if (member->agi) {
        char * agi = pbx_builtin_getvar_helper(chan, "AGI_CONF_JOIN");
        if (agi) {
            app = pbx_findapp("agi");
            if (app) {
                pbx_exec(chan, app, agi, 1);
            }
        } else {
            ast_log(LOG_WARNING, "AGI requested, but AGI_CONF_JOIN missing.\n");
        }
        conf->agi = 1 ;
    }

    // Activate the generator for the channel.
    res = ast_conf_member_genactivate( member );
    if ( !res ) {
	member->force_remove_flag = 1;
	ast_log( AST_CONF_DEBUG, "member marked for removal => %s\n", chan->name ) ;
    }

    //Play the join info messages
    if (!member->force_remove_flag && !member->quiet_mode && !member->mute_incoming_sounds) {
		if (ast_strlen_zero(member->intro_sounds)) {
			conference_queue_sound( member, "conf-youareinconfnum" );
			conference_queue_number( member, member->id );
		}
    }

    // The member at the very beginningis speaking
    member->is_speaking = 1 ;
    // tell conference_exec we're ready for frames
    member->active_flag = 1 ;

    //Main loop.
    while ( !member->force_remove_flag || member->soundq != NULL )
    {
#ifdef SOLARIS
    struct timespec rqtp;
    rqtp.tv_sec = 0;
    rqtp.tv_nsec = 1000000;
    if (nanosleep(&rqtp, (struct timespec *) NULL) == -1) {
        ast_log(LOG_NOTICE, "Nanosleep timer errored.\n");
    }
#else
	usleep(1000);
#endif

	//-----------------//
	// INCOMING FRAMES //
	//-----------------//

	if ( member->force_remove_flag == 1 ) {
	    // break to the loop
	    break;
	}

	// wait for an event on this channel
	int waittime = ( member->framelen == 0 ) ? AST_CONF_WAITFOR_TIME : member->framelen;

	left = ast_waitfor( chan, waittime ) ;

	if ( left < 0 )
	{
	    // an error occured	
	    ast_log( 
		LOG_NOTICE, 
		"an error occured waiting for a frame, channel => %s, error => %d\n", 
		chan->name, left
		) ;
	}
	else if ( left == 0 )
	{
	    // No frame avalaible
	    member->lostframecount ++;

	    // We have lost a frame.
	    // In this case, we queue some silence
	    // Sothat if we keep loosing frames,
	    // there will be no glitching in the conference.
	    // Set the speaking state to 0.
	    if ( member->lostframecount == 1 ) {
		queue_incoming_silent_frame(member,1);
	    }
	    member->is_speaking = 0;
	}
	else if ( left > 0 ) 
	{
	    // a frame has come in before the latency timeout 
	    // was reached, so we process the frame

	    // let's reset the lost frame count
	    if ( member->lostframecount ) {
		member->lostframecount = 0;
		// If vad is not enabled, then set the speaking state back to 1
		if ( !member->enable_vad )
		    member->is_speaking = 1;
	    }
	    
	    f = ast_read( chan ) ;
			
	    if ( f == NULL ) 
	    {
		ast_log( AST_CONF_DEBUG, "unable to read from channel, channel => %s. Got Hangup.\n", chan->name ) ;
		queue_incoming_silent_frame(member,5);
		member->is_speaking = 0;
		break ;
	    } 
	    else {
/*
		ast_log( AST_CONF_DEBUG, 
			"Read (PRE dsp), channel => %s, datalen: %d samplefreq: %ld len: %ld samples %d class: %d\n", 
			chan->name, f->datalen, member->samplefreq, f->len, f->samples, f->subclass) ;
*/

#if 0 == 1
		if ( member->samplefreq == 0 && f->samples != 0 )
		{
		    if ( ( f->len == 0 )  && ( f->datalen == 320 ) && ( f->samples == 160 ) )
			member->framelen = 20;				// This is probably chan_zap not setting the correct len.
		    else
			member->framelen   = f->len;			// frame length in milliseconds
		    member->datalen    = f->datalen;			// frame length in milliseconds
		    member->samples    = f->samples;			// number of samples in framelen
		    member->samplefreq = (int)(member->samples/member->framelen)*1000;	// calculated sample frequency
		    ast_log( AST_CONF_DEBUG, "MEMBER FRAME DATA: datalen %d  samples %d  len(ms) %ld, offset: %d \n", f->datalen, f->samples, f->len, f->offset );
		} 

		if ( 
			    ( (member->framelen != f->len      ) && ( f->len !=0     ) ) 
				|| 
			    ( (member->samples  != f->samples  ) && ( f->samples !=0 )  && ( f->len !=0     ) )
			) 
		{
		    ast_log( AST_CONF_DEBUG, "FRAME CHANGE  : samples %d  len(ms) %ld\n", f->samples, f->len );
		    ast_log( AST_CONF_DEBUG, "FRAME SHOULDBE: samples %d  len(ms) %ld\n", member->samples, member->framelen );
		    if (member->samples == 0 ) {
			member->framelen   = f->len;				// frame length in milliseconds
			member->datalen    = f->datalen;			// frame length in milliseconds
			member->samples    = f->samples;			// number of samples in framelen
			member->samplefreq = (int) ( f->samples/f->len)*1000;	// calculated sample frequency
		    }
		}
#endif
        member->framelen = f->datalen;

		// This fix is for chan_zap
		// Chan_zap NEVER sets framelen value.
		// Probably when adding support to 16Khz we should add a check for this.
		if ( ( member->framelen == 0 ) && ( member->datalen == 320 ) && ( member->samples == 160 ) )
		    member->framelen = 20;
		
	    }
	}

	// actually process the frame.
	res = process_incoming(member, f);

	if (member->force_remove_flag)
	    member->remove_flag = 1 ;

    }

	// Run AGI script
	if (member->agi) {
		char * agi = pbx_builtin_getvar_helper(chan, "AGI_CONF_LEAVE");
		if (agi) {
			app = pbx_findapp("agi");
			if (app) {
				pbx_exec(chan, app, agi, 1);
			}
		} else {
			ast_log(LOG_WARNING, "AGI requested, but AGI_CONF_LEAVE missing.\n");
		}
	}
	if (conf->agi) 
		handle_conf_agi_end(conf->name, member);        
	member->remove_flag = 1 ;

    ast_log( AST_CONF_DEBUG, "end member event loop, time_entered => %ld -  removal: %d\n", member->time_entered.tv_sec, member->remove_flag ) ;

    //ast_log( AST_CONF_DEBUG, "Deactivating generator - Channel => %s\n", member->chan->name ) ;
    ast_generator_deactivate(chan);

	if (member->hangup_go_on) {
		ast_log(AST_CONF_DEBUG, "Hangup go on!\n");
		return 0;
	}

    return -1 ;
		
}