Index: apps/app_voicemail.c =================================================================== --- apps/app_voicemail.c (revision 33395) +++ apps/app_voicemail.c (working copy) @@ -113,6 +113,8 @@ #define VM_DELETE (1 << 12) #define VM_ALLOCED (1 << 13) #define VM_SEARCH (1 << 14) +#define VM_REVERSEORDER (1 << 15) +#define VM_UNAVAILFALLBACK (1 << 16) /* if the Busy greeting was specified and not there, fallback to the Unavailable message */ #define ERROR_LOCK_PATH -100 @@ -461,6 +463,8 @@ ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE); } else if (!strcasecmp(var, "sayduration")){ ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION); + } else if (!strcasecmp(var, "unavailfallback")) { + ast_set2_flag(vmu, ast_true(value), VM_UNAVAILFALLBACK); } else if (!strcasecmp(var, "saydurationm")){ if (sscanf(value, "%d", &x) == 1) { vmu->saydurationm = x; @@ -471,6 +475,8 @@ ast_set2_flag(vmu, ast_true(value), VM_FORCENAME); } else if (!strcasecmp(var, "forcegreetings")){ ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET); + } else if (!strcasecmp(var, "reverseorder")){ + ast_set2_flag(vmu, ast_true(value), VM_REVERSEORDER); } else if (!strcasecmp(var, "callback")) { ast_copy_string(vmu->callback, value, sizeof(vmu->callback)); } else if (!strcasecmp(var, "dialout")) { @@ -2419,9 +2425,11 @@ snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context); else ast_copy_string(ext_context, vmu->context, sizeof(ext_context)); - if (ast_test_flag(options, OPT_BUSY_GREETING)) + if (ast_test_flag(options, OPT_BUSY_GREETING)) { snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext); - else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) + if (ast_test_flag(vmu, VM_UNAVAILFALLBACK) && (ast_fileexists(prefile, NULL, NULL) <= 0)) + snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext); + } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext); snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext); RETRIEVE(tempfile, -1); @@ -3791,10 +3799,17 @@ vms->starting = 0; make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg); adsi_message(chan, vms); - if (!vms->curmsg) - res = wait_file2(chan, vms, "vm-first"); /* "First" */ - else if (vms->curmsg == vms->lastmsg) - res = wait_file2(chan, vms, "vm-last"); /* "last" */ + if (ast_test_flag(vmu, VM_REVERSEORDER)) { + if (vms->curmsg == 0) + res = wait_file2(chan, vms, "vm-first"); /* "First" */ + else if (vms->curmsg == vms->lastmsg) + res = wait_file2(chan, vms, "vm-last"); /* "last" */ + } else { + if (vms->curmsg == 0) + res = wait_file2(chan, vms, "vm-last"); + else if (vms->curmsg == vms->lastmsg) + res = wait_file2(chan, vms, "vm-first"); + } if (!res) { if (!strcasecmp(chan->language, "se")) { /* SWEDISH syntax */ res = wait_file2(chan, vms, "vm-meddelandet"); /* "message" */ @@ -4559,7 +4574,7 @@ } } -static int vm_instructions(struct ast_channel *chan, struct vm_state *vms, int skipadvanced) +static int vm_instructions(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced) { int res = 0; /* Play instructions and wait for new command */ @@ -4573,14 +4588,24 @@ if (!res) res = ast_play_and_wait(chan, "vm-opts"); } else { - if (vms->curmsg) + if (!ast_test_flag(vmu, VM_REVERSEORDER)) { + if (vms->curmsg) + res = ast_play_and_wait(chan, "vm-prev"); + } else { + if (vms->curmsg != vms->lastmsg) res = ast_play_and_wait(chan, "vm-prev"); + } if (!res && !skipadvanced) res = ast_play_and_wait(chan, "vm-advopts"); if (!res) res = ast_play_and_wait(chan, "vm-repeat"); - if (!res && (vms->curmsg != vms->lastmsg)) + if (!ast_test_flag(vmu, VM_REVERSEORDER)) { + if (!res && (vms->curmsg != vms->lastmsg)) res = ast_play_and_wait(chan, "vm-next"); + } else { + if (!res && (vms->curmsg)) + res = ast_play_and_wait(chan, "vm-next"); + } if (!res) { if (!vms->deleted[vms->curmsg]) res = ast_play_and_wait(chan, "vm-delete"); @@ -5064,6 +5089,32 @@ return 0; } +static int vm_skipbackward(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms) +{ + int cmd; + + if (vms->curmsg) { + vms->curmsg--; + cmd = play_message(chan, vmu, vms); + } else { + cmd = ast_play_and_wait(chan, "vm-nomore"); + } + return(cmd); +} + +static int vm_skipforward(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms) +{ + int cmd; + + if (vms->curmsg < vms->lastmsg) { + vms->curmsg++; + cmd = play_message(chan, vmu, vms); + } else { + cmd = ast_play_and_wait(chan, "vm-nomore"); + } + return(cmd); +} + static int vm_execmain(struct ast_channel *chan, void *data) { /* XXX This is, admittedly, some pretty horrendus code. For some @@ -5222,7 +5273,10 @@ /* Run main menu */ switch(cmd) { case '1': - vms.curmsg = 0; + if (ast_test_flag(vmu, VM_REVERSEORDER)) + vms.curmsg = vms.lastmsg; + else + vms.curmsg = 0; /* Fall through */ case '5': cmd = vm_browse_messages(chan, &vms, vmu); @@ -5356,20 +5410,16 @@ } break; case '4': - if (vms.curmsg) { - vms.curmsg--; - cmd = play_message(chan, vmu, &vms); - } else { - cmd = ast_play_and_wait(chan, "vm-nomore"); - } + if (ast_test_flag(vmu, VM_REVERSEORDER)) + cmd = vm_skipforward(chan, vmu, &vms); + else + cmd = vm_skipbackward(chan, vmu, &vms); break; case '6': - if (vms.curmsg < vms.lastmsg) { - vms.curmsg++; - cmd = play_message(chan, vmu, &vms); - } else { - cmd = ast_play_and_wait(chan, "vm-nomore"); - } + if (ast_test_flag(vmu, VM_REVERSEORDER)) + cmd = vm_skipbackward(chan, vmu, &vms); + else + cmd = vm_skipforward(chan, vmu, &vms); break; case '7': vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg]; @@ -5380,12 +5430,10 @@ else cmd = ast_play_and_wait(chan, "vm-undeleted"); if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) { - if (vms.curmsg < vms.lastmsg) { - vms.curmsg++; - cmd = play_message(chan, vmu, &vms); - } else { - cmd = ast_play_and_wait(chan, "vm-nomore"); - } + if (ast_test_flag(vmu, VM_REVERSEORDER)) + cmd = vm_skipbackward(chan, vmu, &vms); + else + cmd = vm_skipforward(chan, vmu, &vms); } break; @@ -5436,12 +5484,10 @@ cmd = ast_play_and_wait(chan, "vm-mailboxfull"); } if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) { - if (vms.curmsg < vms.lastmsg) { - vms.curmsg++; - cmd = play_message(chan, vmu, &vms); - } else { - cmd = ast_play_and_wait(chan, "vm-nomore"); - } + if (ast_test_flag(vmu, VM_REVERSEORDER)) + cmd = vm_skipbackward(chan, vmu, &vms); + else + cmd = vm_skipforward(chan, vmu, &vms); } break; case '*': @@ -5452,7 +5498,7 @@ if (!cmd) cmd = ast_play_and_wait(chan, "vm-opts"); if (!cmd) - cmd = vm_instructions(chan, &vms, 1); + cmd = vm_instructions(chan, vmu, &vms, 1); } else cmd = 0; break; @@ -5462,7 +5508,7 @@ adsi_status(chan, &vms); break; default: /* Nothing */ - cmd = vm_instructions(chan, &vms, 0); + cmd = vm_instructions(chan, vmu, &vms, 0); break; } }