Version 0.1.7 from FTP
authorMark Spencer <markster@digium.com>
Sat, 10 Mar 2001 19:12:11 +0000 (19:12 +0000)
committerMark Spencer <markster@digium.com>
Sat, 10 Mar 2001 19:12:11 +0000 (19:12 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@236 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_intercom.c
apps/app_mp3.c
apps/app_voicemail.c
channels/chan_modem.c
channels/chan_phone.c
channels/chan_vofr.c
cli.c
file.c
include/asterisk/channel.h
include/asterisk/channel_pvt.h
include/asterisk/translate.h

index 97b427b..a50b533 100755 (executable)
@@ -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;
+}
index a7e53cf..7b49dc1 100755 (executable)
@@ -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;
+}
index 0106d61..45a6229 100755 (executable)
@@ -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;
+}
index fc45194..247149c 100755 (executable)
@@ -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;
+}
+
index f46083a..b7f82ea 100755 (executable)
@@ -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;
+}
index 6ea76c0..cfd669e 100755 (executable)
@@ -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 fb8d073..aa41b0e 100755 (executable)
--- 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 89ba698..0ab0676 100755 (executable)
--- 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);
index b3ef376..3f7d5e7 100755 (executable)
@@ -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__; \
index 8657d4d..7fc464e 100755 (executable)
@@ -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 */
index a2bcfff..640c579 100755 (executable)
@@ -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)