diff --git a/conf/autoload_configs/voicemail.conf.xml b/conf/autoload_configs/voicemail.conf.xml
index e18f82301b..f7207d24b8 100644
--- a/conf/autoload_configs/voicemail.conf.xml
+++ b/conf/autoload_configs/voicemail.conf.xml
@@ -33,6 +33,8 @@
+
+
diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index d9305c2f04..5278ed0950 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -67,6 +67,11 @@ typedef enum {
PFLAG_DESTROY = 1 << 0
} vm_flags_t;
+typedef enum {
+ VM_MOVE_NEXT,
+ VM_MOVE_PREV
+} msg_move_t;
+
#define VM_PROFILE_CONFIGITEM_COUNT 100
struct vm_profile {
@@ -99,6 +104,8 @@ struct vm_profile {
char restart_key[2];
char ff_key[2];
char rew_key[2];
+ char prev_msg_key[2];
+ char next_msg_key[2];
char urgent_key[2];
char operator_key[2];
char vmain_key[2];
@@ -498,6 +505,10 @@ vm_profile_t *profile_set_config(vm_profile_t *profile)
&profile->ff_key, "6", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "rew-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->rew_key, "4", &config_dtmf, NULL, NULL);
+ SWITCH_CONFIG_SET_ITEM(profile->config[i++], "previous-message-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
+ &profile->prev_msg_key, "", &config_dtmf, NULL, NULL);
+ SWITCH_CONFIG_SET_ITEM(profile->config[i++], "next-message-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
+ &profile->next_msg_key, "", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "urgent-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->urgent_key, "*", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "operator-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
@@ -870,7 +881,7 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in
if (!cc->noexit
&& (dtmf->digit == *cc->profile->delete_file_key || dtmf->digit == *cc->profile->save_file_key
- || dtmf->digit == *cc->profile->terminator_key)) {
+ || dtmf->digit == *cc->profile->prev_msg_key || dtmf->digit == *cc->profile->next_msg_key)) {
*cc->buf = dtmf->digit;
return SWITCH_STATUS_BREAK;
}
@@ -906,6 +917,10 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in
switch_core_file_seek(fh, &pos, samps, SEEK_CUR);
return SWITCH_STATUS_SUCCESS;
}
+ if (!cc->noexit && dtmf->digit == *cc->profile->terminator_key) {
+ *cc->buf = dtmf->digit;
+ return SWITCH_STATUS_BREAK;
+ }
}
break;
default:
@@ -1214,6 +1229,7 @@ struct listen_callback {
int index;
int want;
msg_type_t type;
+ msg_move_t move;
};
typedef struct listen_callback listen_callback_t;
@@ -1478,8 +1494,11 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t
} else {
TRY_CODE(vm_macro_get(session, VM_LISTEN_FILE_CHECK_MACRO, key_buf, input, sizeof(input), 1, "", &term, profile->digit_timeout));
}
-
- if (!strcmp(input, profile->listen_file_key)) {
+ if (!strcmp(input, profile->prev_msg_key)) {
+ cbt->move = VM_MOVE_PREV;
+ } else if (!strcmp(input, profile->next_msg_key)) {
+ cbt->move = VM_MOVE_NEXT;
+ } else if (!strcmp(input, profile->listen_file_key)) {
goto play_file;
} else if (!strcmp(input, profile->callback_key)) {
switch_core_session_execute_exten(session, cbt->cid_number, profile->callback_dialplan, profile->callback_context);
@@ -1824,6 +1843,7 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
&total_new_urgent_messages, &total_saved_urgent_messages);
memset(&cbt, 0, sizeof(cbt));
cbt.email = vm_email;
+ cbt.move = VM_MOVE_NEXT;
switch (play_msg_type) {
case MSG_NEW:
{
@@ -1849,8 +1869,16 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
cbt.index = 0;
cbt.want = cur_message;
cbt.type = play_msg_type;
+ cbt.move = VM_MOVE_NEXT;
vm_execute_sql_callback(profile, profile->mutex, sql, listen_callback, &cbt);
status = listen_file(session, profile, &cbt);
+ if (cbt.move == VM_MOVE_PREV) {
+ if (cur_message <= 0) {
+ cur_message = -1;
+ } else {
+ cur_message -= 2;
+ }
+ }
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
break;
}