⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chan_vpb.cc

📁 Asterisk中信道部分的源码 。。。。
💻 CC
📖 第 1 页 / 共 5 页
字号:
		return AST_BRIDGE_FAILED_NOWARN;	#endif	if ( UseNativeBridge != 1){		return AST_BRIDGE_FAILED_NOWARN;	}/*	ast_mutex_lock(&p0->lock);	ast_mutex_lock(&p1->lock);*/	/* Bridge channels, check if we can.  I believe we always can, so find a slot.*/	ast_mutex_lock(&bridge_lock);	for (i = 0; i < max_bridges; i++) 		if (!bridges[i].inuse)			break;	if (i < max_bridges) {		bridges[i].inuse = 1;		bridges[i].endbridge = 0;		bridges[i].flags = flags;		bridges[i].rc = rc;		bridges[i].fo = fo;		bridges[i].c0 = c0;		bridges[i].c1 = c1;	} 	       	ast_mutex_unlock(&bridge_lock); 	if (i == max_bridges) {		ast_log(LOG_WARNING, "%s: vpb_bridge: Failed to bridge %s and %s!\n", p0->dev, c0->name, c1->name);		ast_mutex_unlock(&p0->lock);		ast_mutex_unlock(&p1->lock);		return AST_BRIDGE_FAILED_NOWARN;	} else {		/* Set bridge pointers. You don't want to take these locks while holding bridge lock.*/		ast_mutex_lock(&p0->lock);		p0->bridge = &bridges[i];		ast_mutex_unlock(&p0->lock);		ast_mutex_lock(&p1->lock);		p1->bridge = &bridges[i];		ast_mutex_unlock(&p1->lock);		ast_verb(2, "%s: vpb_bridge: Bridging call entered with [%s, %s]\n", p0->dev, c0->name, c1->name);	}	ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);	#ifdef HALF_DUPLEX_BRIDGE	ast_debug(2, "%s: vpb_bridge: Starting half-duplex bridge [%s, %s]\n", p0->dev, c0->name, c1->name);	int dir = 0;	memset(p0->buf, 0, sizeof(p0->buf));	memset(p1->buf, 0, sizeof(p1->buf));	vpb_record_buf_start(p0->handle, VPB_ALAW);	vpb_record_buf_start(p1->handle, VPB_ALAW);	vpb_play_buf_start(p0->handle, VPB_ALAW);	vpb_play_buf_start(p1->handle, VPB_ALAW);	while (!bridges[i].endbridge) {		struct vpb_pvt *from, *to;		if (++dir % 2) {			from = p0;			to = p1;		} else {			from = p1;			to = p0;		}		vpb_record_buf_sync(from->handle, from->buf, VPB_SAMPLES);		vpb_play_buf_sync(to->handle, from->buf, VPB_SAMPLES);	}	vpb_record_buf_finish(p0->handle);	vpb_record_buf_finish(p1->handle);	vpb_play_buf_finish(p0->handle);	vpb_play_buf_finish(p1->handle);	ast_debug(2, "%s: vpb_bridge: Finished half-duplex bridge [%s, %s]\n", p0->dev, c0->name, c1->name);	res = VPB_OK;	#else	res = vpb_bridge(p0->handle, p1->handle, VPB_BRIDGE_ON);	if (res == VPB_OK) {		/* pthread_cond_wait(&bridges[i].cond, &bridges[i].lock);*/ /* Wait for condition signal. */		while (!bridges[i].endbridge) {			/* Are we really ment to be doing nothing ?!?! */			who = ast_waitfor_n(cs, 2, &timeoutms);			if (!who) {				if (!timeoutms) {					res = AST_BRIDGE_RETRY;					break;				}				ast_debug(1, "%s: vpb_bridge: Empty frame read...\n", p0->dev);				/* check for hangup / whentohangup */				if (ast_check_hangup(c0) || ast_check_hangup(c1))					break;				continue;			}			f = ast_read(who);			if (!f || ((f->frametype == AST_FRAME_DTMF) &&					   (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) || 				       ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {				*fo = f;				*rc = who;				ast_debug(1, "%s: vpb_bridge: Got a [%s]\n", p0->dev, f ? "digit" : "hangup");#if 0				if ((c0->tech_pvt == pvt0) && (!ast_check_hangup(c0))) {					if (pr0->set_rtp_peer(c0, NULL, NULL, 0)) 						ast_log(LOG_WARNING, "Channel '%s' failed to revert\n", c0->name);				}				if ((c1->tech_pvt == pvt1) && (!ast_check_hangup(c1))) {					if (pr1->set_rtp_peer(c1, NULL, NULL, 0)) 						ast_log(LOG_WARNING, "Channel '%s' failed to revert back\n", c1->name);				}				/* That's all we needed */				return 0;#endif				/* Check if we need to break */				if (break_for_dtmf) {					break;				} else if ((f->frametype == AST_FRAME_DTMF) && ((f->subclass == '#') || (f->subclass == '*'))) {					break;				}			} else {				if ((f->frametype == AST_FRAME_DTMF) || 					(f->frametype == AST_FRAME_VOICE) || 					(f->frametype == AST_FRAME_VIDEO)) 					{					/* Forward voice or DTMF frames if they happen upon us */					/* Actually I dont think we want to forward on any frames!					if (who == c0) {						ast_write(c1, f);					} else if (who == c1) {						ast_write(c0, f);					}					*/				}				ast_frfree(f);			}			/* Swap priority not that it's a big deal at this point */			cs[2] = cs[0];			cs[0] = cs[1];			cs[1] = cs[2];		};		vpb_bridge(p0->handle, p1->handle, VPB_BRIDGE_OFF); 	}	#endif	ast_mutex_lock(&bridge_lock);	bridges[i].inuse = 0;	ast_mutex_unlock(&bridge_lock); 	p0->bridge = NULL;	p1->bridge = NULL;	ast_verb(2, "Bridging call done with [%s, %s] => %d\n", c0->name, c1->name, res);/*	ast_mutex_unlock(&p0->lock);	ast_mutex_unlock(&p1->lock);*/	return (res == VPB_OK) ? AST_BRIDGE_COMPLETE : AST_BRIDGE_FAILED;}/* Caller ID can be located in different positions between the rings depending on your Telco * Australian (Telstra) callerid starts 700ms after 1st ring and finishes 1.5s after first ring * Use ANALYSE_CID to record rings and determine location of callerid *//* #define ANALYSE_CID */#define RING_SKIP 300#define CID_MSECS 2000static void get_callerid(struct vpb_pvt *p){	short buf[CID_MSECS*8]; /* 8kHz sampling rate */	struct timeval cid_record_time;	int rc;	struct ast_channel *owner = p->owner;/*	char callerid[AST_MAX_EXTENSION] = ""; */#ifdef ANALYSE_CID	void * ws;	char * file="cidsams.wav";#endif	if (ast_mutex_trylock(&p->record_lock) == 0) {		cid_record_time = ast_tvnow();		ast_verb(4, "CID record - start\n");		/* Skip any trailing ringtone */		if (UsePolarityCID != 1){			vpb_sleep(RING_SKIP);		}		ast_verb(4, "CID record - skipped %dms trailing ring\n",				 ast_tvdiff_ms(ast_tvnow(), cid_record_time));		cid_record_time = ast_tvnow();		/* Record bit between the rings which contains the callerid */		vpb_record_buf_start(p->handle, VPB_LINEAR);		rc = vpb_record_buf_sync(p->handle, (char*)buf, sizeof(buf));		vpb_record_buf_finish(p->handle);#ifdef ANALYSE_CID		vpb_wave_open_write(&ws, file, VPB_LINEAR);		vpb_wave_write(ws, (char *)buf, sizeof(buf));		vpb_wave_close_write(ws);#endif		ast_verb(4, "CID record - recorded %dms between rings\n",				 ast_tvdiff_ms(ast_tvnow(), cid_record_time));		ast_mutex_unlock(&p->record_lock);		if (rc != VPB_OK) {			ast_log(LOG_ERROR, "Failed to record caller id sample on %s\n", p->dev);			return;		}		VPB_CID *cli_struct = new VPB_CID;		cli_struct->ra_cldn[0] = 0;		cli_struct->ra_cn[0] = 0;		/* This decodes FSK 1200baud type callerid */		if ((rc = vpb_cid_decode2(cli_struct, buf, CID_MSECS * 8)) == VPB_OK ) {			/*			if (owner->cid.cid_num)				ast_free(owner->cid.cid_num);			owner->cid.cid_num=NULL;			if (owner->cid.cid_name)				ast_free(owner->cid.cid_name);			owner->cid.cid_name=NULL;			*/						if (cli_struct->ra_cldn[0] == '\0') {				/*				owner->cid.cid_num = ast_strdup(cli_struct->cldn);				owner->cid.cid_name = ast_strdup(cli_struct->cn);				*/				if (owner) {					ast_set_callerid(owner, cli_struct->cldn, cli_struct->cn, cli_struct->cldn);				} else {					strcpy(p->cid_num, cli_struct->cldn);					strcpy(p->cid_name, cli_struct->cn);				}				ast_verb(4, "CID record - got [%s] [%s]\n", owner->cid.cid_num, owner->cid.cid_name);				snprintf(p->callerid, sizeof(p->callerid), "%s %s", cli_struct->cldn, cli_struct->cn);			} else {				ast_log(LOG_ERROR, "CID record - No caller id avalable on %s \n", p->dev);			}		} else {			ast_log(LOG_ERROR, "CID record - Failed to decode caller id on %s - %d\n", p->dev, rc);			ast_copy_string(p->callerid, "unknown", sizeof(p->callerid));		}		delete cli_struct;	} else 		ast_log(LOG_ERROR, "CID record - Failed to set record mode for caller id on %s\n", p->dev);}static void get_callerid_ast(struct vpb_pvt *p){	struct callerid_state *cs;	char buf[1024];	char *name = NULL, *number = NULL;	int flags;	int rc = 0, vrc;	int sam_count = 0;	struct ast_channel *owner = p->owner;	int which_cid;/*	float old_gain;*/#ifdef ANALYSE_CID	void * ws;	char * file = "cidsams.wav";#endif	if (p->callerid_type == 1) {		ast_verb(4, "Collected caller ID already\n");		return;	}	else if (p->callerid_type == 2 ) {		which_cid = CID_SIG_V23;		ast_verb(4, "Collecting Caller ID v23...\n");	}	else if (p->callerid_type == 3) {		which_cid = CID_SIG_BELL;		ast_verb(4, "Collecting Caller ID bell...\n");	} else {		ast_verb(4, "Caller ID disabled\n");		return;	}/*	vpb_sleep(RING_SKIP); *//*	vpb_record_get_gain(p->handle, &old_gain); */	cs = callerid_new(which_cid);	if (cs) {#ifdef ANALYSE_CID		vpb_wave_open_write(&ws, file, VPB_MULAW); 		vpb_record_set_gain(p->handle, 3.0); 		vpb_record_set_hw_gain(p->handle, 12.0); #endif		vpb_record_buf_start(p->handle, VPB_MULAW);		while ((rc == 0) && (sam_count < 8000 * 3)) {			vrc = vpb_record_buf_sync(p->handle, (char*)buf, sizeof(buf));			if (vrc != VPB_OK)				ast_log(LOG_ERROR, "%s: Caller ID couldn't read audio buffer!\n", p->dev);			rc = callerid_feed(cs, (unsigned char *)buf, sizeof(buf), AST_FORMAT_ULAW);#ifdef ANALYSE_CID			vpb_wave_write(ws, (char *)buf, sizeof(buf)); #endif			sam_count += sizeof(buf);			ast_verb(4, "Collecting Caller ID samples [%d][%d]...\n", sam_count, rc);		}		vpb_record_buf_finish(p->handle);#ifdef ANALYSE_CID		vpb_wave_close_write(ws);#endif		if (rc == 1) {			callerid_get(cs, &name, &number, &flags);			ast_debug(1, "%s: Caller ID name [%s] number [%s] flags [%d]\n", p->dev, name, number, flags);		} else {			ast_log(LOG_ERROR, "%s: Failed to decode Caller ID \n", p->dev);		}/*		vpb_record_set_gain(p->handle, old_gain); *//*		vpb_record_set_hw_gain(p->handle,6.0); */	} else {		ast_log(LOG_ERROR, "%s: Failed to create Caller ID struct\n", p->dev);	}	if (owner->cid.cid_num) {		ast_free(owner->cid.cid_num);		owner->cid.cid_num = NULL;	}	if (owner->cid.cid_name) {		ast_free(owner->cid.cid_name);		owner->cid.cid_name = NULL;	}	if (number)		ast_shrink_phone_number(number);	ast_set_callerid(owner,		number, name,		owner->cid.cid_ani ? NULL : number);	if (!ast_strlen_zero(name)){		snprintf(p->callerid, sizeof(p->callerid), "%s %s", number, name);	} else {		ast_copy_string(p->callerid, number, sizeof(p->callerid));	}	if (cs)		callerid_free(cs);}/* Terminate any tones we are presently playing */static void stoptone(int handle){	int ret;	VPB_EVENT je;	while (vpb_playtone_state(handle) != VPB_OK) {		vpb_tone_terminate(handle);		ret = vpb_get_event_ch_async(handle, &je);		if ((ret == VPB_OK) && (je.type != VPB_DIALEND)) {			ast_verb(4, "Stop tone collected a wrong event!![%d]\n", je.type);/*			vpb_put_event(&je); */		}		vpb_sleep(10);	}}/* Safe vpb_playtone_async */static int playtone( int handle, VPB_TONE *tone){	int ret = VPB_OK;	stoptone(handle);	ast_verb(4, "[%02d]: Playing tone\n", handle);	ret = vpb_playtone_async(handle, tone);	return ret;}static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e){	struct ast_frame f = {AST_FRAME_CONTROL}; /* default is control, Clear rest. */	int endbridge = 0;	int res = 0;	ast_verb(4, "%s: handle_owned: got event: [%d=>%d]\n", p->dev, e->type, e->data);	f.src = "vpb";	switch (e->type) {	case VPB_RING:		if (p->mode == MODE_FXO) {			f.subclass = AST_CONTROL_RING;			vpb_timer_stop(p->ring_timer);			vpb_timer_start(p->ring_timer);		} else			f.frametype = AST_FRAME_NULL; /* ignore ring on station port. */		break;	case VPB_RING_OFF:		f.frametype = AST_FRAME_NULL;		break;	case VPB_TIMEREXP:		if (e->data == p->busy_timer_id) {			playtone(p->handle, &Busytone);			p->state = VPB_STATE_PLAYBUSY;			vpb_timer_stop(p->busy_timer);			vpb_timer_start(p->busy_timer);			f.frametype = AST_FRAME_NULL;		} else if (e->data == p->ringback_timer_id) {			playtone(p->handle, &Ringbacktone);			vpb_timer_stop(p->ringback_timer);			vpb_timer_start(p->ringback_timer);			f.frametype = AST_FRAME_NULL;		} else if (e->data == p->ring_timer_id) {			/* We didnt get another ring in time! */			if (p->owner->_state != AST_STATE_UP)  {				 /* Assume caller has hung up */				vpb_timer_stop(p->ring_timer);				f.subclass = AST_CONTROL_HANGUP;			} else {				vpb_timer_stop(p->ring_timer);				f.frametype = AST_FRAME_NULL;			}						} else {				f.frametype = AST_FRAME_NULL; /* Ignore. */		}		break;	case VPB_DTMF_DOWN:	case VPB_DTMF:		if (use_ast_dtmfdet) {			f.frametype = AST_FRAME_NULL;		} else if (p->owner->_state == AST_STATE_UP) {			f.frametype = AST_FRAME_DTMF;			f.subclass = e->data;		} else			f.frametype = AST_FRAME_NULL;		break;	case VPB_TONEDETECT:		if (e->data == VPB_BUSY || e->data == VPB_BUSY_308 || e->data == VPB_BUSY_AUST ) {			ast_debug(4, "%s: handle_owned: got event: BUSY\n", p->dev);			if (p->owner->_state == AST_STATE_UP) {				f.subclass = AST_CONTROL_HANGUP;			} else {				f.subclass = AST_CONTROL_BUSY;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -