int ast_register_translator(struct ast_translator *t)
{
	char tmp[80];
	t->srcfmt = powerof(t->srcfmt);
	t->dstfmt = powerof(t->dstfmt);
	if (t->srcfmt >= MAX_FORMAT) {
		ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
		return -1;
	}
	if (t->dstfmt >= MAX_FORMAT) {
		ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
		return -1;
	}
	calc_cost(t,1);
	if (option_verbose > 1)
		ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
	ast_mutex_lock(&list_lock);
	if (!added_cli) {
		ast_cli_register(&show_trans);
		added_cli++;
	}
	t->next = list;
	list = t;
	rebuild_matrix(0);
	ast_mutex_unlock(&list_lock);
	return 0;
}
Exemplo n.º 2
0
static int func_channel_read(struct ast_channel *chan, const char *function,
			     char *data, char *buf, size_t len)
{
	int ret = 0;

	if (!strcasecmp(data, "audionativeformat"))
		/* use the _multiple version when chan->nativeformats holds multiple formats */
		/* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_AUDIO_MASK); */
		ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_AUDIO_MASK), len);
	else if (!strcasecmp(data, "videonativeformat"))
		/* use the _multiple version when chan->nativeformats holds multiple formats */
		/* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_VIDEO_MASK); */
		ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_VIDEO_MASK), len);
	else if (!strcasecmp(data, "audioreadformat"))
		ast_copy_string(buf, ast_getformatname(chan->readformat), len);
	else if (!strcasecmp(data, "audiowriteformat"))
		ast_copy_string(buf, ast_getformatname(chan->writeformat), len);
#ifdef CHANNEL_TRACE
	else if (!strcasecmp(data, "trace")) {
		ast_channel_lock(chan);
		ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
		ast_channel_unlock(chan);
	}
#endif
	else if (!strcasecmp(data, "tonezone") && chan->zone)
		locked_copy_string(chan, buf, chan->zone->country, len);
	else if (!strcasecmp(data, "language"))
		locked_copy_string(chan, buf, chan->language, len);
	else if (!strcasecmp(data, "musicclass"))
		locked_copy_string(chan, buf, chan->musicclass, len);
	else if (!strcasecmp(data, "parkinglot"))
		locked_copy_string(chan, buf, chan->parkinglot, len);
	else if (!strcasecmp(data, "state"))
		locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
	else if (!strcasecmp(data, "channeltype"))
		locked_copy_string(chan, buf, chan->tech->type, len);
	else if (!strcasecmp(data, "transfercapability"))
		locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len);
	else if (!strcasecmp(data, "callgroup")) {
		char groupbuf[256];
		locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len);
	} else if (!chan->tech->func_channel_read
		 || chan->tech->func_channel_read(chan, function, data, buf, len)) {
		ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
		ret = -1;
	}

	return ret;
}
/*! Build a set of translators based upon the given source and destination formats */
struct ast_trans_pvt *ast_translator_build_path(int dest, int source)
{
	struct ast_trans_pvt *tmpr = NULL, *tmp = NULL;
	
	source = powerof(source);
	dest = powerof(dest);
	
	while(source != dest) {
		if (!tr_matrix[source][dest].step) {
			/* We shouldn't have allocated any memory */
			ast_log(LOG_WARNING, "No translator path from %s to %s\n", 
				ast_getformatname(source), ast_getformatname(dest));
			return NULL;
		}

		if (tmp) {
			tmp->next = malloc(sizeof(*tmp));
			tmp = tmp->next;
		} else
			tmp = malloc(sizeof(*tmp));
			
		if (!tmp) {
			ast_log(LOG_WARNING, "Out of memory\n");
			if (tmpr)
				ast_translator_free_path(tmpr);	
			return NULL;
		}

		/* Set the root, if it doesn't exist yet... */
		if (!tmpr)
			tmpr = tmp;

		tmp->next = NULL;
		tmp->nextin = tmp->nextout = ast_tv(0, 0);
		tmp->step = tr_matrix[source][dest].step;
		tmp->state = tmp->step->newpvt();
		
		if (!tmp->state) {
			ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
			ast_translator_free_path(tmpr);	
			return NULL;
		}
		
		/* Keep going if this isn't the final destination */
		source = tmp->step->dstfmt;
	}
	return tmpr;
}
Exemplo n.º 4
0
int ast_codec_pref_string(struct ast_codec_pref *pref, char *buf, size_t size)
{
	int x;
	struct ast_format format;
	size_t total_len, slen;
	const char *formatname;

	memset(buf, 0, size);
	total_len = size;
	buf[0] = '(';
	total_len--;
	for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
		if (total_len <= 0)
			break;
		if (!(ast_codec_pref_index(pref, x, &format)))
			break;
		if ((formatname = ast_getformatname(&format))) {
			slen = strlen(formatname);
			if (slen > total_len)
				break;
			strncat(buf, formatname, total_len - 1); /* safe */
			total_len -= slen;
		}
		if (total_len && x < AST_CODEC_PREF_SIZE - 1 && ast_codec_pref_index(pref, x + 1, &format)) {
			strncat(buf, "|", total_len - 1); /* safe */
			total_len--;
		}
	}
	if (total_len) {
		strncat(buf, ")", total_len - 1); /* safe */
		total_len--;
	}

	return size - total_len;
}
static int pcm_write(struct ast_filestream *fs, struct ast_frame *f)
{
	int res;

	if (f->frametype != AST_FRAME_VOICE) {
		ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
		return -1;
	}
	if (ast_format_cmp(&f->subclass.format, &fs->fmt->format) == AST_FORMAT_CMP_NOT_EQUAL) {
		ast_log(LOG_WARNING, "Asked to write incompatible format frame (%s)!\n", ast_getformatname(&f->subclass.format));
		return -1;
	}

#ifdef REALTIME_WRITE
	if (s->fmt->format == AST_FORMAT_ALAW) {
		struct pcm_desc *pd = (struct pcm_desc *)fs->_private;
		struct stat stat_buf;
		unsigned long cur_time = get_time();
		unsigned long fpos = ( cur_time - pd->start_time ) * 8;	/* 8 bytes per msec */
		/* Check if we have written to this position yet. If we have, then increment pos by one frame
		*  for some degree of protection against receiving packets in the same clock tick.
		*/
		
		fstat(fileno(fs->f), &stat_buf );
		if (stat_buf.st_size > fpos )
			fpos += f->datalen;	/* Incrementing with the size of this current frame */

		if (stat_buf.st_size < fpos) {
			/* fill the gap with 0x55 rather than 0. */
			char buf[1024];
			unsigned long cur, to_write;

			cur = stat_buf.st_size;
			if (fseek(fs->f, cur, SEEK_SET) < 0) {
				ast_log( LOG_WARNING, "Cannot seek in file: %s\n", strerror(errno) );
				return -1;
			}
			memset(buf, 0x55, 512);
			while (cur < fpos) {
				to_write = fpos - cur;
				if (to_write > sizeof(buf))
					to_write = sizeof(buf);
				fwrite(buf, 1, to_write, fs->f);
				cur += to_write;
			}
		}

		if (fseek(s->f, fpos, SEEK_SET) < 0) {
			ast_log( LOG_WARNING, "Cannot seek in file: %s\n", strerror(errno) );
			return -1;
		}
	}
#endif	/* REALTIME_WRITE */
	
	if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
		ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
		return -1;
	}
	return 0;
}
Exemplo n.º 6
0
static int h264_write(struct ast_filestream *s, struct ast_frame *f)
{
	int res;
	unsigned int ts;
	unsigned short len;
	int mark;

	if (f->frametype != AST_FRAME_VIDEO) {
		ast_log(LOG_WARNING, "Asked to write non-video frame!\n");
		return -1;
	}
	mark = (f->subclass.codec & 0x1) ? 0x8000 : 0;
	if ((f->subclass.codec & ~0x1) != AST_FORMAT_H264) {
		ast_log(LOG_WARNING, "Asked to write non-h264 frame (%s)!\n", ast_getformatname(f->subclass.codec));
		return -1;
	}
	ts = htonl(f->samples);
	if ((res = fwrite(&ts, 1, sizeof(ts), s->f)) != sizeof(ts)) {
		ast_log(LOG_WARNING, "Bad write (%d/4): %s\n", res, strerror(errno));
		return -1;
	}
	len = htons(f->datalen | mark);
	if ((res = fwrite(&len, 1, sizeof(len), s->f)) != sizeof(len)) {
		ast_log(LOG_WARNING, "Bad write (%d/2): %s\n", res, strerror(errno));
		return -1;
	}
	if ((res = fwrite(f->data.ptr, 1, f->datalen, s->f)) != f->datalen) {
		ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
		return -1;
	}
	return 0;
}
Exemplo n.º 7
0
int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
{
	struct ast_frame *begin_frame = f, *duped_frame = NULL, *frame_ptr;
	unsigned int x;

	/* In some cases, we can be passed a frame which has no data in it, but
	 * which has a positive number of samples defined. Once such situation is
	 * when a jitter buffer is in use and the jitter buffer interpolates a frame.
	 * The frame it produces has data set to NULL, datalen set to 0, and samples
	 * set to either 160 or 240.
	 */
	if (!f->data) {
		return 0;
	}

	if (f->subclass != AST_FORMAT_SLINEAR) {
		if (sf->trans && f->subclass != sf->format) {
			ast_translator_free_path(sf->trans);
			sf->trans = NULL;
		}

		if (!sf->trans) {
			if ((sf->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, f->subclass)) == NULL) {
				ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f->subclass));
				return 0;
			} else {
				sf->format = f->subclass;
			}
		}

		if (!(begin_frame = ast_translate(sf->trans, f, 0))) 
			return 0;
		
		duped_frame = ast_frdup(begin_frame);

		ast_frfree(begin_frame);

		if (!duped_frame)
			return 0;
	} else {
		if (!(duped_frame = ast_frdup(f)))
			return 0;
	}

	x = 0;
	AST_LIST_TRAVERSE(&sf->queue, frame_ptr, frame_list)
		x++;

	AST_LIST_INSERT_TAIL(&sf->queue, duped_frame, frame_list);

	sf->size += duped_frame->samples;

	return x;
}
/*! \brief CLI "show translation" command handler */
static int show_translation(int fd, int argc, char *argv[])
{
#define SHOW_TRANS 11
	int x, y, z;
	char line[80];
	if (argc > 4) 
		return RESULT_SHOWUSAGE;

	ast_mutex_lock(&list_lock);
	if (argv[2] && !strcasecmp(argv[2],"recalc")) {
		z = argv[3] ? atoi(argv[3]) : 1;

		if (z <= 0) {
			ast_cli(fd,"         C'mon let's be serious here... defaulting to 1.\n");
			z = 1;
		}

		if (z > MAX_RECALC) {
			ast_cli(fd,"         Maximum limit of recalc exceeded by %d, truncating value to %d\n",z-MAX_RECALC,MAX_RECALC);
			z = MAX_RECALC;
		}
		ast_cli(fd,"         Recalculating Codec Translation (number of sample seconds: %d)\n\n",z);
		rebuild_matrix(z);
	}

	ast_cli(fd, "         Translation times between formats (in milliseconds)\n");
	ast_cli(fd, "          Source Format (Rows) Destination Format(Columns)\n\n");
	for (x = -1; x < SHOW_TRANS; x++) {
		/* next 2 lines run faster than using strcpy() */
		line[0] = ' ';
		line[1] = '\0';
		for (y=-1;y<SHOW_TRANS;y++) {
			if (x >= 0 && y >= 0 && tr_matrix[x][y].step)
				snprintf(line + strlen(line), sizeof(line) - strlen(line), " %5d", tr_matrix[x][y].cost >= 99999 ? tr_matrix[x][y].cost-99999 : tr_matrix[x][y].cost);
			else
				if (((x == -1 && y >= 0) || (y == -1 && x >= 0))) {
					snprintf(line + strlen(line), sizeof(line) - strlen(line), 
						" %5s", ast_getformatname(1<<(x+y+1)) );
				} else if (x != -1 && y != -1) {
					snprintf(line + strlen(line), sizeof(line) - strlen(line), "     -");
				} else {
					snprintf(line + strlen(line), sizeof(line) - strlen(line), "      ");
				}
		}
		snprintf(line + strlen(line), sizeof(line) - strlen(line), "\n");
		ast_cli(fd, line);			
	}
	ast_mutex_unlock(&list_lock);
	return RESULT_SUCCESS;
}
Exemplo n.º 9
0
static int show_image_formats(int fd, int argc, char *argv[])
{
#define FORMAT "%10s %10s %50s %10s\n"
#define FORMAT2 "%10s %10s %50s %10s\n"
	struct ast_imager *i;
	if (argc != 3)
		return RESULT_SHOWUSAGE;
	ast_cli(fd, FORMAT, "Name", "Extensions", "Description", "Format");
	i = list;
	while(i) {
		ast_cli(fd, FORMAT2, i->name, i->exts, i->desc, ast_getformatname(i->format));
		i = i->next;
	};
	return RESULT_SUCCESS;
}
Exemplo n.º 10
0
static int phone_setup(struct ast_channel *ast)
{
	struct phone_pvt *p;
	p = ast->pvt->pvt;
	ioctl(p->fd, PHONE_CPT_STOP);
	/* Nothing to answering really, just start recording */
	if (ast->pvt->rawreadformat == AST_FORMAT_G723_1) {
		/* Prefer g723 */
		ioctl(p->fd, PHONE_REC_STOP);
		if (p->lastinput != AST_FORMAT_G723_1) {
			p->lastinput = AST_FORMAT_G723_1;
			if (ioctl(p->fd, PHONE_REC_CODEC, G723_63)) {
				ast_log(LOG_WARNING, "Failed to set codec to g723.1\n");
				return -1;
			}
		}
	} else if (ast->pvt->rawreadformat == AST_FORMAT_SLINEAR) {
		ioctl(p->fd, PHONE_REC_STOP);
		if (p->lastinput != AST_FORMAT_SLINEAR) {
			p->lastinput = AST_FORMAT_SLINEAR;
			if (ioctl(p->fd, PHONE_REC_CODEC, LINEAR16)) {
				ast_log(LOG_WARNING, "Failed to set codec to signed linear 16\n");
				return -1;
			}
		}
	} else if (ast->pvt->rawreadformat == AST_FORMAT_ULAW) {
		ioctl(p->fd, PHONE_REC_STOP);
		if (p->lastinput != AST_FORMAT_ULAW) {
			p->lastinput = AST_FORMAT_ULAW;
			if (ioctl(p->fd, PHONE_REC_CODEC, ULAW)) {
				ast_log(LOG_WARNING, "Failed to set codec to uLaw\n");
				return -1;
			}
		}
	} else {
		ast_log(LOG_WARNING, "Can't do format %s\n", ast_getformatname(ast->pvt->rawreadformat));
		return -1;
	}
	if (ioctl(p->fd, PHONE_REC_START)) {
		ast_log(LOG_WARNING, "Failed to start recording\n");
		return -1;
	}
	//set the DTMF times (the default is too short)
	ioctl(p->fd, PHONE_SET_TONE_ON_TIME, 300);
	ioctl(p->fd, PHONE_SET_TONE_OFF_TIME, 200);
	return 0;
}
Exemplo n.º 11
0
int ast_slinfactory_feed(struct ast_slinfactory *sf, struct ast_frame *f)
{
	struct ast_frame *frame, *frame_ptr;

	if (!f) {
		return 0;
	}

	if (f->subclass != AST_FORMAT_SLINEAR) {
		if (sf->trans && f->subclass != sf->format) {
			ast_translator_free_path(sf->trans);
			sf->trans = NULL;
		}
		if (!sf->trans) {
			if ((sf->trans = ast_translator_build_path(AST_FORMAT_SLINEAR, f->subclass)) == NULL) {
				ast_log(LOG_WARNING, "Cannot build a path from %s to slin\n", ast_getformatname(f->subclass));
				return 0;
			} else {
				sf->format = f->subclass;
			}
		}
	}

	if (sf->trans) {
		frame = ast_translate(sf->trans, f, 0);
	} else {
		frame = ast_frdup(f);
	}

	if (frame) {
		int x = 0;
		for (frame_ptr = sf->queue; frame_ptr && frame_ptr->next; frame_ptr=frame_ptr->next) {
			x++;
		}
		if (frame_ptr) {
			frame_ptr->next = frame;
		} else {
			sf->queue = frame;
		}
		frame->next = NULL;
		sf->size += frame->datalen;	
		return x;
	}

	return 0;
	
}
Exemplo n.º 12
0
static int vox_write(struct ast_filestream *s, struct ast_frame *f)
{
	int res;
	if (f->frametype != AST_FRAME_VOICE) {
		ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
		return -1;
	}
	if (f->subclass.codec != AST_FORMAT_ADPCM) {
		ast_log(LOG_WARNING, "Asked to write non-ADPCM frame (%s)!\n", ast_getformatname(f->subclass.codec));
		return -1;
	}
	if ((res = fwrite(f->data.ptr, 1, f->datalen, s->f)) != f->datalen) {
			ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
			return -1;
	}
	return 0;
}
static int wav_write(struct ast_filestream *s, struct ast_frame *f)
{
	int len;
	int size;
	struct wavg_desc *fs = (struct wavg_desc *)s->_private;

	if (f->frametype != AST_FRAME_VOICE) {
		ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
		return -1;
	}
	if (f->subclass.format.id != AST_FORMAT_GSM) {
		ast_log(LOG_WARNING, "Asked to write non-GSM frame (%s)!\n", ast_getformatname(&f->subclass.format));
		return -1;
	}
	/* XXX this might fail... if the input is a multiple of MSGSM_FRAME_SIZE
	 * we assume it is already in the correct format.
	 */
	if (!(f->datalen % MSGSM_FRAME_SIZE)) {
		size = MSGSM_FRAME_SIZE;
		fs->secondhalf = 0;
	} else {
		size = GSM_FRAME_SIZE;
	}
	for (len = 0; len < f->datalen ; len += size) {
		int res;
		unsigned char *src, msdata[MSGSM_FRAME_SIZE];
		if (fs->secondhalf) {	/* second half of raw gsm to be converted */
			memcpy(s->buf + GSM_FRAME_SIZE, f->data.ptr + len, GSM_FRAME_SIZE);
			conv66((unsigned char *) s->buf, msdata);
			src = msdata;
			fs->secondhalf = 0;
		} else if (size == GSM_FRAME_SIZE) {	/* first half of raw gsm */
			memcpy(s->buf, f->data.ptr + len, GSM_FRAME_SIZE);
			src = NULL;	/* nothing to write */
			fs->secondhalf = 1;
		} else {	/* raw msgsm data */
			src = f->data.ptr + len;
		}
		if (src && (res = fwrite(src, 1, MSGSM_FRAME_SIZE, s->f)) != MSGSM_FRAME_SIZE) {
			ast_log(LOG_WARNING, "Bad write (%d/65): %s\n", res, strerror(errno));
			return -1;
		}
		update_header(s->f); /* XXX inefficient! */
	}
	return 0;
}
Exemplo n.º 14
0
static int generic_write(struct ast_filestream *fs, struct ast_frame *f, enum ast_format_id id)
{
	int res;
	if (f->frametype != AST_FRAME_VOICE) {
		ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
		return -1;
	}
	if (f->subclass.format.id != id) {
		ast_log(LOG_WARNING, "Asked to write non-slinear frame (%s)!\n", ast_getformatname(&f->subclass.format));
		return -1;
	}
	if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
			ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
			return -1;
	}
	return 0;
}
static int siren14write(struct ast_filestream *fs, struct ast_frame *f)
{
	int res;

	if (f->frametype != AST_FRAME_VOICE) {
		ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
		return -1;
	}
	if (f->subclass.format.id != AST_FORMAT_SIREN14) {
		ast_log(LOG_WARNING, "Asked to write non-Siren14 frame (%s)!\n", ast_getformatname(&f->subclass.format));
		return -1;
	}
	if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
		ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, f->datalen, strerror(errno));
		return -1;
	}
	return 0;
}
Exemplo n.º 16
0
static int g729_write(struct ast_filestream *fs, struct ast_frame *f)
{
	int res;
	if (f->frametype != AST_FRAME_VOICE) {
		ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
		return -1;
	}
	if (f->subclass.codec != AST_FORMAT_G729A) {
		ast_log(LOG_WARNING, "Asked to write non-G729 frame (%s)!\n", ast_getformatname(f->subclass.codec));
		return -1;
	}
	if (f->datalen % 10) {
		ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of 10\n", f->datalen);
		return -1;
	}
	if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
			ast_log(LOG_WARNING, "Bad write (%d/10): %s\n", res, strerror(errno));
			return -1;
	}
	return 0;
}
Exemplo n.º 17
0
/*! \brief Add format/lang pairs to the array embedded in the sound object */
static int add_format_information_cb(void *obj, void *arg, int flags)
{
	char *language = obj;
	struct lang_format_info *args = arg;
	struct ast_format format;
	RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
	RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);

	if (!sounds_index) {
		return CMP_STOP;
	}

	cap = ast_media_get_format_cap(sounds_index, args->filename, language);
	if (!cap) {
		return CMP_STOP;
	}

	ast_format_cap_iter_start(cap);
	while (!ast_format_cap_iter_next(cap, &format)) {
		struct ast_json *lang_format_pair;
		const char *format_name = ast_getformatname(&format);

		if (!ast_strlen_zero(args->format_filter)
			&& strcmp(args->format_filter, format_name)) {
			continue;
		}

		lang_format_pair = ast_json_pack("{s: s, s: s}",
			"language", language,
			"format", format_name);
		if (!lang_format_pair) {
			ast_format_cap_iter_end(cap);
			return CMP_STOP;
		}

		ast_json_array_append(args->format_list, lang_format_pair);
	}
	ast_format_cap_iter_end(cap);
	return 0;
}
Exemplo n.º 18
0
/*!
 * \brief Write audio data from a frame to an OGG/Vorbis filestream.
 * \param fs An OGG/Vorbis filestream.
 * \param f A frame containing audio to be written to the filestream.
 * \return -1 if there was an error, 0 on success.
 */
static int ogg_vorbis_write(struct ast_filestream *fs, struct ast_frame *f)
{
	int i;
	float **buffer;
	short *data;
	struct ogg_vorbis_desc *s = (struct ogg_vorbis_desc *) fs->_private;

	if (!s->writing) {
		ast_log(LOG_ERROR, "This stream is not set up for writing!\n");
		return -1;
	}

	if (f->frametype != AST_FRAME_VOICE) {
		ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
		return -1;
	}
	if (f->subclass.format.id != AST_FORMAT_SLINEAR) {
		ast_log(LOG_WARNING, "Asked to write non-SLINEAR frame (%s)!\n",
			ast_getformatname(&f->subclass.format));
		return -1;
	}
	if (!f->datalen)
		return -1;

	data = (short *) f->data.ptr;

	buffer = vorbis_analysis_buffer(&s->vd, f->samples);

	for (i = 0; i < f->samples; i++)
		buffer[0][i] = (double)data[i] / 32768.0;

	vorbis_analysis_wrote(&s->vd, f->samples);

	write_stream(s, fs->f);

	s->writing_pcm_pos +=  f->samples;

	return 0;
}
static int gsm_write(struct ast_filestream *fs, struct ast_frame *f)
{
	int res;
	unsigned char gsm[2*GSM_FRAME_SIZE];

	if (f->frametype != AST_FRAME_VOICE) {
		ast_log(LOG_WARNING, "Asked to write non-voice frame!\n");
		return -1;
	}
	if (f->subclass.format.id != AST_FORMAT_GSM) {
		ast_log(LOG_WARNING, "Asked to write non-GSM frame (%s)!\n", ast_getformatname(&f->subclass.format));
		return -1;
	}
	if (!(f->datalen % 65)) {
		/* This is in MSGSM format, need to be converted */
		int len=0;
		while(len < f->datalen) {
			conv65(f->data.ptr + len, gsm);
			if ((res = fwrite(gsm, 1, 2*GSM_FRAME_SIZE, fs->f)) != 2*GSM_FRAME_SIZE) {
				ast_log(LOG_WARNING, "Bad write (%d/66): %s\n", res, strerror(errno));
				return -1;
			}
			len += 65;
		}
	} else {
		if (f->datalen % GSM_FRAME_SIZE) {
			ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of 33\n", f->datalen);
			return -1;
		}
		if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) {
				ast_log(LOG_WARNING, "Bad write (%d/33): %s\n", res, strerror(errno));
				return -1;
		}
	}
	return 0;
}
Exemplo n.º 20
0
static void print_frame(struct ast_frame *frame)
{
	switch (frame->frametype) {
	case AST_FRAME_DTMF_END:
		ast_verbose("FrameType: DTMF END\n");
		ast_verbose("Digit: %d\n", frame->subclass.integer);
		break;
	case AST_FRAME_VOICE:
		ast_verbose("FrameType: VOICE\n");
		ast_verbose("Codec: %s\n", ast_getformatname(&frame->subclass.format));
		ast_verbose("MS: %ld\n", frame->len);
		ast_verbose("Samples: %d\n", frame->samples);
		ast_verbose("Bytes: %d\n", frame->datalen);
		break;
	case AST_FRAME_VIDEO:
		ast_verbose("FrameType: VIDEO\n");
		ast_verbose("Codec: %s\n", ast_getformatname(&frame->subclass.format));
		ast_verbose("MS: %ld\n", frame->len);
		ast_verbose("Samples: %d\n", frame->samples);
		ast_verbose("Bytes: %d\n", frame->datalen);
		break;
	case AST_FRAME_CONTROL:
		ast_verbose("FrameType: CONTROL\n");
		switch ((enum ast_control_frame_type) frame->subclass.integer) {
		case AST_CONTROL_HANGUP:
			ast_verbose("SubClass: HANGUP\n");
			break;
		case AST_CONTROL_RING:
			ast_verbose("SubClass: RING\n");
			break;
		case AST_CONTROL_RINGING:
			ast_verbose("SubClass: RINGING\n");
			break;
		case AST_CONTROL_ANSWER:
			ast_verbose("SubClass: ANSWER\n");
			break;
		case AST_CONTROL_BUSY:
			ast_verbose("SubClass: BUSY\n");
			break;
		case AST_CONTROL_TAKEOFFHOOK:
			ast_verbose("SubClass: TAKEOFFHOOK\n");
			break;
		case AST_CONTROL_OFFHOOK:
			ast_verbose("SubClass: OFFHOOK\n");
			break;
		case AST_CONTROL_CONGESTION:
			ast_verbose("SubClass: CONGESTION\n");
			break;
		case AST_CONTROL_FLASH:
			ast_verbose("SubClass: FLASH\n");
			break;
		case AST_CONTROL_WINK:
			ast_verbose("SubClass: WINK\n");
			break;
		case AST_CONTROL_OPTION:
			ast_verbose("SubClass: OPTION\n");
			break;
		case AST_CONTROL_RADIO_KEY:
			ast_verbose("SubClass: RADIO KEY\n");
			break;
		case AST_CONTROL_RADIO_UNKEY:
			ast_verbose("SubClass: RADIO UNKEY\n");
			break;
		case AST_CONTROL_PROGRESS:
			ast_verbose("SubClass: PROGRESS\n");
			break;
		case AST_CONTROL_PROCEEDING:
			ast_verbose("SubClass: PROCEEDING\n");
			break;
		case AST_CONTROL_HOLD:
			ast_verbose("SubClass: HOLD\n");
			break;
		case AST_CONTROL_UNHOLD:
			ast_verbose("SubClass: UNHOLD\n");
			break;
		case AST_CONTROL_VIDUPDATE:
			ast_verbose("SubClass: VIDUPDATE\n");
			break;
		case _XXX_AST_CONTROL_T38:
			ast_verbose("SubClass: XXX T38\n");
			break;
		case AST_CONTROL_SRCUPDATE:
			ast_verbose("SubClass: SRCUPDATE\n");
			break;
		case AST_CONTROL_TRANSFER:
			ast_verbose("SubClass: TRANSFER\n");
			break;
		case AST_CONTROL_CONNECTED_LINE:
			ast_verbose("SubClass: CONNECTED LINE\n");
			break;
		case AST_CONTROL_REDIRECTING:
			ast_verbose("SubClass: REDIRECTING\n");
			break;
		case AST_CONTROL_T38_PARAMETERS:
			ast_verbose("SubClass: T38 PARAMETERS\n");
			break;
		case AST_CONTROL_CC:
			ast_verbose("SubClass: CC\n");
			break;
		case AST_CONTROL_SRCCHANGE:
			ast_verbose("SubClass: SRCCHANGE\n");
			break;
		case AST_CONTROL_READ_ACTION:
			ast_verbose("SubClass: READ ACTION\n");
			break;
		case AST_CONTROL_AOC:
			ast_verbose("SubClass: AOC\n");
			break;
		case AST_CONTROL_MCID:
			ast_verbose("SubClass: MCID\n");
			break;
		case AST_CONTROL_INCOMPLETE:
			ast_verbose("SubClass: INCOMPLETE\n");
			break;
		case AST_CONTROL_END_OF_Q:
			ast_verbose("SubClass: END_OF_Q\n");
			break;
		case AST_CONTROL_UPDATE_RTP_PEER:
			ast_verbose("SubClass: UPDATE_RTP_PEER\n");
			break;
		}
		
		if (frame->subclass.integer == -1) {
			ast_verbose("SubClass: %d\n", frame->subclass.integer);
		}
		ast_verbose("Bytes: %d\n", frame->datalen);
		break;
	case AST_FRAME_NULL:
		ast_verbose("FrameType: NULL\n");
		break;
	case AST_FRAME_IAX:
		ast_verbose("FrameType: IAX\n");
		break;
	case AST_FRAME_TEXT:
		ast_verbose("FrameType: TXT\n");
		break;
	case AST_FRAME_IMAGE:
		ast_verbose("FrameType: IMAGE\n");
		break;
	case AST_FRAME_HTML:
		ast_verbose("FrameType: HTML\n");
		break;
	case AST_FRAME_CNG:
		ast_verbose("FrameType: CNG\n");
		break;
	case AST_FRAME_MODEM:
		ast_verbose("FrameType: MODEM\n");
		break;
	case AST_FRAME_DTMF_BEGIN:
		ast_verbose("FrameType: DTMF BEGIN\n");
		ast_verbose("Digit: %d\n", frame->subclass.integer);
		break;
	}

	ast_verbose("Src: %s\n", ast_strlen_zero(frame->src) ? "NOT PRESENT" : frame->src);
	ast_verbose("\n");
}
Exemplo n.º 21
0
	AST_DECLARE_APP_ARGS(args,
		AST_APP_ARG(argInitialSilence);
		AST_APP_ARG(argGreeting);
		AST_APP_ARG(argAfterGreetingSilence);
		AST_APP_ARG(argTotalAnalysisTime);
		AST_APP_ARG(argMinimumWordLength);
		AST_APP_ARG(argBetweenWordsSilence);
		AST_APP_ARG(argMaximumNumberOfWords);
		AST_APP_ARG(argSilenceThreshold);
		AST_APP_ARG(argMaximumWordLength);
	);

	ast_verb(3, "AMD: %s %s %s (Fmt: %s)\n", chan->name,
		S_COR(chan->caller.ani.number.valid, chan->caller.ani.number.str, "(N/A)"),
		S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, "(N/A)"),
		ast_getformatname(chan->readformat));

	/* Lets parse the arguments. */
	if (!ast_strlen_zero(parse)) {
		/* Some arguments have been passed. Lets parse them and overwrite the defaults. */
		AST_STANDARD_APP_ARGS(args, parse);
		if (!ast_strlen_zero(args.argInitialSilence))
			initialSilence = atoi(args.argInitialSilence);
		if (!ast_strlen_zero(args.argGreeting))
			greeting = atoi(args.argGreeting);
		if (!ast_strlen_zero(args.argAfterGreetingSilence))
			afterGreetingSilence = atoi(args.argAfterGreetingSilence);
		if (!ast_strlen_zero(args.argTotalAnalysisTime))
			totalAnalysisTime = atoi(args.argTotalAnalysisTime);
		if (!ast_strlen_zero(args.argMinimumWordLength))
			minimumWordLength = atoi(args.argMinimumWordLength);
Exemplo n.º 22
0
int AST_OPTIONAL_API_NAME(ast_adsi_transmit_message_full)(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype, int dowait)
{
	unsigned char *msgs[5] = { NULL, NULL, NULL, NULL, NULL };
	int msglens[5], msgtypes[5], newdatamode = (ast_channel_adsicpe(chan) & ADSI_FLAG_DATAMODE), res, x, waitforswitch = 0;
	struct ast_format writeformat;
	struct ast_format readformat;

	ast_format_copy(&writeformat, ast_channel_writeformat(chan));
	ast_format_copy(&readformat, ast_channel_readformat(chan));

	for (x = 0; x < msglen; x += (msg[x+1]+2)) {
		if (msg[x] == ADSI_SWITCH_TO_DATA) {
			ast_debug(1, "Switch to data is sent!\n");
			waitforswitch++;
			newdatamode = ADSI_FLAG_DATAMODE;
		}

		if (msg[x] == ADSI_SWITCH_TO_VOICE) {
			ast_debug(1, "Switch to voice is sent!\n");
			waitforswitch++;
			newdatamode = 0;
		}
	}
	msgs[0] = msg;

	msglens[0] = msglen;
	msgtypes[0] = msgtype;

	if (msglen > 253) {
		ast_log(LOG_WARNING, "Can't send ADSI message of %d bytes, too large\n", msglen);
		return -1;
	}

	ast_stopstream(chan);

	if (ast_set_write_format_by_id(chan, AST_FORMAT_ULAW)) {
		ast_log(LOG_WARNING, "Unable to set write format to ULAW\n");
		return -1;
	}

	if (ast_set_read_format_by_id(chan, AST_FORMAT_ULAW)) {
		ast_log(LOG_WARNING, "Unable to set read format to ULAW\n");
		if (writeformat.id) {
			if (ast_set_write_format(chan, &writeformat)) {
				ast_log(LOG_WARNING, "Unable to restore write format to %s\n", ast_getformatname(&writeformat));
			}
		}
		return -1;
	}
	res = __adsi_transmit_messages(chan, msgs, msglens, msgtypes);

	if (dowait) {
		ast_debug(1, "Wait for switch is '%d'\n", waitforswitch);
		while (waitforswitch-- && ((res = ast_waitfordigit(chan, 1000)) > 0)) {
			res = 0;
			ast_debug(1, "Waiting for 'B'...\n");
		}
	}

	if (!res) {
		ast_channel_adsicpe_set(chan, (ast_channel_adsicpe(chan) & ~ADSI_FLAG_DATAMODE) | newdatamode);
	}

	if (writeformat.id) {
		ast_set_write_format(chan, &writeformat);
	}
	if (readformat.id) {
		ast_set_read_format(chan, &readformat);
	}

	if (!res) {
		res = ast_safe_sleep(chan, 100 );
	}
	return res;
}
static int do_waiting(struct ast_channel *chan, int maxsilence) {

	struct ast_frame *f;
	int totalsilence = 0;
	int dspsilence = 0;
	int gotsilence = 0; 
	static int silencethreshold = 128;
	int rfmt = 0;
	int res = 0;
	struct ast_dsp *sildet;	 /* silence detector dsp */
	time_t start, now;
	time(&start);

	rfmt = chan->readformat; /* Set to linear mode */
	res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
	if (res < 0) {
		ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
		return -1;
	}

	sildet = ast_dsp_new(); /* Create the silence detector */
	if (!sildet) {
		ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
		return -1;
	}
	ast_dsp_set_threshold(sildet, silencethreshold);

	/* Await silence... */
	f = NULL;
	for(;;) {
		res = ast_waitfor(chan, 2000);
		if (!res) {
			ast_log(LOG_WARNING, "One waitfor failed, trying another\n");
			/* Try one more time in case of masq */
			res = ast_waitfor(chan, 2000);
			if (!res) {
				ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
				res = -1;
			}
		}

		if (res < 0) {
			f = NULL;
			break;
		}
		f = ast_read(chan);
		if (!f)
			break;
		if (f->frametype == AST_FRAME_VOICE) {
			dspsilence = 0;
			ast_dsp_silence(sildet, f, &dspsilence);
			if (dspsilence) {
				totalsilence = dspsilence;
				time(&start);
			} else {
				totalsilence = 0;
			}

			if (totalsilence >= maxsilence) {
				if (option_verbose > 2)
					ast_verbose(VERBOSE_PREFIX_3 "Exiting with %dms silence > %dms required\n", totalsilence, maxsilence);
				/* Ended happily with silence */
				gotsilence = 1;
				pbx_builtin_setvar_helper(chan, "WAITSTATUS", "SILENCE");
				ast_log(LOG_DEBUG, "WAITSTATUS was set to SILENCE\n");
				ast_frfree(f);
				break;
			} else if ( difftime(time(&now),start) >= maxsilence/1000 ) {
				pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
				ast_log(LOG_DEBUG, "WAITSTATUS was set to TIMEOUT\n");
				ast_frfree(f);
				break;
			}
		}
		ast_frfree(f);
	}
	if (rfmt && ast_set_read_format(chan, rfmt)) {
		ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
	}
	ast_dsp_free(sildet);
	return gotsilence;
}
Exemplo n.º 24
0
static int do_waiting(struct ast_channel *chan, int timereqd, time_t waitstart, int timeout, int wait_for_silence) {
	struct ast_frame *f = NULL;
	int dsptime = 0;
	struct ast_format rfmt;
	int res = 0;
	struct ast_dsp *sildet;	 /* silence detector dsp */
 	time_t now;

	/*Either silence or noise calc depending on wait_for_silence flag*/
	int (*ast_dsp_func)(struct ast_dsp*, struct ast_frame*, int*) =
				wait_for_silence ? ast_dsp_silence : ast_dsp_noise;

	ast_format_copy(&rfmt, &chan->readformat); /* Set to linear mode */
	if ((res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) < 0) {
		ast_log(LOG_WARNING, "Unable to set channel to linear mode, giving up\n");
		return -1;
	}

	/* Create the silence detector */
	if (!(sildet = ast_dsp_new())) {
		ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
		return -1;
	}
	ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));

	/* Await silence... */
	for (;;) {
		/* Start with no silence received */
		dsptime = 0;

		res = ast_waitfor(chan, timereqd);

		/* Must have gotten a hangup; let's exit */
		if (res < 0) {
			pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
			break;
		}
		
		/* We waited and got no frame; sounds like digital silence or a muted digital channel */
		if (res == 0) {
			dsptime = timereqd;
		} else {
			/* Looks like we did get a frame, so let's check it out */
			if (!(f = ast_read(chan))) {
				pbx_builtin_setvar_helper(chan, "WAITSTATUS", "HANGUP");
				break;
			}
			if (f->frametype == AST_FRAME_VOICE) {
				ast_dsp_func(sildet, f, &dsptime);
			}
			ast_frfree(f);
		}

		ast_verb(6, "Got %dms %s < %dms required\n", dsptime, wait_for_silence ? "silence" : "noise", timereqd);

		if (dsptime >= timereqd) {
			ast_verb(3, "Exiting with %dms %s >= %dms required\n", dsptime, wait_for_silence ? "silence" : "noise", timereqd);
			/* Ended happily with silence */
			res = 1;
			pbx_builtin_setvar_helper(chan, "WAITSTATUS", wait_for_silence ? "SILENCE" : "NOISE");
			ast_debug(1, "WAITSTATUS was set to %s\n", wait_for_silence ? "SILENCE" : "NOISE");
			break;
		}

		if (timeout && (difftime(time(&now), waitstart) >= timeout)) {
			pbx_builtin_setvar_helper(chan, "WAITSTATUS", "TIMEOUT");
			ast_debug(1, "WAITSTATUS was set to TIMEOUT\n");
			res = 0;
			break;
		}
	}


	if (rfmt.id && ast_set_read_format(chan, &rfmt)) {
		ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(&rfmt), chan->name);
	}
	ast_dsp_free(sildet);
	return res;
}
/*! \brief Use the list of translators to build a translation matrix */
static void rebuild_matrix(int samples)
{
	struct ast_translator *t;
	int changed;
	int x,y,z;

	if (option_debug)
		ast_log(LOG_DEBUG, "Resetting translation matrix\n");
	memset(tr_matrix, 0, sizeof(tr_matrix));
	t = list;
	while(t) {
		if(samples)
			calc_cost(t, samples);
	  
		if (!tr_matrix[t->srcfmt][t->dstfmt].step ||
		     tr_matrix[t->srcfmt][t->dstfmt].cost > t->cost) {
			tr_matrix[t->srcfmt][t->dstfmt].step = t;
			tr_matrix[t->srcfmt][t->dstfmt].cost = t->cost;
		}
		t = t->next;
	}
	do {
		changed = 0;
		/* Don't you just love O(N^3) operations? */
		for (x=0; x< MAX_FORMAT; x++)				/* For each source format */
			for (y=0; y < MAX_FORMAT; y++) 			/* And each destination format */
				if (x != y)				/* Except ourselves, of course */
					for (z=0; z < MAX_FORMAT; z++) 	/* And each format it might convert to */
						if ((x!=z) && (y!=z)) 		/* Don't ever convert back to us */
							if (tr_matrix[x][y].step && /* We can convert from x to y */
								tr_matrix[y][z].step && /* And from y to z and... */
								(!tr_matrix[x][z].step || 	/* Either there isn't an x->z conversion */
								(tr_matrix[x][y].cost + 
								 tr_matrix[y][z].cost <	/* Or we're cheaper than the existing */
								 tr_matrix[x][z].cost)  /* solution */
							     )) {
								 			/* We can get from x to z via y with a cost that
											   is the sum of the transition from x to y and
											   from y to z */
								 
								 	tr_matrix[x][z].step = tr_matrix[x][y].step;
									tr_matrix[x][z].cost = tr_matrix[x][y].cost + 
														   tr_matrix[y][z].cost;
									if (option_debug)
										ast_log(LOG_DEBUG, "Discovered %d cost path from %s to %s, via %d\n", tr_matrix[x][z].cost, ast_getformatname(x), ast_getformatname(z), y);
									changed++;
								 }
		
	} while (changed);
}
Exemplo n.º 26
0
/*! \brief Get packet size for codec */
struct ast_format_list ast_codec_pref_getsize(struct ast_codec_pref *pref, struct ast_format *format)
{
	int x, idx = -1, framems = 0;
	struct ast_format_list fmt = { { 0, }, };
	size_t f_len = 0;
	const struct ast_format_list *f_list = ast_format_list_get(&f_len);

	for (x = 0; x < f_len; x++) {
		if (ast_format_cmp(&f_list[x].format, format) == AST_FORMAT_CMP_EQUAL) {
			fmt = f_list[x];
			idx = x;
			break;
		}
	}

	if (idx < 0) {
		ast_log(AST_LOG_WARNING, "Format %s unknown; unable to get preferred codec packet size\n", ast_getformatname(format));
		ast_format_list_destroy(f_list);
		return fmt;
	}

	for (x = 0; x < f_len; x++) {
		if (pref->order[x] == (idx + 1)) {
			framems = pref->framing[x];
			break;
		}
	}

	/* size validation */
	if (!framems)
		framems = f_list[idx].def_ms;

	if (f_list[idx].inc_ms && framems % f_list[idx].inc_ms) /* avoid division by zero */
		framems -= framems % f_list[idx].inc_ms;

	if (framems < f_list[idx].min_ms)
		framems = f_list[idx].min_ms;

	if (framems > f_list[idx].max_ms)
		framems = f_list[idx].max_ms;

	fmt.cur_ms = framems;
	ast_format_list_destroy(f_list);
	return fmt;
}
/*! \brief unregister codec translator */
int ast_unregister_translator(struct ast_translator *t)
{
	char tmp[80];
	struct ast_translator *u, *ul = NULL;
	ast_mutex_lock(&list_lock);
	u = list;
	while(u) {
		if (u == t) {
			if (ul)
				ul->next = u->next;
			else
				list = u->next;
			if (option_verbose > 1)
				ast_verbose(VERBOSE_PREFIX_2 "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt));
			break;
		}
		ul = u;
		u = u->next;
	}
	rebuild_matrix(0);
	ast_mutex_unlock(&list_lock);
	return (u ? 0 : -1);
}
Exemplo n.º 28
0
static int func_channel_read(struct ast_channel *chan, const char *function,
                             char *data, char *buf, size_t len)
{
    int ret = 0;
    char tmp[512];
    struct ast_format_cap *tmpcap;

    if (!strcasecmp(data, "audionativeformat")) {
        if ((tmpcap = ast_format_cap_get_type(chan->nativeformats, AST_FORMAT_TYPE_AUDIO))) {
            ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
            tmpcap = ast_format_cap_destroy(tmpcap);
        }
    } else if (!strcasecmp(data, "videonativeformat")) {
        if ((tmpcap = ast_format_cap_get_type(chan->nativeformats, AST_FORMAT_TYPE_VIDEO))) {
            ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
            tmpcap = ast_format_cap_destroy(tmpcap);
        }
    } else if (!strcasecmp(data, "audioreadformat")) {
        ast_copy_string(buf, ast_getformatname(&chan->readformat), len);
    } else if (!strcasecmp(data, "audiowriteformat")) {
        ast_copy_string(buf, ast_getformatname(&chan->writeformat), len);
#ifdef CHANNEL_TRACE
    } else if (!strcasecmp(data, "trace")) {
        ast_channel_lock(chan);
        ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
        ast_channel_unlock(chan);
#endif
    } else if (!strcasecmp(data, "tonezone") && chan->zone)
        locked_copy_string(chan, buf, chan->zone->country, len);
    else if (!strcasecmp(data, "language"))
        locked_copy_string(chan, buf, chan->language, len);
    else if (!strcasecmp(data, "musicclass"))
        locked_copy_string(chan, buf, chan->musicclass, len);
    else if (!strcasecmp(data, "name")) {
        locked_copy_string(chan, buf, chan->name, len);
    } else if (!strcasecmp(data, "parkinglot"))
        locked_copy_string(chan, buf, chan->parkinglot, len);
    else if (!strcasecmp(data, "state"))
        locked_copy_string(chan, buf, ast_state2str(chan->_state), len);
    else if (!strcasecmp(data, "channeltype"))
        locked_copy_string(chan, buf, chan->tech->type, len);
    else if (!strcasecmp(data, "accountcode"))
        locked_copy_string(chan, buf, chan->accountcode, len);
    else if (!strcasecmp(data, "checkhangup")) {
        ast_channel_lock(chan);
        ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
        ast_channel_unlock(chan);
    } else if (!strcasecmp(data, "peeraccount"))
        locked_copy_string(chan, buf, chan->peeraccount, len);
    else if (!strcasecmp(data, "hangupsource"))
        locked_copy_string(chan, buf, chan->hangupsource, len);
    else if (!strcasecmp(data, "appname") && chan->appl)
        locked_copy_string(chan, buf, chan->appl, len);
    else if (!strcasecmp(data, "appdata") && chan->data)
        locked_copy_string(chan, buf, chan->data, len);
    else if (!strcasecmp(data, "exten") && chan->data)
        locked_copy_string(chan, buf, chan->exten, len);
    else if (!strcasecmp(data, "context") && chan->data)
        locked_copy_string(chan, buf, chan->context, len);
    else if (!strcasecmp(data, "userfield") && chan->data)
        locked_copy_string(chan, buf, chan->userfield, len);
    else if (!strcasecmp(data, "channame") && chan->data)
        locked_copy_string(chan, buf, chan->name, len);
    else if (!strcasecmp(data, "linkedid")) {
        ast_channel_lock(chan);
        if (ast_strlen_zero(chan->linkedid)) {
            /* fall back on the channel's uniqueid if linkedid is unset */
            ast_copy_string(buf, chan->uniqueid, len);
        }
        else {
            ast_copy_string(buf, chan->linkedid, len);
        }
        ast_channel_unlock(chan);
    } else if (!strcasecmp(data, "peer")) {
        struct ast_channel *p;
        ast_channel_lock(chan);
        p = ast_bridged_channel(chan);
        if (p || chan->tech || chan->cdr) /* dummy channel? if so, we hid the peer name in the language */
            ast_copy_string(buf, (p ? p->name : ""), len);
        else {
            /* a dummy channel can still pass along bridged peer info via
                           the BRIDGEPEER variable */
            const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
            if (!ast_strlen_zero(pname))
                ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
            else
                buf[0] = 0;
        }
        ast_channel_unlock(chan);
    } else if (!strcasecmp(data, "uniqueid")) {
        locked_copy_string(chan, buf, chan->uniqueid, len);
    } else if (!strcasecmp(data, "transfercapability")) {
        locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len);
    } else if (!strcasecmp(data, "callgroup")) {
        char groupbuf[256];
        locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len);
    } else if (!strcasecmp(data, "pickupgroup")) {
        char groupbuf[256];
        locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), chan->pickupgroup), len);
    } else if (!strcasecmp(data, "amaflags")) {
        char amabuf[256];
        snprintf(amabuf,sizeof(amabuf), "%d", chan->amaflags);
        locked_copy_string(chan, buf, amabuf, len);
    } else if (!strncasecmp(data, "secure_bridge_", 14)) {
        struct ast_datastore *ds;
        ast_channel_lock(chan);
        if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
            struct ast_secure_call_store *encrypt = ds->data;
            if (!strcasecmp(data, "secure_bridge_signaling")) {
                snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
            } else if (!strcasecmp(data, "secure_bridge_media")) {
                snprintf(buf, len, "%s", encrypt->media ? "1" : "");
            }
        }
        ast_channel_unlock(chan);
    } else if (!chan->tech || !chan->tech->func_channel_read || chan->tech->func_channel_read(chan, function, data, buf, len)) {
        ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
        ret = -1;
    }

    return ret;
}
Exemplo n.º 29
0
static int nv_detectfax_exec(struct ast_channel *chan, const char *data)
{
	int res = 0;
	char tmp[256] = "\0";
	char *p = NULL;
	char *waitstr = NULL;
	char *options = NULL;
	char *silstr = NULL;
	char *minstr = NULL;
	char *maxstr = NULL;
	struct ast_frame *fr = NULL;
	struct ast_frame *fr2 = NULL;
	int notsilent = 0;
	struct timeval start = {0, 0}, end = {0, 0};
	int waitdur = 4;
	int sildur = 1000;
	int mindur = 100;
	int maxdur = -1;
	int skipanswer = 0;
	int noextneeded = 0;
	int ignoredtmf = 0;
	int ignorefax = 0;
	int ignoretalk = 0;
	int x = 0;
	struct ast_format* origrformat = NULL;
	int features = 0;
	time_t timeout = 0;
	struct ast_dsp *dsp = NULL;
	
	struct ast_format_cap *cap;
	struct ast_format linearFormat;
	
	/* linear format capabilities */
	ast_format_set(&linearFormat, AST_FORMAT_SLINEAR, 0);
	cap = ast_format_cap_alloc_nolock();
	ast_format_cap_add(cap, &linearFormat);
	/* done */
	
	pbx_builtin_setvar_helper(chan, "FAX_DETECTED", "");
	pbx_builtin_setvar_helper(chan, "FAXEXTEN", "");
	pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", "");
	pbx_builtin_setvar_helper(chan, "TALK_DETECTED", "");
	
	if (data || !ast_strlen_zero(data)) {
		strncpy(tmp, data, sizeof(tmp)-1);
	}	
	
	p = tmp;
	
	waitstr = strsep(&p, ",");
	options = strsep(&p, ",");
	silstr = strsep(&p, ",");
	minstr = strsep(&p, ",");	
	maxstr = strsep(&p, ",");	
	
	if (waitstr) {
		if ((sscanf(waitstr, "%d", &x) == 1) && (x > 0))
			waitdur = x;
	}
	
	if (options) {
		if (strchr(options, 'n'))
			skipanswer = 1;
		if (strchr(options, 'x'))
			noextneeded = 1;
		if (strchr(options, 'd'))
			ignoredtmf = 1;
		if (strchr(options, 'f'))
			ignorefax = 1;
		if (strchr(options, 't'))
			ignoretalk = 1;
	}
	
	if (silstr) {
		if ((sscanf(silstr, "%d", &x) == 1) && (x > 0))
			sildur = x;
	}
	
	if (minstr) {
		if ((sscanf(minstr, "%d", &x) == 1) && (x > 0))
			mindur = x;
	}
	
	if (maxstr) {
		if ((sscanf(maxstr, "%d", &x) == 1) && (x > 0))
			maxdur = x;
	}
	
	ast_log(LOG_DEBUG, "Preparing detect of fax (waitdur=%dms, sildur=%dms, mindur=%dms, maxdur=%dms)\n", 
						waitdur, sildur, mindur, maxdur);
						
	//	LOCAL_USER_ADD(u);
// 	if (chan->_state != AST_STATE_UP && !skipanswer) {
	if (ast_channel_state(chan) != AST_STATE_UP && !skipanswer) {
		/* Otherwise answer unless we're supposed to send this while on-hook */
		res = ast_answer(chan);
	}
	if (!res) {
// 		origrformat = chan->readformat;
		origrformat = ast_channel_readformat(chan);
		
// 		if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR))) 
		if ((res = ast_set_read_format_from_cap(chan, cap)) ){
			ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
		}
	}
	if (!(dsp = ast_dsp_new())) {
		ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
		res = -1;
	}
	
	if (dsp) {	
		if (!ignoretalk)
			; /* features |= DSP_FEATURE_SILENCE_SUPPRESS; */
		if (!ignorefax)
			features |= DSP_FEATURE_FAX_DETECT;
		//if (!ignoredtmf)
			features |= DSP_FEATURE_DIGIT_DETECT;
			
		ast_dsp_set_threshold(dsp, 256); 
		ast_dsp_set_features(dsp, features | DSP_DIGITMODE_RELAXDTMF);
		ast_dsp_set_digitmode(dsp, DSP_DIGITMODE_DTMF);
	}

	if (!res) {
		if (waitdur > 0)
			timeout = time(NULL) + (time_t)waitdur;

		while(ast_waitfor(chan, -1) > -1) {
			if (waitdur > 0 && time(NULL) > timeout) {
				res = 0;
				break;
			}

			fr = ast_read(chan);
			if (!fr) {
				ast_log(LOG_DEBUG, "Got hangup\n");
				res = -1;
				break;
			}

			fr2 = ast_dsp_process(chan, dsp, fr);
			if (!fr2) {
				ast_log(LOG_WARNING, "Bad DSP received (what happened?)\n");
				fr2 = fr;
			} 

			if (fr2->frametype == AST_FRAME_DTMF) {
				if (fr2->subclass.integer == 'f' && !ignorefax) {
					/* Fax tone -- Handle and return NULL */
					ast_log(LOG_DEBUG, "Fax detected on %s\n", ast_channel_name(chan));
					ast_log(LOG_DEBUG, "Fax detected on %s\n", ast_channel_name(chan));
					if (strcmp(ast_channel_exten(chan), "fax")) {
						ast_log(LOG_NOTICE, "Redirecting %s to fax extension\n", ast_channel_name(chan));
						pbx_builtin_setvar_helper(chan, "FAX_DETECTED", "1");
						pbx_builtin_setvar_helper(chan,"FAXEXTEN",ast_channel_exten(chan));								
						if (ast_exists_extension(chan, ast_channel_context(chan), "fax", 1, ast_channel_caller(chan)->id.number.str)) {
							/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
// 							strncpy(ast_channel_exten(chan), "fax", sizeof(ast_channel_exten(chan))-1);
// 							chan->priority = 0;
							ast_channel_exten_set(chan, "fax");
							ast_channel_priority_set(chan, 0);
						} else
							ast_log(LOG_WARNING, "Fax detected, but no fax extension\n");
					} else
						ast_log(LOG_WARNING, "Already in a fax extension, not redirecting\n");

					res = 0;
					ast_frfree(fr);
					break;
				} else if (!ignoredtmf) {
					ast_log(LOG_DEBUG, "DTMF detected on %s\n", ast_channel_name(chan));
					char t[2];
					t[0] = fr2->subclass.integer;
					t[1] = '\0';
					if (noextneeded || ast_canmatch_extension(chan, ast_channel_context(chan), t, 1, ast_channel_caller(chan)->id.number.str)) {
						pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", "1");
						/* They entered a valid extension, or might be anyhow */
						if (noextneeded) {
							ast_log(LOG_NOTICE, "DTMF received (not matching to exten)\n");
							res = 0;
						} else {
							ast_log(LOG_NOTICE, "DTMF received (matching to exten)\n");
							res = fr2->subclass.integer;
						}
						ast_frfree(fr);
						break;
					} else
						ast_log(LOG_DEBUG, "Valid extension requested and DTMF did not match\n");
				}
// 			} else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR) && !ignoretalk) {
			} else if ((fr->frametype == AST_FRAME_VOICE) && ( ast_format_cap_iscompatible(cap, &fr->subclass.format)) && !ignoretalk) {
				int totalsilence;
				int ms;
				res = ast_dsp_silence(dsp, fr, &totalsilence);
				if (res && (totalsilence > sildur)) {
					/* We've been quiet a little while */
					if (notsilent) {
						/* We had heard some talking */
						gettimeofday(&end, NULL);
						ms = (end.tv_sec - start.tv_sec) * 1000;
						ms += (end.tv_usec - start.tv_usec) / 1000;
						ms -= sildur;
						if (ms < 0)
							ms = 0;
						if ((ms > mindur) && ((maxdur < 0) || (ms < maxdur))) {
							char ms_str[10];
							ast_log(LOG_DEBUG, "Found qualified token of %d ms\n", ms);
							ast_log(LOG_NOTICE, "Redirecting %s to talk extension\n", ast_channel_name(chan));

							/* Save detected talk time (in milliseconds) */ 
							sprintf(ms_str, "%d", ms);	
							pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);

							if (ast_exists_extension(chan, ast_channel_context(chan), "talk", 1, ast_channel_caller(chan)->id.number.str)) {
// 								strncpy(ast_channel_exten(chan), "talk", sizeof(ast_channel_exten(chan)) - 1);
// 								chan->priority = 0;
								ast_channel_exten_set(chan, "talk");
								ast_channel_priority_set(chan, 0);
							} else
								ast_log(LOG_WARNING, "Talk detected, but no talk extension\n");
							res = 0;
							ast_frfree(fr);
							break;
						} else
							ast_log(LOG_DEBUG, "Found unqualified token of %d ms\n", ms);
						notsilent = 0;
					}
				} else {
					if (!notsilent) {
						/* Heard some audio, mark the begining of the token */
						gettimeofday(&start, NULL);
						ast_log(LOG_DEBUG, "Start of voice token!\n");
						notsilent = 1;
					}
				}						
			}
			ast_frfree(fr);
		}
	} else
		ast_log(LOG_WARNING, "Could not answer channel '%s'\n", ast_channel_name(chan));
	
	if (res > -1) {
		if (origrformat && ast_set_read_format(chan, origrformat)) {
			ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", 
				ast_channel_name(chan), ast_getformatname(origrformat));
		}
	}
	
	if (dsp)
		ast_dsp_free(dsp);
	
	//	LOCAL_USER_REMOVE(u);
	ast_format_cap_destroy(cap);
	return res;
}
Exemplo n.º 30
0
static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
{
	struct timeval now;
	long elapsed_seconds = 0;
	int hour = 0, min = 0, sec = 0;
	char nf[256];
	char cgrp[256];
	char pgrp[256];
	struct ast_str *write_transpath = ast_str_alloca(256);
	struct ast_str *read_transpath = ast_str_alloca(256);

	now = ast_tvnow();
	memset(buf, 0, size);
	if (!c)
		return 0;

	if (ast_channel_cdr(c)) {
		elapsed_seconds = now.tv_sec - ast_channel_cdr(c)->start.tv_sec;
		hour = elapsed_seconds / 3600;
		min = (elapsed_seconds % 3600) / 60;
		sec = elapsed_seconds % 60;
	}

	snprintf(buf,size,
		"Name=               %s\n"
		"Type=               %s\n"
		"UniqueID=           %s\n"
		"LinkedID=           %s\n"
		"CallerIDNum=        %s\n"
		"CallerIDName=       %s\n"
		"ConnectedLineIDNum= %s\n"
		"ConnectedLineIDName=%s\n"
		"DNIDDigits=         %s\n"
		"RDNIS=              %s\n"
		"Parkinglot=         %s\n"
		"Language=           %s\n"
		"State=              %s (%d)\n"
		"Rings=              %d\n"
		"NativeFormat=       %s\n"
		"WriteFormat=        %s\n"
		"ReadFormat=         %s\n"
		"RawWriteFormat=     %s\n"
		"RawReadFormat=      %s\n"
		"WriteTranscode=     %s %s\n"
		"ReadTranscode=      %s %s\n"
		"1stFileDescriptor=  %d\n"
		"Framesin=           %d %s\n"
		"Framesout=          %d %s\n"
		"TimetoHangup=       %ld\n"
		"ElapsedTime=        %dh%dm%ds\n"
		"DirectBridge=       %s\n"
		"IndirectBridge=     %s\n"
		"Context=            %s\n"
		"Extension=          %s\n"
		"Priority=           %d\n"
		"CallGroup=          %s\n"
		"PickupGroup=        %s\n"
		"Application=        %s\n"
		"Data=               %s\n"
		"Blocking_in=        %s\n",
		ast_channel_name(c),
		ast_channel_tech(c)->type,
		ast_channel_uniqueid(c),
		ast_channel_linkedid(c),
		S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, "(N/A)"),
		S_COR(ast_channel_caller(c)->id.name.valid, ast_channel_caller(c)->id.name.str, "(N/A)"),
		S_COR(ast_channel_connected(c)->id.number.valid, ast_channel_connected(c)->id.number.str, "(N/A)"),
		S_COR(ast_channel_connected(c)->id.name.valid, ast_channel_connected(c)->id.name.str, "(N/A)"),
		S_OR(ast_channel_dialed(c)->number.str, "(N/A)"),
		S_COR(ast_channel_redirecting(c)->from.number.valid, ast_channel_redirecting(c)->from.number.str, "(N/A)"),
		ast_channel_parkinglot(c),
		ast_channel_language(c),
		ast_state2str(ast_channel_state(c)),
		ast_channel_state(c),
		ast_channel_rings(c),
		ast_getformatname_multiple(nf, sizeof(nf), ast_channel_nativeformats(c)),
		ast_getformatname(ast_channel_writeformat(c)),
		ast_getformatname(ast_channel_readformat(c)),
		ast_getformatname(ast_channel_rawwriteformat(c)),
		ast_getformatname(ast_channel_rawreadformat(c)),
		ast_channel_writetrans(c) ? "Yes" : "No",
		ast_translate_path_to_str(ast_channel_writetrans(c), &write_transpath),
		ast_channel_readtrans(c) ? "Yes" : "No",
		ast_translate_path_to_str(ast_channel_readtrans(c), &read_transpath),
		ast_channel_fd(c, 0),
		ast_channel_fin(c) & ~DEBUGCHAN_FLAG, (ast_channel_fin(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
		ast_channel_fout(c) & ~DEBUGCHAN_FLAG, (ast_channel_fout(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
		(long)ast_channel_whentohangup(c)->tv_sec,
		hour,
		min,
		sec,
		ast_channel_internal_bridged_channel(c) ? ast_channel_name(ast_channel_internal_bridged_channel(c)) : "<none>",
		ast_bridged_channel(c) ? ast_channel_name(ast_bridged_channel(c)) : "<none>",
		ast_channel_context(c),
		ast_channel_exten(c),
		ast_channel_priority(c),
		ast_print_group(cgrp, sizeof(cgrp), ast_channel_callgroup(c)),
		ast_print_group(pgrp, sizeof(pgrp), ast_channel_pickupgroup(c)),
		ast_channel_appl(c) ? ast_channel_appl(c) : "(N/A)",
		ast_channel_data(c) ? S_OR(ast_channel_data(c), "(Empty)") : "(None)",
		(ast_test_flag(ast_channel_flags(c), AST_FLAG_BLOCKING) ? ast_channel_blockproc(c) : "(Not Blocking)"));

	return 0;
}