Wed Oct 28 15:48:50 2009

Asterisk developer's documentation


file.c File Reference

Generic File Format Support. More...

#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.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 dependency graph for file.c:

Go to the source code of this file.

Data Structures

struct  ast_filestream
struct  ast_format

Defines

#define ACTION_COPY   5
#define ACTION_DELETE   2
#define ACTION_EXISTS   1
#define ACTION_OPEN   4
#define ACTION_RENAME   3
#define FORMAT   "%-10s %-10s %-20s\n"
#define FORMAT2   "%-10s %-10s %-20s\n"

Functions

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 char *filename2, const char *fmt, int action)
int ast_filerename (const char *filename, const char *filename2, const char *fmt)
int ast_format_register (const char *name, const char *exts, int format, struct ast_filestream *(*open)(FILE *f), struct ast_filestream *(*rewrite)(FILE *f, const char *comment), int(*write)(struct ast_filestream *, struct ast_frame *), int(*seek)(struct ast_filestream *, long sample_offset, int whence), int(*trunc)(struct ast_filestream *), long(*tell)(struct ast_filestream *), struct ast_frame *(*read)(struct ast_filestream *, int *whennext), void(*close)(struct ast_filestream *), char *(*getcomment)(struct ast_filestream *))
int ast_format_unregister (const char *name)
 AST_MUTEX_DEFINE_STATIC (formatlock)
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 int ast_readaudio_callback (void *data)
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 int ast_readvideo_callback (void *data)
int ast_seekstream (struct ast_filestream *fs, long sample_offset, int whence)
int ast_stopstream (struct ast_channel *tmp)
int ast_stream_fastforward (struct ast_filestream *fs, long ms)
int ast_stream_rewind (struct ast_filestream *fs, long ms)
int ast_streamfile (struct ast_channel *chan, const char *filename, const char *preflang)
long 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)
static int copy (const char *infile, const char *outfile)
static int exts_compare (const char *exts, const char *type)
static int show_file_formats (int fd, int argc, char *argv[])

Variables

static struct ast_formatformats = NULL
struct ast_cli_entry show_file


Detailed Description

Generic File Format Support.

Definition in file file.c.


Define Documentation

#define ACTION_COPY   5

Definition at line 349 of file file.c.

Referenced by ast_filecopy(), and ast_filehelper().

#define ACTION_DELETE   2

Definition at line 346 of file file.c.

Referenced by ast_filedelete(), and ast_filehelper().

#define ACTION_EXISTS   1

Definition at line 345 of file file.c.

Referenced by ast_fileexists(), and ast_filehelper().

#define ACTION_OPEN   4

Definition at line 348 of file file.c.

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

#define ACTION_RENAME   3

Definition at line 347 of file file.c.

Referenced by ast_filehelper(), and ast_filerename().

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

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


Function Documentation

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 649 of file file.c.

References ast_filestream::owner.

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

00650 {
00651    s->owner = chan;
00652    return 0;
00653 }

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 694 of file file.c.

References AST_FORMAT_MAX_AUDIO, ast_safe_system(), ast_sched_del(), ast_settimeout(), ast_translator_free_path(), ast_format::close, ast_filestream::filename, ast_filestream::fmt, ast_format::format, free, ast_filestream::owner, ast_filestream::realfilename, ast_channel::sched, ast_channel::stream, ast_channel::streamid, ast_filestream::trans, ast_channel::vstream, and ast_channel::vstreamid.

Referenced by ast_app_getvoice(), ast_filehelper(), ast_hangup(), ast_moh_files_next(), ast_monitor_start(), ast_monitor_stop(), ast_play_and_prepend(), ast_play_and_record_full(), ast_stopstream(), dictate_exec(), gen_closestream(), handle_recordfile(), local_ast_moh_stop(), mixmonitor_thread(), moh_files_release(), record_exec(), and recordthread().

00695 {
00696    char *cmd = NULL;
00697    size_t size = 0;
00698    /* Stop a running stream if there is one */
00699    if (f->owner) {
00700       if (f->fmt->format < AST_FORMAT_MAX_AUDIO) {
00701          f->owner->stream = NULL;
00702          if (f->owner->streamid > -1)
00703             ast_sched_del(f->owner->sched, f->owner->streamid);
00704          f->owner->streamid = -1;
00705 #ifdef ZAPTEL_OPTIMIZATIONS
00706          ast_settimeout(f->owner, 0, NULL, NULL);
00707 #endif         
00708       } else {
00709          f->owner->vstream = NULL;
00710          if (f->owner->vstreamid > -1)
00711             ast_sched_del(f->owner->sched, f->owner->vstreamid);
00712          f->owner->vstreamid = -1;
00713       }
00714    }
00715    /* destroy the translator on exit */
00716    if (f->trans) {
00717       ast_translator_free_path(f->trans);
00718       f->trans = NULL;
00719    }
00720 
00721    if (f->realfilename && f->filename) {
00722          size = strlen(f->filename) + strlen(f->realfilename) + 15;
00723          cmd = alloca(size);
00724          memset(cmd,0,size);
00725          snprintf(cmd,size,"/bin/mv -f %s %s",f->filename,f->realfilename);
00726          ast_safe_system(cmd);
00727    }
00728 
00729    if (f->filename) {
00730       free(f->filename);
00731       f->filename = NULL;
00732    }
00733    if (f->realfilename) {
00734       free(f->realfilename);
00735       f->realfilename = NULL;
00736    }
00737    f->fmt->close(f);
00738    return 0;
00739 }

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 1302 of file file.c.

References ast_cli_register().

Referenced by main().

01303 {
01304    ast_cli_register(&show_file);
01305    return 0;
01306 }

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 800 of file file.c.

References ACTION_COPY, and ast_filehelper().

Referenced by copy_file().

00801 {
00802    return ast_filehelper(filename, filename2, fmt, ACTION_COPY);
00803 }

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 790 of file file.c.

References ACTION_DELETE, and ast_filehelper().

Referenced by ast_monitor_start(), ast_monitor_stop(), ast_play_and_prepend(), conf_run(), dial_exec_full(), leave_voicemail(), play_mailbox_owner(), play_record_review(), and vm_delete().

00791 {
00792    return ast_filehelper(filename, NULL, fmt, ACTION_DELETE);
00793 }

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 742 of file file.c.

References ACTION_EXISTS, ast_filehelper(), ast_strlen_zero(), MAX_LANGUAGE, and strsep().

Referenced by app_exec(), ast_moh_files_next(), ast_monitor_start(), ast_monitor_stop(), ast_openstream_full(), ast_openvstream(), chanspy_exec(), conf_run(), dial_exec_full(), invent_message(), last_message_index(), leave_voicemail(), play_mailbox_owner(), play_message_callerid(), record_exec(), vm_newuser(), and vm_tempgreeting().

00743 {
00744    char filename2[256];
00745    char tmp[256];
00746    char *postfix;
00747    char *prefix;
00748    char *c;
00749    char lang2[MAX_LANGUAGE];
00750    int res = -1;
00751    if (!ast_strlen_zero(preflang)) {
00752       /* Insert the language between the last two parts of the path */
00753       ast_copy_string(tmp, filename, sizeof(tmp));
00754       c = strrchr(tmp, '/');
00755       if (c) {
00756          *c = '\0';
00757          postfix = c+1;
00758          prefix = tmp;
00759          snprintf(filename2, sizeof(filename2), "%s/%s/%s", prefix, preflang, postfix);
00760       } else {
00761          postfix = tmp;
00762          prefix="";
00763          snprintf(filename2, sizeof(filename2), "%s/%s", preflang, postfix);
00764       }
00765       res = ast_filehelper(filename2, NULL, fmt, ACTION_EXISTS);
00766       if (res < 1) {
00767          char *stringp=NULL;
00768          ast_copy_string(lang2, preflang, sizeof(lang2));
00769          stringp=lang2;
00770          strsep(&stringp, "_");
00771          /* If language is a specific locality of a language (like es_MX), strip the locality and try again */
00772          if (strcmp(lang2, preflang)) {
00773             if (ast_strlen_zero(prefix)) {
00774                snprintf(filename2, sizeof(filename2), "%s/%s", lang2, postfix);
00775             } else {
00776                snprintf(filename2, sizeof(filename2), "%s/%s/%s", prefix, lang2, postfix);
00777             }
00778             res = ast_filehelper(filename2, NULL, fmt, ACTION_EXISTS);
00779          }
00780       }
00781    }
00782 
00783    /* Fallback to no language (usually winds up being American English) */
00784    if (res < 1) {
00785       res = ast_filehelper(filename, NULL, fmt, ACTION_EXISTS);
00786    }
00787    return res;
00788 }

static int ast_filehelper ( const char *  filename,
const char *  filename2,
const char *  fmt,
int  action 
) [static]

Definition at line 351 of file file.c.

References ACTION_COPY, ACTION_DELETE, ACTION_EXISTS, ACTION_OPEN, ACTION_RENAME, ast_closestream(), AST_FORMAT_MAX_AUDIO, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, build_filename(), copy(), ast_format::exts, exts_compare(), ast_filestream::filename, ast_filestream::fmt, ast_format::format, free, ast_filestream::lasttimeout, LOG_WARNING, ast_format::next, ast_format::open, s, ast_channel::stream, strsep(), ast_filestream::trans, ast_channel::vstream, and ast_channel::writeformat.

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

00352 {
00353    struct stat st;
00354    struct ast_format *f;
00355    struct ast_filestream *s;
00356    int res=0, ret = 0;
00357    char *ext=NULL, *exts, *fn, *nfn;
00358    FILE *bfile;
00359    struct ast_channel *chan = (struct ast_channel *)filename2;
00360    
00361    /* Start with negative response */
00362    if (action == ACTION_EXISTS)
00363       res = 0;
00364    else
00365       res = -1;
00366    if (action == ACTION_OPEN)
00367       ret = -1;
00368    /* Check for a specific format */
00369    if (ast_mutex_lock(&formatlock)) {
00370       ast_log(LOG_WARNING, "Unable to lock format list\n");
00371       if (action == ACTION_EXISTS)
00372          return 0;
00373       else
00374          return -1;
00375    }
00376    f = formats;
00377    while(f) {
00378       if (!fmt || exts_compare(f->exts, fmt)) {
00379          char *stringp=NULL;
00380          exts = ast_strdupa(f->exts);
00381          /* Try each kind of extension */
00382          stringp=exts;
00383          ext = strsep(&stringp, "|");
00384          do {
00385             fn = build_filename(filename, ext);
00386             if (fn) {
00387                res = stat(fn, &st);
00388                if (!res) {
00389                   switch(action) {
00390                   case ACTION_EXISTS:
00391                      ret |= f->format;
00392                      break;
00393                   case ACTION_DELETE:
00394                      res = unlink(fn);
00395                      if (res)
00396                         ast_log(LOG_WARNING, "unlink(%s) failed: %s\n", fn, strerror(errno));
00397                      break;
00398                   case ACTION_RENAME:
00399                      nfn = build_filename(filename2, ext);
00400                      if (nfn) {
00401                         res = rename(fn, nfn);
00402                         if (res)
00403                            ast_log(LOG_WARNING, "rename(%s,%s) failed: %s\n", fn, nfn, strerror(errno));
00404                         free(nfn);
00405                      } else
00406                         ast_log(LOG_WARNING, "Out of memory\n");
00407                      break;
00408                   case ACTION_COPY:
00409                      nfn = build_filename(filename2, ext);
00410                      if (nfn) {
00411                         res = copy(fn, nfn);
00412                         if (res)
00413                            ast_log(LOG_WARNING, "copy(%s,%s) failed: %s\n", fn, nfn, strerror(errno));
00414                         free(nfn);
00415                      } else
00416                         ast_log(LOG_WARNING, "Out of memory\n");
00417                      break;
00418                   case ACTION_OPEN:
00419                      if ((ret < 0) && ((chan->writeformat & f->format) ||
00420                               ((f->format >= AST_FORMAT_MAX_AUDIO) && fmt))) {
00421                         bfile = fopen(fn, "r");
00422                         if (bfile) {
00423                            ret = 1;
00424                            s = f->open(bfile);
00425                            if (s) {
00426                               s->lasttimeout = -1;
00427                               s->fmt = f;
00428                               s->trans = NULL;
00429                               s->filename = NULL;
00430                               if (s->fmt->format < AST_FORMAT_MAX_AUDIO) {
00431                                  if (chan->stream)
00432                                     ast_closestream(chan->stream);
00433                                  chan->stream = s;
00434                               } else {
00435                                  if (chan->vstream)
00436                                     ast_closestream(chan->vstream);
00437                                  chan->vstream = s;
00438                               }
00439                            } else {
00440                               fclose(bfile);
00441                               ast_log(LOG_WARNING, "Unable to open file on %s\n", fn);
00442                               ret = -1;
00443                            }
00444                         } else{
00445                            ast_log(LOG_WARNING, "Couldn't open file %s\n", fn);
00446                            ret = -1;
00447                         }
00448                      }
00449                      break;
00450                   default:
00451                      ast_log(LOG_WARNING, "Unknown helper %d\n", action);
00452                   }
00453                   /* Conveniently this logic is the same for all */
00454                   if (res)
00455                      break;
00456                }
00457                free(fn);
00458             }
00459             ext = strsep(&stringp, "|");
00460          } while(ext);
00461          
00462       }
00463       f = f->next;
00464    }
00465    ast_mutex_unlock(&formatlock);
00466    if ((action == ACTION_EXISTS) || (action == ACTION_OPEN))
00467       res = ret ? ret : -1;
00468    return res;
00469 }

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 795 of file file.c.

References ACTION_RENAME, and ast_filehelper().

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

00796 {
00797    return ast_filehelper(filename, filename2, fmt, ACTION_RENAME);
00798 }

int ast_format_register ( const char *  name,
const char *  exts,
int  format,
struct ast_filestream *(*)(FILE *f)  open,
struct ast_filestream *(*)(FILE *f, const char *comment)  rewrite,
int(*)(struct ast_filestream *, struct ast_frame *)  write,
int(*)(struct ast_filestream *, long sample_offset, int whence)  seek,
int(*)(struct ast_filestream *)  trunc,
long(*)(struct ast_filestream *)  tell,
struct ast_frame *(*)(struct ast_filestream *, int *whennext)  read,
void(*)(struct ast_filestream *)  close,
char *(*)(struct ast_filestream *)  getcomment 
)

Definition at line 105 of file file.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_format::close, ast_format::exts, ast_format::format, ast_format::getcomment, LOG_WARNING, malloc, ast_format::name, ast_format::next, ast_format::open, option_verbose, ast_format::read, ast_format::rewrite, ast_format::seek, ast_format::tell, ast_format::trunc, VERBOSE_PREFIX_2, and ast_format::write.

Referenced by load_module().

00115 {
00116    struct ast_format *tmp;
00117    if (ast_mutex_lock(&formatlock)) {
00118       ast_log(LOG_WARNING, "Unable to lock format list\n");
00119       return -1;
00120    }
00121    tmp = formats;
00122    while(tmp) {
00123       if (!strcasecmp(name, tmp->name)) {
00124          ast_mutex_unlock(&formatlock);
00125          ast_log(LOG_WARNING, "Tried to register '%s' format, already registered\n", name);
00126          return -1;
00127       }
00128       tmp = tmp->next;
00129    }
00130    tmp = malloc(sizeof(struct ast_format));
00131    if (!tmp) {
00132       ast_log(LOG_WARNING, "Out of memory\n");
00133       ast_mutex_unlock(&formatlock);
00134       return -1;
00135    }
00136    ast_copy_string(tmp->name, name, sizeof(tmp->name));
00137    ast_copy_string(tmp->exts, exts, sizeof(tmp->exts));
00138    tmp->open = open;
00139    tmp->rewrite = rewrite;
00140    tmp->read = read;
00141    tmp->write = write;
00142    tmp->seek = seek;
00143    tmp->trunc = trunc;
00144    tmp->tell = tell;
00145    tmp->close = close;
00146    tmp->format = format;
00147    tmp->getcomment = getcomment;
00148    tmp->next = formats;
00149    formats = tmp;
00150    ast_mutex_unlock(&formatlock);
00151    if (option_verbose > 1)
00152       ast_verbose( VERBOSE_PREFIX_2 "Registered file format %s, extension(s) %s\n", name, exts);
00153    return 0;
00154 }

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 156 of file file.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), free, LOG_WARNING, ast_format::name, ast_format::next, option_verbose, and VERBOSE_PREFIX_2.

Referenced by unload_module().

00157 {
00158    struct ast_format *tmp, *tmpl = NULL;
00159    if (ast_mutex_lock(&formatlock)) {
00160       ast_log(LOG_WARNING, "Unable to lock format list\n");
00161       return -1;
00162    }
00163    tmp = formats;
00164    while(tmp) {
00165       if (!strcasecmp(name, tmp->name)) {
00166          if (tmpl) 
00167             tmpl->next = tmp->next;
00168          else
00169             formats = tmp->next;
00170          free(tmp);
00171          ast_mutex_unlock(&formatlock);
00172          if (option_verbose > 1)
00173             ast_verbose( VERBOSE_PREFIX_2 "Unregistered format %s\n", name);
00174          return 0;
00175       }
00176       tmpl = tmp;
00177       tmp = tmp->next;
00178    }
00179    ast_mutex_unlock(&formatlock);
00180    ast_log(LOG_WARNING, "Tried to unregister format %s, already unregistered\n", name);
00181    return -1;
00182 }

AST_MUTEX_DEFINE_STATIC ( formatlock   ) 

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 470 of file file.c.

References ast_openstream_full().

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

00471 {
00472    return ast_openstream_full(chan, filename, preflang, 0);
00473 }

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 475 of file file.c.

References ACTION_OPEN, ast_deactivate_generator(), ast_fileexists(), ast_filehelper(), ast_log(), ast_set_write_format(), ast_stopstream(), ast_strlen_zero(), ast_channel::generator, LOG_WARNING, ast_channel::oldwriteformat, and ast_channel::writeformat.

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

00476 {
00477    /* This is a fairly complex routine.  Essentially we should do 
00478       the following:
00479       
00480       1) Find which file handlers produce our type of format.
00481       2) Look for a filename which it can handle.
00482       3) If we find one, then great.  
00483       4) If not, see what files are there
00484       5) See what we can actually support
00485       6) Choose the one with the least costly translator path and
00486           set it up.
00487          
00488    */
00489    int fmts = -1;
00490    char filename2[256]="";
00491    char filename3[256];
00492    char *endpart;
00493    int res;
00494 
00495    if (!asis) {
00496       /* do this first, otherwise we detect the wrong writeformat */
00497       ast_stopstream(chan);
00498       if (chan->generator)
00499          ast_deactivate_generator(chan);
00500    }
00501    if (!ast_strlen_zero(preflang)) {
00502       ast_copy_string(filename3, filename, sizeof(filename3));
00503       endpart = strrchr(filename3, '/');
00504       if (endpart) {
00505          *endpart = '\0';
00506          endpart++;
00507          snprintf(filename2, sizeof(filename2), "%s/%s/%s", filename3, preflang, endpart);
00508       } else
00509          snprintf(filename2, sizeof(filename2), "%s/%s", preflang, filename);
00510       fmts = ast_fileexists(filename2, NULL, NULL);
00511    }
00512    if (fmts < 1) {
00513       ast_copy_string(filename2, filename, sizeof(filename2));
00514       fmts = ast_fileexists(filename2, NULL, NULL);
00515    }
00516    if (fmts < 1) {
00517       ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
00518       return NULL;
00519    }
00520    chan->oldwriteformat = chan->writeformat;
00521    /* Set the channel to a format we can work with */
00522    res = ast_set_write_format(chan, fmts);
00523    
00524    res = ast_filehelper(filename2, (char *)chan, NULL, ACTION_OPEN);
00525    if (res >= 0)
00526       return chan->stream;
00527    return NULL;
00528 }

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 530 of file file.c.

References ACTION_OPEN, ast_fileexists(), ast_filehelper(), ast_log(), ast_strlen_zero(), fmt, LOG_WARNING, and MAX_LANGUAGE.

Referenced by ast_streamfile().

00531 {
00532    /* This is a fairly complex routine.  Essentially we should do 
00533       the following:
00534       
00535       1) Find which file handlers produce our type of format.
00536       2) Look for a filename which it can handle.
00537       3) If we find one, then great.  
00538       4) If not, see what files are there
00539       5) See what we can actually support
00540       6) Choose the one with the least costly translator path and
00541           set it up.
00542          
00543    */
00544    int fd = -1;
00545    int fmts = -1;
00546    char filename2[256];
00547    char lang2[MAX_LANGUAGE];
00548    /* XXX H.263 only XXX */
00549    char *fmt = "h263";
00550    if (!ast_strlen_zero(preflang)) {
00551       snprintf(filename2, sizeof(filename2), "%s/%s", preflang, filename);
00552       fmts = ast_fileexists(filename2, fmt, NULL);
00553       if (fmts < 1) {
00554          ast_copy_string(lang2, preflang, sizeof(lang2));
00555          snprintf(filename2, sizeof(filename2), "%s/%s", lang2, filename);
00556          fmts = ast_fileexists(filename2, fmt, NULL);
00557       }
00558    }
00559    if (fmts < 1) {
00560       ast_copy_string(filename2, filename, sizeof(filename2));
00561       fmts = ast_fileexists(filename2, fmt, NULL);
00562    }
00563    if (fmts < 1) {
00564       return NULL;
00565    }
00566    fd = ast_filehelper(filename2, (char *)chan, fmt, ACTION_OPEN);
00567    if (fd >= 0)
00568       return chan->vstream;
00569    ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename);
00570    return NULL;
00571 }

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 655 of file file.c.

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

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

00656 {
00657    if (s->fmt->format < AST_FORMAT_MAX_AUDIO)
00658       ast_readaudio_callback(s);
00659    else
00660       ast_readvideo_callback(s);
00661    return 0;
00662 }

static int ast_readaudio_callback ( void *  data  )  [static]

Definition at line 582 of file file.c.

References ast_log(), ast_sched_add(), ast_settimeout(), ast_write(), ast_filestream::fmt, ast_filestream::lasttimeout, LOG_WARNING, ast_filestream::owner, ast_format::read, s, ast_channel::sched, ast_channel::streamid, and ast_channel::timingfd.

Referenced by ast_playstream().

00583 {
00584    struct ast_filestream *s = data;
00585    struct ast_frame *fr;
00586    int whennext = 0;
00587 
00588    while(!whennext) {
00589       fr = s->fmt->read(s, &whennext);
00590       if (fr) {
00591          if (ast_write(s->owner, fr)) {
00592             ast_log(LOG_WARNING, "Failed to write frame\n");
00593             s->owner->streamid = -1;
00594 #ifdef ZAPTEL_OPTIMIZATIONS
00595             ast_settimeout(s->owner, 0, NULL, NULL);
00596 #endif         
00597             return 0;
00598          }
00599       } else {
00600          /* Stream has finished */
00601          s->owner->streamid = -1;
00602 #ifdef ZAPTEL_OPTIMIZATIONS
00603          ast_settimeout(s->owner, 0, NULL, NULL);
00604 #endif         
00605          return 0;
00606       }
00607    }
00608    if (whennext != s->lasttimeout) {
00609 #ifdef ZAPTEL_OPTIMIZATIONS
00610       if (s->owner->timingfd > -1)
00611          ast_settimeout(s->owner, whennext, ast_readaudio_callback, s);
00612       else
00613 #endif      
00614          s->owner->streamid = ast_sched_add(s->owner->sched, whennext/8, ast_readaudio_callback, s);
00615       s->lasttimeout = whennext;
00616       return 0;
00617    }
00618    return 1;
00619 }

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 832 of file file.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), build_filename(), ast_format::exts, exts_compare(), ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, free, LOG_WARNING, ast_filestream::mode, ast_format::next, ast_format::open, strdup, ast_filestream::trans, and ast_filestream::vfs.

Referenced by ast_play_and_prepend().

00833 {
00834    FILE *bfile;
00835    struct ast_format *f;
00836    struct ast_filestream *fs = NULL;
00837    char *fn;
00838 
00839    if (ast_mutex_lock(&formatlock)) {
00840       ast_log(LOG_WARNING, "Unable to lock format list\n");
00841       return NULL;
00842    }
00843 
00844    for (f = formats; f && !fs; f = f->next) {
00845       if (!exts_compare(f->exts, type))
00846          continue;
00847 
00848       fn = build_filename(filename, type);
00849       bfile = fopen(fn, "r");
00850       if (bfile) {
00851          errno = 0;
00852 
00853          if (!(fs = f->open(bfile))) {
00854             ast_log(LOG_WARNING, "Unable to open %s\n", fn);
00855             fclose(bfile);
00856             free(fn);
00857             continue;
00858          }
00859 
00860          fs->trans = NULL;
00861          fs->fmt = f;
00862          fs->flags = flags;
00863          fs->mode = mode;
00864          fs->filename = strdup(filename);
00865          fs->vfs = NULL;
00866       } else if (errno != EEXIST)
00867          ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno));
00868       free(fn);
00869    }
00870 
00871    ast_mutex_unlock(&formatlock);
00872    if (!fs) 
00873       ast_log(LOG_WARNING, "No such format '%s'\n", type);
00874 
00875    return fs;
00876 }

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 573 of file file.c.

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

Referenced by ast_play_and_prepend(), dictate_exec(), gen_readframe(), and moh_files_readframe().

00574 {
00575    struct ast_frame *f = NULL;
00576    int whennext = 0; 
00577    if (s && s->fmt)
00578       f = s->fmt->read(s, &whennext);
00579    return f;
00580 }

static int ast_readvideo_callback ( void *  data  )  [static]

Definition at line 621 of file file.c.

References ast_log(), ast_sched_add(), ast_write(), ast_filestream::fmt, ast_filestream::lasttimeout, LOG_WARNING, ast_filestream::owner, ast_format::read, s, ast_channel::sched, and ast_channel::vstreamid.

Referenced by ast_playstream().

00622 {
00623    struct ast_filestream *s = data;
00624    struct ast_frame *fr;
00625    int whennext = 0;
00626 
00627    while(!whennext) {
00628       fr = s->fmt->read(s, &whennext);
00629       if (fr) {
00630          if (ast_write(s->owner, fr)) {
00631             ast_log(LOG_WARNING, "Failed to write frame\n");
00632             s->owner->vstreamid = -1;
00633             return 0;
00634          }
00635       } else {
00636          /* Stream has finished */
00637          s->owner->vstreamid = -1;
00638          return 0;
00639       }
00640    }
00641    if (whennext != s->lasttimeout) {
00642       s->owner->vstreamid = ast_sched_add(s->owner->sched, whennext/8, ast_readvideo_callback, s);
00643       s->lasttimeout = whennext;
00644       return 0;
00645    }
00646    return 1;
00647 }

int ast_seekstream ( struct ast_filestream fs,
long  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 664 of file file.c.

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

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

00665 {
00666    return fs->fmt->seek(fs, sample_offset, whence);
00667 }

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 Returns 0 regardless

Definition at line 184 of file file.c.

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

Referenced by adsi_transmit_message_full(), ast_control_streamfile(), ast_openstream_full(), ast_play_and_wait(), ast_readstring(), ast_readstring_full(), ast_say_character_str_full(), ast_say_digit_str_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_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_phonetic_str_full(), ast_waitstream(), ast_waitstream_exten(), ast_waitstream_fr(), ast_waitstream_full(), background_detect_exec(), background_file(), 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(), saycharstr(), sayfile(), saynum(), send_morse(), send_tone_telemetry(), send_waveform_to_channel(), vm_authenticate(), vm_execmain(), and zapateller_exec().

00185 {
00186    /* Stop a running stream if there is one */
00187    if (tmp->vstream) {
00188       ast_closestream(tmp->vstream);
00189       tmp->vstream = NULL;
00190    }
00191    if (tmp->stream) {
00192       ast_closestream(tmp->stream);
00193       tmp->stream = NULL;
00194       if (tmp->oldwriteformat && ast_set_write_format(tmp, tmp->oldwriteformat))
00195          ast_log(LOG_WARNING, "Unable to restore format back to %d\n", tmp->oldwriteformat);
00196    }
00197    return 0;
00198 }

int ast_stream_fastforward ( struct ast_filestream fs,
long  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 679 of file file.c.

References ast_seekstream(), and ast_frame::samples.

Referenced by ast_waitstream_fr().

00680 {
00681    /* I think this is right, 8000 samples per second, 1000 ms a second so 8
00682     * samples per ms  */
00683    long samples = ms * 8;
00684    return ast_seekstream(fs, samples, SEEK_CUR);
00685 }

int ast_stream_rewind ( struct ast_filestream fs,
long  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 687 of file file.c.

References ast_seekstream(), and ast_frame::samples.

Referenced by ast_play_and_prepend(), ast_play_and_record_full(), ast_waitstream_fr(), handle_recordfile(), and record_exec().

00688 {
00689    long samples = ms * 8;
00690    samples = samples * -1;
00691    return ast_seekstream(fs, samples, SEEK_CUR);
00692 }

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 805 of file file.c.

References ast_applystream(), ast_getformatname(), ast_log(), ast_openstream(), ast_openvstream(), ast_playstream(), ast_verbose(), LOG_DEBUG, LOG_WARNING, ast_channel::nativeformats, option_verbose, VERBOSE_PREFIX_3, and ast_filestream::vfs.

Referenced by __login_exec(), agent_call(), ast_app_getdata(), ast_app_getdata_full(), ast_app_getvoice(), ast_control_streamfile(), ast_play_and_prepend(), ast_play_and_record_full(), ast_play_and_wait(), ast_record_review(), ast_say_character_str_full(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), 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_gr(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_tw(), ast_say_digit_str_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_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_phonetic_str_full(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_gr(), ast_say_time_nl(), ast_say_time_tw(), auth_exec(), background_detect_exec(), background_file(), bridge_playfile(), builtin_atxfer(), builtin_automonitor(), builtin_blindtransfer(), chanspy_exec(), check_availability(), check_beep(), conf_exec(), conf_run(), dial_exec_full(), directory_exec(), do_directory(), forward_message(), gr_say_number_female(), handle_recordfile(), invent_message(), ivr_dispatch(), leave_voicemail(), page_exec(), park_exec(), parkandannounce_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_and_wait(), play_file(), play_mailbox_owner(), play_message_callerid(), play_record_review(), playback_exec(), privacy_exec(), record_exec(), retrydial_exec(), rpt_tele_thread(), sayfile(), ss_thread(), vm_authenticate(), wait_file(), and wait_file2().

00806 {
00807    struct ast_filestream *fs;
00808    struct ast_filestream *vfs;
00809 
00810    fs = ast_openstream(chan, filename, preflang);
00811    vfs = ast_openvstream(chan, filename, preflang);
00812    if (vfs)
00813       ast_log(LOG_DEBUG, "Ooh, found a video stream, too\n");
00814    if (fs){
00815       if (ast_applystream(chan, fs))
00816          return -1;
00817       if (vfs && ast_applystream(chan, vfs))
00818          return -1;
00819       ast_playstream(fs);
00820       if (vfs)
00821          ast_playstream(vfs);
00822 #if 1
00823       if (option_verbose > 2)
00824          ast_verbose(VERBOSE_PREFIX_3 "Playing '%s' (language '%s')\n", filename, preflang ? preflang : "default");
00825 #endif
00826       return 0;
00827    }
00828    ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname(chan->nativeformats), strerror(errno));
00829    return -1;
00830 }

long 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 674 of file file.c.

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

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

00675 {
00676    return fs->fmt->tell(fs);
00677 }

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 669 of file file.c.

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

Referenced by ast_play_and_prepend(), ast_play_and_record_full(), handle_recordfile(), and record_exec().

00670 {
00671    return fs->fmt->trunc(fs);
00672 }

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 waitstram 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 997 of file file.c.

References ast_channel::_softhangup, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree(), ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_stopstream(), ast_waitfor(), ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::sched, ast_channel::stream, ast_frame::subclass, and ast_channel::timingfunc.

Referenced by __login_exec(), agent_call(), ast_app_getvoice(), ast_play_and_prepend(), ast_play_and_record_full(), ast_play_and_wait(), ast_readstring(), ast_record_review(), ast_say_character_str_full(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), 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_gr(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_tw(), ast_say_digit_str_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_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_phonetic_str_full(), ast_say_time_de(), ast_say_time_en(), ast_say_time_gr(), ast_say_time_nl(), ast_say_time_tw(), auth_exec(), background_file(), bridge_playfile(), builtin_atxfer(), builtin_automonitor(), builtin_blindtransfer(), chanspy_exec(), check_availability(), check_beep(), conf_exec(), conf_run(), dial_exec_full(), directory_exec(), gr_say_number_female(), handle_recordfile(), invent_message(), ivr_dispatch(), leave_voicemail(), page_exec(), park_exec(), parkandannounce_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_and_wait(), play_file(), play_mailbox_owner(), play_message_callerid(), play_record_review(), playback_exec(), privacy_exec(), record_exec(), retrydial_exec(), rpt_tele_thread(), saycharstr(), sayfile(), saynum(), send_morse(), send_tone_telemetry(), ss_thread(), vm_authenticate(), wait_file(), and wait_file2().

00998 {
00999    /* XXX Maybe I should just front-end ast_waitstream_full ? XXX */
01000    int res;
01001    struct ast_frame *fr;
01002    if (!breakon) breakon = "";
01003    while(c->stream) {
01004       res = ast_sched_wait(c->sched);
01005       if ((res < 0) && !c->timingfunc) {
01006          ast_stopstream(c);
01007          break;
01008       }
01009       if (res < 0)
01010          res = 1000;
01011       res = ast_waitfor(c, res);
01012       if (res < 0) {
01013          ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
01014          return res;
01015       } else if (res > 0) {
01016          fr = ast_read(c);
01017          if (!fr) {
01018 #if 0
01019             ast_log(LOG_DEBUG, "Got hung up\n");
01020 #endif
01021             return -1;
01022          }
01023          
01024          switch(fr->frametype) {
01025          case AST_FRAME_DTMF:
01026             res = fr->subclass;
01027             if (strchr(breakon, res)) {
01028                ast_frfree(fr);
01029                return res;
01030             }
01031             break;
01032          case AST_FRAME_CONTROL:
01033             switch(fr->subclass) {
01034             case AST_CONTROL_HANGUP:
01035             case AST_CONTROL_BUSY:
01036             case AST_CONTROL_CONGESTION:
01037                ast_frfree(fr);
01038                return -1;
01039             case AST_CONTROL_RINGING:
01040             case AST_CONTROL_ANSWER:
01041             case AST_CONTROL_VIDUPDATE:
01042                /* Unimportant */
01043                break;
01044             default:
01045                ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
01046             }
01047          }
01048          /* Ignore */
01049          ast_frfree(fr);
01050       }
01051       ast_sched_runq(c->sched);
01052    }
01053    return (c->_softhangup ? -1 : 0);
01054 }

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 waitstram 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 1200 of file file.c.

References ast_channel::_softhangup, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree(), ast_log(), AST_MAX_EXTENSION, ast_read(), ast_sched_runq(), ast_sched_wait(), ast_stopstream(), ast_waitfor(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, exten, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::sched, ast_channel::stream, ast_frame::subclass, and ast_channel::timingfunc.

Referenced by pbx_builtin_background().

01201 {
01202    /* Waitstream, with return in the case of a valid 1 digit extension */
01203    /* in the current or specified context being pressed */
01204    /* XXX Maybe I should just front-end ast_waitstream_full ? XXX */
01205    int res;
01206    struct ast_frame *fr;
01207    char exten[AST_MAX_EXTENSION];
01208 
01209    if (!context) context = c->context;
01210    while(c->stream) {
01211       res = ast_sched_wait(c->sched);
01212       if ((res < 0) && !c->timingfunc) {
01213          ast_stopstream(c);
01214          break;
01215       }
01216       if (res < 0)
01217          res = 1000;
01218       res = ast_waitfor(c, res);
01219       if (res < 0) {
01220          ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
01221          return res;
01222       } else if (res > 0) {
01223          fr = ast_read(c);
01224          if (!fr) {
01225 #if 0
01226             ast_log(LOG_DEBUG, "Got hung up\n");
01227 #endif
01228             return -1;
01229          }
01230          
01231          switch(fr->frametype) {
01232          case AST_FRAME_DTMF:
01233             res = fr->subclass;
01234             snprintf(exten, sizeof(exten), "%c", res);
01235             if (ast_exists_extension(c, context, exten, 1, c->cid.cid_num)) {
01236                ast_frfree(fr);
01237                return res;
01238             }
01239             break;
01240          case AST_FRAME_CONTROL:
01241             switch(fr->subclass) {
01242             case AST_CONTROL_HANGUP:
01243             case AST_CONTROL_BUSY:
01244             case AST_CONTROL_CONGESTION:
01245                ast_frfree(fr);
01246                return -1;
01247             case AST_CONTROL_RINGING:
01248             case AST_CONTROL_ANSWER:
01249                /* Unimportant */
01250                break;
01251             default:
01252                ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
01253             }
01254          }
01255          /* Ignore */
01256          ast_frfree(fr);
01257       }
01258       ast_sched_runq(c->sched);
01259    }
01260    return (c->_softhangup ? -1 : 0);
01261 }

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 waitstram 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 1056 of file file.c.

References ast_channel::_softhangup, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree(), ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_stopstream(), ast_stream_fastforward(), ast_stream_rewind(), ast_waitfor(), ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::sched, ast_channel::stream, ast_frame::subclass, and ast_channel::timingfunc.

Referenced by ast_control_streamfile().

01057 {
01058    int res;
01059    struct ast_frame *fr;
01060 
01061    if (!breakon)
01062          breakon = "";
01063    if (!forward)
01064          forward = "";
01065    if (!rewind)
01066          rewind = "";
01067    
01068    while(c->stream) {
01069       res = ast_sched_wait(c->sched);
01070       if ((res < 0) && !c->timingfunc) {
01071          ast_stopstream(c);
01072          break;
01073       }
01074       if (res < 0)
01075          res = 1000;
01076       res = ast_waitfor(c, res);
01077       if (res < 0) {
01078          ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
01079          return res;
01080       } else
01081       if (res > 0) {
01082          fr = ast_read(c);
01083          if (!fr) {
01084 #if 0
01085             ast_log(LOG_DEBUG, "Got hung up\n");
01086 #endif
01087             return -1;
01088          }
01089          
01090          switch(fr->frametype) {
01091          case AST_FRAME_DTMF:
01092             res = fr->subclass;
01093             if (strchr(forward,res)) {
01094                ast_stream_fastforward(c->stream, ms);
01095             } else if (strchr(rewind,res)) {
01096                ast_stream_rewind(c->stream, ms);
01097             } else if (strchr(breakon, res)) {
01098                ast_frfree(fr);
01099                return res;
01100             }              
01101             break;
01102          case AST_FRAME_CONTROL:
01103             switch(fr->subclass) {
01104             case AST_CONTROL_HANGUP:
01105             case AST_CONTROL_BUSY:
01106             case AST_CONTROL_CONGESTION:
01107                ast_frfree(fr);
01108                return -1;
01109             case AST_CONTROL_RINGING:
01110             case AST_CONTROL_ANSWER:
01111                /* Unimportant */
01112                break;
01113             default:
01114                ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
01115             }
01116          }
01117          /* Ignore */
01118          ast_frfree(fr);
01119       } else
01120          ast_sched_runq(c->sched);
01121    
01122       
01123    }
01124    return (c->_softhangup ? -1 : 0);
01125 }

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

Definition at line 1127 of file file.c.

References ast_channel::_softhangup, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_sched_runq(), ast_sched_wait(), ast_stopstream(), ast_waitfor_nandfds(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_channel::sched, ast_channel::stream, ast_frame::subclass, and ast_channel::timingfunc.

Referenced by ast_readstring_full(), ast_say_character_str_full(), ast_say_digit_str_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_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_phonetic_str_full(), handle_getoption(), handle_streamfile(), and pl_odtworz_plik().

01128 {
01129    int res;
01130    int ms;
01131    int outfd;
01132    struct ast_frame *fr;
01133    struct ast_channel *rchan;
01134 
01135    if (!breakon)
01136       breakon = "";
01137    
01138    while(c->stream) {
01139       ms = ast_sched_wait(c->sched);
01140       if ((ms < 0) && !c->timingfunc) {
01141          ast_stopstream(c);
01142          break;
01143       }
01144       if (ms < 0)
01145          ms = 1000;
01146       rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
01147       if (!rchan && (outfd < 0) && (ms)) {
01148          /* Continue */
01149          if (errno == EINTR)
01150             continue;
01151          ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
01152          return -1;
01153       } else if (outfd > -1) {
01154          /* The FD we were watching has something waiting */
01155          return 1;
01156       } else if (rchan) {
01157          fr = ast_read(c);
01158          if (!fr) {
01159 #if 0
01160             ast_log(LOG_DEBUG, "Got hung up\n");
01161 #endif
01162             return -1;
01163          }
01164          
01165          switch(fr->frametype) {
01166          case AST_FRAME_DTMF:
01167             res = fr->subclass;
01168             if (strchr(breakon, res)) {
01169                ast_frfree(fr);
01170                return res;
01171             }
01172             break;
01173          case AST_FRAME_CONTROL:
01174             switch(fr->subclass) {
01175             case AST_CONTROL_HANGUP:
01176             case AST_CONTROL_BUSY:
01177             case AST_CONTROL_CONGESTION:
01178                ast_frfree(fr);
01179                return -1;
01180             case AST_CONTROL_RINGING:
01181             case AST_CONTROL_ANSWER:
01182                /* Unimportant */
01183                break;
01184             default:
01185                ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
01186             }
01187          case AST_FRAME_VOICE:
01188             /* Write audio if appropriate */
01189             if (audiofd > -1)
01190                write(audiofd, fr->data, fr->datalen);
01191          }
01192          /* Ignore */
01193          ast_frfree(fr);
01194       }
01195       ast_sched_runq(c->sched);
01196    }
01197    return (c->_softhangup ? -1 : 0);
01198 }

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 878 of file file.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_filestream::buf, build_filename(), ast_format::exts, exts_compare(), ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, free, LOG_WARNING, ast_filestream::mode, ast_format::next, option_cache_record_files, ast_filestream::realfilename, record_cache_dir, ast_format::rewrite, ast_format::seek, strdup, ast_filestream::trans, and ast_filestream::vfs.

Referenced by ast_app_getvoice(), ast_monitor_start(), ast_play_and_prepend(), ast_play_and_record_full(), ast_writestream(), dictate_exec(), handle_recordfile(), mixmonitor_thread(), record_exec(), and recordthread().

00879 {
00880    int fd, myflags = 0;
00881    /* compiler claims this variable can be used before initialization... */
00882    FILE *bfile = NULL;
00883    struct ast_format *f;
00884    struct ast_filestream *fs = NULL;
00885    char *fn, *orig_fn = NULL;
00886    char *buf = NULL;
00887    size_t size = 0;
00888    int format_found = 0;
00889 
00890    if (ast_mutex_lock(&formatlock)) {
00891       ast_log(LOG_WARNING, "Unable to lock format list\n");
00892       return NULL;
00893    }
00894 
00895    /* set the O_TRUNC flag if and only if there is no O_APPEND specified */
00896    if (flags & O_APPEND) { 
00897       /* We really can't use O_APPEND as it will break WAV header updates */
00898       flags &= ~O_APPEND;
00899    } else {
00900       myflags = O_TRUNC;
00901    }
00902    
00903    myflags |= O_WRONLY | O_CREAT;
00904 
00905    for (f = formats; f && !fs; f = f->next) {
00906       if (!exts_compare(f->exts, type))
00907          continue;
00908       else
00909          format_found = 1;
00910 
00911       fn = build_filename(filename, type);
00912       fd = open(fn, flags | myflags, mode);
00913       if (fd > -1) {
00914          /* fdopen() the resulting file stream */
00915          bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w");
00916          if (!bfile) {
00917             ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno));
00918             close(fd);
00919             fd = -1;
00920          }
00921       }
00922       
00923       if (option_cache_record_files && (fd > -1)) {
00924          char *c;
00925 
00926          fclose(bfile);
00927          /*
00928            We touch orig_fn just as a place-holder so other things (like vmail) see the file is there.
00929            What we are really doing is writing to record_cache_dir until we are done then we will mv the file into place.
00930          */
00931          orig_fn = ast_strdupa(fn);
00932          for (c = fn; *c; c++)
00933             if (*c == '/')
00934                *c = '_';
00935 
00936          size = strlen(fn) + strlen(record_cache_dir) + 2;
00937          buf = alloca(size);
00938          strcpy(buf, record_cache_dir);
00939          strcat(buf, "/");
00940          strcat(buf, fn);
00941          free(fn);
00942          fn = buf;
00943          fd = open(fn, flags | myflags, mode);
00944          if (fd > -1) {
00945             /* fdopen() the resulting file stream */
00946             bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w");
00947             if (!bfile) {
00948                ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno));
00949                close(fd);
00950                fd = -1;
00951             }
00952          }
00953       }
00954       if (fd > -1) {
00955          errno = 0;
00956          if ((fs = f->rewrite(bfile, comment))) {
00957             fs->trans = NULL;
00958             fs->fmt = f;
00959             fs->flags = flags;
00960             fs->mode = mode;
00961             if (orig_fn) {
00962                fs->realfilename = strdup(orig_fn);
00963                fs->filename = strdup(fn);
00964             } else {
00965                fs->realfilename = NULL;
00966                fs->filename = strdup(filename);
00967             }
00968             fs->vfs = NULL;
00969             /* If truncated, we'll be at the beginning; if not truncated, then append */
00970             f->seek(fs, 0, SEEK_END);
00971          } else {
00972             ast_log(LOG_WARNING, "Unable to rewrite %s\n", fn);
00973             close(fd);
00974             if (orig_fn) {
00975                unlink(fn);
00976                unlink(orig_fn);
00977             }
00978          }
00979       } else if (errno != EEXIST) {
00980          ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno));
00981          if (orig_fn)
00982             unlink(orig_fn);
00983       }
00984       /* if buf != NULL then fn is already free and pointing to it */
00985       if (!buf)
00986          free(fn);
00987    }
00988 
00989    ast_mutex_unlock(&formatlock);
00990 
00991    if (!format_found)
00992       ast_log(LOG_WARNING, "No such format '%s'\n", type);
00993 
00994    return fs;
00995 }

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 200 of file file.c.

References AST_FORMAT_MAX_AUDIO, AST_FRAME_VIDEO, AST_FRAME_VOICE, 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_app_getvoice(), ast_play_and_prepend(), ast_play_and_record_full(), ast_read(), ast_write(), ast_writestream(), dictate_exec(), handle_recordfile(), mixmonitor_thread(), record_exec(), and recordthread().

00201 {
00202    struct ast_frame *trf;
00203    int res = -1;
00204    int alt=0;
00205    if (f->frametype == AST_FRAME_VIDEO) {
00206       if (fs->fmt->format < AST_FORMAT_MAX_AUDIO) {
00207          /* This is the audio portion.  Call the video one... */
00208          if (!fs->vfs && fs->filename) {
00209             /* XXX Support other video formats XXX */
00210             const char *type = "h263";
00211             fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode);
00212             ast_log(LOG_DEBUG, "Opened video output file\n");
00213          }
00214          if (fs->vfs)
00215             return ast_writestream(fs->vfs, f);
00216          /* Ignore */
00217          return 0;            
00218       } else {
00219          /* Might / might not have mark set */
00220          alt = 1;
00221       }
00222    } else if (f->frametype != AST_FRAME_VOICE) {
00223       ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
00224       return -1;
00225    }
00226    if (((fs->fmt->format | alt) & f->subclass) == f->subclass) {
00227       res =  fs->fmt->write(fs, f);
00228       if (res < 0) 
00229          ast_log(LOG_WARNING, "Natural write failed\n");
00230       if (res > 0)
00231          ast_log(LOG_WARNING, "Huh??\n");
00232       return res;
00233    } else {
00234       /* XXX If they try to send us a type of frame that isn't the normal frame, and isn't
00235              the one we've setup a translator for, we do the "wrong thing" XXX */
00236       if (fs->trans && (f->subclass != fs->lastwriteformat)) {
00237          ast_translator_free_path(fs->trans);
00238          fs->trans = NULL;
00239       }
00240       if (!fs->trans) 
00241          fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass);
00242       if (!fs->trans)
00243          ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n", fs->fmt->name, ast_getformatname(f->subclass));
00244       else {
00245          fs->lastwriteformat = f->subclass;
00246          res = 0;
00247          /* Get the translated frame but don't consume the original in case they're using it on another stream */
00248          trf = ast_translate(fs->trans, f, 0);
00249          if (trf) {
00250             res = fs->fmt->write(fs, trf);
00251             if (res) 
00252                ast_log(LOG_WARNING, "Translated frame write failed\n");
00253          } else
00254             res = 0;
00255       }
00256       return res;
00257    }
00258 }

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

Definition at line 300 of file file.c.

References ast_config_AST_VAR_DIR, AST_CONFIG_MAX_PATH, malloc, and type.

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

00301 {
00302    char *fn, type[16];
00303    int fnsize = 0;
00304 
00305    if (!strcmp(ext, "wav49")) {
00306       ast_copy_string(type, "WAV", sizeof(type));
00307    } else {
00308       ast_copy_string(type, ext, sizeof(type));
00309    }
00310 
00311    if (filename[0] == '/') {
00312       fnsize = strlen(filename) + strlen(type) + 2;
00313       fn = malloc(fnsize);
00314       if (fn)
00315          snprintf(fn, fnsize, "%s.%s", filename, type);
00316    } else {
00317       char tmp[AST_CONFIG_MAX_PATH] = "";
00318 
00319       snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_VAR_DIR, "sounds");
00320       fnsize = strlen(tmp) + strlen(filename) + strlen(type) + 3;
00321       fn = malloc(fnsize);
00322       if (fn)
00323          snprintf(fn, fnsize, "%s/%s.%s", tmp, filename, type);
00324    }
00325 
00326    return fn;
00327 }

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

Definition at line 260 of file file.c.

References ast_log(), and LOG_WARNING.

Referenced by ast_filehelper(), ast_get_group(), copy_file(), get_group(), iax2_register(), and sip_register().

00261 {
00262    int ifd;
00263    int ofd;
00264    int res;
00265    int len;
00266    char buf[4096];
00267 
00268    if ((ifd = open(infile, O_RDONLY)) < 0) {
00269       ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile);
00270       return -1;
00271    }
00272    if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, 0600)) < 0) {
00273       ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile);
00274       close(ifd);
00275       return -1;
00276    }
00277    do {
00278       len = read(ifd, buf, sizeof(buf));
00279       if (len < 0) {
00280          ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
00281          close(ifd);
00282          close(ofd);
00283          unlink(outfile);
00284       }
00285       if (len) {
00286          res = write(ofd, buf, len);
00287          if (res != len) {
00288             ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
00289             close(ifd);
00290             close(ofd);
00291             unlink(outfile);
00292          }
00293       }
00294    } while(len);
00295    close(ifd);
00296    close(ofd);
00297    return 0;
00298 }

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

Definition at line 329 of file file.c.

References strsep().

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

00330 {
00331    char *stringp = NULL, *ext;
00332    char tmp[256];
00333 
00334    ast_copy_string(tmp, exts, sizeof(tmp));
00335    stringp = tmp;
00336    while ((ext = strsep(&stringp, "|"))) {
00337       if (!strcmp(ext, type)) {
00338          return 1;
00339       }
00340    }
00341 
00342    return 0;
00343 }

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

Definition at line 1263 of file file.c.

References ast_cli(), ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_format::exts, ast_format::format, FORMAT, FORMAT2, LOG_WARNING, ast_format::name, ast_format::next, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01264 {
01265 #define FORMAT "%-10s %-10s %-20s\n"
01266 #define FORMAT2 "%-10s %-10s %-20s\n"
01267    struct ast_format *f;
01268    int count_fmt = 0;
01269 
01270    if (argc != 3)
01271       return RESULT_SHOWUSAGE;
01272    ast_cli(fd, FORMAT, "Format", "Name", "Extensions");
01273            
01274    if (ast_mutex_lock(&formatlock)) {
01275       ast_log(LOG_WARNING, "Unable to lock format list\n");
01276       return -1;
01277    }
01278 
01279    f = formats;
01280    while(f) {
01281       ast_cli(fd, FORMAT2, ast_getformatname(f->format), f->name, f->exts);
01282       f = f->next;
01283       count_fmt++;
01284    };
01285    ast_mutex_unlock(&formatlock);
01286    ast_cli(fd, "%d file formats registered.\n", count_fmt);
01287    return RESULT_SUCCESS;
01288 #undef FORMAT
01289 #undef FORMAT2
01290    
01291 }


Variable Documentation

struct ast_format* formats = NULL [static]

Definition at line 103 of file file.c.

Definition at line 1293 of file file.c.


Generated on Wed Oct 28 15:48:50 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6