Realtime capabilities for the Find-Me-Follow-Me application.
authorTilghman Lesher <tilghman@meg.abyt.es>
Mon, 25 Aug 2008 16:02:56 +0000 (16:02 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Mon, 25 Aug 2008 16:02:56 +0000 (16:02 +0000)
(closes issue #13295)
 Reported by: Corydon76
 Patches:
       20080813__followme_realtime_enabled.diff.txt uploaded by Corydon76 (license 14)
 Tested by: dferrer

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@139775 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_followme.c
doc/followme.txt [new file with mode: 0644]

index e582cc5..84fe26c 100644 (file)
@@ -89,6 +89,7 @@ struct call_followme {
        char moh[AST_MAX_CONTEXT];      /*!< Music On Hold Class to be used */
        char context[AST_MAX_CONTEXT];  /*!< Context to dial from */
        unsigned int active;            /*!< Profile is active (1), or disabled (0). */
+       int realtime;           /*!< Cached from realtime */
        char takecall[20];              /*!< Digit mapping to take a call */
        char nextindp[20];              /*!< Digit mapping to decline a call */
        char callfromprompt[PATH_MAX];  /*!< Sound prompt name and path */
@@ -233,17 +234,17 @@ static void profile_set_param(struct call_followme *f, const char *param, const
                ast_copy_string(f->takecall, val, sizeof(f->takecall));
        else if (!strcasecmp(param, "declinecall"))
                ast_copy_string(f->nextindp, val, sizeof(f->nextindp));
-       else if (!strcasecmp(param, "call-from-prompt"))
+       else if (!strcasecmp(param, "call-from-prompt") || !strcasecmp(param, "call_from_prompt"))
                ast_copy_string(f->callfromprompt, val, sizeof(f->callfromprompt));
-       else if (!strcasecmp(param, "followme-norecording-prompt")) 
+       else if (!strcasecmp(param, "followme-norecording-prompt") || !strcasecmp(param, "norecording_prompt")) 
                ast_copy_string(f->norecordingprompt, val, sizeof(f->norecordingprompt));
-       else if (!strcasecmp(param, "followme-options-prompt")) 
+       else if (!strcasecmp(param, "followme-options-prompt") || !strcasecmp(param, "options_prompt")) 
                ast_copy_string(f->optionsprompt, val, sizeof(f->optionsprompt));
-       else if (!strcasecmp(param, "followme-pls-hold-prompt"))
+       else if (!strcasecmp(param, "followme-pls-hold-prompt") || !strcasecmp(param, "hold_prompt"))
                ast_copy_string(f->plsholdprompt, val, sizeof(f->plsholdprompt));
-       else if (!strcasecmp(param, "followme-status-prompt")) 
+       else if (!strcasecmp(param, "followme-status-prompt") || !strcasecmp(param, "status_prompt")) 
                ast_copy_string(f->statusprompt, val, sizeof(f->statusprompt));
-       else if (!strcasecmp(param, "followme-sorry-prompt")) 
+       else if (!strcasecmp(param, "followme-sorry-prompt") || !strcasecmp(param, "sorry_prompt")) 
                ast_copy_string(f->sorryprompt, val, sizeof(f->sorryprompt));
        else if (failunknown) {
                if (linenum >= 0)
@@ -873,6 +874,67 @@ static void findmeexec(struct fm_args *tpargs)
        return;
 }
 
+static struct call_followme *find_realtime(const char *name)
+{
+       struct ast_variable *var = ast_load_realtime("followme", "name", name, NULL), *v;
+       struct ast_config *cfg;
+       const char *catg;
+       struct call_followme *new;
+       struct ast_str *str = ast_str_create(16);
+
+       if (!var) {
+               return NULL;
+       }
+
+       if (!(new = alloc_profile(name))) {
+               return NULL;
+       }
+
+       for (v = var; v; v = v->next) {
+               if (!strcasecmp(v->name, "active")) {
+                       if (ast_false(v->value)) {
+                               ast_mutex_destroy(&new->lock);
+                               ast_free(new);
+                               return NULL;
+                       }
+               } else {
+                       profile_set_param(new, v->name, v->value, 0, 0);
+               }
+       }
+
+       ast_variables_destroy(var);
+       new->realtime = 1;
+
+       /* Load numbers */
+       if (!(cfg = ast_load_realtime_multientry("followme_numbers", "ordinal LIKE", "%", "name", name, NULL))) {
+               ast_mutex_destroy(&new->lock);
+               ast_free(new);
+               return NULL;
+       }
+
+       for (catg = ast_category_browse(cfg, NULL); catg; catg = ast_category_browse(cfg, catg)) {
+               const char *numstr, *timeoutstr, *ordstr;
+               int timeout;
+               struct number *cur;
+               if (!(numstr = ast_variable_retrieve(cfg, catg, "phonenumber"))) {
+                       continue;
+               }
+               if (!(timeoutstr = ast_variable_retrieve(cfg, catg, "timeout")) || sscanf(timeoutstr, "%d", &timeout) != 1 || timeout < 1) {
+                       timeout = 25;
+               }
+               /* This one has to exist; it was part of the query */
+               ordstr = ast_variable_retrieve(cfg, catg, "ordinal");
+               ast_str_make_space(&str, strlen(numstr) + 1);
+               ast_copy_string(str->str, numstr, str->len);
+               if ((cur = create_followme_number(str->str, timeout, atoi(ordstr)))) {
+                       AST_LIST_INSERT_TAIL(&new->numbers, cur, entry);
+               }
+       }
+       ast_config_destroy(cfg);
+
+       return new;
+}
+
 static int app_exec(struct ast_channel *chan, void *data)
 {
        struct fm_args targs;
@@ -918,6 +980,10 @@ static int app_exec(struct ast_channel *chan, void *data)
        ast_debug(1, "New profile %s.\n", args.followmeid);
 
        if (!f) {
+               f = find_realtime(args.followmeid);
+       }
+
+       if (!f) {
                ast_log(LOG_WARNING, "Profile requested, %s, not found in the configuration.\n", args.followmeid);
                return 0;
        }
@@ -1016,6 +1082,12 @@ static int app_exec(struct ast_channel *chan, void *data)
 
        outrun:
 
+       if (f->realtime) {
+               /* Not in list */
+               free_numbers(f);
+               ast_free(f);
+       }
+
        return res;
 }
 
diff --git a/doc/followme.txt b/doc/followme.txt
new file mode 100644 (file)
index 0000000..971814a
--- /dev/null
@@ -0,0 +1,32 @@
+Followme is now realtime-enabled:
+
+To use, you must define two backend data structures, with the following fields:
+
+followme:
+       name                Name of this followme entry.  Specified when invoking the FollowMe
+                           application in the dialplan.  This field is the only one which is
+                           mandatory.  All of the other fields will inherit the default from
+                           followme.conf, if not specified in this data resource.
+       musicclass OR       The musiconhold class used for the caller while waiting to be
+       musiconhold OR      connected.
+    music
+       context             Dialplan context from which to dial numbers
+       takecall            DTMF used to accept the call and be connected.  For obvious reasons,
+                           this needs to be a single digit, '*', or '#'.
+       declinecall         DTMF used to refuse the call, sending it onto the next step, if any.
+       call_from_prompt    Prompt to play to the callee, announcing the call.
+       norecording_prompt  The alternate prompt to play to the callee, when the caller
+                           refuses to leave a name (or the option isn't set to allow them).
+       options_prompt      Normally, "press 1 to accept, 2 to decline".
+       hold_prompt         Message played to the caller while dialing the followme steps.
+       status_prompt       Normally, "Party is not at their desk".
+       sorry_prompt        Normally, "Unable to locate party".
+
+followme_numbers:
+       name                Name of this followme entry.  Must match the name above.
+       ordinal             An integer, specifying the order in which these numbers will be
+                           followed.
+       phonenumber         The telephone number(s) you would like to call, separated by '&'.
+       timeout             Timeout associated with this step.  See the followme documentation
+                           for more information on how this value is handled.
+