Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

app.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/file.h>
#include <asterisk/app.h>
#include <asterisk/dsp.h>
#include <asterisk/logger.h>
#include <asterisk/options.h>
#include <asterisk/utils.h>
#include "asterisk.h"
#include "astconf.h"

Include dependency graph for app.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  linear_state

Functions

int ast_app_getdata (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
 Plays a stream and gets DTMF data from a channel.

int ast_app_getdata_full (struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
int ast_app_getvoice (struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec)
 Record voice (after playing prompt if specified), waiting for silence (in ms) up to a given timeout (in s) or '#'.

int ast_app_has_voicemail (const char *mailbox)
 Determine if a given mailbox has any voicemail.

int ast_app_messagecount (const char *mailbox, int *newmsgs, int *oldmsgs)
 Determine number of new/old messages in a mailbox.

int ast_dtmf_stream (struct ast_channel *chan, struct ast_channel *peer, char *digits, int between)
 Send DTMF to chan (optionally entertain peer).

int ast_linear_stream (struct ast_channel *chan, const char *filename, int fd, int allowoverride)
 Stream a filename (or file descriptor) as a generator.

int ast_control_streamfile (struct ast_channel *chan, char *file, char *fwd, char *rev, char *stop, char *pause, int skipms)
 Stream a file with fast forward, pause, reverse.


Function Documentation

int ast_app_getdata struct ast_channel c,
char *  prompt,
char *  s,
int  maxlen,
int  timeout
 

Plays a stream and gets DTMF data from a channel.

Parameters:
c Which channel one is interacting with
prompt File to pass to ast_streamfile (the one that you wish to play)
s The location where the DTMF data will be stored
maxlen Max Length of the data
timeout Timeout length waiting for data(in milliseconds). Set to 0 for standard timeout(six seconds), or -1 for no time out.
This function was designed for application programmers for situations where they need to play a message and then get some DTMF data in response to the message. If a digit is pressed during playback, it will immediately break out of the message and continue execution of your code.

Definition at line 36 of file app.c.

References ast_readstring(), ast_streamfile(), ast_pbx::dtimeout, ast_channel::language, ast_channel::pbx, ast_pbx::rtimeout, and s.

00037 { 00038 int res,to,fto; 00039 /* XXX Merge with full version? XXX */ 00040 if (prompt) { 00041 res = ast_streamfile(c, prompt, c->language); 00042 if (res < 0) 00043 return res; 00044 } 00045 fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000; 00046 to = c->pbx ? c->pbx->dtimeout * 1000 : 2000; 00047 00048 if (timeout > 0) fto = to = timeout; 00049 if (timeout < 0) fto = to = 1000000000; 00050 res = ast_readstring(c, s, maxlen, to, fto, "#"); 00051 return res; 00052 }

int ast_app_getdata_full struct ast_channel c,
char *  prompt,
char *  s,
int  maxlen,
int  timeout,
int  audiofd,
int  ctrlfd
 

Definition at line 55 of file app.c.

References ast_readstring_full(), ast_streamfile(), ast_channel::language, and s.

00056 { 00057 int res,to,fto; 00058 if (prompt) { 00059 res = ast_streamfile(c, prompt, c->language); 00060 if (res < 0) 00061 return res; 00062 } 00063 fto = 6000; 00064 to = 2000; 00065 if (timeout > 0) fto = to = timeout; 00066 if (timeout < 0) fto = to = 1000000000; 00067 res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd); 00068 return res; 00069 }

int ast_app_getvoice struct ast_channel c,
char *  dest,
char *  dstfmt,
char *  prompt,
int  silence,
int  maxsec
 

Record voice (after playing prompt if specified), waiting for silence (in ms) up to a given timeout (in s) or '#'.

Definition at line 71 of file app.c.

References ast_closestream(), ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_read(), ast_set_read_format(), ast_streamfile(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_channel::language, LOG_NOTICE, LOG_WARNING, ast_channel::name, and ast_channel::readformat.

00072 { 00073 int res; 00074 struct ast_filestream *writer; 00075 int rfmt; 00076 int totalms=0, total; 00077 00078 struct ast_frame *f; 00079 struct ast_dsp *sildet; 00080 /* Play prompt if requested */ 00081 if (prompt) { 00082 res = ast_streamfile(c, prompt, c->language); 00083 if (res < 0) 00084 return res; 00085 res = ast_waitstream(c,""); 00086 if (res < 0) 00087 return res; 00088 } 00089 rfmt = c->readformat; 00090 res = ast_set_read_format(c, AST_FORMAT_SLINEAR); 00091 if (res < 0) { 00092 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); 00093 return -1; 00094 } 00095 sildet = ast_dsp_new(); 00096 if (!sildet) { 00097 ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); 00098 return -1; 00099 } 00100 writer = ast_writefile(dest, dstfmt, "Voice file", 0, 0, 0666); 00101 if (!writer) { 00102 ast_log(LOG_WARNING, "Unable to open file '%s' in format '%s' for writing\n", dest, dstfmt); 00103 ast_dsp_free(sildet); 00104 return -1; 00105 } 00106 for(;;) { 00107 if ((res = ast_waitfor(c, 2000)) < 0) { 00108 ast_log(LOG_NOTICE, "Waitfor failed while recording file '%s' format '%s'\n", dest, dstfmt); 00109 break; 00110 } 00111 if (res) { 00112 f = ast_read(c); 00113 if (!f) { 00114 ast_log(LOG_NOTICE, "Hungup while recording file '%s' format '%s'\n", dest, dstfmt); 00115 break; 00116 } 00117 if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) { 00118 /* Ended happily with DTMF */ 00119 ast_frfree(f); 00120 break; 00121 } else if (f->frametype == AST_FRAME_VOICE) { 00122 ast_dsp_silence(sildet, f, &total); 00123 if (total > silence) { 00124 /* Ended happily with silence */ 00125 ast_frfree(f); 00126 break; 00127 } 00128 totalms += f->samples / 8; 00129 if (totalms > maxsec * 1000) { 00130 /* Ended happily with too much stuff */ 00131 ast_log(LOG_NOTICE, "Constraining voice on '%s' to %d seconds\n", c->name, maxsec); 00132 ast_frfree(f); 00133 break; 00134 } 00135 } 00136 ast_frfree(f); 00137 } 00138 } 00139 res = ast_set_read_format(c, rfmt); 00140 if (res) 00141 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", c->name); 00142 ast_dsp_free(sildet); 00143 ast_closestream(writer); 00144 return 0; 00145 }

int ast_app_has_voicemail const char *  mailbox  ) 
 

Determine if a given mailbox has any voicemail.

Definition at line 147 of file app.c.

References ast_config_AST_SPOOL_DIR.

00148 { 00149 DIR *dir; 00150 struct dirent *de; 00151 char fn[256]; 00152 char tmp[256]=""; 00153 char *mb, *cur; 00154 char *context; 00155 int ret; 00156 /* If no mailbox, return immediately */ 00157 if (ast_strlen_zero(mailbox)) 00158 return 0; 00159 if (strchr(mailbox, ',')) { 00160 strncpy(tmp, mailbox, sizeof(tmp)); 00161 mb = tmp; 00162 ret = 0; 00163 while((cur = strsep(&mb, ","))) { 00164 if (!ast_strlen_zero(cur)) { 00165 if (ast_app_has_voicemail(cur)) 00166 return 1; 00167 } 00168 } 00169 return 0; 00170 } 00171 strncpy(tmp, mailbox, sizeof(tmp) - 1); 00172 context = strchr(tmp, '@'); 00173 if (context) { 00174 *context = '\0'; 00175 context++; 00176 } else 00177 context = "default"; 00178 snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp); 00179 dir = opendir(fn); 00180 if (!dir) 00181 return 0; 00182 while ((de = readdir(dir))) { 00183 if (!strncasecmp(de->d_name, "msg", 3)) 00184 break; 00185 } 00186 closedir(dir); 00187 if (de) 00188 return 1; 00189 return 0; 00190 }

int ast_app_messagecount const char *  mailbox,
int *  newmsgs,
int *  oldmsgs
 

Determine number of new/old messages in a mailbox.

Definition at line 192 of file app.c.

References ast_config_AST_SPOOL_DIR.

00193 { 00194 DIR *dir; 00195 struct dirent *de; 00196 char fn[256]; 00197 char tmp[256]=""; 00198 char *mb, *cur; 00199 char *context; 00200 int ret; 00201 if (newmsgs) 00202 *newmsgs = 0; 00203 if (oldmsgs) 00204 *oldmsgs = 0; 00205 /* If no mailbox, return immediately */ 00206 if (ast_strlen_zero(mailbox)) 00207 return 0; 00208 if (strchr(mailbox, ',')) { 00209 int tmpnew, tmpold; 00210 strncpy(tmp, mailbox, sizeof(tmp)); 00211 mb = tmp; 00212 ret = 0; 00213 while((cur = strsep(&mb, ", "))) { 00214 if (!ast_strlen_zero(cur)) { 00215 if (ast_app_messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL)) 00216 return -1; 00217 else { 00218 if (newmsgs) 00219 *newmsgs += tmpnew; 00220 if (oldmsgs) 00221 *oldmsgs += tmpold; 00222 } 00223 } 00224 } 00225 return 0; 00226 } 00227 strncpy(tmp, mailbox, sizeof(tmp) - 1); 00228 context = strchr(tmp, '@'); 00229 if (context) { 00230 *context = '\0'; 00231 context++; 00232 } else 00233 context = "default"; 00234 if (newmsgs) { 00235 snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp); 00236 dir = opendir(fn); 00237 if (dir) { 00238 while ((de = readdir(dir))) { 00239 if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) && 00240 !strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt")) 00241 (*newmsgs)++; 00242 00243 } 00244 closedir(dir); 00245 } 00246 } 00247 if (oldmsgs) { 00248 snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/Old", (char *)ast_config_AST_SPOOL_DIR, context, tmp); 00249 dir = opendir(fn); 00250 if (dir) { 00251 while ((de = readdir(dir))) { 00252 if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) && 00253 !strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt")) 00254 (*oldmsgs)++; 00255 00256 } 00257 closedir(dir); 00258 } 00259 } 00260 return 0; 00261 }

int ast_control_streamfile struct ast_channel chan,
char *  file,
char *  fwd,
char *  rev,
char *  stop,
char *  pause,
int  skipms
 

Stream a file with fast forward, pause, reverse.

Definition at line 410 of file app.c.

References ast_channel::_state, ast_answer(), AST_STATE_UP, ast_stopstream(), ast_stream_fastforward(), ast_streamfile(), ast_waitfordigit(), ast_waitstream_fr(), ast_channel::language, and ast_channel::stream.

00411 { 00412 struct timeval started, ended; 00413 long elapsed = 0,last_elapsed =0; 00414 char *breaks; 00415 int blen=2; 00416 int res=0; 00417 00418 if (stop) 00419 blen += strlen(stop); 00420 if (pause) 00421 blen += strlen(pause); 00422 00423 breaks = alloca(blen + 1); 00424 breaks[0] = '\0'; 00425 strcat(breaks, stop); 00426 strcat(breaks, pause); 00427 00428 if (chan->_state != AST_STATE_UP) 00429 res = ast_answer(chan); 00430 00431 if (chan) 00432 ast_stopstream(chan); 00433 00434 for (;;) { 00435 gettimeofday(&started,NULL); 00436 00437 if (chan) 00438 ast_stopstream(chan); 00439 res = ast_streamfile(chan, file, chan->language); 00440 if (!res) { 00441 res = 1; 00442 if (elapsed) { 00443 ast_stream_fastforward(chan->stream, elapsed); 00444 last_elapsed = elapsed - 200; 00445 } 00446 if (res) 00447 res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms); 00448 else 00449 break; 00450 } 00451 00452 if (res < 1) 00453 break; 00454 00455 if (pause != NULL && strchr(pause, res)) { 00456 gettimeofday(&ended, NULL); 00457 elapsed = (((ended.tv_sec * 1000) + ended.tv_usec / 1000) - ((started.tv_sec * 1000) + started.tv_usec / 1000) + last_elapsed); 00458 for(;;) { 00459 if (chan) 00460 ast_stopstream(chan); 00461 res = ast_waitfordigit(chan, 1000); 00462 if(res == 0) 00463 continue; 00464 else if(res == -1 || strchr(pause, res) || (stop && strchr(stop, res))) 00465 break; 00466 } 00467 if (res == *pause) { 00468 res = 0; 00469 continue; 00470 } 00471 } 00472 if (res == -1) 00473 break; 00474 00475 if (stop && strchr(stop, res)) { 00476 res = 0; 00477 break; 00478 } 00479 } 00480 if (chan) 00481 ast_stopstream(chan); 00482 00483 return res; 00484 }

int ast_dtmf_stream struct ast_channel chan,
struct ast_channel peer,
char *  digits,
int  between
 

Send DTMF to chan (optionally entertain peer).

Definition at line 263 of file app.c.

References ast_autoservice_start(), ast_autoservice_stop(), AST_FRAME_DTMF, ast_log(), ast_safe_sleep(), ast_waitfor(), ast_write(), and LOG_WARNING.

00264 { 00265 char *ptr=NULL; 00266 int res=0; 00267 struct ast_frame f; 00268 if (!between) 00269 between = 100; 00270 00271 if (peer) 00272 res = ast_autoservice_start(peer); 00273 00274 if (!res) { 00275 res = ast_waitfor(chan,100); 00276 if (res > -1) { 00277 for (ptr=digits;*ptr;*ptr++) { 00278 if (*ptr == 'w') { 00279 res = ast_safe_sleep(chan, 500); 00280 if (res) 00281 break; 00282 continue; 00283 } 00284 memset(&f, 0, sizeof(f)); 00285 f.frametype = AST_FRAME_DTMF; 00286 f.subclass = *ptr; 00287 f.src = "ast_dtmf_stream"; 00288 if (strchr("0123456789*#abcdABCD",*ptr)==NULL) { 00289 ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr); 00290 } else { 00291 res = ast_write(chan, &f); 00292 if (res) 00293 break; 00294 /* pause between digits */ 00295 res = ast_safe_sleep(chan,between); 00296 if (res) 00297 break; 00298 } 00299 } 00300 } 00301 if (peer) 00302 res = ast_autoservice_stop(peer); 00303 } 00304 return res; 00305 }

int ast_linear_stream struct ast_channel chan,
const char *  filename,
int  fd,
int  allowoverride
 

Stream a filename (or file descriptor) as a generator.

Definition at line 379 of file app.c.

References ast_activate_generator(), ast_config_AST_VAR_DIR, ast_log(), LOG_WARNING, and malloc.

00380 { 00381 struct linear_state *lin; 00382 char tmpf[256] = ""; 00383 int res = -1; 00384 int autoclose = 0; 00385 if (fd < 0) { 00386 if (!filename || ast_strlen_zero(filename)) 00387 return -1; 00388 autoclose = 1; 00389 if (filename[0] == '/') 00390 strncpy(tmpf, filename, sizeof(tmpf) - 1); 00391 else 00392 snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", (char *)ast_config_AST_VAR_DIR, "sounds", filename); 00393 fd = open(tmpf, O_RDONLY); 00394 if (fd < 0){ 00395 ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno)); 00396 return -1; 00397 } 00398 } 00399 lin = malloc(sizeof(struct linear_state)); 00400 if (lin) { 00401 memset(lin, 0, sizeof(lin)); 00402 lin->fd = fd; 00403 lin->allowoverride = allowoverride; 00404 lin->autoclose = autoclose; 00405 res = ast_activate_generator(chan, &linearstream, lin); 00406 } 00407 return res; 00408 }


Generated on Sat Jun 12 16:41:02 2004 for Asterisk by doxygen 1.3.7