static int recording_cancel(struct stasis_app_recording *recording) { int res = 0; recording->state = STASIS_APP_RECORDING_STATE_CANCELED; res |= stasis_app_control_queue_control(recording->control, AST_CONTROL_RECORD_CANCEL); res |= ast_filedelete(recording->absolute_name, NULL); return res; }
/*! * \brief Stop monitoring channel * \param chan * \param need_lock * Stop the recording, close any open streams, mix in/out channels if required * \return Always 0 */ int AST_OPTIONAL_API_NAME(ast_monitor_stop)(struct ast_channel *chan, int need_lock) { int delfiles = 0; LOCK_IF_NEEDED(chan, need_lock); if (ast_channel_monitor(chan)) { char filename[ FILENAME_MAX ]; if (ast_channel_monitor(chan)->read_stream) { ast_closestream(ast_channel_monitor(chan)->read_stream); } if (ast_channel_monitor(chan)->write_stream) { ast_closestream(ast_channel_monitor(chan)->write_stream); } if (ast_channel_monitor(chan)->filename_changed && !ast_strlen_zero(ast_channel_monitor(chan)->filename_base)) { if (ast_channel_monitor(chan)->read_stream) { if (ast_fileexists(ast_channel_monitor(chan)->read_filename,NULL,NULL) > 0) { snprintf(filename, FILENAME_MAX, "%s-in", ast_channel_monitor(chan)->filename_base); if (ast_fileexists(filename, NULL, NULL) > 0) { ast_filedelete(filename, NULL); } ast_filerename(ast_channel_monitor(chan)->read_filename, filename, ast_channel_monitor(chan)->format); } else { ast_log(LOG_WARNING, "File %s not found\n", ast_channel_monitor(chan)->read_filename); } } if (ast_channel_monitor(chan)->write_stream) { if (ast_fileexists(ast_channel_monitor(chan)->write_filename,NULL,NULL) > 0) { snprintf(filename, FILENAME_MAX, "%s-out", ast_channel_monitor(chan)->filename_base); if (ast_fileexists(filename, NULL, NULL) > 0) { ast_filedelete(filename, NULL); } ast_filerename(ast_channel_monitor(chan)->write_filename, filename, ast_channel_monitor(chan)->format); } else { ast_log(LOG_WARNING, "File %s not found\n", ast_channel_monitor(chan)->write_filename); } } } if (ast_channel_monitor(chan)->joinfiles && !ast_strlen_zero(ast_channel_monitor(chan)->filename_base)) { char tmp[1024]; char tmp2[1024]; const char *format = !strcasecmp(ast_channel_monitor(chan)->format,"wav49") ? "WAV" : ast_channel_monitor(chan)->format; char *fname_base = ast_channel_monitor(chan)->filename_base; const char *execute, *execute_args; /* at this point, fname_base really is the full path */ /* Set the execute application */ execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); if (ast_strlen_zero(execute)) { #ifdef HAVE_SOXMIX execute = "nice -n 19 soxmix"; #else execute = "nice -n 19 sox -m"; #endif format = get_soxmix_format(format); delfiles = 1; } execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); if (ast_strlen_zero(execute_args)) { execute_args = ""; } snprintf(tmp, sizeof(tmp), "%s \"%s-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &", execute, fname_base, format, fname_base, format, fname_base, format,execute_args); if (delfiles) { snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s-\"* ) &",tmp, fname_base); /* remove legs when done mixing */ ast_copy_string(tmp, tmp2, sizeof(tmp)); } ast_debug(1,"monitor executing %s\n",tmp); if (ast_safe_system(tmp) == -1) ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); } ast_free(ast_channel_monitor(chan)->format); ast_free(ast_channel_monitor(chan)); ast_channel_monitor_set(chan, NULL); ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStop", "Channel: %s\r\n" "Uniqueid: %s\r\n", ast_channel_name(chan), ast_channel_uniqueid(chan) ); pbx_builtin_setvar_helper(chan, "MONITORED", NULL); } pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL); UNLOCK_IF_NEEDED(chan, need_lock); return 0; }
/*! \brief Start monitoring a channel * \param chan ast_channel struct to record * \param format_spec file format to use for recording * \param fname_base filename base to record to * \param need_lock whether to lock the channel mutex * \param stream_action whether to record the input and/or output streams. X_REC_IN | X_REC_OUT is most often used * Creates the file to record, if no format is specified it assumes WAV * It also sets channel variable __MONITORED=yes * \retval 0 on success * \retval -1 on failure */ int AST_OPTIONAL_API_NAME(ast_monitor_start)(struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action) { int res = 0; LOCK_IF_NEEDED(chan, need_lock); if (!(ast_channel_monitor(chan))) { struct ast_channel_monitor *monitor; char *channel_name, *p; /* Create monitoring directory if needed */ ast_mkdir(ast_config_AST_MONITOR_DIR, 0777); if (!(monitor = ast_calloc(1, sizeof(*monitor)))) { UNLOCK_IF_NEEDED(chan, need_lock); return -1; } /* Determine file names */ if (!ast_strlen_zero(fname_base)) { int directory = strchr(fname_base, '/') ? 1 : 0; const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; const char *absolute_suffix = *fname_base == '/' ? "" : "/"; snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in", absolute, absolute_suffix, fname_base); snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out", absolute, absolute_suffix, fname_base); snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s", absolute, absolute_suffix, fname_base); /* try creating the directory just in case it doesn't exist */ if (directory) { char *name = ast_strdupa(monitor->filename_base); ast_mkdir(dirname(name), 0777); } } else { ast_mutex_lock(&monitorlock); snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%lu", ast_config_AST_MONITOR_DIR, seq); snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%lu", ast_config_AST_MONITOR_DIR, seq); seq++; ast_mutex_unlock(&monitorlock); /* Replace all '/' chars from the channel name with '-' chars. */ channel_name = ast_strdupa(ast_channel_name(chan)); for (p = channel_name; (p = strchr(p, '/')); ) { *p = '-'; } snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s", ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name); monitor->filename_changed = 1; } monitor->stop = ast_monitor_stop; /* Determine file format */ if (!ast_strlen_zero(format_spec)) { monitor->format = ast_strdup(format_spec); } else { monitor->format = ast_strdup("wav"); } /* open files */ if (stream_action & X_REC_IN) { if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) ast_filedelete(monitor->read_filename, NULL); if (!(monitor->read_stream = ast_writefile(monitor->read_filename, monitor->format, NULL, O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { ast_log(LOG_WARNING, "Could not create file %s\n", monitor->read_filename); ast_free(monitor); UNLOCK_IF_NEEDED(chan, need_lock); return -1; } } else monitor->read_stream = NULL; if (stream_action & X_REC_OUT) { if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) { ast_filedelete(monitor->write_filename, NULL); } if (!(monitor->write_stream = ast_writefile(monitor->write_filename, monitor->format, NULL, O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { ast_log(LOG_WARNING, "Could not create file %s\n", monitor->write_filename); if (monitor->read_stream) { ast_closestream(monitor->read_stream); } ast_free(monitor); UNLOCK_IF_NEEDED(chan, need_lock); return -1; } } else monitor->write_stream = NULL; ast_channel_monitor_set(chan, monitor); ast_monitor_set_state(chan, AST_MONITOR_RUNNING); /* so we know this call has been monitored in case we need to bill for it or something */ pbx_builtin_setvar_helper(chan, "__MONITORED","true"); ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStart", "Channel: %s\r\n" "Uniqueid: %s\r\n", ast_channel_name(chan), ast_channel_uniqueid(chan)); } else { ast_debug(1,"Cannot start monitoring %s, already monitored\n", ast_channel_name(chan)); res = -1; } UNLOCK_IF_NEEDED(chan, need_lock); return res; }
/*! * \brief Convert a file from one format to another * \param e CLI entry * \param cmd command number * \param a list of cli arguments * \retval CLI_SUCCESS on success. * \retval CLI_SHOWUSAGE or CLI_FAILURE on failure. */ static char *handle_cli_file_convert(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { char *ret = CLI_FAILURE; struct ast_filestream *fs_in = NULL, *fs_out = NULL; struct ast_frame *f; struct timeval start; int cost; char *file_in = NULL, *file_out = NULL; char *name_in, *ext_in, *name_out, *ext_out; switch (cmd) { case CLI_INIT: e->command = "file convert"; e->usage = "Usage: file convert <file_in> <file_out>\n" " Convert from file_in to file_out. If an absolute path\n" " is not given, the default Asterisk sounds directory\n" " will be used.\n\n" " Example:\n" " file convert tt-weasels.gsm tt-weasels.ulaw\n"; return NULL; case CLI_GENERATE: return NULL; } /* ugly, can be removed when CLI entries have ast_module pointers */ ast_module_ref(ast_module_info->self); if (a->argc != 4 || ast_strlen_zero(a->argv[2]) || ast_strlen_zero(a->argv[3])) { ret = CLI_SHOWUSAGE; goto fail_out; } file_in = ast_strdupa(a->argv[2]); file_out = ast_strdupa(a->argv[3]); if (split_ext(file_in, &name_in, &ext_in)) { ast_cli(a->fd, "'%s' is an invalid filename!\n", a->argv[2]); goto fail_out; } if (!(fs_in = ast_readfile(name_in, ext_in, NULL, O_RDONLY, 0, 0))) { ast_cli(a->fd, "Unable to open input file: %s\n", a->argv[2]); goto fail_out; } if (split_ext(file_out, &name_out, &ext_out)) { ast_cli(a->fd, "'%s' is an invalid filename!\n", a->argv[3]); goto fail_out; } if (!(fs_out = ast_writefile(name_out, ext_out, NULL, O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { ast_cli(a->fd, "Unable to open output file: %s\n", a->argv[3]); goto fail_out; } start = ast_tvnow(); while ((f = ast_readframe(fs_in))) { if (ast_writestream(fs_out, f)) { ast_frfree(f); ast_cli(a->fd, "Failed to convert %s.%s to %s.%s!\n", name_in, ext_in, name_out, ext_out); goto fail_out; } ast_frfree(f); } cost = ast_tvdiff_ms(ast_tvnow(), start); ast_cli(a->fd, "Converted %s.%s to %s.%s in %dms\n", name_in, ext_in, name_out, ext_out, cost); ret = CLI_SUCCESS; fail_out: if (fs_out) { ast_closestream(fs_out); if (ret != CLI_SUCCESS) ast_filedelete(name_out, ext_out); } if (fs_in) ast_closestream(fs_in); ast_module_unref(ast_module_info->self); return ret; }
/* Stop monitoring a channel */ int ast_monitor_stop(struct ast_channel *chan, int need_lock) { int delfiles = 0; LOCK_IF_NEEDED(chan, need_lock); if (chan->monitor) { char filename[ FILENAME_MAX ]; if (chan->monitor->read_stream) { ast_closestream(chan->monitor->read_stream); } if (chan->monitor->write_stream) { ast_closestream(chan->monitor->write_stream); } if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) { if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) { snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base); if (ast_fileexists(filename, NULL, NULL) > 0) { ast_filedelete(filename, NULL); } ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format); } else { ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename); } if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) { snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base); if (ast_fileexists(filename, NULL, NULL) > 0) { ast_filedelete(filename, NULL); } ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format); } else { ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename); } } if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) { char tmp[1024]; char tmp2[1024]; char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format; char *name = chan->monitor->filename_base; int directory = strchr(name, '/') ? 1 : 0; char *dir = directory ? "" : ast_config_AST_MONITOR_DIR; const char *execute, *execute_args; /* Set the execute application */ execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); if (ast_strlen_zero(execute)) { execute = "nice -n 19 soxmix"; delfiles = 1; } execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); if (ast_strlen_zero(execute_args)) { execute_args = ""; } snprintf(tmp, sizeof(tmp), "%s \"%s/%s-in.%s\" \"%s/%s-out.%s\" \"%s/%s.%s\" %s &", execute, dir, name, format, dir, name, format, dir, name, format,execute_args); if (delfiles) { snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name); /* remove legs when done mixing */ ast_copy_string(tmp, tmp2, sizeof(tmp)); } ast_log(LOG_DEBUG,"monitor executing %s\n",tmp); if (ast_safe_system(tmp) == -1) ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); } free(chan->monitor->format); free(chan->monitor); chan->monitor = NULL; } UNLOCK_IF_NEEDED(chan, need_lock); return 0; }
/* Start monitoring a channel */ int ast_monitor_start( struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock) { int res = 0; char tmp[256]; LOCK_IF_NEEDED(chan, need_lock); if (!(chan->monitor)) { struct ast_channel_monitor *monitor; char *channel_name, *p; /* Create monitoring directory if needed */ if (mkdir(ast_config_AST_MONITOR_DIR, 0770) < 0) { if (errno != EEXIST) { ast_log(LOG_WARNING, "Unable to create audio monitor directory: %s\n", strerror(errno)); } } if (!(monitor = ast_calloc(1, sizeof(*monitor)))) { UNLOCK_IF_NEEDED(chan, need_lock); return -1; } /* Determine file names */ if (!ast_strlen_zero(fname_base)) { int directory = strchr(fname_base, '/') ? 1 : 0; /* try creating the directory just in case it doesn't exist */ if (directory) { char *name = strdup(fname_base); snprintf(tmp, sizeof(tmp), "mkdir -p \"%s\"",dirname(name)); free(name); ast_safe_system(tmp); } snprintf(monitor->read_filename, FILENAME_MAX, "%s/%s-in", directory ? "" : ast_config_AST_MONITOR_DIR, fname_base); snprintf(monitor->write_filename, FILENAME_MAX, "%s/%s-out", directory ? "" : ast_config_AST_MONITOR_DIR, fname_base); ast_copy_string(monitor->filename_base, fname_base, sizeof(monitor->filename_base)); } else { ast_mutex_lock(&monitorlock); snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld", ast_config_AST_MONITOR_DIR, seq); snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld", ast_config_AST_MONITOR_DIR, seq); seq++; ast_mutex_unlock(&monitorlock); channel_name = ast_strdupa(chan->name); while ((p = strchr(channel_name, '/'))) { *p = '-'; } snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s", ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name); monitor->filename_changed = 1; } monitor->stop = ast_monitor_stop; /* Determine file format */ if (!ast_strlen_zero(format_spec)) { monitor->format = strdup(format_spec); } else { monitor->format = strdup("wav"); } /* open files */ if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) { ast_filedelete(monitor->read_filename, NULL); } if (!(monitor->read_stream = ast_writefile(monitor->read_filename, monitor->format, NULL, O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) { ast_log(LOG_WARNING, "Could not create file %s\n", monitor->read_filename); free(monitor); ast_channel_unlock(chan); return -1; } if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) { ast_filedelete(monitor->write_filename, NULL); } if (!(monitor->write_stream = ast_writefile(monitor->write_filename, monitor->format, NULL, O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) { ast_log(LOG_WARNING, "Could not create file %s\n", monitor->write_filename); ast_closestream(monitor->read_stream); free(monitor); ast_channel_unlock(chan); return -1; } chan->monitor = monitor; ast_monitor_set_state(chan, AST_MONITOR_RUNNING); /* so we know this call has been monitored in case we need to bill for it or something */ pbx_builtin_setvar_helper(chan, "__MONITORED","true"); } else { ast_log(LOG_DEBUG,"Cannot start monitoring %s, already monitored\n", chan->name); res = -1; } UNLOCK_IF_NEEDED(chan, need_lock); return res; }
/* play name of mailbox owner. * returns: -1 for bad or missing extension * '1' for selected entry from directory * '*' for skipped entry from directory */ static int play_mailbox_owner(struct ast_channel *chan, char *context, char *dialcontext, char *ext, char *name, int readext, int fromappvm) { int res = 0; int loop; char fn[256]; /* Check for the VoiceMail2 greeting first */ snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet", ast_config_AST_SPOOL_DIR, context, ext); #ifdef ODBC_STORAGE retrieve_file(fn); #endif if (ast_fileexists(fn, NULL, chan->language) <= 0) { /* no file, check for an old-style Voicemail greeting */ snprintf(fn, sizeof(fn), "%s/vm/%s/greet", ast_config_AST_SPOOL_DIR, ext); } #ifdef ODBC_STORAGE retrieve_file(fn); #endif if (ast_fileexists(fn, NULL, chan->language) > 0) { res = ast_stream_and_wait(chan, fn, chan->language, AST_DIGIT_ANY); ast_stopstream(chan); /* If Option 'e' was specified, also read the extension number with the name */ if (readext) { ast_stream_and_wait(chan, "vm-extension", chan->language, AST_DIGIT_ANY); res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language); } } else { res = ast_say_character_str(chan, S_OR(name, ext), AST_DIGIT_ANY, chan->language); if (!ast_strlen_zero(name) && readext) { ast_stream_and_wait(chan, "vm-extension", chan->language, AST_DIGIT_ANY); res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language); } } #ifdef ODBC_STORAGE ast_filedelete(fn, NULL); #endif for (loop = 3 ; loop > 0; loop--) { if (!res) res = ast_stream_and_wait(chan, "dir-instr", chan->language, AST_DIGIT_ANY); if (!res) res = ast_waitfordigit(chan, 3000); ast_stopstream(chan); if (res < 0) /* User hungup, so jump out now */ break; if (res == '1') { /* Name selected */ if (fromappvm) { /* We still want to set the exten though */ ast_copy_string(chan->exten, ext, sizeof(chan->exten)); } else { if (ast_goto_if_exists(chan, dialcontext, ext, 1)) { ast_log(LOG_WARNING, "Can't find extension '%s' in context '%s'. " "Did you pass the wrong context to Directory?\n", ext, dialcontext); res = -1; } } break; } if (res == '*') /* Skip to next match in list */ break; /* Not '1', or '*', so decrement number of tries */ res = 0; } return(res); }
/*! \brief Convert a file from one format to another */ static int cli_audio_convert(int fd, int argc, char *argv[]) { int ret = RESULT_FAILURE; struct ast_filestream *fs_in = NULL, *fs_out = NULL; struct ast_frame *f; struct timeval start; int cost; char *file_in = NULL, *file_out = NULL; char *name_in, *ext_in, *name_out, *ext_out; ast_atomic_fetchadd_int(&me->usecnt, +1); if (argc != 3 || ast_strlen_zero(argv[1]) || ast_strlen_zero(argv[2])) { ret = RESULT_SHOWUSAGE; goto fail_out; } file_in = ast_strdupa(argv[1]); file_out = ast_strdupa(argv[2]); if (split_ext(file_in, &name_in, &ext_in)) { ast_cli(fd, "'%s' is an invalid filename!\n", argv[1]); goto fail_out; } if (!(fs_in = ast_readfile(name_in, ext_in, NULL, O_RDONLY, 0, 0))) { ast_cli(fd, "Unable to open input file: %s\n", argv[1]); goto fail_out; } if (split_ext(file_out, &name_out, &ext_out)) { ast_cli(fd, "'%s' is an invalid filename!\n", argv[2]); goto fail_out; } if (!(fs_out = ast_writefile(name_out, ext_out, NULL, O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) { ast_cli(fd, "Unable to open output file: %s\n", argv[2]); goto fail_out; } start = ast_tvnow(); while ((f = ast_readframe(fs_in))) { if (ast_writestream(fs_out, f)) { ast_cli(fd, "Failed to convert %s.%s to %s.%s!\n", name_in, ext_in, name_out, ext_out); goto fail_out; } } cost = ast_tvdiff_ms(ast_tvnow(), start); ast_cli(fd, "Converted %s.%s to %s.%s in %dms\n", name_in, ext_in, name_out, ext_out, cost); ret = RESULT_SUCCESS; fail_out: if (fs_out) { ast_closestream(fs_out); if (ret != RESULT_SUCCESS) ast_filedelete(name_out, ext_out); } if (fs_in) ast_closestream(fs_in); ast_atomic_fetchadd_int(&me->usecnt, -1); return ret; }
int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence) { int d = 0; char *fmts; char comment[256]; int x, fmtcnt=1, res=-1,outmsg=0; struct ast_frame *f; struct ast_filestream *others[MAX_OTHER_FORMATS]; struct ast_filestream *realfiles[MAX_OTHER_FORMATS]; char *sfmt[MAX_OTHER_FORMATS]; char *stringp=NULL; time_t start, end; struct ast_dsp *sildet; /* silence detector dsp */ int totalsilence = 0; int dspsilence = 0; int gotsilence = 0; /* did we timeout for silence? */ int rfmt=0; char prependfile[80]; if (silencethreshold < 0) silencethreshold = global_silence_threshold; if (maxsilence < 0) maxsilence = global_maxsilence; /* barf if no pointer passed to store duration in */ if (duration == NULL) { ast_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n"); return -1; } ast_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt); snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name); if (playfile || beep) { if (!beep) d = ast_play_and_wait(chan, playfile); if (d > -1) d = ast_streamfile(chan, "beep",chan->language); if (!d) d = ast_waitstream(chan,""); if (d < 0) return -1; } strncpy(prependfile, recordfile, sizeof(prependfile) -1); strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1); fmts = ast_strdupa(fmt); stringp=fmts; strsep(&stringp, "|"); ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts); sfmt[0] = ast_strdupa(fmts); while((fmt = strsep(&stringp, "|"))) { if (fmtcnt > MAX_OTHER_FORMATS - 1) { ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n"); break; } sfmt[fmtcnt++] = ast_strdupa(fmt); } time(&start); end=start; /* pre-initialize end to be same as start in case we never get into loop */ for (x=0; x<fmtcnt; x++) { others[x] = ast_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700); ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]); if (!others[x]) { break; } } sildet = ast_dsp_new(); /* Create the silence detector */ if (!sildet) { ast_log(LOG_WARNING, "Unable to create silence detector :(\n"); return -1; } ast_dsp_set_threshold(sildet, silencethreshold); if (maxsilence > 0) { rfmt = chan->readformat; res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); return -1; } } if (x == fmtcnt) { /* Loop forever, writing the packets we read to the writer(s), until we read a # or get a hangup */ f = NULL; for(;;) { res = ast_waitfor(chan, 2000); if (!res) { ast_log(LOG_DEBUG, "One waitfor failed, trying another\n"); /* Try one more time in case of masq */ res = ast_waitfor(chan, 2000); if (!res) { ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name); res = -1; } } if (res < 0) { f = NULL; break; } f = ast_read(chan); if (!f) break; if (f->frametype == AST_FRAME_VOICE) { /* write each format */ for (x=0; x<fmtcnt; x++) { if (!others[x]) break; res = ast_writestream(others[x], f); } /* Silence Detection */ if (maxsilence > 0) { dspsilence = 0; ast_dsp_silence(sildet, f, &dspsilence); if (dspsilence) totalsilence = dspsilence; else totalsilence = 0; if (totalsilence > maxsilence) { /* Ended happily with silence */ if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000); ast_frfree(f); gotsilence = 1; outmsg=2; break; } } /* Exit on any error */ if (res) { ast_log(LOG_WARNING, "Error writing frame\n"); ast_frfree(f); break; } } else if (f->frametype == AST_FRAME_VIDEO) { /* Write only once */ ast_writestream(others[0], f); } else if (f->frametype == AST_FRAME_DTMF) { /* stop recording with any digit */ if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass); res = 't'; outmsg = 2; ast_frfree(f); break; } if (maxtime) { time(&end); if (maxtime < (end - start)) { if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n"); res = 't'; outmsg=2; ast_frfree(f); break; } } ast_frfree(f); } if (end == start) time(&end); if (!f) { if (option_verbose > 2) ast_verbose( VERBOSE_PREFIX_3 "User hung up\n"); res = -1; outmsg=1; #if 0 /* delete all the prepend files */ for (x=0; x<fmtcnt; x++) { if (!others[x]) break; ast_closestream(others[x]); ast_filedelete(prependfile, sfmt[x]); } #endif } } else { ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]); } *duration = end - start; #if 0 if (outmsg > 1) { #else if (outmsg) { #endif struct ast_frame *fr; for (x=0; x<fmtcnt; x++) { snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]); realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0); if (!others[x] || !realfiles[x]) break; if (totalsilence) ast_stream_rewind(others[x], totalsilence-200); else ast_stream_rewind(others[x], 200); ast_truncstream(others[x]); /* add the original file too */ while ((fr = ast_readframe(realfiles[x]))) { ast_writestream(others[x],fr); } ast_closestream(others[x]); ast_closestream(realfiles[x]); ast_filerename(prependfile, recordfile, sfmt[x]); #if 0 ast_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile); #endif ast_filedelete(prependfile, sfmt[x]); } } if (rfmt) { if (ast_set_read_format(chan, rfmt)) { ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name); } } if (outmsg) { if (outmsg > 1) { /* Let them know it worked */ ast_streamfile(chan, "auth-thankyou", chan->language); ast_waitstream(chan, ""); } } return res; } int ast_lock_path(const char *path) { char *s; char *fs; int res; int fd; time_t start; s = alloca(strlen(path) + 10); fs = alloca(strlen(path) + 20); if (!fs || !s) { ast_log(LOG_WARNING, "Out of memory!\n"); return -1; } snprintf(fs, strlen(path) + 19, "%s/%s-%08x", path, ".lock", rand()); fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd < 0) { fprintf(stderr, "Unable to create lock file: %s\n", strerror(errno)); return -1; } close(fd); snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock"); time(&start); while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5)) usleep(1); if (res < 0) { ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno)); } unlink(fs); ast_log(LOG_DEBUG, "Locked path '%s'\n", path); return res; }
/* play name of mailbox owner. * returns: -1 for bad or missing extension * '1' for selected entry from directory * '*' for skipped entry from directory */ static int play_mailbox_owner(struct ast_channel *chan, char *context, char *dialcontext, char *ext, char *name, int fromappvm) { int res = 0; int loop = 3; char fn[256]; char fn2[256]; /* Check for the VoiceMail2 greeting first */ snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet", (char *)ast_config_AST_SPOOL_DIR, context, ext); #ifdef USE_ODBC_STORAGE retrieve_file(fn); #endif /* Otherwise, check for an old-style Voicemail greeting */ snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet", (char *)ast_config_AST_SPOOL_DIR, ext); #ifdef USE_ODBC_STORAGE retrieve_file(fn2); #endif if (ast_fileexists(fn, NULL, chan->language) > 0) { res = ast_streamfile(chan, fn, chan->language); if (!res) { res = ast_waitstream(chan, AST_DIGIT_ANY); } ast_stopstream(chan); } else if (ast_fileexists(fn2, NULL, chan->language) > 0) { res = ast_streamfile(chan, fn2, chan->language); if (!res) { res = ast_waitstream(chan, AST_DIGIT_ANY); } ast_stopstream(chan); } else { res = ast_say_character_str(chan, !ast_strlen_zero(name) ? name : ext, AST_DIGIT_ANY, chan->language); } #ifdef USE_ODBC_STORAGE ast_filedelete(fn, NULL); ast_filedelete(fn2, NULL); #endif while (loop) { if (!res) { res = ast_streamfile(chan, "dir-instr", chan->language); } if (!res) { res = ast_waitstream(chan, AST_DIGIT_ANY); } if (!res) { res = ast_waitfordigit(chan, 3000); } ast_stopstream(chan); if (res > -1) { switch (res) { case '1': /* Name selected */ loop = 0; if (fromappvm) { /* We still want to set the exten */ ast_copy_string(chan->exten, ext, sizeof(chan->exten)); } else { if (ast_goto_if_exists(chan, dialcontext, ext, 1)) { ast_log(LOG_WARNING, "Can't find extension '%s' in context '%s'. " "Did you pass the wrong context to Directory?\n", ext, dialcontext); res = -1; } } break; case '*': /* Skip to next match in list */ loop = 0; break; default: /* Not '1', or '*', so decrement number of tries */ res = 0; loop--; break; } /* end switch */ } /* end if */ else { /* User hungup, so jump out now */ loop = 0; } } /* end while */ return(res); }