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

📄 chan_alsa.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (err <= 0)		ast_log(LOG_ERROR, "Unable to get a poll descriptors count, error is %s\n", snd_strerror(err));	if (err != 1)		ast_log(LOG_DEBUG, "Can't handle more than one device\n");	snd_pcm_poll_descriptors(handle, &pfd, err);	ast_log(LOG_DEBUG, "Acquired fd %d from the poll descriptor\n", pfd.fd);	if (stream == SND_PCM_STREAM_CAPTURE)		readdev = pfd.fd;	else		writedev = pfd.fd;	return handle;}static int soundcard_init(void){	alsa.icard = alsa_card_init(indevname, SND_PCM_STREAM_CAPTURE);	alsa.ocard = alsa_card_init(outdevname, SND_PCM_STREAM_PLAYBACK);	if (!alsa.icard || !alsa.ocard) {		ast_log(LOG_ERROR, "Problem opening alsa I/O devices\n");		return -1;	}	return readdev;}static int alsa_digit(struct ast_channel *c, char digit, unsigned int duration){	ast_mutex_lock(&alsalock);	ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 		digit, duration);	ast_mutex_unlock(&alsalock);	return 0;}static int alsa_text(struct ast_channel *c, const char *text){	ast_mutex_lock(&alsalock);	ast_verbose(" << Console Received text %s >> \n", text);	ast_mutex_unlock(&alsalock);	return 0;}static void grab_owner(void){	while (alsa.owner && ast_mutex_trylock(&alsa.owner->lock)) {		DEADLOCK_AVOIDANCE(&alsalock);	}}static int alsa_call(struct ast_channel *c, char *dest, int timeout){	int res = 3;	struct ast_frame f = { AST_FRAME_CONTROL };	ast_mutex_lock(&alsalock);	ast_verbose(" << Call placed to '%s' on console >> \n", dest);	if (autoanswer) {		ast_verbose(" << Auto-answered >> \n");		grab_owner();		if (alsa.owner) {			f.subclass = AST_CONTROL_ANSWER;			ast_queue_frame(alsa.owner, &f);			ast_mutex_unlock(&alsa.owner->lock);		}	} else {		ast_verbose(" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");		grab_owner();		if (alsa.owner) {			f.subclass = AST_CONTROL_RINGING;			ast_queue_frame(alsa.owner, &f);			ast_mutex_unlock(&alsa.owner->lock);		}		write(sndcmd[1], &res, sizeof(res));	}	snd_pcm_prepare(alsa.icard);	snd_pcm_start(alsa.icard);	ast_mutex_unlock(&alsalock);	return 0;}static void answer_sound(void){	int res;	nosound = 1;	res = 4;	write(sndcmd[1], &res, sizeof(res));}static int alsa_answer(struct ast_channel *c){	ast_mutex_lock(&alsalock);	ast_verbose(" << Console call has been answered >> \n");	answer_sound();	ast_setstate(c, AST_STATE_UP);	cursound = -1;	snd_pcm_prepare(alsa.icard);	snd_pcm_start(alsa.icard);	ast_mutex_unlock(&alsalock);	return 0;}static int alsa_hangup(struct ast_channel *c){	int res;	ast_mutex_lock(&alsalock);	cursound = -1;	c->tech_pvt = NULL;	alsa.owner = NULL;	ast_verbose(" << Hangup on console >> \n");	ast_module_unref(ast_module_info->self);	if (hookstate) {		hookstate = 0;		if (!autoanswer) {			/* Congestion noise */			res = 2;			write(sndcmd[1], &res, sizeof(res));		}	}	snd_pcm_drop(alsa.icard);	ast_mutex_unlock(&alsalock);	return 0;}static int alsa_write(struct ast_channel *chan, struct ast_frame *f){	static char sizbuf[8000];	static int sizpos = 0;	int len = sizpos;	int pos;	int res = 0;	/* size_t frames = 0; */	snd_pcm_state_t state;	/* Immediately return if no sound is enabled */	if (nosound)		return 0;	ast_mutex_lock(&alsalock);	/* Stop any currently playing sound */	if (cursound != -1) {		snd_pcm_drop(alsa.ocard);		snd_pcm_prepare(alsa.ocard);		cursound = -1;	}	/* We have to digest the frame in 160-byte portions */	if (f->datalen > sizeof(sizbuf) - sizpos) {		ast_log(LOG_WARNING, "Frame too large\n");		res = -1;	} else {		memcpy(sizbuf + sizpos, f->data, f->datalen);		len += f->datalen;		pos = 0;#ifdef ALSA_MONITOR		alsa_monitor_write(sizbuf, len);#endif		state = snd_pcm_state(alsa.ocard);		if (state == SND_PCM_STATE_XRUN)			snd_pcm_prepare(alsa.ocard);		res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2);		if (res == -EPIPE) {#if DEBUG			ast_log(LOG_DEBUG, "XRUN write\n");#endif			snd_pcm_prepare(alsa.ocard);			res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2);			if (res != len / 2) {				ast_log(LOG_ERROR, "Write error: %s\n", snd_strerror(res));				res = -1;			} else if (res < 0) {				ast_log(LOG_ERROR, "Write error %s\n", snd_strerror(res));				res = -1;			}		} else {			if (res == -ESTRPIPE)				ast_log(LOG_ERROR, "You've got some big problems\n");			else if (res < 0)				ast_log(LOG_NOTICE, "Error %d on write\n", res);		}	}	ast_mutex_unlock(&alsalock);	if (res > 0)		res = 0;	return res;}static struct ast_frame *alsa_read(struct ast_channel *chan){	static struct ast_frame f;	static short __buf[FRAME_SIZE + AST_FRIENDLY_OFFSET / 2];	short *buf;	static int readpos = 0;	static int left = FRAME_SIZE;	snd_pcm_state_t state;	int r = 0;	int off = 0;	ast_mutex_lock(&alsalock);	/* Acknowledge any pending cmd */	f.frametype = AST_FRAME_NULL;	f.subclass = 0;	f.samples = 0;	f.datalen = 0;	f.data = NULL;	f.offset = 0;	f.src = "Console";	f.mallocd = 0;	f.delivery.tv_sec = 0;	f.delivery.tv_usec = 0;	state = snd_pcm_state(alsa.icard);	if ((state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING)) {		snd_pcm_prepare(alsa.icard);	}	buf = __buf + AST_FRIENDLY_OFFSET / 2;	r = snd_pcm_readi(alsa.icard, buf + readpos, left);	if (r == -EPIPE) {#if DEBUG		ast_log(LOG_ERROR, "XRUN read\n");#endif		snd_pcm_prepare(alsa.icard);	} else if (r == -ESTRPIPE) {		ast_log(LOG_ERROR, "-ESTRPIPE\n");		snd_pcm_prepare(alsa.icard);	} else if (r < 0) {		ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r));	} else if (r >= 0) {		off -= r;	}	/* Update positions */	readpos += r;	left -= r;	if (readpos >= FRAME_SIZE) {		/* A real frame */		readpos = 0;		left = FRAME_SIZE;		if (chan->_state != AST_STATE_UP) {			/* Don't transmit unless it's up */			ast_mutex_unlock(&alsalock);			return &f;		}		f.frametype = AST_FRAME_VOICE;		f.subclass = AST_FORMAT_SLINEAR;		f.samples = FRAME_SIZE;		f.datalen = FRAME_SIZE * 2;		f.data = buf;		f.offset = AST_FRIENDLY_OFFSET;		f.src = "Console";		f.mallocd = 0;#ifdef ALSA_MONITOR		alsa_monitor_read((char *) buf, FRAME_SIZE * 2);#endif	}	ast_mutex_unlock(&alsalock);	return &f;}static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan){	struct chan_alsa_pvt *p = newchan->tech_pvt;	ast_mutex_lock(&alsalock);	p->owner = newchan;	ast_mutex_unlock(&alsalock);	return 0;}static int alsa_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen){	int res = 0;	ast_mutex_lock(&alsalock);	switch (cond) {	case AST_CONTROL_BUSY:		res = 1;		break;	case AST_CONTROL_CONGESTION:		res = 2;		break;	case AST_CONTROL_RINGING:	case AST_CONTROL_PROGRESS:		break;	case -1:		res = -1;		break;	case AST_CONTROL_VIDUPDATE:		res = -1;		break;	case AST_CONTROL_HOLD:		ast_verbose(" << Console Has Been Placed on Hold >> \n");		ast_moh_start(chan, data, mohinterpret);		break;	case AST_CONTROL_UNHOLD:		ast_verbose(" << Console Has Been Retrieved from Hold >> \n");		ast_moh_stop(chan);		break;	case AST_CONTROL_SRCUPDATE:		break;	default:		ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, chan->name);		res = -1;	}	if (res > -1)		write(sndcmd[1], &res, sizeof(res));	ast_mutex_unlock(&alsalock);	return res;}static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state){	struct ast_channel *tmp = NULL;		if (!(tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, 0, "ALSA/%s", indevname)))		return NULL;	tmp->tech = &alsa_tech;	tmp->fds[0] = readdev;	tmp->nativeformats = AST_FORMAT_SLINEAR;	tmp->readformat = AST_FORMAT_SLINEAR;	tmp->writeformat = AST_FORMAT_SLINEAR;	tmp->tech_pvt = p;	if (!ast_strlen_zero(p->context))		ast_copy_string(tmp->context, p->context, sizeof(tmp->context));	if (!ast_strlen_zero(p->exten))		ast_copy_string(tmp->exten, p->exten, sizeof(tmp->exten));	if (!ast_strlen_zero(language))		ast_string_field_set(tmp, language, language);	p->owner = tmp;	ast_module_ref(ast_module_info->self);	ast_jb_configure(tmp, &global_jbconf);	if (state != AST_STATE_DOWN) {		if (ast_pbx_start(tmp)) {			ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);			ast_hangup(tmp);			tmp = NULL;		}	}	return tmp;}static struct ast_channel *alsa_request(const char *type, int format, void *data, int *cause){	int oldformat = format;	struct ast_channel *tmp = NULL;	format &= AST_FORMAT_SLINEAR;	if (!format) {		ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat);		return NULL;	}	ast_mutex_lock(&alsalock);	if (alsa.owner) {		ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n");		*cause = AST_CAUSE_BUSY;	} else if (!(tmp = alsa_new(&alsa, AST_STATE_DOWN)))		ast_log(LOG_WARNING, "Unable to create new ALSA channel\n");	ast_mutex_unlock(&alsalock);	return tmp;}static int console_autoanswer_deprecated(int fd, int argc, char *argv[]){	int res = RESULT_SUCCESS;	if ((argc != 1) && (argc != 2))		return RESULT_SHOWUSAGE;	ast_mutex_lock(&alsalock);	if (argc == 1) {		ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off");	} else {		if (!strcasecmp(argv[1], "on"))			autoanswer = -1;		else if (!strcasecmp(argv[1], "off"))			autoanswer = 0;		else			res = RESULT_SHOWUSAGE;	}	ast_mutex_unlock(&alsalock);	return res;}static int console_autoanswer(int fd, int argc, char *argv[]){	int res = RESULT_SUCCESS;;	if ((argc != 2) && (argc != 3))		return RESULT_SHOWUSAGE;	ast_mutex_lock(&alsalock);	if (argc == 2) {		ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off");	} else {		if (!strcasecmp(argv[2], "on"))			autoanswer = -1;		else if (!strcasecmp(argv[2], "off"))			autoanswer = 0;		else			res = RESULT_SHOWUSAGE;	}	ast_mutex_unlock(&alsalock);	return res;}static char *autoanswer_complete(const char *line, const char *word, int pos, int state){#ifndef MIN#define MIN(a,b) ((a) < (b) ? (a) : (b))#endif	switch (state) {		case 0:			if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2)))				return ast_strdup("on");		case 1:			if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3)))				return ast_strdup("off");		default:			return NULL;	}	return NULL;}static const char autoanswer_usage[] =	"Usage: console 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 'alsa.conf'.\n";static int console_answer_deprecated(int fd, int argc, char *argv[]){	int res = RESULT_SUCCESS;	if (argc != 1)		return RESULT_SHOWUSAGE;	ast_mutex_lock(&alsalock);	if (!alsa.owner) {		ast_cli(fd, "No one is calling us\n");		res = RESULT_FAILURE;

⌨️ 快捷键说明

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