dect
/
asterisk
Archived
13
0
Fork 0

Version 0.1.7 from FTP

git-svn-id: http://svn.digium.com/svn/asterisk/trunk@236 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
markster 2001-03-10 19:12:11 +00:00
parent ea452d3fd8
commit dc884645e6
11 changed files with 272 additions and 207 deletions

View File

@ -116,48 +116,48 @@ static int intercom_exec(struct ast_channel *chan, void *data)
int res = 0;
struct localuser *u;
struct ast_frame *f;
struct ast_channel *trans;
int oreadformat;
if (!data) {
ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
return -1;
}
LOCAL_USER_ADD(u);
/* See if we need a translator */
if (!(chan->format & AST_FORMAT_SLINEAR))
trans = ast_translator_create(chan, AST_FORMAT_SLINEAR, AST_DIRECTION_IN);
else
trans = chan;
if (trans) {
/* Read packets from the channel */
while(!res) {
res = ast_waitfor(trans, -1);
if (res > 0) {
res = 0;
f = ast_read(trans);
if (f) {
if (f->frametype == AST_FRAME_DTMF) {
ast_frfree(f);
break;
} else {
if (f->frametype == AST_FRAME_VOICE) {
if (f->subclass == AST_FORMAT_SLINEAR) {
res = write_audio(f->data, f->datalen);
if (res > 0)
res = 0;
} else
ast_log(LOG_DEBUG, "Unable to handle non-signed linear frame (%d)\n", f->subclass);
}
}
/* Remember original read format */
oreadformat = chan->readformat;
/* Set mode to signed linear */
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set format to signed linear on channel %s\n", chan->name);
return -1;
}
/* Read packets from the channel */
while(!res) {
res = ast_waitfor(chan, -1);
if (res > 0) {
res = 0;
f = ast_read(chan);
if (f) {
if (f->frametype == AST_FRAME_DTMF) {
ast_frfree(f);
} else
res = -1;
}
break;
} else {
if (f->frametype == AST_FRAME_VOICE) {
if (f->subclass == AST_FORMAT_SLINEAR) {
res = write_audio(f->data, f->datalen);
if (res > 0)
res = 0;
} else
ast_log(LOG_DEBUG, "Unable to handle non-signed linear frame (%d)\n", f->subclass);
}
}
ast_frfree(f);
} else
res = -1;
}
if (trans != chan)
ast_translator_destroy(trans);
} else
ast_log(LOG_WARNING, "Unable to build translator to signed linear format on '%s'\n", chan->name);
}
LOCAL_USER_REMOVE(u);
if (!res)
ast_set_read_format(chan, oreadformat);
return res;
}
@ -187,3 +187,8 @@ int usecount(void)
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@ -59,12 +59,13 @@ static int mp3_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
struct ast_channel *trans;
int fds[2];
int rfds[2];
int ms = -1;
int pid;
int us;
int exception;
int owriteformat;
struct timeval tv;
struct timeval last;
struct ast_frame *f;
@ -85,87 +86,90 @@ static int mp3_exec(struct ast_channel *chan, void *data)
}
LOCAL_USER_ADD(u);
ast_stopstream(chan);
if (chan->format & AST_FORMAT_SLINEAR)
trans = chan;
else
trans = ast_translator_create(chan, AST_FORMAT_SLINEAR, AST_DIRECTION_OUT);
if (trans) {
res = mp3play((char *)data, fds[1]);
if (res >= 0) {
pid = res;
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
user */
rfds[0] = trans->fd;
rfds[1] = fds[0];
for (;;) {
CHECK_BLOCKING(trans);
res = ast_waitfor_n_fd(rfds, 2, &ms);
trans->blocking = 0;
if (res < 1) {
ast_log(LOG_DEBUG, "Hangup detected\n");
res = -1;
break;
} else if (res == trans->fd) {
f = ast_read(trans);
if (!f) {
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
res = -1;
break;
}
if (f->frametype == AST_FRAME_DTMF) {
ast_log(LOG_DEBUG, "User pressed a key\n");
ast_frfree(f);
res = 0;
break;
}
ast_frfree(f);
} else if (res == fds[0]) {
gettimeofday(&tv, NULL);
if (last.tv_sec || last.tv_usec) {
/* We should wait at least a frame length */
us = sizeof(myf.frdata) / 16 * 1000;
/* Subtract 1,000,000 us for each second late we've passed */
us -= (tv.tv_sec - last.tv_sec) * 1000000;
/* And one for each us late we've passed */
us -= (tv.tv_usec - last.tv_usec);
/* Sleep that long if needed */
if (us > 0)
usleep(us);
}
last = tv;
res = read(fds[0], myf.frdata, sizeof(myf.frdata));
if (res > 0) {
myf.f.frametype = AST_FRAME_VOICE;
myf.f.subclass = AST_FORMAT_SLINEAR;
myf.f.datalen = res;
myf.f.timelen = res / 16;
myf.f.mallocd = 0;
myf.f.offset = AST_FRIENDLY_OFFSET;
myf.f.src = __PRETTY_FUNCTION__;
myf.f.data = myf.frdata;
if (ast_write(trans, &myf.f) < 0) {
res = -1;
break;
}
} else {
ast_log(LOG_DEBUG, "No more mp3\n");
res = 0;
}
} else {
ast_log(LOG_DEBUG, "HuhHHH?\n");
owriteformat = chan->writeformat;
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
return -1;
}
res = mp3play((char *)data, fds[1]);
if (res >= 0) {
pid = res;
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
user */
rfds[0] = chan->fd;
rfds[1] = fds[0];
for (;;) {
CHECK_BLOCKING(chan);
res = ast_waitfor_n_fd(rfds, 2, &ms, &exception);
chan->blocking = 0;
if (res < 1) {
ast_log(LOG_DEBUG, "Hangup detected\n");
res = -1;
break;
} else if (res == chan->fd) {
if (exception)
chan->exception = 1;
f = ast_read(chan);
if (!f) {
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
res = -1;
break;
}
if (f->frametype == AST_FRAME_DTMF) {
ast_log(LOG_DEBUG, "User pressed a key\n");
ast_frfree(f);
res = 0;
break;
}
ast_frfree(f);
} else if (res == fds[0]) {
gettimeofday(&tv, NULL);
if (last.tv_sec || last.tv_usec) {
/* We should wait at least a frame length */
us = sizeof(myf.frdata) / 16 * 1000;
/* Subtract 1,000,000 us for each second late we've passed */
us -= (tv.tv_sec - last.tv_sec) * 1000000;
/* And one for each us late we've passed */
us -= (tv.tv_usec - last.tv_usec);
/* Sleep that long if needed */
if (us > 0)
usleep(us);
}
last = tv;
res = read(fds[0], myf.frdata, sizeof(myf.frdata));
if (res > 0) {
myf.f.frametype = AST_FRAME_VOICE;
myf.f.subclass = AST_FORMAT_SLINEAR;
myf.f.datalen = res;
myf.f.timelen = res / 16;
myf.f.mallocd = 0;
myf.f.offset = AST_FRIENDLY_OFFSET;
myf.f.src = __PRETTY_FUNCTION__;
myf.f.data = myf.frdata;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
break;
}
} else {
ast_log(LOG_DEBUG, "No more mp3\n");
res = 0;
}
} else {
ast_log(LOG_DEBUG, "HuhHHH?\n");
res = -1;
break;
}
kill(pid, SIGTERM);
}
if (trans != chan)
ast_translator_destroy(trans);
} else
ast_log(LOG_WARNING, "No translator channel available\n");
kill(pid, SIGTERM);
}
close(fds[0]);
close(fds[1]);
LOCAL_USER_REMOVE(u);
if (!res)
ast_set_write_format(chan, owriteformat);
return res;
}
@ -191,3 +195,8 @@ int usecount(void)
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@ -418,7 +418,7 @@ static int vm_execmain(struct ast_channel *chan, void *data)
ast_verbose( VERBOSE_PREFIX_3 "User '%s' logged in on channel %s with %d messages\n", username, chan->name, maxmsg);
if (!ast_streamfile(chan, "vm-instructions", chan->language)) {
for(;;) {
if (chan->stream || (chan->trans && chan->trans->stream)) {
if (chan->stream) {
d = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan);
if (!d && (state == STATE_MESSAGE_PLAYING)) {
@ -616,3 +616,8 @@ int usecount(void)
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@ -227,7 +227,7 @@ int ast_modem_read_response(struct ast_modem_pvt *p, int timeout)
timeout *= 1000;
strncpy(p->response, "(No Response)", sizeof(p->response));
do {
res = ast_waitfor_n_fd(&p->fd, 1, &timeout);
res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
if (res < 0) {
return -1;
}
@ -244,7 +244,7 @@ int ast_modem_expect(struct ast_modem_pvt *p, char *result, int timeout)
timeout *= 1000;
strncpy(p->response, "(No Response)", sizeof(p->response));
do {
res = ast_waitfor_n_fd(&p->fd, 1, &timeout);
res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
if (res < 0) {
return -1;
}
@ -432,7 +432,7 @@ struct ast_channel *ast_modem_new(struct ast_modem_pvt *i, int state)
snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5);
tmp->type = type;
tmp->fd = i->fd;
tmp->format = i->mc->formats;
tmp->nativeformats = i->mc->formats;
tmp->state = state;
if (state == AST_STATE_RING)
tmp->rings = 1;
@ -855,3 +855,8 @@ char *description()
return desc;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@ -207,7 +207,7 @@ static int phone_setup(struct ast_channel *ast)
p = ast->pvt->pvt;
ioctl(p->fd, PHONE_CPT_STOP);
/* Nothing to answering really, just start recording */
if (ast->format & AST_FORMAT_G723_1) {
if (ast->pvt->rawreadformat == AST_FORMAT_G723_1) {
/* Prefer g723 */
ioctl(p->fd, PHONE_REC_STOP);
if (p->lastinput != AST_FORMAT_G723_1) {
@ -217,7 +217,7 @@ static int phone_setup(struct ast_channel *ast)
return -1;
}
}
} else if (ast->format & AST_FORMAT_SLINEAR) {
} 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;
@ -227,7 +227,7 @@ static int phone_setup(struct ast_channel *ast)
}
}
} else {
ast_log(LOG_WARNING, "Can't do format %d\n", ast->format);
ast_log(LOG_WARNING, "Can't do format %d\n", ast->pvt->rawreadformat);
return -1;
}
if (ioctl(p->fd, PHONE_REC_START)) {
@ -268,7 +268,7 @@ static char phone_2digit(char c)
return '?';
}
static struct ast_frame *phone_read(struct ast_channel *ast)
static struct ast_frame *phone_exception(struct ast_channel *ast)
{
int res;
union telephony_exception phonee;
@ -286,7 +286,7 @@ static struct ast_frame *phone_read(struct ast_channel *ast)
phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);
if (phonee.bits.dtmf_ready) {
if (option_debug)
ast_log(LOG_DEBUG, "phone_read(): DTMF\n");
ast_log(LOG_DEBUG, "phone_exception(): DTMF\n");
/* We've got a digit -- Just handle this nicely and easily */
digit = ioctl(p->fd, PHONE_GET_DTMF_ASCII);
@ -324,6 +324,25 @@ static struct ast_frame *phone_read(struct ast_channel *ast)
if (phonee.bits.pstn_wink)
ast_verbose("Detected Wink\n");
#endif
/* Strange -- nothing there.. */
p->fr.frametype = AST_FRAME_NULL;
p->fr.subclass = 0;
return &p->fr;
}
static struct ast_frame *phone_read(struct ast_channel *ast)
{
int res;
struct phone_pvt *p = ast->pvt->pvt;
/* Some nice norms */
p->fr.datalen = 0;
p->fr.timelen = 0;
p->fr.data = NULL;
p->fr.src = type;
p->fr.offset = 0;
p->fr.mallocd=0;
/* Try to read some data... */
CHECK_BLOCKING(ast);
res = read(p->fd, p->buf, PHONE_MAX_BUF);
@ -517,7 +536,7 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *conte
tmp->type = type;
tmp->fd = i->fd;
/* XXX Switching formats silently causes kernel panics XXX */
tmp->format = prefformat;
tmp->nativeformats = prefformat;
tmp->state = state;
if (state == AST_STATE_RING)
tmp->rings = 1;
@ -528,6 +547,7 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *conte
tmp->pvt->answer = phone_answer;
tmp->pvt->read = phone_read;
tmp->pvt->write = phone_write;
tmp->pvt->exception = phone_exception;
strncpy(tmp->context, context, sizeof(tmp->context));
if (strlen(i->ext))
strncpy(tmp->exten, i->ext, sizeof(tmp->exten));
@ -1052,3 +1072,7 @@ char *description()
return desc;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@ -795,7 +795,7 @@ static struct ast_channel *vofr_new(struct vofr_pvt *i, int state)
tmp->type = type;
tmp->fd = i->s;
/* Adtran VoFR supports only G723.1 format data. G711 (ulaw) would be nice too */
tmp->format = AST_FORMAT_G723_1;
tmp->nativeformats = AST_FORMAT_G723_1;
tmp->state = state;
if (state == AST_STATE_RING)
tmp->rings = 1;
@ -1241,6 +1241,11 @@ int usecount()
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}
char *description()
{
return desc;

12
cli.c
View File

@ -168,13 +168,13 @@ static int handle_showchan(int fd, int argc, char *argv[])
" -- General --\n"
" Name: %s\n"
" Type: %s\n"
" Translator: %s\n"
" Master: %s\n"
" Caller ID: %s\n"
" DNID Digits: %s\n"
" State: %d\n"
" Rings: %d\n"
" Format: %d\n"
" WriteFormat: %d\n"
" ReadFormat: %d\n"
" NativeFormat: %d\n"
"File Descriptor: %d\n"
" -- PBX --\n"
" Context: %s\n"
@ -184,9 +184,9 @@ static int handle_showchan(int fd, int argc, char *argv[])
" Data: %s\n"
" Stack: %d\n"
" Blocking in: %s\n",
c->name, c->type, (c->trans ? c->trans->name : "(N/A)"),
(c->master ? c->master->name : "(N/A)"), (c->callerid ? c->callerid : "(N/A)"),
(c->dnid ? c->dnid : "(N/A)" ), c->state, c->rings, c->format,
c->name, c->type,
(c->callerid ? c->callerid : "(N/A)"),
(c->dnid ? c->dnid : "(N/A)" ), c->state, c->rings, c->nativeformats, c->writeformat, c->readformat,
c->fd, c->context, c->exten, c->priority, ( c->appl ? c->appl : "(N/A)" ),
( c-> data ? (strlen(c->data) ? c->data : "(Empty)") : "(None)"),
c->stack, (c->blocking ? c->blockproc : "(Not Blocking)"));

77
file.c
View File

@ -142,23 +142,17 @@ int ast_format_unregister(char *name)
int ast_stopstream(struct ast_channel *tmp)
{
if (tmp->trans)
tmp = tmp->trans;
/* Stop a running stream if there is one */
if (!tmp->stream)
return 0;
tmp->stream->fmt->close(tmp->stream);
if (tmp->master) {
ast_translator_destroy(tmp);
}
if (ast_set_write_format(tmp, tmp->oldwriteformat))
ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat);
return 0;
}
int ast_closestream(struct ast_filestream *f)
{
if (f->trans) {
ast_translator_free_path(f->trans);
}
/* Stop a running stream if there is one */
f->fmt->close(f);
return 0;
@ -166,7 +160,7 @@ int ast_closestream(struct ast_filestream *f)
int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
{
struct ast_frame_chain *fc, *f2;
struct ast_frame *trf;
int res = -1;
if (f->frametype != AST_FRAME_VOICE) {
ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
@ -183,24 +177,16 @@ int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
/* XXX If they try to send us a type of frame that isn't the normal frame, and isn't
the one we've setup a translator for, we do the "wrong thing" XXX */
if (!fs->trans)
fs->trans = ast_translator_build_path(f->subclass, fs->fmt->format);
fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass);
if (!fs->trans)
ast_log(LOG_WARNING, "Unable to translate to format %s, source format %d\n", fs->fmt->name, f->subclass);
else {
res = 0;
/* Build a chain of translated frames */
fc = ast_translate(fs->trans, f);
f2 = fc;
while(f2) {
res = fs->fmt->write(fs, f2->fr);
if (res) {
ast_log(LOG_WARNING, "Translated frame write failed\n");
break;
}
f2 = f2->next;
}
if (fc)
ast_frchain(fc);
/* Get the translated frame but don't consume the original in case they're using it on another stream */
trf = ast_translate(fs->trans, f, 0);
res = fs->fmt->write(fs, trf);
if (res)
ast_log(LOG_WARNING, "Translated frame write failed\n");
}
return res;
}
@ -232,7 +218,7 @@ static int ast_filehelper(char *filename, char *filename2, char *fmt, int action
struct ast_filestream *s;
int res=0, ret = 0;
char *ext=NULL, *exts, *fn, *nfn;
struct ast_channel *trans = (struct ast_channel *)filename2;
struct ast_channel *chan = (struct ast_channel *)filename2;
/* Start with negative response */
if (action == ACTION_EXISTS)
@ -280,18 +266,18 @@ static int ast_filehelper(char *filename, char *filename2, char *fmt, int action
ast_log(LOG_WARNING, "Out of memory\n");
break;
case ACTION_OPEN:
if ((ret < 0) && ((trans->format & f->format) /* == trans->format */)) {
if ((ret < 0) && ((chan->writeformat & f->format))) {
ret = open(fn, O_RDONLY);
if (ret >= 0) {
s = f->open(ret);
if (s) {
s->fmt = f;
s->trans = NULL;
trans->stream = s;
if (f->apply(trans, s)) {
chan->stream = s;
if (f->apply(chan, s)) {
f->close(s);
trans->stream = NULL;
ast_log(LOG_WARNING, "Unable to apply stream to channel %s\n", trans->name);
chan->stream = NULL;
ast_log(LOG_WARNING, "Unable to apply stream to channel %s\n", chan->name);
close(ret);
ret = 0;
}
@ -372,10 +358,10 @@ int ast_streamfile(struct ast_channel *chan, char *filename, char *preflang)
*/
int fd = -1;
struct ast_channel *trans;
int fmts = -1;
char filename2[256];
char lang2[MAX_LANGUAGE];
int res;
ast_stopstream(chan);
if (preflang && strlen(preflang)) {
snprintf(filename2, sizeof(filename2), "%s-%s", filename, preflang);
@ -394,24 +380,11 @@ int ast_streamfile(struct ast_channel *chan, char *filename, char *preflang)
ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
return -1;
}
if (fmts & chan->format) {
/* No translation necessary -- we have a file in a format our channel can
handle */
trans = chan;
} else {
/* Find the best */
fmts = ast_translator_best_choice(chan->format, fmts);
if (fmts < 1) {
ast_log(LOG_WARNING, "Unable to find a translator method\n");
return -1;
}
trans = ast_translator_create(chan, fmts, AST_DIRECTION_OUT);
if (!trans) {
ast_log(LOG_WARNING, "Unable to create translator\n");
return -1;
}
}
fd = ast_filehelper(filename2, (char *)trans, NULL, ACTION_OPEN);
chan->oldwriteformat = chan->writeformat;
/* Set the channel to a format we can work with */
res = ast_set_write_format(chan, fmts);
fd = ast_filehelper(filename2, (char *)chan, NULL, ACTION_OPEN);
if (fd >= 0) {
#if 1
if (option_verbose > 2)
@ -419,9 +392,7 @@ int ast_streamfile(struct ast_channel *chan, char *filename, char *preflang)
#endif
return 0;
}
ast_log(LOG_WARNING, "Unable to open %s (format %d): %s\n", filename, chan->format, strerror(errno));
if (chan != trans)
ast_translator_destroy(trans);
ast_log(LOG_WARNING, "Unable to open %s (format %d): %s\n", filename, chan->nativeformats, strerror(errno));
return -1;
}
@ -473,12 +444,10 @@ char ast_waitstream(struct ast_channel *c, char *breakon)
{
int res;
struct ast_frame *fr;
if (c->trans)
c=c->trans;
while(c->stream) {
res = ast_sched_wait(c->sched);
if (res < 0) {
/* Okay, stop :) */
ast_closestream(c->stream);
return 0;
}
res = ast_waitfor(c, res);

View File

@ -36,27 +36,37 @@ extern "C" {
struct ast_channel {
char name[AST_CHANNEL_NAME]; /* ASCII Description of channel name */
char language[MAX_LANGUAGE]; /* Language requested */
char *type; /* Type of channel */
int fd; /* File descriptor for channel -- all must have
a file descriptor! */
int blocking; /* Whether or not we're blocking */
pthread_t blocker; /* If anyone is blocking, this is them */
pthread_mutex_t lock; /* Lock, can be used to lock a channel for some operations */
char *blockproc; /* Procedure causing blocking */
char *appl; /* Current application */
char *data; /* Data passed to current application */
int blocking; /* Whether or not we're blocking */
int exception; /* Has an exception been detected */
struct sched_context *sched; /* Schedule context */
int streamid; /* For streaming playback, the schedule ID */
struct ast_filestream *stream; /* Stream itself. */
struct ast_channel *trans; /* Translator if present */
struct ast_channel *master; /* Master channel, if this is a translator */
int fd; /* File descriptor for channel -- all must have
a file descriptor! */
char *type; /* Type of channel */
int oldwriteformat; /* Original writer format */
int state; /* State of line */
int rings; /* Number of rings so far */
int stack; /* Current level of application */
int format; /* Kinds of data this channel can
int nativeformats; /* Kinds of data this channel can
natively handle */
int readformat; /* Requested read format */
int writeformat; /* Requested write format */
char *dnid; /* Malloc'd Dialed Number Identifier */
char *callerid; /* Malloc'd Caller ID */
char context[AST_MAX_EXTENSION]; /* Current extension context */
char exten[AST_MAX_EXTENSION]; /* Current extension number */
int priority; /* Current extension priority */
@ -125,7 +135,7 @@ int ast_waitfor(struct ast_channel *chan, int ms);
struct ast_channel *ast_waitfor_n(struct ast_channel **chan, int n, int *ms);
/* This version works on fd's only. Be careful with it. */
int ast_waitfor_n_fd(int *fds, int n, int *ms);
int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception);
/* Read a frame. Returns a frame, or NULL on error. If it returns NULL, you
best just stop reading frames and assume the channel has been
@ -135,6 +145,12 @@ struct ast_frame *ast_read(struct ast_channel *chan);
/* Write a frame to a channel */
int ast_write(struct ast_channel *chan, struct ast_frame *frame);
/* Set read format for channelto whichever component of "format" is best. */
int ast_set_read_format(struct ast_channel *chan, int format);
/* Set write format for channel to whichever compoent of "format" is best. */
int ast_set_write_format(struct ast_channel *chan, int format);
/* Write text to a display on a channel */
int ast_sendtext(struct ast_channel *chan, char *text);
@ -148,10 +164,32 @@ char ast_waitfordigit(struct ast_channel *c, int ms);
digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout
for the first digit */
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders);
#define AST_BRIDGE_DTMF_CHANNEL_0 (1 << 0) /* Report DTMF on channel 0 */
#define AST_BRIDGE_DTMF_CHANNEL_1 (1 << 1) /* Report DTMF on channel 1 */
#define AST_BRIDGE_REC_CHANNEL_0 (1 << 2) /* Return all voice frames on channel 0 */
#define AST_BRIDGE_REC_CHANNEL_1 (1 << 3) /* Return all voice frames on channel 1 */
#define AST_BRIDGE_IGNORE_SIGS (1 << 4) /* Ignore all signal frames except NULL */
/* Set two channels to compatible formats -- call before ast_channel_bridge in general . Returns 0 on success
and -1 if it could not be done */
int ast_channel_make_compatible(struct ast_channel *c0, struct ast_channel *c1);
/* Bridge two channels (c0 and c1) together. If an important frame occurs, we return that frame in
*rf (remember, it could be NULL) and which channel (0 or 1) in rc */
int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
#ifdef DO_CRASH
#define CRASH do { *((int *)0) = 0; } while(0)
#else
#define CRASH do { } while(0)
#endif
#define CHECK_BLOCKING(c) { \
if ((c)->blocking) {\
ast_log(LOG_WARNING, "Blocking '%s', already blocked by thread %ld in procedure %s\n", (c)->name, (c)->blocker, (c)->blockproc); \
/* *((int *)0)=0; */ \
ast_log(LOG_WARNING, "Thread %ld Blocking '%s', already blocked by thread %ld in procedure %s\n", pthread_self(), (c)->name, (c)->blocker, (c)->blockproc); \
CRASH; \
} else { \
(c)->blocker = pthread_self(); \
(c)->blockproc = __PRETTY_FUNCTION__; \

View File

@ -24,6 +24,14 @@ extern "C" {
struct ast_channel_pvt {
/* Private data used by channel backend */
void *pvt;
/* Write translation path */
struct ast_trans_pvt *writetrans;
/* Read translation path */
struct ast_trans_pvt *readtrans;
/* Raw read format */
int rawreadformat;
/* Raw write format */
int rawwriteformat;
/* Send a literal DTMF digit */
int (*send_digit)(struct ast_channel *chan, char digit);
/* Call a given phone number (address, etc), but don't
@ -39,6 +47,10 @@ struct ast_channel_pvt {
int (*write)(struct ast_channel *chan, struct ast_frame *frame);
/* Display or transmit text */
int (*send_text)(struct ast_channel *chan, char *text);
/* Handle an exception, reading a frame */
struct ast_frame * (*exception)(struct ast_channel *chan);
/* Bridge two channels of the same type together */
int (*bridge)(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc);
};
/* Create a channel structure */

View File

@ -29,7 +29,7 @@ struct ast_translator {
char name[80];
int srcfmt;
int dstfmt;
struct ast_translator_pvt *(*new)();
struct ast_translator_pvt *(*new)(void);
int (*framein)(struct ast_translator_pvt *pvt, struct ast_frame *in);
struct ast_frame * (*frameout)(struct ast_translator_pvt *pvt);
void (*destroy)(struct ast_translator_pvt *pvt);
@ -44,29 +44,22 @@ struct ast_translator {
struct ast_trans_pvt;
/* Create a pseudo channel which translates from a real channel into our
desired format. When a translator is installed, you should not use the
sub channel until you have stopped the translator. For all other
actions, use the real channel. Generally, translators should be created
when needed and immediately destroyed when no longer needed. */
/* Directions */
#define AST_DIRECTION_OUT 1
#define AST_DIRECTION_IN 2
#define AST_DIRECTION_BOTH 3
extern struct ast_channel *ast_translator_create(struct ast_channel *real, int format, int direction);
extern void ast_translator_destroy(struct ast_channel *tran);
/* Register a Codec translator */
extern int ast_register_translator(struct ast_translator *t);
/* Unregister same */
extern int ast_unregister_translator(struct ast_translator *t);
/* Given a list of sources, and a designed destination format, which should
I choose? */
extern int ast_translator_best_choice(int dst, int srcs);
extern struct ast_trans_pvt *ast_translator_build_path(int source, int dest);
I choose? Returns 0 on success, -1 if no path could be found. Modifies
dests and srcs in place */
extern int ast_translator_best_choice(int *dsts, int *srcs);
/* Build a path (possibly NULL) from source to dest */
extern struct ast_trans_pvt *ast_translator_build_path(int dest, int source);
extern void ast_translator_free_path(struct ast_trans_pvt *tr);
extern struct ast_frame_chain *ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f);
/* Apply an input frame into the translator and receive zero or one output frames. Consume
determines whether the original frame should be freed */
extern struct ast_frame *ast_translate(struct ast_trans_pvt *tr, struct ast_frame *f, int consume);
#if defined(__cplusplus) || defined(c_plusplus)