提交 f64d7e43 authored 作者: Anthony Minessale's avatar Anthony Minessale

improve voicemail

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6399 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 5dfde041
......@@ -2,7 +2,7 @@
<settings>
</settings>
<profiles>
<profile name="default">
<profile name="demo">
<param name="file-extension" value="wav"/>
<param name="terminator-key" value="#"/>
<param name="max-login-attempts" value="3"/>
......@@ -31,18 +31,20 @@
<param name="rew-key" value="4"/>
<param name="record-silence-threshold" value="200"/>
<param name="record-silence-hits" value="2"/>
<!-- if you need to change the sample rate of the recorded files e.g. gmail voicemail player -->
<!--<param name="record-sample-rate" value="11025"/>-->
<!-- the next two both must be set for this to be enabled
the extension is in the format of <dest> [<dialplan>] [<context>]
-->
<param name="operator-extension" value="operator XML default"/>
<param name="operator-key" value="9"/>
<email>
<body><![CDATA[At ${voicemail_time} you were left a message from ${voicemail_caller_id_name} ${voicemail_caller_id_number}
<body><![CDATA[At ${voicemail_time} you were left a ${voicemail_message_len} second message from ${voicemail_caller_id_name} ${voicemail_caller_id_number}
to your account ${voicemail_account}@${voicemail_domain}
]]></body>
<headers><![CDATA[From: FreeSWITCH mod_voicemail <${voicemail_account}@${voicemail_domain}>
To: <${voicemail_email}>
Subject: Voicemail from ${voicemail_caller_id_name} ${voicemail_caller_id_number}
Subject: ${voicemail_message_len} sec Voicemail from ${voicemail_caller_id_name} ${voicemail_caller_id_number}
X-Priority: ${voicemail_priority}
X-Mailer: FreeSWITCH
]]></headers>
......
差异被折叠。
......@@ -158,6 +158,7 @@ struct switch_media_bug {
struct switch_runtime {
switch_time_t initiated;
switch_hash_t *global_vars;
switch_hash_t *mime_types;
switch_memory_pool_t *memory_pool;
const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS];
int state_handler_index;
......
......@@ -1494,6 +1494,9 @@ SWITCH_DECLARE(void) switch_core_set_globals(void);
SWITCH_DECLARE(uint8_t) switch_core_session_compare(switch_core_session_t *a, switch_core_session_t *b);
SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext);
SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext);
SWITCH_DECLARE(switch_loadable_module_interface_t *) switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, const char *name);
SWITCH_DECLARE(void *) switch_loadable_module_create_interface(switch_loadable_module_interface_t *mod, switch_module_interface_name_t iname);
SWITCH_DECLARE(switch_time_t) switch_timestamp_now(void);
......
......@@ -69,6 +69,8 @@ static inline switch_bool_t switch_is_digit_string(const char *s) {
return SWITCH_TRUE;
}
switch_size_t switch_fd_read_line(int fd, char *buf, switch_size_t len);
/*!
\brief Evaluate the truthfullness of a string expression
\param expr a string expression
......
......@@ -237,6 +237,7 @@ static switch_status_t local_stream_file_read(switch_file_handle_t *handle, void
*len = need / 2;
}
switch_mutex_unlock(context->audio_mutex);
handle->sample_count += *len;
return SWITCH_STATUS_SUCCESS;
}
......
......@@ -65,6 +65,7 @@ struct shout_context {
uint8_t thread_running;
uint8_t shout_init;
uint32_t prebuf;
int lame_ready;
};
typedef struct shout_context shout_context_t;
......@@ -91,6 +92,7 @@ static inline void free_context(shout_context_t * context)
}
lame_mp3_tags_fid(context->gfp, context->fp);
fclose(context->fp);
context->fp = NULL;
}
......@@ -576,19 +578,23 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
goto error;
}
if (!handle->handler) {
id3tag_init(context->gfp);
id3tag_v2_only(context->gfp);
id3tag_pad_v2(context->gfp);
}
lame_set_num_channels(context->gfp, handle->channels);
lame_set_in_samplerate(context->gfp, handle->samplerate);
lame_set_brate(context->gfp, 64);
lame_set_brate(context->gfp, 24);
lame_set_mode(context->gfp, 3);
lame_set_quality(context->gfp, 2); /* 2=high 5 = medium 7=low */
lame_set_errorf(context->gfp, log_error);
lame_set_debugf(context->gfp, log_debug);
lame_set_msgf(context->gfp, log_msg);
lame_init_params(context->gfp);
lame_print_config(context->gfp);
if (handle->handler) {
if (switch_buffer_create_dynamic(&context->audio_buffer, MY_BLOCK_SIZE, MY_BUF_LEN, 0) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
......@@ -674,7 +680,7 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
goto error;
}
if (shout_set_audio_info(context->shout, "bitrate", "64000") != SHOUTERR_SUCCESS) {
if (shout_set_audio_info(context->shout, "bitrate", "24000") != SHOUTERR_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting user: %s\n", shout_get_error(context->shout));
goto error;
}
......@@ -780,6 +786,8 @@ static switch_status_t shout_file_read(switch_file_handle_t *handle, void *data,
*len = bytes / sizeof(int16_t);
}
handle->sample_count += *len;
return SWITCH_STATUS_SUCCESS;
}
......@@ -817,6 +825,13 @@ static switch_status_t shout_file_write(switch_file_handle_t *handle, void *data
return SWITCH_STATUS_FALSE;
}
} else {
if (!context->lame_ready) {
lame_init_params(context->gfp);
lame_print_config(context->gfp);
context->lame_ready = 1;
}
if ((rlen = lame_encode_buffer(context->gfp, audio, NULL, nsamples, mp3buf, sizeof(mp3buf))) < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen);
return SWITCH_STATUS_FALSE;
......@@ -828,26 +843,63 @@ static switch_status_t shout_file_write(switch_file_handle_t *handle, void *data
}
}
handle->sample_count += *len;
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t shout_file_set_string(switch_file_handle_t *handle, switch_audio_col_t col, const char *string)
{
shout_context_t *context = handle->private_info;
switch_status_t status = SWITCH_STATUS_FALSE;
if (!context->shout) {
switch (col) {
case SWITCH_AUDIO_COL_STR_TITLE:
id3tag_set_title(context->gfp, string);
break;
case SWITCH_AUDIO_COL_STR_COMMENT:
id3tag_set_comment(context->gfp, string);
break;
case SWITCH_AUDIO_COL_STR_ARTIST:
id3tag_set_artist(context->gfp, string);
break;
case SWITCH_AUDIO_COL_STR_DATE:
id3tag_set_year(context->gfp, string);
break;
case SWITCH_AUDIO_COL_STR_SOFTWARE:
break;
id3tag_set_album(context->gfp, string);
case SWITCH_AUDIO_COL_STR_COPYRIGHT:
id3tag_set_genre(context->gfp, string);
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Value Ignored\n");
break;
}
return status;
}
switch (col) {
case SWITCH_AUDIO_COL_STR_TITLE:
if (shout_set_name(context->shout, string) != SHOUTERR_SUCCESS) {
if (shout_set_name(context->shout, string) == SHOUTERR_SUCCESS) {
status = SWITCH_STATUS_SUCCESS;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout));
}
break;
case SWITCH_AUDIO_COL_STR_COMMENT:
if (shout_set_url(context->shout, string) != SHOUTERR_SUCCESS) {
if (shout_set_url(context->shout, string) == SHOUTERR_SUCCESS) {
status = SWITCH_STATUS_SUCCESS;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout));
}
break;
case SWITCH_AUDIO_COL_STR_ARTIST:
if (shout_set_description(context->shout, string) != SHOUTERR_SUCCESS) {
if (shout_set_description(context->shout, string) == SHOUTERR_SUCCESS) {
status = SWITCH_STATUS_SUCCESS;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout));
}
break;
......@@ -855,7 +907,8 @@ static switch_status_t shout_file_set_string(switch_file_handle_t *handle, switc
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Value Ignored\n");
break;
}
return SWITCH_STATUS_FALSE;
return status;
}
static switch_status_t shout_file_get_string(switch_file_handle_t *handle, switch_audio_col_t col, const char **string)
......
......@@ -205,6 +205,8 @@ static switch_status_t sndfile_file_read(switch_file_handle_t *handle, void *dat
*len = (size_t) sf_readf_int(context->handle, (int *) data, inlen);
}
handle->sample_count += *len;
return SWITCH_STATUS_SUCCESS;
}
......@@ -227,6 +229,8 @@ static switch_status_t sndfile_file_write(switch_file_handle_t *handle, void *da
*len = (size_t) sf_writef_int(context->handle, (int *) data, inlen);
}
handle->sample_count += *len;
return SWITCH_STATUS_SUCCESS;
}
......
......@@ -549,6 +549,87 @@ SWITCH_DECLARE(void) switch_core_runtime_loop(int bg)
}
}
SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext)
{
return (const char *) switch_core_hash_find(runtime.mime_types, ext);
}
SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext)
{
const char *check = (const char *) switch_core_hash_find(runtime.mime_types, ext);
switch_status_t status = SWITCH_STATUS_FALSE;
assert(type);
assert(ext);
if (!check) {
char *ptype = switch_core_permanent_strdup(type);
char *ext_list = strdup(ext);
int argc = 0;
char *argv[20] = { 0 };
int x;
assert(ext_list);
if ((argc = switch_separate_string(ext_list, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
for (x = 0; x < argc; x++) {
switch_core_hash_insert(runtime.mime_types, argv[x], ptype);
}
status = SWITCH_STATUS_SUCCESS;
}
free(ext_list);
}
return status;
}
static void load_mime_types(void)
{
char *cf = "mime.types";
int fd = -1;
char line_buf[1024] = "";
char *mime_path = NULL;
mime_path = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.conf_dir, cf);
assert(mime_path);
if (!(fd = open(mime_path, O_RDONLY))) {
return;
}
while((switch_fd_read_line(fd, line_buf, sizeof(line_buf)))) {
char *p;
char *type = line_buf;
if (*line_buf == '#') {
continue;
}
if ((p = strchr(line_buf, '\r')) || (p = strchr(line_buf, '\n'))) {
*p = '\0';
}
if ((p = strchr(type, '\t')) || (p = strchr(type, ' '))) {
*p++ = '\0';
while(*p == ' ' || *p == '\t') {
p++;
}
switch_core_mime_add_type(type, p);
}
}
if (fd > -1) {
close(fd);
fd = -1;
}
}
SWITCH_DECLARE(switch_status_t) switch_core_init(const char *console, switch_core_flag_t flags, const char **err)
{
......@@ -578,6 +659,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(const char *console, switch_cor
switch_core_set_globals();
switch_core_session_init(runtime.memory_pool);
switch_core_hash_init(&runtime.global_vars, runtime.memory_pool);
switch_core_hash_init(&runtime.mime_types, runtime.memory_pool);
load_mime_types();
runtime.flags = flags;
runtime.sps_total = 30;
......@@ -591,8 +674,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(const char *console, switch_cor
apr_terminate();
return SWITCH_STATUS_MEMERR;
}
if ((xml = switch_xml_open_cfg("switch.conf", &cfg, NULL))) {
switch_xml_t settings, param;
......@@ -918,6 +1000,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
switch_core_hash_destroy(&runtime.global_vars);
switch_core_hash_destroy(&runtime.mime_types);
if (runtime.memory_pool) {
apr_pool_destroy(runtime.memory_pool);
......
......@@ -348,6 +348,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
const char *vval;
time_t start = 0;
uint32_t org_silence_hits = 0;
switch_audio_resampler_t *resampler = NULL;
int16_t resamp_out[2048];
if (!fh) {
fh = &lfh;
......@@ -360,13 +362,27 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
assert(read_codec != NULL);
fh->channels = read_codec->implementation->number_of_channels;
fh->samplerate = read_codec->implementation->actual_samples_per_second;
if (fh->samplerate) {
if (fh->samplerate != read_codec->implementation->actual_samples_per_second) {
if (switch_resample_create(&resampler,
read_codec->implementation->actual_samples_per_second,
read_codec->implementation->actual_samples_per_second * 20,
fh->samplerate,
fh->samplerate * 20,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n");
return SWITCH_STATUS_GENERR;
}
}
} else {
fh->samplerate = read_codec->implementation->actual_samples_per_second;
}
if (switch_core_file_open(fh,
file,
read_codec->implementation->number_of_channels,
read_codec->implementation->actual_samples_per_second,
fh->channels,
fh->samplerate,
SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
switch_core_session_reset(session);
......@@ -539,7 +555,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
if (!switch_test_flag(fh, SWITCH_FILE_PAUSE)) {
len = (switch_size_t) read_frame->datalen / 2;
if (switch_core_file_write(fh, read_frame->data, &len) != SWITCH_STATUS_SUCCESS) {
int16_t *data = read_frame->data;
if (resampler) {
resampler->from_len = switch_short_to_float(read_frame->data, resampler->from, (int) len);
resampler->to_len = switch_resample_process(resampler, resampler->from, resampler->from_len, resampler->to, resampler->to_size, 0);
switch_float_to_short(resampler->to, resamp_out, read_frame->datalen);
len = resampler->to_len;
data = resamp_out;
}
if (switch_core_file_write(fh, data, &len) != SWITCH_STATUS_SUCCESS) {
break;
}
}
......@@ -609,28 +635,25 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_gentones(switch_core_session_t *sessi
}
for(;;) {
switch_status_t status = switch_core_session_read_frame(session, &read_frame, 1000, 0);
switch_status_t status;
if (!switch_channel_ready(channel)) {
status = SWITCH_STATUS_FALSE;
break;
}
if (switch_channel_test_flag(channel, CF_BREAK)) {
switch_channel_clear_flag(channel, CF_BREAK);
status = SWITCH_STATUS_BREAK;
break;
}
status = switch_core_session_read_frame(session, &read_frame, 1000, 0);
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
}
if (read_frame->datalen < 2 || switch_test_flag(read_frame, SFF_CNG)) {
continue;
}
if (args && (args->read_frame_callback)) {
if (args->read_frame_callback(session, read_frame, args->user_data) != SWITCH_STATUS_SUCCESS) {
break;
......
......@@ -35,6 +35,28 @@
#endif
#include "private/switch_core_pvt.h"
switch_size_t switch_fd_read_line(int fd, char *buf, switch_size_t len)
{
char c, *p;
int cur;
switch_size_t total = 0;
p = buf;
while (total + sizeof(c) < len && (cur = read(fd, &c, sizeof(c))) > 0) {
total += cur;
*p++ = c;
if (c == '\r' || c == '\n') {
break;
}
}
*p++ = '\0';
return total;
}
static const char switch_b64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define B64BUFFLEN 1024
SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size_t ilen, unsigned char *out, switch_size_t olen)
......@@ -85,7 +107,7 @@ static int write_buf(int fd, const char *buf)
SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, const char *from, const char *headers, const char *body, const char *file)
{
char *bound = "XXXX_boundary_XXXX";
char *mime_type = "audio/x-WAV";
const char *mime_type = "audio/inline";
char filename[80], buf[B64BUFFLEN];
int fd = 0, ifd = 0;
int x = 0, y = 0, bytes = 0, ilen = 0;
......@@ -127,6 +149,16 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, const char *fr
if (file) {
const char *filename = switch_cut_path(file);
const char *new_type;
char *ext;
if ((ext = strrchr(filename, '.'))) {
ext++;
if ((new_type = switch_core_mime_ext2type(ext))) {
mime_type = new_type;
}
}
snprintf(buf, B64BUFFLEN,
"\n\n--%s\nContent-Type: %s; name=\"%s\"\n"
"Content-Transfer-Encoding: base64\n"
......@@ -188,7 +220,7 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, const char *fr
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to execute command: %s\n", buf);
}
unlink(filename);
//unlink(filename);
if (file) {
......
......@@ -878,25 +878,6 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_fd(int fd)
return &root->xml;
}
static switch_size_t read_line(int fd, char *buf, switch_size_t len)
{
char c, *p;
int cur;
switch_size_t total = 0;
p = buf;
while (total + sizeof(c) < len && (cur = read(fd, &c, sizeof(c))) > 0) {
total += cur;
*p++ = c;
if (c == '\n') {
break;
}
}
*p++ = '\0';
return total;
}
static char *expand_vars(char *buf, char *ebuf, switch_size_t elen, switch_size_t *newlen)
{
char *var, *val;
......@@ -999,7 +980,7 @@ static int preprocess(const char *cwd, const char *file, int write_fd, int rleve
return -1;
}
while ((cur = read_line(read_fd, buf, sizeof(buf))) > 0) {
while ((cur = switch_fd_read_line(read_fd, buf, sizeof(buf))) > 0) {
char *arg, *e;
char *bp = expand_vars(buf, ebuf, sizeof(ebuf), &cur);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论