file.c File Reference

Generic File Format Support. More...

#include "asterisk.h"
#include <dirent.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <math.h>
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include "asterisk/mod_format.h"
#include "asterisk/cli.h"
#include "asterisk/channel.h"
#include "asterisk/sched.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 "asterisk/astobj2.h"
#include "asterisk/test.h"
#include "asterisk/stasis.h"
#include "asterisk/json.h"
#include "asterisk/stasis_system.h"

Include dependency graph for file.c:

Go to the source code of this file.

Data Structures

struct  formats

Defines

#define FORMAT   "%-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_def_register (const struct ast_format_def *f, struct ast_module *mod)
 Register a new file format capability. Adds a format to Asterisk's format abilities.
static void __fini_formats (void)
static void __init_formats (void)
int ast_applystream (struct ast_channel *chan, struct ast_filestream *s)
 Applys a open stream to a channel.
int ast_closestream (struct ast_filestream *f)
 Closes a stream.
int ast_file_init (void)
int ast_filecopy (const char *filename, const char *filename2, const char *fmt)
 Copies a file.
int ast_filedelete (const char *filename, const char *fmt)
 Deletes a file.
int ast_fileexists (const char *filename, const char *fmt, const char *preflang)
 Checks for the existence of a given file.
int ast_filerename (const char *filename, const char *filename2, const char *fmt)
 Renames a file.
int ast_format_def_unregister (const char *name)
 Unregisters a file format.
char * ast_format_str_reduce (char *fmts)
static int ast_fsread_audio (const void *data)
static int ast_fsread_video (const void *data)
struct ast_formatast_get_format_for_file_ext (const char *file_ext)
 Get the ast_format associated with the given file extension.
struct ast_filestreamast_openstream (struct ast_channel *chan, const char *filename, const char *preflang)
 Opens stream for use in seeking, playing.
struct ast_filestreamast_openstream_full (struct ast_channel *chan, const char *filename, const char *preflang, int asis)
 Opens stream for use in seeking, playing.
struct ast_filestreamast_openvstream (struct ast_channel *chan, const char *filename, const char *preflang)
 Opens stream for use in seeking, playing.
int ast_playstream (struct ast_filestream *s)
 Play a open stream on a channel.
int ast_ratestream (struct ast_filestream *fs)
 Return the sample rate of the stream's format.
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)
 Starts reading from a file.
struct ast_frameast_readframe (struct ast_filestream *s)
 Read a frame from a filestream.
static enum fsread_res ast_readvideo_callback (struct ast_filestream *s)
int ast_seekstream (struct ast_filestream *fs, off_t sample_offset, int whence)
 Seeks into stream.
int ast_stopstream (struct ast_channel *tmp)
 Stops a stream.
int ast_stream_and_wait (struct ast_channel *chan, const char *file, const char *digits)
 stream file until digit If the file name is non-empty, try to play it.
int ast_stream_fastforward (struct ast_filestream *fs, off_t ms)
 Fast forward stream ms.
int ast_stream_rewind (struct ast_filestream *fs, off_t ms)
 Rewind stream ms.
int ast_streamfile (struct ast_channel *chan, const char *filename, const char *preflang)
 Streams a file.
off_t ast_tellstream (struct ast_filestream *fs)
 Tell where we are in a stream.
int ast_truncstream (struct ast_filestream *fs)
 Trunc stream at current location.
int ast_waitstream (struct ast_channel *c, const char *breakon)
 Waits for a stream to stop or digit to be pressed.
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.
int ast_waitstream_fr (struct ast_channel *c, const char *breakon, const char *forward, const char *reverse, int ms)
 Same as waitstream but allows stream to be forwarded or rewound.
int ast_waitstream_fr_w_cb (struct ast_channel *c, const char *breakon, const char *forward, const char *reverse, int ms, ast_waitstream_fr_cb cb)
 Same as waitstream_fr but allows a callback to be alerted when a user fastforwards or rewinds the file.
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)
 Starts writing a file.
int ast_writestream (struct ast_filestream *fs, struct ast_frame *f)
 Writes a frame to a stream.
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 void file_shutdown (void)
static int fileexists_core (const char *filename, const char *fmt, const char *preflang, char *buf, int buflen, struct ast_format_cap *result_cap)
 helper routine to locate a file with a given format and language preference.
static int fileexists_test (const char *filename, const char *fmt, const char *lang, char *buf, int buflen, struct ast_format_cap *result_cap)
 test if a file exists for a given format.
static int filehelper (const char *filename, const void *arg2, const char *fmt, const enum file_action action)
static void filestream_close (struct ast_filestream *f)
static void filestream_destructor (void *arg)
static int fn_wrapper (struct ast_filestream *s, const char *comment, enum wrap_fn mode)
static struct ast_filestreamget_filestream (struct ast_format_def *fmt, FILE *bfile)
static char * handle_cli_core_show_file_formats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int is_absolute_path (const char *filename)
static struct ast_jsonjson_array_from_list (const char *list, const char *sep)
static int open_wrapper (struct ast_filestream *s)
static int publish_format_update (const struct ast_format_def *f, struct stasis_message_type *type)
static struct ast_frameread_frame (struct ast_filestream *s, int *whennext)
static int rewrite_wrapper (struct ast_filestream *s, const char *comment)
static int sanitize_waitstream_return (int return_value)
 STASIS_MESSAGE_TYPE_DEFN (ast_format_unregister_type)
 STASIS_MESSAGE_TYPE_DEFN (ast_format_register_type)
static void waitstream_control (struct ast_channel *c, enum ast_waitstream_fr_cb_values type, ast_waitstream_fr_cb cb, int skip_ms)
static int waitstream_core (struct ast_channel *c, const char *breakon, const char *forward, const char *reverse, int skip_ms, int audiofd, int cmdfd, const char *context, ast_waitstream_fr_cb cb)
 the core of all waitstream() functions

Variables

int ast_language_is_prefix = 1
 The following variable controls the layout of localized sound files. If 0, use the historical layout with prefix just before the filename (i.e. digits/en/1.gsm , digits/it/1.gsm or default to digits/1.gsm), if 1 put the prefix at the beginning of the filename (i.e. en/digits/1.gsm, it/digits/1.gsm or default to digits/1.gsm). The latter permits a language to be entirely in one directory.
static struct ast_cli_entry cli_file []


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 FORMAT2   "%-10s %-10s %-20s\n"


Enumeration Type Documentation

Enumerator:
ACTION_EXISTS 
ACTION_DELETE 
ACTION_RENAME 
ACTION_OPEN 
ACTION_COPY 

Definition at line 487 of file file.c.

00487                  {
00488    ACTION_EXISTS = 1, /* return matching format if file exists, 0 otherwise */
00489    ACTION_DELETE, /* delete file, return 0 on success, -1 on error */
00490    ACTION_RENAME, /* rename file. return 0 on success, -1 on error */
00491    ACTION_OPEN,
00492    ACTION_COPY /* copy file. return 0 on success, -1 on error */
00493 };

enum fsread_res

Enumerator:
FSREAD_FAILURE 
FSREAD_SUCCESS_SCHED 
FSREAD_SUCCESS_NOSCHED 

Definition at line 877 of file file.c.

00877                 {
00878    FSREAD_FAILURE,
00879    FSREAD_SUCCESS_SCHED,
00880    FSREAD_SUCCESS_NOSCHED,
00881 };

enum wrap_fn

Enumerator:
WRAP_OPEN 
WRAP_REWRITE 

Definition at line 458 of file file.c.

00458 { WRAP_OPEN, WRAP_REWRITE };


Function Documentation

int __ast_format_def_register ( const struct ast_format_def f,
struct ast_module mod 
)

Register a new file format capability. Adds a format to Asterisk's format abilities.

Return values:
0 on success
-1 on failure

Definition at line 125 of file file.c.

References a, ast_calloc, ast_format_register_type(), ast_log, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, b, ast_format_def::buf_size, ast_format_def::exts, ast_format_def::list, LOG_WARNING, ast_format_def::module, ast_format_def::name, publish_format_update(), and tmp().

00126 {
00127    struct ast_format_def *tmp;
00128 
00129    AST_RWLIST_WRLOCK(&formats);
00130    AST_RWLIST_TRAVERSE(&formats, tmp, list) {
00131       if (!strcasecmp(f->name, tmp->name)) {
00132          AST_RWLIST_UNLOCK(&formats);
00133          ast_log(LOG_WARNING, "Tried to register '%s' format, already registered\n", f->name);
00134          return -1;
00135       }
00136    }
00137    if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
00138       AST_RWLIST_UNLOCK(&formats);
00139       return -1;
00140    }
00141    *tmp = *f;
00142    tmp->module = mod;
00143    if (tmp->buf_size) {
00144       /*
00145        * Align buf_size properly, rounding up to the machine-specific
00146        * alignment for pointers.
00147        */
00148       struct _test_align { void *a, *b; } p;
00149       int align = (char *)&p.b - (char *)&p.a;
00150       tmp->buf_size = ((f->buf_size + align - 1) / align) * align;
00151    }
00152 
00153    memset(&tmp->list, 0, sizeof(tmp->list));
00154 
00155    AST_RWLIST_INSERT_HEAD(&formats, tmp, list);
00156    AST_RWLIST_UNLOCK(&formats);
00157    ast_verb(2, "Registered file format %s, extension(s) %s\n", f->name, f->exts);
00158    publish_format_update(f, ast_format_register_type());
00159 
00160    return 0;
00161 }

static void __fini_formats ( void   )  [static]

Definition at line 70 of file file.c.

00076 {

static void __init_formats ( void   )  [static]

Definition at line 70 of file file.c.

00076 {

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
Return values:
0 on success.
-1 on failure.

Definition at line 991 of file file.c.

References ast_filestream::owner.

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

00992 {
00993    s->owner = chan;
00994    return 0;
00995 }

int ast_closestream ( struct ast_filestream f  ) 

Closes a stream.

Parameters:
f filestream to close Close a playback or recording stream
Return values:
0 on success.
-1 on failure.

Definition at line 1039 of file file.c.

References ao2_ref, filestream_close(), and NULL.

Referenced by __ast_play_and_record(), ast_hangup(), ast_moh_files_next(), ast_monitor_start(), ast_monitor_stop(), ast_readfile(), ast_stopstream(), ast_writefile(), dictate_exec(), filehelper(), filestream_destructor(), gen_closestream(), handle_cli_file_convert(), handle_recordfile(), local_ast_moh_stop(), mixmonitor_ds_close_fs(), moh_files_release(), msg_create_from_file(), record_exec(), and recordthread().

01040 {
01041    /* This used to destroy the filestream, but it now just decrements a refcount.
01042     * We close the stream in order to quit queuing frames now, because we might
01043     * change the writeformat, which could result in a subsequent write error, if
01044     * the format is different. */
01045    if (f == NULL) {
01046       return 0;
01047    }
01048    filestream_close(f);
01049    ao2_ref(f, -1);
01050    return 0;
01051 }

int ast_file_init ( void   ) 

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

References ACTION_COPY, and filehelper().

Referenced by copy_plain_file(), msg_create_from_file(), stasis_app_stored_recording_copy(), and vm_forwardoptions().

01080 {
01081    return filehelper(filename, filename2, fmt, ACTION_COPY);
01082 }

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

References ACTION_DELETE, filehelper(), and NULL.

Referenced by __ast_play_and_record(), announce_thread(), ast_monitor_start(), ast_monitor_stop(), conf_free(), conf_run(), confbridge_exec(), dial_exec_full(), handle_cli_file_convert(), leave_voicemail(), msg_create_from_file(), play_record_review(), record_exec(), recording_cancel(), setup_privacy_args(), and vm_delete().

01070 {
01071    return filehelper(filename, NULL, fmt, ACTION_DELETE);
01072 }

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.
Return values:
0,false. The file does not exist
1,true. The file does exist.

Definition at line 1057 of file file.c.

References ast_alloca, buf, fileexists_core(), and NULL.

Referenced by announce_thread(), app_exec(), ast_moh_files_next(), ast_monitor_start(), ast_monitor_stop(), common_exec(), conf_run(), dial_exec_full(), eivr_comm(), forward_message(), get_folder(), invent_message(), leave_voicemail(), meetme_menu_admin_extended(), minivm_delete_exec(), msg_create_from_file(), play_file(), play_message(), play_message_by_id_helper(), play_message_callerid(), readexten_exec(), record_exec(), retrydial_exec(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), sayname(), setup_privacy_args(), sound_file_exists(), stasis_app_control_record(), vm_intro(), vm_msg_play(), vm_newuser(), vm_options(), and vm_tempgreeting().

01058 {
01059    char *buf;
01060    int buflen;
01061 
01062    if (preflang == NULL)
01063       preflang = "";
01064    buflen = strlen(preflang) + strlen(filename) + 4;  /* room for everything */
01065    buf = ast_alloca(buflen);
01066    return fileexists_core(filename, fmt, preflang, buf, buflen, NULL) ? 1 : 0;
01067 }

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

References ACTION_RENAME, and filehelper().

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

01075 {
01076    return filehelper(filename, filename2, fmt, ACTION_RENAME);
01077 }

int ast_format_def_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.
Return values:
0 on success
-1 on failure to unregister

Definition at line 163 of file file.c.

References ast_format_unregister_type(), ast_free, ast_log, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_format_def::list, LOG_WARNING, ast_format_def::name, publish_format_update(), and tmp().

Referenced by unload_module().

00164 {
00165    struct ast_format_def *tmp;
00166    int res = -1;
00167 
00168    AST_RWLIST_WRLOCK(&formats);
00169    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&formats, tmp, list) {
00170       if (!strcasecmp(name, tmp->name)) {
00171          AST_RWLIST_REMOVE_CURRENT(list);
00172          publish_format_update(tmp, ast_format_unregister_type());
00173          ast_free(tmp);
00174          res = 0;
00175       }
00176    }
00177    AST_RWLIST_TRAVERSE_SAFE_END;
00178    AST_RWLIST_UNLOCK(&formats);
00179 
00180    if (!res)
00181       ast_verb(2, "Unregistered format %s\n", name);
00182    else
00183       ast_log(LOG_WARNING, "Tried to unregister format %s, already unregistered\n", name);
00184 
00185    return res;
00186 }

char* ast_format_str_reduce ( char *  fmts  ) 

Remove duplicate formats from a format string.

Parameters:
fmts a format string, this string will be modified
Return values:
NULL error
Returns:
a pointer to the reduced format string, this is a pointer to fmts

Definition at line 1642 of file file.c.

References ast_log, AST_MAX_FORMATS, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdupa, ast_format_def::exts, exts_compare(), f, first, len(), ast_format_def::list, LOG_WARNING, NULL, strsep(), and type.

Referenced by actual_load_config(), and AST_TEST_DEFINE().

01643 {
01644    struct ast_format_def *f;
01645    struct ast_format_def *fmts_ptr[AST_MAX_FORMATS];
01646    char *fmts_str[AST_MAX_FORMATS];
01647    char *stringp, *type;
01648    char *orig = fmts;
01649    int i, j, x, first, found = 0;
01650    int len = strlen(fmts) + 1;
01651    int res;
01652 
01653    if (AST_RWLIST_RDLOCK(&formats)) {
01654       ast_log(LOG_WARNING, "Unable to lock format list\n");
01655       return NULL;
01656    }
01657 
01658    stringp = ast_strdupa(fmts);
01659 
01660    for (x = 0; (type = strsep(&stringp, "|")) && x < AST_MAX_FORMATS; x++) {
01661       AST_RWLIST_TRAVERSE(&formats, f, list) {
01662          if (exts_compare(f->exts, type)) {
01663             found = 1;
01664             break;
01665          }
01666       }
01667 
01668       fmts_str[x] = type;
01669       if (found) {
01670          fmts_ptr[x] = f;
01671       } else {
01672          fmts_ptr[x] = NULL;
01673       }
01674    }
01675    AST_RWLIST_UNLOCK(&formats);
01676 
01677    first = 1;
01678    for (i = 0; i < x; i++) {
01679       /* ignore invalid entries */
01680       if (!fmts_ptr[i]) {
01681          ast_log(LOG_WARNING, "ignoring unknown format '%s'\n", fmts_str[i]);
01682          continue;
01683       }
01684 
01685       /* special handling for the first entry */
01686       if (first) {
01687          res = snprintf(fmts, len, "%s", fmts_str[i]);
01688          fmts += res;
01689          len -= res;
01690          first = 0;
01691          continue;
01692       }
01693 
01694       found = 0;
01695       for (j = 0; j < i; j++) {
01696          /* this is a duplicate */
01697          if (fmts_ptr[j] == fmts_ptr[i]) {
01698             found = 1;
01699             break;
01700          }
01701       }
01702 
01703       if (!found) {
01704          res = snprintf(fmts, len, "|%s", fmts_str[i]);
01705          fmts += res;
01706          len -= res;
01707       }
01708    }
01709 
01710    if (first) {
01711       ast_log(LOG_WARNING, "no known formats found in format list (%s)\n", orig);
01712       return NULL;
01713    }
01714 
01715    return orig;
01716 }

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

Definition at line 933 of file file.c.

References ast_readaudio_callback(), and FSREAD_SUCCESS_SCHED.

Referenced by ast_readaudio_callback().

00934 {
00935    struct ast_filestream *fs = (struct ast_filestream *)data;
00936    enum fsread_res res;
00937 
00938    res = ast_readaudio_callback(fs);
00939 
00940    if (res == FSREAD_SUCCESS_SCHED)
00941       return 1;
00942 
00943    return 0;
00944 }

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

Definition at line 978 of file file.c.

References ast_readvideo_callback(), and FSREAD_SUCCESS_SCHED.

Referenced by ast_readvideo_callback().

00979 {
00980    struct ast_filestream *fs = (struct ast_filestream *)data;
00981    enum fsread_res res;
00982 
00983    res = ast_readvideo_callback(fs);
00984 
00985    if (res == FSREAD_SUCCESS_SCHED)
00986       return 1;
00987 
00988    return 0;
00989 }

struct ast_format* ast_get_format_for_file_ext ( const char *  file_ext  )  [read]

Get the ast_format associated with the given file extension.

Since:
12
Parameters:
file_ext The file extension for which to find the format
Return values:
NULL if not found
A pointer to the ast_format associated with this file extension

Definition at line 1754 of file file.c.

References AST_RWLIST_TRAVERSE, ast_format_def::exts, exts_compare(), f, ast_format_def::format, ast_format_def::list, lock, NULL, and SCOPED_RDLOCK.

Referenced by ast_ari_bridges_record(), ast_ari_channels_record(), find_recording(), process_media_file(), and scan_file().

01755 {
01756    struct ast_format_def *f;
01757    SCOPED_RDLOCK(lock, &formats.lock);
01758    AST_RWLIST_TRAVERSE(&formats, f, list) {
01759       if (exts_compare(f->exts, file_ext)) {
01760          return f->format;
01761       }
01762    }
01763 
01764    return NULL;
01765 }

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
Return values:
a ast_filestream pointer if it opens the file.
NULL on error.

Definition at line 735 of file file.c.

References ast_openstream_full().

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

00736 {
00737    return ast_openstream_full(chan, filename, preflang, 0);
00738 }

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
Return values:
a ast_filestream pointer if it opens the file.
NULL on error.

Definition at line 740 of file file.c.

References ACTION_OPEN, ao2_ref, ast_alloca, ast_channel_generator(), ast_channel_lock, ast_channel_set_oldwriteformat(), ast_channel_stream(), ast_channel_unlock, ast_channel_writeformat(), ast_deactivate_generator(), ast_format_cap_alloc, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_has_type(), ast_log, AST_MEDIA_TYPE_AUDIO, ast_set_write_format_from_cap(), ast_stopstream(), buf, fileexists_core(), filehelper(), LOG_WARNING, and NULL.

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

00741 {
00742    /*
00743     * Use fileexists_core() to find a file in a compatible
00744     * language and format, set up a suitable translator,
00745     * and open the stream.
00746     */
00747    struct ast_format_cap *file_fmt_cap;
00748    int res;
00749    int buflen;
00750    char *buf;
00751 
00752    if (!asis) {
00753       /* do this first, otherwise we detect the wrong writeformat */
00754       ast_stopstream(chan);
00755       if (ast_channel_generator(chan))
00756          ast_deactivate_generator(chan);
00757    }
00758    if (preflang == NULL)
00759       preflang = "";
00760    buflen = strlen(preflang) + strlen(filename) + 4;
00761    buf = ast_alloca(buflen);
00762 
00763    if (!(file_fmt_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
00764       return NULL;
00765    }
00766    if (!fileexists_core(filename, NULL, preflang, buf, buflen, file_fmt_cap) ||
00767       !ast_format_cap_has_type(file_fmt_cap, AST_MEDIA_TYPE_AUDIO)) {
00768 
00769       ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
00770       ao2_ref(file_fmt_cap, -1);
00771       return NULL;
00772    }
00773 
00774    /* Set the channel to a format we can work with and save off the previous format. */
00775    ast_channel_lock(chan);
00776    ast_channel_set_oldwriteformat(chan, ast_channel_writeformat(chan));
00777    /* Set the channel to the best format that exists for the file. */
00778    res = ast_set_write_format_from_cap(chan, file_fmt_cap);
00779    ast_channel_unlock(chan);
00780    /* don't need this anymore now that the channel's write format is set. */
00781    ao2_ref(file_fmt_cap, -1);
00782 
00783    if (res == -1) {  /* No format available that works with this channel */
00784       return NULL;
00785    }
00786    res = filehelper(buf, chan, NULL, ACTION_OPEN);
00787    if (res >= 0)
00788       return ast_channel_stream(chan);
00789    return NULL;
00790 }

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
Return values:
a ast_filestream pointer if it opens the file.
NULL on error.

Definition at line 792 of file file.c.

References ACTION_OPEN, ao2_ref, ast_alloca, ast_channel_nativeformats(), ast_channel_vstream(), ast_format_cap_alloc, ast_format_cap_count(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_format(), ast_format_cap_has_type(), ast_format_cap_iscompatible(), ast_format_get_name(), ast_format_get_type(), ast_log, AST_MEDIA_TYPE_VIDEO, buf, fileexists_core(), filehelper(), format, LOG_WARNING, and NULL.

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

00793 {
00794    /* As above, but for video. But here we don't have translators
00795     * so we must enforce a format.
00796     */
00797    struct ast_format_cap *tmp_cap;
00798    char *buf;
00799    int buflen;
00800    int i, fd;
00801 
00802    if (preflang == NULL) {
00803       preflang = "";
00804    }
00805    buflen = strlen(preflang) + strlen(filename) + 4;
00806    buf = ast_alloca(buflen);
00807 
00808    /* is the channel capable of video without translation ?*/
00809    if (!ast_format_cap_has_type(ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO)) {
00810       return NULL;
00811    }
00812    if (!(tmp_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
00813       return NULL;
00814    }
00815    /* Video is supported, so see what video formats exist for this file */
00816    if (!fileexists_core(filename, NULL, preflang, buf, buflen, tmp_cap)) {
00817       ao2_ref(tmp_cap, -1);
00818       return NULL;
00819    }
00820 
00821    /* iterate over file formats and pick the first one compatible with the channel's native formats */
00822    for (i = 0; i < ast_format_cap_count(tmp_cap); ++i) {
00823       struct ast_format *format = ast_format_cap_get_format(tmp_cap, i);
00824 
00825       if ((ast_format_get_type(format) != AST_MEDIA_TYPE_VIDEO) ||
00826          !ast_format_cap_iscompatible(ast_channel_nativeformats(chan), tmp_cap)) {
00827          ao2_ref(format, -1);
00828          continue;
00829       }
00830 
00831       fd = filehelper(buf, chan, ast_format_get_name(format), ACTION_OPEN);
00832       if (fd >= 0) {
00833          ao2_ref(format, -1);
00834          ao2_ref(tmp_cap, -1);
00835          return ast_channel_vstream(chan);
00836       }
00837       ast_log(LOG_WARNING, "File %s has video but couldn't be opened\n", filename);
00838       ao2_ref(format, -1);
00839    }
00840    ao2_ref(tmp_cap, -1);
00841 
00842    return NULL;
00843 }

int ast_playstream ( struct ast_filestream s  ) 

Play a open stream on a channel.

Parameters:
s filestream to play
Return values:
0 on success.
-1 on failure.

Definition at line 997 of file file.c.

References ast_format_get_type(), AST_MEDIA_TYPE_AUDIO, ast_readaudio_callback(), ast_readvideo_callback(), ast_filestream::fmt, ast_format_def::format, and FSREAD_FAILURE.

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

00998 {
00999    enum fsread_res res;
01000 
01001    if (ast_format_get_type(s->fmt->format) == AST_MEDIA_TYPE_AUDIO)
01002       res = ast_readaudio_callback(s);
01003    else
01004       res = ast_readvideo_callback(s);
01005 
01006    return (res == FSREAD_FAILURE) ? -1 : 0;
01007 }

int ast_ratestream ( struct ast_filestream fs  ) 

Return the sample rate of the stream's format.

Parameters:
fs fs to act on
Returns:
sample rate in Hz

Definition at line 1024 of file file.c.

References ast_format_get_sample_rate(), ast_filestream::fmt, and ast_format_def::format.

Referenced by msg_create_from_file().

01025 {
01026    return ast_format_get_sample_rate(fs->fmt->format);
01027 }

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

Definition at line 885 of file file.c.

References ast_channel_name(), ast_channel_sched(), ast_channel_streamid_set(), ast_channel_timingfd(), ast_format_get_sample_rate(), ast_frfree, ast_fsread_audio(), ast_log, ast_sched_add(), ast_settimeout(), ast_settimeout_full(), ast_write(), ast_filestream::fmt, ast_format_def::format, FSREAD_FAILURE, FSREAD_SUCCESS_NOSCHED, FSREAD_SUCCESS_SCHED, ast_filestream::lasttimeout, LOG_WARNING, NULL, ast_filestream::orig_chan_name, ast_filestream::owner, read_frame(), and roundf().

Referenced by ast_fsread_audio(), and ast_playstream().

00886 {
00887    int whennext = 0;
00888 
00889    while (!whennext) {
00890       struct ast_frame *fr;
00891 
00892       if (s->orig_chan_name && strcasecmp(ast_channel_name(s->owner), s->orig_chan_name)) {
00893          goto return_failure;
00894       }
00895 
00896       fr = read_frame(s, &whennext);
00897 
00898       if (!fr /* stream complete */ || ast_write(s->owner, fr) /* error writing */) {
00899          if (fr) {
00900             ast_log(LOG_WARNING, "Failed to write frame\n");
00901             ast_frfree(fr);
00902          }
00903          goto return_failure;
00904       }
00905 
00906       if (fr) {
00907          ast_frfree(fr);
00908       }
00909    }
00910 
00911    if (whennext != s->lasttimeout) {
00912       if (ast_channel_timingfd(s->owner) > -1) {
00913          float samp_rate = (float) ast_format_get_sample_rate(s->fmt->format);
00914          unsigned int rate;
00915 
00916          rate = (unsigned int) roundf(samp_rate / ((float) whennext));
00917 
00918          ast_settimeout_full(s->owner, rate, ast_fsread_audio, s, 1);
00919       } else {
00920          ast_channel_streamid_set(s->owner, ast_sched_add(ast_channel_sched(s->owner), whennext / (ast_format_get_sample_rate(s->fmt->format) / 1000), ast_fsread_audio, s));
00921       }
00922       s->lasttimeout = whennext;
00923       return FSREAD_SUCCESS_NOSCHED;
00924    }
00925    return FSREAD_SUCCESS_SCHED;
00926 
00927 return_failure:
00928    ast_channel_streamid_set(s->owner, -1);
00929    ast_settimeout(s->owner, 0, NULL, NULL);
00930    return FSREAD_FAILURE;
00931 }

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.
Return values:
a struct ast_filestream on success.
NULL on failure.

Definition at line 1136 of file file.c.

References ast_closestream(), ast_free, ast_log, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, build_filename(), errno, ast_format_def::exts, exts_compare(), f, ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, get_filestream(), LOG_WARNING, ast_filestream::mode, NULL, open_wrapper(), ast_filestream::trans, and ast_filestream::vfs.

Referenced by __ast_play_and_record(), handle_cli_file_convert(), and msg_create_from_file().

01137 {
01138    FILE *bfile;
01139    struct ast_format_def *f;
01140    struct ast_filestream *fs = NULL;
01141    char *fn;
01142    int format_found = 0;
01143 
01144    AST_RWLIST_RDLOCK(&formats);
01145 
01146    AST_RWLIST_TRAVERSE(&formats, f, list) {
01147       fs = NULL;
01148       if (!exts_compare(f->exts, type))
01149          continue;
01150       else
01151          format_found = 1;
01152 
01153       fn = build_filename(filename, type);
01154       if (!fn) {
01155          continue;
01156       }
01157       errno = 0;
01158       bfile = fopen(fn, "r");
01159 
01160       if (!bfile || (fs = get_filestream(f, bfile)) == NULL || open_wrapper(fs) ) {
01161          ast_log(LOG_WARNING, "Unable to open %s\n", fn);
01162          if (fs) {
01163             ast_closestream(fs);
01164          }
01165          fs = NULL;
01166          bfile = NULL;
01167          ast_free(fn);
01168          break;
01169       }
01170       /* found it */
01171       fs->trans = NULL;
01172       fs->fmt = f;
01173       fs->flags = flags;
01174       fs->mode = mode;
01175       fs->filename = ast_strdup(filename);
01176       fs->vfs = NULL;
01177       ast_free(fn);
01178       break;
01179    }
01180 
01181    AST_RWLIST_UNLOCK(&formats);
01182    if (!format_found)
01183       ast_log(LOG_WARNING, "No such format '%s'\n", type);
01184 
01185    return fs;
01186 }

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.
Return values:
NULL if read failed.

Definition at line 870 of file file.c.

References read_frame().

Referenced by __ast_play_and_record(), dictate_exec(), gen_readframe(), handle_cli_file_convert(), and moh_files_readframe().

00871 {
00872    int whennext = 0;
00873 
00874    return read_frame(s, &whennext);
00875 }

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

Definition at line 948 of file file.c.

References ast_channel_sched(), ast_channel_vstreamid_set(), ast_format_get_sample_rate(), ast_frfree, ast_fsread_video(), ast_log, ast_sched_add(), ast_write(), ast_filestream::fmt, ast_format_def::format, FSREAD_FAILURE, FSREAD_SUCCESS_NOSCHED, FSREAD_SUCCESS_SCHED, ast_filestream::lasttimeout, LOG_WARNING, ast_filestream::owner, and read_frame().

Referenced by ast_fsread_video(), and ast_playstream().

00949 {
00950    int whennext = 0;
00951 
00952    while (!whennext) {
00953       struct ast_frame *fr = read_frame(s, &whennext);
00954 
00955       if (!fr /* stream complete */ || ast_write(s->owner, fr) /* error writing */) {
00956          if (fr) {
00957             ast_log(LOG_WARNING, "Failed to write frame\n");
00958             ast_frfree(fr);
00959          }
00960          ast_channel_vstreamid_set(s->owner, -1);
00961          return FSREAD_FAILURE;
00962       }
00963 
00964       if (fr) {
00965          ast_frfree(fr);
00966       }
00967    }
00968 
00969    if (whennext != s->lasttimeout) {
00970       ast_channel_vstreamid_set(s->owner, ast_sched_add(ast_channel_sched(s->owner), whennext / (ast_format_get_sample_rate(s->fmt->format) / 1000), ast_fsread_video, s));
00971       s->lasttimeout = whennext;
00972       return FSREAD_SUCCESS_NOSCHED;
00973    }
00974 
00975    return FSREAD_SUCCESS_SCHED;
00976 }

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
Return values:
0 on success.
-1 on failure.

Definition at line 1009 of file file.c.

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

Referenced by __ast_read(), ast_moh_files_next(), ast_stream_fastforward(), ast_stream_rewind(), ast_streamfile(), ast_write(), control_streamfile(), dictate_exec(), handle_getoption(), handle_recordfile(), handle_streamfile(), msg_create_from_file(), and speech_streamfile().

01010 {
01011    return fs->fmt->seek(fs, sample_offset, whence);
01012 }

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

References ast_channel_lock, ast_channel_oldwriteformat(), ast_channel_stream(), ast_channel_stream_set(), ast_channel_unlock, ast_channel_vstream(), ast_channel_vstream_set(), ast_closestream(), ast_format_get_name(), ast_log, ast_set_write_format(), LOG_WARNING, and NULL.

Referenced by action_playback_and_continue(), adsi_transmit_message_full(), agent_alert(), announce_to_dial(), 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_enumeration_full_he(), ast_say_enumeration_full_vi(), ast_say_number_full_cs(), 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_hu(), ast_say_number_full_it(), ast_say_number_full_ja(), ast_say_number_full_ka(), 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_th(), ast_say_number_full_ur(), ast_say_number_full_vi(), ast_say_number_full_zh(), background_detect_exec(), conf_exec(), conf_run(), control_streamfile(), dial_exec_full(), directory_exec(), grab_transfer(), handle_getoption(), handle_speechrecognize(), handle_streamfile(), ices_exec(), ivr_dispatch(), leave_voicemail(), meetme_menu_admin(), meetme_menu_admin_extended(), minivm_greet_exec(), mp3_exec(), NBScat_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_file(), play_files_helper(), play_mailbox_owner(), playback_exec(), queue_exec(), read_exec(), readexten_exec(), record_exec(), recordthread(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), select_item_seq(), send_waveform_to_channel(), speech_background(), vm_authenticate(), vm_execmain(), wait_for_winner(), waitstream_core(), and zapateller_exec().

00189 {
00190    ast_channel_lock(tmp);
00191 
00192    /* Stop a running stream if there is one */
00193    if (ast_channel_stream(tmp)) {
00194       ast_closestream(ast_channel_stream(tmp));
00195       ast_channel_stream_set(tmp, NULL);
00196       if (ast_channel_oldwriteformat(tmp) && ast_set_write_format(tmp, ast_channel_oldwriteformat(tmp)))
00197          ast_log(LOG_WARNING, "Unable to restore format back to %s\n", ast_format_get_name(ast_channel_oldwriteformat(tmp)));
00198    }
00199    /* Stop the video stream too */
00200    if (ast_channel_vstream(tmp) != NULL) {
00201       ast_closestream(ast_channel_vstream(tmp));
00202       ast_channel_vstream_set(tmp, NULL);
00203    }
00204 
00205    ast_channel_unlock(tmp);
00206 
00207    return 0;
00208 }

int ast_stream_and_wait ( struct ast_channel chan,
const char *  file,
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
Return values:
0 on success.
-1 on failure.

Definition at line 1029 of file file.c.

References ast_seekstream(), and DEFAULT_SAMPLES_PER_MS.

Referenced by waitstream_control().

01030 {
01031    return ast_seekstream(fs, ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR);
01032 }

int ast_stream_rewind ( struct ast_filestream fs,
off_t  ms 
)

Rewind stream ms.

Parameters:
fs filestream to act on
ms milliseconds to move
Return values:
0 on success.
-1 on failure.

Definition at line 1034 of file file.c.

References ast_seekstream(), and DEFAULT_SAMPLES_PER_MS.

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

01035 {
01036    return ast_seekstream(fs, -ms * DEFAULT_SAMPLES_PER_MS, SEEK_CUR);
01037 }

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.
Return values:
0 on success.
-1 on failure.

Definition at line 1084 of file file.c.

References ast_applystream(), ast_channel_flags(), ast_channel_name(), ast_channel_nativeformats(), ast_channel_writeformat(), ast_debug, AST_FLAG_MASQ_NOSTREAM, ast_format_cap_get_names(), ast_format_get_name(), ast_log, ast_openstream(), ast_openvstream(), ast_playstream(), ast_seekstream(), ast_str_alloca, ast_strdup, ast_test_flag, ast_test_suite_event_notify, ast_verb, errno, ast_filestream::f, ast_filestream::fmt, ast_format_def::format, LOG_WARNING, NULL, ast_filestream::orig_chan_name, and ast_filestream::vfs.

Referenced by __analog_ss_thread(), action_playback_and_continue(), analog_ss_thread(), announce_thread(), announce_to_dial(), app_exec(), ast_app_getdata(), ast_app_getdata_full(), ast_play_and_wait(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_hu(), ast_say_date_ja(), ast_say_date_ka(), ast_say_date_nl(), ast_say_date_th(), 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_he(), ast_say_datetime_from_now_ka(), ast_say_datetime_gr(), ast_say_datetime_he(), ast_say_datetime_ja(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_th(), ast_say_datetime_zh(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_enumeration_full_he(), ast_say_enumeration_full_vi(), ast_say_number_full_cs(), 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_hu(), ast_say_number_full_it(), ast_say_number_full_ja(), ast_say_number_full_ka(), 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_th(), ast_say_number_full_ur(), ast_say_number_full_vi(), ast_say_number_full_zh(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_gr(), ast_say_time_hu(), ast_say_time_ja(), ast_say_time_ka(), ast_say_time_nl(), ast_say_time_zh(), ast_stream_and_wait(), auth_exec(), background_detect_exec(), common_exec(), conf_exec(), conf_get_pin(), conf_run(), control_streamfile(), dial_exec_full(), do_directory(), find_conf_realtime(), forward_message(), gr_say_number_female(), handle_recordfile(), invent_message(), leave_voicemail(), meetme_menu_admin(), meetme_menu_admin_extended(), meetme_menu_normal(), minivm_greet_exec(), page_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_and_wait(), play_file(), play_record_review(), playback_exec(), privacy_exec(), readexten_exec(), record_exec(), retrydial_exec(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), select_item_menu(), setup_privacy_args(), vm_authenticate(), wait_file(), and wait_for_winner().

01085 {
01086    struct ast_filestream *fs;
01087    struct ast_filestream *vfs=NULL;
01088    off_t pos;
01089    int seekattempt;
01090    int res;
01091 
01092    fs = ast_openstream(chan, filename, preflang);
01093    if (!fs) {
01094       struct ast_str *codec_buf = ast_str_alloca(64);
01095       ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n",
01096          filename, ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf), strerror(errno));
01097       return -1;
01098    }
01099 
01100    /* check to see if there is any data present (not a zero length file),
01101     * done this way because there is no where for ast_openstream_full to
01102     * return the file had no data. */
01103    pos = ftello(fs->f);
01104    seekattempt = fseeko(fs->f, -1, SEEK_END);
01105    if (seekattempt) {
01106       if (errno == EINVAL) {
01107          /* Zero-length file, as opposed to a pipe */
01108          return 0;
01109       } else {
01110          ast_seekstream(fs, 0, SEEK_SET);
01111       }
01112    } else {
01113       fseeko(fs->f, pos, SEEK_SET);
01114    }
01115 
01116    vfs = ast_openvstream(chan, filename, preflang);
01117    if (vfs) {
01118       ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_format_get_name(vfs->fmt->format));
01119    }
01120 
01121    if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_MASQ_NOSTREAM))
01122       fs->orig_chan_name = ast_strdup(ast_channel_name(chan));
01123    if (ast_applystream(chan, fs))
01124       return -1;
01125    if (vfs && ast_applystream(chan, vfs))
01126       return -1;
01127    ast_test_suite_event_notify("PLAYBACK", "Message: %s\r\nChannel: %s", filename, ast_channel_name(chan));
01128    res = ast_playstream(fs);
01129    if (!res && vfs)
01130       res = ast_playstream(vfs);
01131    ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", ast_channel_name(chan), filename, ast_format_get_name(ast_channel_writeformat(chan)), preflang ? preflang : "default");
01132 
01133    return res;
01134 }

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

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

Referenced by __ast_play_and_record(), ast_moh_files_next(), control_streamfile(), handle_getoption(), handle_recordfile(), handle_speechrecognize(), handle_streamfile(), msg_create_from_file(), waitstream_control(), and waitstream_core().

01020 {
01021    return fs->fmt->tell(fs);
01022 }

int ast_truncstream ( struct ast_filestream fs  ) 

Trunc stream at current location.

Parameters:
fs filestream to act on
Return values:
0 on success.
-1 on failure.

Definition at line 1014 of file file.c.

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

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

01015 {
01016    return fs->fmt->trunc(fs);
01017 }

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,
Return values:
0 if the stream finishes
the character if it was interrupted by the channel.
-1 on error

Definition at line 1592 of file file.c.

References NULL, sanitize_waitstream_return(), and waitstream_core().

Referenced by __analog_ss_thread(), action_playback_and_continue(), analog_ss_thread(), announce_thread(), announce_to_dial(), app_exec(), ast_play_and_wait(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_hu(), ast_say_date_ja(), ast_say_date_ka(), ast_say_date_nl(), ast_say_date_th(), 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_he(), ast_say_datetime_from_now_ka(), ast_say_datetime_gr(), ast_say_datetime_he(), ast_say_datetime_ja(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_th(), ast_say_datetime_zh(), ast_say_enumeration_full_da(), ast_say_enumeration_full_de(), ast_say_enumeration_full_en(), ast_say_enumeration_full_he(), ast_say_enumeration_full_vi(), ast_say_number_full_cs(), 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_hu(), ast_say_number_full_it(), ast_say_number_full_ja(), ast_say_number_full_ka(), 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_th(), ast_say_number_full_ur(), ast_say_number_full_vi(), ast_say_number_full_zh(), ast_say_time_de(), ast_say_time_en(), ast_say_time_gr(), ast_say_time_he(), ast_say_time_hu(), ast_say_time_ja(), ast_say_time_ka(), ast_say_time_nl(), ast_say_time_zh(), ast_stream_and_wait(), auth_exec(), common_exec(), conf_exec(), conf_get_pin(), conf_run(), directory_exec(), find_conf_realtime(), gr_say_number_female(), handle_recordfile(), invent_message(), leave_voicemail(), meetme_menu_admin(), meetme_menu_admin_extended(), meetme_menu_normal(), minivm_greet_exec(), page_exec(), pbx_builtin_background(), pl_odtworz_plik(), play_and_wait(), play_file(), play_record_review(), playback_exec(), privacy_exec(), record_exec(), retrydial_exec(), s_streamwait3(), say_character_str_full(), say_digit_str_full(), say_phonetic_str_full(), select_item_menu(), setup_privacy_args(), vm_authenticate(), and wait_file().

01593 {
01594    int res;
01595 
01596    res = waitstream_core(c, breakon, NULL, NULL, 0, -1, -1, NULL, NULL /* no callback */);
01597 
01598    return sanitize_waitstream_return(res);
01599 }

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,
Return values:
0 if the stream finishes.
the character if it was interrupted.
-1 on error.

Definition at line 1611 of file file.c.

References ast_channel_context(), NULL, sanitize_waitstream_return(), and waitstream_core().

Referenced by pbx_builtin_background().

01612 {
01613    int res;
01614 
01615    /* Waitstream, with return in the case of a valid 1 digit extension */
01616    /* in the current or specified context being pressed */
01617    if (!context)
01618       context = ast_channel_context(c);
01619    res = waitstream_core(c, NULL, NULL, NULL, 0,
01620       -1, -1, context, NULL /* no callback */);
01621 
01622    return sanitize_waitstream_return(res);
01623 }

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,
Return values:
0 if the stream finishes.
the character if it was interrupted,
the value of the control frame if it was interrupted by some other party,
-1 on error.

Definition at line 1561 of file file.c.

References NULL, and waitstream_core().

Referenced by control_streamfile().

01562 {
01563    return waitstream_core(c, breakon, forward, reverse, ms,
01564       -1 /* no audiofd */, -1 /* no cmdfd */, NULL /* no context */, NULL /* no callback */);
01565 }

int ast_waitstream_fr_w_cb ( struct ast_channel c,
const char *  breakon,
const char *  forward,
const char *  rewind,
int  ms,
ast_waitstream_fr_cb  cb 
)

Same as waitstream_fr but allows a callback to be alerted when a user fastforwards or rewinds the file.

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 milliseconds to skip forward/back
cb to call when rewind or fastfoward occurs. Begins playback of a stream... Wait for a stream to stop or for any one of a given digit to arrive,
Return values:
0 if the stream finishes.
the character if it was interrupted,
the value of the control frame if it was interrupted by some other party,
-1 on error.

Definition at line 1550 of file file.c.

References NULL, and waitstream_core().

Referenced by control_streamfile().

01556 {
01557    return waitstream_core(c, breakon, forward, reverse, ms,
01558       -1 /* no audiofd */, -1 /* no cmdfd */, NULL /* no context */, cb);
01559 }

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

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.
Return values:
a struct ast_filestream on success.
NULL on failure.

Definition at line 1188 of file file.c.

References ast_alloca, ast_closestream(), ast_free, ast_log, ast_malloc, ast_opt_cache_record_files, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdup, ast_strdupa, buf, build_filename(), c, errno, ast_format_def::exts, exts_compare(), ast_filestream::f, f, ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, get_filestream(), LOG_WARNING, ast_filestream::mode, NULL, ast_filestream::realfilename, record_cache_dir, rewrite_wrapper(), ast_format_def::seek, ast_filestream::trans, ast_filestream::vfs, and ast_filestream::write_buffer.

Referenced by __ast_play_and_record(), ast_monitor_start(), ast_writestream(), dictate_exec(), handle_cli_file_convert(), handle_recordfile(), mixmonitor_save_prep(), record_exec(), and recordthread().

01189 {
01190    int fd, myflags = 0;
01191    /* compiler claims this variable can be used before initialization... */
01192    FILE *bfile = NULL;
01193    struct ast_format_def *f;
01194    struct ast_filestream *fs = NULL;
01195    char *buf = NULL;
01196    size_t size = 0;
01197    int format_found = 0;
01198 
01199    AST_RWLIST_RDLOCK(&formats);
01200 
01201    /* set the O_TRUNC flag if and only if there is no O_APPEND specified */
01202    /* We really can't use O_APPEND as it will break WAV header updates */
01203    if (flags & O_APPEND) {
01204       flags &= ~O_APPEND;
01205    } else {
01206       myflags = O_TRUNC;
01207    }
01208 
01209    myflags |= O_WRONLY | O_CREAT;
01210 
01211    /* XXX need to fix this - we should just do the fopen,
01212     * not open followed by fdopen()
01213     */
01214    AST_RWLIST_TRAVERSE(&formats, f, list) {
01215       char *fn, *orig_fn = NULL;
01216       if (fs)
01217          break;
01218 
01219       if (!exts_compare(f->exts, type))
01220          continue;
01221       else
01222          format_found = 1;
01223 
01224       fn = build_filename(filename, type);
01225       if (!fn) {
01226          continue;
01227       }
01228       fd = open(fn, flags | myflags, mode);
01229       if (fd > -1) {
01230          /* fdopen() the resulting file stream */
01231          bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w");
01232          if (!bfile) {
01233             ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno));
01234             close(fd);
01235             fd = -1;
01236          }
01237       }
01238 
01239       if (ast_opt_cache_record_files && (fd > -1)) {
01240          char *c;
01241 
01242          fclose(bfile); /* this also closes fd */
01243          /*
01244            We touch orig_fn just as a place-holder so other things (like vmail) see the file is there.
01245            What we are really doing is writing to record_cache_dir until we are done then we will mv the file into place.
01246          */
01247          orig_fn = ast_strdupa(fn);
01248          for (c = fn; *c; c++)
01249             if (*c == '/')
01250                *c = '_';
01251 
01252          size = strlen(fn) + strlen(record_cache_dir) + 2;
01253          buf = ast_alloca(size);
01254          strcpy(buf, record_cache_dir);
01255          strcat(buf, "/");
01256          strcat(buf, fn);
01257          ast_free(fn);
01258          fn = buf;
01259          fd = open(fn, flags | myflags, mode);
01260          if (fd > -1) {
01261             /* fdopen() the resulting file stream */
01262             bfile = fdopen(fd, ((flags | myflags) & O_RDWR) ? "w+" : "w");
01263             if (!bfile) {
01264                ast_log(LOG_WARNING, "Whoa, fdopen failed: %s!\n", strerror(errno));
01265                close(fd);
01266                fd = -1;
01267             }
01268          }
01269       }
01270       if (fd > -1) {
01271          errno = 0;
01272          fs = get_filestream(f, bfile);
01273          if (fs) {
01274             if ((fs->write_buffer = ast_malloc(32768))) {
01275                setvbuf(fs->f, fs->write_buffer, _IOFBF, 32768);
01276             }
01277          }
01278          if (!fs || rewrite_wrapper(fs, comment)) {
01279             ast_log(LOG_WARNING, "Unable to rewrite %s\n", fn);
01280             close(fd);
01281             if (orig_fn) {
01282                unlink(fn);
01283                unlink(orig_fn);
01284             }
01285             if (fs) {
01286                ast_closestream(fs);
01287                fs = NULL;
01288             }
01289             if (!buf) {
01290                ast_free(fn);
01291             }
01292             continue;
01293          }
01294          fs->trans = NULL;
01295          fs->fmt = f;
01296          fs->flags = flags;
01297          fs->mode = mode;
01298          if (orig_fn) {
01299             fs->realfilename = ast_strdup(orig_fn);
01300             fs->filename = ast_strdup(fn);
01301          } else {
01302             fs->realfilename = NULL;
01303             fs->filename = ast_strdup(filename);
01304          }
01305          fs->vfs = NULL;
01306          /* If truncated, we'll be at the beginning; if not truncated, then append */
01307          f->seek(fs, 0, SEEK_END);
01308       } else if (errno != EEXIST) {
01309          ast_log(LOG_WARNING, "Unable to open file %s: %s\n", fn, strerror(errno));
01310          if (orig_fn)
01311             unlink(orig_fn);
01312       }
01313       /* if buf != NULL then fn is already free and pointing to it */
01314       if (!buf)
01315          ast_free(fn);
01316    }
01317 
01318    AST_RWLIST_UNLOCK(&formats);
01319 
01320    if (!format_found)
01321       ast_log(LOG_WARNING, "No such format '%s'\n", type);
01322 
01323    return fs;
01324 }

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
Return values:
0 on success.
-1 on failure.

Definition at line 210 of file file.c.

References ao2_replace, ast_debug, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_name(), ast_format_get_type(), AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, AST_LIST_NEXT, ast_log, AST_MEDIA_TYPE_AUDIO, ast_translate(), ast_translator_build_path(), ast_translator_free_path(), ast_writefile(), ast_writestream(), ast_filestream::filename, ast_filestream::flags, ast_filestream::fmt, ast_frame_subclass::format, ast_format_def::format, ast_frame::frametype, ast_filestream::lastwriteformat, LOG_WARNING, ast_filestream::mode, ast_format_def::name, NULL, ast_frame::subclass, ast_filestream::trans, type, ast_filestream::vfs, and ast_format_def::write.

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

00211 {
00212    int res = -1;
00213    if (f->frametype == AST_FRAME_VIDEO) {
00214       if (ast_format_get_type(fs->fmt->format) == AST_MEDIA_TYPE_AUDIO) {
00215          /* This is the audio portion.  Call the video one... */
00216          if (!fs->vfs && fs->filename) {
00217             const char *type = ast_format_get_name(f->subclass.format);
00218             fs->vfs = ast_writefile(fs->filename, type, NULL, fs->flags, 0, fs->mode);
00219             ast_debug(1, "Opened video output file\n");
00220          }
00221          if (fs->vfs)
00222             return ast_writestream(fs->vfs, f);
00223          /* else ignore */
00224          return 0;
00225       }
00226    } else if (f->frametype != AST_FRAME_VOICE) {
00227       ast_log(LOG_WARNING, "Tried to write non-voice frame\n");
00228       return -1;
00229    }
00230    if (ast_format_cmp(f->subclass.format, fs->fmt->format) != AST_FORMAT_CMP_NOT_EQUAL) {
00231       res =  fs->fmt->write(fs, f);
00232       if (res < 0)
00233          ast_log(LOG_WARNING, "Natural write failed\n");
00234       else if (res > 0)
00235          ast_log(LOG_WARNING, "Huh??\n");
00236    } else {
00237       /* XXX If they try to send us a type of frame that isn't the normal frame, and isn't
00238              the one we've setup a translator for, we do the "wrong thing" XXX */
00239       if (fs->trans && (ast_format_cmp(f->subclass.format, fs->lastwriteformat) != AST_FORMAT_CMP_EQUAL)) {
00240          ast_translator_free_path(fs->trans);
00241          fs->trans = NULL;
00242       }
00243       if (!fs->trans) {
00244          fs->trans = ast_translator_build_path(fs->fmt->format, f->subclass.format);
00245       }
00246       if (!fs->trans) {
00247          ast_log(LOG_WARNING, "Unable to translate to format %s, source format %s\n",
00248             fs->fmt->name, ast_format_get_name(f->subclass.format));
00249       } else {
00250          struct ast_frame *trf;
00251          ao2_replace(fs->lastwriteformat, f->subclass.format);
00252          /* Get the translated frame but don't consume the original in case they're using it on another stream */
00253          if ((trf = ast_translate(fs->trans, f, 0))) {
00254             struct ast_frame *cur;
00255 
00256             /* the translator may have returned multiple frames, so process them */
00257             for (cur = trf; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
00258                if ((res = fs->fmt->write(fs, trf))) {
00259                   ast_log(LOG_WARNING, "Translated frame write failed\n");
00260                   break;
00261                }
00262             }
00263             ast_frfree(trf);
00264          } else {
00265             res = 0;
00266          }
00267       }
00268    }
00269    return res;
00270 }

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

References ast_asprintf, ast_config_AST_DATA_DIR, and NULL.

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

00316 {
00317    char *fn = NULL;
00318 
00319    if (!strcmp(ext, "wav49"))
00320       ext = "WAV";
00321 
00322    if (filename[0] == '/') {
00323       if (ast_asprintf(&fn, "%s.%s", filename, ext) < 0) {
00324          fn = NULL;
00325       }
00326    } else {
00327       if (ast_asprintf(&fn, "%s/sounds/%s.%s",
00328               ast_config_AST_DATA_DIR, filename, ext) < 0) {
00329          fn = NULL;
00330       }
00331    }
00332    return fn;
00333 }

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

Definition at line 272 of file file.c.

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

00273 {
00274    int ifd, ofd, len;
00275    char buf[4096];   /* XXX make it lerger. */
00276 
00277    if ((ifd = open(infile, O_RDONLY)) < 0) {
00278       ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile);
00279       return -1;
00280    }
00281    if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, AST_FILE_MODE)) < 0) {
00282       ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile);
00283       close(ifd);
00284       return -1;
00285    }
00286    while ( (len = read(ifd, buf, sizeof(buf)) ) ) {
00287       int res;
00288       if (len < 0) {
00289          ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
00290          break;
00291       }
00292       /* XXX handle partial writes */
00293       res = write(ofd, buf, len);
00294       if (res != len) {
00295          ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
00296          len = -1; /* error marker */
00297          break;
00298       }
00299    }
00300    close(ifd);
00301    close(ofd);
00302    if (len < 0) {
00303       unlink(outfile);
00304       return -1; /* error */
00305    }
00306    return 0;   /* success */
00307 }

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

Definition at line 337 of file file.c.

References ast_copy_string(), ext, strsep(), and tmp().

Referenced by ast_format_str_reduce(), ast_get_format_for_file_ext(), ast_readfile(), ast_writefile(), and filehelper().

00338 {
00339    char tmp[256];
00340    char *stringp = tmp, *ext;
00341 
00342    ast_copy_string(tmp, exts, sizeof(tmp));
00343    while ((ext = strsep(&stringp, "|"))) {
00344       if (!strcmp(ext, type))
00345          return 1;
00346    }
00347 
00348    return 0;
00349 }

static void file_shutdown ( void   )  [static]

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

helper routine to locate a file with a given format and language preference.

Note:
Try preflang, preflang with stripped '_' suffices, or NULL.

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

Parameters:
filename Name of the file.
fmt Format to look for the file in. OPTIONAL
preflang The perfered language
buf Returns the matching filename
buflen Size of the buf
result_cap OPTIONAL format capabilities result structure returns what formats the file was found in.
Return values:
1,true. file exists and result format is set
0,false. file does not exist.

Definition at line 686 of file file.c.

References ast_strdupa, ast_strlen_zero, DEFAULT_LANGUAGE, end, fileexists_test(), and NULL.

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

00688 {
00689    char *lang;
00690 
00691    if (buf == NULL) {
00692       return 0;
00693    }
00694 
00695    /* We try languages in the following order:
00696     *    preflang (may include dialect and style codes)
00697     *    lang (preflang without dialect - if any)
00698     *    <none>
00699     *    default (unless the same as preflang or lang without dialect)
00700     */
00701 
00702    lang = ast_strdupa(preflang);
00703 
00704    /* Try preferred language, including removing any style or dialect codes */
00705    while (!ast_strlen_zero(lang)) {
00706       char *end;
00707 
00708       if (fileexists_test(filename, fmt, lang, buf, buflen, result_cap)) {
00709          return 1;
00710       }
00711 
00712       if ((end = strrchr(lang, '_')) != NULL) {
00713          *end = '\0';
00714          continue;
00715       }
00716 
00717       break;
00718    }
00719 
00720    /* Try without any language */
00721    if (fileexists_test(filename, fmt, NULL, buf, buflen, result_cap)) {
00722       return 1;
00723    }
00724 
00725    /* Finally try the default language unless it was already tried before */
00726    if ((ast_strlen_zero(preflang) || strcmp(preflang, DEFAULT_LANGUAGE)) && (ast_strlen_zero(lang) || strcmp(lang, DEFAULT_LANGUAGE))) {
00727       if ((fileexists_test(filename, fmt, DEFAULT_LANGUAGE, buf, buflen, result_cap)) > 0) {
00728          return 1;
00729       }
00730    }
00731 
00732    return 0;
00733 }

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

test if a file exists for a given format.

Note:
result_cap is OPTIONAL
Return values:
1,true and result_cap represents format capabilities file exists in.
0,false 

Definition at line 640 of file file.c.

References ACTION_EXISTS, c, filehelper(), is_absolute_path(), and NULL.

Referenced by fileexists_core().

00642 {
00643    if (buf == NULL) {
00644       return 0;
00645    }
00646 
00647    if (ast_language_is_prefix && !is_absolute_path(filename)) { /* new layout */
00648       if (lang) {
00649          snprintf(buf, buflen, "%s/%s", lang, filename);
00650       } else {
00651          snprintf(buf, buflen, "%s", filename);
00652       }
00653    } else { /* old layout */
00654       strcpy(buf, filename);  /* first copy the full string */
00655       if (lang) {
00656          /* insert the language and suffix if needed */
00657          const char *c = strrchr(filename, '/');
00658          int offset = c ? c - filename + 1 : 0; /* points right after the last '/' */
00659          snprintf(buf + offset, buflen - offset, "%s/%s", lang, filename + offset);
00660       }
00661    }
00662 
00663    return filehelper(buf, result_cap, fmt, ACTION_EXISTS);
00664 }

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

Definition at line 506 of file file.c.

References ACTION_COPY, ACTION_DELETE, ACTION_EXISTS, ACTION_OPEN, ACTION_RENAME, ast_channel_stream(), ast_channel_stream_set(), ast_channel_vstream(), ast_channel_vstream_set(), ast_channel_writeformat(), ast_closestream(), ast_format_cap_append, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_type(), ast_free, ast_log, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_strdupa, build_filename(), copy(), errno, ext, ast_format_def::exts, exts_compare(), f, ast_filestream::filename, ast_filestream::fmt, ast_format_def::format, get_filestream(), ast_filestream::lasttimeout, ast_format_def::list, LOG_WARNING, NULL, open_wrapper(), strsep(), and ast_filestream::trans.

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

00507 {
00508    struct ast_format_def *f;
00509    int res = (action == ACTION_EXISTS) ? 0 : -1;
00510 
00511    AST_RWLIST_RDLOCK(&formats);
00512    /* Check for a specific format */
00513    AST_RWLIST_TRAVERSE(&formats, f, list) {
00514       char *stringp, *ext = NULL;
00515 
00516       if (fmt && !exts_compare(f->exts, fmt))
00517          continue;
00518 
00519       /* Look for a file matching the supported extensions.
00520        * The file must exist, and for OPEN, must match
00521        * one of the formats supported by the channel.
00522        */
00523       stringp = ast_strdupa(f->exts);  /* this is in the stack so does not need to be freed */
00524       while ( (ext = strsep(&stringp, "|")) ) {
00525          struct stat st;
00526          char *fn = build_filename(filename, ext);
00527 
00528          if (fn == NULL)
00529             continue;
00530 
00531          if ( stat(fn, &st) ) { /* file not existent */
00532             ast_free(fn);
00533             continue;
00534          }
00535          /* for 'OPEN' we need to be sure that the format matches
00536           * what the channel can process
00537           */
00538          if (action == ACTION_OPEN) {
00539             struct ast_channel *chan = (struct ast_channel *)arg2;
00540             FILE *bfile;
00541             struct ast_filestream *s;
00542 
00543             if ((ast_format_cmp(ast_channel_writeformat(chan), f->format) == AST_FORMAT_CMP_NOT_EQUAL) &&
00544                  !(((ast_format_get_type(f->format) == AST_MEDIA_TYPE_AUDIO) && fmt) ||
00545                  ((ast_format_get_type(f->format) == AST_MEDIA_TYPE_VIDEO) && fmt))) {
00546                ast_free(fn);
00547                continue;   /* not a supported format */
00548             }
00549             if ( (bfile = fopen(fn, "r")) == NULL) {
00550                ast_free(fn);
00551                continue;   /* cannot open file */
00552             }
00553             s = get_filestream(f, bfile);
00554             if (!s) {
00555                fclose(bfile);
00556                ast_free(fn);  /* cannot allocate descriptor */
00557                continue;
00558             }
00559             if (open_wrapper(s)) {
00560                ast_free(fn);
00561                ast_closestream(s);
00562                continue;   /* cannot run open on file */
00563             }
00564             if (st.st_size == 0) {
00565                ast_log(LOG_WARNING, "File %s detected to have zero size.\n", fn);
00566             }
00567             /* ok this is good for OPEN */
00568             res = 1; /* found */
00569             s->lasttimeout = -1;
00570             s->fmt = f;
00571             s->trans = NULL;
00572             s->filename = NULL;
00573             if (ast_format_get_type(s->fmt->format) == AST_MEDIA_TYPE_AUDIO) {
00574                if (ast_channel_stream(chan))
00575                   ast_closestream(ast_channel_stream(chan));
00576                ast_channel_stream_set(chan, s);
00577             } else {
00578                if (ast_channel_vstream(chan))
00579                   ast_closestream(ast_channel_vstream(chan));
00580                ast_channel_vstream_set(chan, s);
00581             }
00582             ast_free(fn);
00583             break;
00584          }
00585          switch (action) {
00586          case ACTION_OPEN:
00587             break;   /* will never get here */
00588 
00589          case ACTION_EXISTS:  /* return the matching format */
00590             /* if arg2 is present, it is a format capabilities structure.
00591              * Add this format to the set of formats this file can be played in */
00592             if (arg2) {
00593                ast_format_cap_append((struct ast_format_cap *) arg2, f->format, 0);
00594             }
00595             res = 1; /* file does exist and format it exists in is returned in arg2 */
00596             break;
00597 
00598          case ACTION_DELETE:
00599             if ( (res = unlink(fn)) )
00600                ast_log(LOG_WARNING, "unlink(%s) failed: %s\n", fn, strerror(errno));
00601             break;
00602 
00603          case ACTION_RENAME:
00604          case ACTION_COPY: {
00605             char *nfn = build_filename((const char *)arg2, ext);
00606             if (!nfn)
00607                ast_log(LOG_WARNING, "Out of memory\n");
00608             else {
00609                res = action == ACTION_COPY ? copy(fn, nfn) : rename(fn, nfn);
00610                if (res)
00611                   ast_log(LOG_WARNING, "%s(%s,%s) failed: %s\n",
00612                      action == ACTION_COPY ? "copy" : "rename",
00613                       fn, nfn, strerror(errno));
00614                ast_free(nfn);
00615             }
00616              }
00617             break;
00618 
00619          default:
00620             ast_log(LOG_WARNING, "Unknown helper %u\n", action);
00621          }
00622          ast_free(fn);
00623       }
00624    }
00625    AST_RWLIST_UNLOCK(&formats);
00626    return res;
00627 }

static void filestream_close ( struct ast_filestream f  )  [static]

Definition at line 355 of file file.c.

References ast_channel_sched(), ast_channel_stream_set(), ast_channel_streamid(), ast_channel_streamid_set(), ast_channel_vstream_set(), ast_channel_vstreamid(), ast_channel_vstreamid_set(), ast_format_get_type(), ast_log, AST_LOG_WARNING, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, AST_SCHED_DEL_ACCESSOR, ast_settimeout(), ast_filestream::fmt, ast_format_def::format, ast_format_def::name, NULL, and ast_filestream::owner.

Referenced by ast_closestream(), and filestream_destructor().

00356 {
00357    enum ast_media_type format_type = ast_format_get_type(f->fmt->format);
00358 
00359    if (!f->owner) {
00360       return;
00361    }
00362 
00363    /* Stop a running stream if there is one */
00364    switch (format_type)
00365    {
00366    case AST_MEDIA_TYPE_AUDIO:
00367       ast_channel_stream_set(f->owner, NULL);
00368       AST_SCHED_DEL_ACCESSOR(ast_channel_sched(f->owner), f->owner, ast_channel_streamid, ast_channel_streamid_set);
00369       ast_settimeout(f->owner, 0, NULL, NULL);
00370       break;
00371    case AST_MEDIA_TYPE_VIDEO:
00372       ast_channel_vstream_set(f->owner, NULL);
00373       AST_SCHED_DEL_ACCESSOR(ast_channel_sched(f->owner), f->owner, ast_channel_vstreamid, ast_channel_vstreamid_set);
00374       break;
00375    default:
00376       ast_log(AST_LOG_WARNING, "Unable to schedule deletion of filestream with unsupported type %s\n", f->fmt->name);
00377       break;
00378    }
00379 }

static void filestream_destructor ( void *  arg  )  [static]

Definition at line 381 of file file.c.

References ao2_cleanup, ast_closestream(), ast_free, ast_module_unref, ast_safe_fork(), ast_translator_free_path(), ast_format_def::close, ast_filestream::f, f, ast_filestream::filename, filestream_close(), ast_filestream::fmt, ast_frame_subclass::format, ast_filestream::fr, ast_filestream::lastwriteformat, ast_format_def::module, ast_filestream::orig_chan_name, ast_filestream::realfilename, SENTINEL, status, ast_frame::subclass, ast_filestream::trans, ast_filestream::vfs, and ast_filestream::write_buffer.

Referenced by get_filestream().

00382 {
00383    struct ast_filestream *f = arg;
00384    int status;
00385    int pid = -1;
00386 
00387    /* Stop a running stream if there is one */
00388    filestream_close(f);
00389 
00390    /* destroy the translator on exit */
00391    if (f->trans)
00392       ast_translator_free_path(f->trans);
00393 
00394    if (f->fmt->close) {
00395       void (*closefn)(struct ast_filestream *) = f->fmt->close;
00396       closefn(f);
00397    }
00398 
00399    if (f->f) {
00400       fclose(f->f);
00401    }
00402 
00403    if (f->realfilename && f->filename) {
00404       pid = ast_safe_fork(0);
00405       if (!pid) {
00406          execl("/bin/mv", "mv", "-f", f->filename, f->realfilename, SENTINEL);
00407          _exit(1);
00408       }
00409       else if (pid > 0) {
00410          /* Block the parent until the move is complete.*/
00411          waitpid(pid, &status, 0);
00412       }
00413    }
00414 
00415    ast_free(f->filename);
00416    ast_free(f->realfilename);
00417    if (f->vfs)
00418       ast_closestream(f->vfs);
00419    ast_free(f->write_buffer);
00420    ast_free((void *)f->orig_chan_name);
00421    ao2_cleanup(f->lastwriteformat);
00422    ao2_cleanup(f->fr.subclass.format);
00423    ast_module_unref(f->fmt->module);
00424 }

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

Definition at line 460 of file file.c.

References ast_log, f, ast_filestream::fmt, LOG_WARNING, ast_format_def::name, ast_format_def::open, ast_format_def::rewrite, WRAP_OPEN, and WRAP_REWRITE.

Referenced by open_wrapper(), and rewrite_wrapper().

00461 {
00462    struct ast_format_def *f = s->fmt;
00463    int ret = -1;
00464    int (*openfn)(struct ast_filestream *s);
00465 
00466    if (mode == WRAP_OPEN && (openfn = f->open) && openfn(s))
00467       ast_log(LOG_WARNING, "Unable to open format %s\n", f->name);
00468    else if (mode == WRAP_REWRITE && f->rewrite && f->rewrite(s, comment))
00469       ast_log(LOG_WARNING, "Unable to rewrite format %s\n", f->name);
00470    else {
00471       /* preliminary checks succeed. */
00472       ret = 0;
00473    }
00474    return ret;
00475 }

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

Definition at line 426 of file file.c.

References ast_filestream::_private, ao2_alloc, ao2_bump, ast_format_get_type(), AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, ast_module_ref, ast_filestream::buf, ast_format_def::buf_size, ast_format_def::desc_size, ast_filestream::f, filestream_destructor(), ast_filestream::fmt, ast_frame_subclass::format, ast_format_def::format, ast_filestream::fr, ast_frame::frametype, ast_frame::mallocd, ast_format_def::module, ast_format_def::name, NULL, ast_frame::src, and ast_frame::subclass.

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

00427 {
00428    struct ast_filestream *s;
00429 
00430    int l = sizeof(*s) + fmt->buf_size + fmt->desc_size;  /* total allocation size */
00431    if ( (s = ao2_alloc(l, filestream_destructor)) == NULL)
00432       return NULL;
00433    ast_module_ref(fmt->module);
00434    s->fmt = fmt;
00435    s->f = bfile;
00436 
00437    if (fmt->desc_size)
00438       s->_private = ((char *)(s + 1)) + fmt->buf_size;
00439    if (fmt->buf_size)
00440       s->buf = (char *)(s + 1);
00441    s->fr.src = fmt->name;
00442 
00443    if (ast_format_get_type(fmt->format) == AST_MEDIA_TYPE_AUDIO) {
00444       s->fr.frametype = AST_FRAME_VOICE;
00445    } else if (ast_format_get_type(fmt->format) == AST_MEDIA_TYPE_VIDEO) {
00446       s->fr.frametype = AST_FRAME_VIDEO;
00447    }
00448    s->fr.mallocd = 0;
00449    s->fr.subclass.format = ao2_bump(fmt->format);
00450 
00451    return s;
00452 }

static char* handle_cli_core_show_file_formats ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1718 of file file.c.

References ast_cli_args::argc, ast_cli(), ast_format_get_name(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_format_def::exts, f, ast_cli_args::fd, ast_format_def::format, FORMAT, FORMAT2, ast_format_def::list, ast_format_def::name, NULL, and ast_cli_entry::usage.

01719 {
01720 #define FORMAT "%-10s %-10s %-20s\n"
01721 #define FORMAT2 "%-10s %-10s %-20s\n"
01722    struct ast_format_def *f;
01723    int count_fmt = 0;
01724 
01725    switch (cmd) {
01726    case CLI_INIT:
01727       e->command = "core show file formats";
01728       e->usage =
01729          "Usage: core show file formats\n"
01730          "       Displays currently registered file formats (if any).\n";
01731       return NULL;
01732    case CLI_GENERATE:
01733       return NULL;
01734    }
01735 
01736    if (a->argc != 4)
01737       return CLI_SHOWUSAGE;
01738 
01739    ast_cli(a->fd, FORMAT, "Format", "Name", "Extensions");
01740    ast_cli(a->fd, FORMAT, "------", "----", "----------");
01741 
01742    AST_RWLIST_RDLOCK(&formats);
01743    AST_RWLIST_TRAVERSE(&formats, f, list) {
01744       ast_cli(a->fd, FORMAT2, ast_format_get_name(f->format), f->name, f->exts);
01745       count_fmt++;
01746    }
01747    AST_RWLIST_UNLOCK(&formats);
01748    ast_cli(a->fd, "%d file formats registered.\n", count_fmt);
01749    return CLI_SUCCESS;
01750 #undef FORMAT
01751 #undef FORMAT2
01752 }

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

Definition at line 629 of file file.c.

Referenced by fileexists_test().

00630 {
00631    return filename[0] == '/';
00632 }

static struct ast_json* json_array_from_list ( const char *  list,
const char *  sep 
) [static, read]

Definition at line 75 of file file.c.

References array(), ast_json_array_append(), ast_json_array_create(), ast_json_ref(), ast_json_string_create(), ast_json_unref(), ast_strdupa, ext, NULL, RAII_VAR, and strsep().

Referenced by publish_format_update().

00076 {
00077    RAII_VAR(struct ast_json *, array, ast_json_array_create(), ast_json_unref);
00078    char *stringp, *ext;
00079 
00080    stringp = ast_strdupa(list);  /* this is in the stack so does not need to be freed */
00081    if (!array || !stringp) {
00082       return NULL;
00083    }
00084 
00085    while ((ext = strsep(&stringp, sep))) {
00086       if (ast_json_array_append(array, ast_json_string_create(ext))) {
00087          return NULL;
00088       }
00089    }
00090 
00091    return ast_json_ref(array);
00092 }

static int open_wrapper ( struct ast_filestream s  )  [static]

Definition at line 482 of file file.c.

References fn_wrapper(), NULL, and WRAP_OPEN.

Referenced by ast_readfile(), and filehelper().

00483 {
00484    return fn_wrapper(s, NULL, WRAP_OPEN);
00485 }

static int publish_format_update ( const struct ast_format_def f,
struct stasis_message_type type 
) [static]

Definition at line 94 of file file.c.

References ao2_cleanup, ast_json_pack(), ast_json_payload_create(), ast_json_unref(), ast_system_topic(), ast_format_def::exts, json_array_from_list(), ast_format_def::name, NULL, RAII_VAR, stasis_message_create(), and stasis_publish().

Referenced by __ast_format_def_register(), and ast_format_def_unregister().

00095 {
00096    RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
00097    RAII_VAR(struct ast_json_payload *, json_payload, NULL, ao2_cleanup);
00098    RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
00099 
00100    if (!type) {
00101       return -1;
00102    }
00103 
00104    json_object = ast_json_pack("{s: s, s: o}",
00105       "format", f->name,
00106       "extensions", json_array_from_list(f->exts, "|"));
00107    if (!json_object) {
00108       return -1;
00109    }
00110 
00111    json_payload = ast_json_payload_create(json_object);
00112    if (!json_payload) {
00113       return -1;
00114    }
00115 
00116    msg = stasis_message_create(type, json_payload);
00117    if (!msg) {
00118       return -1;
00119    }
00120 
00121    stasis_publish(ast_system_topic(), msg);
00122    return 0;
00123 }

static struct ast_frame* read_frame ( struct ast_filestream s,
int *  whennext 
) [static, read]

Definition at line 845 of file file.c.

References ast_frfree, ast_frisolate(), ast_filestream::fmt, NULL, and ast_format_def::read.

Referenced by ast_readaudio_callback(), ast_readframe(), ast_readvideo_callback(), and audiohook_read_frame_helper().

00846 {
00847    struct ast_frame *fr, *new_fr;
00848 
00849    if (!s || !s->fmt) {
00850       return NULL;
00851    }
00852 
00853    if (!(fr = s->fmt->read(s, whennext))) {
00854       return NULL;
00855    }
00856 
00857    if (!(new_fr = ast_frisolate(fr))) {
00858       ast_frfree(fr);
00859       return NULL;
00860    }
00861 
00862    if (new_fr != fr) {
00863       ast_frfree(fr);
00864       fr = new_fr;
00865    }
00866 
00867    return fr;
00868 }

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

Definition at line 477 of file file.c.

References fn_wrapper(), and WRAP_REWRITE.

Referenced by ast_writefile().

00478 {
00479    return fn_wrapper(s, comment, WRAP_REWRITE);
00480 }

static int sanitize_waitstream_return ( int  return_value  )  [static]

Definition at line 1575 of file file.c.

References AST_CONTROL_STREAM_RESTART, AST_CONTROL_STREAM_STOP, and AST_CONTROL_STREAM_SUSPEND.

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

01576 {
01577    switch (return_value) {
01578    case AST_CONTROL_STREAM_STOP:
01579    case AST_CONTROL_STREAM_SUSPEND:
01580    case AST_CONTROL_STREAM_RESTART:
01581       /* Fall through and set return_value to 0 */
01582       return_value = 0;
01583       break;
01584    default:
01585       /* Do nothing */
01586       break;
01587    }
01588 
01589    return return_value;
01590 }

STASIS_MESSAGE_TYPE_DEFN ( ast_format_unregister_type   ) 

STASIS_MESSAGE_TYPE_DEFN ( ast_format_register_type   ) 

static void waitstream_control ( struct ast_channel c,
enum ast_waitstream_fr_cb_values  type,
ast_waitstream_fr_cb  cb,
int  skip_ms 
) [static]

Definition at line 1326 of file file.c.

References ast_channel_name(), ast_channel_stream(), ast_format_get_sample_rate(), ast_stream_fastforward(), ast_stream_rewind(), ast_tellstream(), ast_test_suite_event_notify, AST_WAITSTREAM_CB_FASTFORWARD, AST_WAITSTREAM_CB_REWIND, f, ast_filestream::fmt, and ast_format_def::format.

Referenced by waitstream_core().

01330 {
01331    switch (type)
01332    {
01333    case AST_WAITSTREAM_CB_FASTFORWARD:
01334       {
01335          int eoftest;
01336          ast_stream_fastforward(ast_channel_stream(c), skip_ms);
01337          eoftest = fgetc(ast_channel_stream(c)->f);
01338          if (feof(ast_channel_stream(c)->f)) {
01339             ast_stream_rewind(ast_channel_stream(c), skip_ms);
01340          } else {
01341             ungetc(eoftest, ast_channel_stream(c)->f);
01342          }
01343       }
01344       break;
01345    case AST_WAITSTREAM_CB_REWIND:
01346       ast_stream_rewind(ast_channel_stream(c), skip_ms);
01347       break;
01348    default:
01349       break;
01350    }
01351 
01352    if (cb) {
01353       long ms_len = ast_tellstream(ast_channel_stream(c)) / (ast_format_get_sample_rate(ast_channel_stream(c)->fmt->format) / 1000);
01354       cb(c, ms_len, type);
01355    }
01356 
01357    ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
01358       "Control: %s\r\n"
01359       "SkipMs: %d\r\n",
01360       ast_channel_name(c),
01361       (type == AST_WAITSTREAM_CB_FASTFORWARD) ? "FastForward" : "Rewind",
01362       skip_ms);
01363 }

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

the core of all waitstream() functions

Definition at line 1368 of file file.c.

References ast_channel_caller(), ast_channel_flags(), ast_channel_name(), ast_channel_sched(), ast_channel_softhangup_internal_flag(), ast_channel_stream(), ast_channel_timingfunc(), ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_AOC, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_PVT_CAUSE_CODE, AST_CONTROL_REDIRECTING, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_STREAM_FORWARD, AST_CONTROL_STREAM_RESTART, AST_CONTROL_STREAM_REVERSE, AST_CONTROL_STREAM_STOP, AST_CONTROL_STREAM_SUSPEND, AST_CONTROL_UNHOLD, AST_CONTROL_UPDATE_RTP_PEER, AST_CONTROL_VIDUPDATE, ast_exists_extension(), AST_FLAG_END_DTMF_ONLY, AST_FLAG_MASQ_NOSTREAM, ast_format_get_sample_rate(), 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_tellstream(), ast_test_flag, ast_test_suite_event_notify, ast_waitfor(), ast_waitfor_nandfds(), AST_WAITSTREAM_CB_FASTFORWARD, AST_WAITSTREAM_CB_REWIND, AST_WAITSTREAM_CB_START, ast_frame::data, ast_frame::datalen, errno, exten, ast_filestream::fmt, ast_format_def::format, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, NULL, ast_filestream::orig_chan_name, ast_frame::ptr, S_COR, ast_frame::subclass, and waitstream_control().

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

01377 {
01378    const char *orig_chan_name = NULL;
01379 
01380    int err = 0;
01381 
01382    if (!breakon)
01383       breakon = "";
01384    if (!forward)
01385       forward = "";
01386    if (!reverse)
01387       reverse = "";
01388 
01389    /* Switch the channel to end DTMF frame only. waitstream_core doesn't care about the start of DTMF. */
01390    ast_set_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
01391 
01392    if (ast_test_flag(ast_channel_flags(c), AST_FLAG_MASQ_NOSTREAM))
01393       orig_chan_name = ast_strdupa(ast_channel_name(c));
01394 
01395    if (ast_channel_stream(c) && cb) {
01396       long ms_len = ast_tellstream(ast_channel_stream(c)) / (ast_format_get_sample_rate(ast_channel_stream(c)->fmt->format) / 1000);
01397       cb(c, ms_len, AST_WAITSTREAM_CB_START);
01398    }
01399 
01400    while (ast_channel_stream(c)) {
01401       int res;
01402       int ms;
01403 
01404       if (orig_chan_name && strcasecmp(orig_chan_name, ast_channel_name(c))) {
01405          ast_stopstream(c);
01406          err = 1;
01407          break;
01408       }
01409 
01410       ms = ast_sched_wait(ast_channel_sched(c));
01411 
01412       if (ms < 0 && !ast_channel_timingfunc(c)) {
01413          ast_stopstream(c);
01414          break;
01415       }
01416       if (ms < 0)
01417          ms = 1000;
01418       if (cmdfd < 0) {
01419          res = ast_waitfor(c, ms);
01420          if (res < 0) {
01421             ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
01422             ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
01423             return res;
01424          }
01425       } else {
01426          int outfd;
01427          struct ast_channel *rchan = ast_waitfor_nandfds(&c, 1, &cmdfd, (cmdfd > -1) ? 1 : 0, NULL, &outfd, &ms);
01428          if (!rchan && (outfd < 0) && (ms)) {
01429             /* Continue */
01430             if (errno == EINTR)
01431                continue;
01432             ast_log(LOG_WARNING, "Wait failed (%s)\n", strerror(errno));
01433             ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
01434             return -1;
01435          } else if (outfd > -1) { /* this requires cmdfd set */
01436             /* The FD we were watching has something waiting */
01437             ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
01438             return 1;
01439          }
01440          /* if rchan is set, it is 'c' */
01441          res = rchan ? 1 : 0; /* map into 'res' values */
01442       }
01443       if (res > 0) {
01444          struct ast_frame *fr = ast_read(c);
01445          if (!fr) {
01446             ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
01447             return -1;
01448          }
01449          switch (fr->frametype) {
01450          case AST_FRAME_DTMF_END:
01451             if (context) {
01452                const char exten[2] = { fr->subclass.integer, '\0' };
01453                if (ast_exists_extension(c, context, exten, 1,
01454                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
01455                   res = fr->subclass.integer;
01456                   ast_frfree(fr);
01457                   ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
01458                   return res;
01459                }
01460             } else {
01461                res = fr->subclass.integer;
01462                if (strchr(forward, res)) {
01463                   waitstream_control(c, AST_WAITSTREAM_CB_FASTFORWARD, cb, skip_ms);
01464                } else if (strchr(reverse, res)) {
01465                   waitstream_control(c, AST_WAITSTREAM_CB_REWIND, cb, skip_ms);
01466                } else if (strchr(breakon, res)) {
01467                   ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
01468                      "Control: %s\r\n",
01469                      ast_channel_name(c),
01470                      "Break");
01471 
01472                   ast_frfree(fr);
01473                   ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
01474                   return res;
01475                }
01476             }
01477             break;
01478          case AST_FRAME_CONTROL:
01479             switch (fr->subclass.integer) {
01480             case AST_CONTROL_STREAM_STOP:
01481             case AST_CONTROL_STREAM_SUSPEND:
01482             case AST_CONTROL_STREAM_RESTART:
01483                /* Fall-through and break out */
01484                ast_test_suite_event_notify("PLAYBACK","Channel: %s\r\n"
01485                   "Control: %s\r\n",
01486                   ast_channel_name(c),
01487                   "Break");
01488                res = fr->subclass.integer;
01489                ast_frfree(fr);
01490                ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
01491                return res;
01492             case AST_CONTROL_STREAM_REVERSE:
01493                if (!skip_ms) {
01494                   skip_ms = 3000;
01495                }
01496                waitstream_control(c, AST_WAITSTREAM_CB_REWIND, cb, skip_ms);
01497                break;
01498             case AST_CONTROL_STREAM_FORWARD:
01499                if (!skip_ms) {
01500                   skip_ms = 3000;
01501                }
01502                waitstream_control(c, AST_WAITSTREAM_CB_FASTFORWARD, cb, skip_ms);
01503                break;
01504             case AST_CONTROL_HANGUP:
01505             case AST_CONTROL_BUSY:
01506             case AST_CONTROL_CONGESTION:
01507                ast_frfree(fr);
01508                ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
01509                return -1;
01510             case AST_CONTROL_RINGING:
01511             case AST_CONTROL_ANSWER:
01512             case AST_CONTROL_VIDUPDATE:
01513             case AST_CONTROL_SRCUPDATE:
01514             case AST_CONTROL_SRCCHANGE:
01515             case AST_CONTROL_HOLD:
01516             case AST_CONTROL_UNHOLD:
01517             case AST_CONTROL_CONNECTED_LINE:
01518             case AST_CONTROL_REDIRECTING:
01519             case AST_CONTROL_AOC:
01520             case AST_CONTROL_UPDATE_RTP_PEER:
01521             case AST_CONTROL_PVT_CAUSE_CODE:
01522             case -1:
01523                /* Unimportant */
01524                break;
01525             default:
01526                ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass.integer);
01527             }
01528             break;
01529          case AST_FRAME_VOICE:
01530             /* Write audio if appropriate */
01531             if (audiofd > -1) {
01532                if (write(audiofd, fr->data.ptr, fr->datalen) < 0) {
01533                   ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
01534                }
01535             }
01536          default:
01537             /* Ignore all others */
01538             break;
01539          }
01540          ast_frfree(fr);
01541       }
01542       ast_sched_runq(ast_channel_sched(c));
01543    }
01544 
01545    ast_clear_flag(ast_channel_flags(c), AST_FLAG_END_DTMF_ONLY);
01546 
01547    return (err || ast_channel_softhangup_internal_flag(c)) ? -1 : 0;
01548 }


Variable Documentation

The following variable controls the layout of localized sound files. If 0, use the historical layout with prefix just before the filename (i.e. digits/en/1.gsm , digits/it/1.gsm or default to digits/1.gsm), if 1 put the prefix at the beginning of the filename (i.e. en/digits/1.gsm, it/digits/1.gsm or default to digits/1.gsm). The latter permits a language to be entirely in one directory.

This is settable in asterisk.conf.

Definition at line 68 of file file.c.

Referenced by ast_readconfig(), handle_show_settings(), and main().

struct ast_cli_entry cli_file[] [static]

Initial value:

 {
   AST_CLI_DEFINE(handle_cli_core_show_file_formats, "Displays file formats")
}

Definition at line 1767 of file file.c.


Generated on Thu Apr 16 06:31:00 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6