aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2001-03-10 19:12:11 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2001-03-10 19:12:11 +0000
commitdc884645e6463fb181af816fdea3599713b0bd87 (patch)
treec16bdd5583e05977a7893075e3b541e1a3afa073
parentea452d3fd8f99256d987297e5afa8d1c226b465e (diff)
Version 0.1.7 from FTP
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@236 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-xapps/app_intercom.c73
-rwxr-xr-xapps/app_mp3.c149
-rwxr-xr-xapps/app_voicemail.c7
-rwxr-xr-xchannels/chan_modem.c11
-rwxr-xr-xchannels/chan_phone.c36
-rwxr-xr-xchannels/chan_vofr.c7
-rwxr-xr-xcli.c12
-rwxr-xr-xfile.c77
-rwxr-xr-xinclude/asterisk/channel.h58
-rwxr-xr-xinclude/asterisk/channel_pvt.h12
-rwxr-xr-xinclude/asterisk/translate.h29
11 files changed, 268 insertions, 203 deletions
diff --git a/apps/app_intercom.c b/apps/app_intercom.c
index 97b427ba1..a50b533a2 100755
--- a/apps/app_intercom.c
+++ b/apps/app_intercom.c
@@ -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;
+}
diff --git a/apps/app_mp3.c b/apps/app_mp3.c
index a7e53cff2..7b49dc172 100755
--- a/apps/app_mp3.c
+++ b/apps/app_mp3.c
@@ -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");
+
+ 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;
- } else if (res == trans->fd) {
- f = ast_read(trans);
- if (!f) {
- ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
+ }
+ 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;
}
- 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");
- res = -1;
- break;
+ 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;
+}
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 0106d6168..45a6229f1 100755
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -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;
+}
diff --git a/channels/chan_modem.c b/channels/chan_modem.c
index fc45194d3..247149c26 100755
--- a/channels/chan_modem.c
+++ b/channels/chan_modem.c
@@ -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;
+}
+
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index f46083a58..b7f82ea04 100755
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -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;
+}
diff --git a/channels/chan_vofr.c b/channels/chan_vofr.c
index 6ea76c0d2..cfd669eb0 100755
--- a/channels/chan_vofr.c
+++ b/channels/chan_vofr.c
@@ -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;
diff --git a/cli.c b/cli.c
index fb8d0731e..aa41b0e7a 100755
--- a/cli.c
+++ b/cli.c
@@ -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)"));
diff --git a/file.c b/file.c
index 89ba69836..0ab0676e8 100755
--- a/file.c
+++ b/file.c
@@ -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);
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index b3ef37653..3f7d5e744 100755
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -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__; \
diff --git a/include/asterisk/channel_pvt.h b/include/asterisk/channel_pvt.h
index 8657d4d58..7fc464ebb 100755
--- a/include/asterisk/channel_pvt.h
+++ b/include/asterisk/channel_pvt.h
@@ -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 */
diff --git a/include/asterisk/translate.h b/include/asterisk/translate.h
index a2bcfff19..640c5794d 100755
--- a/include/asterisk/translate.h
+++ b/include/asterisk/translate.h
@@ -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)