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; int res = 0;
struct localuser *u; struct localuser *u;
struct ast_frame *f; struct ast_frame *f;
struct ast_channel *trans; int oreadformat;
if (!data) { if (!data) {
ast_log(LOG_WARNING, "Playback requires an argument (filename)\n"); ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
return -1; return -1;
} }
LOCAL_USER_ADD(u); LOCAL_USER_ADD(u);
/* See if we need a translator */ /* Remember original read format */
if (!(chan->format & AST_FORMAT_SLINEAR)) oreadformat = chan->readformat;
trans = ast_translator_create(chan, AST_FORMAT_SLINEAR, AST_DIRECTION_IN); /* Set mode to signed linear */
else res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
trans = chan; if (res < 0) {
if (trans) { ast_log(LOG_WARNING, "Unable to set format to signed linear on channel %s\n", chan->name);
/* Read packets from the channel */ return -1;
while(!res) { }
res = ast_waitfor(trans, -1); /* Read packets from the channel */
if (res > 0) { while(!res) {
res = 0; res = ast_waitfor(chan, -1);
f = ast_read(trans); if (res > 0) {
if (f) { res = 0;
if (f->frametype == AST_FRAME_DTMF) { f = ast_read(chan);
ast_frfree(f); if (f) {
break; if (f->frametype == AST_FRAME_DTMF) {
} 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); ast_frfree(f);
} else break;
res = -1; } 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); LOCAL_USER_REMOVE(u);
if (!res)
ast_set_read_format(chan, oreadformat);
return res; return res;
} }
@ -187,3 +187,8 @@ int usecount(void)
STANDARD_USECOUNT(res); STANDARD_USECOUNT(res);
return 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; int res=0;
struct localuser *u; struct localuser *u;
struct ast_channel *trans;
int fds[2]; int fds[2];
int rfds[2]; int rfds[2];
int ms = -1; int ms = -1;
int pid; int pid;
int us; int us;
int exception;
int owriteformat;
struct timeval tv; struct timeval tv;
struct timeval last; struct timeval last;
struct ast_frame *f; struct ast_frame *f;
@ -85,87 +86,90 @@ static int mp3_exec(struct ast_channel *chan, void *data)
} }
LOCAL_USER_ADD(u); LOCAL_USER_ADD(u);
ast_stopstream(chan); ast_stopstream(chan);
if (chan->format & AST_FORMAT_SLINEAR)
trans = chan; owriteformat = chan->writeformat;
else res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
trans = ast_translator_create(chan, AST_FORMAT_SLINEAR, AST_DIRECTION_OUT); if (res < 0) {
if (trans) { ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
res = mp3play((char *)data, fds[1]); return -1;
if (res >= 0) { }
pid = res;
/* Order is important -- there's almost always going to be mp3... we want to prioritize the res = mp3play((char *)data, fds[1]);
user */ if (res >= 0) {
rfds[0] = trans->fd; pid = res;
rfds[1] = fds[0]; /* Order is important -- there's almost always going to be mp3... we want to prioritize the
for (;;) { user */
CHECK_BLOCKING(trans); rfds[0] = chan->fd;
res = ast_waitfor_n_fd(rfds, 2, &ms); rfds[1] = fds[0];
trans->blocking = 0; for (;;) {
if (res < 1) { CHECK_BLOCKING(chan);
ast_log(LOG_DEBUG, "Hangup detected\n"); res = ast_waitfor_n_fd(rfds, 2, &ms, &exception);
res = -1; chan->blocking = 0;
break; if (res < 1) {
} else if (res == trans->fd) { ast_log(LOG_DEBUG, "Hangup detected\n");
f = ast_read(trans); res = -1;
if (!f) { break;
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n"); } else if (res == chan->fd) {
res = -1; if (exception)
break; chan->exception = 1;
} f = ast_read(chan);
if (f->frametype == AST_FRAME_DTMF) { if (!f) {
ast_log(LOG_DEBUG, "User pressed a key\n"); ast_log(LOG_DEBUG, "Null frame == hangup() detected\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");
res = -1; res = -1;
break; 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) kill(pid, SIGTERM);
ast_translator_destroy(trans); }
} else
ast_log(LOG_WARNING, "No translator channel available\n");
close(fds[0]); close(fds[0]);
close(fds[1]); close(fds[1]);
LOCAL_USER_REMOVE(u); LOCAL_USER_REMOVE(u);
if (!res)
ast_set_write_format(chan, owriteformat);
return res; return res;
} }
@ -191,3 +195,8 @@ int usecount(void)
STANDARD_USECOUNT(res); STANDARD_USECOUNT(res);
return 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); 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)) { if (!ast_streamfile(chan, "vm-instructions", chan->language)) {
for(;;) { for(;;) {
if (chan->stream || (chan->trans && chan->trans->stream)) { if (chan->stream) {
d = ast_waitstream(chan, AST_DIGIT_ANY); d = ast_waitstream(chan, AST_DIGIT_ANY);
ast_stopstream(chan); ast_stopstream(chan);
if (!d && (state == STATE_MESSAGE_PLAYING)) { if (!d && (state == STATE_MESSAGE_PLAYING)) {
@ -616,3 +616,8 @@ int usecount(void)
STANDARD_USECOUNT(res); STANDARD_USECOUNT(res);
return 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; timeout *= 1000;
strncpy(p->response, "(No Response)", sizeof(p->response)); strncpy(p->response, "(No Response)", sizeof(p->response));
do { do {
res = ast_waitfor_n_fd(&p->fd, 1, &timeout); res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
if (res < 0) { if (res < 0) {
return -1; return -1;
} }
@ -244,7 +244,7 @@ int ast_modem_expect(struct ast_modem_pvt *p, char *result, int timeout)
timeout *= 1000; timeout *= 1000;
strncpy(p->response, "(No Response)", sizeof(p->response)); strncpy(p->response, "(No Response)", sizeof(p->response));
do { do {
res = ast_waitfor_n_fd(&p->fd, 1, &timeout); res = ast_waitfor_n_fd(&p->fd, 1, &timeout, NULL);
if (res < 0) { if (res < 0) {
return -1; 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); snprintf(tmp->name, sizeof(tmp->name), "Modem[%s]/%s", i->mc->name, i->dev + 5);
tmp->type = type; tmp->type = type;
tmp->fd = i->fd; tmp->fd = i->fd;
tmp->format = i->mc->formats; tmp->nativeformats = i->mc->formats;
tmp->state = state; tmp->state = state;
if (state == AST_STATE_RING) if (state == AST_STATE_RING)
tmp->rings = 1; tmp->rings = 1;
@ -855,3 +855,8 @@ char *description()
return desc; 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; p = ast->pvt->pvt;
ioctl(p->fd, PHONE_CPT_STOP); ioctl(p->fd, PHONE_CPT_STOP);
/* Nothing to answering really, just start recording */ /* Nothing to answering really, just start recording */
if (ast->format & AST_FORMAT_G723_1) { if (ast->pvt->rawreadformat == AST_FORMAT_G723_1) {
/* Prefer g723 */ /* Prefer g723 */
ioctl(p->fd, PHONE_REC_STOP); ioctl(p->fd, PHONE_REC_STOP);
if (p->lastinput != AST_FORMAT_G723_1) { if (p->lastinput != AST_FORMAT_G723_1) {
@ -217,7 +217,7 @@ static int phone_setup(struct ast_channel *ast)
return -1; return -1;
} }
} }
} else if (ast->format & AST_FORMAT_SLINEAR) { } else if (ast->pvt->rawreadformat == AST_FORMAT_SLINEAR) {
ioctl(p->fd, PHONE_REC_STOP); ioctl(p->fd, PHONE_REC_STOP);
if (p->lastinput != AST_FORMAT_SLINEAR) { if (p->lastinput != AST_FORMAT_SLINEAR) {
p->lastinput = AST_FORMAT_SLINEAR; p->lastinput = AST_FORMAT_SLINEAR;
@ -227,7 +227,7 @@ static int phone_setup(struct ast_channel *ast)
} }
} }
} else { } 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; return -1;
} }
if (ioctl(p->fd, PHONE_REC_START)) { if (ioctl(p->fd, PHONE_REC_START)) {
@ -268,7 +268,7 @@ static char phone_2digit(char c)
return '?'; return '?';
} }
static struct ast_frame *phone_read(struct ast_channel *ast) static struct ast_frame *phone_exception(struct ast_channel *ast)
{ {
int res; int res;
union telephony_exception phonee; 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); phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);
if (phonee.bits.dtmf_ready) { if (phonee.bits.dtmf_ready) {
if (option_debug) 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 */ /* We've got a digit -- Just handle this nicely and easily */
digit = ioctl(p->fd, PHONE_GET_DTMF_ASCII); 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) if (phonee.bits.pstn_wink)
ast_verbose("Detected Wink\n"); ast_verbose("Detected Wink\n");
#endif #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... */ /* Try to read some data... */
CHECK_BLOCKING(ast); CHECK_BLOCKING(ast);
res = read(p->fd, p->buf, PHONE_MAX_BUF); 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->type = type;
tmp->fd = i->fd; tmp->fd = i->fd;
/* XXX Switching formats silently causes kernel panics XXX */ /* XXX Switching formats silently causes kernel panics XXX */
tmp->format = prefformat; tmp->nativeformats = prefformat;
tmp->state = state; tmp->state = state;
if (state == AST_STATE_RING) if (state == AST_STATE_RING)
tmp->rings = 1; 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->answer = phone_answer;
tmp->pvt->read = phone_read; tmp->pvt->read = phone_read;
tmp->pvt->write = phone_write; tmp->pvt->write = phone_write;
tmp->pvt->exception = phone_exception;
strncpy(tmp->context, context, sizeof(tmp->context)); strncpy(tmp->context, context, sizeof(tmp->context));
if (strlen(i->ext)) if (strlen(i->ext))
strncpy(tmp->exten, i->ext, sizeof(tmp->exten)); strncpy(tmp->exten, i->ext, sizeof(tmp->exten));
@ -1052,3 +1072,7 @@ char *description()
return desc; 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->type = type;
tmp->fd = i->s; tmp->fd = i->s;
/* Adtran VoFR supports only G723.1 format data. G711 (ulaw) would be nice too */ /* 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; tmp->state = state;
if (state == AST_STATE_RING) if (state == AST_STATE_RING)
tmp->rings = 1; tmp->rings = 1;
@ -1241,6 +1241,11 @@ int usecount()
return res; return res;
} }
char *key()
{
return ASTERISK_GPL_KEY;
}
char *description() char *description()
{ {
return desc; return desc;

12
cli.c
View File

@ -168,13 +168,13 @@ static int handle_showchan(int fd, int argc, char *argv[])
" -- General --\n" " -- General --\n"
" Name: %s\n" " Name: %s\n"
" Type: %s\n" " Type: %s\n"
" Translator: %s\n"
" Master: %s\n"
" Caller ID: %s\n" " Caller ID: %s\n"
" DNID Digits: %s\n" " DNID Digits: %s\n"
" State: %d\n" " State: %d\n"
" Rings: %d\n" " Rings: %d\n"
" Format: %d\n" " WriteFormat: %d\n"
" ReadFormat: %d\n"
" NativeFormat: %d\n"
"File Descriptor: %d\n" "File Descriptor: %d\n"
" -- PBX --\n" " -- PBX --\n"
" Context: %s\n" " Context: %s\n"
@ -184,9 +184,9 @@ static int handle_showchan(int fd, int argc, char *argv[])
" Data: %s\n" " Data: %s\n"
" Stack: %d\n" " Stack: %d\n"
" Blocking in: %s\n", " Blocking in: %s\n",
c->name, c->type, (c->trans ? c->trans->name : "(N/A)"), c->name, c->type,
(c->master ? c->master->name : "(N/A)"), (c->callerid ? c->callerid : "(N/A)"), (c->callerid ? c->callerid : "(N/A)"),
(c->dnid ? c->dnid : "(N/A)" ), c->state, c->rings, c->format, (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->fd, c->context, c->exten, c->priority, ( c->appl ? c->appl : "(N/A)" ),
( c-> data ? (strlen(c->data) ? c->data : "(Empty)") : "(None)"), ( c-> data ? (strlen(c->data) ? c->data : "(Empty)") : "(None)"),
c->stack, (c->blocking ? c->blockproc : "(Not Blocking)")); 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) int ast_stopstream(struct ast_channel *tmp)
{ {
if (tmp->trans)
tmp = tmp->trans;
/* Stop a running stream if there is one */ /* Stop a running stream if there is one */
if (!tmp->stream) if (!tmp->stream)
return 0; return 0;
tmp->stream->fmt->close(tmp->stream); tmp->stream->fmt->close(tmp->stream);
if (tmp->master) { if (ast_set_write_format(tmp, tmp->oldwriteformat))
ast_translator_destroy(tmp); ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat);
}
return 0; return 0;
} }
int ast_closestream(struct ast_filestream *f) int ast_closestream(struct ast_filestream *f)
{ {
if (f->trans) {
ast_translator_free_path(f->trans);
}
/* Stop a running stream if there is one */ /* Stop a running stream if there is one */
f->fmt->close(f); f->fmt->close(f);
return 0; return 0;
@ -166,7 +160,7 @@ int ast_closestream(struct ast_filestream *f)
int ast_writestream(struct ast_filestream *fs, struct ast_frame *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; int res = -1;
if (f->frametype != AST_FRAME_VOICE) { if (f->frametype != AST_FRAME_VOICE) {
ast_log(LOG_WARNING, "Tried to write non-voice frame\n"); 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 /* 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 */ the one we've setup a translator for, we do the "wrong thing" XXX */
if (!fs->trans) 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) if (!fs->trans)
ast_log(LOG_WARNING, "Unable to translate to format %s, source format %d\n", fs->fmt->name, f->subclass); ast_log(LOG_WARNING, "Unable to translate to format %s, source format %d\n", fs->fmt->name, f->subclass);
else { else {
res = 0; res = 0;
/* Build a chain of translated frames */ /* Get the translated frame but don't consume the original in case they're using it on another stream */
fc = ast_translate(fs->trans, f); trf = ast_translate(fs->trans, f, 0);
f2 = fc; res = fs->fmt->write(fs, trf);
while(f2) { if (res)
res = fs->fmt->write(fs, f2->fr); ast_log(LOG_WARNING, "Translated frame write failed\n");
if (res) {
ast_log(LOG_WARNING, "Translated frame write failed\n");
break;
}
f2 = f2->next;
}
if (fc)
ast_frchain(fc);
} }
return res; return res;
} }
@ -232,7 +218,7 @@ static int ast_filehelper(char *filename, char *filename2, char *fmt, int action
struct ast_filestream *s; struct ast_filestream *s;
int res=0, ret = 0; int res=0, ret = 0;
char *ext=NULL, *exts, *fn, *nfn; 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 */ /* Start with negative response */
if (action == ACTION_EXISTS) 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"); ast_log(LOG_WARNING, "Out of memory\n");
break; break;
case ACTION_OPEN: case ACTION_OPEN:
if ((ret < 0) && ((trans->format & f->format) /* == trans->format */)) { if ((ret < 0) && ((chan->writeformat & f->format))) {
ret = open(fn, O_RDONLY); ret = open(fn, O_RDONLY);
if (ret >= 0) { if (ret >= 0) {
s = f->open(ret); s = f->open(ret);
if (s) { if (s) {
s->fmt = f; s->fmt = f;
s->trans = NULL; s->trans = NULL;
trans->stream = s; chan->stream = s;
if (f->apply(trans, s)) { if (f->apply(chan, s)) {
f->close(s); f->close(s);
trans->stream = NULL; chan->stream = NULL;
ast_log(LOG_WARNING, "Unable to apply stream to channel %s\n", trans->name); ast_log(LOG_WARNING, "Unable to apply stream to channel %s\n", chan->name);
close(ret); close(ret);
ret = 0; ret = 0;
} }
@ -372,10 +358,10 @@ int ast_streamfile(struct ast_channel *chan, char *filename, char *preflang)
*/ */
int fd = -1; int fd = -1;
struct ast_channel *trans;
int fmts = -1; int fmts = -1;
char filename2[256]; char filename2[256];
char lang2[MAX_LANGUAGE]; char lang2[MAX_LANGUAGE];
int res;
ast_stopstream(chan); ast_stopstream(chan);
if (preflang && strlen(preflang)) { if (preflang && strlen(preflang)) {
snprintf(filename2, sizeof(filename2), "%s-%s", filename, 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); ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
return -1; return -1;
} }
if (fmts & chan->format) { chan->oldwriteformat = chan->writeformat;
/* No translation necessary -- we have a file in a format our channel can /* Set the channel to a format we can work with */
handle */ res = ast_set_write_format(chan, fmts);
trans = chan;
} else { fd = ast_filehelper(filename2, (char *)chan, NULL, ACTION_OPEN);
/* 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);
if (fd >= 0) { if (fd >= 0) {
#if 1 #if 1
if (option_verbose > 2) if (option_verbose > 2)
@ -419,9 +392,7 @@ int ast_streamfile(struct ast_channel *chan, char *filename, char *preflang)
#endif #endif
return 0; return 0;
} }
ast_log(LOG_WARNING, "Unable to open %s (format %d): %s\n", filename, chan->format, strerror(errno)); ast_log(LOG_WARNING, "Unable to open %s (format %d): %s\n", filename, chan->nativeformats, strerror(errno));
if (chan != trans)
ast_translator_destroy(trans);
return -1; return -1;
} }
@ -473,12 +444,10 @@ char ast_waitstream(struct ast_channel *c, char *breakon)
{ {
int res; int res;
struct ast_frame *fr; struct ast_frame *fr;
if (c->trans)
c=c->trans;
while(c->stream) { while(c->stream) {
res = ast_sched_wait(c->sched); res = ast_sched_wait(c->sched);
if (res < 0) { if (res < 0) {
/* Okay, stop :) */ ast_closestream(c->stream);
return 0; return 0;
} }
res = ast_waitfor(c, res); res = ast_waitfor(c, res);

View File

@ -36,27 +36,37 @@ extern "C" {
struct ast_channel { struct ast_channel {
char name[AST_CHANNEL_NAME]; /* ASCII Description of channel name */ char name[AST_CHANNEL_NAME]; /* ASCII Description of channel name */
char language[MAX_LANGUAGE]; /* Language requested */ 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_t blocker; /* If anyone is blocking, this is them */
pthread_mutex_t lock; /* Lock, can be used to lock a channel for some operations */ pthread_mutex_t lock; /* Lock, can be used to lock a channel for some operations */
char *blockproc; /* Procedure causing blocking */ char *blockproc; /* Procedure causing blocking */
char *appl; /* Current application */ char *appl; /* Current application */
char *data; /* Data passed to 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 */ struct sched_context *sched; /* Schedule context */
int streamid; /* For streaming playback, the schedule ID */ int streamid; /* For streaming playback, the schedule ID */
struct ast_filestream *stream; /* Stream itself. */ struct ast_filestream *stream; /* Stream itself. */
struct ast_channel *trans; /* Translator if present */ int oldwriteformat; /* Original writer format */
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 state; /* State of line */ int state; /* State of line */
int rings; /* Number of rings so far */ int rings; /* Number of rings so far */
int stack; /* Current level of application */ int stack; /* Current level of application */
int format; /* Kinds of data this channel can
int nativeformats; /* Kinds of data this channel can
natively handle */ natively handle */
int readformat; /* Requested read format */
int writeformat; /* Requested write format */
char *dnid; /* Malloc'd Dialed Number Identifier */ char *dnid; /* Malloc'd Dialed Number Identifier */
char *callerid; /* Malloc'd Caller ID */ char *callerid; /* Malloc'd Caller ID */
char context[AST_MAX_EXTENSION]; /* Current extension context */ char context[AST_MAX_EXTENSION]; /* Current extension context */
char exten[AST_MAX_EXTENSION]; /* Current extension number */ char exten[AST_MAX_EXTENSION]; /* Current extension number */
int priority; /* Current extension priority */ 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); 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. */ /* 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 /* 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 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 */ /* Write a frame to a channel */
int ast_write(struct ast_channel *chan, struct ast_frame *frame); 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 */ /* Write text to a display on a channel */
int ast_sendtext(struct ast_channel *chan, char *text); 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 digits "timeout" (-1 for none), terminated by anything in "enders". Give them rtimeout
for the first digit */ for the first digit */
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders); 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) { \ #define CHECK_BLOCKING(c) { \
if ((c)->blocking) {\ if ((c)->blocking) {\
ast_log(LOG_WARNING, "Blocking '%s', already blocked by thread %ld in procedure %s\n", (c)->name, (c)->blocker, (c)->blockproc); \ 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); \
/* *((int *)0)=0; */ \ CRASH; \
} else { \ } else { \
(c)->blocker = pthread_self(); \ (c)->blocker = pthread_self(); \
(c)->blockproc = __PRETTY_FUNCTION__; \ (c)->blockproc = __PRETTY_FUNCTION__; \

View File

@ -24,6 +24,14 @@ extern "C" {
struct ast_channel_pvt { struct ast_channel_pvt {
/* Private data used by channel backend */ /* Private data used by channel backend */
void *pvt; 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 */ /* Send a literal DTMF digit */
int (*send_digit)(struct ast_channel *chan, char digit); int (*send_digit)(struct ast_channel *chan, char digit);
/* Call a given phone number (address, etc), but don't /* 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); int (*write)(struct ast_channel *chan, struct ast_frame *frame);
/* Display or transmit text */ /* Display or transmit text */
int (*send_text)(struct ast_channel *chan, char *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 */ /* Create a channel structure */

View File

@ -29,7 +29,7 @@ struct ast_translator {
char name[80]; char name[80];
int srcfmt; int srcfmt;
int dstfmt; int dstfmt;
struct ast_translator_pvt *(*new)(); struct ast_translator_pvt *(*new)(void);
int (*framein)(struct ast_translator_pvt *pvt, struct ast_frame *in); int (*framein)(struct ast_translator_pvt *pvt, struct ast_frame *in);
struct ast_frame * (*frameout)(struct ast_translator_pvt *pvt); struct ast_frame * (*frameout)(struct ast_translator_pvt *pvt);
void (*destroy)(struct ast_translator_pvt *pvt); void (*destroy)(struct ast_translator_pvt *pvt);
@ -44,29 +44,22 @@ struct ast_translator {
struct ast_trans_pvt; 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 */ /* Register a Codec translator */
extern int ast_register_translator(struct ast_translator *t); extern int ast_register_translator(struct ast_translator *t);
/* Unregister same */ /* Unregister same */
extern int ast_unregister_translator(struct ast_translator *t); extern int ast_unregister_translator(struct ast_translator *t);
/* Given a list of sources, and a designed destination format, which should /* Given a list of sources, and a designed destination format, which should
I choose? */ I choose? Returns 0 on success, -1 if no path could be found. Modifies
extern int ast_translator_best_choice(int dst, int srcs); dests and srcs in place */
extern struct ast_trans_pvt *ast_translator_build_path(int source, int dest); 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 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) #if defined(__cplusplus) || defined(c_plusplus)