Thu Oct 8 21:57:48 2009

Asterisk developer's documentation


file.c File Reference

Generic File Format Support. More...

#include "asterisk.h"
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/stat.h>
#include "asterisk/frame.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/sched.h"
#include "asterisk/options.h"
#include "asterisk/translate.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/linkedlists.h"
#include "asterisk/module.h"

Include dependency graph for file.c:

Go to the source code of this file.

Defines

#define FORMAT   "%-10s %-10s %-20s\n"
#define FORMAT   "%-10s %-10s %-20s\n"
#define FORMAT2   "%-10s %-10s %-20s\n"
#define FORMAT2   "%-10s %-10s %-20s\n"

Enumerations

enum  file_action {
  ACTION_EXISTS = 1, ACTION_DELETE, ACTION_RENAME, ACTION_OPEN,
  ACTION_COPY
}
enum  fsread_res { FSREAD_FAILURE, FSREAD_SUCCESS_SCHED, FSREAD_SUCCESS_NOSCHED }
enum  wrap_fn { WRAP_OPEN, WRAP_REWRITE }

Functions

int __ast_format_register (const struct ast_format *f, struct ast_module *mod)
int ast_applystream (struct ast_channel *chan, struct ast_filestream *s)
int ast_closestream (struct ast_filestream *f)
int ast_file_init (void)
int ast_filecopy (const char *filename, const char *filename2, const char *fmt)
int ast_filedelete (const char *filename, const char *fmt)
int ast_fileexists (const char *filename, const char *fmt, const char *preflang)
static int ast_filehelper (const char *filename, const void *arg2, const char *fmt, const enum file_action action)
 perform various actions on a file. Second argument arg2 depends on the command: unused for EXISTS and DELETE destination file name (const char *) for COPY and RENAME struct ast_channel * for OPEN if fmt is NULL, OPEN will return the first matching entry, whereas other functions will run on all matching entries.
int ast_filerename (const char *filename, const char *filename2, const char *fmt)
int ast_format_unregister (const char *name)
static int ast_fsread_audio (const void *data)
static int ast_fsread_video (const void *data)
static AST_LIST_HEAD_STATIC (formats, ast_format)
struct ast_filestreamast_openstream (struct ast_channel *chan, const char *filename, const char *preflang)
struct ast_filestreamast_openstream_full (struct ast_channel *chan, const char *filename, const char *preflang, int asis)
struct ast_filestreamast_openvstream (struct ast_channel *chan, const char *filename, const char *preflang)
int ast_playstream (struct ast_filestream *s)
static enum fsread_res ast_readaudio_callback (struct ast_filestream *s)
struct ast_filestreamast_readfile (const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
struct ast_frameast_readframe (struct ast_filestream *s)
static enum fsread_res ast_readvideo_callback (struct ast_filestream *s)
int ast_seekstream (struct ast_filestream *fs, off_t sample_offset, int whence)
int ast_stopstream (struct ast_channel *tmp)
 Stops a stream.
int ast_stream_and_wait (struct ast_channel *chan, const char *file, const char *language, const char *digits)
int ast_stream_fastforward (struct ast_filestream *fs, off_t ms)
int ast_stream_rewind (struct ast_filestream *fs, off_t ms)
int ast_streamfile (struct ast_channel *chan, const char *filename, const char *preflang)
off_t ast_tellstream (struct ast_filestream *fs)
int ast_truncstream (struct ast_filestream *fs)
int ast_waitstream (struct ast_channel *c, const char *breakon)
int ast_waitstream_exten (struct ast_channel *c, const char *context)
int ast_waitstream_fr (struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int ms)
int ast_waitstream_full (struct ast_channel *c, const char *breakon, int audiofd, int cmdfd)
struct ast_filestreamast_writefile (const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
int ast_writestream (struct ast_filestream *fs, struct ast_frame *f)
static char * build_filename (const char *filename, const char *ext)
 construct a filename. Absolute pathnames are preserved, relative names are prefixed by the sounds/ directory. The wav49 suffix is replaced by 'WAV'. Returns a malloc'ed string to be freed by the caller.
static int copy (const char *infile, const char *outfile)
static int exts_compare (const char *exts, const char *type)
static int fileexists_core (const char *filename, const char *fmt, const char *preflang, char *buf, int buflen)
 helper routine to locate a file with a given format and language preference. Try preflang, preflang with stripped '_' suffix, or NULL. In the standard asterisk, language goes just before the last component. In an alternative configuration, the language should be a prefix to the actual filename.
static int fileexists_test (const char *filename, const char *fmt, const char *lang, char *buf, int buflen)
static int fn_wrapper (struct ast_filestream *s, const char *comment, enum wrap_fn mode)
static struct ast_filestreamget_filestream (struct ast_format *fmt, FILE *bfile)
static int is_absolute_path (const char *filename)
static int open_wrapper (struct ast_filestream *s)
static int rewrite_wrapper (struct ast_filestream *s, const char *comment)
static int show_file_formats (int fd, int argc, char *argv[])
static int show_file_formats_deprecated (int fd, int argc, char *argv[])
static int waitstream_core (struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int skip_ms, int audiofd, int cmdfd, const char *context)
 the core of all waitstream() functions

Variables

int ast_language_is_prefix
struct ast_cli_entry cli_file []
struct ast_cli_entry cli_show_file_formats_deprecated
char show_file_formats_usage []


Detailed Description

Generic File Format Support.

Author:
Mark Spencer <markster@digium.com>

Definition in file file.c.


Define Documentation

#define FORMAT   "%-10s %-10s %-20s\n"

#define FORMAT   "%-10s %-10s %-20s\n"

#define FORMAT2   "%-10s %-10s %-20s\n"

#define FORMAT2   "%-10s %-10s %-20s\n"


Enumeration Type Documentation

Enumerator:
ACTION_EXISTS 
ACTION_DELETE 
ACTION_RENAME 
ACTION_OPEN 
ACTION_COPY 

Definition at line 343 of file file.c.

00343                  {
00344    ACTION_EXISTS = 1, /* return matching format if file exists, 0 otherwise */
00345    ACTION_DELETE, /* delete file, return 0 on success, -1 on error */
00346    ACTION_RENAME, /* rename file. return 0 on success, -1 on error */
00347    ACTION_OPEN,
00348    ACTION_COPY /* copy file. return 0 on success, -1 on error */
00349 };

enum fsread_res

Enumerator:
FSREAD_FAILURE 
FSREAD_SUCCESS_SCHED 
FSREAD_SUCCESS_NOSCHED 

Definition at line 656 of file file.c.

00656                 {
00657    FSREAD_FAILURE,
00658    FSREAD_SUCCESS_SCHED,
00659    FSREAD_SUCCESS_NOSCHED,
00660 };

enum wrap_fn

Enumerator:
WRAP_OPEN 
WRAP_REWRITE 

Definition at line 314 of file file.c.

00314 { WRAP_OPEN, WRAP_REWRITE };


Function Documentation

int __ast_format_register ( const struct ast_format f,
struct ast_module mod 
)

Register a new file format capability Adds a format to Asterisk's format abilities. returns 0 on success, -1 on failure

Definition at line 68 of file file.c.

References ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_verbose(), ast_format::buf_size, ast_format::exts, LOG_WARNING, ast_format::module, ast_format::name, option_verbose, and VERBOSE_PREFIX_2.

00069 {
00070    struct ast_format *tmp;
00071 
00072    if (AST_LIST_LOCK(&formats)) {
00073       ast_log(LOG_WARNING, "Unable to lock format list\n");
00074       return -1;
00075    }
00076    AST_LIST_TRAVERSE(&formats, tmp, list) {
00077       if (!strcasecmp(f->name, tmp->name)) {
00078          AST_LIST_UNLOCK(&formats);
00079          ast_log(LOG_WARNING, "Tried to register '%s' format, already registered\n", f->name);
00080          return -1;
00081       }
00082    }
00083    if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
00084       AST_LIST_UNLOCK(&formats);
00085       return -1;
00086    }
00087    *tmp = *f;
00088    tmp->module = mod;
00089    if (tmp->buf_size) {
00090       /*
00091        * Align buf_size properly, rounding up to the machine-specific
00092        * alignment for pointers.
00093        */
00094       struct _test_align { void *a, *b; } p;
00095       int align = (char *)&p.b - (char *)&p.a;
00096       tmp->buf_size = ((f->buf_size + align - 1)/align)*align;
00097    }
00098    
00099    memset(&tmp->list, 0, sizeof(tmp->list));
00100 
00101    AST_LIST_INSERT_HEAD(&formats, tmp, list);
00102    AST_LIST_UNLOCK(&formats);
00103    if (option_verbose > 1)
00104       ast_verbose( VERBOSE_PREFIX_2 "Registered file format %s, extension(s) %s\n", f->name, f->exts);
00105 
00106    return 0;
00107 }

int ast_applystream ( struct ast_channel chan,
struct ast_filestream s 
)

Applys a open stream to a channel.

Parameters:
chan channel to work
s ast_filestream to apply Returns 0 for success, -1 on failure

Definition at line 764 of file file.c.

References ast_filestream::owner.

Referenced by ast_streamfile(), handle_getoption(), handle_recordfile(), handle_streamfile(), and speech_streamfile().

00765 {
00766    s->owner = chan;
00767    return 0;
00768 }

int ast_closestream ( struct ast_filestream f  ) 

Closes a stream

Parameters:
f filestream to close Close a playback or recording stream Returns 0 on success, -1 on failure

Definition at line 807 of file file.c.

References ast_closestream(), AST_FORMAT_MAX_AUDIO, ast_module_unref(), ast_safe_system(), AST_SCHED_DEL, ast_settimeout(), ast_translator_free_path(), ast_format::close, ast_filestream::f, ast_filestream::filename, ast_filestream::fmt, ast_format::format, free, ast_format::module, ast_filestream::orig_chan_name, ast_filestream::owner, ast_filestream::realfilename, ast_channel::sched, ast_channel::stream, ast_channel::streamid, ast_filestream::trans, ast_filestream::vfs, ast_channel::vstream, and ast_channel::vstreamid.

Referenced by __ast_play_and_record(), ast_closestream(), ast_filehelper(), ast_hangup(), ast_moh_files_next(), ast_monitor_start(), ast_monitor_stop(), ast_stopstream(), cli_audio_convert(), cli_audio_convert_deprecated(), dictate_exec(), gen_closestream(), handle_recordfile(), local_ast_moh_stop(), mixmonitor_thread(), moh_files_release(), record_exec(), recordthread(), and rpt().

00808 {
00809    char *cmd = NULL;
00810    size_t size = 0;
00811    /* Stop a running stream if there is one */
00812    if (f->owner) {
00813       if (f->fmt->format < AST_FORMAT_MAX_AUDIO) {
00814          f->owner->stream = NULL;
00815          AST_SCHED_DEL(f->owner->sched, f->owner->streamid);
00816 #ifdef HAVE_ZAPTEL
00817          ast_settimeout(f->owner, 0, NULL, NULL);
00818 #endif         
00819       } else {
00820          f->owner->vstream = NULL;
00821          AST_SCHED_DEL(f->owner->sched, f->owner->vstreamid);
00822       }
00823    }
00824    /* destroy the translator on exit */
00825    if (f->trans)
00826       ast_translator_free_path(f->trans);
00827 
00828    if (f->realfilename && f->filename) {
00829          size = strlen(f->filename) + strlen(f->realfilename) + 15;
00830          cmd = alloca(size);
00831          memset(cmd,0,size);
00832          snprintf(cmd,size,"/bin/mv -f %s %s",f->filename,f->realfilename);
00833          ast_safe_system(cmd);
00834    }
00835 
00836    if (f->filename)
00837       free(f->filename);
00838    if (f->realfilename)
00839       free(f->realfilename);
00840    if (f->fmt->close)
00841       f->fmt->close(f);
00842    fclose(f->f);
00843    if (f->vfs)
00844       ast_closestream(f->vfs);
00845    if (f->orig_chan_name)
00846       free((void *) f->orig_chan_name);
00847    ast_module_unref(f->fmt->module);
00848    free(f);
00849    return 0;
00850 }

int ast_file_init ( void   ) 

Initialize file stuff

Initializes all the various file stuff. Basically just registers the cli stuff Returns 0 all the time

Definition at line 1339 of file file.c.

References ast_cli_register_multiple().

Referenced by main().

01340 {
01341    ast_cli_register_multiple(cli_file, sizeof(cli_file) / sizeof(struct ast_cli_entry));
01342    return 0;
01343 }

int ast_filecopy ( const char *  oldname,
const char *  newname,
const char *  fmt 
)

Copies a file

Parameters:
oldname name of the file you wish to copy (minus extension)
newname name you wish the file to be copied to (minus extension)
fmt the format of the file Copy a given file in a given format, or if fmt is NULL, then do so for all

Definition at line 880 of file file.c.

References ACTION_COPY, and ast_filehelper().

Referenced by copy_plain_file(), and vm_forwardoptions().

00881 {
00882    return ast_filehelper(filename, filename2, fmt, ACTION_COPY);
00883 }

int ast_filedelete ( const char *  filename,
const char *  fmt 
)

Deletes a file

Parameters:
filename name of the file you wish to delete (minus the extension)
fmt of the file Delete a given file in a given format, or if fmt is NULL, then do so for all

Definition at line 870 of file file.c.

References ACTION_DELETE, and ast_filehelper().

Referenced by __ast_play_and_record(), ast_monitor_start(), ast_monitor_stop(), cli_audio_convert(), cli_audio_convert_deprecated(), conf_run(), leave_voicemail(), play_mailbox_owner(), play_record_review(), vm_delete(), and vm_forwardoptions().

00871 {
00872    return ast_filehelper(filename, NULL, fmt, ACTION_DELETE);
00873 }

int ast_fileexists ( const char *  filename,
const char *  fmt,
const char *  preflang 
)

Checks for the existence of a given file

Parameters:
filename name of the file you wish to check, minus the extension
fmt the format you wish to check (the extension)
preflang (the preferred language you wisht to find the file in) See if a given file exists in a given format. If fmt is NULL, any format is accepted. Returns -1 if file does not exist, non-zero positive otherwise.

Definition at line 856 of file file.c.

References ast_filestream::buf, and fileexists_core().

Referenced by app_exec(), ast_moh_files_next(), ast_monitor_start(), ast_monitor_stop(), common_exec(), conf_run(), last_message_index(), leave_voicemail(), play_greeting(), play_mailbox_owner(), play_message_callerid(), record_exec(), retrydial_exec(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), vm_intro(), vm_newuser(), vm_options(), and vm_tempgreeting().

00857 {
00858    char *buf;
00859    int buflen;
00860 
00861    if (preflang == NULL)
00862       preflang = "";
00863    buflen = strlen(preflang) + strlen(filename) + 4;  /* room for everything */
00864    buf = alloca(buflen);
00865    if (buf == NULL)
00866       return 0;
00867    return fileexists_core(filename, fmt, preflang, buf, buflen);
00868 }

static int ast_filehelper ( const char *  filename,
const void *  arg2,
const char *  fmt,
const enum file_action  action 
) [static]

perform various actions on a file. Second argument arg2 depends on the command: unused for EXISTS and DELETE destination file name (const char *) for COPY and RENAME struct ast_channel * for OPEN if fmt is NULL, OPEN will return the first matching entry, whereas other functions will run on all matching entries.

Definition at line 360 of file file.c.

References ACTION_COPY, ACTION_DELETE, ACTION_EXISTS, ACTION_OPEN, ACTION_RENAME, ast_closestream(), AST_FORMAT_MAX_AUDIO, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strdupa, build_filename(), copy(), errno, ext, ast_format::exts, exts_compare(), f, ast_filestream::filename, ast_filestream::fmt, ast_format::format, free, get_filestream(), ast_filestream::lasttimeout, LOG_WARNING, open_wrapper(), s, ast_channel::stream, strsep(), ast_filestream::trans, ast_channel::vstream, and ast_channel::writeformat.

Referenced by ast_filecopy(), ast_filedelete(), ast_filerename(), ast_openstream_full(), ast_openvstream(), and fileexists_test().

00361 {
00362    struct ast_format *f;
00363    int res = (action == ACTION_EXISTS) ? 0 : -1;
00364 
00365    if (AST_LIST_LOCK(&formats)) {
00366       ast_log(LOG_WARNING, "Unable to lock format list\n");
00367       return res;
00368    }
00369    /* Check for a specific format */
00370    AST_LIST_TRAVERSE(&formats, f, list) {
00371       char *stringp, *ext = NULL;
00372 
00373       if (fmt && !exts_compare(f->exts, fmt))
00374          continue;
00375 
00376       /* Look for a file matching the supported extensions.
00377        * The file must exist, and for OPEN, must match
00378        * one of the formats supported by the channel.
00379        */
00380       stringp = ast_strdupa(f->exts);  /* this is in the stack so does not need to be freed */
00381       while ( (ext = strsep(&stringp, "|")) ) {
00382          struct stat st;
00383          char *fn = build_filename(filename, ext);
00384 
00385          if (fn == NULL)
00386             continue;
00387 
00388          if ( stat(fn, &st) ) { /* file not existent */
00389             free(fn);
00390             continue;
00391          }
00392          /* for 'OPEN' we need to be sure that the format matches
00393           * what the channel can process
00394           */
00395          if (action == ACTION_OPEN) {
00396             struct ast_channel *chan = (struct ast_channel *)arg2;
00397             FILE *bfile;
00398             struct ast_filestream *s;
00399 
00400             if ( !(chan->writeformat & f->format) &&
00401                  !(f->format >= AST_FORMAT_MAX_AUDIO && fmt)) {
00402                free(fn);
00403                continue;   /* not a supported format */
00404             }
00405             if ( (bfile = fopen(fn, "r")) == NULL) {
00406                free(fn);
00407                continue;   /* cannot open file */
00408             }
00409             s = get_filestream(f, bfile);
00410             if (!s) {
00411                fclose(bfile);
00412                free(fn);   /* cannot allocate descriptor */
00413                continue;
00414             }
00415             if (open_wrapper(s)) {
00416                fclose(bfile);
00417                free(fn);
00418                free(s);
00419                continue;   /* cannot run open on file */
00420             }
00421             /* ok this is good for OPEN */
00422             res = 1; /* found */
00423             s->lasttimeout = -1;
00424             s->fmt = f;
00425             s->trans = NULL;
00426             s->filename = NULL;
00427             if (s->fmt->format < AST_FORMAT_MAX_AUDIO) {
00428                if (chan->stream)
00429                   ast_closestream(chan->stream);
00430                chan->stream = s;
00431             } else {
00432                if (chan->vstream)
00433                   ast_closestream(chan->vstream);
00434                chan->vstream = s;
00435             }
00436             free(fn);
00437             break;
00438          }
00439          switch (action) {
00440          case ACTION_OPEN:
00441             break;   /* will never get here */
00442 
00443          case ACTION_EXISTS:  /* return the matching format */
00444             res |= f->format;
00445             break;
00446 
00447          case ACTION_DELETE:
00448             if ( (res = unlink(fn)) )
00449                ast_log(LOG_WARNING, "unlink(%s) failed: %s\n", fn, strerror(errno));
00450             break;
00451 
00452          case ACTION_RENAME:
00453          case ACTION_COPY: {
00454             char *nfn = build_filename((const char *)arg2, ext);
00455             if (!nfn)
00456                ast_log(LOG_WARNING, "Out of memory\n");
00457             else {
00458                res = action == ACTION_COPY ? copy(fn, nfn) : rename(fn, nfn);
00459                if (res)
00460                   ast_log(LOG_WARNING, "%s(%s,%s) failed: %s\n",
00461                      action == ACTION_COPY ? "copy" : "rename",
00462                       fn, nfn, strerror(errno));
00463                free(nfn);
00464             }
00465              }
00466             break;
00467 
00468          default:
00469             ast_log(LOG_WARNING, "Unknown helper %d\n", action);
00470          }
00471          free(fn);
00472       }
00473    }
00474    AST_LIST_UNLOCK(&formats);
00475    return res;
00476 }

int ast_filerename ( const char *  oldname,
const char *  newname,
const char *  fmt 
)

Renames a file

Parameters:
oldname the name of the file you wish to act upon (minus the extension)
newname the name you wish to rename the file to (minus the extension)
fmt the format of the file Rename a given file in a given format, or if fmt is NULL, then do so for all Returns -1 on failure

Definition at line 875 of file file.c.

References ACTION_RENAME, and ast_filehelper().

Referenced by __ast_play_and_record(), ast_monitor_stop(), leave_voicemail(), play_record_review(), and rename_file().

00876 {
00877    return ast_filehelper(filename, filename2, fmt, ACTION_RENAME);
00878 }

int ast_format_unregister ( const char *  name  ) 

Unregisters a file format

Parameters:
name the name of the format you wish to unregister Unregisters a format based on the name of the format. Returns 0 on success, -1 on failure to unregister

Definition at line 109 of file file.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), free, LOG_WARNING, ast_format::name, option_verbose, and VERBOSE_PREFIX_2.

Referenced by unload_module().

00110 {
00111    struct ast_format *tmp;
00112    int res = -1;
00113 
00114    if (AST_LIST_LOCK(&formats)) {
00115       ast_log(LOG_WARNING, "Unable to lock format list\n");
00116       return -1;
00117    }
00118    AST_LIST_TRAVERSE_SAFE_BEGIN(&formats, tmp, list) {
00119       if (!strcasecmp(name, tmp->name)) {
00120          AST_LIST_REMOVE_CURRENT(&formats, list);
00121          free(tmp);
00122          res = 0;
00123       }
00124    }
00125    AST_LIST_TRAVERSE_SAFE_END
00126    AST_LIST_UNLOCK(&formats);
00127 
00128    if (!res) {
00129       if (option_verbose > 1)
00130          ast_verbose( VERBOSE_PREFIX_2 "Unregistered format %s\n", name);
00131    } else
00132       ast_log(LOG_WARNING, "Tried to unregister format %s, already unregistered\n", name);
00133 
00134    return res;
00135 }

static int ast_fsread_audio ( const void *  data  )  [static]

Definition at line 711 of file file.c.

References ast_readaudio_callback(), and FSREAD_SUCCESS_SCHED.

Referenced by ast_readaudio_callback().

00712 {
00713    struct ast_filestream *fs = (struct ast_filestream *)data;
00714    enum fsread_res res;
00715 
00716    res = ast_readaudio_callback(fs);
00717 
00718    if (res == FSREAD_SUCCESS_SCHED)
00719       return 1;
00720    
00721    return 0;
00722 }

static int ast_fsread_video ( const void *  data  )  [static]

Definition at line 751 of file file.c.

References ast_readvideo_callback(), and FSREAD_SUCCESS_SCHED.

Referenced by ast_readvideo_callback().

00752 {
00753    struct ast_filestream *fs = (struct ast_filestream *)data;
00754    enum fsread_res res;
00755 
00756    res = ast_readvideo_callback(fs);
00757 
00758    if (res == FSREAD_SUCCESS_SCHED)
00759       return 1;
00760    
00761    return 0;
00762 }

static AST_LIST_HEAD_STATIC ( formats  ,
ast_format   
) [static]

struct ast_filestream* ast_openstream ( struct ast_channel chan,
const char *  filename,
const char *  preflang 
) [read]

Opens stream for use in seeking, playing

Parameters:
chan channel to work with
filename to use
preflang prefered language to use Returns a ast_filestream pointer if it opens the file, NULL on error

Definition at line 571 of file file.c.

References ast_openstream_full().

Referenced by ast_streamfile(), dictate_exec(), handle_getoption(), handle_streamfile(), and speech_streamfile().

00572 {
00573    return ast_openstream_full(chan, filename, preflang, 0);
00574 }

struct ast_filestream* ast_openstream_full ( struct ast_channel chan,
const char *  filename,
const char *  preflang,
int  asis 
) [read]

Opens stream for use in seeking, playing

Parameters:
chan channel to work with
filename to use
preflang prefered language to use
asis if set, don't clear generators Returns a ast_filestream pointer if it opens the file, NULL on error

Definition at line 576 of file file.c.

References ACTION_OPEN, ast_deactivate_generator(), ast_filehelper(), AST_FORMAT_AUDIO_MASK, ast_log(), ast_set_write_format(), ast_stopstream(), ast_filestream::buf, fileexists_core(), ast_channel::generator, LOG_WARNING, ast_channel::oldwriteformat, ast_channel::stream, and ast_channel::writeformat.

Referenced by ast_moh_files_next(), ast_openstream(), and gen_nextfile().

00577 {
00578    /* 
00579     * Use fileexists_core() to find a file in a compatible
00580     * language and format, set up a suitable translator,
00581     * and open the stream.
00582     */
00583    int fmts, res, buflen;
00584    char *buf;
00585 
00586    if (!asis) {
00587       /* do this first, otherwise we detect the wrong writeformat */
00588       ast_stopstream(chan);
00589       if (chan->generator)
00590          ast_deactivate_generator(chan);
00591    }
00592    if (preflang == NULL)
00593       preflang = "";
00594    buflen = strlen(preflang) + strlen(filename) + 4;
00595    buf = alloca(buflen);
00596    if (buf == NULL)
00597       return NULL;
00598    fmts = fileexists_core(filename, NULL, preflang, buf, buflen);
00599    if (fmts > 0)
00600       fmts &= AST_FORMAT_AUDIO_MASK;
00601    if (fmts < 1) {
00602       ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
00603       return NULL;
00604    }
00605    chan->oldwriteformat = chan->writeformat;
00606    /* Set the channel to a format we can work with */
00607    res = ast_set_write_format(chan, fmts);
00608    res = ast_filehelper(buf, chan, NULL, ACTION_OPEN);
00609    if (res >= 0)
00610       return chan->stream;
00611    return NULL;
00612 }

struct ast_filestream* ast_openvstream ( struct ast_channel chan,
const char *  filename,
const char *  preflang 
) [read]

Opens stream for use in seeking, playing

Parameters:
chan channel to work with
filename to use
preflang prefered language to use Returns a ast_filestream pointer if it opens the file, NULL on error

Definition at line 614 of file file.c.

References ACTION_OPEN, ast_filehelper(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_MAX_VIDEO, ast_getformatname(), ast_log(), ast_filestream::buf, fileexists_core(), fmt, format, LOG_WARNING, ast_channel::nativeformats, and ast_channel::vstream.

Referenced by ast_streamfile(), handle_getoption(), and handle_streamfile().

00615 {
00616    /* As above, but for video. But here we don't have translators
00617     * so we must enforce a format.
00618     */
00619    unsigned int format;
00620    char *buf;
00621    int buflen;
00622 
00623    if (preflang == NULL)
00624       preflang = "";
00625    buflen = strlen(preflang) + strlen(filename) + 4;
00626    buf = alloca(buflen);
00627    if (buf == NULL)
00628       return NULL;
00629 
00630    for (format = AST_FORMAT_MAX_AUDIO << 1; format <= AST_FORMAT_MAX_VIDEO; format = format << 1) {
00631       int fd;
00632       const char *fmt;
00633 
00634       if (!(chan->nativeformats & format))
00635          continue;
00636       fmt = ast_getformatname(format);
00637       if ( fileexists_core(filename, fmt, preflang, buf, buflen) < 1)   /* no valid format */
00638          continue;
00639       fd = ast_filehelper(buf, chan, fmt, ACTION_OPEN);
00640       if (fd >= 0)
00641          return chan->vstream;
00642       ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename);
00643    }
00644    return NULL;
00645 }

int ast_playstream ( struct ast_filestream s  ) 

play a open stream on a channel.

Parameters:
s filestream to play Returns 0 for success, -1 on failure

Definition at line 770 of file file.c.

References AST_FORMAT_MAX_AUDIO, ast_readaudio_callback(), ast_readvideo_callback(), ast_filestream::fmt, ast_format::format, and FSREAD_FAILURE.

Referenced by ast_streamfile(), handle_getoption(), handle_streamfile(), and speech_streamfile().

00771 {
00772    enum fsread_res res;
00773 
00774    if (s->fmt->format < AST_FORMAT_MAX_AUDIO)
00775       res = ast_readaudio_callback(s);
00776    else
00777       res = ast_readvideo_callback(s);
00778 
00779    return (res == FSREAD_FAILURE) ? -1 : 0;
00780 }

static enum fsread_res ast_readaudio_callback ( struct ast_filestream s  )  [static]

Definition at line 664 of file file.c.

References ast_format_rate(), ast_fsread_audio(), ast_log(), ast_sched_add(), ast_settimeout(), ast_write(), ast_filestream::fmt, ast_format::format, FSREAD_FAILURE, FSREAD_SUCCESS_NOSCHED, FSREAD_SUCCESS_SCHED, ast_filestream::lasttimeout, LOG_WARNING, ast_filestream::orig_chan_name, ast_filestream::owner, ast_format::read, ast_channel::sched, ast_channel::streamid, and ast_channel::timingfd.

Referenced by ast_fsread_audio(), and ast_playstream().

00665 {
00666    int whennext = 0;
00667 
00668    while (!whennext) {
00669       struct ast_frame *fr;
00670       
00671       if (s->orig_chan_name && strcasecmp(s->owner->name, s->orig_chan_name))
00672          goto return_failure;
00673       
00674       fr = s->fmt->read(s, &whennext);
00675       if (!fr /* stream complete */ || ast_write(s->owner, fr) /* error writing */) {
00676          if (fr)
00677             ast_log(LOG_WARNING, "Failed to write frame\n");
00678          goto return_failure;
00679       }
00680    }
00681    if (whennext != s->lasttimeout) {
00682 #ifdef HAVE_ZAPTEL
00683       if (s->owner->timingfd > -1) {
00684          int zap_timer_samples = whennext;
00685          int rate;
00686          /* whennext is in samples, but zaptel timers operate in 8 kHz samples. */
00687          if ((rate = ast_format_rate(s->fmt->format)) != 8000) {
00688             float factor;
00689             factor = ((float) rate) / ((float) 8000.0); 
00690             zap_timer_samples = (int) ( ((float) zap_timer_samples) / factor );
00691          }
00692          ast_settimeout(s->owner, zap_timer_samples, ast_fsread_audio, s);
00693       } else
00694 #endif      
00695          s->owner->streamid = ast_sched_add(s->owner->sched, 
00696             whennext / (ast_format_rate(s->fmt->format) / 1000), 
00697             ast_fsread_audio, s);
00698       s->lasttimeout = whennext;
00699       return FSREAD_SUCCESS_NOSCHED;
00700    }
00701    return FSREAD_SUCCESS_SCHED;
00702 
00703 return_failure:
00704    s->owner->streamid = -1;
00705 #ifdef HAVE_ZAPTEL
00706    ast_settimeout(s->owner, 0, NULL, NULL);
00707 #endif         
00708    return FSREAD_FAILURE;
00709 }

struct ast_filestream* ast_readfile ( const char *  filename,
const char *  type,
const char *  comment,
int  flags,
int  check,
mode_t  mode 
) [read]

Starts reading from a file

Parameters:
filename the name of the file to read from
type format of file you wish to read from
comment comment to go with
flags file flags
check (unimplemented, hence negligible)
mode Open mode Open an incoming file stream. flags are flags for the open() command, and if check is non-zero, then it will not read a file if there are any files that start with that name and have an extension Please note, this is a blocking function. Program execution will not return until ast_waitstream completes it's execution. Returns a struct ast_filestream on success, NULL on failure

Definition at line 916 of file file.c.

References ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), build_filename(), errno, ast_format::exts, exts_compare(), f, ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, free, get_filestream(), LOG_WARNING, ast_filestream::mode, open_wrapper(), strdup, ast_filestream::trans, and ast_filestream::vfs.

Referenced by __ast_play_and_record(), cli_audio_convert(), and cli_audio_convert_deprecated().

00917 {
00918    FILE *bfile;
00919    struct ast_format *f;
00920    struct ast_filestream *fs = NULL;
00921    char *fn;
00922 
00923    if (AST_LIST_LOCK(&formats)) {
00924       ast_log(LOG_WARNING, "Unable to lock format list\n");
00925       return NULL;
00926    }
00927 
00928    AST_LIST_TRAVERSE(&formats, f, list) {
00929       fs = NULL;
00930       if (!exts_compare(f->exts, type))
00931          continue;
00932 
00933       fn = build_filename(filename, type);
00934       errno = 0;
00935       bfile = fopen(fn, "r");
00936       if (!bfile || (fs = get_filestream(f, bfile)) == NULL ||
00937           open_wrapper(fs) ) {
00938          ast_log(LOG_WARNING, "Unable to open %s\n", fn);
00939          if (fs)
00940             ast_free(fs);
00941          if (bfile)
00942             fclose(bfile);
00943          free(fn);
00944          continue;
00945       }
00946       /* found it */
00947       fs->trans = NULL;
00948       fs->fmt = f;
00949       fs->flags = flags;
00950       fs->mode = mode;
00951       fs->filename = strdup(filename);
00952       fs->vfs = NULL;
00953       break;
00954    }
00955 
00956    AST_LIST_UNLOCK(&formats);
00957    if (!fs) 
00958       ast_log(LOG_WARNING, "No such format '%s'\n", type);
00959 
00960    return fs;
00961 }

struct ast_frame* ast_readframe ( struct ast_filestream s  )  [read]

Read a frame from a filestream

Parameters:
s ast_filestream to act on Returns a frame or NULL if read failed

Definition at line 647 of file file.c.

References f, ast_filestream::fmt, and ast_format::read.

Referenced by __ast_play_and_record(), cli_audio_convert(), cli_audio_convert_deprecated(), dictate_exec(), gen_readframe(), and moh_files_readframe().

00648 {
00649    struct ast_frame *f = NULL;
00650    int whennext = 0; 
00651    if (s && s->fmt)
00652       f = s->fmt->read(s, &whennext);
00653    return f;
00654 }

static enum fsread_res ast_readvideo_callback ( struct ast_filestream s  )  [static]

Definition at line 726 of file file.c.

References ast_format_rate(), ast_fsread_video(), ast_log(), ast_sched_add(), ast_write(), ast_filestream::fmt, ast_format::format, FSREAD_FAILURE, FSREAD_SUCCESS_NOSCHED, FSREAD_SUCCESS_SCHED, ast_filestream::lasttimeout, LOG_WARNING, ast_filestream::owner, ast_format::read, ast_channel::sched, and ast_channel::vstreamid.

Referenced by ast_fsread_video(), and ast_playstream().

00727 {
00728    int whennext = 0;
00729 
00730    while (!whennext) {
00731       struct ast_frame *fr = s->fmt->read(s, &whennext);
00732       if (!fr || ast_write(s->owner, fr)) { /* no stream or error, as above */
00733          if (fr)
00734             ast_log(LOG_WARNING, "Failed to write frame\n");
00735          s->owner->vstreamid = -1;
00736          return FSREAD_FAILURE;
00737       }
00738    }
00739 
00740    if (whennext != s->lasttimeout) {
00741       s->owner->vstreamid = ast_sched_add(s->owner->sched, 
00742          whennext / (ast_format_rate(s->fmt->format) / 1000), 
00743          ast_fsread_video, s);
00744       s->lasttimeout = whennext;
00745       return FSREAD_SUCCESS_NOSCHED;
00746    }
00747 
00748    return FSREAD_SUCCESS_SCHED;
00749 }

int ast_seekstream ( struct ast_filestream fs,
off_t  sample_offset,
int  whence 
)

Seeks into stream

Parameters:
fs ast_filestream to perform seek on
sample_offset numbers of samples to seek
whence SEEK_SET, SEEK_CUR, SEEK_END Returns 0 for success, or -1 for error

Definition at line 782 of file file.c.

References ast_filestream::fmt, and ast_format::seek.

Referenced by __ast_read(), ast_control_streamfile(), ast_moh_files_next(), ast_stream_fastforward(), ast_stream_rewind(), ast_write(), dictate_exec(), handle_getoption(), handle_recordfile(), and handle_streamfile().

00783 {
00784    return fs->fmt->seek(fs, sample_offset, whence);
00785 }

int ast_stopstream ( struct ast_channel c  ) 

Stops a stream.

Parameters:
c The channel you wish to stop playback on
Stop playback of a stream

Return values:
0 always
Note:
The channel does not need to be locked before calling this function.

Definition at line 137 of file file.c.

References ast_channel_lock, ast_channel_unlock, ast_closestream(), ast_log(), ast_set_write_format(), LOG_WARNING, ast_channel::oldwriteformat, ast_channel::stream, and ast_channel::vstream.

Referenced by ast_adsi_transmit_message_full(), ast_control_streamfile(), ast_openstream_full(), ast_play_and_wait(), ast_readstring_full(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_number_full_cz(), ast_say_number_full_da(), ast_say_number_full_de(), ast_say_number_full_en(), ast_say_number_full_en_GB(), ast_say_number_full_es(), ast_say_number_full_fr(), ast_say_number_full_ge(), ast_say_number_full_gr(), ast_say_number_full_he(), ast_say_number_full_it(), ast_say_number_full_nl(), ast_say_number_full_no(), ast_say_number_full_pt(), ast_say_number_full_ru(), ast_say_number_full_se(), ast_say_number_full_tw(), background_detect_exec(), builtin_blindtransfer(), conf_exec(), conf_run(), directory_exec(), handle_getoption(), handle_streamfile(), ices_exec(), ivr_dispatch(), leave_voicemail(), mp3_exec(), NBScat_exec(), parkandannounce_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_file(), play_mailbox_owner(), playback_exec(), queue_exec(), read_exec(), record_exec(), recordthread(), rpt_tele_thread(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), saycharstr(), sayfile(), saynum(), send_morse(), send_tone_telemetry(), send_waveform_to_channel(), speech_background(), vm_authenticate(), vm_execmain(), wait_for_winner(), waitstream_core(), and zapateller_exec().

00138 {
00139    ast_channel_lock(tmp);
00140 
00141    /* Stop a running stream if there is one */
00142    if (tmp->stream) {
00143       ast_closestream(tmp->stream);
00144       tmp->stream = NULL;
00145       if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat))
00146          ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat);
00147    }
00148    /* Stop the video stream too */
00149    if (tmp->vstream != NULL) {
00150       ast_closestream(tmp->vstream);
00151       tmp->vstream = NULL;
00152    }
00153 
00154    ast_channel_unlock(tmp);
00155 
00156    return 0;
00157 }

int ast_stream_and_wait ( struct ast_channel chan,
const char *  file,
const char *  language,
const char *  digits 
)

int ast_stream_fastforward ( struct ast_filestream fs,
off_t  ms 
)

Fast forward stream ms

Parameters:
fs filestream to act on
ms milliseconds to move Returns 0 for success, or -1 for error

Definition at line 797 of file file.c.

References ast_seekstream(), and DEFAULT_SAMPLES_PER_MS.

Referenced by waitstream_core().

00798 {
00799    return ast_seekstream(fs, ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR);
00800 }

int ast_stream_rewind ( struct ast_filestream fs,
off_t  ms 
)

Rewind stream ms

Parameters:
fs filestream to act on
ms milliseconds to move Returns 0 for success, or -1 for error

Definition at line 802 of file file.c.

References ast_seekstream(), and DEFAULT_SAMPLES_PER_MS.

Referenced by __ast_play_and_record(), handle_recordfile(), record_exec(), and waitstream_core().

00803 {
00804    return ast_seekstream(fs, -ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR);
00805 }

int ast_streamfile ( struct ast_channel c,
const char *  filename,
const char *  preflang 
)

Streams a file

Parameters:
c channel to stream the file to
filename the name of the file you wish to stream, minus the extension
preflang the preferred language you wish to have the file streamed to you in Prepares a channel for the streaming of a file. To start the stream, afterward do a ast_waitstream() on the channel Also, it will stop any existing streams on the channel. Returns 0 on success, or -1 on failure.

Definition at line 885 of file file.c.

References ast_applystream(), AST_FLAG_MASQ_NOSTREAM, ast_getformatname(), ast_getformatname_multiple(), ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_strdup, ast_test_flag, ast_verbose(), errno, ast_filestream::fmt, fmt, ast_format::format, LOG_DEBUG, LOG_WARNING, ast_channel::nativeformats, option_verbose, ast_filestream::orig_chan_name, VERBOSE_PREFIX_3, and ast_filestream::vfs.

Referenced by __login_exec(), action_bridge(), agent_call(), app_exec(), ast_app_getdata(), ast_app_getdata_full(), ast_control_streamfile(), ast_play_and_wait(), ast_retrieve_call(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_ge(), ast_say_date_gr(), ast_say_date_nl(), ast_say_date_with_format_gr(), ast_say_datetime_en(), ast_say_datetime_fr(), ast_say_datetime_from_now_en(), ast_say_datetime_from_now_fr(), ast_say_datetime_from_now_ge(), ast_say_datetime_gr(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_tw(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_number_full_cz(), ast_say_number_full_da(), ast_say_number_full_de(), ast_say_number_full_en(), ast_say_number_full_en_GB(), ast_say_number_full_es(), ast_say_number_full_fr(), ast_say_number_full_ge(), ast_say_number_full_gr(), ast_say_number_full_he(), ast_say_number_full_it(), ast_say_number_full_nl(), ast_say_number_full_no(), ast_say_number_full_pt(), ast_say_number_full_ru(), ast_say_number_full_se(), ast_say_number_full_tw(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_ge(), ast_say_time_gr(), ast_say_time_nl(), ast_say_time_tw(), ast_stream_and_wait(), auth_exec(), autoanswer_exec(), background_detect_exec(), bridge_exec(), check_availability(), check_beep(), common_exec(), conf_exec(), conf_run(), do_directory(), forward_message(), gr_say_number_female(), handle_recordfile(), leave_voicemail(), page_exec(), park_exec(), parkandannounce_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_and_wait(), play_file(), play_greeting(), playback_exec(), privacy_exec(), record_exec(), retrydial_exec(), rpt_tele_thread(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), sayfile(), ss_thread(), vm_authenticate(), wait_file(), and wait_for_winner().

00886 {
00887    struct ast_filestream *fs;
00888    struct ast_filestream *vfs=NULL;
00889    char fmt[256];
00890 
00891    fs = ast_openstream(chan, filename, preflang);
00892    if (fs)
00893       vfs = ast_openvstream(chan, filename, preflang);
00894    if (vfs)
00895       ast_log(LOG_DEBUG, "Ooh, found a video stream, too, format %s\n", ast_getformatname(vfs->fmt->format));
00896    if (fs){
00897       int res;
00898       if (ast_test_flag(chan, AST_FLAG_MASQ_NOSTREAM))
00899          fs->orig_chan_name = ast_strdup(chan->name);
00900       if (ast_applystream(chan, fs))
00901          return -1;
00902       if (vfs && ast_applystream(chan, vfs))
00903          return -1;
00904       res = ast_playstream(fs);
00905       if (!res && vfs)
00906          res = ast_playstream(vfs);
00907       if (option_verbose > 2)
00908          ast_verbose(VERBOSE_PREFIX_3 "<%s> Playing '%s' (language '%s')\n", chan->name, filename, preflang ? preflang : "default");
00909 
00910       return res;
00911    }
00912    ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname_multiple(fmt, sizeof(fmt), chan->nativeformats), strerror(errno));
00913    return -1;
00914 }

off_t ast_tellstream ( struct ast_filestream fs  ) 

Tell where we are in a stream

Parameters:
fs fs to act on Returns a long as a sample offset into stream

Definition at line 792 of file file.c.

References ast_filestream::fmt, and ast_format::tell.

Referenced by __ast_play_and_record(), ast_control_streamfile(), handle_getoption(), handle_recordfile(), and handle_streamfile().

00793 {
00794    return fs->fmt->tell(fs);
00795 }

int ast_truncstream ( struct ast_filestream fs  ) 

Trunc stream at current location

Parameters:
fs filestream to act on Returns 0 for success, or -1 for error

Definition at line 787 of file file.c.

References ast_filestream::fmt, and ast_format::trunc.

Referenced by __ast_play_and_record(), handle_recordfile(), and record_exec().

00788 {
00789    return fs->fmt->trunc(fs);
00790 }

int ast_waitstream ( struct ast_channel c,
const char *  breakon 
)

Waits for a stream to stop or digit to be pressed

Parameters:
c channel to waitstream on
breakon string of DTMF digits to break upon Begins playback of a stream... Wait for a stream to stop or for any one of a given digit to arrive, Returns 0 if the stream finishes, the character if it was interrupted, and -1 on error

Definition at line 1231 of file file.c.

References waitstream_core().

Referenced by __login_exec(), action_bridge(), agent_call(), app_exec(), ast_play_and_wait(), ast_retrieve_call(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_ge(), ast_say_date_gr(), ast_say_date_nl(), ast_say_date_with_format_gr(), ast_say_datetime_en(), ast_say_datetime_fr(), ast_say_datetime_from_now_en(), ast_say_datetime_from_now_fr(), ast_say_datetime_from_now_ge(), ast_say_datetime_gr(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_tw(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_number_full_cz(), ast_say_number_full_da(), ast_say_number_full_de(), ast_say_number_full_en(), ast_say_number_full_en_GB(), ast_say_number_full_es(), ast_say_number_full_fr(), ast_say_number_full_ge(), ast_say_number_full_gr(), ast_say_number_full_he(), ast_say_number_full_it(), ast_say_number_full_nl(), ast_say_number_full_no(), ast_say_number_full_pt(), ast_say_number_full_ru(), ast_say_number_full_se(), ast_say_number_full_tw(), ast_say_time_de(), ast_say_time_en(), ast_say_time_ge(), ast_say_time_gr(), ast_say_time_nl(), ast_say_time_tw(), ast_stream_and_wait(), auth_exec(), autoanswer_exec(), bridge_exec(), check_availability(), check_beep(), common_exec(), conf_exec(), conf_run(), directory_exec(), gr_say_number_female(), handle_recordfile(), leave_voicemail(), page_exec(), park_exec(), parkandannounce_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_and_wait(), play_file(), play_greeting(), playback_exec(), privacy_exec(), record_exec(), retrydial_exec(), rpt_tele_thread(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), saycharstr(), sayfile(), saynum(), send_morse(), send_tone_telemetry(), ss_thread(), vm_authenticate(), and wait_file().

01232 {
01233    return waitstream_core(c, breakon, NULL, NULL, 0, -1, -1, NULL);
01234 }

int ast_waitstream_exten ( struct ast_channel c,
const char *  context 
)

Waits for a stream to stop or digit matching a valid one digit exten to be pressed

Parameters:
c channel to waitstream on
context string of context to match digits to break upon Begins playback of a stream... Wait for a stream to stop or for any one of a valid extension digit to arrive, Returns 0 if the stream finishes, the character if it was interrupted, and -1 on error

Definition at line 1242 of file file.c.

References ast_channel::context, and waitstream_core().

Referenced by pbx_builtin_background().

01243 {
01244    /* Waitstream, with return in the case of a valid 1 digit extension */
01245    /* in the current or specified context being pressed */
01246 
01247    if (!context)
01248       context = c->context;
01249    return waitstream_core(c, NULL, NULL, NULL, 0,
01250       -1, -1, context);
01251 }

int ast_waitstream_fr ( struct ast_channel c,
const char *  breakon,
const char *  forward,
const char *  rewind,
int  ms 
)

Same as waitstream but allows stream to be forwarded or rewound

Parameters:
c channel to waitstream on
breakon string of DTMF digits to break upon
forward DTMF digit to fast forward upon
rewind DTMF digit to rewind upon
ms How many miliseconds to skip forward/back Begins playback of a stream... Wait for a stream to stop or for any one of a given digit to arrive, Returns 0 if the stream finishes, the character if it was interrupted, and -1 on error

Definition at line 1225 of file file.c.

References waitstream_core().

Referenced by ast_control_streamfile().

01226 {
01227    return waitstream_core(c, breakon, forward, rewind, ms,
01228       -1 /* no audiofd */, -1 /* no cmdfd */, NULL /* no context */);
01229 }

int ast_waitstream_full ( struct ast_channel c,
const char *  breakon,
int  audiofd,
int  cmdfd 
)

struct ast_filestream* ast_writefile ( const char *  filename,
const char *  type,
const char *  comment,
int  flags,
int  check,
mode_t  mode 
) [read]

Starts writing a file

Parameters:
filename the name of the file to write to
type format of file you wish to write out to
comment comment to go with
flags output file flags
check (unimplemented, hence negligible)
mode Open mode Create an outgoing file stream. oflags are flags for the open() command, and if check is non-zero, then it will not write a file if there are any files that start with that name and have an extension Please note, this is a blocking function. Program execution will not return until ast_waitstream completes it's execution. Returns a struct ast_filestream on success, NULL on failure

Definition at line 963 of file file.c.

References ast_free, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_opt_cache_record_files, ast_strdupa, ast_filestream::buf, build_filename(), errno, ast_format::exts, exts_compare(), f, ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, free, get_filestream(), LOG_WARNING, ast_filestream::mode, ast_filestream::realfilename, record_cache_dir, rewrite_wrapper(), ast_format::seek, strdup, ast_filestream::trans, and ast_filestream::vfs.

Referenced by __ast_play_and_record(), ast_monitor_start(), ast_writestream(), cli_audio_convert(), cli_audio_convert_deprecated(), dictate_exec(), handle_recordfile(), mixmonitor_thread(), record_exec(), recordthread(), and rpt().

00964 {
00965    int fd, myflags = 0;
00966    /* compiler claims this variable can be used before initialization... */
00967    FILE *bfile = NULL;
00968    struct ast_format *f;
00969    struct ast_filestream *fs = NULL;
00970    char *buf = NULL;
00971    size_t size = 0;
00972    int format_found = 0;
00973 
00974    if (AST_LIST_LOCK(&formats)) {
00975       ast_log(LOG_WARNING, "Unable to lock format list\n");
00976       return NULL;
00977    }
00978 
00979    /* set the O_TRUNC flag if and only if there is no O_APPEND specified */
00980    /* We really can't use O_APPEND as it will break WAV header updates */
00981    if (flags & O_APPEND) { 
00982       flags &= ~O_APPEND;
00983    } else {
00984       myflags = O_TRUNC;
00985    }
00986    
00987    myflags |= O_WRONLY | O_CREAT;
00988 
00989    /* XXX need to fix this - we should just do the fopen,
00990     * not open followed by fdopen()
00991     */
00992    AST_LIST_TRAVERSE(&formats, f, list) {
00993       char *fn, *orig_fn = NULL;
00994       if (fs)
00995          break;
00996 
00997       if (!exts_compare(f->exts, type))
00998          continue;
00999       else
01000          format_found = 1;
01001 
01002       fn = build_filename(filename, type);
01003       fd = open(fn, flags | myflags, mode);
01004       if (fd > -1) {
01005          /* fdopen() the resulting file stream */
01006          bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w");
01007          if (!bfile) {
01008             ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno));
01009             close(fd);
01010             fd = -1;
01011          }
01012       }
01013       
01014       if (ast_opt_cache_record_files && (fd > -1)) {
01015          char *c;
01016 
01017          fclose(bfile); /* this also closes fd */
01018          /*
01019            We touch orig_fn just as a place-holder so other things (like vmail) see the file is there.
01020            What we are really doing is writing to record_cache_dir until we are done then we will mv the file into place.
01021          */
01022          orig_fn = ast_strdupa(fn);
01023          for (c = fn; *c; c++)
01024             if (*c == '/')
01025                *c = '_';
01026 
01027          size = strlen(fn) + strlen(record_cache_dir) + 2;
01028          buf = alloca(size);
01029          strcpy(buf, record_cache_dir);
01030          strcat(buf, "/");
01031          strcat(buf, fn);
01032          free(fn);
01033          fn = buf;
01034          fd = open(fn, flags | myflags, mode);
01035          if (fd > -1) {
01036             /* fdopen() the resulting file stream */
01037             bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w");
01038             if (!bfile) {
01039                ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno));
01040                close(fd);
01041                fd = -1;
01042             }
01043          }
01044       }
01045       if (fd > -1) {
01046          errno = 0;
01047          fs = get_filestream(f, bfile);
01048          if (!fs || rewrite_wrapper(fs, comment)) {
01049             ast_log(LOG_WARNING, "Unable to rewrite %s\n", fn);
01050             close(fd);
01051             if (orig_fn) {
01052                unlink(fn);
01053                unlink(orig_fn);
01054             }
01055             if (fs)
01056                ast_free(fs);
01057             fs = NULL;
01058             continue;
01059          }
01060          fs->trans = NULL;
01061          fs->fmt = f;
01062          fs->flags = flags;
01063          fs->mode = mode;
01064          if (orig_fn) {
01065             fs->realfilename = strdup(orig_fn);
01066             fs->filename = strdup(fn);
01067          } else {
01068             fs->realfilename = NULL;
01069             fs->filename = strdup(filename);
01070          }
01071          fs->vfs = NULL;
01072          /* If truncated, we'll be at the beginning; if not truncated, then append */
01073          f->seek(fs, 0, SEEK_END);
01074       } else if (errno != EEXIST) {
01075          ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno));
01076          if (orig_fn)
01077             unlink(orig_fn);
01078       }
01079       /* if buf != NULL then fn is already free and pointing to it */
01080       if (!buf)
01081          free(fn);
01082    }
01083 
01084    AST_LIST_UNLOCK(&formats);
01085 
01086    if (!format_found)
01087       ast_log(LOG_WARNING, "No such format '%s'\n", type);
01088 
01089    return fs;
01090 }

int ast_writestream ( struct ast_filestream fs,
struct ast_frame f 
)

Writes a frame to a stream

Parameters:
fs filestream to write to
f frame to write to the filestream Send a frame to a filestream -- note: does NOT free the frame, call ast_frfree manually Returns 0 on success, -1 on failure.

Definition at line 159 of file file.c.

References AST_FORMAT_MAX_AUDIO, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_getformatname(), ast_log(), ast_translate(), ast_translator_build_path(), ast_translator_free_path(), ast_writefile(), ast_writestream(), ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, ast_format::format, ast_frame::frametype, ast_filestream::lastwriteformat, LOG_DEBUG, LOG_WARNING, ast_filestream::mode, ast_format::name, ast_frame::subclass, ast_filestream::trans, type, ast_filestream::vfs, and ast_format::write.

Referenced by __ast_play_and_record(), __ast_read(), ast_write(), ast_writestream(), cli_audio_convert(), cli_audio_convert_deprecated(), dictate_exec(), handle_recordfile(), mixmonitor_thread(), record_exec(), recordthread(), and rpt().

00160 {
00161    int res = -1;
00162    int alt = 0;
00163    if (f->frametype == AST_FRAME_VIDEO) {
00164       if (fs->fmt->format < AST_FORMAT_MAX_AUDIO) {
00165          /* This is the audio portion.  Call the video one... */
00166          if (!fs->vfs && fs->filename) {
00167             const char *type = ast_getformatname(f->subclass & ~0x1);
00168             fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode);
00169             ast_log(LOG_DEBUG, "Opened video output file\n");
00170          }
00171          if (fs->vfs)
00172             return ast_writestream(fs->vfs, f);
00173          /* else ignore */
00174          return 0;            
00175       } else {
00176          /* Might / might not have mark set */
00177          alt = 1;
00178       }
00179    } else if (f->frametype != AST_FRAME_VOICE) {
00180       ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
00181       return -1;
00182    }
00183    if (((fs->fmt->format | alt) & f->subclass) == f->subclass) {
00184       res =  fs->fmt->write(fs, f);
00185       if (res < 0) 
00186          ast_log(LOG_WARNING, "Natural write failed\n");
00187       else if (res > 0)
00188          ast_log(LOG_WARNING, "Huh??\n");
00189    } else {
00190       /* XXX If they try to send us a type of frame that isn't the normal frame, and isn't
00191              the one we've setup a translator for, we do the "wrong thing" XXX */
00192       if (fs->trans && f->subclass != fs->lastwriteformat) {
00193          ast_translator_free_path(fs->trans);
00194          fs->trans = NULL;
00195       }
00196       if (!fs->trans) 
00197          fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass);
00198       if (!fs->trans)
00199          ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n",
00200             fs->fmt->name, ast_getformatname(f->subclass));
00201       else {
00202          struct ast_frame *trf;
00203          fs->lastwriteformat = f->subclass;
00204          /* Get the translated frame but don't consume the original in case they're using it on another stream */
00205          trf = ast_translate(fs->trans, f, 0);
00206          if (trf) {
00207             res = fs->fmt->write(fs, trf);
00208             ast_frfree(trf);
00209             if (res) 
00210                ast_log(LOG_WARNING, "Translated frame write failed\n");
00211          } else
00212             res = 0;
00213       }
00214    }
00215    return res;
00216 }

static char* build_filename ( const char *  filename,
const char *  ext 
) [static]

construct a filename. Absolute pathnames are preserved, relative names are prefixed by the sounds/ directory. The wav49 suffix is replaced by 'WAV'. Returns a malloc'ed string to be freed by the caller.

Definition at line 261 of file file.c.

References asprintf, and ast_config_AST_DATA_DIR.

Referenced by ast_filehelper(), ast_readfile(), and ast_writefile().

00262 {
00263    char *fn = NULL;
00264 
00265    if (!strcmp(ext, "wav49"))
00266       ext = "WAV";
00267 
00268    if (filename[0] == '/')
00269       asprintf(&fn, "%s.%s", filename, ext);
00270    else
00271       asprintf(&fn, "%s/sounds/%s.%s",
00272          ast_config_AST_DATA_DIR, filename, ext);
00273    return fn;
00274 }

static int copy ( const char *  infile,
const char *  outfile 
) [static]

Definition at line 218 of file file.c.

References ast_log(), errno, len, and LOG_WARNING.

Referenced by action_getvar(), ast_filehelper(), copy_plain_file(), and iax2_register().

00219 {
00220    int ifd, ofd, len;
00221    char buf[4096];   /* XXX make it lerger. */
00222 
00223    if ((ifd = open(infile, O_RDONLY)) < 0) {
00224       ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile);
00225       return -1;
00226    }
00227    if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) {
00228       ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile);
00229       close(ifd);
00230       return -1;
00231    }
00232    while ( (len = read(ifd, buf, sizeof(buf)) ) ) {
00233       int res;
00234       if (len < 0) {
00235          ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
00236          break;
00237       }
00238       /* XXX handle partial writes */
00239       res = write(ofd, buf, len);
00240       if (res != len) {
00241          ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
00242          len = -1; /* error marker */
00243          break;
00244       }
00245    }
00246    close(ifd);
00247    close(ofd);
00248    if (len < 0) {
00249       unlink(outfile);
00250       return -1; /* error */
00251    }
00252    return 0;   /* success */
00253 }

static int exts_compare ( const char *  exts,
const char *  type 
) [static]

Definition at line 278 of file file.c.

References ext, and strsep().

Referenced by ast_filehelper(), ast_readfile(), and ast_writefile().

00279 {
00280    char tmp[256];
00281    char *stringp = tmp, *ext;
00282 
00283    ast_copy_string(tmp, exts, sizeof(tmp));
00284    while ((ext = strsep(&stringp, "|"))) {
00285       if (!strcmp(ext, type))
00286          return 1;
00287    }
00288 
00289    return 0;
00290 }

static int fileexists_core ( const char *  filename,
const char *  fmt,
const char *  preflang,
char *  buf,
int  buflen 
) [static]

helper routine to locate a file with a given format and language preference. Try preflang, preflang with stripped '_' suffix, or NULL. In the standard asterisk, language goes just before the last component. In an alternative configuration, the language should be a prefix to the actual filename.

The last parameter(s) point to a buffer of sufficient size, which on success is filled with the matching filename.

Definition at line 520 of file file.c.

References ast_strdupa, ast_strlen_zero(), DEFAULT_LANGUAGE, fileexists_test(), and strsep().

Referenced by ast_fileexists(), ast_openstream_full(), and ast_openvstream().

00522 {
00523    int res = -1;
00524    char *lang = NULL;
00525 
00526    if (buf == NULL) {
00527       return -1;
00528    }
00529 
00530    /* We try languages in the following order:
00531     *    preflang (may include dialect)
00532     *    lang (preflang without dialect - if any)
00533     *    <none>
00534     *    default (unless the same as preflang or lang without dialect)
00535     */
00536 
00537    /* Try preferred language */
00538    if (!ast_strlen_zero(preflang)) {
00539       /* try the preflang exactly as it was requested */
00540       if ((res = fileexists_test(filename, fmt, preflang, buf, buflen)) > 0) {
00541          return res;
00542       } else {
00543          /* try without a dialect */
00544          char *postfix = NULL;
00545          postfix = lang = ast_strdupa(preflang);
00546 
00547          strsep(&postfix, "_");
00548          if (postfix) {
00549             if ((res = fileexists_test(filename, fmt, lang, buf, buflen)) > 0) {
00550                return res;
00551             }
00552          }
00553       }
00554    }
00555 
00556    /* Try without any language */
00557    if ((res = fileexists_test(filename, fmt, NULL, buf, buflen)) > 0) {
00558       return res;
00559    }
00560 
00561    /* Finally try the default language unless it was already tried before */
00562    if ((ast_strlen_zero(preflang) || strcmp(preflang, DEFAULT_LANGUAGE)) && (ast_strlen_zero(lang) || strcmp(lang, DEFAULT_LANGUAGE))) {
00563       if ((res = fileexists_test(filename, fmt, DEFAULT_LANGUAGE, buf, buflen)) > 0) {
00564          return res;
00565       }
00566    }
00567 
00568    return 0;
00569 }

static int fileexists_test ( const char *  filename,
const char *  fmt,
const char *  lang,
char *  buf,
int  buflen 
) [static]

Definition at line 483 of file file.c.

References ACTION_EXISTS, ast_filehelper(), is_absolute_path(), and offset.

Referenced by fileexists_core().

00485 {
00486    if (buf == NULL) {
00487       return -1;
00488    }
00489 
00490    if (ast_language_is_prefix && !is_absolute_path(filename)) { /* new layout */
00491       if (lang) {
00492          snprintf(buf, buflen, "%s/%s", lang, filename);
00493       } else {
00494          snprintf(buf, buflen, "%s", filename);
00495       }
00496    } else { /* old layout */
00497       strcpy(buf, filename);  /* first copy the full string */
00498       if (lang) {
00499          /* insert the language and suffix if needed */
00500          const char *c = strrchr(filename, '/');
00501          int offset = c ? c - filename + 1 : 0; /* points right after the last '/' */
00502          snprintf(buf + offset, buflen - offset, "%s/%s", lang, filename + offset);
00503       }
00504    }
00505 
00506    return ast_filehelper(buf, NULL, fmt, ACTION_EXISTS);
00507 }

static int fn_wrapper ( struct ast_filestream s,
const char *  comment,
enum wrap_fn  mode 
) [static]

Definition at line 316 of file file.c.

References ast_log(), ast_module_ref(), f, ast_filestream::fmt, LOG_WARNING, ast_format::module, ast_format::name, ast_format::open, ast_format::rewrite, WRAP_OPEN, and WRAP_REWRITE.

Referenced by open_wrapper(), and rewrite_wrapper().

00317 {
00318    struct ast_format *f = s->fmt;
00319    int ret = -1;
00320 
00321    if (mode == WRAP_OPEN && f->open && f->open(s))
00322                 ast_log(LOG_WARNING, "Unable to open format %s\n", f->name);
00323    else if (mode == WRAP_REWRITE && f->rewrite && f->rewrite(s, comment))
00324                 ast_log(LOG_WARNING, "Unable to rewrite format %s\n", f->name);
00325    else {
00326       /* preliminary checks succeed. update usecount */
00327       ast_module_ref(f->module);
00328       ret = 0;
00329    }
00330         return ret;
00331 }

static struct ast_filestream* get_filestream ( struct ast_format fmt,
FILE *  bfile 
) [static, read]

Definition at line 292 of file file.c.

References ast_filestream::_private, ast_calloc, ast_filestream::buf, ast_format::buf_size, ast_format::desc_size, ast_filestream::f, ast_filestream::fmt, ast_filestream::fr, ast_format::name, s, and ast_frame::src.

Referenced by ast_filehelper(), ast_readfile(), and ast_writefile().

00293 {
00294    struct ast_filestream *s;
00295 
00296    int l = sizeof(*s) + fmt->buf_size + fmt->desc_size;  /* total allocation size */
00297    if ( (s = ast_calloc(1, l)) == NULL)
00298       return NULL;
00299    s->fmt = fmt;
00300    s->f = bfile;
00301 
00302    if (fmt->desc_size)
00303       s->_private = ((char *)(s+1)) + fmt->buf_size;
00304    if (fmt->buf_size)
00305       s->buf = (char *)(s+1);
00306    s->fr.src = fmt->name;
00307    return s;
00308 }

static int is_absolute_path ( const char *  filename  )  [static]

Definition at line 478 of file file.c.

Referenced by fileexists_test().

00479 {
00480    return filename[0] == '/';
00481 }

static int open_wrapper ( struct ast_filestream s  )  [static]

Definition at line 338 of file file.c.

References fn_wrapper(), and WRAP_OPEN.

Referenced by ast_filehelper(), and ast_readfile().

00339 {
00340    return fn_wrapper(s, NULL, WRAP_OPEN);
00341 }

static int rewrite_wrapper ( struct ast_filestream s,
const char *  comment 
) [static]

Definition at line 333 of file file.c.

References fn_wrapper(), and WRAP_REWRITE.

Referenced by ast_writefile().

00334 {
00335    return fn_wrapper(s, comment, WRAP_REWRITE);
00336 }

static int show_file_formats ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1270 of file file.c.

References ast_cli(), ast_getformatname(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_format::exts, f, ast_format::format, FORMAT, FORMAT2, LOG_WARNING, ast_format::name, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01271 {
01272 #define FORMAT "%-10s %-10s %-20s\n"
01273 #define FORMAT2 "%-10s %-10s %-20s\n"
01274    struct ast_format *f;
01275    int count_fmt = 0;
01276 
01277    if (argc != 4)
01278       return RESULT_SHOWUSAGE;
01279    ast_cli(fd, FORMAT, "Format", "Name", "Extensions");
01280            
01281    if (AST_LIST_LOCK(&formats)) {
01282       ast_log(LOG_WARNING, "Unable to lock format list\n");
01283       return -1;
01284    }
01285 
01286    AST_LIST_TRAVERSE(&formats, f, list) {
01287       ast_cli(fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts);
01288       count_fmt++;
01289    }
01290    AST_LIST_UNLOCK(&formats);
01291    ast_cli(fd, "%d file formats registered.\n", count_fmt);
01292    return RESULT_SUCCESS;
01293 #undef FORMAT
01294 #undef FORMAT2
01295 }

static int show_file_formats_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1297 of file file.c.

References ast_cli(), ast_getformatname(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_format::exts, f, ast_format::format, FORMAT, FORMAT2, LOG_WARNING, ast_format::name, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01298 {
01299 #define FORMAT "%-10s %-10s %-20s\n"
01300 #define FORMAT2 "%-10s %-10s %-20s\n"
01301    struct ast_format *f;
01302    int count_fmt = 0;
01303    
01304    if (argc != 3)
01305       return RESULT_SHOWUSAGE;
01306    ast_cli(fd, FORMAT, "Format", "Name", "Extensions");
01307    
01308    if (AST_LIST_LOCK(&formats)) {
01309       ast_log(LOG_WARNING, "Unable to lock format list\n");
01310       return -1;
01311    }
01312    
01313    AST_LIST_TRAVERSE(&formats, f, list) {
01314       ast_cli(fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts);
01315       count_fmt++;
01316    }
01317    AST_LIST_UNLOCK(&formats);
01318    ast_cli(fd, "%d file formats registered.\n", count_fmt);
01319    return RESULT_SUCCESS;
01320 #undef FORMAT
01321 #undef FORMAT2
01322 }

static int waitstream_core ( struct ast_channel c,
const char *  breakon,
const char *  forward,
const char *  rewind,
int  skip_ms,
int  audiofd,
int  cmdfd,
const char *  context 
) [static]

the core of all waitstream() functions

Definition at line 1095 of file file.c.

References ast_channel::_softhangup, ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, AST_FLAG_MASQ_NOSTREAM, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_VOICE, ast_frfree, ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_set_flag, ast_stopstream(), ast_strdupa, ast_stream_fastforward(), ast_stream_rewind(), ast_test_flag, ast_waitfor(), ast_waitfor_nandfds(), ast_channel::cid, ast_callerid::cid_num, ast_frame::data, ast_frame::datalen, errno, exten, ast_frame::frametype, LOG_WARNING, ast_filestream::orig_chan_name, ast_channel::sched, ast_channel::stream, and ast_frame::subclass.

Referenced by ast_waitstream(), ast_waitstream_exten(), ast_waitstream_fr(), and ast_waitstream_full().

01098 {
01099    const char *orig_chan_name = NULL;
01100    int err = 0;
01101 
01102    if (!breakon)
01103       breakon = "";
01104    if (!forward)
01105       forward = "";
01106    if (!rewind)
01107       rewind = "";
01108 
01109    /* Switch the channel to end DTMF frame only. waitstream_core doesn't care about the start of DTMF. */
01110    ast_set_flag(c, AST_FLAG_END_DTMF_ONLY);
01111 
01112    if (ast_test_flag(c, AST_FLAG_MASQ_NOSTREAM))
01113       orig_chan_name = ast_strdupa(c->name);
01114 
01115    while (c->stream) {
01116       int res;
01117       int ms;
01118 
01119       if (orig_chan_name && strcasecmp(orig_chan_name, c->name)) {
01120          ast_stopstream(c);
01121          err = 1;
01122          break;
01123       }
01124 
01125       ms = ast_sched_wait(c->sched);
01126 
01127       if (ms < 0 && !c->timingfunc) {
01128          ast_stopstream(c);
01129          break;
01130       }
01131       if (ms < 0)
01132          ms = 1000;
01133       if (cmdfd < 0) {
01134          res = ast_waitfor(c, ms);
01135          if (res < 0) {
01136             ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
01137             ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
01138             return res;
01139          }
01140       } else {
01141          int outfd;
01142          struct ast_channel *rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
01143          if (!rchan && (outfd < 0) && (ms)) {
01144             /* Continue */
01145             if (errno == EINTR)
01146                continue;
01147             ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
01148             ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
01149             return -1;
01150          } else if (outfd > -1) { /* this requires cmdfd set */
01151             /* The FD we were watching has something waiting */
01152             ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
01153             return 1;
01154          }
01155          /* if rchan is set, it is 'c' */
01156          res = rchan ? 1 : 0; /* map into 'res' values */
01157       }
01158       if (res > 0) {
01159          struct ast_frame *fr = ast_read(c);
01160          if (!fr) {
01161             ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
01162             return -1;
01163          }
01164          switch(fr->frametype) {
01165          case AST_FRAME_DTMF_END:
01166             if (context) {
01167                const char exten[2] = { fr->subclass, '\0' };
01168                if (ast_exists_extension(c, context, exten, 1, c->cid.cid_num)) {
01169                   res = fr->subclass;
01170                   ast_frfree(fr);
01171                   ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
01172                   return res;
01173                }
01174             } else {
01175                res = fr->subclass;
01176                if (strchr(forward,res)) {
01177                   ast_stream_fastforward(c->stream, skip_ms);
01178                } else if (strchr(rewind,res)) {
01179                   ast_stream_rewind(c->stream, skip_ms);
01180                } else if (strchr(breakon, res)) {
01181                   ast_frfree(fr);
01182                   ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
01183                   return res;
01184                }              
01185             }
01186             break;
01187          case AST_FRAME_CONTROL:
01188             switch(fr->subclass) {
01189             case AST_CONTROL_HANGUP:
01190             case AST_CONTROL_BUSY:
01191             case AST_CONTROL_CONGESTION:
01192                ast_frfree(fr);
01193                ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
01194                return -1;
01195             case AST_CONTROL_RINGING:
01196             case AST_CONTROL_ANSWER:
01197             case AST_CONTROL_VIDUPDATE:
01198             case AST_CONTROL_SRCUPDATE:
01199             case AST_CONTROL_HOLD:
01200             case AST_CONTROL_UNHOLD:
01201                /* Unimportant */
01202                break;
01203             default:
01204                ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
01205             }
01206             break;
01207          case AST_FRAME_VOICE:
01208             /* Write audio if appropriate */
01209             if (audiofd > -1)
01210                write(audiofd, fr->data, fr->datalen);
01211          default:
01212             /* Ignore all others */
01213             break;
01214          }
01215          ast_frfree(fr);
01216       }
01217       ast_sched_runq(c->sched);
01218    }
01219 
01220    ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
01221 
01222    return (err || c->_softhangup) ? -1 : 0;
01223 }


Variable Documentation

Definition at line 64 of file file.c.

Referenced by ast_readconfig().

Initial value:

 {
   { { "core", "show", "file", "formats" },
   show_file_formats, "Displays file formats",
   show_file_formats_usage, NULL, &cli_show_file_formats_deprecated },
}

Definition at line 1333 of file file.c.

Initial value:

 {
   { "show", "file", "formats" },
   show_file_formats_deprecated, NULL,
   NULL }

Definition at line 1328 of file file.c.

Initial value:

 
"Usage: core show file formats\n"
"       Displays currently registered file formats (if any)\n"

Definition at line 1324 of file file.c.


Generated on Thu Oct 8 21:57:49 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.8