capitalize dialplan function
[asterisk/asterisk.git] / file.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*
20  *
21  * Generic File Format Support.
22  * 
23  */
24
25 #include <sys/types.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <fcntl.h>
32 #include <dirent.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
40 #include "asterisk/frame.h"
41 #include "asterisk/file.h"
42 #include "asterisk/cli.h"
43 #include "asterisk/logger.h"
44 #include "asterisk/channel.h"
45 #include "asterisk/sched.h"
46 #include "asterisk/options.h"
47 #include "asterisk/translate.h"
48 #include "asterisk/utils.h"
49 #include "asterisk/lock.h"
50 #include "asterisk/app.h"
51 #include "asterisk/pbx.h"
52
53 struct ast_format {
54         /* Name of format */
55         char name[80];
56         /* Extensions (separated by | if more than one) 
57            this format can read.  First is assumed for writing (e.g. .mp3) */
58         char exts[80];
59         /* Format of frames it uses/provides (one only) */
60         int format;
61         /* Open an input stream, and start playback */
62         struct ast_filestream * (*open)(int fd);
63         /* Open an output stream, of a given file descriptor and comment it appropriately if applicable */
64         struct ast_filestream * (*rewrite)(int fd, const char *comment);
65         /* Write a frame to a channel */
66         int (*write)(struct ast_filestream *, struct ast_frame *);
67         /* seek num samples into file, whence(think normal seek) */
68         int (*seek)(struct ast_filestream *, long offset, int whence);
69         /* trunc file to current position */
70         int (*trunc)(struct ast_filestream *fs);
71         /* tell current position */
72         long (*tell)(struct ast_filestream *fs);
73         /* Read the next frame from the filestream (if available) and report when to get next one
74                 (in samples) */
75         struct ast_frame * (*read)(struct ast_filestream *, int *whennext);
76         /* Close file, and destroy filestream structure */
77         void (*close)(struct ast_filestream *);
78         /* Retrieve file comment */
79         char * (*getcomment)(struct ast_filestream *);
80         /* Link */
81         struct ast_format *next;
82 };
83
84 struct ast_filestream {
85         /* Everybody reserves a block of AST_RESERVED_POINTERS pointers for us */
86         struct ast_format *fmt;
87         int flags;
88         mode_t mode;
89         char *filename;
90         char *realfilename;
91         /* Video file stream */
92         struct ast_filestream *vfs;
93         /* Transparently translate from another format -- just once */
94         struct ast_trans_pvt *trans;
95         struct ast_tranlator_pvt *tr;
96         int lastwriteformat;
97         int lasttimeout;
98         struct ast_channel *owner;
99 };
100
101 AST_MUTEX_DEFINE_STATIC(formatlock);
102
103 static struct ast_format *formats = NULL;
104
105 int ast_format_register(const char *name, const char *exts, int format,
106                                                 struct ast_filestream * (*open)(int fd),
107                                                 struct ast_filestream * (*rewrite)(int fd, const char *comment),
108                                                 int (*write)(struct ast_filestream *, struct ast_frame *),
109                                                 int (*seek)(struct ast_filestream *, long sample_offset, int whence),
110                                                 int (*trunc)(struct ast_filestream *),
111                                                 long (*tell)(struct ast_filestream *),
112                                                 struct ast_frame * (*read)(struct ast_filestream *, int *whennext),
113                                                 void (*close)(struct ast_filestream *),
114                                                 char * (*getcomment)(struct ast_filestream *))
115 {
116         struct ast_format *tmp;
117         if (ast_mutex_lock(&formatlock)) {
118                 ast_log(LOG_WARNING, "Unable to lock format list\n");
119                 return -1;
120         }
121         tmp = formats;
122         while(tmp) {
123                 if (!strcasecmp(name, tmp->name)) {
124                         ast_mutex_unlock(&formatlock);
125                         ast_log(LOG_WARNING, "Tried to register '%s' format, already registered\n", name);
126                         return -1;
127                 }
128                 tmp = tmp->next;
129         }
130         tmp = malloc(sizeof(struct ast_format));
131         if (!tmp) {
132                 ast_log(LOG_WARNING, "Out of memory\n");
133                 ast_mutex_unlock(&formatlock);
134                 return -1;
135         }
136         ast_copy_string(tmp->name, name, sizeof(tmp->name));
137         ast_copy_string(tmp->exts, exts, sizeof(tmp->exts));
138         tmp->open = open;
139         tmp->rewrite = rewrite;
140         tmp->read = read;
141         tmp->write = write;
142         tmp->seek = seek;
143         tmp->trunc = trunc;
144         tmp->tell = tell;
145         tmp->close = close;
146         tmp->format = format;
147         tmp->getcomment = getcomment;
148         tmp->next = formats;
149         formats = tmp;
150         ast_mutex_unlock(&formatlock);
151         if (option_verbose > 1)
152                 ast_verbose( VERBOSE_PREFIX_2 "Registered file format %s, extension(s) %s\n", name, exts);
153         return 0;
154 }
155
156 int ast_format_unregister(const char *name)
157 {
158         struct ast_format *tmp, *tmpl = NULL;
159         if (ast_mutex_lock(&formatlock)) {
160                 ast_log(LOG_WARNING, "Unable to lock format list\n");
161                 return -1;
162         }
163         tmp = formats;
164         while(tmp) {
165                 if (!strcasecmp(name, tmp->name)) {
166                         if (tmpl) 
167                                 tmpl->next = tmp->next;
168                         else
169                                 formats = tmp->next;
170                         free(tmp);
171                         ast_mutex_unlock(&formatlock);
172                         if (option_verbose > 1)
173                                 ast_verbose( VERBOSE_PREFIX_2 "Unregistered format %s\n", name);
174                         return 0;
175                 }
176                 tmpl = tmp;
177                 tmp = tmp->next;
178         }
179         ast_log(LOG_WARNING, "Tried to unregister format %s, already unregistered\n", name);
180         return -1;
181 }
182
183 int ast_stopstream(struct ast_channel *tmp)
184 {
185         /* Stop a running stream if there is one */
186         if (tmp->vstream)
187                 ast_closestream(tmp->vstream);
188         if (tmp->stream) {
189                 ast_closestream(tmp->stream);
190                 if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat))
191                         ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat);
192         }
193         return 0;
194 }
195
196 int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
197 {
198         struct ast_frame *trf;
199         int res = -1;
200         int alt=0;
201         if (f->frametype == AST_FRAME_VIDEO) {
202                 if (fs->fmt->format < AST_FORMAT_MAX_AUDIO) {
203                         /* This is the audio portion.  Call the video one... */
204                         if (!fs->vfs && fs->filename) {
205                                 /* XXX Support other video formats XXX */
206                                 const char *type = "h263";
207                                 fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode);
208                                 ast_log(LOG_DEBUG, "Opened video output file\n");
209                         }
210                         if (fs->vfs)
211                                 return ast_writestream(fs->vfs, f);
212                         /* Ignore */
213                         return 0;                               
214                 } else {
215                         /* Might / might not have mark set */
216                         alt = 1;
217                 }
218         } else if (f->frametype != AST_FRAME_VOICE) {
219                 ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
220                 return -1;
221         }
222         if (((fs->fmt->format | alt) & f->subclass) == f->subclass) {
223                 res =  fs->fmt->write(fs, f);
224                 if (res < 0) 
225                         ast_log(LOG_WARNING, "Natural write failed\n");
226                 if (res > 0)
227                         ast_log(LOG_WARNING, "Huh??\n");
228                 return res;
229         } else {
230                 /* XXX If they try to send us a type of frame that isn't the normal frame, and isn't
231                        the one we've setup a translator for, we do the "wrong thing" XXX */
232                 if (fs->trans && (f->subclass != fs->lastwriteformat)) {
233                         ast_translator_free_path(fs->trans);
234                         fs->trans = NULL;
235                 }
236                 if (!fs->trans) 
237                         fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass);
238                 if (!fs->trans)
239                         ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n", fs->fmt->name, ast_getformatname(f->subclass));
240                 else {
241                         fs->lastwriteformat = f->subclass;
242                         res = 0;
243                         /* Get the translated frame but don't consume the original in case they're using it on another stream */
244                         trf = ast_translate(fs->trans, f, 0);
245                         if (trf) {
246                                 res = fs->fmt->write(fs, trf);
247                                 if (res) 
248                                         ast_log(LOG_WARNING, "Translated frame write failed\n");
249                         } else
250                                 res = 0;
251                 }
252                 return res;
253         }
254 }
255
256 static int copy(const char *infile, const char *outfile)
257 {
258         int ifd;
259         int ofd;
260         int res;
261         int len;
262         char buf[4096];
263
264         if ((ifd = open(infile, O_RDONLY)) < 0) {
265                 ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile);
266                 return -1;
267         }
268         if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) {
269                 ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile);
270                 close(ifd);
271                 return -1;
272         }
273         do {
274                 len = read(ifd, buf, sizeof(buf));
275                 if (len < 0) {
276                         ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
277                         close(ifd);
278                         close(ofd);
279                         unlink(outfile);
280                 }
281                 if (len) {
282                         res = write(ofd, buf, len);
283                         if (res != len) {
284                                 ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
285                                 close(ifd);
286                                 close(ofd);
287                                 unlink(outfile);
288                         }
289                 }
290         } while(len);
291         close(ifd);
292         close(ofd);
293         return 0;
294 }
295
296 static char *build_filename(const char *filename, const char *ext)
297 {
298         char *fn, type[16];
299         int fnsize = 0;
300
301         if (!strcmp(ext, "wav49")) {
302                 ast_copy_string(type, "WAV", sizeof(type));
303         } else {
304                 ast_copy_string(type, ext, sizeof(type));
305         }
306
307         if (filename[0] == '/') {
308                 fnsize = strlen(filename) + strlen(type) + 2;
309                 fn = malloc(fnsize);
310                 if (fn)
311                         snprintf(fn, fnsize, "%s.%s", filename, type);
312         } else {
313                 char tmp[AST_CONFIG_MAX_PATH] = "";
314
315                 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_VAR_DIR, "sounds");
316                 fnsize = strlen(tmp) + strlen(filename) + strlen(type) + 3;
317                 fn = malloc(fnsize);
318                 if (fn)
319                         snprintf(fn, fnsize, "%s/%s.%s", tmp, filename, type);
320         }
321
322         return fn;
323 }
324
325 static int exts_compare(const char *exts, const char *type)
326 {
327         char *stringp = NULL, *ext;
328         char tmp[256];
329
330         ast_copy_string(tmp, exts, sizeof(tmp));
331         stringp = tmp;
332         while ((ext = strsep(&stringp, "|"))) {
333                 if (!strcmp(ext, type)) {
334                         return 1;
335                 }
336         }
337
338         return 0;
339 }
340
341 #define ACTION_EXISTS 1
342 #define ACTION_DELETE 2
343 #define ACTION_RENAME 3
344 #define ACTION_OPEN   4
345 #define ACTION_COPY   5
346
347 static int ast_filehelper(const char *filename, const char *filename2, const char *fmt, int action)
348 {
349         struct stat st;
350         struct ast_format *f;
351         struct ast_filestream *s;
352         int res=0, ret = 0;
353         char *ext=NULL, *exts, *fn, *nfn;
354         struct ast_channel *chan = (struct ast_channel *)filename2;
355         
356         /* Start with negative response */
357         if (action == ACTION_EXISTS)
358                 res = 0;
359         else
360                 res = -1;
361         if (action == ACTION_OPEN)
362                 ret = -1;
363         /* Check for a specific format */
364         if (ast_mutex_lock(&formatlock)) {
365                 ast_log(LOG_WARNING, "Unable to lock format list\n");
366                 if (action == ACTION_EXISTS)
367                         return 0;
368                 else
369                         return -1;
370         }
371         f = formats;
372         while(f) {
373                 if (!fmt || exts_compare(f->exts, fmt)) {
374                         char *stringp=NULL;
375                         exts = ast_strdupa(f->exts);
376                         /* Try each kind of extension */
377                         stringp=exts;
378                         ext = strsep(&stringp, "|");
379                         do {
380                                 fn = build_filename(filename, ext);
381                                 if (fn) {
382                                         res = stat(fn, &st);
383                                         if (!res) {
384                                                 switch(action) {
385                                                 case ACTION_EXISTS:
386                                                         ret |= f->format;
387                                                         break;
388                                                 case ACTION_DELETE:
389                                                         res = unlink(fn);
390                                                         if (res)
391                                                                 ast_log(LOG_WARNING, "unlink(%s) failed: %s\n", fn, strerror(errno));
392                                                         break;
393                                                 case ACTION_RENAME:
394                                                         nfn = build_filename(filename2, ext);
395                                                         if (nfn) {
396                                                                 res = rename(fn, nfn);
397                                                                 if (res)
398                                                                         ast_log(LOG_WARNING, "rename(%s,%s) failed: %s\n", fn, nfn, strerror(errno));
399                                                                 free(nfn);
400                                                         } else
401                                                                 ast_log(LOG_WARNING, "Out of memory\n");
402                                                         break;
403                                                 case ACTION_COPY:
404                                                         nfn = build_filename(filename2, ext);
405                                                         if (nfn) {
406                                                                 res = copy(fn, nfn);
407                                                                 if (res)
408                                                                         ast_log(LOG_WARNING, "copy(%s,%s) failed: %s\n", fn, nfn, strerror(errno));
409                                                                 free(nfn);
410                                                         } else
411                                                                 ast_log(LOG_WARNING, "Out of memory\n");
412                                                         break;
413                                                 case ACTION_OPEN:
414                                                         if ((ret < 0) && ((chan->writeformat & f->format) ||
415                                                                                 ((f->format >= AST_FORMAT_MAX_AUDIO) && fmt))) {
416                                                                 ret = open(fn, O_RDONLY);
417                                                                 if (ret >= 0) {
418                                                                         s = f->open(ret);
419                                                                         if (s) {
420                                                                                 s->lasttimeout = -1;
421                                                                                 s->fmt = f;
422                                                                                 s->trans = NULL;
423                                                                                 s->filename = NULL;
424                                                                                 if (s->fmt->format < AST_FORMAT_MAX_AUDIO)
425                                                                                         chan->stream = s;
426                                                                                 else
427                                                                                         chan->vstream = s;
428                                                                         } else {
429                                                                                 close(ret);
430                                                                                 ast_log(LOG_WARNING, "Unable to open fd on %s\n", fn);
431                                                                         }
432                                                                 } else
433                                                                         ast_log(LOG_WARNING, "Couldn't open file %s\n", fn);
434                                                         }
435                                                         break;
436                                                 default:
437                                                         ast_log(LOG_WARNING, "Unknown helper %d\n", action);
438                                                 }
439                                                 /* Conveniently this logic is the same for all */
440                                                 if (res)
441                                                         break;
442                                         }
443                                         free(fn);
444                                 }
445                                 ext = strsep(&stringp, "|");
446                         } while(ext);
447                         
448                 }
449                 f = f->next;
450         }
451         ast_mutex_unlock(&formatlock);
452         if ((action == ACTION_EXISTS) || (action == ACTION_OPEN))
453                 res = ret ? ret : -1;
454         return res;
455 }
456 struct ast_filestream *ast_openstream(struct ast_channel *chan, const char *filename, const char *preflang)
457 {
458         return ast_openstream_full(chan, filename, preflang, 0);
459 }
460
461 struct ast_filestream *ast_openstream_full(struct ast_channel *chan, const char *filename, const char *preflang, int asis)
462 {
463         /* This is a fairly complex routine.  Essentially we should do 
464            the following:
465            
466            1) Find which file handlers produce our type of format.
467            2) Look for a filename which it can handle.
468            3) If we find one, then great.  
469            4) If not, see what files are there
470            5) See what we can actually support
471            6) Choose the one with the least costly translator path and
472                set it up.
473                    
474         */
475         int fd = -1;
476         int fmts = -1;
477         char filename2[256]="";
478         char filename3[256];
479         char *endpart;
480         int res;
481
482         if (!asis) {
483                 /* do this first, otherwise we detect the wrong writeformat */
484                 ast_stopstream(chan);
485                 if (chan->generator)
486                         ast_deactivate_generator(chan);
487         }
488         if (preflang && !ast_strlen_zero(preflang)) {
489                 ast_copy_string(filename3, filename, sizeof(filename3));
490                 endpart = strrchr(filename3, '/');
491                 if (endpart) {
492                         *endpart = '\0';
493                         endpart++;
494                         snprintf(filename2, sizeof(filename2), "%s/%s/%s", filename3, preflang, endpart);
495                 } else
496                         snprintf(filename2, sizeof(filename2), "%s/%s", preflang, filename);
497                 fmts = ast_fileexists(filename2, NULL, NULL);
498         }
499         if (fmts < 1) {
500                 ast_copy_string(filename2, filename, sizeof(filename2));
501                 fmts = ast_fileexists(filename2, NULL, NULL);
502         }
503         if (fmts < 1) {
504                 ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
505                 return NULL;
506         }
507         chan->oldwriteformat = chan->writeformat;
508         /* Set the channel to a format we can work with */
509         res = ast_set_write_format(chan, fmts);
510         
511         fd = ast_filehelper(filename2, (char *)chan, NULL, ACTION_OPEN);
512         if (fd >= 0)
513                 return chan->stream;
514         return NULL;
515 }
516
517 struct ast_filestream *ast_openvstream(struct ast_channel *chan, const char *filename, const char *preflang)
518 {
519         /* This is a fairly complex routine.  Essentially we should do 
520            the following:
521            
522            1) Find which file handlers produce our type of format.
523            2) Look for a filename which it can handle.
524            3) If we find one, then great.  
525            4) If not, see what files are there
526            5) See what we can actually support
527            6) Choose the one with the least costly translator path and
528                set it up.
529                    
530         */
531         int fd = -1;
532         int fmts = -1;
533         char filename2[256];
534         char lang2[MAX_LANGUAGE];
535         /* XXX H.263 only XXX */
536         char *fmt = "h263";
537         if (preflang && !ast_strlen_zero(preflang)) {
538                 snprintf(filename2, sizeof(filename2), "%s/%s", preflang, filename);
539                 fmts = ast_fileexists(filename2, fmt, NULL);
540                 if (fmts < 1) {
541                         ast_copy_string(lang2, preflang, sizeof(lang2));
542                         snprintf(filename2, sizeof(filename2), "%s/%s", lang2, filename);
543                         fmts = ast_fileexists(filename2, fmt, NULL);
544                 }
545         }
546         if (fmts < 1) {
547                 ast_copy_string(filename2, filename, sizeof(filename2));
548                 fmts = ast_fileexists(filename2, fmt, NULL);
549         }
550         if (fmts < 1) {
551                 return NULL;
552         }
553         fd = ast_filehelper(filename2, (char *)chan, fmt, ACTION_OPEN);
554         if (fd >= 0)
555                 return chan->vstream;
556         ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename);
557         return NULL;
558 }
559
560 struct ast_frame *ast_readframe(struct ast_filestream *s)
561 {
562         struct ast_frame *f = NULL;
563         int whennext = 0;       
564         if (s && s->fmt)
565                 f = s->fmt->read(s, &whennext);
566         return f;
567 }
568
569 static int ast_readaudio_callback(void *data)
570 {
571         struct ast_filestream *s = data;
572         struct ast_frame *fr;
573         int whennext = 0;
574
575         while(!whennext) {
576                 fr = s->fmt->read(s, &whennext);
577                 if (fr) {
578                         if (ast_write(s->owner, fr)) {
579                                 ast_log(LOG_WARNING, "Failed to write frame\n");
580                                 s->owner->streamid = -1;
581 #ifdef ZAPTEL_OPTIMIZATIONS
582                                 ast_settimeout(s->owner, 0, NULL, NULL);
583 #endif                  
584                                 return 0;
585                         }
586                 } else {
587                         /* Stream has finished */
588                         s->owner->streamid = -1;
589 #ifdef ZAPTEL_OPTIMIZATIONS
590                         ast_settimeout(s->owner, 0, NULL, NULL);
591 #endif                  
592                         return 0;
593                 }
594         }
595         if (whennext != s->lasttimeout) {
596 #ifdef ZAPTEL_OPTIMIZATIONS
597                 if (s->owner->timingfd > -1)
598                         ast_settimeout(s->owner, whennext, ast_readaudio_callback, s);
599                 else
600 #endif          
601                         s->owner->streamid = ast_sched_add(s->owner->sched, whennext/8, ast_readaudio_callback, s);
602                 s->lasttimeout = whennext;
603                 return 0;
604         }
605         return 1;
606 }
607
608 static int ast_readvideo_callback(void *data)
609 {
610         struct ast_filestream *s = data;
611         struct ast_frame *fr;
612         int whennext = 0;
613
614         while(!whennext) {
615                 fr = s->fmt->read(s, &whennext);
616                 if (fr) {
617                         if (ast_write(s->owner, fr)) {
618                                 ast_log(LOG_WARNING, "Failed to write frame\n");
619                                 s->owner->vstreamid = -1;
620                                 return 0;
621                         }
622                 } else {
623                         /* Stream has finished */
624                         s->owner->vstreamid = -1;
625                         return 0;
626                 }
627         }
628         if (whennext != s->lasttimeout) {
629                 s->owner->vstreamid = ast_sched_add(s->owner->sched, whennext/8, ast_readvideo_callback, s);
630                 s->lasttimeout = whennext;
631                 return 0;
632         }
633         return 1;
634 }
635
636 int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
637 {
638         s->owner = chan;
639         return 0;
640 }
641
642 int ast_playstream(struct ast_filestream *s)
643 {
644         if (s->fmt->format < AST_FORMAT_MAX_AUDIO)
645                 ast_readaudio_callback(s);
646         else
647                 ast_readvideo_callback(s);
648         return 0;
649 }
650
651 int ast_seekstream(struct ast_filestream *fs, long sample_offset, int whence)
652 {
653         return fs->fmt->seek(fs, sample_offset, whence);
654 }
655
656 int ast_truncstream(struct ast_filestream *fs)
657 {
658         return fs->fmt->trunc(fs);
659 }
660
661 long ast_tellstream(struct ast_filestream *fs)
662 {
663         return fs->fmt->tell(fs);
664 }
665
666 int ast_stream_fastforward(struct ast_filestream *fs, long ms)
667 {
668         /* I think this is right, 8000 samples per second, 1000 ms a second so 8
669          * samples per ms  */
670         long samples = ms * 8;
671         return ast_seekstream(fs, samples, SEEK_CUR);
672 }
673
674 int ast_stream_rewind(struct ast_filestream *fs, long ms)
675 {
676         long samples = ms * 8;
677         samples = samples * -1;
678         return ast_seekstream(fs, samples, SEEK_CUR);
679 }
680
681 int ast_closestream(struct ast_filestream *f)
682 {
683         char *cmd = NULL;
684         size_t size = 0;
685         /* Stop a running stream if there is one */
686         if (f->owner) {
687                 if (f->fmt->format < AST_FORMAT_MAX_AUDIO) {
688                         f->owner->stream = NULL;
689                         if (f->owner->streamid > -1)
690                                 ast_sched_del(f->owner->sched, f->owner->streamid);
691                         f->owner->streamid = -1;
692 #ifdef ZAPTEL_OPTIMIZATIONS
693                         ast_settimeout(f->owner, 0, NULL, NULL);
694 #endif                  
695                 } else {
696                         f->owner->vstream = NULL;
697                         if (f->owner->vstreamid > -1)
698                                 ast_sched_del(f->owner->sched, f->owner->vstreamid);
699                         f->owner->vstreamid = -1;
700                 }
701         }
702         /* destroy the translator on exit */
703         if (f->trans) {
704                 ast_translator_free_path(f->trans);
705                 f->trans = NULL;
706         }
707
708         if (f->realfilename && f->filename) {
709                         size = strlen(f->filename) + strlen(f->realfilename) + 15;
710                         cmd = alloca(size);
711                         memset(cmd,0,size);
712                         snprintf(cmd,size,"/bin/mv -f %s %s",f->filename,f->realfilename);
713                         ast_safe_system(cmd);
714         }
715
716         if (f->filename) {
717                 free(f->filename);
718                 f->filename = NULL;
719         }
720         if (f->realfilename) {
721                 free(f->realfilename);
722                 f->realfilename = NULL;
723         }
724         f->fmt->close(f);
725         return 0;
726 }
727
728
729 int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
730 {
731         char filename2[256];
732         char tmp[256];
733         char *postfix;
734         char *prefix;
735         char *c;
736         char lang2[MAX_LANGUAGE];
737         int res = -1;
738         if (preflang && !ast_strlen_zero(preflang)) {
739                 /* Insert the language between the last two parts of the path */
740                 ast_copy_string(tmp, filename, sizeof(tmp));
741                 c = strrchr(tmp, '/');
742                 if (c) {
743                         *c = '\0';
744                         postfix = c+1;
745                         prefix = tmp;
746                         snprintf(filename2, sizeof(filename2), "%s/%s/%s", prefix, preflang, postfix);
747                 } else {
748                         postfix = tmp;
749                         prefix="";
750                         snprintf(filename2, sizeof(filename2), "%s/%s", preflang, postfix);
751                 }
752                 res = ast_filehelper(filename2, NULL, fmt, ACTION_EXISTS);
753                 if (res < 1) {
754                         char *stringp=NULL;
755                         ast_copy_string(lang2, preflang, sizeof(lang2));
756                         stringp=lang2;
757                         strsep(&stringp, "_");
758                         /* If language is a specific locality of a language (like es_MX), strip the locality and try again */
759                         if (strcmp(lang2, preflang)) {
760                                 if (ast_strlen_zero(prefix)) {
761                                         snprintf(filename2, sizeof(filename2), "%s/%s", lang2, postfix);
762                                 } else {
763                                         snprintf(filename2, sizeof(filename2), "%s/%s/%s", prefix, lang2, postfix);
764                                 }
765                                 res = ast_filehelper(filename2, NULL, fmt, ACTION_EXISTS);
766                         }
767                 }
768         }
769
770         /* Fallback to no language (usually winds up being American English) */
771         if (res < 1) {
772                 res = ast_filehelper(filename, NULL, fmt, ACTION_EXISTS);
773         }
774         return res;
775 }
776
777 int ast_filedelete(const char *filename, const char *fmt)
778 {
779         return ast_filehelper(filename, NULL, fmt, ACTION_DELETE);
780 }
781
782 int ast_filerename(const char *filename, const char *filename2, const char *fmt)
783 {
784         return ast_filehelper(filename, filename2, fmt, ACTION_RENAME);
785 }
786
787 int ast_filecopy(const char *filename, const char *filename2, const char *fmt)
788 {
789         return ast_filehelper(filename, filename2, fmt, ACTION_COPY);
790 }
791
792 int ast_streamfile(struct ast_channel *chan, const char *filename, const char *preflang)
793 {
794         struct ast_filestream *fs;
795         struct ast_filestream *vfs;
796
797         fs = ast_openstream(chan, filename, preflang);
798         vfs = ast_openvstream(chan, filename, preflang);
799         if (vfs)
800                 ast_log(LOG_DEBUG, "Ooh, found a video stream, too\n");
801         if (fs){
802                 if (ast_applystream(chan, fs))
803                         return -1;
804                 if (vfs && ast_applystream(chan, vfs))
805                         return -1;
806                 if (ast_playstream(fs))
807                         return -1;
808                 if (vfs && ast_playstream(vfs))
809                         return -1;
810 #if 1
811                 if (option_verbose > 2)
812                         ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (language '%s')\n", filename, preflang ? preflang : "default");
813 #endif
814                 return 0;
815         }
816         ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname(chan->nativeformats), strerror(errno));
817         return -1;
818 }
819
820 struct ast_filestream *ast_readfile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
821 {
822         int fd;
823         struct ast_format *f;
824         struct ast_filestream *fs = NULL;
825         char *fn;
826
827         if (ast_mutex_lock(&formatlock)) {
828                 ast_log(LOG_WARNING, "Unable to lock format list\n");
829                 return NULL;
830         }
831
832         for (f = formats; f && !fs; f = f->next) {
833                 if (!exts_compare(f->exts, type))
834                         continue;
835
836                 fn = build_filename(filename, type);
837                 fd = open(fn, flags);
838                 if (fd >= 0) {
839                         errno = 0;
840
841                         if (!(fs = f->open(fd))) {
842                                 ast_log(LOG_WARNING, "Unable to open %s\n", fn);
843                                 close(fd);
844                                 free(fn);
845                                 continue;
846                         }
847
848                         fs->trans = NULL;
849                         fs->fmt = f;
850                         fs->flags = flags;
851                         fs->mode = mode;
852                         fs->filename = strdup(filename);
853                         fs->vfs = NULL;
854                 } else if (errno != EEXIST)
855                         ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno));
856                 free(fn);
857         }
858
859         ast_mutex_unlock(&formatlock);
860         if (!fs) 
861                 ast_log(LOG_WARNING, "No such format '%s'\n", type);
862
863         return fs;
864 }
865
866 struct ast_filestream *ast_writefile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
867 {
868         int fd, myflags = 0;
869         struct ast_format *f;
870         struct ast_filestream *fs = NULL;
871         char *fn, *orig_fn = NULL;
872         char *buf = NULL;
873         size_t size = 0;
874
875         if (ast_mutex_lock(&formatlock)) {
876                 ast_log(LOG_WARNING, "Unable to lock format list\n");
877                 return NULL;
878         }
879
880         /* set the O_TRUNC flag if and only if there is no O_APPEND specified */
881         if (flags & O_APPEND) { 
882                 /* We really can't use O_APPEND as it will break WAV header updates */
883                 flags &= ~O_APPEND;
884         } else {
885                 myflags = O_TRUNC;
886         }
887         
888         myflags |= O_WRONLY | O_CREAT;
889
890         for (f = formats; f && !fs; f = f->next) {
891                 if (!exts_compare(f->exts, type))
892                         continue;
893
894                 fn = build_filename(filename, type);
895                 fd = open(fn, flags | myflags, mode);
896                 
897                 if (option_cache_record_files && fd >= 0) {
898                         char *c;
899
900                         close(fd);
901                         /*
902                           We touch orig_fn just as a place-holder so other things (like vmail) see the file is there.
903                           What we are really doing is writing to record_cache_dir until we are done then we will mv the file into place.
904                         */
905                         orig_fn = ast_strdupa(fn);
906                         for (c = fn; *c; c++)
907                                 if (*c == '/')
908                                         *c = '_';
909
910                         size = strlen(fn) + strlen(record_cache_dir) + 2;
911                         buf = alloca(size);
912                         memset(buf, 0, size);
913                         snprintf(buf, size, "%s/%s", record_cache_dir, fn);
914                         free(fn);
915                         fn = buf;
916                         fd = open(fn, flags | myflags, mode);
917                 }
918                 if (fd >= 0) {
919                         errno = 0;
920
921                         if ((fs = f->rewrite(fd, comment))) {
922                                 fs->trans = NULL;
923                                 fs->fmt = f;
924                                 fs->flags = flags;
925                                 fs->mode = mode;
926                                 if (orig_fn) {
927                                         fs->realfilename = strdup(orig_fn);
928                                         fs->filename = strdup(fn);
929                                 } else {
930                                         fs->realfilename = NULL;
931                                         fs->filename = strdup(filename);
932                                 }
933                                 fs->vfs = NULL;
934                         } else {
935                                 ast_log(LOG_WARNING, "Unable to rewrite %s\n", fn);
936                                 close(fd);
937                                 if (orig_fn) {
938                                         unlink(fn);
939                                         unlink(orig_fn);
940                                 }
941                         }
942                 } else if (errno != EEXIST) {
943                         ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno));
944                         if (orig_fn)
945                                 unlink(orig_fn);
946                 }
947                 /* if buf != NULL then fn is already free and pointing to it */
948                 if (!buf)
949                         free(fn);
950         }
951
952         ast_mutex_unlock(&formatlock);
953         if (!fs)
954                 ast_log(LOG_WARNING, "No such format '%s'\n", type);
955
956         return fs;
957 }
958
959 int ast_waitstream(struct ast_channel *c, const char *breakon)
960 {
961         /* XXX Maybe I should just front-end ast_waitstream_full ? XXX */
962         int res;
963         struct ast_frame *fr;
964         if (!breakon) breakon = "";
965         while(c->stream) {
966                 res = ast_sched_wait(c->sched);
967                 if ((res < 0) && !c->timingfunc) {
968                         ast_stopstream(c);
969                         break;
970                 }
971                 if (res < 0)
972                         res = 1000;
973                 res = ast_waitfor(c, res);
974                 if (res < 0) {
975                         ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
976                         return res;
977                 } else if (res > 0) {
978                         fr = ast_read(c);
979                         if (!fr) {
980 #if 0
981                                 ast_log(LOG_DEBUG, "Got hung up\n");
982 #endif
983                                 return -1;
984                         }
985                         
986                         switch(fr->frametype) {
987                         case AST_FRAME_DTMF:
988                                 res = fr->subclass;
989                                 if (strchr(breakon, res)) {
990                                         ast_frfree(fr);
991                                         return res;
992                                 }
993                                 break;
994                         case AST_FRAME_CONTROL:
995                                 switch(fr->subclass) {
996                                 case AST_CONTROL_HANGUP:
997                                         ast_frfree(fr);
998                                         return -1;
999                                 case AST_CONTROL_RINGING:
1000                                 case AST_CONTROL_ANSWER:
1001                                 case AST_CONTROL_VIDUPDATE:
1002                                         /* Unimportant */
1003                                         break;
1004                                 default:
1005                                         ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
1006                                 }
1007                         }
1008                         /* Ignore */
1009                         ast_frfree(fr);
1010                 }
1011                 ast_sched_runq(c->sched);
1012         }
1013         return (c->_softhangup ? -1 : 0);
1014 }
1015
1016 int ast_waitstream_fr(struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int ms)
1017 {
1018         int res;
1019         struct ast_frame *fr;
1020
1021         if (!breakon)
1022                         breakon = "";
1023         if (!forward)
1024                         forward = "";
1025         if (!rewind)
1026                         rewind = "";
1027         
1028         while(c->stream) {
1029                 res = ast_sched_wait(c->sched);
1030                 if ((res < 0) && !c->timingfunc) {
1031                         ast_stopstream(c);
1032                         break;
1033                 }
1034                 if (res < 0)
1035                         res = 1000;
1036                 res = ast_waitfor(c, res);
1037                 if (res < 0) {
1038                         ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
1039                         return res;
1040                 } else
1041                 if (res > 0) {
1042                         fr = ast_read(c);
1043                         if (!fr) {
1044 #if 0
1045                                 ast_log(LOG_DEBUG, "Got hung up\n");
1046 #endif
1047                                 return -1;
1048                         }
1049                         
1050                         switch(fr->frametype) {
1051                         case AST_FRAME_DTMF:
1052                                 res = fr->subclass;
1053                                 if (strchr(forward,res)) {
1054                                         ast_stream_fastforward(c->stream, ms);
1055                                 } else if (strchr(rewind,res)) {
1056                                         ast_stream_rewind(c->stream, ms);
1057                                 } else if (strchr(breakon, res)) {
1058                                         ast_frfree(fr);
1059                                         return res;
1060                                 }                                       
1061                                 break;
1062                         case AST_FRAME_CONTROL:
1063                                 switch(fr->subclass) {
1064                                 case AST_CONTROL_HANGUP:
1065                                         ast_frfree(fr);
1066                                         return -1;
1067                                 case AST_CONTROL_RINGING:
1068                                 case AST_CONTROL_ANSWER:
1069                                         /* Unimportant */
1070                                         break;
1071                                 default:
1072                                         ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
1073                                 }
1074                         }
1075                         /* Ignore */
1076                         ast_frfree(fr);
1077                 } else
1078                         ast_sched_runq(c->sched);
1079         
1080                 
1081         }
1082         return (c->_softhangup ? -1 : 0);
1083 }
1084
1085 int ast_waitstream_full(struct ast_channel *c, const char *breakon, int audiofd, int cmdfd)
1086 {
1087         int res;
1088         int ms;
1089         int outfd;
1090         struct ast_frame *fr;
1091         struct ast_channel *rchan;
1092
1093         if (!breakon)
1094                 breakon = "";
1095         
1096         while(c->stream) {
1097                 ms = ast_sched_wait(c->sched);
1098                 if ((ms < 0) && !c->timingfunc) {
1099                         ast_stopstream(c);
1100                         break;
1101                 }
1102                 if (ms < 0)
1103                         ms = 1000;
1104                 rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
1105                 if (!rchan && (outfd < 0) && (ms)) {
1106                         /* Continue */
1107                         if (errno == EINTR)
1108                                 continue;
1109                         ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
1110                         return -1;
1111                 } else if (outfd > -1) {
1112                         /* The FD we were watching has something waiting */
1113                         return 1;
1114                 } else if (rchan) {
1115                         fr = ast_read(c);
1116                         if (!fr) {
1117 #if 0
1118                                 ast_log(LOG_DEBUG, "Got hung up\n");
1119 #endif
1120                                 return -1;
1121                         }
1122                         
1123                         switch(fr->frametype) {
1124                         case AST_FRAME_DTMF:
1125                                 res = fr->subclass;
1126                                 if (strchr(breakon, res)) {
1127                                         ast_frfree(fr);
1128                                         return res;
1129                                 }
1130                                 break;
1131                         case AST_FRAME_CONTROL:
1132                                 switch(fr->subclass) {
1133                                 case AST_CONTROL_HANGUP:
1134                                         ast_frfree(fr);
1135                                         return -1;
1136                                 case AST_CONTROL_RINGING:
1137                                 case AST_CONTROL_ANSWER:
1138                                         /* Unimportant */
1139                                         break;
1140                                 default:
1141                                         ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
1142                                 }
1143                         case AST_FRAME_VOICE:
1144                                 /* Write audio if appropriate */
1145                                 if (audiofd > -1)
1146                                         write(audiofd, fr->data, fr->datalen);
1147                         }
1148                         /* Ignore */
1149                         ast_frfree(fr);
1150                 }
1151                 ast_sched_runq(c->sched);
1152         }
1153         return (c->_softhangup ? -1 : 0);
1154 }
1155
1156 int ast_waitstream_exten(struct ast_channel *c, const char *context)
1157 {
1158         /* Waitstream, with return in the case of a valid 1 digit extension */
1159         /* in the current or specified context being pressed */
1160         /* XXX Maybe I should just front-end ast_waitstream_full ? XXX */
1161         int res;
1162         struct ast_frame *fr;
1163         char exten[AST_MAX_EXTENSION];
1164
1165         if (!context) context = c->context;
1166         while(c->stream) {
1167                 res = ast_sched_wait(c->sched);
1168                 if ((res < 0) && !c->timingfunc) {
1169                         ast_stopstream(c);
1170                         break;
1171                 }
1172                 if (res < 0)
1173                         res = 1000;
1174                 res = ast_waitfor(c, res);
1175                 if (res < 0) {
1176                         ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
1177                         return res;
1178                 } else if (res > 0) {
1179                         fr = ast_read(c);
1180                         if (!fr) {
1181 #if 0
1182                                 ast_log(LOG_DEBUG, "Got hung up\n");
1183 #endif
1184                                 return -1;
1185                         }
1186                         
1187                         switch(fr->frametype) {
1188                         case AST_FRAME_DTMF:
1189                                 res = fr->subclass;
1190                                 snprintf(exten, sizeof(exten), "%c", res);
1191                                 if (ast_exists_extension(c, context, exten, 1, c->cid.cid_num)) {
1192                                         ast_frfree(fr);
1193                                         return res;
1194                                 }
1195                                 break;
1196                         case AST_FRAME_CONTROL:
1197                                 switch(fr->subclass) {
1198                                 case AST_CONTROL_HANGUP:
1199                                         ast_frfree(fr);
1200                                         return -1;
1201                                 case AST_CONTROL_RINGING:
1202                                 case AST_CONTROL_ANSWER:
1203                                         /* Unimportant */
1204                                         break;
1205                                 default:
1206                                         ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
1207                                 }
1208                         }
1209                         /* Ignore */
1210                         ast_frfree(fr);
1211                 }
1212                 ast_sched_runq(c->sched);
1213         }
1214         return (c->_softhangup ? -1 : 0);
1215 }
1216
1217 static int show_file_formats(int fd, int argc, char *argv[])
1218 {
1219 #define FORMAT "%-10s %-10s %-20s\n"
1220 #define FORMAT2 "%-10s %-10s %-20s\n"
1221         struct ast_format *f;
1222         int count_fmt = 0;
1223
1224         if (argc != 3)
1225                 return RESULT_SHOWUSAGE;
1226         ast_cli(fd, FORMAT, "Format", "Name", "Extensions");
1227                 
1228         if (ast_mutex_lock(&formatlock)) {
1229                 ast_log(LOG_WARNING, "Unable to lock format list\n");
1230                 return -1;
1231         }
1232
1233         f = formats;
1234         while(f) {
1235                 ast_cli(fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts);
1236                 f = f->next;
1237                 count_fmt++;
1238         };
1239         ast_mutex_unlock(&formatlock);
1240         ast_cli(fd, "%d file formats registered.\n", count_fmt);
1241         return RESULT_SUCCESS;
1242 #undef FORMAT
1243 #undef FORMAT2
1244         
1245 }
1246
1247 struct ast_cli_entry show_file =
1248 {
1249         { "show", "file", "formats" },
1250         show_file_formats,
1251         "Displays file formats",
1252         "Usage: show file formats\n"
1253         "       displays currently registered file formats (if any)\n"
1254 };
1255
1256 int ast_file_init(void)
1257 {
1258         ast_cli_register(&show_file);
1259         return 0;
1260 }