diff options
-rw-r--r-- | include/asterisk/devicestate.h | 48 | ||||
-rw-r--r-- | main/devicestate.c | 88 | ||||
-rw-r--r-- | main/pbx.c | 89 |
3 files changed, 160 insertions, 65 deletions
diff --git a/include/asterisk/devicestate.h b/include/asterisk/devicestate.h index d52430301..69470a9f7 100644 --- a/include/asterisk/devicestate.h +++ b/include/asterisk/devicestate.h @@ -196,6 +196,54 @@ int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback) */ int ast_devstate_prov_del(const char *label); +/*! + * \brief An object to hold state when calculating aggregate device state + */ +struct ast_devstate_aggregate; + +/*! + * \brief Initialize aggregate device state + * + * \arg agg the state object + * + * \return nothing + */ +void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg); + +/*! + * \brief Add a device state to the aggregate device state + * + * \arg agg the state object + * \arg state the state to add + * + * \return nothing + */ +void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state); + +/*! + * \brief Get the aggregate device state result + * + * \arg agg the state object + * + * \return the aggregate device state after adding some number of device states. + */ +enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg); + +/*! + * \brief You shouldn't care about the contents of this struct + * + * This struct is only here so that it can be easily declared on the stack. + */ +struct ast_devstate_aggregate { + unsigned int all_unavail:1; + unsigned int all_busy:1; + unsigned int all_free:1; + unsigned int all_on_hold:1; + unsigned int busy:1; + unsigned int in_use:1; + unsigned int ring:1; +}; + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/main/devicestate.c b/main/devicestate.c index bd9261306..85ac6492e 100644 --- a/main/devicestate.c +++ b/main/devicestate.c @@ -551,3 +551,91 @@ int ast_device_state_engine_init(void) return 0; } + +void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg) +{ + memset(agg, 0, sizeof(*agg)); + + agg->all_unavail = 1; + agg->all_busy = 1; + agg->all_free = 1; + agg->all_on_hold = 1; +} + +void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state) +{ + switch (state) { + case AST_DEVICE_NOT_INUSE: + agg->all_unavail = 0; + agg->all_busy = 0; + agg->all_on_hold = 0; + break; + case AST_DEVICE_INUSE: + agg->in_use = 1; + agg->all_busy = 0; + agg->all_unavail = 0; + agg->all_free = 0; + agg->all_on_hold = 0; + break; + case AST_DEVICE_RINGING: + agg->ring = 1; + agg->all_busy = 0; + agg->all_unavail = 0; + agg->all_free = 0; + agg->all_on_hold = 0; + break; + case AST_DEVICE_RINGINUSE: + agg->in_use = 1; + agg->ring = 1; + agg->all_busy = 0; + agg->all_unavail = 0; + agg->all_free = 0; + agg->all_on_hold = 0; + break; + case AST_DEVICE_ONHOLD: + agg->all_unavail = 0; + agg->all_free = 0; + break; + case AST_DEVICE_BUSY: + agg->all_unavail = 0; + agg->all_free = 0; + agg->all_on_hold = 0; + agg->busy = 1; + break; + case AST_DEVICE_UNAVAILABLE: + case AST_DEVICE_INVALID: + agg->all_busy = 0; + agg->all_free = 0; + agg->all_on_hold = 0; + break; + case AST_DEVICE_UNKNOWN: + break; + } +} + +enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg) +{ + if (agg->all_free) + return AST_DEVICE_NOT_INUSE; + + if (agg->all_on_hold) + return AST_DEVICE_ONHOLD; + + if (agg->all_busy) + return AST_DEVICE_BUSY; + + if (agg->all_unavail) + return AST_DEVICE_UNAVAILABLE; + + if (agg->ring) + return agg->in_use ? AST_DEVICE_RINGINUSE : AST_DEVICE_RINGING; + + if (agg->in_use) + return AST_DEVICE_INUSE; + + if (agg->busy) + return AST_DEVICE_BUSY; + + return AST_DEVICE_NOT_INUSE; +} + diff --git a/main/pbx.c b/main/pbx.c index b2aebbd9b..fcc3fb3f0 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -2798,7 +2798,7 @@ static void pbx_substitute_variables_helper_full(struct ast_channel *c, struct v } else ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); } - ast_debug(1, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); + ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)"); } else { /* Retrieve variable value */ pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp); @@ -3041,82 +3041,41 @@ static int ast_extension_state2(struct ast_exten *e) { char hint[AST_MAX_EXTENSION] = ""; char *cur, *rest; - int allunavailable = 1, allbusy = 1, allfree = 1, allonhold = 1; - int busy = 0, inuse = 0, ring = 0; + struct ast_devstate_aggregate agg; + enum ast_device_state state; if (!e) return -1; + ast_devstate_aggregate_init(&agg); + ast_copy_string(hint, ast_get_extension_app(e), sizeof(hint)); rest = hint; /* One or more devices separated with a & character */ - while ( (cur = strsep(&rest, "&")) ) { - int res = ast_device_state(cur); - switch (res) { - case AST_DEVICE_NOT_INUSE: - allunavailable = 0; - allbusy = 0; - allonhold = 0; - break; - case AST_DEVICE_INUSE: - inuse = 1; - allunavailable = 0; - allfree = 0; - allonhold = 0; - break; - case AST_DEVICE_RINGING: - ring = 1; - allunavailable = 0; - allfree = 0; - allonhold = 0; - break; - case AST_DEVICE_RINGINUSE: - inuse = 1; - ring = 1; - allunavailable = 0; - allfree = 0; - allonhold = 0; - break; - case AST_DEVICE_ONHOLD: - allunavailable = 0; - allfree = 0; - break; - case AST_DEVICE_BUSY: - allunavailable = 0; - allfree = 0; - allonhold = 0; - busy = 1; - break; - case AST_DEVICE_UNAVAILABLE: - case AST_DEVICE_INVALID: - allbusy = 0; - allfree = 0; - allonhold = 0; - break; - default: - allunavailable = 0; - allbusy = 0; - allfree = 0; - allonhold = 0; - } - } - if (!inuse && ring) - return AST_EXTENSION_RINGING; - if (inuse && ring) - return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); - if (inuse) - return AST_EXTENSION_INUSE; - if (allfree) - return AST_EXTENSION_NOT_INUSE; - if (allonhold) + while ( (cur = strsep(&rest, "&")) ) + ast_devstate_aggregate_add(&agg, ast_device_state(cur)); + + state = ast_devstate_aggregate_result(&agg); + + switch (state) { + case AST_DEVICE_ONHOLD: return AST_EXTENSION_ONHOLD; - if (allbusy) + case AST_DEVICE_BUSY: return AST_EXTENSION_BUSY; - if (allunavailable) + case AST_DEVICE_UNAVAILABLE: return AST_EXTENSION_UNAVAILABLE; - if (busy) + case AST_DEVICE_RINGINUSE: + return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING); + case AST_DEVICE_RINGING: + return AST_EXTENSION_RINGING; + case AST_DEVICE_INUSE: return AST_EXTENSION_INUSE; + case AST_DEVICE_UNKNOWN: + case AST_DEVICE_INVALID: + case AST_DEVICE_NOT_INUSE: + return AST_EXTENSION_NOT_INUSE; + } return AST_EXTENSION_NOT_INUSE; } |