Version 0.1.10 from FTP
[asterisk/asterisk.git] / file.c
diff --git a/file.c b/file.c
index be82f91..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)
 {
 
 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);
        /* 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)
 {
        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;
        /* Stop a running stream if there is one */
        f->fmt->close(f);
        return 0;
@@ -166,35 +160,33 @@ 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;
        if (f->frametype != AST_FRAME_VOICE) {
                ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
                return -1;
        }
        int res = -1;
        if (f->frametype != AST_FRAME_VOICE) {
                ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
                return -1;
        }
-       if ((fs->fmt->format & f->subclass) == f->subclass)
-               return fs->fmt->write(fs, f);
-       else {
+       if ((fs->fmt->format & f->subclass) == f->subclass) {
+               res =  fs->fmt->write(fs, f);
+               if (res < 0) 
+                       ast_log(LOG_WARNING, "Natural write failed\n");
+               if (res > 0)
+                       ast_log(LOG_WARNING, "Huh??\n");
+               return res;
+       } else {
                /* 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) 
                /* 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 {
                if (!fs->trans)
                        ast_log(LOG_WARNING, "Unable to translate to format %s, source format %d\n", fs->fmt->name, f->subclass);
                else {
-                       /* 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, "Frame write failed\n");
-                                       break;
-                               }
-                               f2 = f2->next;
-                       }
-                       if (fc)
-                               ast_frchain(fc);
+                       res = 0;
+                       /* 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;
        }
                }
                return res;
        }
@@ -226,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_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)
        
        /* Start with negative response */
        if (action == ACTION_EXISTS)
@@ -274,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:
                                                                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;
                                                                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);
                                                                                        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;
                                                                                }
                                                                                        close(ret);
                                                                                        ret = 0;
                                                                                }
@@ -318,9 +310,27 @@ static int ast_filehelper(char *filename, char *filename2, char *fmt, int action
        return res;
 }
 
        return res;
 }
 
-int ast_fileexists(char *filename, char *fmt)
+int ast_fileexists(char *filename, char *fmt, char *preflang)
 {
 {
-       return ast_filehelper(filename, NULL, fmt, ACTION_EXISTS);
+       char filename2[256];
+       char lang2[MAX_LANGUAGE];
+       int res = -1;
+       if (preflang && strlen(preflang)) {
+               snprintf(filename2, sizeof(filename2), "%s-%s", filename, preflang);
+               res = ast_filehelper(filename2, NULL, fmt, ACTION_EXISTS);
+               if (res < 1) {
+                       strncpy(lang2, preflang, sizeof(lang2));
+                       strtok(lang2, "_");
+                       if (strcmp(lang2, preflang)) {
+                               snprintf(filename2, sizeof(filename2), "%s-%s", filename, lang2);
+                               res = ast_filehelper(filename2, NULL, fmt, ACTION_EXISTS);
+                       }
+               }
+       }
+       if (res < 1) {
+               res = ast_filehelper(filename, NULL, fmt, ACTION_EXISTS);
+       }
+       return res;
 }
 
 int ast_filedelete(char *filename, char *fmt)
 }
 
 int ast_filedelete(char *filename, char *fmt)
@@ -333,7 +343,7 @@ int ast_filerename(char *filename, char *filename2, char *fmt)
        return ast_filehelper(filename, filename2, fmt, ACTION_RENAME);
 }
 
        return ast_filehelper(filename, filename2, fmt, ACTION_RENAME);
 }
 
-int ast_streamfile(struct ast_channel *chan, char *filename)
+int ast_streamfile(struct ast_channel *chan, char *filename, char *preflang)
 {
        /* This is a fairly complex routine.  Essentially we should do 
           the following:
 {
        /* This is a fairly complex routine.  Essentially we should do 
           the following:
@@ -341,49 +351,48 @@ int ast_streamfile(struct ast_channel *chan, char *filename)
           1) Find which file handlers produce our type of format.
           2) Look for a filename which it can handle.
           3) If we find one, then great.  
           1) Find which file handlers produce our type of format.
           2) Look for a filename which it can handle.
           3) If we find one, then great.  
-          *4) If not, see what files are there
-          *5) See what we can actually support
-          *6) Choose the one with the least costly translator path and
+          4) If not, see what files are there
+          5) See what we can actually support
+          6) Choose the one with the least costly translator path and
               set it up.
                   
               set it up.
                   
-               XXX * = unimplemented XXX
        */
        int fd = -1;
        */
        int fd = -1;
-       struct ast_channel *trans;
-       int fmts;
+       int fmts = -1;
+       char filename2[256];
+       char lang2[MAX_LANGUAGE];
+       int res;
        ast_stopstream(chan);
        ast_stopstream(chan);
-       fmts = ast_fileexists(filename, NULL);
+       if (preflang && strlen(preflang)) {
+               snprintf(filename2, sizeof(filename2), "%s-%s", filename, preflang);
+               fmts = ast_fileexists(filename2, NULL, NULL);
+               if (fmts < 1) {
+                       strncpy(lang2, preflang, sizeof(lang2));
+                       snprintf(filename2, sizeof(filename2), "%s-%s", filename, lang2);
+                       fmts = ast_fileexists(filename2, NULL, NULL);
+               }
+       }
+       if (fmts < 1) {
+               strncpy(filename2, filename, sizeof(filename2));
+               fmts = ast_fileexists(filename2, NULL, NULL);
+       }
        if (fmts < 1) {
                ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
                return -1;
        }
        if (fmts < 1) {
                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(filename, (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 (fd >= 0) {
-#if 0
-               ast_verbose(VERBOSE_PREFIX_3 "Playing '%s'\n", filename);
+#if 1
+               if (option_verbose > 2)
+                       ast_verbose(VERBOSE_PREFIX_3 "Playing '%s'\n", filename2);
 #endif
                return 0;
        }
 #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;
 }
 
        return -1;
 }
 
@@ -435,12 +444,10 @@ char ast_waitstream(struct ast_channel *c, char *breakon)
 {
        int res;
        struct ast_frame *fr;
 {
        int res;
        struct ast_frame *fr;
-       if (c->trans)
-               c=c->trans;
        while(c->stream) {
                res = ast_sched_wait(c->sched);
                if (res < 0) {
        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);
                        return 0;
                }
                res = ast_waitfor(c, res);