コード例 #1
0
ファイル: member.c プロジェクト: wildzero-cw/callweaver
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 ;
		
}
コード例 #2
0
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 ;
		
}